svn commit: r364475 - in head/sys: conf modules/krpc rpc rpc/rpcsec_tls

Rick Macklem rmacklem at FreeBSD.org
Sat Aug 22 03:57:58 UTC 2020


Author: rmacklem
Date: Sat Aug 22 03:57:55 2020
New Revision: 364475
URL: https://svnweb.freebsd.org/changeset/base/364475

Log:
  Add TLS support to the kernel RPC.
  
  An internet draft titled "Towards Remote Procedure Call Encryption By Default"
  describes how TLS is to be used for Sun RPC, with NFS as an intended use case.
  This patch adds client and server support for this to the kernel RPC,
  using KERN_TLS and upcalls to daemons for the handshake, peer reset and
  other non-application data record cases.
  
  The upcalls to the daemons use three fields to uniquely identify the
  TCP connection. They are the time.tv_sec, time.tv_usec of the connection
  establshment, plus a 64bit sequence number. The time fields avoid problems
  with re-use of the sequence number after a daemon restart.
  For the server side, once a Null RPC with AUTH_TLS is received, kernel
  reception on the socket is blocked and an upcall to the rpctlssd(8) daemon
  is done to perform the TLS handshake.  Upon completion, the completion
  status of the handshake is stored in xp_tls as flag bits and the reply to
  the Null RPC is sent.
  For the client, if CLSET_TLS has been set, a new TCP connection will
  send the Null RPC with AUTH_TLS to initiate the handshake.  The client
  kernel RPC code will then block kernel I/O on the socket and do an upcall
  to the rpctlscd(8) daemon to perform the handshake.
  If the upcall is successful, ct_rcvstate will be maintained to indicate
  if/when an upcall is being done.
  
  If non-application data records are received, the code does an upcall to
  the appropriate daemon, which will do a SSL_read() of 0 length to handle
  the record(s).
  
  When the socket is being shut down, upcalls are done to the daemons, so
  that they can perform SSL_shutdown() calls to perform the "peer reset".
  
  The rpctlssd(8) and rpctlscd(8) daemons require a patched version of the
  openssl library and, as such, will not be committed to head at this time.
  
  Although the changes done by this patch are fairly numerous, there should
  be no semantics change to the kernel RPC at this time.
  A future commit to the NFS code will optionally enable use of TLS for NFS.

Added:
  head/sys/rpc/rpcsec_tls/
  head/sys/rpc/rpcsec_tls/auth_tls.c   (contents, props changed)
  head/sys/rpc/rpcsec_tls/rpctls_impl.c   (contents, props changed)
  head/sys/rpc/rpcsec_tls/rpctlscd.x   (contents, props changed)
  head/sys/rpc/rpcsec_tls/rpctlssd.x   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/modules/krpc/Makefile
  head/sys/rpc/auth.h
  head/sys/rpc/clnt_bck.c
  head/sys/rpc/clnt_rc.c
  head/sys/rpc/clnt_vc.c
  head/sys/rpc/krpc.h
  head/sys/rpc/rpc_generic.c
  head/sys/rpc/rpcsec_tls.h
  head/sys/rpc/svc.h
  head/sys/rpc/svc_auth.c
  head/sys/rpc/svc_vc.c

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/conf/files	Sat Aug 22 03:57:55 2020	(r364475)
@@ -4868,6 +4868,41 @@ rpc/svc_auth_unix.c		optional krpc | nfslockd | nfscl 
 rpc/svc_dg.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_generic.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_vc.c			optional krpc | nfslockd | nfscl | nfsd
+#
+# Kernel RPC-over-TLS
+#
+rpctlscd.h			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x"			\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -hM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v pthread.h > rpctlscd.h" \
+	no-obj no-implicit-rule before-depend local			\
+	clean			"rpctlscd.h"
+rpctlscd_xdr.c			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x rpctlscd.h"		\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -c $S/rpc/rpcsec_tls/rpctlscd.x -o rpctlscd_xdr.c" no-ctfconvert \
+	no-implicit-rule before-depend local				\
+	clean			"rpctlscd_xdr.c"
+rpctlscd_clnt.c			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x rpctlscd.h"		\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -lM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v string.h > rpctlscd_clnt.c" no-ctfconvert \
+	no-implicit-rule before-depend local				\
+	clean			"rpctlscd_clnt.c"
+rpctlssd.h			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x"			\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -hM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v pthread.h > rpctlssd.h" \
+	no-obj no-implicit-rule before-depend local			\
+	clean			"rpctlssd.h"
+rpctlssd_xdr.c			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x rpctlssd.h"		\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -c $S/rpc/rpcsec_tls/rpctlssd.x -o rpctlssd_xdr.c" no-ctfconvert \
+	no-implicit-rule before-depend local				\
+	clean			"rpctlssd_xdr.c"
+rpctlssd_clnt.c			optional krpc | nfslockd | nfscl | nfsd	\
+	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x rpctlssd.h"		\
+	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -lM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v string.h > rpctlssd_clnt.c" no-ctfconvert \
+	no-implicit-rule before-depend local				\
+	clean			"rpctlssd_clnt.c"
+rpc/rpcsec_tls/rpctls_impl.c	optional krpc | nfslockd | nfscl | nfsd
+rpc/rpcsec_tls/auth_tls.c	optional krpc | nfslockd | nfscl | nfsd
 rpc/rpcsec_gss/rpcsec_gss.c	optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/rpcsec_gss_conf.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/rpcsec_gss_misc.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi

