nfsd: Add support for the NFSv4.1/4.2 Secinfo_no_name operation
The Linux client is now attempting to use the Secinfo_no_name operation for NFSv4.1/4.2 mounts. Although it does not seem to mind the NFSERR_NOTSUPP reply, adding support for it seems reasonable. I also noticed that "savflag" needed to be 64bits in nfsrvd_secinfo() since nd_flag in now 64bits, so I changed the declaration of it there. I also added code to set "vp" NULL after performing Secinfo/Secinfo_no_name, since these operations consume the current FH, which is represented by "vp" in nfsrvd_compound(). Fixing when the server replies NFSERR_WRONGSEC so that it conforms to RFC5661 Sec. 2.6 still needs to be done in a future commit. MFC after: 2 weeks
This commit is contained in:
parent
f0d577fd2d
commit
947bd2479b
@ -168,7 +168,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
|
||||
{ 0, 1, 0, 1, LK_EXCLUSIVE, 1, 1 }, /* Layout Commit */
|
||||
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Layout Get */
|
||||
{ 0, 1, 0, 1, LK_EXCLUSIVE, 1, 0 }, /* Layout Return */
|
||||
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Secinfo No name */
|
||||
{ 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Secinfo No name */
|
||||
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Sequence */
|
||||
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Set SSV */
|
||||
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Test StateID */
|
||||
|
@ -232,6 +232,8 @@ int nfsrvd_renew(struct nfsrv_descript *, int,
|
||||
vnode_t, struct nfsexstuff *);
|
||||
int nfsrvd_secinfo(struct nfsrv_descript *, int,
|
||||
vnode_t, struct nfsexstuff *);
|
||||
int nfsrvd_secinfononame(struct nfsrv_descript *, int,
|
||||
vnode_t, struct nfsexstuff *);
|
||||
int nfsrvd_setclientid(struct nfsrv_descript *, int,
|
||||
vnode_t, struct nfsexstuff *);
|
||||
int nfsrvd_setclientidcfrm(struct nfsrv_descript *, int,
|
||||
|
@ -726,6 +726,10 @@
|
||||
#define NFSCDFS4_BACK 0x2
|
||||
#define NFSCDFS4_BOTH 0x3
|
||||
|
||||
/* Enum values for Secinfo_no_name. */
|
||||
#define NFSSECINFONONAME_CURFH 0
|
||||
#define NFSSECINFONONAME_PARENT 1
|
||||
|
||||
#if defined(_KERNEL) || defined(KERNEL)
|
||||
/* Conversion macros */
|
||||
#define vtonfsv2_mode(t,m) \
|
||||
|
@ -3664,7 +3664,8 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
|
||||
struct nfsrvfh fh;
|
||||
struct nfsexstuff retnes;
|
||||
u_int32_t *sizp;
|
||||
int error = 0, savflag, i;
|
||||
int error = 0, i;
|
||||
uint64_t savflag;
|
||||
char *bufp;
|
||||
u_long *hashp;
|
||||
struct thread *p = curthread;
|
||||
@ -3754,6 +3755,116 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfsv4 security info no name service
|
||||
*/
|
||||
int
|
||||
nfsrvd_secinfononame(struct nfsrv_descript *nd, int isdgram,
|
||||
vnode_t dp, struct nfsexstuff *exp)
|
||||
{
|
||||
uint32_t *tl, *sizp;
|
||||
struct nameidata named;
|
||||
vnode_t dirp = NULL, vp;
|
||||
struct nfsrvfh fh;
|
||||
struct nfsexstuff retnes;
|
||||
int error = 0, fhstyle, i, len;
|
||||
uint64_t savflag;
|
||||
char *bufp;
|
||||
u_long *hashp;
|
||||
struct thread *p = curthread;
|
||||
|
||||
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
fhstyle = fxdr_unsigned(int, *tl);
|
||||
switch (fhstyle) {
|
||||
case NFSSECINFONONAME_PARENT:
|
||||
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
|
||||
LOCKLEAF | SAVESTART);
|
||||
nfsvno_setpathbuf(&named, &bufp, &hashp);
|
||||
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
|
||||
if (error != 0) {
|
||||
vput(dp);
|
||||
nfsvno_relpathbuf(&named);
|
||||
goto nfsmout;
|
||||
}
|
||||
if (nd->nd_repstat == 0)
|
||||
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
|
||||
else
|
||||
vput(dp);
|
||||
if (dirp != NULL)
|
||||
vrele(dirp);
|
||||
vrele(named.ni_startdir);
|
||||
nfsvno_relpathbuf(&named);
|
||||
vp = named.ni_vp;
|
||||
break;
|
||||
case NFSSECINFONONAME_CURFH:
|
||||
vp = dp;
|
||||
break;
|
||||
default:
|
||||
nd->nd_repstat = NFSERR_INVAL;
|
||||
vput(dp);
|
||||
}
|
||||
if (nd->nd_repstat != 0)
|
||||
goto nfsmout;
|
||||
fh.nfsrvfh_len = NFSX_MYFH;
|
||||
nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
|
||||
vput(vp);
|
||||
savflag = nd->nd_flag;
|
||||
if (nd->nd_repstat == 0) {
|
||||
nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0);
|
||||
if (vp != NULL)
|
||||
vput(vp);
|
||||
}
|
||||
nd->nd_flag = savflag;
|
||||
if (nd->nd_repstat != 0)
|
||||
goto nfsmout;
|
||||
|
||||
/*
|
||||
* Finally have the export flags for fh/parent, so we can create
|
||||
* the security info.
|
||||
*/
|
||||
len = 0;
|
||||
NFSM_BUILD(sizp, uint32_t *, NFSX_UNSIGNED);
|
||||
for (i = 0; i < retnes.nes_numsecflavor; i++) {
|
||||
if (retnes.nes_secflavors[i] == AUTH_SYS) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(RPCAUTH_UNIX);
|
||||
len++;
|
||||
} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(RPCAUTH_GSS);
|
||||
nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
|
||||
nfsgss_mechlist[KERBV_MECH].len);
|
||||
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(GSS_KERBV_QOP);
|
||||
*tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
|
||||
len++;
|
||||
} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(RPCAUTH_GSS);
|
||||
nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
|
||||
nfsgss_mechlist[KERBV_MECH].len);
|
||||
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(GSS_KERBV_QOP);
|
||||
*tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
|
||||
len++;
|
||||
} else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(RPCAUTH_GSS);
|
||||
nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
|
||||
nfsgss_mechlist[KERBV_MECH].len);
|
||||
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(GSS_KERBV_QOP);
|
||||
*tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
|
||||
len++;
|
||||
}
|
||||
}
|
||||
*sizp = txdr_unsigned(len);
|
||||
|
||||
nfsmout:
|
||||
NFSEXITCODE2(error, nd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfsv4 set client id service
|
||||
*/
|
||||
|
@ -188,7 +188,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
|
||||
nfsrvd_layoutcommit,
|
||||
nfsrvd_layoutget,
|
||||
nfsrvd_layoutreturn,
|
||||
nfsrvd_notsupp,
|
||||
nfsrvd_secinfononame,
|
||||
nfsrvd_sequence,
|
||||
nfsrvd_notsupp,
|
||||
nfsrvd_teststateid,
|
||||
@ -1175,9 +1175,20 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (nd->nd_repstat == 0)
|
||||
if (nd->nd_repstat == 0) {
|
||||
error = (*(nfsrv4_ops0[op]))(nd,
|
||||
isdgram, vp, &vpnes);
|
||||
if ((op == NFSV4OP_SECINFO ||
|
||||
op == NFSV4OP_SECINFONONAME) &&
|
||||
error == 0 && nd->nd_repstat == 0) {
|
||||
/*
|
||||
* Secinfo and Secinfo_no_name
|
||||
* consume the current FH.
|
||||
*/
|
||||
vrele(vp);
|
||||
vp = NULL;
|
||||
}
|
||||
}
|
||||
if (nfsv4_opflag[op].modifyfs)
|
||||
vn_finished_write(temp_mp);
|
||||
} else {
|
||||
|
@ -1890,7 +1890,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
|
||||
* For V4, check for lookup parent.
|
||||
* Otherwise, get the component name.
|
||||
*/
|
||||
if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
|
||||
if ((nd->nd_flag & ND_NFSV4) && (nd->nd_procnum == NFSV4OP_LOOKUPP ||
|
||||
nd->nd_procnum == NFSV4OP_SECINFONONAME)) {
|
||||
*tocp++ = '.';
|
||||
hash += ((u_char)'.');
|
||||
*tocp++ = '.';
|
||||
|
Loading…
Reference in New Issue
Block a user