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