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 /* Modified from the kernel GSSAPI code for RPC-over-TLS. */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "opt_kern_tls.h" 36 37 #include <sys/param.h> 38 #include <sys/capsicum.h> 39 #include <sys/file.h> 40 #include <sys/filedesc.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/mbuf.h> 45 #include <sys/mutex.h> 46 #include <sys/priv.h> 47 #include <sys/proc.h> 48 #include <sys/socketvar.h> 49 #include <sys/syscall.h> 50 #include <sys/syscallsubr.h> 51 #include <sys/sysent.h> 52 #include <sys/sysproto.h> 53 54 #include <rpc/rpc.h> 55 #include <rpc/rpc_com.h> 56 #include <rpc/rpcsec_tls.h> 57 58 #include <vm/vm.h> 59 #include <vm/pmap.h> 60 #include <vm/vm_param.h> 61 62 #include "rpctlscd.h" 63 #include "rpctlssd.h" 64 65 /* 66 * Syscall hooks 67 */ 68 static struct syscall_helper_data rpctls_syscalls[] = { 69 SYSCALL_INIT_HELPER(rpctls_syscall), 70 SYSCALL_INIT_LAST 71 }; 72 73 static CLIENT *rpctls_connect_handle; 74 static struct mtx rpctls_connect_lock; 75 static struct socket *rpctls_connect_so = NULL; 76 static CLIENT *rpctls_connect_cl = NULL; 77 static CLIENT *rpctls_server_handle; 78 static struct mtx rpctls_server_lock; 79 static struct socket *rpctls_server_so = NULL; 80 static SVCXPRT *rpctls_server_xprt = NULL; 81 static struct opaque_auth rpctls_null_verf; 82 83 static CLIENT *rpctls_connect_client(void); 84 static CLIENT *rpctls_server_client(void); 85 static enum clnt_stat rpctls_server(SVCXPRT *xprt, struct socket *so, 86 uint32_t *flags, uint64_t *sslp, 87 uid_t *uid, int *ngrps, gid_t **gids); 88 89 int 90 rpctls_init(void) 91 { 92 int error; 93 94 error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD); 95 if (error != 0) { 96 printf("rpctls_init: cannot register syscall\n"); 97 return (error); 98 } 99 mtx_init(&rpctls_connect_lock, "rpctls_connect_lock", NULL, 100 MTX_DEF); 101 mtx_init(&rpctls_server_lock, "rpctls_server_lock", NULL, 102 MTX_DEF); 103 rpctls_null_verf.oa_flavor = AUTH_NULL; 104 rpctls_null_verf.oa_base = RPCTLS_START_STRING; 105 rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING); 106 return (0); 107 } 108 109 int 110 sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap) 111 { 112 struct sockaddr_un sun; 113 struct netconfig *nconf; 114 struct file *fp; 115 struct socket *so; 116 SVCXPRT *xprt; 117 char path[MAXPATHLEN]; 118 int fd = -1, error, try_count; 119 CLIENT *cl, *oldcl, *concl; 120 uint64_t ssl[3]; 121 struct timeval timeo; 122 #ifdef KERN_TLS 123 u_int maxlen; 124 #endif 125 126 error = priv_check(td, PRIV_NFS_DAEMON); 127 if (error != 0) 128 return (error); 129 130 switch (uap->op) { 131 case RPCTLS_SYSC_CLSETPATH: 132 error = copyinstr(uap->path, path, sizeof(path), NULL); 133 if (error == 0) { 134 error = ENXIO; 135 #ifdef KERN_TLS 136 if (rpctls_getinfo(&maxlen, false, false)) 137 error = 0; 138 #endif 139 } 140 if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || 141 strlen(path) == 0)) 142 error = EINVAL; 143 144 cl = NULL; 145 if (error == 0) { 146 sun.sun_family = AF_LOCAL; 147 strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 148 sun.sun_len = SUN_LEN(&sun); 149 150 nconf = getnetconfigent("local"); 151 cl = clnt_reconnect_create(nconf, 152 (struct sockaddr *)&sun, RPCTLSCD, RPCTLSCDVERS, 153 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 154 /* 155 * The number of retries defaults to INT_MAX, which 156 * effectively means an infinite, uninterruptable loop. 157 * Set the try_count to 1 so that no retries of the 158 * RPC occur. Since it is an upcall to a local daemon, 159 * requests should not be lost and doing one of these 160 * RPCs multiple times is not correct. 161 * If the server is not working correctly, the 162 * daemon can get stuck in SSL_connect() trying 163 * to read data from the socket during the upcall. 164 * Set a timeout (currently 15sec) and assume the 165 * daemon is hung when the timeout occurs. 166 */ 167 if (cl != NULL) { 168 try_count = 1; 169 CLNT_CONTROL(cl, CLSET_RETRIES, &try_count); 170 timeo.tv_sec = 15; 171 timeo.tv_usec = 0; 172 CLNT_CONTROL(cl, CLSET_TIMEOUT, &timeo); 173 } else 174 error = EINVAL; 175 } 176 177 mtx_lock(&rpctls_connect_lock); 178 oldcl = rpctls_connect_handle; 179 rpctls_connect_handle = cl; 180 mtx_unlock(&rpctls_connect_lock); 181 182 if (oldcl != NULL) { 183 CLNT_CLOSE(oldcl); 184 CLNT_RELEASE(oldcl); 185 } 186 break; 187 case RPCTLS_SYSC_SRVSETPATH: 188 error = copyinstr(uap->path, path, sizeof(path), NULL); 189 if (error == 0) { 190 error = ENXIO; 191 #ifdef KERN_TLS 192 if (rpctls_getinfo(&maxlen, false, false)) 193 error = 0; 194 #endif 195 } 196 if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || 197 strlen(path) == 0)) 198 error = EINVAL; 199 200 cl = NULL; 201 if (error == 0) { 202 sun.sun_family = AF_LOCAL; 203 strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 204 sun.sun_len = SUN_LEN(&sun); 205 206 nconf = getnetconfigent("local"); 207 cl = clnt_reconnect_create(nconf, 208 (struct sockaddr *)&sun, RPCTLSSD, RPCTLSSDVERS, 209 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 210 /* 211 * The number of retries defaults to INT_MAX, which 212 * effectively means an infinite, uninterruptable loop. 213 * Set the try_count to 1 so that no retries of the 214 * RPC occur. Since it is an upcall to a local daemon, 215 * requests should not be lost and doing one of these 216 * RPCs multiple times is not correct. 217 * Set a timeout (currently 15sec) and assume that 218 * the daemon is hung if a timeout occurs. 219 */ 220 if (cl != NULL) { 221 try_count = 1; 222 CLNT_CONTROL(cl, CLSET_RETRIES, &try_count); 223 timeo.tv_sec = 15; 224 timeo.tv_usec = 0; 225 CLNT_CONTROL(cl, CLSET_TIMEOUT, &timeo); 226 } else 227 error = EINVAL; 228 } 229 230 mtx_lock(&rpctls_server_lock); 231 oldcl = rpctls_server_handle; 232 rpctls_server_handle = cl; 233 mtx_unlock(&rpctls_server_lock); 234 235 if (oldcl != NULL) { 236 CLNT_CLOSE(oldcl); 237 CLNT_RELEASE(oldcl); 238 } 239 break; 240 case RPCTLS_SYSC_CLSHUTDOWN: 241 mtx_lock(&rpctls_connect_lock); 242 oldcl = rpctls_connect_handle; 243 rpctls_connect_handle = NULL; 244 mtx_unlock(&rpctls_connect_lock); 245 246 if (oldcl != NULL) { 247 CLNT_CLOSE(oldcl); 248 CLNT_RELEASE(oldcl); 249 } 250 break; 251 case RPCTLS_SYSC_SRVSHUTDOWN: 252 mtx_lock(&rpctls_server_lock); 253 oldcl = rpctls_server_handle; 254 rpctls_server_handle = NULL; 255 mtx_unlock(&rpctls_server_lock); 256 257 if (oldcl != NULL) { 258 CLNT_CLOSE(oldcl); 259 CLNT_RELEASE(oldcl); 260 } 261 break; 262 case RPCTLS_SYSC_CLSOCKET: 263 mtx_lock(&rpctls_connect_lock); 264 so = rpctls_connect_so; 265 rpctls_connect_so = NULL; 266 concl = rpctls_connect_cl; 267 rpctls_connect_cl = NULL; 268 mtx_unlock(&rpctls_connect_lock); 269 if (so != NULL) { 270 error = falloc(td, &fp, &fd, 0); 271 if (error == 0) { 272 /* 273 * Set ssl refno so that clnt_vc_destroy() will 274 * not close the socket and will leave that for 275 * the daemon to do. 276 */ 277 soref(so); 278 ssl[0] = ssl[1] = 0; 279 ssl[2] = RPCTLS_REFNO_HANDSHAKE; 280 CLNT_CONTROL(concl, CLSET_TLS, ssl); 281 finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, 282 &socketops); 283 fdrop(fp, td); /* Drop fp reference. */ 284 td->td_retval[0] = fd; 285 } 286 } else 287 error = EPERM; 288 break; 289 case RPCTLS_SYSC_SRVSOCKET: 290 mtx_lock(&rpctls_server_lock); 291 so = rpctls_server_so; 292 rpctls_server_so = NULL; 293 xprt = rpctls_server_xprt; 294 rpctls_server_xprt = NULL; 295 mtx_unlock(&rpctls_server_lock); 296 if (so != NULL) { 297 error = falloc(td, &fp, &fd, 0); 298 if (error == 0) { 299 /* 300 * Once this file descriptor is associated 301 * with the socket, it cannot be closed by 302 * the server side krpc code (svc_vc.c). 303 */ 304 soref(so); 305 sx_xlock(&xprt->xp_lock); 306 xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL; 307 sx_xunlock(&xprt->xp_lock); 308 finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, 309 &socketops); 310 fdrop(fp, td); /* Drop fp reference. */ 311 td->td_retval[0] = fd; 312 } 313 } else 314 error = EPERM; 315 break; 316 default: 317 error = EINVAL; 318 } 319 320 return (error); 321 } 322 323 /* 324 * Acquire the rpctls_connect_handle and return it with a reference count, 325 * if it is available. 326 */ 327 static CLIENT * 328 rpctls_connect_client(void) 329 { 330 CLIENT *cl; 331 332 mtx_lock(&rpctls_connect_lock); 333 cl = rpctls_connect_handle; 334 if (cl != NULL) 335 CLNT_ACQUIRE(cl); 336 mtx_unlock(&rpctls_connect_lock); 337 return (cl); 338 } 339 340 /* 341 * Acquire the rpctls_server_handle and return it with a reference count, 342 * if it is available. 343 */ 344 static CLIENT * 345 rpctls_server_client(void) 346 { 347 CLIENT *cl; 348 349 mtx_lock(&rpctls_server_lock); 350 cl = rpctls_server_handle; 351 if (cl != NULL) 352 CLNT_ACQUIRE(cl); 353 mtx_unlock(&rpctls_server_lock); 354 return (cl); 355 } 356 357 /* Do an upcall for a new socket connect using TLS. */ 358 enum clnt_stat 359 rpctls_connect(CLIENT *newclient, char *certname, struct socket *so, 360 uint64_t *sslp, uint32_t *reterr) 361 { 362 struct rpctlscd_connect_arg arg; 363 struct rpctlscd_connect_res res; 364 struct rpc_callextra ext; 365 struct timeval utimeout; 366 enum clnt_stat stat; 367 CLIENT *cl; 368 int val; 369 static bool rpctls_connect_busy = false; 370 371 cl = rpctls_connect_client(); 372 if (cl == NULL) 373 return (RPC_AUTHERROR); 374 375 /* First, do the AUTH_TLS NULL RPC. */ 376 memset(&ext, 0, sizeof(ext)); 377 utimeout.tv_sec = 30; 378 utimeout.tv_usec = 0; 379 ext.rc_auth = authtls_create(); 380 stat = clnt_call_private(newclient, &ext, NULLPROC, (xdrproc_t)xdr_void, 381 NULL, (xdrproc_t)xdr_void, NULL, utimeout); 382 AUTH_DESTROY(ext.rc_auth); 383 if (stat == RPC_AUTHERROR) 384 return (stat); 385 if (stat != RPC_SUCCESS) 386 return (RPC_SYSTEMERROR); 387 388 /* Serialize the connect upcalls. */ 389 mtx_lock(&rpctls_connect_lock); 390 while (rpctls_connect_busy) 391 msleep(&rpctls_connect_busy, &rpctls_connect_lock, PVFS, 392 "rtlscn", 0); 393 rpctls_connect_busy = true; 394 rpctls_connect_so = so; 395 rpctls_connect_cl = newclient; 396 mtx_unlock(&rpctls_connect_lock); 397 398 /* Temporarily block reception during the handshake upcall. */ 399 val = 1; 400 CLNT_CONTROL(newclient, CLSET_BLOCKRCV, &val); 401 402 /* Do the connect handshake upcall. */ 403 if (certname != NULL) { 404 arg.certname.certname_len = strlen(certname); 405 arg.certname.certname_val = certname; 406 } else 407 arg.certname.certname_len = 0; 408 stat = rpctlscd_connect_1(&arg, &res, cl); 409 if (stat == RPC_SUCCESS) { 410 *reterr = res.reterr; 411 if (res.reterr == 0) { 412 *sslp++ = res.sec; 413 *sslp++ = res.usec; 414 *sslp = res.ssl; 415 } 416 } else if (stat == RPC_TIMEDOUT) { 417 /* 418 * Do a shutdown on the socket, since the daemon is probably 419 * stuck in SSL_connect() trying to read the socket. 420 * Do not soclose() the socket, since the daemon will close() 421 * the socket after SSL_connect() returns an error. 422 */ 423 soshutdown(so, SHUT_RD); 424 } 425 CLNT_RELEASE(cl); 426 427 /* Unblock reception. */ 428 val = 0; 429 CLNT_CONTROL(newclient, CLSET_BLOCKRCV, &val); 430 431 /* Once the upcall is done, the daemon is done with the fp and so. */ 432 mtx_lock(&rpctls_connect_lock); 433 rpctls_connect_so = NULL; 434 rpctls_connect_cl = NULL; 435 rpctls_connect_busy = false; 436 wakeup(&rpctls_connect_busy); 437 mtx_unlock(&rpctls_connect_lock); 438 439 return (stat); 440 } 441 442 /* Do an upcall to handle an non-application data record using TLS. */ 443 enum clnt_stat 444 rpctls_cl_handlerecord(uint64_t sec, uint64_t usec, uint64_t ssl, 445 uint32_t *reterr) 446 { 447 struct rpctlscd_handlerecord_arg arg; 448 struct rpctlscd_handlerecord_res res; 449 enum clnt_stat stat; 450 CLIENT *cl; 451 452 cl = rpctls_connect_client(); 453 if (cl == NULL) { 454 *reterr = RPCTLSERR_NOSSL; 455 return (RPC_SUCCESS); 456 } 457 458 /* Do the handlerecord upcall. */ 459 arg.sec = sec; 460 arg.usec = usec; 461 arg.ssl = ssl; 462 stat = rpctlscd_handlerecord_1(&arg, &res, cl); 463 CLNT_RELEASE(cl); 464 if (stat == RPC_SUCCESS) 465 *reterr = res.reterr; 466 return (stat); 467 } 468 469 enum clnt_stat 470 rpctls_srv_handlerecord(uint64_t sec, uint64_t usec, uint64_t ssl, 471 uint32_t *reterr) 472 { 473 struct rpctlssd_handlerecord_arg arg; 474 struct rpctlssd_handlerecord_res res; 475 enum clnt_stat stat; 476 CLIENT *cl; 477 478 cl = rpctls_server_client(); 479 if (cl == NULL) { 480 *reterr = RPCTLSERR_NOSSL; 481 return (RPC_SUCCESS); 482 } 483 484 /* Do the handlerecord upcall. */ 485 arg.sec = sec; 486 arg.usec = usec; 487 arg.ssl = ssl; 488 stat = rpctlssd_handlerecord_1(&arg, &res, cl); 489 CLNT_RELEASE(cl); 490 if (stat == RPC_SUCCESS) 491 *reterr = res.reterr; 492 return (stat); 493 } 494 495 /* Do an upcall to shut down a socket using TLS. */ 496 enum clnt_stat 497 rpctls_cl_disconnect(uint64_t sec, uint64_t usec, uint64_t ssl, 498 uint32_t *reterr) 499 { 500 struct rpctlscd_disconnect_arg arg; 501 struct rpctlscd_disconnect_res res; 502 enum clnt_stat stat; 503 CLIENT *cl; 504 505 cl = rpctls_connect_client(); 506 if (cl == NULL) { 507 *reterr = RPCTLSERR_NOSSL; 508 return (RPC_SUCCESS); 509 } 510 511 /* Do the disconnect upcall. */ 512 arg.sec = sec; 513 arg.usec = usec; 514 arg.ssl = ssl; 515 stat = rpctlscd_disconnect_1(&arg, &res, cl); 516 CLNT_RELEASE(cl); 517 if (stat == RPC_SUCCESS) 518 *reterr = res.reterr; 519 return (stat); 520 } 521 522 enum clnt_stat 523 rpctls_srv_disconnect(uint64_t sec, uint64_t usec, uint64_t ssl, 524 uint32_t *reterr) 525 { 526 struct rpctlssd_disconnect_arg arg; 527 struct rpctlssd_disconnect_res res; 528 enum clnt_stat stat; 529 CLIENT *cl; 530 531 cl = rpctls_server_client(); 532 if (cl == NULL) { 533 *reterr = RPCTLSERR_NOSSL; 534 return (RPC_SUCCESS); 535 } 536 537 /* Do the disconnect upcall. */ 538 arg.sec = sec; 539 arg.usec = usec; 540 arg.ssl = ssl; 541 stat = rpctlssd_disconnect_1(&arg, &res, cl); 542 CLNT_RELEASE(cl); 543 if (stat == RPC_SUCCESS) 544 *reterr = res.reterr; 545 return (stat); 546 } 547 548 /* Do an upcall for a new server socket using TLS. */ 549 static enum clnt_stat 550 rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t *flags, uint64_t *sslp, 551 uid_t *uid, int *ngrps, gid_t **gids) 552 { 553 enum clnt_stat stat; 554 CLIENT *cl; 555 struct rpctlssd_connect_res res; 556 gid_t *gidp; 557 uint32_t *gidv; 558 int i; 559 static bool rpctls_server_busy = false; 560 561 cl = rpctls_server_client(); 562 if (cl == NULL) 563 return (RPC_SYSTEMERROR); 564 565 /* Serialize the server upcalls. */ 566 mtx_lock(&rpctls_server_lock); 567 while (rpctls_server_busy) 568 msleep(&rpctls_server_busy, &rpctls_server_lock, PVFS, 569 "rtlssn", 0); 570 rpctls_server_busy = true; 571 rpctls_server_so = so; 572 rpctls_server_xprt = xprt; 573 mtx_unlock(&rpctls_server_lock); 574 575 /* Do the server upcall. */ 576 res.gid.gid_val = NULL; 577 stat = rpctlssd_connect_1(NULL, &res, cl); 578 if (stat == RPC_SUCCESS) { 579 *flags = res.flags; 580 *sslp++ = res.sec; 581 *sslp++ = res.usec; 582 *sslp = res.ssl; 583 if ((*flags & (RPCTLS_FLAGS_CERTUSER | 584 RPCTLS_FLAGS_DISABLED)) == RPCTLS_FLAGS_CERTUSER) { 585 *ngrps = res.gid.gid_len; 586 *uid = res.uid; 587 *gids = gidp = mem_alloc(*ngrps * sizeof(gid_t)); 588 gidv = res.gid.gid_val; 589 for (i = 0; i < *ngrps; i++) 590 *gidp++ = *gidv++; 591 } 592 } else if (stat == RPC_TIMEDOUT) { 593 /* 594 * Do a shutdown on the socket, since the daemon is probably 595 * stuck in SSL_accept() trying to read the socket. 596 * Do not soclose() the socket, since the daemon will close() 597 * the socket after SSL_accept() returns an error. 598 */ 599 soshutdown(so, SHUT_RD); 600 } 601 CLNT_RELEASE(cl); 602 mem_free(res.gid.gid_val, 0); 603 604 /* Once the upcall is done, the daemon is done with the fp and so. */ 605 mtx_lock(&rpctls_server_lock); 606 rpctls_server_so = NULL; 607 rpctls_server_xprt = NULL; 608 rpctls_server_busy = false; 609 wakeup(&rpctls_server_busy); 610 mtx_unlock(&rpctls_server_lock); 611 612 return (stat); 613 } 614 615 /* 616 * Handle the NULL RPC with authentication flavor of AUTH_TLS. 617 * This is a STARTTLS command, so do the upcall to the rpctlssd daemon, 618 * which will do the TLS handshake. 619 */ 620 enum auth_stat 621 _svcauth_rpcsec_tls(struct svc_req *rqst, struct rpc_msg *msg) 622 623 { 624 bool_t call_stat; 625 enum clnt_stat stat; 626 SVCXPRT *xprt; 627 uint32_t flags; 628 uint64_t ssl[3]; 629 int ngrps; 630 uid_t uid; 631 gid_t *gidp; 632 #ifdef KERN_TLS 633 u_int maxlen; 634 #endif 635 636 /* Initialize reply. */ 637 rqst->rq_verf = rpctls_null_verf; 638 639 /* Check client credentials. */ 640 if (rqst->rq_cred.oa_length != 0 || 641 msg->rm_call.cb_verf.oa_length != 0 || 642 msg->rm_call.cb_verf.oa_flavor != AUTH_NULL) 643 return (AUTH_BADCRED); 644 645 if (rqst->rq_proc != NULLPROC) 646 return (AUTH_REJECTEDCRED); 647 648 call_stat = FALSE; 649 #ifdef KERN_TLS 650 if (rpctls_getinfo(&maxlen, false, true)) 651 call_stat = TRUE; 652 #endif 653 if (!call_stat) 654 return (AUTH_REJECTEDCRED); 655 656 /* 657 * Disable reception for the krpc so that the TLS handshake can 658 * be done on the socket in the rpctlssd daemon. 659 */ 660 xprt = rqst->rq_xprt; 661 sx_xlock(&xprt->xp_lock); 662 xprt->xp_dontrcv = TRUE; 663 sx_xunlock(&xprt->xp_lock); 664 665 /* 666 * Send the reply to the NULL RPC with AUTH_TLS, which is the 667 * STARTTLS command for Sun RPC. 668 */ 669 call_stat = svc_sendreply(rqst, (xdrproc_t)xdr_void, NULL); 670 if (!call_stat) { 671 sx_xlock(&xprt->xp_lock); 672 xprt->xp_dontrcv = FALSE; 673 sx_xunlock(&xprt->xp_lock); 674 xprt_active(xprt); /* Harmless if already active. */ 675 return (AUTH_REJECTEDCRED); 676 } 677 678 /* Do an upcall to do the TLS handshake. */ 679 stat = rpctls_server(xprt, xprt->xp_socket, &flags, 680 ssl, &uid, &ngrps, &gidp); 681 682 /* Re-enable reception on the socket within the krpc. */ 683 sx_xlock(&xprt->xp_lock); 684 xprt->xp_dontrcv = FALSE; 685 if (stat == RPC_SUCCESS) { 686 xprt->xp_tls = flags; 687 xprt->xp_sslsec = ssl[0]; 688 xprt->xp_sslusec = ssl[1]; 689 xprt->xp_sslrefno = ssl[2]; 690 if ((flags & (RPCTLS_FLAGS_CERTUSER | 691 RPCTLS_FLAGS_DISABLED)) == RPCTLS_FLAGS_CERTUSER) { 692 xprt->xp_ngrps = ngrps; 693 xprt->xp_uid = uid; 694 xprt->xp_gidp = gidp; 695 } 696 } 697 sx_xunlock(&xprt->xp_lock); 698 xprt_active(xprt); /* Harmless if already active. */ 699 700 return (RPCSEC_GSS_NODISPATCH); 701 } 702 703 /* 704 * Get kern.ipc.tls.enable and kern.ipc.tls.maxlen. 705 */ 706 bool 707 rpctls_getinfo(u_int *maxlenp, bool rpctlscd_run, bool rpctlssd_run) 708 { 709 u_int maxlen; 710 bool enable; 711 int error; 712 size_t siz; 713 714 if (!mb_use_ext_pgs) 715 return (false); 716 siz = sizeof(enable); 717 error = kernel_sysctlbyname(curthread, "kern.ipc.tls.enable", 718 &enable, &siz, NULL, 0, NULL, 0); 719 if (error != 0) 720 return (false); 721 siz = sizeof(maxlen); 722 error = kernel_sysctlbyname(curthread, "kern.ipc.tls.maxlen", 723 &maxlen, &siz, NULL, 0, NULL, 0); 724 if (error != 0) 725 return (false); 726 if (rpctlscd_run && rpctls_connect_handle == NULL) 727 return (false); 728 if (rpctlssd_run && rpctls_server_handle == NULL) 729 return (false); 730 *maxlenp = maxlen; 731 return (enable); 732 } 733 734