aboutsummaryrefslogtreecommitdiff
path: root/sys/rpc/clnt_rc.c
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2020-12-21 23:14:53 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2020-12-23 21:42:55 +0000
commit665b1365fe8e24d618d63b0d57b0b4ad39e97824 (patch)
tree44fecd432dcd0b10c880a0fe045f5ba27d5a3a67 /sys/rpc/clnt_rc.c
parente523262107865130e40fb19f7c3c571c8dd0b252 (diff)
downloadsrc-665b1365fe8e24d618d63b0d57b0b4ad39e97824.tar.gz
src-665b1365fe8e24d618d63b0d57b0b4ad39e97824.zip
Add a new "tlscertname" NFS mount option.
When using NFS-over-TLS, an NFS client can optionally provide an X.509 certificate to the server during the TLS handshake. For some situations, such as different NFS servers or different certificates being mapped to different user credentials on the NFS server, there may be a need for different mounts to provide different certificates. This new mount option called "tlscertname" may be used to specify a non-default certificate be provided. This alernate certificate will be stored in /etc/rpc.tlsclntd in a file with a name based on what is provided by this mount option.
Diffstat (limited to 'sys/rpc/clnt_rc.c')
-rw-r--r--sys/rpc/clnt_rc.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c
index 730001723e94..8c204989d0ea 100644
--- a/sys/rpc/clnt_rc.c
+++ b/sys/rpc/clnt_rc.c
@@ -110,6 +110,7 @@ clnt_reconnect_create(
rc->rc_ucred = crdup(curthread->td_ucred);
rc->rc_client = NULL;
rc->rc_tls = false;
+ rc->rc_tlscertname = NULL;
cl->cl_refs = 1;
cl->cl_ops = &clnt_reconnect_ops;
@@ -198,7 +199,8 @@ clnt_reconnect_connect(CLIENT *cl)
(struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
if (rc->rc_tls && newclient != NULL) {
- stat = rpctls_connect(newclient, so, ssl, &reterr);
+ stat = rpctls_connect(newclient, rc->rc_tlscertname, so,
+ ssl, &reterr);
if (stat != RPC_SUCCESS || reterr != RPCTLSERR_OK) {
if (stat == RPC_SUCCESS)
stat = RPC_FAILED;
@@ -405,6 +407,7 @@ clnt_reconnect_control(CLIENT *cl, u_int request, void *info)
{
struct rc_data *rc = (struct rc_data *)cl->cl_private;
SVCXPRT *xprt;
+ size_t slen;
if (info == NULL) {
return (FALSE);
@@ -496,6 +499,20 @@ clnt_reconnect_control(CLIENT *cl, u_int request, void *info)
rc->rc_tls = true;
break;
+ case CLSET_TLSCERTNAME:
+ slen = strlen(info) + 1;
+ /*
+ * tlscertname with "key.pem" appended to it forms a file
+ * name. As such, the maximum allowable strlen(info) is
+ * NAME_MAX - 7. However, "slen" includes the nul termination
+ * byte so it can be up to NAME_MAX - 6.
+ */
+ if (slen <= 1 || slen > NAME_MAX - 6)
+ return (FALSE);
+ rc->rc_tlscertname = mem_alloc(slen);
+ strlcpy(rc->rc_tlscertname, info, slen);
+ break;
+
default:
return (FALSE);
}
@@ -543,6 +560,7 @@ clnt_reconnect_destroy(CLIENT *cl)
}
crfree(rc->rc_ucred);
mtx_destroy(&rc->rc_lock);
+ mem_free(rc->rc_tlscertname, 0); /* 0 ok, since arg. ignored. */
mem_free(rc, sizeof(*rc));
mem_free(cl, sizeof (CLIENT));
}