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