diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 15809dfd88a5..b3d55c6747fd 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -56,6 +56,8 @@ | |||
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> | ||
60 | #include <linux/sunrpc/svcauth_gss.h> | ||
59 | 61 | ||
60 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 62 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
61 | 63 | ||
@@ -819,6 +821,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) | |||
819 | } | 821 | } |
820 | 822 | ||
821 | static __be32 | 823 | static __be32 |
824 | nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, | ||
825 | struct nfsd4_secinfo *secinfo) | ||
826 | { | ||
827 | DECODE_HEAD; | ||
828 | |||
829 | READ_BUF(4); | ||
830 | READ32(secinfo->si_namelen); | ||
831 | READ_BUF(secinfo->si_namelen); | ||
832 | SAVEMEM(secinfo->si_name, secinfo->si_namelen); | ||
833 | status = check_filename(secinfo->si_name, secinfo->si_namelen, | ||
834 | nfserr_noent); | ||
835 | if (status) | ||
836 | return status; | ||
837 | DECODE_TAIL; | ||
838 | } | ||
839 | |||
840 | static __be32 | ||
822 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) | 841 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) |
823 | { | 842 | { |
824 | DECODE_HEAD; | 843 | DECODE_HEAD; |
@@ -1131,6 +1150,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1131 | case OP_SAVEFH: | 1150 | case OP_SAVEFH: |
1132 | op->status = nfs_ok; | 1151 | op->status = nfs_ok; |
1133 | break; | 1152 | break; |
1153 | case OP_SECINFO: | ||
1154 | op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo); | ||
1155 | break; | ||
1134 | case OP_SETATTR: | 1156 | case OP_SETATTR: |
1135 | op->status = nfsd4_decode_setattr(argp, &op->u.setattr); | 1157 | op->status = nfsd4_decode_setattr(argp, &op->u.setattr); |
1136 | break; | 1158 | break; |
@@ -1296,7 +1318,7 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 * | |||
1296 | char *path, *rootpath; | 1318 | char *path, *rootpath; |
1297 | 1319 | ||
1298 | fh_init(&tmp_fh, NFS4_FHSIZE); | 1320 | fh_init(&tmp_fh, NFS4_FHSIZE); |
1299 | *stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); | 1321 | *stat = exp_pseudoroot(rqstp, &tmp_fh); |
1300 | if (*stat) | 1322 | if (*stat) |
1301 | return NULL; | 1323 | return NULL; |
1302 | rootpath = tmp_fh.fh_export->ex_path; | 1324 | rootpath = tmp_fh.fh_export->ex_path; |
@@ -1847,11 +1869,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
1847 | if (d_mountpoint(dentry)) { | 1869 | if (d_mountpoint(dentry)) { |
1848 | int err; | 1870 | int err; |
1849 | 1871 | ||
1872 | /* | ||
1873 | * Why the heck aren't we just using nfsd_lookup?? | ||
1874 | * Different "."/".." handling? Something else? | ||
1875 | * At least, add a comment here to explain.... | ||
1876 | */ | ||
1850 | err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); | 1877 | err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); |
1851 | if (err) { | 1878 | if (err) { |
1852 | nfserr = nfserrno(err); | 1879 | nfserr = nfserrno(err); |
1853 | goto out_put; | 1880 | goto out_put; |
1854 | } | 1881 | } |
1882 | nfserr = check_nfsd_access(exp, cd->rd_rqstp); | ||
1883 | if (nfserr) | ||
1884 | goto out_put; | ||
1855 | 1885 | ||
1856 | } | 1886 | } |
1857 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, | 1887 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, |
@@ -2419,6 +2449,72 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2419 | } | 2449 | } |
2420 | } | 2450 | } |
2421 | 2451 | ||
2452 | static void | ||
2453 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr, | ||
2454 | struct nfsd4_secinfo *secinfo) | ||
2455 | { | ||
2456 | int i = 0; | ||
2457 | struct svc_export *exp = secinfo->si_exp; | ||
2458 | u32 nflavs; | ||
2459 | struct exp_flavor_info *flavs; | ||
2460 | struct exp_flavor_info def_flavs[2]; | ||
2461 | ENCODE_HEAD; | ||
2462 | |||
2463 | if (nfserr) | ||
2464 | goto out; | ||
2465 | if (exp->ex_nflavors) { | ||
2466 | flavs = exp->ex_flavors; | ||
2467 | nflavs = exp->ex_nflavors; | ||
2468 | } else { /* Handling of some defaults in absence of real secinfo: */ | ||
2469 | flavs = def_flavs; | ||
2470 | if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) { | ||
2471 | nflavs = 2; | ||
2472 | flavs[0].pseudoflavor = RPC_AUTH_UNIX; | ||
2473 | flavs[1].pseudoflavor = RPC_AUTH_NULL; | ||
2474 | } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) { | ||
2475 | nflavs = 1; | ||
2476 | flavs[0].pseudoflavor | ||
2477 | = svcauth_gss_flavor(exp->ex_client); | ||
2478 | } else { | ||
2479 | nflavs = 1; | ||
2480 | flavs[0].pseudoflavor | ||
2481 | = exp->ex_client->flavour->flavour; | ||
2482 | } | ||
2483 | } | ||
2484 | |||
2485 | RESERVE_SPACE(4); | ||
2486 | WRITE32(nflavs); | ||
2487 | ADJUST_ARGS(); | ||
2488 | for (i = 0; i < nflavs; i++) { | ||
2489 | u32 flav = flavs[i].pseudoflavor; | ||
2490 | struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); | ||
2491 | |||
2492 | if (gm) { | ||
2493 | RESERVE_SPACE(4); | ||
2494 | WRITE32(RPC_AUTH_GSS); | ||
2495 | ADJUST_ARGS(); | ||
2496 | RESERVE_SPACE(4 + gm->gm_oid.len); | ||
2497 | WRITE32(gm->gm_oid.len); | ||
2498 | WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); | ||
2499 | ADJUST_ARGS(); | ||
2500 | RESERVE_SPACE(4); | ||
2501 | WRITE32(0); /* qop */ | ||
2502 | ADJUST_ARGS(); | ||
2503 | RESERVE_SPACE(4); | ||
2504 | WRITE32(gss_pseudoflavor_to_service(gm, flav)); | ||
2505 | ADJUST_ARGS(); | ||
2506 | gss_mech_put(gm); | ||
2507 | } else { | ||
2508 | RESERVE_SPACE(4); | ||
2509 | WRITE32(flav); | ||
2510 | ADJUST_ARGS(); | ||
2511 | } | ||
2512 | } | ||
2513 | out: | ||
2514 | if (exp) | ||
2515 | exp_put(exp); | ||
2516 | } | ||
2517 | |||
2422 | /* | 2518 | /* |
2423 | * The SETATTR encode routine is special -- it always encodes a bitmap, | 2519 | * The SETATTR encode routine is special -- it always encodes a bitmap, |
2424 | * regardless of the error status. | 2520 | * regardless of the error status. |
@@ -2559,6 +2655,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
2559 | break; | 2655 | break; |
2560 | case OP_SAVEFH: | 2656 | case OP_SAVEFH: |
2561 | break; | 2657 | break; |
2658 | case OP_SECINFO: | ||
2659 | nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo); | ||
2660 | break; | ||
2562 | case OP_SETATTR: | 2661 | case OP_SETATTR: |
2563 | nfsd4_encode_setattr(resp, op->status, &op->u.setattr); | 2662 | nfsd4_encode_setattr(resp, op->status, &op->u.setattr); |
2564 | break; | 2663 | break; |