Date: Sun, 26 Jan 2020 18:57:33 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r357154 - in projects/nfs-over-tls/sys/rpc: . rpcsec_tls Message-ID: <202001261857.00QIvXO3068052@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Sun Jan 26 18:57:33 2020 New Revision: 357154 URL: https://svnweb.freebsd.org/changeset/base/357154 Log: Add some new files for the RPC-over-TLS kernel rpc. Added: projects/nfs-over-tls/sys/rpc/rpcsec_tls/ projects/nfs-over-tls/sys/rpc/rpcsec_tls.h (contents, props changed) projects/nfs-over-tls/sys/rpc/rpcsec_tls/auth_tls.c (contents, props changed) projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c (contents, props changed) projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlscd.x projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlssd.x Added: projects/nfs-over-tls/sys/rpc/rpcsec_tls.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/sys/rpc/rpcsec_tls.h Sun Jan 26 18:57:33 2020 (r357154) @@ -0,0 +1,48 @@ +/*- + * 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$ + */ + +#ifndef _RPCTLS_IMPL_H +#define _RPCTLS_IMPL_H + +/* Operation values for rpctls syscall. */ +#define RPCTLS_SYSC_SETPATH 1 +#define RPCTLS_SYSC_CONNECT 2 +#define RPCTLS_SYSC_SERVER 3 + +#ifdef _KERNEL +/* Functions that perform upcalls to the rpctlsd daemon. */ +enum clnt_stat rpctls_connect(CLIENT *newclient, struct socket *so); +enum clnt_stat rpctls_server(struct socket *so); + +/* String for AUTH_TLS reply verifier. */ +#define RPCTLS_START_STRING "STARTTLS" + +#endif /* _KERNEL */ + +#endif /* _RPCTLS_IMPL_H */ Added: projects/nfs-over-tls/sys/rpc/rpcsec_tls/auth_tls.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/sys/rpc/rpcsec_tls/auth_tls.c Sun Jan 26 18:57:33 2020 (r357154) @@ -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: projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c Sun Jan 26 18:57:33 2020 (r357154) @@ -0,0 +1,507 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ + * Authors: Doug Rabson <dfr@rabson.org> + * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> + * + * 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. + */ + +/* Modified from the kernel GSSAPI code for RPC-over-TLS. */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/capsicum.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/priv.h> +#include <sys/proc.h> +#include <sys/socketvar.h> +#include <sys/syscall.h> +#include <sys/syscallsubr.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> + +#include <rpc/rpc.h> +#include <rpc/rpc_com.h> +#include <rpc/rpcsec_tls.h> + +#include "rpctlscd.h" +#include "rpctlssd.h" + +extern struct fileops badfileops; + +/* + * Syscall hooks + */ +static struct syscall_helper_data rpctls_syscalls[] = { + SYSCALL_INIT_HELPER(gssd_syscall), + SYSCALL_INIT_LAST +}; + +#ifdef notnow +struct rpctls_syscall_args { + char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; + char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; +}; +#endif + +static CLIENT *rpctls_connect_handle; +static struct mtx rpctls_connect_lock; +static struct socket *rpctls_connect_so = NULL; +static struct file *rpctls_connect_fp = NULL; +static int rpctls_connect_fd = -1; +static CLIENT *rpctls_server_handle; +static struct mtx rpctls_server_lock; +static struct socket *rpctls_server_so = NULL; +static struct file *rpctls_server_fp = NULL; +static int rpctls_server_fd = -1; +static struct opaque_auth rpctls_null_verf; + +static CLIENT *rpctls_connect_client(void); +static CLIENT *rpctls_server_client(void); + +static void +rpctls_init(void *dummy) +{ + int error; + + error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD); + if (error != 0) + printf("rpctls_init: cannot register syscall\n"); + mtx_init(&rpctls_connect_lock, "rpctls_connect_lock", NULL, + MTX_DEF); + mtx_init(&rpctls_server_lock, "rpctls_server_lock", NULL, + MTX_DEF); + rpctls_null_verf.oa_flavor = AUTH_NULL; + rpctls_null_verf.oa_base = RPCTLS_START_STRING; + rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING); +printf("RPCTLS init done\n"); +} +SYSINIT(rpctls_init, SI_SUB_KMEM, SI_ORDER_ANY, rpctls_init, NULL); + +int +sys_gssd_syscall(struct thread *td, struct gssd_syscall_args *uap) +{ + struct sockaddr_un sun; + struct netconfig *nconf; + struct file *fp; + struct socket *so; + char path[MAXPATHLEN], *pathp; + int fd, error, retry_count = 5; + CLIENT *cl, *oldcl; + bool ssd; + +printf("in gssd syscall\n"); + error = priv_check(td, PRIV_NFS_DAEMON); +printf("aft priv_check=%d\n", error); + if (error != 0) + return (error); + +#ifdef notyet + switch (uap->op) { + case RPCTLS_SYSC_SETPATH: +#else + error = copyinstr(uap->path, path, sizeof(path), NULL); +printf("setting err=%d path=%s\n", error, path); + if (error != 0) + return (error); + if (path[0] == 'S') { + ssd = true; + pathp = &path[1]; + } else { + ssd = false; + pathp = &path[0]; + } + if (pathp[0] == '/' || pathp[0] == '\0') { +#endif + if (ssd) { + if (error == 0 && strlen(pathp) + 1 > sizeof(sun.sun_path)) + error = EINVAL; + + if (error == 0 && pathp[0] != '\0') { + sun.sun_family = AF_LOCAL; + strlcpy(sun.sun_path, pathp, sizeof(sun.sun_path)); + sun.sun_len = SUN_LEN(&sun); + + nconf = getnetconfigent("local"); + cl = clnt_reconnect_create(nconf, + (struct sockaddr *)&sun, RPCTLSSD, RPCTLSSDVERS, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); +printf("got cl=%p\n", cl); + /* + * The number of retries defaults to INT_MAX, which + * effectively means an infinite, uninterruptable loop. + * Limiting it to five retries keeps it from running + * forever. + */ + if (cl != NULL) + CLNT_CONTROL(cl, CLSET_RETRIES, &retry_count); + } else + cl = NULL; + + mtx_lock(&rpctls_server_lock); + oldcl = rpctls_server_handle; + rpctls_server_handle = cl; + mtx_unlock(&rpctls_server_lock); + +printf("cl=%p oldcl=%p\n", cl, oldcl); + if (oldcl != NULL) { + CLNT_CLOSE(oldcl); + CLNT_RELEASE(oldcl); + } + } else { + if (error == 0 && strlen(pathp) + 1 > sizeof(sun.sun_path)) + error = EINVAL; + + if (error == 0 && pathp[0] != '\0') { + sun.sun_family = AF_LOCAL; + strlcpy(sun.sun_path, pathp, sizeof(sun.sun_path)); + sun.sun_len = SUN_LEN(&sun); + + nconf = getnetconfigent("local"); + cl = clnt_reconnect_create(nconf, + (struct sockaddr *)&sun, RPCTLSCD, RPCTLSCDVERS, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); +printf("got cl=%p\n", cl); + /* + * The number of retries defaults to INT_MAX, which + * effectively means an infinite, uninterruptable loop. + * Limiting it to five retries keeps it from running + * forever. + */ + if (cl != NULL) + CLNT_CONTROL(cl, CLSET_RETRIES, &retry_count); + } else + cl = NULL; + + mtx_lock(&rpctls_connect_lock); + oldcl = rpctls_connect_handle; + rpctls_connect_handle = cl; + mtx_unlock(&rpctls_connect_lock); + +printf("cl=%p oldcl=%p\n", cl, oldcl); + if (oldcl != NULL) { + CLNT_CLOSE(oldcl); + CLNT_RELEASE(oldcl); + } + } + } else if (path[0] == 'C') { +printf("In connect\n"); + KASSERT(rpctls_connect_so != NULL, + ("rpctlsc syscall so != NULL")); + KASSERT(rpctls_connect_fd == -1, + ("rpctlsc syscall fd not -1")); + error = falloc(td, &fp, &fd, 0); +printf("falloc=%d fd=%d\n", error, fd); + if (error == 0) { + mtx_lock(&rpctls_connect_lock); + so = rpctls_connect_so; + rpctls_connect_so = NULL; + rpctls_connect_fp = fp; + rpctls_connect_fd = fd; + mtx_unlock(&rpctls_connect_lock); + finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops); + td->td_retval[0] = fd; + } +printf("returning=%d\n", fd); + } else if (path[0] == 'D') { +printf("In EOconnect\n"); + mtx_lock(&rpctls_connect_lock); + fd = rpctls_connect_fd; + rpctls_connect_fd = -1; + fp = rpctls_connect_fp; + rpctls_connect_fp = NULL; + mtx_unlock(&rpctls_connect_lock); +printf("fd=%d\n", fd); + if (fd >= 0) { + /* + * Since the daemon will not be using the fd any + * more, we want to close the fd, but we do not + * want to soclose() the associated socket. + * Set f_ops == badfileops so that kern_close() will + * not do a soclose(). + */ + fp->f_ops = &badfileops; + kern_close(td, fd); +printf("aft kern_close\n"); + } else + printf("rpctlsc fd -1\n"); + } else if (path[0] == 'E') { +printf("In srvconnect\n"); + KASSERT(rpctls_server_so != NULL, + ("rpctlss syscall so != NULL")); + KASSERT(rpctls_server_fd == -1, + ("rpctlss syscall fd not -1")); + error = falloc(td, &fp, &fd, 0); +printf("srv falloc=%d fd=%d\n", error, fd); + if (error == 0) { + mtx_lock(&rpctls_server_lock); + so = rpctls_server_so; + rpctls_server_so = NULL; + rpctls_server_fp = fp; + rpctls_server_fd = fd; + mtx_unlock(&rpctls_server_lock); + finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops); + td->td_retval[0] = fd; + } +printf("srv returning=%d\n", fd); + } else if (path[0] == 'F') { +printf("In EOserver\n"); + mtx_lock(&rpctls_server_lock); + fd = rpctls_server_fd; + rpctls_server_fd = -1; + fp = rpctls_server_fp; + rpctls_server_fp = NULL; + mtx_unlock(&rpctls_server_lock); +printf("srv fd=%d\n", fd); + if (fd >= 0) { + /* + * Since the daemon will not be using the fd any + * more, we want to close the fd, but we do not + * want to soclose() the associated socket. + * Set f_ops == badfileops so that kern_close() will + * not do a soclose(). + */ + fp->f_ops = &badfileops; + kern_close(td, fd); +printf("srv aft kern_close\n"); + } else + printf("rpctlss fd -1\n"); + } + + return (error); +} + +/* + * Acquire the rpctls_connect_handle and return it with a reference count, + * if it is available. + */ +static CLIENT * +rpctls_connect_client(void) +{ + CLIENT *cl; + + mtx_lock(&rpctls_connect_lock); + cl = rpctls_connect_handle; + if (cl != NULL) + CLNT_ACQUIRE(cl); + mtx_unlock(&rpctls_connect_lock); + return (cl); +} + +/* + * Acquire the rpctls_server_handle and return it with a reference count, + * if it is available. + */ +static CLIENT * +rpctls_server_client(void) +{ + CLIENT *cl; + + mtx_lock(&rpctls_server_lock); + cl = rpctls_server_handle; + if (cl != NULL) + CLNT_ACQUIRE(cl); + mtx_unlock(&rpctls_server_lock); + return (cl); +} + +/* Do an upcall for a new socket connect using TLS. */ +enum clnt_stat +rpctls_connect(CLIENT *newclient, struct socket *so) +{ + struct rpc_callextra ext; + struct timeval utimeout; + enum clnt_stat stat; + CLIENT *cl; + int val; + static bool rpctls_connect_busy = false; + +printf("In rpctls_connect\n"); + cl = rpctls_connect_client(); +printf("connect_client=%p\n", cl); + if (cl == NULL) + return (RPC_TLSCONNECT); + + /* First, do the AUTH_TLS NULL RPC. */ + memset(&ext, 0, sizeof(ext)); + utimeout.tv_sec = 30; + utimeout.tv_usec = 0; + ext.rc_auth = authtls_create(); +printf("authtls=%p\n", ext.rc_auth); + stat = clnt_call_private(newclient, &ext, NULLPROC, (xdrproc_t)xdr_void, + NULL, (xdrproc_t)xdr_void, NULL, utimeout); +printf("aft NULLRPC=%d\n", stat); + AUTH_DESTROY(ext.rc_auth); + if (stat != RPC_SUCCESS) + return (RPC_SYSTEMERROR); + + /* Serialize the connect upcalls. */ + mtx_lock(&rpctls_connect_lock); + while (rpctls_connect_busy) + msleep(&rpctls_connect_busy, &rpctls_connect_lock, PVFS, + "rtlscn", 0); + rpctls_connect_busy = true; + rpctls_connect_so = so; + mtx_unlock(&rpctls_connect_lock); +printf("rpctls_conect so=%p\n", so); + + /* Temporarily block reception during the handshake upcall. */ + val = 1; + CLNT_CONTROL(newclient, CLSET_BLOCKRCV, &val); + + /* Do the connect handshake upcall. */ + stat = rpctlscd_connect_1(NULL, NULL, cl); +printf("aft connect upcall=%d\n", stat); + CLNT_RELEASE(cl); + + /* Unblock reception. */ + val = 0; + CLNT_CONTROL(newclient, CLSET_BLOCKRCV, &val); + + /* Once the upcall is done, the daemon is done with the fp and so. */ + mtx_lock(&rpctls_connect_lock); + rpctls_connect_so = NULL; + rpctls_connect_fd = -1; + rpctls_connect_busy = false; + wakeup(&rpctls_connect_busy); + mtx_unlock(&rpctls_connect_lock); +printf("aft wakeup\n"); + + return (stat); +} + +/* Do an upcall for a new server socket using TLS. */ +enum clnt_stat +rpctls_server(struct socket *so) +{ + enum clnt_stat stat; + CLIENT *cl; + static bool rpctls_server_busy = false; + +printf("In rpctls_server\n"); + cl = rpctls_server_client(); +printf("server_client=%p\n", cl); + if (cl == NULL) + return (RPC_SYSTEMERROR); + + /* Serialize the server upcalls. */ + mtx_lock(&rpctls_server_lock); + while (rpctls_server_busy) + msleep(&rpctls_server_busy, &rpctls_server_lock, PVFS, + "rtlssn", 0); + rpctls_server_busy = true; + rpctls_server_so = so; + mtx_unlock(&rpctls_server_lock); +printf("rpctls_conect so=%p\n", so); + + /* Do the server upcall. */ + stat = rpctlssd_connect_1(NULL, NULL, cl); +printf("aft server upcall=%d\n", stat); + CLNT_RELEASE(cl); + + /* Once the upcall is done, the daemon is done with the fp and so. */ + mtx_lock(&rpctls_server_lock); + rpctls_server_so = NULL; + rpctls_server_fd = -1; + rpctls_server_busy = false; + wakeup(&rpctls_server_busy); + mtx_unlock(&rpctls_server_lock); +printf("aft wakeup\n"); + + return (stat); +} + +/* + * Handle the NULL RPC with authentication flavor of AUTH_TLS. + * This is a STARTTLS command, so do the upcall to the rpctlssd daemon, + * which will do the TLS handshake. + */ +enum auth_stat +_svcauth_rpcsec_tls(struct svc_req *rqst, struct rpc_msg *msg) + +{ + bool_t call_stat; + enum clnt_stat stat; + SVCXPRT *xprt; + + /* Initialize reply. */ + rqst->rq_verf = rpctls_null_verf; +printf("authtls: clen=%d vlen=%d fl=%d\n", rqst->rq_cred.oa_length, msg->rm_call.cb_verf.oa_length, msg->rm_call.cb_verf.oa_flavor); + + /* Check client credentials. */ + if (rqst->rq_cred.oa_length != 0 || + msg->rm_call.cb_verf.oa_length != 0 || + msg->rm_call.cb_verf.oa_flavor != AUTH_NULL) + return (AUTH_BADCRED); + +printf("authtls proc=%d\n", rqst->rq_proc); + if (rqst->rq_proc != NULLPROC) + return (AUTH_REJECTEDCRED); + + /* + * Disable reception for the krpc so that the TLS handshake can + * be done on the socket in the rpctlssd daemon. + */ + xprt = rqst->rq_xprt; + sx_xlock(&xprt->xp_lock); + xprt->xp_dontrcv = TRUE; + sx_xunlock(&xprt->xp_lock); + + /* + * Send the reply to the NULL RPC with AUTH_TLS, which is the + * STARTTLS command for Sun RPC. + */ + call_stat = svc_sendreply(rqst, (xdrproc_t)xdr_void, NULL); +printf("authtls: null reply=%d\n", call_stat); + if (!call_stat) { + sx_xlock(&xprt->xp_lock); + xprt->xp_dontrcv = FALSE; + sx_xunlock(&xprt->xp_lock); + xprt_active(xprt); /* Harmless if already active. */ + return (AUTH_FAILED); + } + + /* Do an upcall to do the TLS handshake. */ + stat = rpctls_server(rqst->rq_xprt->xp_socket); + + /* Re-enable reception on the socket within the krpc. */ + sx_xlock(&xprt->xp_lock); + xprt->xp_dontrcv = FALSE; + sx_xunlock(&xprt->xp_lock); + xprt_active(xprt); /* Harmless if already active. */ +printf("authtls: aft handshake stat=%d\n", stat); + + if (stat != RPC_SUCCESS) + return (AUTH_FAILED); + return (RPCSEC_GSS_NODISPATCH); +} + Added: projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlscd.x ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlscd.x Sun Jan 26 18:57:33 2020 (r357154) @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ + * Authors: Doug Rabson <dfr@rabson.org> + * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> + * + * 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. + */ + +/* Modified from gssd.x for the client side of RPC-over-TLS. */ + +/* $FreeBSD$ */ + +program RPCTLSCD { + version RPCTLSCDVERS { + void RPCTLSCD_NULL(void) = 0; + + void RPCTLSCD_CONNECT(void) = 1; + } = 1; +} = 0x40677374; Added: projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlssd.x ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctlssd.x Sun Jan 26 18:57:33 2020 (r357154) @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ + * Authors: Doug Rabson <dfr@rabson.org> + * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> + * + * 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. + */ + +/* Modified from gssd.x for the server side of RPC-over-TLS. */ + +/* $FreeBSD$ */ + +program RPCTLSSD { + version RPCTLSSDVERS { + void RPCTLSSD_NULL(void) = 0; + + void RPCTLSSD_CONNECT(void) = 1; + } = 1; +} = 0x40677375;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001261857.00QIvXO3068052>