From owner-svn-src-projects@freebsd.org Wed Sep 16 22:42:28 2020 Return-Path: Delivered-To: svn-src-projects@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 257BD3F3DC5 for ; Wed, 16 Sep 2020 22:42:28 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsFTw0D7bz4P4P; Wed, 16 Sep 2020 22:42:28 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id DF60C20A03; Wed, 16 Sep 2020 22:42:27 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08GMgRk0076598; Wed, 16 Sep 2020 22:42:27 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08GMgRQW076597; Wed, 16 Sep 2020 22:42:27 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009162242.08GMgRQW076597@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 16 Sep 2020 22:42:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365818 - projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Commit-Revision: 365818 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Sep 2020 22:42:28 -0000 Author: rmacklem Date: Wed Sep 16 22:42:27 2020 New Revision: 365818 URL: https://svnweb.freebsd.org/changeset/base/365818 Log: Add support to the rpc.tlsservd daemon for shutting down connections that were verified with no longer valid certificates. When SIGHUP is posted to rpc.tlsservd, the CRL file is reloaded if one was specified when the daemon was started. This patch adds code that also scans the extant connections after a reload and, for any that presented a certificate that is no longer valid, shuts the connection down. This required the code to be changed so that the reload would happen right away, instead of waiting until the next TLS handshake. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Wed Sep 16 22:37:44 2020 (r365817) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Wed Sep 16 22:42:27 2020 (r365818) @@ -78,6 +78,12 @@ __FBSDID("$FreeBSD$"); #define _PREFERRED_CIPHERS "AES128-GCM-SHA256" #endif +/* + * How long to delay a reload of the CRL when there are RPC request(s) + * to process, in usec. Must be less than 1second. + */ +#define RELOADDELAY 250000 + static struct pidfh *rpctls_pfh = NULL; static int rpctls_debug_level; static bool rpctls_verbose; @@ -108,7 +114,9 @@ struct ssl_entry { LIST_ENTRY(ssl_entry) next; uint64_t refno; int s; + bool shutoff; SSL *ssl; + X509 *cert; }; static struct ssl_list rpctls_ssllist; @@ -116,7 +124,7 @@ static void rpctlssd_terminate(int); static SSL_CTX *rpctls_setup_ssl(const char *certdir); static SSL *rpctls_server(SSL_CTX *ctx, int s, uint32_t *flags, uint32_t *uidp, - int *ngrps, uint32_t *gidp); + int *ngrps, uint32_t *gidp, X509 **certp); static int rpctls_gethost(int s, struct sockaddr *sad, char *hostip, size_t hostlen); static int rpctls_checkhost(struct sockaddr *sad, X509 *cert); @@ -125,6 +133,8 @@ static int rpctls_cnname(X509 *cert, uint32_t *uidp, int *ngrps, uint32_t *gidp); static char *rpctls_getdnsname(char *dnsname); static void rpctls_huphandler(int sig __unused); +static void rpctls_checkcrl(void); +static void rpctlssd_verbose_out(const char *fmt, ...); extern void rpctlssd_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -153,12 +163,16 @@ main(int argc, char **argv) * TLS handshake. */ struct sockaddr_un sun; - int fd, oldmask, ch, debug; + int ch, debug, fd, oldmask, ret; SVCXPRT *xprt; struct timeval tm; struct timezone tz; char hostname[MAXHOSTNAMELEN + 2]; pid_t otherpid; + fd_set readfds; + uint64_t curtime, nexttime; + struct timespec tp; + sigset_t sighup_mask; /* Check that another rpctlssd isn't already running. */ rpctls_pfh = pidfile_open(_PATH_RPCTLSSDPID, 0600, &otherpid); @@ -347,7 +361,62 @@ fprintf(stderr, "dnsname=%s\n", rpctls_dnsname); LIST_INIT(&rpctls_ssllist); rpctls_syscall(RPCTLS_SYSC_SRVSETPATH, _PATH_RPCTLSSDSOCK); - svc_run(); + + /* Expand svc_run() here so that we can call rpctls_loadcrlfile(). */ + curtime = nexttime = 0; + sigemptyset(&sighup_mask); + sigaddset(&sighup_mask, SIGHUP); + for (;;) { + clock_gettime(CLOCK_MONOTONIC, &tp); + curtime = tp.tv_sec; + curtime = curtime * 1000000 + tp.tv_nsec / 1000; + sigprocmask(SIG_BLOCK, &sighup_mask, NULL); + if (rpctls_gothup && curtime >= nexttime) { + rpctls_gothup = false; + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + ret = rpctls_loadcrlfile(rpctls_ctx); + if (ret != 0) + rpctls_checkcrl(); + else + rpctlssd_verbose_out("rpc.tlsservd: Can't " + "reload CRLfile\n"); + clock_gettime(CLOCK_MONOTONIC, &tp); + nexttime = tp.tv_sec; + nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 + + RELOADDELAY; + } else + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + + /* + * If a reload is pending, poll for received request(s), + * otherwise set a RELOADDELAY timeout, since a SIGHUP + * could be processed between the got_sighup test and + * the select() system call. + */ + tm.tv_sec = 0; + if (rpctls_gothup) + tm.tv_usec = 0; + else + tm.tv_usec = RELOADDELAY; + readfds = svc_fdset; + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tm)) { + case -1: + if (errno == EINTR) { + /* Allow a reload now. */ + nexttime = 0; + continue; + } + syslog(LOG_ERR, "rpc.tlsservd died: select: %m"); + exit(1); + case 0: + /* Allow a reload now. */ + nexttime = 0; + continue; + default: + svc_getreqset(&readfds); + } + } + rpctls_syscall(RPCTLS_SYSC_SRVSHUTDOWN, ""); SSL_CTX_free(rpctls_ctx); @@ -388,6 +457,7 @@ rpctlssd_connect_1_svc(void *argp, struct ssl_entry *newslp; uint32_t uid; uint32_t *gidp; + X509 *cert; rpctlssd_verbose_out("rpctlsd_connect_svc: started\n"); memset(result, 0, sizeof(*result)); @@ -399,7 +469,7 @@ rpctlssd_verbose_out("rpctlsd_connect_svc s=%d\n", s); /* Do the server side of a TLS handshake. */ gidp = calloc(NGROUPS, sizeof(*gidp)); - ssl = rpctls_server(rpctls_ctx, s, &flags, &uid, &ngrps, gidp); + ssl = rpctls_server(rpctls_ctx, s, &flags, &uid, &ngrps, gidp, &cert); if (ssl == NULL) { free(gidp); rpctlssd_verbose_out("rpctlssd_connect_svc: ssl " @@ -435,7 +505,9 @@ rpctlssd_verbose_out("rpctlsd_connect_svc s=%d\n", s); newslp = malloc(sizeof(*newslp)); newslp->ssl = ssl; newslp->s = s; + newslp->shutoff = false; newslp->refno = rpctls_ssl_refno; + newslp->cert = cert; LIST_INSERT_HEAD(&rpctls_ssllist, newslp, next); return (TRUE); } @@ -504,21 +576,25 @@ rpctlssd_disconnect_1_svc(struct rpctlssd_disconnect_a rpctlssd_verbose_out("rpctlssd_disconnect fd=%d closed\n", slp->s); LIST_REMOVE(slp, next); - ret = SSL_get_shutdown(slp->ssl); + if (!slp->shutoff) { + ret = SSL_get_shutdown(slp->ssl); rpctlssd_verbose_out("get_shutdown1=%d\n", ret); - /* - * Do an SSL_shutdown() unless a close alert has - * already been sent. - */ - if ((ret & SSL_SENT_SHUTDOWN) == 0) - SSL_shutdown(slp->ssl); + /* + * Do an SSL_shutdown() unless a close alert has + * already been sent. + */ + if ((ret & SSL_SENT_SHUTDOWN) == 0) + SSL_shutdown(slp->ssl); + } SSL_free(slp->ssl); /* * For RPC-over-TLS, this upcall is expected * to close off the socket. */ - shutdown(slp->s, SHUT_WR); + if (!slp->shutoff) + shutdown(slp->s, SHUT_WR); close(slp->s); + free(slp->cert); free(slp); result->reterr = RPCTLSERR_OK; } else @@ -547,10 +623,6 @@ rpctlssd_terminate(int sig __unused) rpctls_syscall(RPCTLS_SYSC_SRVSHUTDOWN, ""); pidfile_remove(rpctls_pfh); - /* - * Shut down all TCP connections, so that any compromised TLS - * connection is no longer usable. - */ LIST_FOREACH(slp, &rpctls_ssllist, next) shutdown(slp->s, SHUT_RD); exit(0); @@ -665,7 +737,7 @@ rpctls_setup_ssl(const char *certdir) static SSL * rpctls_server(SSL_CTX *ctx, int s, uint32_t *flags, uint32_t *uidp, - int *ngrps, uint32_t *gidp) + int *ngrps, uint32_t *gidp, X509 **certp) { SSL *ssl; X509 *cert; @@ -676,14 +748,8 @@ rpctls_server(SSL_CTX *ctx, int s, uint32_t *flags, ui char *cp, *cp2; *flags = 0; + *certp = NULL; sad = (struct sockaddr *)&ad; - if (rpctls_gothup) { - rpctls_gothup = false; - ret = rpctls_loadcrlfile(ctx); - if (ret == 0) - rpctlssd_verbose_out("rpctls_server: Can't " - "reload CRLfile\n"); - } ssl = SSL_new(ctx); if (ssl == NULL) { rpctlssd_verbose_out("rpctls_server: SSL_new failed\n"); @@ -758,8 +824,11 @@ rpctlssd_verbose_out("%s\n", cp2); *flags |= RPCTLS_FLAGS_CERTUSER; } *flags |= RPCTLS_FLAGS_VERIFIED; + *certp = cert; + cert = NULL; } - X509_free(cert); + if (cert != NULL) + X509_free(cert); } else rpctlssd_verbose_out("rpctls_server: " "No peer certificate\n"); @@ -991,3 +1060,52 @@ rpctls_huphandler(int sig __unused) rpctls_gothup = true; } +/* + * Read the CRL file and check for any extant connections + * that might now be revoked. + */ +static void +rpctls_checkcrl(void) +{ + struct ssl_entry *slp; + BIO *infile; + X509_CRL *crl; + X509_REVOKED *revoked; + int ret; + + infile = BIO_new(BIO_s_file()); + if (infile == NULL) { + rpctlssd_verbose_out("rpctls_checkcrl: Cannot BIO_new\n"); + return; + } + ret = BIO_read_filename(infile, rpctls_crlfile); + if (ret != 1) { + rpctlssd_verbose_out("rpctls_checkcrl: Cannot read CRL file\n"); + BIO_free(infile); + return; + } + + for (crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, ""); + crl != NULL; crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, "")) { + LIST_FOREACH(slp, &rpctls_ssllist, next) { + if (slp->cert != NULL) { + ret = X509_CRL_get0_by_cert(crl, &revoked, + slp->cert); +rpctlssd_verbose_out("get0_by_cert=%d\n", ret); + /* + * Do a shutdown on the socket, so that it + * can no longer be used. The kernel RPC + * code will notice the socket is disabled + * and will do a disconnect upcall, which will + * close the socket. + */ + if (ret == 1) { + shutdown(slp->s, SHUT_WR); + slp->shutoff = true; + } + } + } + X509_CRL_free(crl); + } + BIO_free(infile); +} From owner-svn-src-projects@freebsd.org Wed Sep 16 23:30:57 2020 Return-Path: Delivered-To: svn-src-projects@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 CFBCF3F4CDB for ; Wed, 16 Sep 2020 23:30:57 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsGYs56tcz4RYc; Wed, 16 Sep 2020 23:30:57 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 88078209ED; Wed, 16 Sep 2020 23:30:57 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08GNUvNh002693; Wed, 16 Sep 2020 23:30:57 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08GNUvYC002692; Wed, 16 Sep 2020 23:30:57 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009162330.08GNUvYC002692@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 16 Sep 2020 23:30:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365822 - projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Commit-Revision: 365822 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Sep 2020 23:30:57 -0000 Author: rmacklem Date: Wed Sep 16 23:30:57 2020 New Revision: 365822 URL: https://svnweb.freebsd.org/changeset/base/365822 Log: Add a check for the CRL file being used to rpctls_checkcrl(). Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Wed Sep 16 23:17:15 2020 (r365821) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Wed Sep 16 23:30:57 2020 (r365822) @@ -1073,6 +1073,9 @@ rpctls_checkcrl(void) X509_REVOKED *revoked; int ret; + if (rpctls_crlfile == NULL || (rpctls_verify_cafile == NULL && + rpctls_verify_capath == NULL)) + return; infile = BIO_new(BIO_s_file()); if (infile == NULL) { rpctlssd_verbose_out("rpctls_checkcrl: Cannot BIO_new\n"); From owner-svn-src-projects@freebsd.org Wed Sep 16 23:36:38 2020 Return-Path: Delivered-To: svn-src-projects@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 50EE93F5193 for ; Wed, 16 Sep 2020 23:36:38 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsGhQ12DKz4Rrl; Wed, 16 Sep 2020 23:36:38 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 06A0F21335; Wed, 16 Sep 2020 23:36:38 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08GNab2O007674; Wed, 16 Sep 2020 23:36:37 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08GNabTu007673; Wed, 16 Sep 2020 23:36:37 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009162336.08GNabTu007673@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 16 Sep 2020 23:36:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365823 - projects/nfs-over-tls/usr.sbin/rpc.tlsclntd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd X-SVN-Commit-Revision: 365823 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Sep 2020 23:36:38 -0000 Author: rmacklem Date: Wed Sep 16 23:36:37 2020 New Revision: 365823 URL: https://svnweb.freebsd.org/changeset/base/365823 Log: Add support for checking extant connections when the CRL is reloaded and shutting down any connections where the certificate has been revoked. This is probably a rare use of the client (usually it will not be checking the NFS server's certificate and maintaining a CRL in the client), but I cloned the code in rpc.tlsservd.c to do this the same way. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c Wed Sep 16 23:30:57 2020 (r365822) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c Wed Sep 16 23:36:37 2020 (r365823) @@ -77,6 +77,12 @@ __FBSDID("$FreeBSD$"); #define _PREFERRED_CIPHERS "AES128-GCM-SHA256" #endif +/* + * How long to delay a reload of the CRL when there are RPC request(s) + * to process, in usec. Must be less than 1second. + */ +#define RELOADDELAY 250000 + static struct pidfh *rpctls_pfh = NULL; static int rpctls_debug_level; static bool rpctls_verbose; @@ -101,18 +107,22 @@ struct ssl_entry { LIST_ENTRY(ssl_entry) next; uint64_t refno; int s; + bool shutoff; SSL *ssl; + X509 *cert; }; static struct ssl_list rpctls_ssllist; static void rpctlscd_terminate(int); static SSL_CTX *rpctls_setupcl_ssl(bool cert); -static SSL *rpctls_connect(SSL_CTX *ctx, int s); +static SSL *rpctls_connect(SSL_CTX *ctx, int s, X509 **certp); static int rpctls_gethost(int s, struct sockaddr *sad, char *hostip, size_t hostlen); static int rpctls_checkhost(struct sockaddr *sad, X509 *cert); static int rpctls_loadcrlfile(SSL_CTX *ctx); static void rpctls_huphandler(int sig __unused); +static void rpctls_checkcrl(void); +static void rpctlscd_verbose_out(const char *fmt, ...); extern void rpctlscd_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -136,12 +146,16 @@ main(int argc, char **argv) * TLS handshake. */ struct sockaddr_un sun; - int fd, oldmask, ch; + int ch, fd, oldmask, ret; SVCXPRT *xprt; bool cert; struct timeval tm; struct timezone tz; pid_t otherpid; + fd_set readfds; + uint64_t curtime, nexttime; + struct timespec tp; + sigset_t sighup_mask; /* Check that another rpctlscd isn't already running. */ rpctls_pfh = pidfile_open(_PATH_RPCTLSCDPID, 0600, &otherpid); @@ -290,7 +304,62 @@ main(int argc, char **argv) } rpctls_syscall(RPCTLS_SYSC_CLSETPATH, _PATH_RPCTLSCDSOCK); - svc_run(); + + /* Expand svc_run() here so that we can call rpctls_loadcrlfile(). */ + curtime = nexttime = 0; + sigemptyset(&sighup_mask); + sigaddset(&sighup_mask, SIGHUP); + for (;;) { + clock_gettime(CLOCK_MONOTONIC, &tp); + curtime = tp.tv_sec; + curtime = curtime * 1000000 + tp.tv_nsec / 1000; + sigprocmask(SIG_BLOCK, &sighup_mask, NULL); + if (rpctls_gothup && curtime >= nexttime) { + rpctls_gothup = false; + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + ret = rpctls_loadcrlfile(rpctls_ctx); + if (ret != 0) + rpctls_checkcrl(); + else + rpctlscd_verbose_out("rpc.tlsclntd: Can't " + "reload CRLfile\n"); + clock_gettime(CLOCK_MONOTONIC, &tp); + nexttime = tp.tv_sec; + nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 + + RELOADDELAY; + } else + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + + /* + * If a reload is pending, poll for received request(s), + * otherwise set a RELOADDELAY timeout, since a SIGHUP + * could be processed between the got_sighup test and + * the select() system call. + */ + tm.tv_sec = 0; + if (rpctls_gothup) + tm.tv_usec = 0; + else + tm.tv_usec = RELOADDELAY; + readfds = svc_fdset; + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tm)) { + case -1: + if (errno == EINTR) { + /* Allow a reload now. */ + nexttime = 0; + continue; + } + syslog(LOG_ERR, "rpc.tlsservd died: select: %m"); + exit(1); + case 0: + /* Allow a reload now. */ + nexttime = 0; + continue; + default: + svc_getreqset(&readfds); + } + } + rpctls_syscall(RPCTLS_SYSC_CLSHUTDOWN, ""); SSL_CTX_free(rpctls_ctx); @@ -331,6 +400,7 @@ rpctlscd_connect_1_svc(void *argp, char buf[1024]; ssize_t siz, ret; struct ssl_entry *newslp; + X509 *cert; rpctlscd_verbose_out("rpctlsd_connect: started\n"); /* Get the socket fd from the kernel. */ @@ -342,7 +412,7 @@ rpctlscd_verbose_out("rpctlsd_connect s=%d\n", s); } /* Do a TLS connect handshake. */ - ssl = rpctls_connect(rpctls_ctx, s); + ssl = rpctls_connect(rpctls_ctx, s, &cert); if (ssl == NULL) { rpctlscd_verbose_out("rpctlsd_connect: can't do TLS " "handshake\n"); @@ -370,7 +440,9 @@ rpctlscd_verbose_out("rpctlsd_connect s=%d\n", s); newslp = malloc(sizeof(*newslp)); newslp->refno = rpctls_ssl_refno; newslp->s = s; + newslp->shutoff = false; newslp->ssl = ssl; + newslp->cert = cert; LIST_INSERT_HEAD(&rpctls_ssllist, newslp, next); return (TRUE); } @@ -441,20 +513,25 @@ rpctlscd_verbose_out("disconnect refno=%jx\n", (uintma rpctlscd_verbose_out("rpctlscd_disconnect: fd=%d closed\n", slp->s); LIST_REMOVE(slp, next); - ret = SSL_get_shutdown(slp->ssl); + if (!slp->shutoff) { + ret = SSL_get_shutdown(slp->ssl); rpctlscd_verbose_out("get_shutdown0=%d\n", ret); - /* - * Do an SSL_shutdown() unless a close alert has - * already been sent. - */ - if ((ret & SSL_SENT_SHUTDOWN) == 0) - SSL_shutdown(slp->ssl); + /* + * Do an SSL_shutdown() unless a close alert has + * already been sent. + */ + if ((ret & SSL_SENT_SHUTDOWN) == 0) + SSL_shutdown(slp->ssl); + } SSL_free(slp->ssl); + if (slp->cert != NULL) + X509_free(slp->cert); /* * For RPC-over-TLS, this upcall is expected * to close off the socket. */ - shutdown(slp->s, SHUT_WR); + if (!slp->shutoff) + shutdown(slp->s, SHUT_WR); close(slp->s); free(slp); result->reterr = RPCTLSERR_OK; @@ -595,7 +672,7 @@ rpctls_setupcl_ssl(bool cert) } static SSL * -rpctls_connect(SSL_CTX *ctx, int s) +rpctls_connect(SSL_CTX *ctx, int s, X509 **certp) { SSL *ssl; X509 *cert; @@ -605,13 +682,7 @@ rpctls_connect(SSL_CTX *ctx, int s) int gethostret, ret; char *cp, *cp2; - if (rpctls_gothup) { - rpctls_gothup = false; - ret = rpctls_loadcrlfile(ctx); - if (ret == 0) - rpctlscd_verbose_out("rpctls_connect: Can't " - "reload CRLfile\n"); - } + *certp = NULL; ssl = SSL_new(ctx); if (ssl == NULL) { rpctlscd_verbose_out("rpctls_connect: " @@ -650,7 +721,6 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); rpctls_verify_capath != NULL) && (gethostret == 0 || rpctls_checkhost(sad, cert) != 1)) ret = X509_V_ERR_HOSTNAME_MISMATCH; - X509_free(cert); if (ret != X509_V_OK && (rpctls_verify_cafile != NULL || rpctls_verify_capath != NULL)) { if (ret != X509_V_OK) { @@ -671,6 +741,7 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); "failed %s\n", hostnam, cp, cp2, X509_verify_cert_error_string(ret)); } + X509_free(cert); SSL_free(ssl); return (NULL); } @@ -680,16 +751,23 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); rpctlscd_verbose_out("rpctls_connect: BIO_get_ktls_send=%d\n", ret); if (ret != 0) { ret = BIO_get_ktls_recv(SSL_get_rbio(ssl)); - rpctlscd_verbose_out("rpctls_connect: BIO_get_ktls_recv=%d\n", ret); + rpctlscd_verbose_out("rpctls_connect: BIO_get_ktls_recv=%d\n", + ret); } if (ret == 0) { if (rpctls_debug_level == 0) syslog(LOG_ERR, "ktls not working\n"); else fprintf(stderr, "ktls not working\n"); + X509_free(cert); SSL_free(ssl); return (NULL); } + if (ret == X509_V_OK && (rpctls_verify_cafile != NULL || + rpctls_verify_capath != NULL) && rpctls_crlfile != NULL) + *certp = cert; + else + X509_free(cert); return (ssl); } @@ -781,3 +859,55 @@ rpctls_huphandler(int sig __unused) rpctls_gothup = true; } +/* + * Read the CRL file and check for any extant connections + * that might now be revoked. + */ +static void +rpctls_checkcrl(void) +{ + struct ssl_entry *slp; + BIO *infile; + X509_CRL *crl; + X509_REVOKED *revoked; + int ret; + + if (rpctls_crlfile == NULL || (rpctls_verify_cafile == NULL && + rpctls_verify_capath == NULL)) + return; + infile = BIO_new(BIO_s_file()); + if (infile == NULL) { + rpctlscd_verbose_out("rpctls_checkcrl: Cannot BIO_new\n"); + return; + } + ret = BIO_read_filename(infile, rpctls_crlfile); + if (ret != 1) { + rpctlscd_verbose_out("rpctls_checkcrl: Cannot read CRL file\n"); + BIO_free(infile); + return; + } + + for (crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, ""); + crl != NULL; crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, "")) { + LIST_FOREACH(slp, &rpctls_ssllist, next) { + if (slp->cert != NULL) { + ret = X509_CRL_get0_by_cert(crl, &revoked, + slp->cert); +rpctlscd_verbose_out("get0_by_cert=%d\n", ret); + /* + * Do a shutdown on the socket, so that it + * can no longer be used. The kernel RPC + * code will notice the socket is disabled + * and will do a disconnect upcall, which will + * close the socket. + */ + if (ret == 1) { + shutdown(slp->s, SHUT_WR); + slp->shutoff = true; + } + } + } + X509_CRL_free(crl); + } + BIO_free(infile); +} From owner-svn-src-projects@freebsd.org Wed Sep 16 23:58:18 2020 Return-Path: Delivered-To: svn-src-projects@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 A221A3F5463 for ; Wed, 16 Sep 2020 23:58:18 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsH9Q3qpYz4ShR; Wed, 16 Sep 2020 23:58:18 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 66BA12164D; Wed, 16 Sep 2020 23:58:18 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08GNwI0X019946; Wed, 16 Sep 2020 23:58:18 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08GNwI4i019945; Wed, 16 Sep 2020 23:58:18 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009162358.08GNwI4i019945@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 16 Sep 2020 23:58:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365824 - projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Commit-Revision: 365824 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Sep 2020 23:58:18 -0000 Author: rmacklem Date: Wed Sep 16 23:58:17 2020 New Revision: 365824 URL: https://svnweb.freebsd.org/changeset/base/365824 Log: Update the rpc.tlsservd man page to indicate that extant connections that presented certificates during TLS handshake and are now revoked are shut down. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Wed Sep 16 23:36:37 2020 (r365823) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Wed Sep 16 23:58:17 2020 (r365824) @@ -119,7 +119,9 @@ and .Dq key.pem . .Pp If a SIGHUP signal is sent to the daemon it will reload the -.Dq CRLfile . +.Dq CRLfile +and will shut down any extant connections that presented certificates +during TLS handshake that have been revoked. If the .Fl r option was not specified, the SIGHUP signal will be ignored. From owner-svn-src-projects@freebsd.org Thu Sep 17 00:03:19 2020 Return-Path: Delivered-To: svn-src-projects@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 E35D33F5C05 for ; Thu, 17 Sep 2020 00:03:19 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsHHC5hPfz4StY; Thu, 17 Sep 2020 00:03:19 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id A60F82155F; Thu, 17 Sep 2020 00:03:19 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08H03J5e025837; Thu, 17 Sep 2020 00:03:19 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08H03JZt025836; Thu, 17 Sep 2020 00:03:19 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009170003.08H03JZt025836@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Thu, 17 Sep 2020 00:03:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365825 - projects/nfs-over-tls/usr.sbin/rpc.tlsclntd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd X-SVN-Commit-Revision: 365825 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Sep 2020 00:03:19 -0000 Author: rmacklem Date: Thu Sep 17 00:03:19 2020 New Revision: 365825 URL: https://svnweb.freebsd.org/changeset/base/365825 Log: Update the rpc.tlsclntd man page to indicate that extant connections that presented certificates during TLS handshake and have been revoked will be shut down. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 Wed Sep 16 23:58:17 2020 (r365824) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 Thu Sep 17 00:03:19 2020 (r365825) @@ -72,7 +72,9 @@ cannot have a wildcard in it. .Pp If a SIGHUP signal is sent to the daemon it will reload the -.Dq CRLfile . +.Dq CRLfile +and will shut down any extant connections that presented certificates +during TLS handshake that have been revoked. If the .Fl r option was not specified, the SIGHUP signal will be ignored. From owner-svn-src-projects@freebsd.org Thu Sep 17 01:23:17 2020 Return-Path: Delivered-To: svn-src-projects@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 1FDCC3F7290 for ; Thu, 17 Sep 2020 01:23:17 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsK3S73k2z4X97; Thu, 17 Sep 2020 01:23:16 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id CEE31223B7; Thu, 17 Sep 2020 01:23:16 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08H1NGCN075037; Thu, 17 Sep 2020 01:23:16 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08H1NGsI075035; Thu, 17 Sep 2020 01:23:16 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009170123.08H1NGsI075035@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Thu, 17 Sep 2020 01:23:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365827 - in projects/nfs-over-tls/usr.sbin: rpc.tlsclntd rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in projects/nfs-over-tls/usr.sbin: rpc.tlsclntd rpc.tlsservd X-SVN-Commit-Revision: 365827 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Sep 2020 01:23:17 -0000 Author: rmacklem Date: Thu Sep 17 01:23:16 2020 New Revision: 365827 URL: https://svnweb.freebsd.org/changeset/base/365827 Log: Update man pages with a STANDARDS section. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 Thu Sep 17 00:07:15 2020 (r365826) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.8 Thu Sep 17 01:23:16 2020 (r365827) @@ -26,7 +26,7 @@ .\" $FreeBSD$ .\" .\" Modified from gssd.8 for rpc.tlsclntd.8 by Rick Macklem. -.Dd September 3, 2020 +.Dd September 16, 2020 .Dt RPC.TLSCLNTD 8 .Os .Sh NAME @@ -164,6 +164,17 @@ option has also been specified. .Xr mount_nfs 8 , .Xr rpc.tlsservd 8 , .Xr syslogd 8 +.Sh STANDARDS +The implementation is based on the specification in +.Rs +.%B "RFC NNNN" +.%T "Towards Remote Procedure Call Encryption By Default" +.Re +.Sh HISTORY +The +.Nm +manual page first appeared in +.Fx 13.0 . .Sh BUGS This daemon cannot be safely shut down and restarted if there are any active RPC-over-TLS connections. @@ -171,8 +182,3 @@ Doing so will orphan the KERNEL_TLS connections, so th can no longer do upcalls successfully, since the .Dq SSL * structures in userspace have been lost. -.Sh HISTORY -The -.Nm -manual page first appeared in -.Fx 13.0 . Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Thu Sep 17 00:07:15 2020 (r365826) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.8 Thu Sep 17 01:23:16 2020 (r365827) @@ -26,7 +26,7 @@ .\" $FreeBSD$ .\" .\" Modified from gssd.8 for rpc.tlsservd.8 by Rick Macklem. -.Dd September 3, 2020 +.Dd September 16, 2020 .Dt RPC.TLSSERVD 8 .Os .Sh NAME @@ -320,6 +320,17 @@ options is allowed. .Xr nfsuserd 8 , .Xr rpc.tlsclntd 8 , .Xr syslogd 8 +.Sh STANDARDS +The implementation is based on the specification in +.Rs +.%B "RFC NNNN" +.%T "Towards Remote Procedure Call Encryption By Default" +.Re +.Sh HISTORY +The +.Nm +manual page first appeared in +.Fx 13.0 . .Sh BUGS This daemon cannot be safely shut down and restarted if there are any active RPC-over-TLS connections. @@ -327,8 +338,3 @@ Doing so will orphan the KERNEL_TLS connections, so th can no longer do upcalls successfully, since the .Dq SSL * structures in userspace have been lost. -.Sh HISTORY -The -.Nm -manual page first appeared in -.Fx 13.0 . From owner-svn-src-projects@freebsd.org Thu Sep 17 02:03:52 2020 Return-Path: Delivered-To: svn-src-projects@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 A6B8F3F7B3B for ; Thu, 17 Sep 2020 02:03:52 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BsKyJ3fmrz4Z2r; Thu, 17 Sep 2020 02:03:52 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 60F3822C3D; Thu, 17 Sep 2020 02:03:52 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08H23qL9099539; Thu, 17 Sep 2020 02:03:52 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08H23qwD099538; Thu, 17 Sep 2020 02:03:52 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009170203.08H23qwD099538@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Thu, 17 Sep 2020 02:03:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365828 - projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/usr.sbin/rpc.tlsservd X-SVN-Commit-Revision: 365828 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Sep 2020 02:03:52 -0000 Author: rmacklem Date: Thu Sep 17 02:03:51 2020 New Revision: 365828 URL: https://svnweb.freebsd.org/changeset/base/365828 Log: Oops, used the wrong free() function to free a X509 certificate. Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Thu Sep 17 01:23:16 2020 (r365827) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Thu Sep 17 02:03:51 2020 (r365828) @@ -587,6 +587,8 @@ rpctlssd_verbose_out("get_shutdown1=%d\n", ret); SSL_shutdown(slp->ssl); } SSL_free(slp->ssl); + if (slp->cert != NULL) + X509_free(slp->cert); /* * For RPC-over-TLS, this upcall is expected * to close off the socket. @@ -594,7 +596,6 @@ rpctlssd_verbose_out("get_shutdown1=%d\n", ret); if (!slp->shutoff) shutdown(slp->s, SHUT_WR); close(slp->s); - free(slp->cert); free(slp); result->reterr = RPCTLSERR_OK; } else From owner-svn-src-projects@freebsd.org Fri Sep 18 01:11:12 2020 Return-Path: Delivered-To: svn-src-projects@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 C2DAA3F3C8D for ; Fri, 18 Sep 2020 01:11:12 +0000 (UTC) (envelope-from rmacklem@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Bswl459Wmz3f6G; Fri, 18 Sep 2020 01:11:12 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 94A64131B6; Fri, 18 Sep 2020 01:11:12 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08I1BC1K053650; Fri, 18 Sep 2020 01:11:12 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08I1BBkM053644; Fri, 18 Sep 2020 01:11:11 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202009180111.08I1BBkM053644@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Fri, 18 Sep 2020 01:11:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r365866 - in projects/nfs-over-tls/usr.sbin: rpc.tlsclntd rpc.tlsservd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in projects/nfs-over-tls/usr.sbin: rpc.tlsclntd rpc.tlsservd X-SVN-Commit-Revision: 365866 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Sep 2020 01:11:12 -0000 Author: rmacklem Date: Fri Sep 18 01:11:11 2020 New Revision: 365866 URL: https://svnweb.freebsd.org/changeset/base/365866 Log: Factor out several functions from the daemons and put them in common files shared by both daemons. Added: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.c (contents, props changed) projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.h (contents, props changed) Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/Makefile projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c projects/nfs-over-tls/usr.sbin/rpc.tlsservd/Makefile projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/Makefile ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/Makefile Fri Sep 18 00:02:58 2020 (r365865) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/Makefile Fri Sep 18 01:11:11 2020 (r365866) @@ -4,9 +4,9 @@ PROG= rpc.tlsclntd MAN= rpc.tlsclntd.8 -SRCS= rpc.tlsclntd.c rpctlscd.h rpctlscd_svc.c rpctlscd_xdr.c +SRCS= rpc.tlsclntd.c rpc.tlscommon.c rpctlscd.h rpctlscd_svc.c rpctlscd_xdr.c -CFLAGS+= -I. +CFLAGS+= -I. -I${SRCTOP}/usr.sbin/rpc.tlsservd CFLAGS+= -I/usr/ktls/include LDFLAGS+= -L/usr/ktls/lib @@ -27,6 +27,6 @@ rpctlscd_xdr.c: ${RPCSRC} rpctlscd.h rpctlscd.h: ${RPCSRC} ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} -.PATH: ${SRCTOP}/sys/rpc/rpcsec_tls +.PATH: ${SRCTOP}/sys/rpc/rpcsec_tls ${SRCTOP}/usr.sbin/rpc.tlsservd .include Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c Fri Sep 18 00:02:58 2020 (r365865) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c Fri Sep 18 01:11:11 2020 (r365866) @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include "rpctlscd.h" +#include "rpc.tlscommon.h" #ifndef _PATH_RPCTLSCDSOCK #define _PATH_RPCTLSCDSOCK "/var/run/rpc.tlsclntd.sock" @@ -77,52 +78,27 @@ __FBSDID("$FreeBSD$"); #define _PREFERRED_CIPHERS "AES128-GCM-SHA256" #endif -/* - * How long to delay a reload of the CRL when there are RPC request(s) - * to process, in usec. Must be less than 1second. - */ -#define RELOADDELAY 250000 +/* Global variables also used by rpc.tlscommon.c. */ +int rpctls_debug_level; +bool rpctls_verbose; +SSL_CTX *rpctls_ctx = NULL; +const char *rpctls_verify_cafile = NULL; +const char *rpctls_verify_capath = NULL; +const char *rpctls_crlfile = NULL; +bool rpctls_gothup = false; +struct ssl_list rpctls_ssllist; + static struct pidfh *rpctls_pfh = NULL; -static int rpctls_debug_level; -static bool rpctls_verbose; -static SSL_CTX *rpctls_ctx = NULL; -static const char *rpctls_verify_cafile = NULL; -static const char *rpctls_verify_capath = NULL; -static const char *rpctls_crlfile = NULL; static const char *rpctls_certdir = _PATH_CERTANDKEY; static uint64_t rpctls_ssl_refno = 0; static uint64_t rpctls_ssl_sec = 0; static uint64_t rpctls_ssl_usec = 0; -static bool rpctls_gothup = false; -/* - * A linked list of all current "SSL *"s and socket "fd"s - * for kernel RPC TLS connections is maintained. - * The "refno" field is a unique 64bit value used to - * identify which entry a kernel RPC upcall refers to. - */ -LIST_HEAD(ssl_list, ssl_entry); -struct ssl_entry { - LIST_ENTRY(ssl_entry) next; - uint64_t refno; - int s; - bool shutoff; - SSL *ssl; - X509 *cert; -}; -static struct ssl_list rpctls_ssllist; - static void rpctlscd_terminate(int); static SSL_CTX *rpctls_setupcl_ssl(bool cert); static SSL *rpctls_connect(SSL_CTX *ctx, int s, X509 **certp); -static int rpctls_gethost(int s, struct sockaddr *sad, - char *hostip, size_t hostlen); -static int rpctls_checkhost(struct sockaddr *sad, X509 *cert); -static int rpctls_loadcrlfile(SSL_CTX *ctx); static void rpctls_huphandler(int sig __unused); -static void rpctls_checkcrl(void); -static void rpctlscd_verbose_out(const char *fmt, ...); extern void rpctlscd_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -146,16 +122,12 @@ main(int argc, char **argv) * TLS handshake. */ struct sockaddr_un sun; - int ch, fd, oldmask, ret; + int ch, fd, oldmask; SVCXPRT *xprt; bool cert; struct timeval tm; struct timezone tz; pid_t otherpid; - fd_set readfds; - uint64_t curtime, nexttime; - struct timespec tp; - sigset_t sighup_mask; /* Check that another rpctlscd isn't already running. */ rpctls_pfh = pidfile_open(_PATH_RPCTLSCDPID, 0600, &otherpid); @@ -305,61 +277,8 @@ main(int argc, char **argv) rpctls_syscall(RPCTLS_SYSC_CLSETPATH, _PATH_RPCTLSCDSOCK); - /* Expand svc_run() here so that we can call rpctls_loadcrlfile(). */ - curtime = nexttime = 0; - sigemptyset(&sighup_mask); - sigaddset(&sighup_mask, SIGHUP); - for (;;) { - clock_gettime(CLOCK_MONOTONIC, &tp); - curtime = tp.tv_sec; - curtime = curtime * 1000000 + tp.tv_nsec / 1000; - sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - if (rpctls_gothup && curtime >= nexttime) { - rpctls_gothup = false; - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - ret = rpctls_loadcrlfile(rpctls_ctx); - if (ret != 0) - rpctls_checkcrl(); - else - rpctlscd_verbose_out("rpc.tlsclntd: Can't " - "reload CRLfile\n"); - clock_gettime(CLOCK_MONOTONIC, &tp); - nexttime = tp.tv_sec; - nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 + - RELOADDELAY; - } else - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + rpctls_svc_run(); - /* - * If a reload is pending, poll for received request(s), - * otherwise set a RELOADDELAY timeout, since a SIGHUP - * could be processed between the got_sighup test and - * the select() system call. - */ - tm.tv_sec = 0; - if (rpctls_gothup) - tm.tv_usec = 0; - else - tm.tv_usec = RELOADDELAY; - readfds = svc_fdset; - switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tm)) { - case -1: - if (errno == EINTR) { - /* Allow a reload now. */ - nexttime = 0; - continue; - } - syslog(LOG_ERR, "rpc.tlsservd died: select: %m"); - exit(1); - case 0: - /* Allow a reload now. */ - nexttime = 0; - continue; - default: - svc_getreqset(&readfds); - } - } - rpctls_syscall(RPCTLS_SYSC_CLSHUTDOWN, ""); SSL_CTX_free(rpctls_ctx); @@ -367,26 +286,11 @@ main(int argc, char **argv) return (0); } -static void -rpctlscd_verbose_out(const char *fmt, ...) -{ - va_list ap; - - if (rpctls_verbose) { - va_start(ap, fmt); - if (rpctls_debug_level == 0) - vsyslog(LOG_INFO | LOG_DAEMON, fmt, ap); - else - vfprintf(stderr, fmt, ap); - va_end(ap); - } -} - bool_t rpctlscd_null_1_svc(void *argp, void *result, struct svc_req *rqstp) { - rpctlscd_verbose_out("rpctlscd_null: done\n"); + rpctls_verbose_out("rpctlscd_null: done\n"); return (TRUE); } @@ -402,10 +306,10 @@ rpctlscd_connect_1_svc(void *argp, struct ssl_entry *newslp; X509 *cert; - rpctlscd_verbose_out("rpctlsd_connect: started\n"); + rpctls_verbose_out("rpctlsd_connect: started\n"); /* Get the socket fd from the kernel. */ s = rpctls_syscall(RPCTLS_SYSC_CLSOCKET, ""); -rpctlscd_verbose_out("rpctlsd_connect s=%d\n", s); +rpctls_verbose_out("rpctlsd_connect s=%d\n", s); if (s < 0) { result->reterr = RPCTLSERR_NOSOCKET; return (TRUE); @@ -414,7 +318,7 @@ rpctlscd_verbose_out("rpctlsd_connect s=%d\n", s); /* Do a TLS connect handshake. */ ssl = rpctls_connect(rpctls_ctx, s, &cert); if (ssl == NULL) { - rpctlscd_verbose_out("rpctlsd_connect: can't do TLS " + rpctls_verbose_out("rpctlsd_connect: can't do TLS " "handshake\n"); result->reterr = RPCTLSERR_NOSSL; } else { @@ -455,7 +359,7 @@ rpctlscd_handlerecord_1_svc(struct rpctlscd_handlereco int ret; char junk; -rpctlscd_verbose_out("handlerec sslref=%jx\n", (uintmax_t)slp->refno); +rpctls_verbose_out("handlerec sslref=%jx\n", (uintmax_t)slp->refno); slp = NULL; if (argp->sec == rpctls_ssl_sec && argp->usec == rpctls_ssl_usec) { @@ -466,7 +370,7 @@ rpctlscd_verbose_out("handlerec sslref=%jx\n", (uintma } if (slp != NULL) { - rpctlscd_verbose_out("rpctlscd_handlerecord fd=%d\n", + rpctls_verbose_out("rpctlscd_handlerecord fd=%d\n", slp->s); /* * An SSL_read() of 0 bytes should fail, but it should @@ -476,7 +380,7 @@ rpctlscd_verbose_out("handlerec sslref=%jx\n", (uintma if (ret <= 0) { /* Check to see if this was a close alert. */ ret = SSL_get_shutdown(slp->ssl); -rpctlscd_verbose_out("get_shutdown2=%d\n", ret); +rpctls_verbose_out("get_shutdown2=%d\n", ret); if ((ret & (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) == SSL_RECEIVED_SHUTDOWN) SSL_shutdown(slp->ssl); @@ -499,7 +403,7 @@ rpctlscd_disconnect_1_svc(struct rpctlscd_disconnect_a struct ssl_entry *slp; int ret; -rpctlscd_verbose_out("disconnect refno=%jx\n", (uintmax_t)slp->refno); +rpctls_verbose_out("disconnect refno=%jx\n", (uintmax_t)slp->refno); slp = NULL; if (argp->sec == rpctls_ssl_sec && argp->usec == rpctls_ssl_usec) { @@ -510,12 +414,12 @@ rpctlscd_verbose_out("disconnect refno=%jx\n", (uintma } if (slp != NULL) { - rpctlscd_verbose_out("rpctlscd_disconnect: fd=%d closed\n", + rpctls_verbose_out("rpctlscd_disconnect: fd=%d closed\n", slp->s); LIST_REMOVE(slp, next); if (!slp->shutoff) { ret = SSL_get_shutdown(slp->ssl); -rpctlscd_verbose_out("get_shutdown0=%d\n", ret); +rpctls_verbose_out("get_shutdown0=%d\n", ret); /* * Do an SSL_shutdown() unless a close alert has * already been sent. @@ -571,7 +475,7 @@ rpctls_setupcl_ssl(bool cert) ctx = SSL_CTX_new(TLS_client_method()); if (ctx == NULL) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: SSL_CTX_new " + rpctls_verbose_out("rpctls_setupcl_ssl: SSL_CTX_new " "failed\n"); return (NULL); } @@ -583,7 +487,7 @@ rpctls_setupcl_ssl(bool cert) */ ret = SSL_CTX_set_cipher_list(ctx, _PREFERRED_CIPHERS); if (ret == 0) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: " + rpctls_verbose_out("rpctls_setupcl_ssl: " "SSL_CTX_set_cipher_list failed to set any ciphers\n"); SSL_CTX_free(ctx); return (NULL); @@ -604,7 +508,7 @@ rpctls_setupcl_ssl(bool cert) ret = SSL_CTX_use_certificate_file(ctx, path, SSL_FILETYPE_PEM); if (ret != 1) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: can't use " + rpctls_verbose_out("rpctls_setupcl_ssl: can't use " "certificate file path=%s ret=%d\n", path, ret); SSL_CTX_free(ctx); return (NULL); @@ -616,7 +520,7 @@ rpctls_setupcl_ssl(bool cert) ret = SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM); if (ret != 1) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: Can't use " + rpctls_verbose_out("rpctls_setupcl_ssl: Can't use " "private key path=%s ret=%d\n", path, ret); SSL_CTX_free(ctx); return (NULL); @@ -626,7 +530,7 @@ rpctls_setupcl_ssl(bool cert) if (rpctls_crlfile != NULL) { ret = rpctls_loadcrlfile(ctx); if (ret == 0) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: " + rpctls_verbose_out("rpctls_setupcl_ssl: " "Load CRLfile failed\n"); SSL_CTX_free(ctx); return (NULL); @@ -645,7 +549,7 @@ rpctls_setupcl_ssl(bool cert) rpctls_verify_cafile, rpctls_verify_capath); #endif if (ret == 0) { - rpctlscd_verbose_out("rpctls_setupcl_ssl: " + rpctls_verbose_out("rpctls_setupcl_ssl: " "Can't load verify locations\n"); SSL_CTX_free(ctx); return (NULL); @@ -685,21 +589,21 @@ rpctls_connect(SSL_CTX *ctx, int s, X509 **certp) *certp = NULL; ssl = SSL_new(ctx); if (ssl == NULL) { - rpctlscd_verbose_out("rpctls_connect: " + rpctls_verbose_out("rpctls_connect: " "SSL_new failed\n"); return (NULL); } if (SSL_set_fd(ssl, s) != 1) { - rpctlscd_verbose_out("rpctls_connect: " + rpctls_verbose_out("rpctls_connect: " "SSL_set_fd failed\n"); SSL_free(ssl); return (NULL); } -rpctlscd_verbose_out("at SSL_connect\n"); +rpctls_verbose_out("at SSL_connect\n"); ret = SSL_connect(ssl); -rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); +rpctls_verbose_out("aft SSL_connect ret=%d\n", ret); if (ret != 1) { - rpctlscd_verbose_out("rpctls_connect: " + rpctls_verbose_out("rpctls_connect: " "SSL_connect failed %d\n", ret); SSL_free(ssl); @@ -708,7 +612,7 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); cert = SSL_get_peer_certificate(ssl); if (cert == NULL) { - rpctlscd_verbose_out("rpctls_connect: get peer" + rpctls_verbose_out("rpctls_connect: get peer" " certificate failed\n"); SSL_free(ssl); return (NULL); @@ -719,7 +623,7 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); ret = SSL_get_verify_result(ssl); if (ret == X509_V_OK && (rpctls_verify_cafile != NULL || rpctls_verify_capath != NULL) && (gethostret == 0 || - rpctls_checkhost(sad, cert) != 1)) + rpctls_checkhost(sad, cert, X509_CHECK_FLAG_NO_WILDCARDS) != 1)) ret = X509_V_ERR_HOSTNAME_MISMATCH; if (ret != X509_V_OK && (rpctls_verify_cafile != NULL || rpctls_verify_capath != NULL)) { @@ -748,10 +652,10 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); /* Check to see if ktls is enabled on the connection. */ ret = BIO_get_ktls_send(SSL_get_wbio(ssl)); - rpctlscd_verbose_out("rpctls_connect: BIO_get_ktls_send=%d\n", ret); + rpctls_verbose_out("rpctls_connect: BIO_get_ktls_send=%d\n", ret); if (ret != 0) { ret = BIO_get_ktls_recv(SSL_get_rbio(ssl)); - rpctlscd_verbose_out("rpctls_connect: BIO_get_ktls_recv=%d\n", + rpctls_verbose_out("rpctls_connect: BIO_get_ktls_recv=%d\n", ret); } if (ret == 0) { @@ -772,142 +676,9 @@ rpctlscd_verbose_out("aft SSL_connect ret=%d\n", ret); return (ssl); } -/* - * Get the server's IP address. - */ -static int -rpctls_gethost(int s, struct sockaddr *sad, char *hostip, size_t hostlen) -{ - socklen_t slen; - int ret; - - slen = sizeof(struct sockaddr_storage); - if (getpeername(s, sad, &slen) < 0) - return (0); - ret = 0; - if (getnameinfo((const struct sockaddr *)sad, - sad->sa_len, hostip, hostlen, - NULL, 0, NI_NUMERICHOST) == 0) { - rpctlscd_verbose_out("rpctls_gethost: %s\n", - hostip); - ret = 1; - } - return (ret); -} - -/* - * Check a server IP address against any host address in the - * certificate. Basically getnameinfo(3) and - * X509_check_host(). - */ -static int -rpctls_checkhost(struct sockaddr *sad, X509 *cert) -{ - char hostnam[NI_MAXHOST]; - int ret; - - if (getnameinfo((const struct sockaddr *)sad, - sad->sa_len, hostnam, sizeof(hostnam), - NULL, 0, NI_NAMEREQD) != 0) - return (0); - rpctlscd_verbose_out("rpctls_checkhost: DNS %s\n", - hostnam); - ret = X509_check_host(cert, hostnam, strlen(hostnam), - X509_CHECK_FLAG_NO_WILDCARDS, NULL); - return (ret); -} - -/* - * (re)load the CRLfile into the certificate verification store. - */ -static int -rpctls_loadcrlfile(SSL_CTX *ctx) -{ - X509_STORE *certstore; - X509_LOOKUP *certlookup; - int ret; - - if ((rpctls_verify_cafile != NULL || - rpctls_verify_capath != NULL) && - rpctls_crlfile != NULL) { - certstore = SSL_CTX_get_cert_store(ctx); - certlookup = X509_STORE_add_lookup( - certstore, X509_LOOKUP_file()); - ret = 0; - if (certlookup != NULL) - ret = X509_load_crl_file(certlookup, - rpctls_crlfile, X509_FILETYPE_PEM); - if (ret != 0) - ret = X509_STORE_set_flags(certstore, - X509_V_FLAG_CRL_CHECK | - X509_V_FLAG_CRL_CHECK_ALL); - if (ret == 0) { - rpctlscd_verbose_out( - "rpctls_loadcrlfile: Can't" - " load CRLfile=%s\n", - rpctls_crlfile); - return (ret); - } - } - return (1); -} - static void rpctls_huphandler(int sig __unused) { rpctls_gothup = true; -} - -/* - * Read the CRL file and check for any extant connections - * that might now be revoked. - */ -static void -rpctls_checkcrl(void) -{ - struct ssl_entry *slp; - BIO *infile; - X509_CRL *crl; - X509_REVOKED *revoked; - int ret; - - if (rpctls_crlfile == NULL || (rpctls_verify_cafile == NULL && - rpctls_verify_capath == NULL)) - return; - infile = BIO_new(BIO_s_file()); - if (infile == NULL) { - rpctlscd_verbose_out("rpctls_checkcrl: Cannot BIO_new\n"); - return; - } - ret = BIO_read_filename(infile, rpctls_crlfile); - if (ret != 1) { - rpctlscd_verbose_out("rpctls_checkcrl: Cannot read CRL file\n"); - BIO_free(infile); - return; - } - - for (crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, ""); - crl != NULL; crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, "")) { - LIST_FOREACH(slp, &rpctls_ssllist, next) { - if (slp->cert != NULL) { - ret = X509_CRL_get0_by_cert(crl, &revoked, - slp->cert); -rpctlscd_verbose_out("get0_by_cert=%d\n", ret); - /* - * Do a shutdown on the socket, so that it - * can no longer be used. The kernel RPC - * code will notice the socket is disabled - * and will do a disconnect upcall, which will - * close the socket. - */ - if (ret == 1) { - shutdown(slp->s, SHUT_WR); - slp->shutoff = true; - } - } - } - X509_CRL_free(crl); - } - BIO_free(infile); } Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/Makefile ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/Makefile Fri Sep 18 00:02:58 2020 (r365865) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/Makefile Fri Sep 18 01:11:11 2020 (r365866) @@ -4,7 +4,7 @@ PROG= rpc.tlsservd MAN= rpc.tlsservd.8 -SRCS= rpc.tlsservd.c rpctlssd.h rpctlssd_svc.c rpctlssd_xdr.c +SRCS= rpc.tlsservd.c rpc.tlscommon.c rpctlssd.h rpctlssd_svc.c rpctlssd_xdr.c CFLAGS+= -I. Added: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.c Fri Sep 18 01:11:11 2020 (r365866) @@ -0,0 +1,305 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Rick Macklem + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "rpctlssd.h" +#include "rpc.tlscommon.h" + +/* Global variables defined in the daemons. */ +extern bool rpctls_gothup; +extern bool rpctls_verbose; +extern int rpctls_debug_level; +extern SSL_CTX *rpctls_ctx; +extern const char *rpctls_verify_cafile; +extern const char *rpctls_verify_capath; +extern const char *rpctls_crlfile; +extern struct ssl_list rpctls_ssllist; + +/* + * How long to delay a reload of the CRL when there are RPC request(s) + * to process, in usec. Must be less than 1second. + */ +#define RELOADDELAY 250000 + +void +rpctls_svc_run(void) +{ + int ret; + struct timeval tv; + fd_set readfds; + uint64_t curtime, nexttime; + struct timespec tp; + sigset_t sighup_mask; + + /* Expand svc_run() here so that we can call rpctls_loadcrlfile(). */ + curtime = nexttime = 0; + sigemptyset(&sighup_mask); + sigaddset(&sighup_mask, SIGHUP); + for (;;) { + clock_gettime(CLOCK_MONOTONIC, &tp); + curtime = tp.tv_sec; + curtime = curtime * 1000000 + tp.tv_nsec / 1000; + sigprocmask(SIG_BLOCK, &sighup_mask, NULL); + if (rpctls_gothup && curtime >= nexttime) { + rpctls_gothup = false; + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + ret = rpctls_loadcrlfile(rpctls_ctx); + if (ret != 0) + rpctls_checkcrl(); + else + rpctls_verbose_out("rpc.tlsservd: Can't " + "reload CRLfile\n"); + clock_gettime(CLOCK_MONOTONIC, &tp); + nexttime = tp.tv_sec; + nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 + + RELOADDELAY; + } else + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + + /* + * If a reload is pending, poll for received request(s), + * otherwise set a RELOADDELAY timeout, since a SIGHUP + * could be processed between the got_sighup test and + * the select() system call. + */ + tv.tv_sec = 0; + if (rpctls_gothup) + tv.tv_usec = 0; + else + tv.tv_usec = RELOADDELAY; + readfds = svc_fdset; + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tv)) { + case -1: + if (errno == EINTR) { + /* Allow a reload now. */ + nexttime = 0; + continue; + } + syslog(LOG_ERR, "rpc.tls daemon died: select: %m"); + exit(1); + case 0: + /* Allow a reload now. */ + nexttime = 0; + continue; + default: + svc_getreqset(&readfds); + } + } +} + +/* + * (re)load the CRLfile into the certificate verification store. + */ +int +rpctls_loadcrlfile(SSL_CTX *ctx) +{ + X509_STORE *certstore; + X509_LOOKUP *certlookup; + int ret; + + if ((rpctls_verify_cafile != NULL || + rpctls_verify_capath != NULL) && + rpctls_crlfile != NULL) { + certstore = SSL_CTX_get_cert_store(ctx); + certlookup = X509_STORE_add_lookup( + certstore, X509_LOOKUP_file()); + ret = 0; + if (certlookup != NULL) + ret = X509_load_crl_file(certlookup, + rpctls_crlfile, X509_FILETYPE_PEM); + if (ret != 0) + ret = X509_STORE_set_flags(certstore, + X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + if (ret == 0) { + rpctls_verbose_out( + "rpctls_loadcrlfile: Can't" + " load CRLfile=%s\n", + rpctls_crlfile); + return (ret); + } + } + return (1); +} + +/* + * Read the CRL file and check for any extant connections + * that might now be revoked. + */ +void +rpctls_checkcrl(void) +{ + struct ssl_entry *slp; + BIO *infile; + X509_CRL *crl; + X509_REVOKED *revoked; + char *cp, *cp2; + int ret; + + if (rpctls_crlfile == NULL || (rpctls_verify_cafile == NULL && + rpctls_verify_capath == NULL)) + return; + infile = BIO_new(BIO_s_file()); + if (infile == NULL) { + rpctls_verbose_out("rpctls_checkcrl: Cannot BIO_new\n"); + return; + } + ret = BIO_read_filename(infile, rpctls_crlfile); + if (ret != 1) { + rpctls_verbose_out("rpctls_checkcrl: Cannot read CRL file\n"); + BIO_free(infile); + return; + } + + for (crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, ""); + crl != NULL; crl = PEM_read_bio_X509_CRL(infile, NULL, NULL, "")) { + LIST_FOREACH(slp, &rpctls_ssllist, next) { + if (slp->cert != NULL) { + ret = X509_CRL_get0_by_cert(crl, &revoked, + slp->cert); +rpctls_verbose_out("get0_by_cert=%d\n", ret); + /* + * Do a shutdown on the socket, so that it + * can no longer be used. The kernel RPC + * code will notice the socket is disabled + * and will do a disconnect upcall, which will + * close the socket. + */ + if (ret == 1) { + cp2 = X509_NAME_oneline( + X509_get_subject_name(slp->cert), + NULL, 0); + cp = X509_NAME_oneline( + X509_get_issuer_name(slp->cert), + NULL, 0); + if (rpctls_debug_level == 0) + syslog(LOG_INFO | LOG_DAEMON, + "rpctls_daemon: Certificate" + " Revoked " + "issuerName=%s " + "subjectName=%s: " + "TCP connection closed", + cp, cp2); + else + fprintf(stderr, + "rpctls_daemon: Certificate" + " Revoked " + "issuerName=%s " + "subjectName=%s: " + "TCP connection closed", + cp, cp2); + shutdown(slp->s, SHUT_WR); + slp->shutoff = true; + } + } + } + X509_CRL_free(crl); + } + BIO_free(infile); +} + +void +rpctls_verbose_out(const char *fmt, ...) +{ + va_list ap; + + if (rpctls_verbose) { + va_start(ap, fmt); + if (rpctls_debug_level == 0) + vsyslog(LOG_INFO | LOG_DAEMON, fmt, ap); + else + vfprintf(stderr, fmt, ap); + va_end(ap); + } +} + +/* + * Check a IP address against any host address in the + * certificate. Basically getnameinfo(3) and + * X509_check_host(). + */ +int +rpctls_checkhost(struct sockaddr *sad, X509 *cert, unsigned int wildcard) +{ + char hostnam[NI_MAXHOST]; + int ret; + + if (getnameinfo((const struct sockaddr *)sad, + sad->sa_len, hostnam, sizeof(hostnam), + NULL, 0, NI_NAMEREQD) != 0) + return (0); + rpctls_verbose_out("rpctls_checkhost: DNS %s\n", + hostnam); + ret = X509_check_host(cert, hostnam, strlen(hostnam), + wildcard, NULL); + return (ret); +} + +/* + * Get the peer's IP address. + */ +int +rpctls_gethost(int s, struct sockaddr *sad, char *hostip, size_t hostlen) +{ + socklen_t slen; + int ret; + + slen = sizeof(struct sockaddr_storage); + if (getpeername(s, sad, &slen) < 0) + return (0); + ret = 0; + if (getnameinfo((const struct sockaddr *)sad, + sad->sa_len, hostip, hostlen, + NULL, 0, NI_NUMERICHOST) == 0) { + rpctls_verbose_out("rpctls_gethost: %s\n", + hostip); + ret = 1; + } + return (ret); +} Added: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlscommon.h Fri Sep 18 01:11:11 2020 (r365866) @@ -0,0 +1,56 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Rick Macklem + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + * Functions in rpc.tlscommon.c used by both rpc.tlsservd.c and rpc.tlsclntd.c. + */ +int rpctls_gethost(int s, struct sockaddr *sad, + char *hostip, size_t hostlen); +int rpctls_checkhost(struct sockaddr *sad, X509 *cert, + unsigned int wildcard); +int rpctls_loadcrlfile(SSL_CTX *ctx); +void rpctls_checkcrl(void); +void rpctls_verbose_out(const char *fmt, ...); +void rpctls_svc_run(void); + +/* + * A linked list of all current "SSL *"s and socket "fd"s + * for kernel RPC TLS connections is maintained. + * The "refno" field is a unique 64bit value used to + * identify which entry a kernel RPC upcall refers to. + */ +LIST_HEAD(ssl_list, ssl_entry); +struct ssl_entry { + LIST_ENTRY(ssl_entry) next; + uint64_t refno; + int s; + bool shutoff; + SSL *ssl; + X509 *cert; +}; Modified: projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Fri Sep 18 00:02:58 2020 (r365865) +++ projects/nfs-over-tls/usr.sbin/rpc.tlsservd/rpc.tlsservd.c Fri Sep 18 01:11:11 2020 (r365866) @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include "rpctlssd.h" +#include "rpc.tlscommon.h" #ifndef _PATH_RPCTLSSDSOCK #define _PATH_RPCTLSSDSOCK "/var/run/rpc.tlsservd.sock" @@ -78,63 +79,37 @@ __FBSDID("$FreeBSD$"); #define _PREFERRED_CIPHERS "AES128-GCM-SHA256" #endif -/* - * How long to delay a reload of the CRL when there are RPC request(s) - * to process, in usec. Must be less than 1second. - */ -#define RELOADDELAY 250000 +/* Global variables also used by rpc.tlscommon.c. */ +int rpctls_debug_level; +bool rpctls_verbose; +SSL_CTX *rpctls_ctx = NULL; +const char *rpctls_verify_cafile = NULL; +const char *rpctls_verify_capath = NULL; +const char *rpctls_crlfile = NULL; +bool rpctls_gothup = false; +struct ssl_list rpctls_ssllist; static struct pidfh *rpctls_pfh = NULL; -static int rpctls_debug_level; -static bool rpctls_verbose; -static SSL_CTX *rpctls_ctx = NULL; static bool rpctls_do_mutual = false; -static const char *rpctls_verify_cafile = NULL; -static const char *rpctls_verify_capath = NULL; -static const char *rpctls_crlfile = NULL; static const char *rpctls_certdir = _PATH_CERTANDKEY; static bool rpctls_comparehost = false; static unsigned int rpctls_wildcard = X509_CHECK_FLAG_NO_WILDCARDS; static uint64_t rpctls_ssl_refno = 0; static uint64_t rpctls_ssl_sec = 0; static uint64_t rpctls_ssl_usec = 0; -static bool rpctls_gothup = false; static bool rpctls_cnuser = false; static char *rpctls_dnsname; static const char *rpctls_cnuseroid = "1.3.6.1.4.1.2238.1.1.1"; -/* - * A linked list of all current "SSL *"s and socket "fd"s - * for kernel RPC TLS connections is maintained. - * The "refno" field is a unique 64bit value used to - * identify which entry a kernel RPC upcall refers to. - */ -LIST_HEAD(ssl_list, ssl_entry); -struct ssl_entry { - LIST_ENTRY(ssl_entry) next; - uint64_t refno; - int s; - bool shutoff; - SSL *ssl; - X509 *cert; -}; -static struct ssl_list rpctls_ssllist; - static void rpctlssd_terminate(int); static SSL_CTX *rpctls_setup_ssl(const char *certdir); static SSL *rpctls_server(SSL_CTX *ctx, int s, uint32_t *flags, uint32_t *uidp, int *ngrps, uint32_t *gidp, X509 **certp); -static int rpctls_gethost(int s, struct sockaddr *sad, - char *hostip, size_t hostlen); -static int rpctls_checkhost(struct sockaddr *sad, X509 *cert); -static int rpctls_loadcrlfile(SSL_CTX *ctx); static int rpctls_cnname(X509 *cert, uint32_t *uidp, int *ngrps, uint32_t *gidp); static char *rpctls_getdnsname(char *dnsname); static void rpctls_huphandler(int sig __unused); -static void rpctls_checkcrl(void); -static void rpctlssd_verbose_out(const char *fmt, ...); extern void rpctlssd_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -163,16 +138,12 @@ main(int argc, char **argv) * TLS handshake. */ struct sockaddr_un sun; - int ch, debug, fd, oldmask, ret; + int ch, debug, fd, oldmask; SVCXPRT *xprt; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***