git: 984c71f90300 - main - nfsd: Fix the failure return for non-fh NFSv4 operations

Rick Macklem rmacklem at FreeBSD.org
Wed Jun 2 22:31:33 UTC 2021


The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=984c71f90300906e106b9714af0e7d9b542c50e6

commit 984c71f90300906e106b9714af0e7d9b542c50e6
Author:     Rick Macklem <rmacklem at FreeBSD.org>
AuthorDate: 2021-06-02 22:28:07 +0000
Commit:     Rick Macklem <rmacklem at FreeBSD.org>
CommitDate: 2021-06-02 22:28:07 +0000

    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 at 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
---
 sys/fs/nfsserver/nfs_nfsdserv.c | 45 ++++++++++-------------------------------
 sys/fs/nfsserver/nfs_nfsdsubs.c | 11 ++++++++--
 sys/rpc/auth.h                  |  5 +++++
 3 files changed, 25 insertions(+), 36 deletions(-)

diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 329c096c7570..f4d6dbe42a21 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
 extern u_int32_t newnfs_false, newnfs_true;
 extern enum vtype nv34tov_type[8];
 extern struct timeval nfsboottime;
-extern int nfs_rootfhset;
 extern int nfsrv_enable_crossmntpt;
 extern int nfsrv_statehashsize;
 extern int nfsrv_layouthashsize;
@@ -3360,10 +3359,8 @@ nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
 	nfsquad_t clientid;
 	struct thread *p = curthread;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	clientid.lval[0] = *tl++;
 	clientid.lval[1] = *tl;
@@ -3625,10 +3622,8 @@ nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
 		nd->nd_repstat = NFSERR_NOTSUPP;
 		goto nfsmout;
 	}
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
 	clientid.lval[0] = *tl++;
 	clientid.lval[1] = *tl;
@@ -3893,10 +3888,8 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
 		nd->nd_repstat = NFSERR_NOTSUPP;
 		goto nfsmout;
 	}
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto out;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
 	verf = (u_char *)tl;
 	tl += (NFSX_VERF / NFSX_UNSIGNED);
@@ -4048,10 +4041,8 @@ nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
 		nd->nd_repstat = NFSERR_NOTSUPP;
 		goto nfsmout;
 	}
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
 	clientid.lval[0] = *tl++;
 	clientid.lval[1] = *tl++;
@@ -4146,10 +4137,8 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
 		nd->nd_repstat = NFSERR_NOTSUPP;
 		goto nfsmout;
 	}
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 	len = fxdr_unsigned(int, *(tl + 2));
 	if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
@@ -4213,10 +4202,8 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
 #endif
 	struct thread *p = curthread;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
 	verf = (uint8_t *)tl;
 	tl += (NFSX_VERF / NFSX_UNSIGNED);
@@ -4370,10 +4357,8 @@ nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
 	uint32_t rdmacnt;
 	struct thread *p = curthread;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
 	    M_NFSDSESSION, M_WAITOK | M_ZERO);
 	sep->sess_refcnt = 1;
@@ -4481,10 +4466,8 @@ nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
 	int cache_this, error = 0;
 	struct thread *p = curthread;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
 	NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
 	NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
@@ -4554,10 +4537,8 @@ nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
 	int error = 0;
 	struct thread *p = curthread;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	clientid.lval[0] = *tl++;
 	clientid.lval[1] = *tl;
@@ -4578,10 +4559,8 @@ nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram,
 	uint8_t sessid[NFSX_V4SESSIONID];
 	int error = 0, foreaft;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
 	NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
 	tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
@@ -4616,10 +4595,8 @@ nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
 	uint8_t *cp, sessid[NFSX_V4SESSIONID];
 	int error = 0;
 
-	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
-		nd->nd_repstat = NFSERR_WRONGSEC;
+	if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0)
 		goto nfsmout;
-	}
 	NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
 	NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
 	nd->nd_repstat = nfsrv_destroysession(nd, sessid);
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index 8c7db36bbd05..8c3e748a290f 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <fs/nfs/nfsport.h>
 
 extern u_int32_t newnfs_true, newnfs_false;
+extern int nfs_rootfhset;
 extern int nfs_pubfhset;
 extern struct nfsclienthashhead *nfsclienthash;
 extern int nfsrv_clienthashsize;
@@ -1543,6 +1544,8 @@ nfsd_errmap(struct nfsrv_descript *nd)
 
 	if (!nd->nd_repstat)
 		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_procnum == NFSPROC_NOOP)
 			return (txdr_unsigned(nd->nd_repstat & 0xffff));
@@ -2116,6 +2119,8 @@ int
 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)
 		goto checktls;
 	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 |
 	     ND_EXGSS)) == (ND_GSS | ND_EXGSS))
 		goto checktls;
-	return (1);
+	return (NFSERR_AUTHERR | AUTH_TOOWEAK);
 checktls:
 	if ((nd->nd_flag & ND_EXTLS) == 0)
 		return (0);
@@ -2140,7 +2145,9 @@ checktls:
 	if ((nd->nd_flag & (ND_TLS | ND_EXTLSCERTUSER | ND_EXTLSCERT)) ==
 	    ND_TLS)
 		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);
 }
 
 /*
diff --git a/sys/rpc/auth.h b/sys/rpc/auth.h
index a426a34c3747..fd56b33da52e 100644
--- a/sys/rpc/auth.h
+++ b/sys/rpc/auth.h
@@ -150,6 +150,11 @@ enum auth_stat {
 	 */
 	RPCSEC_GSS_CREDPROBLEM = 13,
 	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 */
 	RPCSEC_GSS_NODISPATCH = 0x8000000
 };


More information about the dev-commits-src-all mailing list