Modified: head/sys/modules/krpc/Makefile
==============================================================================
--- head/sys/modules/krpc/Makefile	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/modules/krpc/Makefile	Sat Aug 22 03:57:55 2020	(r364475)
@@ -1,6 +1,6 @@
 # $FreeBSD$
 
-.PATH: ${SRCTOP}/sys/rpc
+.PATH: ${SRCTOP}/sys/rpc ${SRCTOP}/sys/rpc/rpcsec_tls
 KMOD=	krpc
 SRCS=	auth_none.c \
 	auth_unix.c \
@@ -21,8 +21,38 @@ SRCS=	auth_none.c \
 	svc_auth_unix.c \
 	svc_dg.c \
 	svc_generic.c \
-	svc_vc.c \
+	svc_vc.c
 
-SRCS+=	opt_inet6.h
+SRCS+=	rpctls_impl.c auth_tls.c
+
+SRCS+=	opt_inet6.h opt_kern_tls.h
+
+SRCS+=		rpctlscd.h rpctlscd_xdr.c rpctlscd_clnt.c
+CLEANFILES=	rpctlscd.h rpctlscd_xdr.c rpctlscd_clnt.c
+
+S=		${SRCTOP}/sys
+
+rpctlscd.h:	$S/rpc/rpcsec_tls/rpctlscd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -hM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v pthread.h > rpctlscd.h
+
+rpctlscd_xdr.c:	$S/rpc/rpcsec_tls/rpctlscd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -c $S/rpc/rpcsec_tls/rpctlscd.x -o rpctlscd_xdr.c
+
+rpctlscd_clnt.c:	$S/rpc/rpcsec_tls/rpctlscd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -lM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v string.h > rpctlscd_clnt.c
+
+SRCS+=		rpctlssd.h rpctlssd_xdr.c rpctlssd_clnt.c
+CLEANFILES=	rpctlssd.h rpctlssd_xdr.c rpctlssd_clnt.c
+
+S=		${SRCTOP}/sys
+
+rpctlssd.h:	$S/rpc/rpcsec_tls/rpctlssd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -hM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v pthread.h > rpctlssd.h
+
+rpctlssd_xdr.c:	$S/rpc/rpcsec_tls/rpctlssd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -c $S/rpc/rpcsec_tls/rpctlssd.x -o rpctlssd_xdr.c
+
+rpctlssd_clnt.c:	$S/rpc/rpcsec_tls/rpctlssd.x
+	RPCGEN_CPP=${CPP:Q} rpcgen -lM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v string.h > rpctlssd_clnt.c
 
 .include <bsd.kmod.mk>

Modified: head/sys/rpc/auth.h
==============================================================================
--- head/sys/rpc/auth.h	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/auth.h	Sat Aug 22 03:57:55 2020	(r364475)
@@ -150,6 +150,7 @@ enum auth_stat {
 	 */
 	RPCSEC_GSS_CREDPROBLEM = 13,
 	RPCSEC_GSS_CTXPROBLEM = 14,
+	/* Also used by RPCSEC_TLS for the same purpose */
 	RPCSEC_GSS_NODISPATCH = 0x8000000
 };
 
