nfsd: Fix the failure return for non-fh NFSv4 operations
Without this patch, nfsd_checkrootexp() returns failure and then the NFSv4 operation would reply NFSERR_WRONGSEC. RFC5661 Sec. 2.6 only allows a few NFSv4 operations, none of which call nfsv4_checktootexp(), to return NFSERR_WRONGSEC. This patch modifies nfsd_checkrootexp() to return the error instead of a boolean and sets the returned error to an RPC layer AUTH_ERR, as discussed on nfsv4@ietf.org. The patch also fixes nfsd_errmap() so that the pseudo error NFSERR_AUTHERR is handled correctly such that an RPC layer AUTH_ERR is replied to the NFSv4 client. The two new "enum auth_stat" values have not yet been assigned by IANA, but are the expected next two values. The effect on extant NFSv4 clients of this change appears limited to reporting a different failure error when a mount that does not use adequate security is attempted. MFC after: 2 weeks
This commit is contained in:
parent
56fd97660a
commit
984c71f903
@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
extern u_int32_t newnfs_false, newnfs_true;
|
extern u_int32_t newnfs_false, newnfs_true;
|
||||||
extern enum vtype nv34tov_type[8];
|
extern enum vtype nv34tov_type[8];
|
||||||
extern struct timeval nfsboottime;
|
extern struct timeval nfsboottime;
|
||||||
extern int nfs_rootfhset;
|
|
||||||
extern int nfsrv_enable_crossmntpt;
|
extern int nfsrv_enable_crossmntpt;
|
||||||
extern int nfsrv_statehashsize;
|
extern int nfsrv_statehashsize;
|
||||||
extern int nfsrv_layouthashsize;
|
extern int nfsrv_layouthashsize;
|
||||||
@ -3360,10 +3359,8 @@ nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
nfsquad_t clientid;
|
nfsquad_t clientid;
|
||||||
struct thread *p = curthread;
|
struct thread *p = curthread;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
||||||
clientid.lval[0] = *tl++;
|
clientid.lval[0] = *tl++;
|
||||||
clientid.lval[1] = *tl;
|
clientid.lval[1] = *tl;
|
||||||
@ -3625,10 +3622,8 @@ nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
nd->nd_repstat = NFSERR_NOTSUPP;
|
nd->nd_repstat = NFSERR_NOTSUPP;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
|
NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
|
||||||
clientid.lval[0] = *tl++;
|
clientid.lval[0] = *tl++;
|
||||||
clientid.lval[1] = *tl;
|
clientid.lval[1] = *tl;
|
||||||
@ -3893,10 +3888,8 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
nd->nd_repstat = NFSERR_NOTSUPP;
|
nd->nd_repstat = NFSERR_NOTSUPP;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
|
||||||
verf = (u_char *)tl;
|
verf = (u_char *)tl;
|
||||||
tl += (NFSX_VERF / NFSX_UNSIGNED);
|
tl += (NFSX_VERF / NFSX_UNSIGNED);
|
||||||
@ -4048,10 +4041,8 @@ nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
|
|||||||
nd->nd_repstat = NFSERR_NOTSUPP;
|
nd->nd_repstat = NFSERR_NOTSUPP;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
|
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
|
||||||
clientid.lval[0] = *tl++;
|
clientid.lval[0] = *tl++;
|
||||||
clientid.lval[1] = *tl++;
|
clientid.lval[1] = *tl++;
|
||||||
@ -4146,10 +4137,8 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
nd->nd_repstat = NFSERR_NOTSUPP;
|
nd->nd_repstat = NFSERR_NOTSUPP;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
|
||||||
len = fxdr_unsigned(int, *(tl + 2));
|
len = fxdr_unsigned(int, *(tl + 2));
|
||||||
if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
|
if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
|
||||||
@ -4213,10 +4202,8 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
#endif
|
#endif
|
||||||
struct thread *p = curthread;
|
struct thread *p = curthread;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
|
||||||
verf = (uint8_t *)tl;
|
verf = (uint8_t *)tl;
|
||||||
tl += (NFSX_VERF / NFSX_UNSIGNED);
|
tl += (NFSX_VERF / NFSX_UNSIGNED);
|
||||||
@ -4370,10 +4357,8 @@ nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
uint32_t rdmacnt;
|
uint32_t rdmacnt;
|
||||||
struct thread *p = curthread;
|
struct thread *p = curthread;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
|
sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
|
||||||
M_NFSDSESSION, M_WAITOK | M_ZERO);
|
M_NFSDSESSION, M_WAITOK | M_ZERO);
|
||||||
sep->sess_refcnt = 1;
|
sep->sess_refcnt = 1;
|
||||||
@ -4481,10 +4466,8 @@ nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
int cache_this, error = 0;
|
int cache_this, error = 0;
|
||||||
struct thread *p = curthread;
|
struct thread *p = curthread;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
|
NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
|
||||||
NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
|
NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
|
||||||
NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
|
||||||
@ -4554,10 +4537,8 @@ nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
struct thread *p = curthread;
|
struct thread *p = curthread;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||||
clientid.lval[0] = *tl++;
|
clientid.lval[0] = *tl++;
|
||||||
clientid.lval[1] = *tl;
|
clientid.lval[1] = *tl;
|
||||||
@ -4578,10 +4559,8 @@ nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
uint8_t sessid[NFSX_V4SESSIONID];
|
uint8_t sessid[NFSX_V4SESSIONID];
|
||||||
int error = 0, foreaft;
|
int error = 0, foreaft;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
|
||||||
NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
|
NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
|
||||||
tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
|
tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
|
||||||
@ -4616,10 +4595,8 @@ nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
uint8_t *cp, sessid[NFSX_V4SESSIONID];
|
uint8_t *cp, sessid[NFSX_V4SESSIONID];
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
|
if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
|
||||||
nd->nd_repstat = NFSERR_WRONGSEC;
|
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
|
||||||
NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
|
NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
|
||||||
NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
|
NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
|
||||||
nd->nd_repstat = nfsrv_destroysession(nd, sessid);
|
nd->nd_repstat = nfsrv_destroysession(nd, sessid);
|
||||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <fs/nfs/nfsport.h>
|
#include <fs/nfs/nfsport.h>
|
||||||
|
|
||||||
extern u_int32_t newnfs_true, newnfs_false;
|
extern u_int32_t newnfs_true, newnfs_false;
|
||||||
|
extern int nfs_rootfhset;
|
||||||
extern int nfs_pubfhset;
|
extern int nfs_pubfhset;
|
||||||
extern struct nfsclienthashhead *nfsclienthash;
|
extern struct nfsclienthashhead *nfsclienthash;
|
||||||
extern int nfsrv_clienthashsize;
|
extern int nfsrv_clienthashsize;
|
||||||
@ -1543,6 +1544,8 @@ nfsd_errmap(struct nfsrv_descript *nd)
|
|||||||
|
|
||||||
if (!nd->nd_repstat)
|
if (!nd->nd_repstat)
|
||||||
return (0);
|
return (0);
|
||||||
|
if ((nd->nd_repstat & NFSERR_AUTHERR) != 0)
|
||||||
|
return (txdr_unsigned(NFSERR_ACCES));
|
||||||
if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
|
if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
|
||||||
if (nd->nd_procnum == NFSPROC_NOOP)
|
if (nd->nd_procnum == NFSPROC_NOOP)
|
||||||
return (txdr_unsigned(nd->nd_repstat & 0xffff));
|
return (txdr_unsigned(nd->nd_repstat & 0xffff));
|
||||||
@ -2116,6 +2119,8 @@ int
|
|||||||
nfsd_checkrootexp(struct nfsrv_descript *nd)
|
nfsd_checkrootexp(struct nfsrv_descript *nd)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (nfs_rootfhset == 0)
|
||||||
|
return (NFSERR_AUTHERR | AUTH_FAILED);
|
||||||
if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
|
if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
|
||||||
goto checktls;
|
goto checktls;
|
||||||
if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
|
if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
|
||||||
@ -2127,7 +2132,7 @@ nfsd_checkrootexp(struct nfsrv_descript *nd)
|
|||||||
if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
|
if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
|
||||||
ND_EXGSS)) == (ND_GSS | ND_EXGSS))
|
ND_EXGSS)) == (ND_GSS | ND_EXGSS))
|
||||||
goto checktls;
|
goto checktls;
|
||||||
return (1);
|
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||||
checktls:
|
checktls:
|
||||||
if ((nd->nd_flag & ND_EXTLS) == 0)
|
if ((nd->nd_flag & ND_EXTLS) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
@ -2140,7 +2145,9 @@ nfsd_checkrootexp(struct nfsrv_descript *nd)
|
|||||||
if ((nd->nd_flag & (ND_TLS | ND_EXTLSCERTUSER | ND_EXTLSCERT)) ==
|
if ((nd->nd_flag & (ND_TLS | ND_EXTLSCERTUSER | ND_EXTLSCERT)) ==
|
||||||
ND_TLS)
|
ND_TLS)
|
||||||
return (0);
|
return (0);
|
||||||
return (1);
|
if ((nd->nd_flag & ND_TLS) == 0)
|
||||||
|
return (NFSERR_AUTHERR | AUTH_NEEDS_TLS);
|
||||||
|
return (NFSERR_AUTHERR | AUTH_NEEDS_TLS_MUTUAL_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -150,6 +150,11 @@ enum auth_stat {
|
|||||||
*/
|
*/
|
||||||
RPCSEC_GSS_CREDPROBLEM = 13,
|
RPCSEC_GSS_CREDPROBLEM = 13,
|
||||||
RPCSEC_GSS_CTXPROBLEM = 14,
|
RPCSEC_GSS_CTXPROBLEM = 14,
|
||||||
|
/*
|
||||||
|
* RPC-over-TLS errors
|
||||||
|
*/
|
||||||
|
AUTH_NEEDS_TLS = 15,
|
||||||
|
AUTH_NEEDS_TLS_MUTUAL_HOST = 16,
|
||||||
/* Also used by RPCSEC_TLS for the same purpose */
|
/* Also used by RPCSEC_TLS for the same purpose */
|
||||||
RPCSEC_GSS_NODISPATCH = 0x8000000
|
RPCSEC_GSS_NODISPATCH = 0x8000000
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user