1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/errno.h> 30 #include <sys/vfs.h> 31 #include <sys/vnode.h> 32 #include <sys/cred.h> 33 #include <sys/cmn_err.h> 34 #include <sys/systm.h> 35 #include <sys/kmem.h> 36 #include <sys/pathname.h> 37 #include <sys/utsname.h> 38 #include <sys/debug.h> 39 #include <sys/door.h> 40 #include <sys/sdt.h> 41 42 #include <rpc/types.h> 43 #include <rpc/auth.h> 44 #include <rpc/clnt.h> 45 46 #include <nfs/nfs.h> 47 #include <nfs/export.h> 48 #include <nfs/nfs_clnt.h> 49 #include <nfs/auth.h> 50 51 #define EQADDR(a1, a2) \ 52 (bcmp((char *)(a1)->buf, (char *)(a2)->buf, (a1)->len) == 0 && \ 53 (a1)->len == (a2)->len) 54 55 static struct knetconfig auth_knconf; 56 static servinfo_t svp; 57 static clinfo_t ci; 58 59 static struct kmem_cache *exi_cache_handle; 60 static void exi_cache_reclaim(void *); 61 static void exi_cache_trim(struct exportinfo *exi); 62 63 int nfsauth_cache_hit; 64 int nfsauth_cache_miss; 65 int nfsauth_cache_reclaim; 66 67 /* 68 * Number of seconds to wait for an NFSAUTH upcall. 69 */ 70 static int nfsauth_timeout = 20; 71 72 /* 73 * mountd is a server-side only daemon. This will need to be 74 * revisited if the NFS server is ever made zones-aware. 75 */ 76 kmutex_t mountd_lock; 77 door_handle_t mountd_dh; 78 79 void 80 mountd_args(uint_t did) 81 { 82 mutex_enter(&mountd_lock); 83 if (mountd_dh) 84 door_ki_rele(mountd_dh); 85 mountd_dh = door_ki_lookup(did); 86 mutex_exit(&mountd_lock); 87 } 88 89 void 90 nfsauth_init(void) 91 { 92 /* 93 * mountd can be restarted by smf(5). We need to make sure 94 * the updated door handle will safely make it to mountd_dh 95 */ 96 mutex_init(&mountd_lock, NULL, MUTEX_DEFAULT, NULL); 97 98 /* 99 * Allocate nfsauth cache handle 100 */ 101 exi_cache_handle = kmem_cache_create("exi_cache_handle", 102 sizeof (struct auth_cache), 0, NULL, NULL, 103 exi_cache_reclaim, NULL, NULL, 0); 104 } 105 106 /* 107 * Finalization routine for nfsauth. It is important to call this routine 108 * before destroying the exported_lock. 109 */ 110 void 111 nfsauth_fini(void) 112 { 113 /* 114 * Deallocate nfsauth cache handle 115 */ 116 kmem_cache_destroy(exi_cache_handle); 117 } 118 119 /* 120 * Convert the address in a netbuf to 121 * a hash index for the auth_cache table. 122 */ 123 static int 124 hash(struct netbuf *a) 125 { 126 int i, h = 0; 127 128 for (i = 0; i < a->len; i++) 129 h ^= a->buf[i]; 130 131 return (h & (AUTH_TABLESIZE - 1)); 132 } 133 134 /* 135 * Mask out the components of an 136 * address that do not identify 137 * a host. For socket addresses the 138 * masking gets rid of the port number. 139 */ 140 static void 141 addrmask(struct netbuf *addr, struct netbuf *mask) 142 { 143 int i; 144 145 for (i = 0; i < addr->len; i++) 146 addr->buf[i] &= mask->buf[i]; 147 } 148 149 /* 150 * nfsauth4_access is used for NFS V4 auth checking. Besides doing 151 * the common nfsauth_access(), it will check if the client can 152 * have a limited access to this vnode even if the security flavor 153 * used does not meet the policy. 154 */ 155 int 156 nfsauth4_access(struct exportinfo *exi, vnode_t *vp, struct svc_req *req) 157 { 158 int access; 159 160 access = nfsauth_access(exi, req); 161 162 /* 163 * There are cases that the server needs to allow the client 164 * to have a limited view. 165 * 166 * e.g. 167 * /export is shared as "sec=sys,rw=dfs-test-4,sec=krb5,rw" 168 * /export/home is shared as "sec=sys,rw" 169 * 170 * When the client mounts /export with sec=sys, the client 171 * would get a limited view with RO access on /export to see 172 * "home" only because the client is allowed to access 173 * /export/home with auth_sys. 174 */ 175 if (access & NFSAUTH_DENIED || access & NFSAUTH_WRONGSEC) { 176 /* 177 * Allow ro permission with LIMITED view if there is a 178 * sub-dir exported under vp. 179 */ 180 if (has_visible(exi, vp)) { 181 return (NFSAUTH_LIMITED); 182 } 183 } 184 185 return (access); 186 } 187 188 static void 189 sys_log(const char *msg) 190 { 191 static time_t tstamp = 0; 192 time_t now; 193 194 /* 195 * msg is shown (at most) once per minute 196 */ 197 now = gethrestime_sec(); 198 if ((tstamp + 60) < now) { 199 tstamp = now; 200 cmn_err(CE_WARN, msg); 201 } 202 } 203 204 /* 205 * Get the access information from the cache or callup to the mountd 206 * to get and cache the access information in the kernel. 207 */ 208 int 209 nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor) 210 { 211 struct netbuf addr; 212 struct netbuf *claddr; 213 struct auth_cache **head; 214 struct auth_cache *ap; 215 int access; 216 varg_t varg = {0}; 217 nfsauth_res_t res = {0}; 218 XDR xdrs_a; 219 XDR xdrs_r; 220 size_t absz; 221 caddr_t abuf; 222 size_t rbsz = (size_t)(BYTES_PER_XDR_UNIT * 2); 223 char result[BYTES_PER_XDR_UNIT * 2] = {0}; 224 caddr_t rbuf = (caddr_t)&result; 225 int last = 0; 226 door_arg_t da; 227 door_info_t di; 228 door_handle_t dh; 229 uint_t ntries = 0; 230 231 /* 232 * Now check whether this client already 233 * has an entry for this flavor in the cache 234 * for this export. 235 * Get the caller's address, mask off the 236 * parts of the address that do not identify 237 * the host (port number, etc), and then hash 238 * it to find the chain of cache entries. 239 */ 240 241 claddr = svc_getrpccaller(req->rq_xprt); 242 addr = *claddr; 243 addr.buf = kmem_alloc(addr.len, KM_SLEEP); 244 bcopy(claddr->buf, addr.buf, claddr->len); 245 addrmask(&addr, svc_getaddrmask(req->rq_xprt)); 246 head = &exi->exi_cache[hash(&addr)]; 247 248 rw_enter(&exi->exi_cache_lock, RW_READER); 249 for (ap = *head; ap; ap = ap->auth_next) { 250 if (EQADDR(&addr, &ap->auth_addr) && flavor == ap->auth_flavor) 251 break; 252 } 253 if (ap) { /* cache hit */ 254 access = ap->auth_access; 255 ap->auth_time = gethrestime_sec(); 256 nfsauth_cache_hit++; 257 } 258 259 rw_exit(&exi->exi_cache_lock); 260 261 if (ap) { 262 kmem_free(addr.buf, addr.len); 263 return (access); 264 } 265 266 nfsauth_cache_miss++; 267 268 /* 269 * No entry in the cache for this client/flavor 270 * so we need to call the nfsauth service in the 271 * mount daemon. 272 */ 273 retry: 274 mutex_enter(&mountd_lock); 275 dh = mountd_dh; 276 if (dh) 277 door_ki_hold(dh); 278 mutex_exit(&mountd_lock); 279 280 if (dh == NULL) { 281 /* 282 * The rendezvous point has not been established yet ! 283 * This could mean that either mountd(1m) has not yet 284 * been started or that _this_ routine nuked the door 285 * handle after receiving an EINTR for a REVOKED door. 286 * 287 * Returning NFSAUTH_DROP will cause the NFS client 288 * to retransmit the request, so let's try to be more 289 * rescillient and attempt for ntries before we bail. 290 */ 291 if (++ntries % NFSAUTH_DR_TRYCNT) { 292 delay(hz); 293 goto retry; 294 } 295 sys_log("nfsauth: mountd has not established door"); 296 kmem_free(addr.buf, addr.len); 297 return (NFSAUTH_DROP); 298 } 299 ntries = 0; 300 varg.vers = V_PROTO; 301 varg.arg_u.arg.cmd = NFSAUTH_ACCESS; 302 varg.arg_u.arg.areq.req_client.n_len = addr.len; 303 varg.arg_u.arg.areq.req_client.n_bytes = addr.buf; 304 varg.arg_u.arg.areq.req_netid = svc_getnetid(req->rq_xprt); 305 varg.arg_u.arg.areq.req_path = exi->exi_export.ex_path; 306 varg.arg_u.arg.areq.req_flavor = flavor; 307 308 /* 309 * Setup the XDR stream for encoding the arguments. Notice that 310 * in addition to the args having variable fields (req_netid and 311 * req_path), the argument data structure is itself versioned, 312 * so we need to make sure we can size the arguments buffer 313 * appropriately to encode all the args. If we can't get sizing 314 * info _or_ properly encode the arguments, there's really no 315 * point in continuting, so we fail the request. 316 */ 317 DTRACE_PROBE1(nfsserv__func__nfsauth__varg, varg_t *, &varg); 318 if ((absz = xdr_sizeof(xdr_varg, (void *)&varg)) == 0) { 319 door_ki_rele(dh); 320 kmem_free(addr.buf, addr.len); 321 return (NFSAUTH_DENIED); 322 } 323 abuf = (caddr_t)kmem_alloc(absz, KM_SLEEP); 324 xdrmem_create(&xdrs_a, abuf, absz, XDR_ENCODE); 325 if (!xdr_varg(&xdrs_a, &varg)) { 326 door_ki_rele(dh); 327 goto fail; 328 } 329 XDR_DESTROY(&xdrs_a); 330 331 /* 332 * The result (nfsauth_res_t) is always two int's, so we don't 333 * have to dynamically size (or allocate) the results buffer. 334 * Now that we've got what we need, we prep the door arguments 335 * and place the call. 336 */ 337 da.data_ptr = (char *)abuf; 338 da.data_size = absz; 339 da.desc_ptr = NULL; 340 da.desc_num = 0; 341 da.rbuf = (char *)rbuf; 342 da.rsize = rbsz; 343 344 switch (door_ki_upcall(dh, &da)) { 345 case 0: /* Success */ 346 if (da.data_ptr != da.rbuf && da.data_size == 0) { 347 /* 348 * The door_return that contained the data 349 * failed ! We're here because of the 2nd 350 * door_return (w/o data) such that we can 351 * get control of the thread (and exit 352 * gracefully). 353 */ 354 DTRACE_PROBE1(nfsserv__func__nfsauth__door__nil, 355 door_arg_t *, &da); 356 door_ki_rele(dh); 357 goto fail; 358 359 } else if (rbuf != da.rbuf) { 360 /* 361 * The only time this should be true 362 * is iff userland wanted to hand us 363 * a bigger response than what we 364 * expect; that should not happen 365 * (nfsauth_res_t is only 2 int's), 366 * but we check nevertheless. 367 */ 368 rbuf = da.rbuf; 369 rbsz = da.rsize; 370 371 } else if (rbsz > da.data_size) { 372 /* 373 * We were expecting two int's; but if 374 * userland fails in encoding the XDR 375 * stream, we detect that here, since 376 * the mountd forces down only one byte 377 * in such scenario. 378 */ 379 door_ki_rele(dh); 380 goto fail; 381 } 382 door_ki_rele(dh); 383 break; 384 385 case EAGAIN: 386 /* 387 * Server out of resources; back off for a bit 388 */ 389 door_ki_rele(dh); 390 kmem_free(abuf, absz); 391 delay(hz); 392 goto retry; 393 /* NOTREACHED */ 394 395 case EINTR: 396 if (!door_ki_info(dh, &di)) { 397 if (di.di_attributes & DOOR_REVOKED) { 398 /* 399 * The server barfed and revoked 400 * the (existing) door on us; we 401 * want to wait to give smf(5) a 402 * chance to restart mountd(1m) 403 * and establish a new door handle. 404 */ 405 mutex_enter(&mountd_lock); 406 if (dh == mountd_dh) 407 mountd_dh = NULL; 408 mutex_exit(&mountd_lock); 409 door_ki_rele(dh); 410 kmem_free(abuf, absz); 411 delay(hz); 412 goto retry; 413 } 414 /* 415 * If the door was _not_ revoked on us, 416 * then more than likely we took an INTR, 417 * so we need to fail the operation. 418 */ 419 door_ki_rele(dh); 420 goto fail; 421 } 422 /* 423 * The only failure that can occur from getting 424 * the door info is EINVAL, so we let the code 425 * below handle it. 426 */ 427 /* FALLTHROUGH */ 428 429 case EBADF: 430 case EINVAL: 431 default: 432 /* 433 * If we have a stale door handle, give smf a last 434 * chance to start it by sleeping for a little bit. 435 * If we're still hosed, we'll fail the call. 436 * 437 * Since we're going to reacquire the door handle 438 * upon the retry, we opt to sleep for a bit and 439 * _not_ to clear mountd_dh. If mountd restarted 440 * and was able to set mountd_dh, we should see 441 * the new instance; if not, we won't get caught 442 * up in the retry/DELAY loop. 443 */ 444 door_ki_rele(dh); 445 if (!last) { 446 delay(hz); 447 last++; 448 goto retry; 449 } 450 sys_log("nfsauth: stale mountd door handle"); 451 goto fail; 452 } 453 454 /* 455 * No door errors encountered; setup the XDR stream for decoding 456 * the results. If we fail to decode the results, we've got no 457 * other recourse than to fail the request. 458 */ 459 xdrmem_create(&xdrs_r, rbuf, rbsz, XDR_DECODE); 460 if (!xdr_nfsauth_res(&xdrs_r, &res)) 461 goto fail; 462 XDR_DESTROY(&xdrs_r); 463 464 DTRACE_PROBE1(nfsserv__func__nfsauth__results, nfsauth_res_t *, &res); 465 switch (res.stat) { 466 case NFSAUTH_DR_OKAY: 467 access = res.ares.auth_perm; 468 kmem_free(abuf, absz); 469 break; 470 471 case NFSAUTH_DR_EFAIL: 472 case NFSAUTH_DR_DECERR: 473 case NFSAUTH_DR_BADCMD: 474 default: 475 fail: 476 kmem_free(addr.buf, addr.len); 477 kmem_free(abuf, absz); 478 return (NFSAUTH_DENIED); 479 /* NOTREACHED */ 480 } 481 482 /* 483 * Now cache the result on the cache chain 484 * for this export (if there's enough memory) 485 */ 486 ap = kmem_cache_alloc(exi_cache_handle, KM_NOSLEEP); 487 if (ap) { 488 ap->auth_addr = addr; 489 ap->auth_flavor = flavor; 490 ap->auth_access = access; 491 ap->auth_time = gethrestime_sec(); 492 rw_enter(&exi->exi_cache_lock, RW_WRITER); 493 ap->auth_next = *head; 494 *head = ap; 495 rw_exit(&exi->exi_cache_lock); 496 } else { 497 kmem_free(addr.buf, addr.len); 498 } 499 500 return (access); 501 } 502 503 /* 504 * Check if the requesting client has access to the filesystem with 505 * a given nfs flavor number which is an explicitly shared flavor. 506 */ 507 int 508 nfsauth4_secinfo_access(struct exportinfo *exi, struct svc_req *req, 509 int flavor, int perm) 510 { 511 int access; 512 513 if (! (perm & M_4SEC_EXPORTED)) { 514 return (NFSAUTH_DENIED); 515 } 516 517 /* 518 * Optimize if there are no lists 519 */ 520 if ((perm & M_ROOT) == 0) { 521 perm &= ~M_4SEC_EXPORTED; 522 if (perm == M_RO) 523 return (NFSAUTH_RO); 524 if (perm == M_RW) 525 return (NFSAUTH_RW); 526 } 527 528 access = nfsauth_cache_get(exi, req, flavor); 529 530 return (access); 531 } 532 533 int 534 nfsauth_access(struct exportinfo *exi, struct svc_req *req) 535 { 536 int access, mapaccess; 537 struct secinfo *sp; 538 int i, flavor, perm; 539 int authnone_entry = -1; 540 541 /* 542 * Get the nfs flavor number from xprt. 543 */ 544 flavor = (int)(uintptr_t)req->rq_xprt->xp_cookie; 545 546 /* 547 * First check the access restrictions on the filesystem. If 548 * there are no lists associated with this flavor then there's no 549 * need to make an expensive call to the nfsauth service or to 550 * cache anything. 551 */ 552 553 sp = exi->exi_export.ex_secinfo; 554 for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 555 if (flavor != sp[i].s_secinfo.sc_nfsnum) { 556 if (sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) 557 authnone_entry = i; 558 continue; 559 } 560 break; 561 } 562 563 mapaccess = 0; 564 565 if (i >= exi->exi_export.ex_seccnt) { 566 /* 567 * Flavor not found, but use AUTH_NONE if it exists 568 */ 569 if (authnone_entry == -1) 570 return (NFSAUTH_DENIED); 571 flavor = AUTH_NONE; 572 mapaccess = NFSAUTH_MAPNONE; 573 i = authnone_entry; 574 } 575 576 /* 577 * If the flavor is in the ex_secinfo list, but not an explicitly 578 * shared flavor by the user, it is a result of the nfsv4 server 579 * namespace setup. We will grant an RO permission similar for 580 * a pseudo node except that this node is a shared one. 581 * 582 * e.g. flavor in (flavor) indicates that it is not explictly 583 * shared by the user: 584 * 585 * / (sys, krb5) 586 * | 587 * export #share -o sec=sys (krb5) 588 * | 589 * secure #share -o sec=krb5 590 * 591 * In this case, when a krb5 request coming in to access 592 * /export, RO permission is granted. 593 */ 594 if (!(sp[i].s_flags & M_4SEC_EXPORTED)) 595 return (mapaccess | NFSAUTH_RO); 596 597 /* 598 * Optimize if there are no lists 599 */ 600 perm = sp[i].s_flags; 601 if ((perm & M_ROOT) == 0) { 602 perm &= ~M_4SEC_EXPORTED; 603 if (perm == M_RO) 604 return (mapaccess | NFSAUTH_RO); 605 if (perm == M_RW) 606 return (mapaccess | NFSAUTH_RW); 607 } 608 609 access = nfsauth_cache_get(exi, req, flavor); 610 611 return (access | mapaccess); 612 } 613 614 /* 615 * Free the nfsauth cache for a given export 616 */ 617 void 618 nfsauth_cache_free(struct exportinfo *exi) 619 { 620 int i; 621 struct auth_cache *p, *next; 622 623 for (i = 0; i < AUTH_TABLESIZE; i++) { 624 for (p = exi->exi_cache[i]; p; p = next) { 625 kmem_free(p->auth_addr.buf, p->auth_addr.len); 626 next = p->auth_next; 627 kmem_cache_free(exi_cache_handle, (void *)p); 628 } 629 } 630 } 631 632 /* 633 * Called by the kernel memory allocator when 634 * memory is low. Free unused cache entries. 635 * If that's not enough, the VM system will 636 * call again for some more. 637 */ 638 /*ARGSUSED*/ 639 void 640 exi_cache_reclaim(void *cdrarg) 641 { 642 int i; 643 struct exportinfo *exi; 644 645 rw_enter(&exported_lock, RW_READER); 646 647 for (i = 0; i < EXPTABLESIZE; i++) { 648 for (exi = exptable[i]; exi; exi = exi->exi_hash) { 649 exi_cache_trim(exi); 650 } 651 } 652 nfsauth_cache_reclaim++; 653 654 rw_exit(&exported_lock); 655 } 656 657 /* 658 * Don't reclaim entries until they've been 659 * in the cache for at least exi_cache_time 660 * seconds. 661 */ 662 time_t exi_cache_time = 60 * 60; 663 664 void 665 exi_cache_trim(struct exportinfo *exi) 666 { 667 struct auth_cache *p; 668 struct auth_cache *prev, *next; 669 int i; 670 time_t stale_time; 671 672 stale_time = gethrestime_sec() - exi_cache_time; 673 674 rw_enter(&exi->exi_cache_lock, RW_WRITER); 675 676 for (i = 0; i < AUTH_TABLESIZE; i++) { 677 678 /* 679 * Free entries that have not been 680 * used for exi_cache_time seconds. 681 */ 682 prev = NULL; 683 for (p = exi->exi_cache[i]; p; p = next) { 684 next = p->auth_next; 685 if (p->auth_time > stale_time) { 686 prev = p; 687 continue; 688 } 689 690 kmem_free(p->auth_addr.buf, p->auth_addr.len); 691 kmem_cache_free(exi_cache_handle, (void *)p); 692 if (prev == NULL) 693 exi->exi_cache[i] = next; 694 else 695 prev->auth_next = next; 696 } 697 } 698 699 rw_exit(&exi->exi_cache_lock); 700 } 701