svn commit: r357154 - in projects/nfs-over-tls/sys/rpc: . rpcsec_tls
Rick Macklem
rmacklem at FreeBSD.org
Sun Jan 26 18:57:34 UTC 2020
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 at rabson.org>
+ * Developed with Red Inc: Alfred Perlstein <alfred at 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 at rabson.org>
+ * Developed with Red Inc: Alfred Perlstein <alfred at 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 at rabson.org>
+ * Developed with Red Inc: Alfred Perlstein <alfred at 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;
More information about the svn-src-projects
mailing list