diff options
-rw-r--r-- | fs/nfsd/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 75 | ||||
-rw-r--r-- | include/linux/nfsd/nfsd.h | 3 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 7 |
4 files changed, 113 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a106e3be7c13..3c627128e205 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/nfsd/state.h> | 47 | #include <linux/nfsd/state.h> |
48 | #include <linux/nfsd/xdr4.h> | 48 | #include <linux/nfsd/xdr4.h> |
49 | #include <linux/nfs4_acl.h> | 49 | #include <linux/nfs4_acl.h> |
50 | #include <linux/sunrpc/gss_api.h> | ||
50 | 51 | ||
51 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 52 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
52 | 53 | ||
@@ -610,6 +611,30 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
610 | } | 611 | } |
611 | 612 | ||
612 | static __be32 | 613 | static __be32 |
614 | nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
615 | struct nfsd4_secinfo *secinfo) | ||
616 | { | ||
617 | struct svc_fh resfh; | ||
618 | struct svc_export *exp; | ||
619 | struct dentry *dentry; | ||
620 | __be32 err; | ||
621 | |||
622 | fh_init(&resfh, NFS4_FHSIZE); | ||
623 | err = nfsd_lookup_dentry(rqstp, &cstate->current_fh, | ||
624 | secinfo->si_name, secinfo->si_namelen, | ||
625 | &exp, &dentry); | ||
626 | if (err) | ||
627 | return err; | ||
628 | if (dentry->d_inode == NULL) { | ||
629 | exp_put(exp); | ||
630 | err = nfserr_noent; | ||
631 | } else | ||
632 | secinfo->si_exp = exp; | ||
633 | dput(dentry); | ||
634 | return err; | ||
635 | } | ||
636 | |||
637 | static __be32 | ||
613 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 638 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
614 | struct nfsd4_setattr *setattr) | 639 | struct nfsd4_setattr *setattr) |
615 | { | 640 | { |
@@ -1008,6 +1033,9 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = { | |||
1008 | [OP_SAVEFH] = { | 1033 | [OP_SAVEFH] = { |
1009 | .op_func = (nfsd4op_func)nfsd4_savefh, | 1034 | .op_func = (nfsd4op_func)nfsd4_savefh, |
1010 | }, | 1035 | }, |
1036 | [OP_SECINFO] = { | ||
1037 | .op_func = (nfsd4op_func)nfsd4_secinfo, | ||
1038 | }, | ||
1011 | [OP_SETATTR] = { | 1039 | [OP_SETATTR] = { |
1012 | .op_func = (nfsd4op_func)nfsd4_setattr, | 1040 | .op_func = (nfsd4op_func)nfsd4_setattr, |
1013 | }, | 1041 | }, |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b0bfbda375e1..864498f8f2d9 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/nfsd_idmap.h> | 56 | #include <linux/nfsd_idmap.h> |
57 | #include <linux/nfs4.h> | 57 | #include <linux/nfs4.h> |
58 | #include <linux/nfs4_acl.h> | 58 | #include <linux/nfs4_acl.h> |
59 | #include <linux/sunrpc/gss_api.h> | ||
59 | 60 | ||
60 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 61 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
61 | 62 | ||
@@ -819,6 +820,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) | |||
819 | } | 820 | } |
820 | 821 | ||
821 | static __be32 | 822 | static __be32 |
823 | nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, | ||
824 | struct nfsd4_secinfo *secinfo) | ||
825 | { | ||
826 | DECODE_HEAD; | ||
827 | |||
828 | READ_BUF(4); | ||
829 | READ32(secinfo->si_namelen); | ||
830 | READ_BUF(secinfo->si_namelen); | ||
831 | SAVEMEM(secinfo->si_name, secinfo->si_namelen); | ||
832 | status = check_filename(secinfo->si_name, secinfo->si_namelen, | ||
833 | nfserr_noent); | ||
834 | if (status) | ||
835 | return status; | ||
836 | DECODE_TAIL; | ||
837 | } | ||
838 | |||
839 | static __be32 | ||
822 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) | 840 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) |
823 | { | 841 | { |
824 | DECODE_HEAD; | 842 | DECODE_HEAD; |
@@ -1131,6 +1149,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1131 | case OP_SAVEFH: | 1149 | case OP_SAVEFH: |
1132 | op->status = nfs_ok; | 1150 | op->status = nfs_ok; |
1133 | break; | 1151 | break; |
1152 | case OP_SECINFO: | ||
1153 | op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo); | ||
1154 | break; | ||
1134 | case OP_SETATTR: | 1155 | case OP_SETATTR: |
1135 | op->status = nfsd4_decode_setattr(argp, &op->u.setattr); | 1156 | op->status = nfsd4_decode_setattr(argp, &op->u.setattr); |
1136 | break; | 1157 | break; |
@@ -1847,11 +1868,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
1847 | if (d_mountpoint(dentry)) { | 1868 | if (d_mountpoint(dentry)) { |
1848 | int err; | 1869 | int err; |
1849 | 1870 | ||
1871 | /* | ||
1872 | * Why the heck aren't we just using nfsd_lookup?? | ||
1873 | * Different "."/".." handling? Something else? | ||
1874 | * At least, add a comment here to explain.... | ||
1875 | */ | ||
1850 | err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); | 1876 | err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); |
1851 | if (err) { | 1877 | if (err) { |
1852 | nfserr = nfserrno(err); | 1878 | nfserr = nfserrno(err); |
1853 | goto out_put; | 1879 | goto out_put; |
1854 | } | 1880 | } |
1881 | nfserr = check_nfsd_access(exp, cd->rd_rqstp); | ||
1882 | if (nfserr) | ||
1883 | goto out_put; | ||
1855 | 1884 | ||
1856 | } | 1885 | } |
1857 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, | 1886 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, |
@@ -2419,6 +2448,49 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2419 | } | 2448 | } |
2420 | } | 2449 | } |
2421 | 2450 | ||
2451 | static void | ||
2452 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr, | ||
2453 | struct nfsd4_secinfo *secinfo) | ||
2454 | { | ||
2455 | int i = 0; | ||
2456 | struct svc_export *exp = secinfo->si_exp; | ||
2457 | ENCODE_HEAD; | ||
2458 | |||
2459 | if (nfserr) | ||
2460 | goto out; | ||
2461 | RESERVE_SPACE(4); | ||
2462 | WRITE32(exp->ex_nflavors); | ||
2463 | ADJUST_ARGS(); | ||
2464 | for (i = 0; i < exp->ex_nflavors; i++) { | ||
2465 | u32 flav = exp->ex_flavors[i].pseudoflavor; | ||
2466 | struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); | ||
2467 | |||
2468 | if (gm) { | ||
2469 | RESERVE_SPACE(4); | ||
2470 | WRITE32(RPC_AUTH_GSS); | ||
2471 | ADJUST_ARGS(); | ||
2472 | RESERVE_SPACE(4 + gm->gm_oid.len); | ||
2473 | WRITE32(gm->gm_oid.len); | ||
2474 | WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); | ||
2475 | ADJUST_ARGS(); | ||
2476 | RESERVE_SPACE(4); | ||
2477 | WRITE32(0); /* qop */ | ||
2478 | ADJUST_ARGS(); | ||
2479 | RESERVE_SPACE(4); | ||
2480 | WRITE32(gss_pseudoflavor_to_service(gm, flav)); | ||
2481 | ADJUST_ARGS(); | ||
2482 | gss_mech_put(gm); | ||
2483 | } else { | ||
2484 | RESERVE_SPACE(4); | ||
2485 | WRITE32(flav); | ||
2486 | ADJUST_ARGS(); | ||
2487 | } | ||
2488 | } | ||
2489 | out: | ||
2490 | if (exp) | ||
2491 | exp_put(exp); | ||
2492 | } | ||
2493 | |||
2422 | /* | 2494 | /* |
2423 | * The SETATTR encode routine is special -- it always encodes a bitmap, | 2495 | * The SETATTR encode routine is special -- it always encodes a bitmap, |
2424 | * regardless of the error status. | 2496 | * regardless of the error status. |
@@ -2559,6 +2631,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
2559 | break; | 2631 | break; |
2560 | case OP_SAVEFH: | 2632 | case OP_SAVEFH: |
2561 | break; | 2633 | break; |
2634 | case OP_SECINFO: | ||
2635 | nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo); | ||
2636 | break; | ||
2562 | case OP_SETATTR: | 2637 | case OP_SETATTR: |
2563 | nfsd4_encode_setattr(resp, op->status, &op->u.setattr); | 2638 | nfsd4_encode_setattr(resp, op->status, &op->u.setattr); |
2564 | break; | 2639 | break; |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 54ef1a18a56c..e452256d3f72 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
@@ -71,6 +71,9 @@ int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | |||
71 | struct svc_export **expp); | 71 | struct svc_export **expp); |
72 | __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, | 72 | __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, |
73 | const char *, int, struct svc_fh *); | 73 | const char *, int, struct svc_fh *); |
74 | __be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *, | ||
75 | const char *, int, | ||
76 | struct svc_export **, struct dentry **); | ||
74 | __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, | 77 | __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, |
75 | struct iattr *, int, time_t); | 78 | struct iattr *, int, time_t); |
76 | #ifdef CONFIG_NFSD_V4 | 79 | #ifdef CONFIG_NFSD_V4 |
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 09799bcee0ac..1b653267133a 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h | |||
@@ -293,6 +293,12 @@ struct nfsd4_rename { | |||
293 | struct nfsd4_change_info rn_tinfo; /* response */ | 293 | struct nfsd4_change_info rn_tinfo; /* response */ |
294 | }; | 294 | }; |
295 | 295 | ||
296 | struct nfsd4_secinfo { | ||
297 | u32 si_namelen; /* request */ | ||
298 | char *si_name; /* request */ | ||
299 | struct svc_export *si_exp; /* response */ | ||
300 | }; | ||
301 | |||
296 | struct nfsd4_setattr { | 302 | struct nfsd4_setattr { |
297 | stateid_t sa_stateid; /* request */ | 303 | stateid_t sa_stateid; /* request */ |
298 | u32 sa_bmval[2]; /* request */ | 304 | u32 sa_bmval[2]; /* request */ |
@@ -365,6 +371,7 @@ struct nfsd4_op { | |||
365 | struct nfsd4_remove remove; | 371 | struct nfsd4_remove remove; |
366 | struct nfsd4_rename rename; | 372 | struct nfsd4_rename rename; |
367 | clientid_t renew; | 373 | clientid_t renew; |
374 | struct nfsd4_secinfo secinfo; | ||
368 | struct nfsd4_setattr setattr; | 375 | struct nfsd4_setattr setattr; |
369 | struct nfsd4_setclientid setclientid; | 376 | struct nfsd4_setclientid setclientid; |
370 | struct nfsd4_setclientid_confirm setclientid_confirm; | 377 | struct nfsd4_setclientid_confirm setclientid_confirm; |