diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b0bfbda..864498f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -56,6 +56,7 @@ #include <linux/nfsd_idmap.h> #include <linux/nfs4.h> #include <linux/nfs4_acl.h> +#include <linux/sunrpc/gss_api.h> #define NFSDDBG_FACILITY NFSDDBG_XDR @@ -819,6 +820,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) } static __be32 +nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, + struct nfsd4_secinfo *secinfo) +{ + DECODE_HEAD; + + READ_BUF(4); + READ32(secinfo->si_namelen); + READ_BUF(secinfo->si_namelen); + SAVEMEM(secinfo->si_name, secinfo->si_namelen); + status = check_filename(secinfo->si_name, secinfo->si_namelen, + nfserr_noent); + if (status) + return status; + DECODE_TAIL; +} + +static __be32 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) { DECODE_HEAD; @@ -1131,6 +1149,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) case OP_SAVEFH: op->status = nfs_ok; break; + case OP_SECINFO: + op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo); + break; case OP_SETATTR: op->status = nfsd4_decode_setattr(argp, &op->u.setattr); break; @@ -1847,11 +1868,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, if (d_mountpoint(dentry)) { int err; + /* + * Why the heck aren't we just using nfsd_lookup?? + * Different "."/".." handling? Something else? + * At least, add a comment here to explain.... + */ err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); if (err) { nfserr = nfserrno(err); goto out_put; } + nfserr = check_nfsd_access(exp, cd->rd_rqstp); + if (nfserr) + goto out_put; } 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_ } } +static void +nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr, + struct nfsd4_secinfo *secinfo) +{ + int i = 0; + struct svc_export *exp = secinfo->si_exp; + ENCODE_HEAD; + + if (nfserr) + goto out; + RESERVE_SPACE(4); + WRITE32(exp->ex_nflavors); + ADJUST_ARGS(); + for (i = 0; i < exp->ex_nflavors; i++) { + u32 flav = exp->ex_flavors[i].pseudoflavor; + struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); + + if (gm) { + RESERVE_SPACE(4); + WRITE32(RPC_AUTH_GSS); + ADJUST_ARGS(); + RESERVE_SPACE(4 + gm->gm_oid.len); + WRITE32(gm->gm_oid.len); + WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); + ADJUST_ARGS(); + RESERVE_SPACE(4); + WRITE32(0); /* qop */ + ADJUST_ARGS(); + RESERVE_SPACE(4); + WRITE32(gss_pseudoflavor_to_service(gm, flav)); + ADJUST_ARGS(); + gss_mech_put(gm); + } else { + RESERVE_SPACE(4); + WRITE32(flav); + ADJUST_ARGS(); + } + } +out: + if (exp) + exp_put(exp); +} + /* * The SETATTR encode routine is special -- it always encodes a bitmap, * regardless of the error status. @@ -2559,6 +2631,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) break; case OP_SAVEFH: break; + case OP_SECINFO: + nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo); + break; case OP_SETATTR: nfsd4_encode_setattr(resp, op->status, &op->u.setattr); break; |