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