]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rpc.tlsservd/rpc.tlsservd.c
unbound: Vendor import 1.16.3
[FreeBSD/FreeBSD.git] / usr.sbin / rpc.tlsservd / rpc.tlsservd.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 server side of kernel RPC-over-TLS by Rick Macklem.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/linker.h>
41 #include <sys/module.h>
42 #include <sys/queue.h>
43 #include <sys/stat.h>
44 #include <sys/sysctl.h>
45 #include <sys/syslog.h>
46 #include <sys/time.h>
47 #include <err.h>
48 #include <getopt.h>
49 #include <libutil.h>
50 #include <netdb.h>
51 #include <pwd.h>
52 #include <signal.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <stdbool.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 #include <rpc/rpc.h>
61 #include <rpc/rpc_com.h>
62 #include <rpc/rpcsec_tls.h>
63
64 #include <openssl/opensslconf.h>
65 #include <openssl/bio.h>
66 #include <openssl/ssl.h>
67 #include <openssl/err.h>
68 #include <openssl/x509v3.h>
69
70 #include "rpctlssd.h"
71 #include "rpc.tlscommon.h"
72
73 #ifndef _PATH_RPCTLSSDSOCK
74 #define _PATH_RPCTLSSDSOCK      "/var/run/rpc.tlsservd.sock"
75 #endif
76 #ifndef _PATH_CERTANDKEY
77 #define _PATH_CERTANDKEY        "/etc/rpc.tlsservd/"
78 #endif
79 #ifndef _PATH_RPCTLSSDPID
80 #define _PATH_RPCTLSSDPID       "/var/run/rpc.tlsservd.pid"
81 #endif
82 #ifndef _PREFERRED_CIPHERS
83 #define _PREFERRED_CIPHERS      "AES128-GCM-SHA256"
84 #endif
85
86 /* Global variables also used by rpc.tlscommon.c. */
87 int                     rpctls_debug_level;
88 bool                    rpctls_verbose;
89 SSL_CTX                 *rpctls_ctx = NULL;
90 const char              *rpctls_verify_cafile = NULL;
91 const char              *rpctls_verify_capath = NULL;
92 char                    *rpctls_crlfile = NULL;
93 bool                    rpctls_gothup = false;
94 struct ssl_list         rpctls_ssllist;
95
96 static struct pidfh     *rpctls_pfh = NULL;
97 static bool             rpctls_do_mutual = false;
98 static const char       *rpctls_certdir = _PATH_CERTANDKEY;
99 static bool             rpctls_comparehost = false;
100 static unsigned int     rpctls_wildcard = X509_CHECK_FLAG_NO_WILDCARDS;
101 static uint64_t         rpctls_ssl_refno = 0;
102 static uint64_t         rpctls_ssl_sec = 0;
103 static uint64_t         rpctls_ssl_usec = 0;
104 static bool             rpctls_cnuser = false;
105 static char             *rpctls_dnsname;
106 static const char       *rpctls_cnuseroid = "1.3.6.1.4.1.2238.1.1.1";
107 static const char       *rpctls_ciphers = NULL;
108 static int              rpctls_mintls = TLS1_3_VERSION;
109
110 static void             rpctlssd_terminate(int);
111 static SSL_CTX          *rpctls_setup_ssl(const char *certdir);
112 static SSL              *rpctls_server(SSL_CTX *ctx, int s,
113                             uint32_t *flags, uint32_t *uidp,
114                             int *ngrps, uint32_t *gidp, X509 **certp);
115 static int              rpctls_cnname(X509 *cert, uint32_t *uidp,
116                             int *ngrps, uint32_t *gidp);
117 static char             *rpctls_getdnsname(char *dnsname);
118 static void             rpctls_huphandler(int sig __unused);
119
120 extern void             rpctlssd_1(struct svc_req *rqstp, SVCXPRT *transp);
121
122 static struct option longopts[] = {
123         { "allowtls1_2",        no_argument,            NULL,   '2' },
124         { "ciphers",            required_argument,      NULL,   'C' },
125         { "certdir",            required_argument,      NULL,   'D' },
126         { "debuglevel",         no_argument,            NULL,   'd' },
127         { "checkhost",          no_argument,            NULL,   'h' },
128         { "verifylocs",         required_argument,      NULL,   'l' },
129         { "mutualverf",         no_argument,            NULL,   'm' },
130         { "domain",             required_argument,      NULL,   'n' },
131         { "verifydir",          required_argument,      NULL,   'p' },
132         { "crl",                required_argument,      NULL,   'r' },
133         { "certuser",           no_argument,            NULL,   'u' },
134         { "verbose",            no_argument,            NULL,   'v' },
135         { "multiwild",          no_argument,            NULL,   'W' },
136         { "singlewild",         no_argument,            NULL,   'w' },
137         { NULL,                 0,                      NULL,   0  }
138 };
139
140 int
141 main(int argc, char **argv)
142 {
143         /*
144          * We provide an RPC service on a local-domain socket. The
145          * kernel rpctls code will upcall to this daemon to do the initial
146          * TLS handshake.
147          */
148         struct sockaddr_un sun;
149         int ch, fd, oldmask;
150         SVCXPRT *xprt;
151         struct timeval tm;
152         struct timezone tz;
153         char hostname[MAXHOSTNAMELEN + 2];
154         pid_t otherpid;
155         bool tls_enable;
156         size_t tls_enable_len;
157
158         /* Check that another rpctlssd isn't already running. */
159         rpctls_pfh = pidfile_open(_PATH_RPCTLSSDPID, 0600, &otherpid);
160         if (rpctls_pfh == NULL) {
161                 if (errno == EEXIST)
162                         errx(1, "rpctlssd already running, pid: %d.", otherpid);
163                 warn("cannot open or create pidfile");
164         }
165
166         /* Check to see that the ktls is enabled. */
167         tls_enable_len = sizeof(tls_enable);
168         if (sysctlbyname("kern.ipc.tls.enable", &tls_enable, &tls_enable_len,
169             NULL, 0) != 0 || !tls_enable)
170                 errx(1, "Kernel TLS not enabled");
171
172         /* Get the time when this daemon is started. */
173         gettimeofday(&tm, &tz);
174         rpctls_ssl_sec = tm.tv_sec;
175         rpctls_ssl_usec = tm.tv_usec;
176
177         /* Set the dns name for the server. */
178         rpctls_dnsname = rpctls_getdnsname(hostname);
179         if (rpctls_dnsname == NULL) {
180                 strcpy(hostname, "@default.domain");
181                 rpctls_dnsname = hostname;
182         }
183
184         rpctls_verbose = false;
185         while ((ch = getopt_long(argc, argv, "2C:D:dhl:n:mp:r:uvWw", longopts,
186             NULL)) != -1) {
187                 switch (ch) {
188                 case '2':
189                         rpctls_mintls = TLS1_2_VERSION;
190                         break;
191                 case 'C':
192                         rpctls_ciphers = optarg;
193                         break;
194                 case 'D':
195                         rpctls_certdir = optarg;
196                         break;
197                 case 'd':
198                         rpctls_debug_level++;
199                         break;
200                 case 'h':
201                         rpctls_comparehost = true;
202                         break;
203                 case 'l':
204                         rpctls_verify_cafile = optarg;
205                         break;
206                 case 'm':
207                         rpctls_do_mutual = true;
208                         break;
209                 case 'n':
210                         hostname[0] = '@';
211                         strlcpy(&hostname[1], optarg, MAXHOSTNAMELEN + 1);
212                         rpctls_dnsname = hostname;
213                         break;
214                 case 'p':
215                         rpctls_verify_capath = optarg;
216                         break;
217                 case 'r':
218                         rpctls_crlfile = optarg;
219                         break;
220                 case 'u':
221                         rpctls_cnuser = true;
222                         break;
223                 case 'v':
224                         rpctls_verbose = true;
225                         break;
226                 case 'W':
227                         if (rpctls_wildcard != X509_CHECK_FLAG_NO_WILDCARDS)
228                                 errx(1, "options -w and -W are mutually "
229                                     "exclusive");
230                         rpctls_wildcard = X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS;
231                         break;
232                 case 'w':
233                         if (rpctls_wildcard != X509_CHECK_FLAG_NO_WILDCARDS)
234                                 errx(1, "options -w and -W are mutually "
235                                     "exclusive");
236                         rpctls_wildcard = 0;
237                         break;
238                 default:
239                         fprintf(stderr, "usage: %s "
240                             "[-2/--allowtls1_2] "
241                             "[-C/--ciphers available_ciphers] "
242                             "[-D/--certdir certdir] [-d/--debuglevel] "
243                             "[-h/--checkhost] "
244                             "[-l/--verifylocs CAfile] [-m/--mutualverf] "
245                             "[-n/--domain domain_name] "
246                             "[-p/--verifydir CApath] [-r/--crl CRLfile] "
247                             "[-u/--certuser] [-v/--verbose] [-W/--multiwild] "
248                             "[-w/--singlewild]\n", argv[0]);
249                         exit(1);
250                 }
251         }
252         if (rpctls_do_mutual && rpctls_verify_cafile == NULL &&
253             rpctls_verify_capath == NULL)
254                 errx(1, "-m requires the -l <CAfile> and/or "
255                     "-p <CApath> options");
256         if (rpctls_comparehost && (!rpctls_do_mutual ||
257             (rpctls_verify_cafile == NULL && rpctls_verify_capath == NULL)))
258                 errx(1, "-h requires the -m plus the "
259                     "-l <CAfile> and/or -p <CApath> options");
260         if (!rpctls_comparehost && rpctls_wildcard !=
261             X509_CHECK_FLAG_NO_WILDCARDS)
262                 errx(1, "The -w or -W options require the -h option");
263         if (rpctls_cnuser && (!rpctls_do_mutual ||
264             (rpctls_verify_cafile == NULL && rpctls_verify_capath == NULL)))
265                 errx(1, "-u requires the -m plus the "
266                     "-l <CAfile> and/or -p <CApath> options");
267
268         if (modfind("krpc") < 0) {
269                 /* Not present in kernel, try loading it */
270                 if (kldload("krpc") < 0 || modfind("krpc") < 0)
271                         errx(1, "Kernel RPC is not available");
272         }
273
274         if (rpctls_debug_level == 0) {
275                 if (daemon(0, 0) != 0)
276                         err(1, "Can't daemonize");
277                 signal(SIGINT, SIG_IGN);
278                 signal(SIGQUIT, SIG_IGN);
279                 signal(SIGHUP, SIG_IGN);
280         }
281         signal(SIGTERM, rpctlssd_terminate);
282         signal(SIGPIPE, SIG_IGN);
283         signal(SIGHUP, rpctls_huphandler);
284
285         pidfile_write(rpctls_pfh);
286
287         memset(&sun, 0, sizeof sun);
288         sun.sun_family = AF_LOCAL;
289         unlink(_PATH_RPCTLSSDSOCK);
290         strcpy(sun.sun_path, _PATH_RPCTLSSDSOCK);
291         sun.sun_len = SUN_LEN(&sun);
292         fd = socket(AF_LOCAL, SOCK_STREAM, 0);
293         if (fd < 0) {
294                 if (rpctls_debug_level == 0) {
295                         syslog(LOG_ERR, "Can't create local rpctlssd socket");
296                         exit(1);
297                 }
298                 err(1, "Can't create local rpctlssd socket");
299         }
300         oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
301         if (bind(fd, (struct sockaddr *)&sun, sun.sun_len) < 0) {
302                 if (rpctls_debug_level == 0) {
303                         syslog(LOG_ERR, "Can't bind local rpctlssd socket");
304                         exit(1);
305                 }
306                 err(1, "Can't bind local rpctlssd socket");
307         }
308         umask(oldmask);
309         if (listen(fd, SOMAXCONN) < 0) {
310                 if (rpctls_debug_level == 0) {
311                         syslog(LOG_ERR,
312                             "Can't listen on local rpctlssd socket");
313                         exit(1);
314                 }
315                 err(1, "Can't listen on local rpctlssd socket");
316         }
317         xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
318         if (!xprt) {
319                 if (rpctls_debug_level == 0) {
320                         syslog(LOG_ERR,
321                             "Can't create transport for local rpctlssd socket");
322                         exit(1);
323                 }
324                 err(1, "Can't create transport for local rpctlssd socket");
325         }
326         if (!svc_reg(xprt, RPCTLSSD, RPCTLSSDVERS, rpctlssd_1, NULL)) {
327                 if (rpctls_debug_level == 0) {
328                         syslog(LOG_ERR,
329                             "Can't register service for local rpctlssd socket");
330                         exit(1);
331                 }
332                 err(1, "Can't register service for local rpctlssd socket");
333         }
334
335         rpctls_ctx = rpctls_setup_ssl(rpctls_certdir);
336         if (rpctls_ctx == NULL) {
337                 if (rpctls_debug_level == 0) {
338                         syslog(LOG_ERR, "Can't create SSL context");
339                         exit(1);
340                 }
341                 err(1, "Can't create SSL context");
342         }
343         rpctls_gothup = false;
344         LIST_INIT(&rpctls_ssllist);
345
346         rpctls_syscall(RPCTLS_SYSC_SRVSETPATH, _PATH_RPCTLSSDSOCK);
347
348         rpctls_svc_run();
349
350         rpctls_syscall(RPCTLS_SYSC_SRVSHUTDOWN, "");
351
352         SSL_CTX_free(rpctls_ctx);
353         EVP_cleanup();
354         return (0);
355 }
356
357 bool_t
358 rpctlssd_null_1_svc(__unused void *argp, __unused void *result,
359     __unused struct svc_req *rqstp)
360 {
361
362         rpctls_verbose_out("rpctlssd_null_svc: done\n");
363         return (TRUE);
364 }
365
366 bool_t
367 rpctlssd_connect_1_svc(__unused void *argp,
368     struct rpctlssd_connect_res *result, __unused struct svc_req *rqstp)
369 {
370         int ngrps, s;
371         SSL *ssl;
372         uint32_t flags;
373         struct ssl_entry *newslp;
374         uint32_t uid;
375         uint32_t *gidp;
376         X509 *cert;
377
378         rpctls_verbose_out("rpctlsd_connect_svc: started\n");
379         memset(result, 0, sizeof(*result));
380         /* Get the socket fd from the kernel. */
381         s = rpctls_syscall(RPCTLS_SYSC_SRVSOCKET, "");
382         if (s < 0)
383                 return (FALSE);
384
385         /* Do the server side of a TLS handshake. */
386         gidp = calloc(NGROUPS, sizeof(*gidp));
387         ssl = rpctls_server(rpctls_ctx, s, &flags, &uid, &ngrps, gidp, &cert);
388         if (ssl == NULL) {
389                 free(gidp);
390                 rpctls_verbose_out("rpctlssd_connect_svc: ssl "
391                     "accept failed\n");
392                 /*
393                  * For RPC-over-TLS, this upcall is expected
394                  * to close off the socket upon handshake failure.
395                  */
396                 close(s);
397                 return (FALSE);
398         } else {
399                 rpctls_verbose_out("rpctlssd_connect_svc: "
400                     "succeeded flags=0x%x\n", flags);
401                 result->flags = flags;
402                 result->sec = rpctls_ssl_sec;
403                 result->usec = rpctls_ssl_usec;
404                 result->ssl = ++rpctls_ssl_refno;
405                 /* Hard to believe this could ever wrap around.. */
406                 if (rpctls_ssl_refno == 0)
407                         result->ssl = ++rpctls_ssl_refno;
408                 if ((flags & RPCTLS_FLAGS_CERTUSER) != 0) {
409                         result->uid = uid;
410                         result->gid.gid_len = ngrps;
411                         result->gid.gid_val = gidp;
412                 } else {
413                         result->uid = 0;
414                         result->gid.gid_len = 0;
415                         result->gid.gid_val = gidp;
416                 }
417         }
418
419         /* Maintain list of all current SSL *'s */
420         newslp = malloc(sizeof(*newslp));
421         newslp->ssl = ssl;
422         newslp->s = s;
423         newslp->shutoff = false;
424         newslp->refno = rpctls_ssl_refno;
425         newslp->cert = cert;
426         LIST_INSERT_HEAD(&rpctls_ssllist, newslp, next);
427         return (TRUE);
428 }
429
430 bool_t
431 rpctlssd_handlerecord_1_svc(struct rpctlssd_handlerecord_arg *argp,
432     struct rpctlssd_handlerecord_res *result, __unused struct svc_req *rqstp)
433 {
434         struct ssl_entry *slp;
435         int ret;
436         char junk;
437
438         slp = NULL;
439         if (argp->sec == rpctls_ssl_sec && argp->usec ==
440             rpctls_ssl_usec) {
441                 LIST_FOREACH(slp, &rpctls_ssllist, next) {
442                         if (slp->refno == argp->ssl)
443                                 break;
444                 }
445         }
446
447         if (slp != NULL) {
448                 rpctls_verbose_out("rpctlssd_handlerecord fd=%d\n",
449                     slp->s);
450                 /*
451                  * An SSL_read() of 0 bytes should fail, but it should
452                  * handle the non-application data record before doing so.
453                  */
454                 ret = SSL_read(slp->ssl, &junk, 0);
455                 if (ret <= 0) {
456                         /* Check to see if this was a close alert. */
457                         ret = SSL_get_shutdown(slp->ssl);
458                         if ((ret & (SSL_SENT_SHUTDOWN |
459                             SSL_RECEIVED_SHUTDOWN)) == SSL_RECEIVED_SHUTDOWN)
460                                 SSL_shutdown(slp->ssl);
461                 } else {
462                         if (rpctls_debug_level == 0)
463                                 syslog(LOG_ERR, "SSL_read returned %d", ret);
464                         else
465                                 fprintf(stderr, "SSL_read returned %d\n", ret);
466                 }
467                 result->reterr = RPCTLSERR_OK;
468         } else
469                 result->reterr = RPCTLSERR_NOSSL;
470         return (TRUE);
471 }
472
473 bool_t
474 rpctlssd_disconnect_1_svc(struct rpctlssd_disconnect_arg *argp,
475     struct rpctlssd_disconnect_res *result, __unused struct svc_req *rqstp)
476 {
477         struct ssl_entry *slp;
478         int ret;
479
480         slp = NULL;
481         if (argp->sec == rpctls_ssl_sec && argp->usec ==
482             rpctls_ssl_usec) {
483                 LIST_FOREACH(slp, &rpctls_ssllist, next) {
484                         if (slp->refno == argp->ssl)
485                                 break;
486                 }
487         }
488
489         if (slp != NULL) {
490                 rpctls_verbose_out("rpctlssd_disconnect fd=%d closed\n",
491                     slp->s);
492                 LIST_REMOVE(slp, next);
493                 if (!slp->shutoff) {
494                         ret = SSL_get_shutdown(slp->ssl);
495                         /*
496                          * Do an SSL_shutdown() unless a close alert has
497                          * already been sent.
498                          */
499                         if ((ret & SSL_SENT_SHUTDOWN) == 0)
500                                 SSL_shutdown(slp->ssl);
501                 }
502                 SSL_free(slp->ssl);
503                 if (slp->cert != NULL)
504                         X509_free(slp->cert);
505                 /*
506                  * For RPC-over-TLS, this upcall is expected
507                  * to close off the socket.
508                  */
509                 if (!slp->shutoff)
510                         shutdown(slp->s, SHUT_WR);
511                 close(slp->s);
512                 free(slp);
513                 result->reterr = RPCTLSERR_OK;
514         } else
515                 result->reterr = RPCTLSERR_NOCLOSE;
516         return (TRUE);
517 }
518
519 int
520 rpctlssd_1_freeresult(__unused SVCXPRT *transp, xdrproc_t xdr_result,
521     caddr_t result)
522 {
523         rpctlssd_connect_res *res;
524
525         if (xdr_result == (xdrproc_t)xdr_rpctlssd_connect_res) {
526                 res = (rpctlssd_connect_res *)(void *)result;
527                 free(res->gid.gid_val);
528         }
529         return (TRUE);
530 }
531
532 static void
533 rpctlssd_terminate(int sig __unused)
534 {
535         struct ssl_entry *slp;
536
537         rpctls_syscall(RPCTLS_SYSC_SRVSHUTDOWN, "");
538         pidfile_remove(rpctls_pfh);
539
540         LIST_FOREACH(slp, &rpctls_ssllist, next)
541                 shutdown(slp->s, SHUT_RD);
542         exit(0);
543 }
544
545 /* Allow the handshake to proceed. */
546 static int
547 rpctls_verify_callback(__unused int preverify_ok,
548     __unused X509_STORE_CTX *x509_ctx)
549 {
550
551         return (1);
552 }
553
554 static SSL_CTX *
555 rpctls_setup_ssl(const char *certdir)
556 {
557         SSL_CTX *ctx;
558         char path[PATH_MAX];
559         size_t len, rlen;
560         int ret;
561
562         SSL_library_init();
563         SSL_load_error_strings();
564         OpenSSL_add_all_algorithms();
565
566         ctx = SSL_CTX_new(TLS_server_method());
567         if (ctx == NULL) {
568                 rpctls_verbose_out("rpctls_setup_ssl: SSL_CTX_new failed\n");
569                 return (NULL);
570         }
571         SSL_CTX_set_ecdh_auto(ctx, 1);
572
573         if (rpctls_ciphers != NULL) {
574                 /*
575                  * Set available ciphers, since KERN_TLS only supports a
576                  * few of them.  Normally, not doing this should be ok,
577                  * since the library defaults will work.
578                  */
579                 ret = SSL_CTX_set_ciphersuites(ctx, rpctls_ciphers);
580                 if (ret == 0) {
581                         rpctls_verbose_out("rpctls_setup_ssl: "
582                             "SSL_CTX_set_ciphersuites failed: %s\n",
583                             rpctls_ciphers);
584                         SSL_CTX_free(ctx);
585                         return (NULL);
586                 }
587         }
588
589         ret = SSL_CTX_set_min_proto_version(ctx, rpctls_mintls);
590         if (ret == 0) {
591                 rpctls_verbose_out("rpctls_setup_ssl: "
592                     "SSL_CTX_set_min_proto_version failed\n");
593                 SSL_CTX_free(ctx);
594                 return (NULL);
595         }
596         ret = SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
597         if (ret == 0) {
598                 rpctls_verbose_out("rpctls_setup_ssl: "
599                     "SSL_CTX_set_max_proto_version failed\n");
600                 SSL_CTX_free(ctx);
601                 return (NULL);
602         }
603
604         /* Get the cert.pem and certkey.pem files from the directory certdir. */
605         len = strlcpy(path, certdir, sizeof(path));
606         rlen = sizeof(path) - len;
607         if (strlcpy(&path[len], "cert.pem", rlen) != 8) {
608                 SSL_CTX_free(ctx);
609                 return (NULL);
610         }
611         ret = SSL_CTX_use_certificate_file(ctx, path, SSL_FILETYPE_PEM);
612         if (ret != 1) {
613                 rpctls_verbose_out("rpctls_setup_ssl: can't use certificate "
614                     "file path=%s ret=%d\n", path, ret);
615                 SSL_CTX_free(ctx);
616                 return (NULL);
617         }
618         if (strlcpy(&path[len], "certkey.pem", rlen) != 11) {
619                 SSL_CTX_free(ctx);
620                 return (NULL);
621         }
622         ret = SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM);
623         if (ret != 1) {
624                 rpctls_verbose_out("rpctls_setup_ssl: Can't use private "
625                     "key path=%s ret=%d\n", path, ret);
626                 SSL_CTX_free(ctx);
627                 return (NULL);
628         }
629
630         /* Set Mutual authentication, as required. */
631         if (rpctls_do_mutual) {
632                 if (rpctls_verify_cafile != NULL ||
633                     rpctls_verify_capath != NULL) {
634                         if (rpctls_crlfile != NULL) {
635                                 ret = rpctls_loadcrlfile(ctx);
636                                 if (ret == 0) {
637                                         rpctls_verbose_out("rpctls_setup_ssl:"
638                                             " Load CRLfile failed\n");
639                                         SSL_CTX_free(ctx);
640                                         return (NULL);
641                                 }
642                         }
643 #if OPENSSL_VERSION_NUMBER >= 0x30000000
644                         ret = 1;
645                         if (rpctls_verify_cafile != NULL)
646                                 ret = SSL_CTX_load_verify_file(ctx,
647                                     rpctls_verify_cafile);
648                         if (ret != 0 && rpctls_verify_capath != NULL)
649                                 ret = SSL_CTX_load_verify_dir(ctx,
650                                     rpctls_verify_capath);
651 #else
652                         ret = SSL_CTX_load_verify_locations(ctx,
653                             rpctls_verify_cafile, rpctls_verify_capath);
654 #endif
655                         if (ret == 0) {
656                                 rpctls_verbose_out("rpctls_setup_ssl: "
657                                     "Can't load verify locations\n");
658                                 SSL_CTX_free(ctx);
659                                 return (NULL);
660                         }
661                         if (rpctls_verify_cafile != NULL)
662                                 SSL_CTX_set_client_CA_list(ctx,
663                                     SSL_load_client_CA_file(
664                             rpctls_verify_cafile));
665                 }
666                 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER,
667                     rpctls_verify_callback);
668         }
669 #ifdef SSL_OP_ENABLE_KTLS
670         SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS);
671 #endif
672 #ifdef SSL_MODE_NO_KTLS_TX
673         SSL_CTX_clear_mode(ctx, SSL_MODE_NO_KTLS_TX | SSL_MODE_NO_KTLS_RX);
674 #endif
675         return (ctx);
676 }
677
678 static SSL *
679 rpctls_server(SSL_CTX *ctx, int s, uint32_t *flags, uint32_t *uidp,
680     int *ngrps, uint32_t *gidp, X509 **certp)
681 {
682         SSL *ssl;
683         X509 *cert;
684         struct sockaddr *sad;
685         struct sockaddr_storage ad;
686         char hostnam[NI_MAXHOST];
687         int gethostret, ret;
688         char *cp, *cp2;
689         long verfret;
690
691         *flags = 0;
692         *certp = NULL;
693         sad = (struct sockaddr *)&ad;
694         ssl = SSL_new(ctx);
695         if (ssl == NULL) {
696                 rpctls_verbose_out("rpctls_server: SSL_new failed\n");
697                 return (NULL);
698         }
699         if (SSL_set_fd(ssl, s) != 1) {
700                 rpctls_verbose_out("rpctls_server: SSL_set_fd failed\n");
701                 SSL_free(ssl);
702                 return (NULL);
703         }
704         ret = SSL_accept(ssl);
705         if (ret != 1) {
706                 rpctls_verbose_out("rpctls_server: SSL_accept "
707                     "failed ret=%d\n", ret);
708                 SSL_free(ssl);
709                 return (NULL);
710         }
711         *flags |= RPCTLS_FLAGS_HANDSHAKE;
712         if (rpctls_verbose) {
713                 gethostret = rpctls_gethost(s, sad, hostnam, sizeof(hostnam));
714                 if (gethostret == 0)
715                         hostnam[0] = '\0';
716                 rpctls_verbose_out("rpctls_server: SSL handshake ok for host %s"
717                     " <%s %s>\n", hostnam, SSL_get_version(ssl),
718                     SSL_get_cipher(ssl));
719         }
720         if (rpctls_do_mutual) {
721                 cert = SSL_get_peer_certificate(ssl);
722                 if (cert != NULL) {
723                         if (!rpctls_verbose) {
724                                 gethostret = rpctls_gethost(s, sad, hostnam,
725                                     sizeof(hostnam));
726                                 if (gethostret == 0)
727                                         hostnam[0] = '\0';
728                         }
729                         cp2 = X509_NAME_oneline(
730                             X509_get_subject_name(cert), NULL, 0);
731                         *flags |= RPCTLS_FLAGS_GOTCERT;
732                         verfret = SSL_get_verify_result(ssl);
733                         if (verfret != X509_V_OK) {
734                                 cp = X509_NAME_oneline(
735                                     X509_get_issuer_name(cert), NULL, 0);
736                                 if (rpctls_debug_level == 0)
737                                         syslog(LOG_INFO | LOG_DAEMON,
738                                             "rpctls_server: client IP %s "
739                                             "issuerName=%s subjectName=%s"
740                                             " verify failed %s\n", hostnam,
741                                             cp, cp2,
742                                             X509_verify_cert_error_string(
743                                             verfret));
744                                 else
745                                         fprintf(stderr,
746                                             "rpctls_server: client IP %s "
747                                             "issuerName=%s subjectName=%s"
748                                             " verify failed %s\n", hostnam,
749                                             cp, cp2,
750                                             X509_verify_cert_error_string(
751                                             verfret));
752                         }
753                         if (verfret ==
754                             X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
755                             verfret == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
756                                 *flags |= RPCTLS_FLAGS_SELFSIGNED;
757                         else if (verfret == X509_V_OK) {
758                                 if (rpctls_comparehost) {
759                                         ret = 0;
760                                         if (gethostret != 0)
761                                                 ret = rpctls_checkhost(sad,
762                                                     cert, rpctls_wildcard);
763                                         if (ret != 1) {
764                                                 *flags |=
765                                                     RPCTLS_FLAGS_DISABLED;
766                                                 rpctls_verbose_out(
767                                                     "rpctls_server: "
768                                                     "checkhost "
769                                                     "failed\n");
770                                         }
771                                 }
772                                 if (rpctls_cnuser) {
773                                         ret = rpctls_cnname(cert, uidp,
774                                             ngrps, gidp);
775                                         if (ret != 0)
776                                                 *flags |= RPCTLS_FLAGS_CERTUSER;
777                                 }
778                                 *flags |= RPCTLS_FLAGS_VERIFIED;
779                                 *certp = cert;
780                                 cert = NULL;
781                         }
782                         if (cert != NULL)
783                                 X509_free(cert);
784                 } else
785                         rpctls_verbose_out("rpctls_server: "
786                             "No peer certificate\n");
787         }
788
789         /* Check to see that ktls is working for the connection. */
790         ret = BIO_get_ktls_send(SSL_get_wbio(ssl));
791         rpctls_verbose_out("rpctls_server: BIO_get_ktls_send=%d\n", ret);
792         if (ret != 0) {
793                 ret = BIO_get_ktls_recv(SSL_get_rbio(ssl));
794                 rpctls_verbose_out("rpctls_server: BIO_get_ktls_recv=%d\n",
795                     ret);
796         }
797         if (ret == 0) {
798                 if (rpctls_debug_level == 0)
799                         syslog(LOG_ERR, "ktls not working");
800                 else
801                         fprintf(stderr, "ktls not working\n");
802                 /*
803                  * The handshake has completed, so all that can be
804                  * done is disable the connection.
805                  */
806                 *flags |= RPCTLS_FLAGS_DISABLED;
807         }
808
809         return (ssl);
810 }
811
812 /*
813  * Acquire the dnsname for this server.
814  */
815 static char *
816 rpctls_getdnsname(char *hostname)
817 {
818         char *cp, *dnsname;
819         struct addrinfo *aip, hints;
820         int error;
821
822         dnsname = NULL;
823         if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
824                 if ((cp = strchr(hostname, '.')) != NULL &&
825                     *(cp + 1) != '\0') {
826                         *cp = '@';
827                         dnsname = cp;
828                 } else {
829                         memset((void *)&hints, 0, sizeof (hints));
830                         hints.ai_flags = AI_CANONNAME;
831                         error = getaddrinfo(hostname, NULL, &hints, &aip);
832                         if (error == 0) {
833                                 if (aip->ai_canonname != NULL &&
834                                     (cp = strchr(aip->ai_canonname, '.')) !=
835                                     NULL && *(cp + 1) != '\0') {
836                                         hostname[0] = '@';
837                                         strlcpy(&hostname[1], cp + 1,
838                                             MAXHOSTNAMELEN + 1);
839                                         dnsname = hostname;
840                                 }
841                                 freeaddrinfo(aip);
842                         }
843                 }
844         }
845         return (dnsname);
846 }
847
848 /*
849  * Check for an otherName component of subjectAltName where the OID
850  * matches and the "domain" matches that of this server.
851  * If found, map "user" to a <uid, gidlist> for it.
852  */
853 static int
854 rpctls_cnname(X509 *cert, uint32_t *uidp, int *ngrps, uint32_t *gidp)
855 {
856         char *cp, usern[1024 + 1];
857         struct passwd *pwd;
858         gid_t gids[NGROUPS];
859         int i, j;
860         GENERAL_NAMES *genlist;
861         GENERAL_NAME *genname;
862         OTHERNAME *val;
863         size_t slen;
864
865         /* First, find the otherName in the subjectAltName. */
866         genlist = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
867         if (genlist == NULL)
868                 return (0);
869         cp = NULL;
870         for (i = 0; i < sk_GENERAL_NAME_num(genlist); i++) {
871                 genname = sk_GENERAL_NAME_value(genlist, i);
872                 if (genname->type != GEN_OTHERNAME)
873                         continue;
874                 val = genname->d.otherName;
875
876                 /* Check to see that it is the correct OID. */
877                 slen = i2t_ASN1_OBJECT(usern, sizeof(usern), val->type_id);
878                 if (slen != strlen(rpctls_cnuseroid) || memcmp(usern,
879                     rpctls_cnuseroid, slen) != 0)
880                         continue;
881
882                 /* Sanity check the otherName. */
883                 if (val->value->type != V_ASN1_UTF8STRING ||
884                     val->value->value.utf8string->length < 3 ||
885                     (size_t)val->value->value.utf8string->length > sizeof(usern)
886                     - 1) {
887                         rpctls_verbose_out("rpctls_cnname: invalid cnuser "
888                             "type=%d\n", val->value->type);
889                         continue;
890                 }
891
892                 /* Look for a "user" in the otherName */
893                 memcpy(usern, val->value->value.utf8string->data,
894                     val->value->value.utf8string->length);
895                 usern[val->value->value.utf8string->length] = '\0';
896
897                 /* Now, look for the @dnsname suffix in the commonName. */
898                 cp = strcasestr(usern, rpctls_dnsname);
899                 if (cp == NULL)
900                         continue;
901                 if (*(cp + strlen(rpctls_dnsname)) != '\0') {
902                         cp = NULL;
903                         continue;
904                 }
905                 *cp = '\0';
906                 break;
907         }
908         if (cp == NULL)
909                 return (0);
910
911         /* See if the "user" is in the passwd database. */
912         pwd = getpwnam(usern);
913         if (pwd == NULL)
914                 return (0);
915         *uidp = pwd->pw_uid;
916         *ngrps = NGROUPS;
917         if (getgrouplist(pwd->pw_name, pwd->pw_gid, gids, ngrps) < 0)
918                 return (0);
919         rpctls_verbose_out("mapped user=%s ngrps=%d uid=%d\n", pwd->pw_name,
920             *ngrps, pwd->pw_uid);
921         for (j = 0; j < *ngrps; j++)
922                 gidp[j] = gids[j];
923         return (1);
924 }
925
926 static void
927 rpctls_huphandler(int sig __unused)
928 {
929
930         rpctls_gothup = true;
931 }