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