1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
5 * Authors: Doug Rabson <dfr@rabson.org>
6 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Extensively modified from /usr/src/usr.sbin/gssd.c r344402 for
32 * the client side of kernel RPC-over-TLS by Rick Macklem.
33 */
34
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/queue.h>
38 #include <sys/linker.h>
39 #include <sys/module.h>
40 #include <sys/stat.h>
41 #include <sys/sysctl.h>
42 #include <sys/syslog.h>
43 #include <sys/time.h>
44 #include <err.h>
45 #include <getopt.h>
46 #include <libutil.h>
47 #include <netdb.h>
48 #include <signal.h>
49 #include <stdarg.h>
50 #include <stdbool.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 #include <rpc/rpc.h>
57 #include <rpc/rpc_com.h>
58 #include <rpc/rpcsec_tls.h>
59
60 #include <openssl/opensslconf.h>
61 #include <openssl/bio.h>
62 #include <openssl/ssl.h>
63 #include <openssl/err.h>
64 #include <openssl/x509v3.h>
65
66 #include "rpctlscd.h"
67 #include "rpc.tlscommon.h"
68
69 #ifndef _PATH_RPCTLSCDSOCK
70 #define _PATH_RPCTLSCDSOCK "/var/run/rpc.tlsclntd.sock"
71 #endif
72 #ifndef _PATH_CERTANDKEY
73 #define _PATH_CERTANDKEY "/etc/rpc.tlsclntd/"
74 #endif
75 #ifndef _PATH_RPCTLSCDPID
76 #define _PATH_RPCTLSCDPID "/var/run/rpc.tlsclntd.pid"
77 #endif
78
79 /* Global variables also used by rpc.tlscommon.c. */
80 int rpctls_debug_level;
81 bool rpctls_verbose;
82 SSL_CTX *rpctls_ctx = NULL;
83 const char *rpctls_verify_cafile = NULL;
84 const char *rpctls_verify_capath = NULL;
85 char *rpctls_crlfile = NULL;
86 bool rpctls_cert = false;
87 bool rpctls_gothup = false;
88 struct ssl_list rpctls_ssllist;
89
90 static struct pidfh *rpctls_pfh = NULL;
91 static const char *rpctls_certdir = _PATH_CERTANDKEY;
92 static const char *rpctls_ciphers = NULL;
93 static uint64_t rpctls_ssl_refno = 0;
94 static uint64_t rpctls_ssl_sec = 0;
95 static uint64_t rpctls_ssl_usec = 0;
96 static int rpctls_tlsvers = TLS1_3_VERSION;
97
98 static void rpctlscd_terminate(int);
99 static SSL_CTX *rpctls_setupcl_ssl(void);
100 static SSL *rpctls_connect(SSL_CTX *ctx, int s, char *certname,
101 u_int certlen, X509 **certp);
102 static void rpctls_huphandler(int sig __unused);
103
104 extern void rpctlscd_1(struct svc_req *rqstp, SVCXPRT *transp);
105
106 static struct option longopts[] = {
107 { "usetls1_2", no_argument, NULL, '2' },
108 { "certdir", required_argument, NULL, 'D' },
109 { "ciphers", required_argument, NULL, 'C' },
110 { "debuglevel", no_argument, NULL, 'd' },
111 { "verifylocs", required_argument, NULL, 'l' },
112 { "mutualverf", no_argument, NULL, 'm' },
113 { "verifydir", required_argument, NULL, 'p' },
114 { "crl", required_argument, NULL, 'r' },
115 { "verbose", no_argument, NULL, 'v' },
116 { NULL, 0, NULL, 0 }
117 };
118
119 int
main(int argc,char ** argv)120 main(int argc, char **argv)
121 {
122 /*
123 * We provide an RPC service on a local-domain socket. The
124 * kernel rpctls code will upcall to this daemon to do the initial
125 * TLS handshake.
126 */
127 struct sockaddr_un sun;
128 int ch, fd, oldmask;
129 SVCXPRT *xprt;
130 bool tls_enable;
131 struct timeval tm;
132 struct timezone tz;
133 pid_t otherpid;
134 size_t tls_enable_len;
135
136 /* Check that another rpctlscd isn't already running. */
137 rpctls_pfh = pidfile_open(_PATH_RPCTLSCDPID, 0600, &otherpid);
138 if (rpctls_pfh == NULL) {
139 if (errno == EEXIST)
140 errx(1, "rpctlscd already running, pid: %d.", otherpid);
141 warn("cannot open or create pidfile");
142 }
143
144 /* Check to see that the ktls is enabled. */
145 tls_enable_len = sizeof(tls_enable);
146 if (sysctlbyname("kern.ipc.tls.enable", &tls_enable, &tls_enable_len,
147 NULL, 0) != 0 || !tls_enable)
148 errx(1, "Kernel TLS not enabled");
149
150 /* Get the time when this daemon is started. */
151 gettimeofday(&tm, &tz);
152 rpctls_ssl_sec = tm.tv_sec;
153 rpctls_ssl_usec = tm.tv_usec;
154
155 rpctls_verbose = false;
156 while ((ch = getopt_long(argc, argv, "2C:D:dl:mp:r:v", longopts,
157 NULL)) != -1) {
158 switch (ch) {
159 case '2':
160 rpctls_tlsvers = TLS1_2_VERSION;
161 break;
162 case 'C':
163 rpctls_ciphers = optarg;
164 break;
165 case 'D':
166 rpctls_certdir = optarg;
167 break;
168 case 'd':
169 rpctls_debug_level++;
170 break;
171 case 'l':
172 rpctls_verify_cafile = optarg;
173 break;
174 case 'm':
175 rpctls_cert = true;
176 break;
177 case 'p':
178 rpctls_verify_capath = optarg;
179 break;
180 case 'r':
181 rpctls_crlfile = optarg;
182 break;
183 case 'v':
184 rpctls_verbose = true;
185 break;
186 default:
187 fprintf(stderr, "usage: %s "
188 "[-2/--usetls1_2] "
189 "[-C/--ciphers available_ciphers] "
190 "[-D/--certdir certdir] [-d/--debuglevel] "
191 "[-l/--verifylocs CAfile] [-m/--mutualverf] "
192 "[-p/--verifydir CApath] [-r/--crl CRLfile] "
193 "[-v/--verbose]\n", argv[0]);
194 exit(1);
195 break;
196 }
197 }
198 if (rpctls_crlfile != NULL && rpctls_verify_cafile == NULL &&
199 rpctls_verify_capath == NULL)
200 errx(1, "-r requires the -l <CAfile> and/or "
201 "-p <CApath> options");
202
203 if (modfind("krpc") < 0) {
204 /* Not present in kernel, try loading it */
205 if (kldload("krpc") < 0 || modfind("krpc") < 0)
206 errx(1, "Kernel RPC is not available");
207 }
208
209 /*
210 * Set up the SSL_CTX *.
211 * Do it now, before daemonizing, in case the private key
212 * is encrypted and requires a passphrase to be entered.
213 */
214 rpctls_ctx = rpctls_setupcl_ssl();
215 if (rpctls_ctx == NULL) {
216 if (rpctls_debug_level == 0) {
217 syslog(LOG_ERR, "Can't set up TLS context");
218 exit(1);
219 }
220 err(1, "Can't set up TLS context");
221 }
222 LIST_INIT(&rpctls_ssllist);
223
224 if (!rpctls_debug_level) {
225 if (daemon(0, 0) != 0)
226 err(1, "Can't daemonize");
227 signal(SIGINT, SIG_IGN);
228 signal(SIGQUIT, SIG_IGN);
229 signal(SIGHUP, SIG_IGN);
230 }
231 signal(SIGTERM, rpctlscd_terminate);
232 signal(SIGPIPE, SIG_IGN);
233 signal(SIGHUP, rpctls_huphandler);
234
235 pidfile_write(rpctls_pfh);
236
237 memset(&sun, 0, sizeof sun);
238 sun.sun_family = AF_LOCAL;
239 unlink(_PATH_RPCTLSCDSOCK);
240 strcpy(sun.sun_path, _PATH_RPCTLSCDSOCK);
241 sun.sun_len = SUN_LEN(&sun);
242 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
243 if (fd < 0) {
244 if (rpctls_debug_level == 0) {
245 syslog(LOG_ERR, "Can't create local rpctlscd socket");
246 exit(1);
247 }
248 err(1, "Can't create local rpctlscd socket");
249 }
250 oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
251 if (bind(fd, (struct sockaddr *)&sun, sun.sun_len) < 0) {
252 if (rpctls_debug_level == 0) {
253 syslog(LOG_ERR, "Can't bind local rpctlscd socket");
254 exit(1);
255 }
256 err(1, "Can't bind local rpctlscd socket");
257 }
258 umask(oldmask);
259 if (listen(fd, SOMAXCONN) < 0) {
260 if (rpctls_debug_level == 0) {
261 syslog(LOG_ERR,
262 "Can't listen on local rpctlscd socket");
263 exit(1);
264 }
265 err(1, "Can't listen on local rpctlscd socket");
266 }
267 xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
268 if (!xprt) {
269 if (rpctls_debug_level == 0) {
270 syslog(LOG_ERR,
271 "Can't create transport for local rpctlscd socket");
272 exit(1);
273 }
274 err(1, "Can't create transport for local rpctlscd socket");
275 }
276 if (!svc_reg(xprt, RPCTLSCD, RPCTLSCDVERS, rpctlscd_1, NULL)) {
277 if (rpctls_debug_level == 0) {
278 syslog(LOG_ERR,
279 "Can't register service for local rpctlscd socket");
280 exit(1);
281 }
282 err(1, "Can't register service for local rpctlscd socket");
283 }
284
285 if (rpctls_syscall(RPCTLS_SYSC_CLSETPATH, _PATH_RPCTLSCDSOCK) < 0) {
286 if (rpctls_debug_level == 0) {
287 syslog(LOG_ERR,
288 "Can't set upcall socket path errno=%d", errno);
289 exit(1);
290 }
291 err(1, "Can't set upcall socket path");
292 }
293
294 rpctls_svc_run();
295
296 rpctls_syscall(RPCTLS_SYSC_CLSHUTDOWN, "");
297
298 SSL_CTX_free(rpctls_ctx);
299 return (0);
300 }
301
302 bool_t
rpctlscd_null_1_svc(__unused void * argp,__unused void * result,__unused struct svc_req * rqstp)303 rpctlscd_null_1_svc(__unused void *argp, __unused void *result,
304 __unused struct svc_req *rqstp)
305 {
306
307 rpctls_verbose_out("rpctlscd_null: done\n");
308 return (TRUE);
309 }
310
311 bool_t
rpctlscd_connect_1_svc(struct rpctlscd_connect_arg * argp,struct rpctlscd_connect_res * result,__unused struct svc_req * rqstp)312 rpctlscd_connect_1_svc(struct rpctlscd_connect_arg *argp,
313 struct rpctlscd_connect_res *result, __unused struct svc_req *rqstp)
314 {
315 int s;
316 SSL *ssl;
317 struct ssl_entry *newslp;
318 X509 *cert;
319
320 rpctls_verbose_out("rpctlsd_connect: started\n");
321 /* Get the socket fd from the kernel. */
322 s = rpctls_syscall(RPCTLS_SYSC_CLSOCKET, "");
323 if (s < 0) {
324 result->reterr = RPCTLSERR_NOSOCKET;
325 return (TRUE);
326 }
327
328 /* Do a TLS connect handshake. */
329 ssl = rpctls_connect(rpctls_ctx, s, argp->certname.certname_val,
330 argp->certname.certname_len, &cert);
331 if (ssl == NULL) {
332 rpctls_verbose_out("rpctlsd_connect: can't do TLS "
333 "handshake\n");
334 result->reterr = RPCTLSERR_NOSSL;
335 } else {
336 result->reterr = RPCTLSERR_OK;
337 result->sec = rpctls_ssl_sec;
338 result->usec = rpctls_ssl_usec;
339 result->ssl = ++rpctls_ssl_refno;
340 /* Hard to believe this will ever wrap around.. */
341 if (rpctls_ssl_refno == 0)
342 result->ssl = ++rpctls_ssl_refno;
343 }
344
345 if (ssl == NULL) {
346 /*
347 * For RPC-over-TLS, this upcall is expected
348 * to close off the socket.
349 */
350 close(s);
351 return (TRUE);
352 }
353
354 /* Maintain list of all current SSL *'s */
355 newslp = malloc(sizeof(*newslp));
356 newslp->refno = rpctls_ssl_refno;
357 newslp->s = s;
358 newslp->shutoff = false;
359 newslp->ssl = ssl;
360 newslp->cert = cert;
361 LIST_INSERT_HEAD(&rpctls_ssllist, newslp, next);
362 return (TRUE);
363 }
364
365 bool_t
rpctlscd_handlerecord_1_svc(struct rpctlscd_handlerecord_arg * argp,struct rpctlscd_handlerecord_res * result,__unused struct svc_req * rqstp)366 rpctlscd_handlerecord_1_svc(struct rpctlscd_handlerecord_arg *argp,
367 struct rpctlscd_handlerecord_res *result, __unused struct svc_req *rqstp)
368 {
369 struct ssl_entry *slp;
370 int ret;
371 char junk;
372
373 slp = NULL;
374 if (argp->sec == rpctls_ssl_sec && argp->usec ==
375 rpctls_ssl_usec) {
376 LIST_FOREACH(slp, &rpctls_ssllist, next) {
377 if (slp->refno == argp->ssl)
378 break;
379 }
380 }
381
382 if (slp != NULL) {
383 rpctls_verbose_out("rpctlscd_handlerecord fd=%d\n",
384 slp->s);
385 /*
386 * An SSL_read() of 0 bytes should fail, but it should
387 * handle the non-application data record before doing so.
388 */
389 ret = SSL_read(slp->ssl, &junk, 0);
390 if (ret <= 0) {
391 /* Check to see if this was a close alert. */
392 ret = SSL_get_shutdown(slp->ssl);
393 if ((ret & (SSL_SENT_SHUTDOWN |
394 SSL_RECEIVED_SHUTDOWN)) == SSL_RECEIVED_SHUTDOWN)
395 SSL_shutdown(slp->ssl);
396 } else {
397 if (rpctls_debug_level == 0)
398 syslog(LOG_ERR, "SSL_read returned %d", ret);
399 else
400 fprintf(stderr, "SSL_read returned %d\n", ret);
401 }
402 result->reterr = RPCTLSERR_OK;
403 } else
404 result->reterr = RPCTLSERR_NOSSL;
405 return (TRUE);
406 }
407
408 bool_t
rpctlscd_disconnect_1_svc(struct rpctlscd_disconnect_arg * argp,struct rpctlscd_disconnect_res * result,__unused struct svc_req * rqstp)409 rpctlscd_disconnect_1_svc(struct rpctlscd_disconnect_arg *argp,
410 struct rpctlscd_disconnect_res *result, __unused struct svc_req *rqstp)
411 {
412 struct ssl_entry *slp;
413 int ret;
414
415 slp = NULL;
416 if (argp->sec == rpctls_ssl_sec && argp->usec ==
417 rpctls_ssl_usec) {
418 LIST_FOREACH(slp, &rpctls_ssllist, next) {
419 if (slp->refno == argp->ssl)
420 break;
421 }
422 }
423
424 if (slp != NULL) {
425 rpctls_verbose_out("rpctlscd_disconnect: fd=%d closed\n",
426 slp->s);
427 LIST_REMOVE(slp, next);
428 if (!slp->shutoff) {
429 ret = SSL_get_shutdown(slp->ssl);
430 /*
431 * Do an SSL_shutdown() unless a close alert has
432 * already been sent.
433 */
434 if ((ret & SSL_SENT_SHUTDOWN) == 0)
435 SSL_shutdown(slp->ssl);
436 }
437 SSL_free(slp->ssl);
438 if (slp->cert != NULL)
439 X509_free(slp->cert);
440 /*
441 * For RPC-over-TLS, this upcall is expected
442 * to close off the socket.
443 */
444 if (!slp->shutoff)
445 shutdown(slp->s, SHUT_WR);
446 close(slp->s);
447 free(slp);
448 result->reterr = RPCTLSERR_OK;
449 } else
450 result->reterr = RPCTLSERR_NOCLOSE;
451 return (TRUE);
452 }
453
454 int
rpctlscd_1_freeresult(__unused SVCXPRT * transp,__unused xdrproc_t xdr_result,__unused caddr_t result)455 rpctlscd_1_freeresult(__unused SVCXPRT *transp, __unused xdrproc_t xdr_result,
456 __unused caddr_t result)
457 {
458
459 return (TRUE);
460 }
461
462 static void
rpctlscd_terminate(int sig __unused)463 rpctlscd_terminate(int sig __unused)
464 {
465
466 rpctls_syscall(RPCTLS_SYSC_CLSHUTDOWN, "");
467 pidfile_remove(rpctls_pfh);
468 exit(0);
469 }
470
471 static SSL_CTX *
rpctls_setupcl_ssl(void)472 rpctls_setupcl_ssl(void)
473 {
474 SSL_CTX *ctx;
475 char path[PATH_MAX];
476 size_t len, rlen;
477 int ret;
478
479 ctx = SSL_CTX_new(TLS_client_method());
480 if (ctx == NULL) {
481 rpctls_verbose_out("rpctls_setupcl_ssl: SSL_CTX_new "
482 "failed\n");
483 return (NULL);
484 }
485
486 if (rpctls_ciphers != NULL) {
487 /*
488 * Set available ciphers, since KERN_TLS only supports a
489 * few of them.
490 */
491 ret = SSL_CTX_set_ciphersuites(ctx, rpctls_ciphers);
492 if (ret == 0) {
493 rpctls_verbose_out("rpctls_setupcl_ssl: "
494 "SSL_CTX_set_ciphersuites failed: %s\n",
495 rpctls_ciphers);
496 SSL_CTX_free(ctx);
497 return (NULL);
498 }
499 }
500
501 /*
502 * If rpctls_cert is true, a certificate and key exists in
503 * rpctls_certdir, so that it can do mutual authentication.
504 */
505 if (rpctls_cert) {
506 /* Get the cert.pem and certkey.pem files. */
507 len = strlcpy(path, rpctls_certdir, sizeof(path));
508 rlen = sizeof(path) - len;
509 if (strlcpy(&path[len], "cert.pem", rlen) != 8) {
510 SSL_CTX_free(ctx);
511 return (NULL);
512 }
513 ret = SSL_CTX_use_certificate_file(ctx, path,
514 SSL_FILETYPE_PEM);
515 if (ret != 1) {
516 rpctls_verbose_out("rpctls_setupcl_ssl: can't use "
517 "certificate file path=%s ret=%d\n", path, ret);
518 SSL_CTX_free(ctx);
519 return (NULL);
520 }
521 if (strlcpy(&path[len], "certkey.pem", rlen) != 11) {
522 SSL_CTX_free(ctx);
523 return (NULL);
524 }
525 ret = SSL_CTX_use_PrivateKey_file(ctx, path,
526 SSL_FILETYPE_PEM);
527 if (ret != 1) {
528 rpctls_verbose_out("rpctls_setupcl_ssl: Can't use "
529 "private key path=%s ret=%d\n", path, ret);
530 SSL_CTX_free(ctx);
531 return (NULL);
532 }
533 }
534
535 if (rpctls_verify_cafile != NULL || rpctls_verify_capath != NULL) {
536 if (rpctls_crlfile != NULL) {
537 ret = rpctls_loadcrlfile(ctx);
538 if (ret == 0) {
539 rpctls_verbose_out("rpctls_setupcl_ssl: "
540 "Load CRLfile failed\n");
541 SSL_CTX_free(ctx);
542 return (NULL);
543 }
544 }
545 #if OPENSSL_VERSION_NUMBER >= 0x30000000
546 ret = 1;
547 if (rpctls_verify_cafile != NULL)
548 ret = SSL_CTX_load_verify_file(ctx,
549 rpctls_verify_cafile);
550 if (ret != 0 && rpctls_verify_capath != NULL)
551 ret = SSL_CTX_load_verify_dir(ctx,
552 rpctls_verify_capath);
553 #else
554 ret = SSL_CTX_load_verify_locations(ctx,
555 rpctls_verify_cafile, rpctls_verify_capath);
556 #endif
557 if (ret == 0) {
558 rpctls_verbose_out("rpctls_setupcl_ssl: "
559 "Can't load verify locations\n");
560 SSL_CTX_free(ctx);
561 return (NULL);
562 }
563 /*
564 * The man page says that the
565 * SSL_CTX_set0_CA_list() call is not normally
566 * needed, but I believe it is harmless.
567 */
568 if (rpctls_verify_cafile != NULL)
569 SSL_CTX_set0_CA_list(ctx,
570 SSL_load_client_CA_file(rpctls_verify_cafile));
571 }
572
573 /*
574 * The RFC specifies that RPC-over-TLS must use TLS1.3.
575 * However, early FreeBSD versions (13.0, 13.1) did not
576 * support RX for KTLS1.3, so TLS1.2 needs to be used for
577 * these servers.
578 */
579 ret = SSL_CTX_set_min_proto_version(ctx, rpctls_tlsvers);
580 if (ret == 0) {
581 rpctls_verbose_out("rpctls_setupcl_ssl: "
582 "SSL_CTX_set_min_proto_version failed\n");
583 SSL_CTX_free(ctx);
584 return (NULL);
585 }
586 ret = SSL_CTX_set_max_proto_version(ctx, rpctls_tlsvers);
587 if (ret == 0) {
588 rpctls_verbose_out("rpctls_setupcl_ssl: "
589 "SSL_CTX_set_max_proto_version failed\n");
590 SSL_CTX_free(ctx);
591 return (NULL);
592 }
593
594 #ifdef SSL_OP_ENABLE_KTLS
595 SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS);
596 #endif
597 #ifdef SSL_MODE_NO_KTLS_TX
598 SSL_CTX_clear_mode(ctx, SSL_MODE_NO_KTLS_TX | SSL_MODE_NO_KTLS_RX);
599 #endif
600 return (ctx);
601 }
602
603 static SSL *
rpctls_connect(SSL_CTX * ctx,int s,char * certname,u_int certlen,X509 ** certp)604 rpctls_connect(SSL_CTX *ctx, int s, char *certname, u_int certlen, X509 **certp)
605 {
606 SSL *ssl;
607 X509 *cert;
608 struct sockaddr_storage ad;
609 struct sockaddr *sad;
610 char hostnam[NI_MAXHOST], path[PATH_MAX];
611 int gethostret, ret;
612 char *cp, *cp2;
613 size_t len, rlen;
614 long verfret;
615
616 *certp = NULL;
617 sad = (struct sockaddr *)&ad;
618 ssl = SSL_new(ctx);
619 if (ssl == NULL) {
620 rpctls_verbose_out("rpctls_connect: "
621 "SSL_new failed\n");
622 return (NULL);
623 }
624 if (SSL_set_fd(ssl, s) != 1) {
625 rpctls_verbose_out("rpctls_connect: "
626 "SSL_set_fd failed\n");
627 SSL_free(ssl);
628 return (NULL);
629 }
630
631 /*
632 * If rpctls_cert is true and certname is set, a alternate certificate
633 * and key exists in files named <certname>.pem and <certname>key.pem
634 * in rpctls_certdir that is to be used for mutual authentication.
635 */
636 if (rpctls_cert && certlen > 0) {
637 len = strlcpy(path, rpctls_certdir, sizeof(path));
638 rlen = sizeof(path) - len;
639 if (rlen <= certlen) {
640 SSL_free(ssl);
641 return (NULL);
642 }
643 memcpy(&path[len], certname, certlen);
644 rlen -= certlen;
645 len += certlen;
646 path[len] = '\0';
647 if (strlcpy(&path[len], ".pem", rlen) != 4) {
648 SSL_free(ssl);
649 return (NULL);
650 }
651 ret = SSL_use_certificate_file(ssl, path, SSL_FILETYPE_PEM);
652 if (ret != 1) {
653 rpctls_verbose_out("rpctls_connect: can't use "
654 "certificate file path=%s ret=%d\n", path, ret);
655 SSL_free(ssl);
656 return (NULL);
657 }
658 if (strlcpy(&path[len], "key.pem", rlen) != 7) {
659 SSL_free(ssl);
660 return (NULL);
661 }
662 ret = SSL_use_PrivateKey_file(ssl, path, SSL_FILETYPE_PEM);
663 if (ret != 1) {
664 rpctls_verbose_out("rpctls_connect: Can't use "
665 "private key path=%s ret=%d\n", path, ret);
666 SSL_free(ssl);
667 return (NULL);
668 }
669 }
670
671 ret = SSL_connect(ssl);
672 if (ret != 1) {
673 rpctls_verbose_out("rpctls_connect: "
674 "SSL_connect failed %d: %s\n",
675 ret, ERR_error_string(ERR_get_error(), NULL));
676 SSL_free(ssl);
677 return (NULL);
678 }
679
680 #if OPENSSL_VERSION_NUMBER >= 0x30000000
681 cert = SSL_get1_peer_certificate(ssl);
682 #else
683 cert = SSL_get_peer_certificate(ssl);
684 #endif
685 if (cert == NULL) {
686 rpctls_verbose_out("rpctls_connect: get peer"
687 " certificate failed\n");
688 SSL_free(ssl);
689 return (NULL);
690 }
691 gethostret = rpctls_gethost(s, sad, hostnam, sizeof(hostnam));
692 if (gethostret == 0)
693 hostnam[0] = '\0';
694 verfret = SSL_get_verify_result(ssl);
695 if (verfret == X509_V_OK && (rpctls_verify_cafile != NULL ||
696 rpctls_verify_capath != NULL) && (gethostret == 0 ||
697 rpctls_checkhost(sad, cert, X509_CHECK_FLAG_NO_WILDCARDS) != 1))
698 verfret = X509_V_ERR_HOSTNAME_MISMATCH;
699 if (verfret != X509_V_OK && (rpctls_verify_cafile != NULL ||
700 rpctls_verify_capath != NULL)) {
701 if (verfret != X509_V_OK) {
702 cp = X509_NAME_oneline(X509_get_issuer_name(cert),
703 NULL, 0);
704 cp2 = X509_NAME_oneline(X509_get_subject_name(cert),
705 NULL, 0);
706 if (rpctls_debug_level == 0)
707 syslog(LOG_INFO | LOG_DAEMON,
708 "rpctls_connect: client IP %s "
709 "issuerName=%s subjectName=%s verify "
710 "failed %s\n", hostnam, cp, cp2,
711 X509_verify_cert_error_string(verfret));
712 else
713 fprintf(stderr,
714 "rpctls_connect: client IP %s "
715 "issuerName=%s subjectName=%s verify "
716 "failed %s\n", hostnam, cp, cp2,
717 X509_verify_cert_error_string(verfret));
718 }
719 X509_free(cert);
720 SSL_free(ssl);
721 return (NULL);
722 }
723
724 /* Check to see if ktls is enabled on the connection. */
725 ret = BIO_get_ktls_send(SSL_get_wbio(ssl));
726 rpctls_verbose_out("rpctls_connect: BIO_get_ktls_send=%d\n", ret);
727 if (ret != 0) {
728 ret = BIO_get_ktls_recv(SSL_get_rbio(ssl));
729 rpctls_verbose_out("rpctls_connect: BIO_get_ktls_recv=%d\n",
730 ret);
731 }
732 if (ret == 0) {
733 if (rpctls_debug_level == 0)
734 syslog(LOG_ERR, "ktls not working\n");
735 else
736 fprintf(stderr, "ktls not working\n");
737 X509_free(cert);
738 SSL_free(ssl);
739 return (NULL);
740 }
741 if (ret == X509_V_OK && (rpctls_verify_cafile != NULL ||
742 rpctls_verify_capath != NULL) && rpctls_crlfile != NULL)
743 *certp = cert;
744 else
745 X509_free(cert);
746
747 return (ssl);
748 }
749
750 static void
rpctls_huphandler(int sig __unused)751 rpctls_huphandler(int sig __unused)
752 {
753
754 rpctls_gothup = true;
755 }
756