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