Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Jul 2020 02:11:16 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r362820 - projects/nfs-over-tls/sys/rpc
Message-ID:  <202007010211.0612BG0u098822@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Wed Jul  1 02:11:15 2020
New Revision: 362820
URL: https://svnweb.freebsd.org/changeset/base/362820

Log:
  Use a reserved value for ssl refno to indicate that a handshake is in progress.
  
  This is needed so clnt_vc_destroy() will not do a soclose() on the socket,
  since the daemon may still be in SSL_connect().

Modified:
  projects/nfs-over-tls/sys/rpc/clnt_rc.c
  projects/nfs-over-tls/sys/rpc/clnt_vc.c
  projects/nfs-over-tls/sys/rpc/rpcsec_tls.h

Modified: projects/nfs-over-tls/sys/rpc/clnt_rc.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/clnt_rc.c	Wed Jul  1 01:12:23 2020	(r362819)
+++ projects/nfs-over-tls/sys/rpc/clnt_rc.c	Wed Jul  1 02:11:15 2020	(r362820)
@@ -198,6 +198,16 @@ clnt_reconnect_connect(CLIENT *cl)
 		    (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) {
+			/*
+			 * Set ssl refno so that clnt_vc_destroy() will not
+			 * close the socket and will leave that for the
+			 * daemon to do.  It is possible that the upcall
+			 * will time out, so that closing the socket via
+			 * the CLNT_CLOSE() below would happen too soon.
+			 */
+			ssl[0] = ssl[1] = 0;
+			ssl[2] = RPCTLS_REFNO_HANDSHAKE;
+			CLNT_CONTROL(newclient, CLSET_TLS, ssl);
 printf("at rpctls_connect\n");
 			stat = rpctls_connect(newclient, so, ssl, &reterr);
 printf("aft rpctls_connect=%d ssl=%jd\n", stat, (uintmax_t)ssl[2]);

Modified: projects/nfs-over-tls/sys/rpc/clnt_vc.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/clnt_vc.c	Wed Jul  1 01:12:23 2020	(r362819)
+++ projects/nfs-over-tls/sys/rpc/clnt_vc.c	Wed Jul  1 02:11:15 2020	(r362820)
@@ -775,12 +775,15 @@ printf("backch tls=0x%x xprt=%p\n", xprt->xp_tls, xprt
 		ct->ct_sslsec = *p++;
 		ct->ct_sslusec = *p++;
 		ct->ct_sslrefno = *p;
-		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);
+		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:
@@ -892,24 +895,22 @@ clnt_vc_destroy(CLIENT *cl)
 	if (so) {
 		if (ct->ct_sslrefno != 0) {
 			/*
-			 * If the upcall fails, the socket has
-			 * probably been closed via the rpctlscd
-			 * daemon having crashed or been
-			 * restarted, so ignore return stat.
+			 * 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.
 			 */
-			stat = rpctls_cl_disconnect(ct->ct_sslsec,
-			    ct->ct_sslusec, ct->ct_sslrefno,
-			    &reterr);
-		} else if ((ct->ct_rcvstate & RPCRCVSTATE_TLSHANDSHAKE) == 0) {
-			/*
-			 * If the TLS handshake is in progress, leave the
-			 * socket so that it will closed by the daemon.
-			 * This can only occur if the daemon is waiting for
-			 * an openssl call like SSL_connect() for a long
-			 * time.  The call will normally eventually fail and
-			 * then the daemon will close the socket, so do not
-			 * do it here.
-			 */
+			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);
+			}
+		} else {
 			soshutdown(so, SHUT_WR);
 			soclose(so);
 		}
@@ -1293,7 +1294,8 @@ clnt_vc_dotlsupcall(void *data)
 		if ((ct->ct_rcvstate & RPCRCVSTATE_UPCALLNEEDED) != 0) {
 			ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLNEEDED;
 			ct->ct_rcvstate |= RPCRCVSTATE_UPCALLINPROG;
-			if (ct->ct_sslrefno != 0) {
+			if (ct->ct_sslrefno != 0 && ct->ct_sslrefno !=
+			    RPCTLS_REFNO_HANDSHAKE) {
 				mtx_unlock(&ct->ct_lock);
 printf("at handlerecord\n");
 				ret = rpctls_cl_handlerecord(ct->ct_sslsec,

Modified: projects/nfs-over-tls/sys/rpc/rpcsec_tls.h
==============================================================================
--- projects/nfs-over-tls/sys/rpc/rpcsec_tls.h	Wed Jul  1 01:12:23 2020	(r362819)
+++ projects/nfs-over-tls/sys/rpc/rpcsec_tls.h	Wed Jul  1 02:11:15 2020	(r362820)
@@ -78,6 +78,9 @@ bool		rpctls_getinfo(u_int *maxlen, bool rpctlscd_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 */
 
 #endif	/* _RPC_RPCSEC_TLS_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007010211.0612BG0u098822>