aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c101
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
821static __be32 823static __be32
824nfsd4_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
840static __be32
822nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 841nfsd4_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
2452static void
2453nfsd4_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 }
2513out:
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;