@@ -249,6 +250,7 @@ extern AUTH *authunix_create(char *, u_int, u_int, int
 extern AUTH *authunix_create_default(void);	/* takes no parameters */
 #endif
 extern AUTH *authnone_create(void);		/* takes no parameters */
+extern AUTH *authtls_create(void);		/* takes no parameters */
 __END_DECLS
 /*
  * DES style authentication
@@ -344,6 +346,7 @@ struct rpc_msg;
 enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *);
 enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
 enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
+enum auth_stat _svcauth_rpcsec_tls (struct svc_req *, struct rpc_msg *);
 __END_DECLS
 
 #define AUTH_NONE	0		/* no authentication */
@@ -355,6 +358,7 @@ __END_DECLS
 #define AUTH_DES	AUTH_DH		/* for backward compatibility */
 #define AUTH_KERB	4		/* kerberos style */
 #define RPCSEC_GSS	6		/* RPCSEC_GSS */
+#define	AUTH_TLS	7		/* Initiate RPC-over-TLS */
 
 /*
  * Pseudo auth flavors for RPCSEC_GSS.

Modified: head/sys/rpc/clnt_bck.c
==============================================================================
--- head/sys/rpc/clnt_bck.c	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/clnt_bck.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -61,8 +61,11 @@ __FBSDID("$FreeBSD$");
  * connection provided by the client to the server.
  */
 
+#include "opt_kern_tls.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/ktls.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
@@ -84,6 +87,7 @@ __FBSDID("$FreeBSD$");
 #include <rpc/rpc.h>
 #include <rpc/rpc_com.h>
 #include <rpc/krpc.h>
+#include <rpc/rpcsec_tls.h>
 
 struct cmessage {
         struct cmsghdr cmsg;
@@ -203,7 +207,10 @@ clnt_bck_call(
 	uint32_t xid;
 	struct mbuf *mreq = NULL, *results;
 	struct ct_request *cr;
-	int error;
+	int error, maxextsiz;
+#ifdef KERN_TLS
+	u_int maxlen;
+#endif
 
 	cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
 
@@ -296,6 +303,19 @@ call_again:
 	TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link);
 	mtx_unlock(&ct->ct_lock);
 
+	/* For RPC-over-TLS, copy mrep to a chain of ext_pgs. */
+	if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) {
+		/*
+		 * Copy the mbuf chain to a chain of
+		 * ext_pgs mbuf(s) as required by KERN_TLS.
+		 */
+		maxextsiz = TLS_MAX_MSG_SIZE_V10_2;
+#ifdef KERN_TLS
+		if (rpctls_getinfo(&maxlen, false, false))
+			maxextsiz = min(maxextsiz, maxlen);
+#endif
+		mreq = _rpc_copym_into_ext_pgs(mreq, maxextsiz);
+	}
 	/*
 	 * sosend consumes mreq.
 	 */

Modified: head/sys/rpc/clnt_rc.c
==============================================================================
--- head/sys/rpc/clnt_rc.c	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/clnt_rc.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <rpc/rpc.h>
 #include <rpc/rpc_com.h>
 #include <rpc/krpc.h>
+#include <rpc/rpcsec_tls.h>
 
 static enum clnt_stat clnt_reconnect_call(CLIENT *, struct rpc_callextra *,
     rpcproc_t, struct mbuf *, struct mbuf **, struct timeval);
@@ -108,6 +109,7 @@ clnt_reconnect_create(
 	rc->rc_closed = FALSE;
 	rc->rc_ucred = crdup(curthread->td_ucred);
 	rc->rc_client = NULL;
+	rc->rc_tls = false;
 
 	cl->cl_refs = 1;
 	cl->cl_ops = &clnt_reconnect_ops;
@@ -129,6 +131,8 @@ clnt_reconnect_connect(CLIENT *cl)
 	int one = 1;
 	struct ucred *oldcred;
 	CLIENT *newclient = NULL;
+	uint64_t ssl[3];
+	uint32_t reterr;
 
 	mtx_lock(&rc->rc_lock);
 	while (rc->rc_connecting) {
@@ -193,6 +197,20 @@ clnt_reconnect_connect(CLIENT *cl)
 		newclient = clnt_vc_create(so,
 		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
 		    rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
+		if (rc->rc_tls && newclient != NULL) {
+			stat = rpctls_connect(newclient, so, ssl, &reterr);
+			if (stat != RPC_SUCCESS || reterr != RPCTLSERR_OK) {
+				if (stat == RPC_SUCCESS)
+					stat = RPC_FAILED;
+				stat = rpc_createerr.cf_stat = stat;
+				rpc_createerr.cf_error.re_errno = 0;
+				CLNT_CLOSE(newclient);
+				CLNT_RELEASE(newclient);
+				newclient = NULL;
+				td->td_ucred = oldcred;
+				goto out;
+			}
+		}
 	}
 	td->td_ucred = oldcred;
 
@@ -209,6 +227,8 @@ clnt_reconnect_connect(CLIENT *cl)
 	CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry);
 	CLNT_CONTROL(newclient, CLSET_WAITCHAN, rc->rc_waitchan);
 	CLNT_CONTROL(newclient, CLSET_INTERRUPTIBLE, &rc->rc_intr);
+	if (rc->rc_tls)
+		CLNT_CONTROL(newclient, CLSET_TLS, ssl);
 	if (rc->rc_backchannel != NULL)
 		CLNT_CONTROL(newclient, CLSET_BACKCHANNEL, rc->rc_backchannel);
 	stat = RPC_SUCCESS;
@@ -470,6 +490,10 @@ clnt_reconnect_control(CLIENT *cl, u_int request, void
 		xprt = (SVCXPRT *)info;
 		xprt_register(xprt);
 		rc->rc_backchannel = info;
+		break;
+
+	case CLSET_TLS:
+		rc->rc_tls = true;
 		break;
 
 	default:

Modified: head/sys/rpc/clnt_vc.c
==============================================================================
--- head/sys/rpc/clnt_vc.c	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/clnt_vc.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -57,9 +57,13 @@ __FBSDID("$FreeBSD$");
  * Now go hang yourself.
  */
 
+#include "opt_kern_tls.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/ktls.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
@@ -81,6 +85,7 @@ __FBSDID("$FreeBSD$");
 #include <rpc/rpc.h>
 #include <rpc/rpc_com.h>
 #include <rpc/krpc.h>
+#include <rpc/rpcsec_tls.h>
 
 struct cmessage {
         struct cmsghdr cmsg;
@@ -97,6 +102,7 @@ static void clnt_vc_close(CLIENT *);
 static void clnt_vc_destroy(CLIENT *);
 static bool_t time_not_ok(struct timeval *);
 static int clnt_vc_soupcall(struct socket *so, void *arg, int waitflag);
+static void clnt_vc_dotlsupcall(void *data);
 
 static struct clnt_ops clnt_vc_ops = {
 	.cl_call =	clnt_vc_call,
@@ -154,6 +160,7 @@ clnt_vc_create(
 	ct->ct_closing = FALSE;
 	ct->ct_closed = FALSE;
 	ct->ct_upcallrefs = 0;
+	ct->ct_rcvstate = RPCRCVSTATE_NORMAL;
 
 	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
 		error = soconnect(so, raddr, curthread);
@@ -272,6 +279,7 @@ clnt_vc_create(
 	ct->ct_raw = NULL;
 	ct->ct_record = NULL;
 	ct->ct_record_resid = 0;
+	ct->ct_sslrefno = 0;
 	TAILQ_INIT(&ct->ct_pending);
 	return (cl);
 
@@ -304,7 +312,10 @@ clnt_vc_call(
 	uint32_t xid;
 	struct mbuf *mreq = NULL, *results;
 	struct ct_request *cr;
-	int error, trycnt;
+	int error, maxextsiz, trycnt;
+#ifdef KERN_TLS
+	u_int maxlen;
+#endif
 
 	cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
 
@@ -407,9 +418,27 @@ call_again:
 		stat = RPC_CANTRECV;
 		goto out;
 	}
+
+	/* For TLS, wait for an upcall to be done, as required. */
+	while ((ct->ct_rcvstate & (RPCRCVSTATE_NORMAL |
+	    RPCRCVSTATE_NONAPPDATA)) == 0)
+		msleep(&ct->ct_rcvstate, &ct->ct_lock, 0, "rpcrcvst", hz);
+
 	TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link);
 	mtx_unlock(&ct->ct_lock);
 
+	if (ct->ct_sslrefno != 0) {
+		/*
+		 * Copy the mbuf chain to a chain of ext_pgs mbuf(s)
+		 * as required by KERN_TLS.
+		 */
+		maxextsiz = TLS_MAX_MSG_SIZE_V10_2;
+#ifdef KERN_TLS
+		if (rpctls_getinfo(&maxlen, false, false))
+			maxextsiz = min(maxextsiz, maxlen);
+#endif
+		mreq = _rpc_copym_into_ext_pgs(mreq, maxextsiz);
+	}
 	/*
 	 * sosend consumes mreq.
 	 */
@@ -615,6 +644,9 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
 	struct ct_data *ct = (struct ct_data *)cl->cl_private;
 	void *infop = info;
 	SVCXPRT *xprt;
+	uint64_t *p;
+	int error;
+	static u_int thrdnum = 0;
 
 	mtx_lock(&ct->ct_lock);
 
@@ -730,10 +762,38 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
 		xprt = (SVCXPRT *)info;
 		if (ct->ct_backchannelxprt == NULL) {
 			xprt->xp_p2 = ct;
+			if (ct->ct_sslrefno != 0)
+				xprt->xp_tls = RPCTLS_FLAGS_HANDSHAKE;
 			ct->ct_backchannelxprt = xprt;
 		}
 		break;
 
+	case CLSET_TLS:
+		p = (uint64_t *)info;
+		ct->ct_sslsec = *p++;
+		ct->ct_sslusec = *p++;
+		ct->ct_sslrefno = *p;
+		if (ct->ct_sslrefno != RPCTLS_REFNO_HANDSHAKE) {
+			mtx_unlock(&ct->ct_lock);
+			/* Start the kthread that handles upcalls. */
+			error = kthread_add(clnt_vc_dotlsupcall, ct,
+			    NULL, NULL, 0, 0, "krpctls%u", thrdnum++);
+			if (error != 0)
+				panic("Can't add KRPC thread error %d", error);
+		} else
+			mtx_unlock(&ct->ct_lock);
+		return (TRUE);
+
+	case CLSET_BLOCKRCV:
+		if (*(int *) info) {
+			ct->ct_rcvstate &= ~RPCRCVSTATE_NORMAL;
+			ct->ct_rcvstate |= RPCRCVSTATE_TLSHANDSHAKE;
+		} else {
+			ct->ct_rcvstate &= ~RPCRCVSTATE_TLSHANDSHAKE;
+			ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
+		}
+		break;
+
 	default:
 		mtx_unlock(&ct->ct_lock);
 		return (FALSE);
@@ -769,8 +829,10 @@ clnt_vc_close(CLIENT *cl)
 		mtx_unlock(&ct->ct_lock);
 
 		SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
-		soupcall_clear(ct->ct_socket, SO_RCV);
-		clnt_vc_upcallsdone(ct);
+		if (ct->ct_socket->so_rcv.sb_upcall != NULL) {
+			soupcall_clear(ct->ct_socket, SO_RCV);
+			clnt_vc_upcallsdone(ct);
+		}
 		SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
 
 		/*
@@ -790,6 +852,7 @@ clnt_vc_close(CLIENT *cl)
 
 	ct->ct_closing = FALSE;
 	ct->ct_closed = TRUE;
+	wakeup(&ct->ct_sslrefno);
 	mtx_unlock(&ct->ct_lock);
 	wakeup(ct);
 }
@@ -800,6 +863,8 @@ clnt_vc_destroy(CLIENT *cl)
 	struct ct_data *ct = (struct ct_data *) cl->cl_private;
 	struct socket *so = NULL;
 	SVCXPRT *xprt;
+	enum clnt_stat stat;
+	uint32_t reterr;
 
 	clnt_vc_close(cl);
 
@@ -820,12 +885,40 @@ clnt_vc_destroy(CLIENT *cl)
 		}
 	}
 
+	/* Wait for the upcall kthread to terminate. */
+	while ((ct->ct_rcvstate & RPCRCVSTATE_UPCALLTHREAD) != 0)
+		msleep(&ct->ct_sslrefno, &ct->ct_lock, 0,
+		    "clntvccl", hz);
 	mtx_unlock(&ct->ct_lock);
 
 	mtx_destroy(&ct->ct_lock);
 	if (so) {
-		soshutdown(so, SHUT_WR);
-		soclose(so);
+		if (ct->ct_sslrefno != 0) {
+			/*
+			 * If the TLS handshake is in progress, the upcall
+			 * will fail, but the socket should be closed by the
+			 * daemon, since the connect upcall has just failed.
+			 */
+			if (ct->ct_sslrefno != RPCTLS_REFNO_HANDSHAKE) {
+				/*
+				 * If the upcall fails, the socket has
+				 * probably been closed via the rpctlscd
+				 * daemon having crashed or been
+				 * restarted, so ignore return stat.
+				 */
+				stat = rpctls_cl_disconnect(ct->ct_sslsec,
+				    ct->ct_sslusec, ct->ct_sslrefno,
+				    &reterr);
+			}
+			/* Must sorele() to get rid of reference. */
+			CURVNET_SET(so->so_vnet);
+			SOCK_LOCK(so);
+			sorele(so);
+			CURVNET_RESTORE();
+		} else {
+			soshutdown(so, SHUT_WR);
+			soclose(so);
+		}
 	}
 	m_freem(ct->ct_record);
 	m_freem(ct->ct_raw);
@@ -853,15 +946,34 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 {
 	struct ct_data *ct = (struct ct_data *) arg;
 	struct uio uio;
-	struct mbuf *m, *m2;
+	struct mbuf *m, *m2, **ctrlp;
 	struct ct_request *cr;
 	int error, rcvflag, foundreq;
 	uint32_t xid_plus_direction[2], header;
 	SVCXPRT *xprt;
 	struct cf_conn *cd;
 	u_int rawlen;
+	struct cmsghdr *cmsg;
+	struct tls_get_record tgr;
 
 	/*
+	 * RPC-over-TLS needs to block reception during
+	 * upcalls since the upcall will be doing I/O on
+	 * the socket via openssl library calls.
+	 */
+	mtx_lock(&ct->ct_lock);
+	if ((ct->ct_rcvstate & (RPCRCVSTATE_NORMAL |
+	    RPCRCVSTATE_NONAPPDATA)) == 0) {
+		/* Mark that a socket upcall needs to be done. */
+		if ((ct->ct_rcvstate & (RPCRCVSTATE_UPCALLNEEDED |
+		    RPCRCVSTATE_UPCALLINPROG)) != 0)
+			ct->ct_rcvstate |= RPCRCVSTATE_SOUPCALLNEEDED;
+		mtx_unlock(&ct->ct_lock);
+		return (SU_OK);
+	}
+	mtx_unlock(&ct->ct_lock);
+
+	/*
 	 * If another thread is already here, it must be in
 	 * soreceive(), so just return to avoid races with it.
 	 * ct_upcallrefs is protected by the SOCKBUF_LOCK(),
@@ -881,8 +993,14 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 		uio.uio_td = curthread;
 		m2 = m = NULL;
 		rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
+		if (ct->ct_sslrefno != 0 && (ct->ct_rcvstate &
+		    RPCRCVSTATE_NORMAL) != 0) {
+			rcvflag |= MSG_TLSAPPDATA;
+			ctrlp = NULL;
+		} else
+			ctrlp = &m2;
 		SOCKBUF_UNLOCK(&so->so_rcv);
-		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
+		error = soreceive(so, NULL, &uio, &m, ctrlp, &rcvflag);
 		SOCKBUF_LOCK(&so->so_rcv);
 
 		if (error == EWOULDBLOCK) {
@@ -905,9 +1023,55 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 			 */
 			error = ECONNRESET;
 		}
+
+		/*
+		 * A return of ENXIO indicates that there is a
+		 * non-application data record at the head of the
+		 * socket's receive queue, for TLS connections.
+		 * This record needs to be handled in userland
+		 * via an SSL_read() call, so do an upcall to the daemon.
+		 */
+		if (ct->ct_sslrefno != 0 && error == ENXIO) {
+			/* Disable reception, marking an upcall needed. */
+			mtx_lock(&ct->ct_lock);
+			ct->ct_rcvstate |= RPCRCVSTATE_UPCALLNEEDED;
+			/*
+			 * If an upcall in needed, wake up the kthread
+			 * that runs clnt_vc_dotlsupcall().
+			 */
+			wakeup(&ct->ct_sslrefno);
+			mtx_unlock(&ct->ct_lock);
+			break;
+		}
 		if (error != 0)
 			break;
 
+		/* Process any record header(s). */
+		if (m2 != NULL) {
+			cmsg = mtod(m2, struct cmsghdr *);
+			if (cmsg->cmsg_type == TLS_GET_RECORD &&
+			    cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) {
+				memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr));
+				/*
+				 * This should have been handled by
+				 * setting RPCRCVSTATE_UPCALLNEEDED in
+				 * ct_rcvstate but if not, all we can do
+				 * is toss it away.
+				 */
+				if (tgr.tls_type != TLS_RLTYPE_APP) {
+					m_freem(m);
+					m_free(m2);
+					mtx_lock(&ct->ct_lock);
+					ct->ct_rcvstate &=
+					    ~RPCRCVSTATE_NONAPPDATA;
+					ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
+					mtx_unlock(&ct->ct_lock);
+					continue;
+				}
+			}
+			m_free(m2);
+		}
+
 		if (ct->ct_raw != NULL)
 			m_last(ct->ct_raw)->m_next = m;
 		else
@@ -1108,4 +1272,51 @@ clnt_vc_upcallsdone(struct ct_data *ct)
 	while (ct->ct_upcallrefs > 0)
 		(void) msleep(&ct->ct_upcallrefs,
 		    SOCKBUF_MTX(&ct->ct_socket->so_rcv), 0, "rpcvcup", 0);
+}
+
+/*
+ * Do a TLS upcall to the rpctlscd daemon, as required.
+ * This function runs as a kthread.
+ */
+static void
+clnt_vc_dotlsupcall(void *data)
+{
+	struct ct_data *ct = (struct ct_data *)data;
+	enum clnt_stat ret;
+	uint32_t reterr;
+
+	mtx_lock(&ct->ct_lock);
+	ct->ct_rcvstate |= RPCRCVSTATE_UPCALLTHREAD;
+	while (!ct->ct_closed) {
+		if ((ct->ct_rcvstate & RPCRCVSTATE_UPCALLNEEDED) != 0) {
+			ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLNEEDED;
+			ct->ct_rcvstate |= RPCRCVSTATE_UPCALLINPROG;
+			if (ct->ct_sslrefno != 0 && ct->ct_sslrefno !=
+			    RPCTLS_REFNO_HANDSHAKE) {
+				mtx_unlock(&ct->ct_lock);
+				ret = rpctls_cl_handlerecord(ct->ct_sslsec,
+				    ct->ct_sslusec, ct->ct_sslrefno, &reterr);
+				mtx_lock(&ct->ct_lock);
+			}
+			ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLINPROG;
+			if (ret == RPC_SUCCESS && reterr == RPCTLSERR_OK)
+				ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
+			else
+				ct->ct_rcvstate |= RPCRCVSTATE_NONAPPDATA;
+			wakeup(&ct->ct_rcvstate);
+		}
+		if ((ct->ct_rcvstate & RPCRCVSTATE_SOUPCALLNEEDED) != 0) {
+			ct->ct_rcvstate &= ~RPCRCVSTATE_SOUPCALLNEEDED;
+			mtx_unlock(&ct->ct_lock);
+			SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
+			clnt_vc_soupcall(ct->ct_socket, ct, M_NOWAIT);
+			SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
+			mtx_lock(&ct->ct_lock);
+		}
+		msleep(&ct->ct_sslrefno, &ct->ct_lock, 0, "clntvcdu", hz);
+	}
+	ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLTHREAD;
+	wakeup(&ct->ct_sslrefno);
+	mtx_unlock(&ct->ct_lock);
+	kthread_exit();
 }

Modified: head/sys/rpc/krpc.h
==============================================================================
--- head/sys/rpc/krpc.h	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/krpc.h	Sat Aug 22 03:57:55 2020	(r364475)
@@ -42,6 +42,7 @@
 void clnt_bck_svccall(void *, struct mbuf *, uint32_t);
 enum clnt_stat clnt_bck_call(CLIENT *, struct rpc_callextra *, rpcproc_t,
     struct mbuf *, struct mbuf **, struct timeval, SVCXPRT *);
+struct mbuf *_rpc_copym_into_ext_pgs(struct mbuf *, int);
 
 /*
  * A pending RPC request which awaits a reply. Requests which have
@@ -78,8 +79,18 @@ struct rc_data {
 	CLIENT*			rc_client; /* underlying RPC client */
 	struct rpc_err		rc_err;
 	void			*rc_backchannel;
+	bool			rc_tls; /* Enable TLS on connection */
 };
 
+/* Bits for ct_rcvstate. */
+#define RPCRCVSTATE_NORMAL		0x01	/* Normal reception. */
+#define RPCRCVSTATE_NONAPPDATA		0x02	/* Reception of a non-application record. */
+#define RPCRCVSTATE_TLSHANDSHAKE	0x04	/* Reception blocked for TLS handshake. */
+#define RPCRCVSTATE_UPCALLNEEDED	0x08	/* Upcall to rpctlscd needed. */
+#define RPCRCVSTATE_UPCALLINPROG	0x10	/* Upcall to rpctlscd in progress. */
+#define RPCRCVSTATE_SOUPCALLNEEDED	0x20	/* Socket upcall needed. */
+#define RPCRCVSTATE_UPCALLTHREAD	0x40	/* Upcall kthread running. */
+
 struct ct_data {
 	struct mtx	ct_lock;
 	int		ct_threads;	/* number of threads in clnt_vc_call */
@@ -101,6 +112,10 @@ struct ct_data {
 	struct ct_request_list ct_pending;
 	int		ct_upcallrefs;	/* Ref cnt of upcalls in prog. */
 	SVCXPRT		*ct_backchannelxprt; /* xprt for backchannel */
+	uint64_t	ct_sslsec;	/* RPC-over-TLS connection. */
+	uint64_t	ct_sslusec;
+	uint64_t	ct_sslrefno;
+	uint32_t 	ct_rcvstate;	/* Handle receiving for TLS upcalls */
 	struct mbuf	*ct_raw;	/* Raw mbufs recv'd */
 };
 

Modified: head/sys/rpc/rpc_generic.c
==============================================================================
--- head/sys/rpc/rpc_generic.c	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/rpc_generic.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -62,9 +62,15 @@ __FBSDID("$FreeBSD$");
 #include <rpc/rpc.h>
 #include <rpc/nettype.h>
 #include <rpc/rpcsec_gss.h>
+#include <rpc/rpcsec_tls.h>
 
 #include <rpc/rpc_com.h>
+#include <rpc/krpc.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_param.h>
+
 extern	u_long sb_max_adj;	/* not defined in socketvar.h */
 
 /* Provide an entry point hook for the rpcsec_gss module. */
@@ -865,13 +871,115 @@ out:
 }
 
 /*
+ * Make sure an mbuf list is made up entirely of ext_pgs mbufs.
+ * This is needed for sosend() when KERN_TLS is being used.
+ * (There might also be a performance improvement for certain
+ *  network interfaces that handle ext_pgs mbufs efficiently.)
+ * It expects at least one non-ext_pgs mbuf followed by zero
+ * or more ext_pgs mbufs.  It does not handle the case where
+ * non-ext_pgs mbuf(s) follow ext_pgs ones.
+ * It also performs sanity checks on the resultant list.
+ * The "mp" argument list is consumed.
+ * The "maxextsiz" argument is the upper bound on the data
+ * size for each mbuf (usually 16K for KERN_TLS).
+ */
+struct mbuf *
+_rpc_copym_into_ext_pgs(struct mbuf *mp, int maxextsiz)
+{
+	struct mbuf *m, *m2, *m3, *mhead;
+	int tlen;
+
+	KASSERT((mp->m_flags & (M_EXT | M_EXTPG)) !=
+	    (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
+	    " first mbuf is an ext_pgs"));
+	/*
+	 * Find the last non-ext_pgs mbuf and the total
+	 * length of the non-ext_pgs mbuf(s).
+	 * The first mbuf must always be a non-ext_pgs
+	 * mbuf.
+	 */
+	tlen = mp->m_len;
+	m2 = mp;
+	for (m = mp->m_next; m != NULL; m = m->m_next) {
+		if ((m->m_flags & M_EXTPG) != 0)
+			break;
+		tlen += m->m_len;
+		m2 = m;
+	}
+
+	/*
+	 * Copy the non-ext_pgs mbuf(s) into an ext_pgs
+	 * mbuf list.
+	 */
+	m2->m_next = NULL;
+	mhead = mb_mapped_to_unmapped(mp, tlen, maxextsiz,
+	    M_WAITOK, &m2);
+
+	/*
+	 * Link the ext_pgs list onto the newly copied
+	 * list and free up the non-ext_pgs mbuf(s).
+	 */
+	m2->m_next = m;
+	m_freem(mp);
+
+	/*
+	 * Sanity check the resultant mbuf list.  Check for and
+	 * remove any 0 length mbufs in the list, since the
+	 * KERN_TLS code does not expect any 0 length mbuf(s)
+	 * in the list.
+	 */
+	m3 = NULL;
+	m2 = mhead;
+	tlen = 0;
+	while (m2 != NULL) {
+		KASSERT(m2->m_len >= 0, ("_rpc_copym_into_ext_pgs:"
+		    " negative m_len"));
+		KASSERT((m2->m_flags & (M_EXT | M_EXTPG)) ==
+		    (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
+			    " non-nomap mbuf in list"));
+		if (m2->m_len == 0) {
+			if (m3 != NULL)
+				m3->m_next = m2->m_next;
+			else
+				m = m2->m_next;
+			m2->m_next = NULL;
+			m_free(m2);
+			if (m3 != NULL)
+				m2 = m3->m_next;
+			else
+				m2 = m;
+		} else {
+			MBUF_EXT_PGS_ASSERT_SANITY(m2);
+			m3 = m2;
+			tlen += m2->m_len;
+			m2 = m2->m_next;
+		}
+	}
+	return (mhead);
+}
+
+/*
  * Kernel module glue
  */
 static int
 krpc_modevent(module_t mod, int type, void *data)
 {
+	int error = 0;
 
-	return (0);
+	switch (type) {
+	case MOD_LOAD:
+		error = rpctls_init();
+		break;
+	case MOD_UNLOAD:
+		/*
+		 * Cannot be unloaded, since the rpctlssd or rpctlscd daemons
+		 * might be performing a rpctls syscall.
+		 */
+		/* FALLTHROUGH */
+	default:
+		error = EOPNOTSUPP;
+	}
+	return (error);
 }
 static moduledata_t krpc_mod = {
 	"krpc",

Modified: head/sys/rpc/rpcsec_tls.h
==============================================================================
--- head/sys/rpc/rpcsec_tls.h	Sat Aug 22 01:10:59 2020	(r364474)
+++ head/sys/rpc/rpcsec_tls.h	Sat Aug 22 03:57:55 2020	(r364475)
@@ -48,6 +48,7 @@ int	rpctls_syscall(int, const char *);
 #define	RPCTLS_FLAGS_VERIFIED	0x08
 #define	RPCTLS_FLAGS_DISABLED	0x10
 #define	RPCTLS_FLAGS_CERTUSER	0x20
+#define	RPCTLS_FLAGS_HANDSHFAIL	0x40
 
 /* Error return values for upcall rpcs. */
 #define	RPCTLSERR_OK		0
@@ -72,10 +73,14 @@ enum clnt_stat	rpctls_srv_disconnect(uint64_t sec, uin
 int		rpctls_init(void);
 
 /* Get TLS information function. */
-bool		rpctls_getinfo(u_int *maxlen);
+bool		rpctls_getinfo(u_int *maxlen, bool rpctlscd_run,
+		    bool rpctlssd_run);
 
 /* String for AUTH_TLS reply verifier. */
 #define	RPCTLS_START_STRING	"STARTTLS"
+
+/* ssl refno value to indicate TLS handshake being done. */
+#define	RPCTLS_REFNO_HANDSHAKE	0xFFFFFFFFFFFFFFFFULL
 
 #endif	/* _KERNEL */
 

Added: head/sys/rpc/rpcsec_tls/auth_tls.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/rpc/rpcsec_tls/auth_tls.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -0,0 +1,169 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Modified from auth_none.c to expect a reply verifier of "STARTTLS"
+ * for the RPC-over-TLS STARTTLS command.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <rpc/rpcsec_tls.h>
+
+#define MAX_MARSHAL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+
+static bool_t authtls_marshal (AUTH *, uint32_t, XDR *, struct mbuf *);
+static void authtls_verf (AUTH *);
+static bool_t authtls_validate (AUTH *, uint32_t, struct opaque_auth *,
+    struct mbuf **);
+static bool_t authtls_refresh (AUTH *, void *);
+static void authtls_destroy (AUTH *);
+
+static struct auth_ops authtls_ops = {
+	.ah_nextverf =		authtls_verf,
+	.ah_marshal =		authtls_marshal,
+	.ah_validate =		authtls_validate,
+	.ah_refresh =		authtls_refresh,
+	.ah_destroy =		authtls_destroy,
+};
+
+struct authtls_private {
+	AUTH	no_client;
+	char	mclient[MAX_MARSHAL_SIZE];
+	u_int	mcnt;
+};
+
+static struct authtls_private authtls_private;
+static struct opaque_auth _tls_null_auth;
+
+static void
+authtls_init(void *dummy)
+{
+	struct authtls_private *ap = &authtls_private;
+	XDR xdrs;
+
+	_tls_null_auth.oa_flavor = AUTH_TLS;
+	_tls_null_auth.oa_base = NULL;
+	_tls_null_auth.oa_length = 0;
+	ap->no_client.ah_cred = _tls_null_auth;
+	ap->no_client.ah_verf = _null_auth;
+	ap->no_client.ah_ops = &authtls_ops;
+	xdrmem_create(&xdrs, ap->mclient, MAX_MARSHAL_SIZE, XDR_ENCODE);
+	xdr_opaque_auth(&xdrs, &ap->no_client.ah_cred);
+	xdr_opaque_auth(&xdrs, &ap->no_client.ah_verf);
+	ap->mcnt = XDR_GETPOS(&xdrs);
+	XDR_DESTROY(&xdrs);
+}
+SYSINIT(authtls_init, SI_SUB_KMEM, SI_ORDER_ANY, authtls_init, NULL);
+
+AUTH *
+authtls_create(void)
+{
+	struct authtls_private *ap = &authtls_private;
+
+	return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authtls_marshal(AUTH *client, uint32_t xid, XDR *xdrs, struct mbuf *args)
+{
+	struct authtls_private *ap = &authtls_private;
+
+	KASSERT(xdrs != NULL, ("authtls_marshal: xdrs is null"));
+
+	if (!XDR_PUTBYTES(xdrs, ap->mclient, ap->mcnt))
+		return (FALSE);
+
+	xdrmbuf_append(xdrs, args);
+
+	return (TRUE);
+}
+
+/* All these unused parameters are required to keep ANSI-C from grumbling */
+/*ARGSUSED*/
+static void
+authtls_verf(AUTH *client)
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+authtls_validate(AUTH *client, uint32_t xid, struct opaque_auth *opaque,
+    struct mbuf **mrepp)
+{
+	size_t strsiz;
+
+	strsiz = strlen(RPCTLS_START_STRING);
+	/* The verifier must be the string RPCTLS_START_STRING. */
+	if (opaque != NULL &&
+	    (opaque->oa_length != strsiz || memcmp(opaque->oa_base,
+	     RPCTLS_START_STRING, strsiz) != 0))
+		return (FALSE);
+	return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+authtls_refresh(AUTH *client, void *dummy)
+{
+
+	return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+authtls_destroy(AUTH *client)
+{
+}

Added: head/sys/rpc/rpcsec_tls/rpctls_impl.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/rpc/rpcsec_tls/rpctls_impl.c	Sat Aug 22 03:57:55 2020	(r364475)
@@ -0,0 +1,727 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list