From owner-dev-commits-src-all@freebsd.org Sat Jun 26 22:50:23 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id BD72A65B129; Sat, 26 Jun 2021 22:50:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GC8GR4g59z3tDc; Sat, 26 Jun 2021 22:50:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8838226F4A; Sat, 26 Jun 2021 22:50:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 15QMoNOx050077; Sat, 26 Jun 2021 22:50:23 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 15QMoN1J050076; Sat, 26 Jun 2021 22:50:23 GMT (envelope-from git) Date: Sat, 26 Jun 2021 22:50:23 GMT Message-Id: <202106262250.15QMoN1J050076@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Rick Macklem Subject: git: 92500ec0c45c - stable/13 - nfsd: Fix the failure return for non-fh NFSv4 operations MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 92500ec0c45cbef90634fb9987287ac2768ab475 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Jun 2021 22:50:23 -0000 The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=92500ec0c45cbef90634fb9987287ac2768ab475 commit 92500ec0c45cbef90634fb9987287ac2768ab475 Author: Rick Macklem AuthorDate: 2021-06-02 22:28:07 +0000 Commit: Rick Macklem CommitDate: 2021-06-26 22:46:18 +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@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. (cherry picked from commit 984c71f90300906e106b9714af0e7d9b542c50e6) --- 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 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 };