|
@@ -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
|
|
|
|
|
@@ -818,6 +819,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
|
|
|
DECODE_TAIL;
|
|
|
}
|
|
|
|
|
|
+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)
|
|
|
{
|
|
@@ -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;
|