1 /* $NetBSD: kern_auth.c,v 1.32 2006/11/19 00:11:29 elad Exp $ */ 2 3 /*- 4 * Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Elad Efrat. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.32 2006/11/19 00:11:29 elad Exp $"); 35 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/queue.h> 39 #include <sys/time.h> 40 #include <sys/proc.h> 41 #include <sys/ucred.h> 42 #include <sys/pool.h> 43 #include <sys/kauth.h> 44 #include <sys/acct.h> 45 #include <sys/sysctl.h> 46 47 /* 48 * Credentials. 49 */ 50 struct kauth_cred { 51 struct simplelock cr_lock; /* lock on cr_refcnt */ 52 u_int cr_refcnt; /* reference count */ 53 uid_t cr_uid; /* user id */ 54 uid_t cr_euid; /* effective user id */ 55 uid_t cr_svuid; /* saved effective user id */ 56 gid_t cr_gid; /* group id */ 57 gid_t cr_egid; /* effective group id */ 58 gid_t cr_svgid; /* saved effective group id */ 59 u_int cr_ngroups; /* number of groups */ 60 gid_t cr_groups[NGROUPS]; /* group memberships */ 61 }; 62 63 /* 64 * Listener. 65 */ 66 struct kauth_listener { 67 kauth_scope_callback_t func; /* callback */ 68 kauth_scope_t scope; /* scope backpointer */ 69 u_int refcnt; /* reference count */ 70 SIMPLEQ_ENTRY(kauth_listener) listener_next; /* listener list */ 71 }; 72 73 /* 74 * Scope. 75 */ 76 struct kauth_scope { 77 const char *id; /* scope name */ 78 void *cookie; /* user cookie */ 79 u_int nlisteners; /* # of listeners */ 80 SIMPLEQ_HEAD(, kauth_listener) listenq; /* listener list */ 81 SIMPLEQ_ENTRY(kauth_scope) next_scope; /* scope list */ 82 }; 83 84 static POOL_INIT(kauth_scope_pool, sizeof(struct kauth_scope), 0, 0, 0, 85 "kauth_scopepl", &pool_allocator_nointr); 86 static POOL_INIT(kauth_listener_pool, sizeof(struct kauth_listener), 0, 0, 0, 87 "kauth_listenerpl", &pool_allocator_nointr); 88 static POOL_INIT(kauth_cred_pool, sizeof(struct kauth_cred), 0, 0, 0, 89 "kauth_credpl", &pool_allocator_nointr); 90 91 /* List of scopes and its lock. */ 92 static SIMPLEQ_HEAD(, kauth_scope) scope_list; 93 static struct simplelock scopes_lock; 94 95 /* Built-in scopes: generic, process. */ 96 static kauth_scope_t kauth_builtin_scope_generic; 97 static kauth_scope_t kauth_builtin_scope_system; 98 static kauth_scope_t kauth_builtin_scope_process; 99 static kauth_scope_t kauth_builtin_scope_network; 100 static kauth_scope_t kauth_builtin_scope_machdep; 101 static kauth_scope_t kauth_builtin_scope_device; 102 103 static boolean_t listeners_have_been_loaded = FALSE; 104 105 /* Allocate new, empty kauth credentials. */ 106 kauth_cred_t 107 kauth_cred_alloc(void) 108 { 109 kauth_cred_t cred; 110 111 cred = pool_get(&kauth_cred_pool, PR_WAITOK); 112 memset(cred, 0, sizeof(*cred)); 113 simple_lock_init(&cred->cr_lock); 114 cred->cr_refcnt = 1; 115 116 return (cred); 117 } 118 119 /* Increment reference count to cred. */ 120 void 121 kauth_cred_hold(kauth_cred_t cred) 122 { 123 KASSERT(cred != NULL); 124 KASSERT(cred->cr_refcnt > 0); 125 126 simple_lock(&cred->cr_lock); 127 cred->cr_refcnt++; 128 simple_unlock(&cred->cr_lock); 129 } 130 131 /* Decrease reference count to cred. If reached zero, free it. */ 132 void 133 kauth_cred_free(kauth_cred_t cred) 134 { 135 u_int refcnt; 136 137 KASSERT(cred != NULL); 138 KASSERT(cred->cr_refcnt > 0); 139 140 simple_lock(&cred->cr_lock); 141 refcnt = --cred->cr_refcnt; 142 simple_unlock(&cred->cr_lock); 143 144 if (refcnt == 0) 145 pool_put(&kauth_cred_pool, cred); 146 } 147 148 void 149 kauth_cred_clone(kauth_cred_t from, kauth_cred_t to) 150 { 151 KASSERT(from != NULL); 152 KASSERT(to != NULL); 153 KASSERT(from->cr_refcnt > 0); 154 155 to->cr_uid = from->cr_uid; 156 to->cr_euid = from->cr_euid; 157 to->cr_svuid = from->cr_svuid; 158 to->cr_gid = from->cr_gid; 159 to->cr_egid = from->cr_egid; 160 to->cr_svgid = from->cr_svgid; 161 to->cr_ngroups = from->cr_ngroups; 162 memcpy(to->cr_groups, from->cr_groups, sizeof(to->cr_groups)); 163 } 164 165 /* 166 * Duplicate cred and return a new kauth_cred_t. 167 */ 168 kauth_cred_t 169 kauth_cred_dup(kauth_cred_t cred) 170 { 171 kauth_cred_t new_cred; 172 173 KASSERT(cred != NULL); 174 KASSERT(cred->cr_refcnt > 0); 175 176 new_cred = kauth_cred_alloc(); 177 178 kauth_cred_clone(cred, new_cred); 179 180 return (new_cred); 181 } 182 183 /* 184 * Similar to crcopy(), only on a kauth_cred_t. 185 * XXX: Is this even needed? [kauth_cred_copy] 186 */ 187 kauth_cred_t 188 kauth_cred_copy(kauth_cred_t cred) 189 { 190 kauth_cred_t new_cred; 191 192 KASSERT(cred != NULL); 193 KASSERT(cred->cr_refcnt > 0); 194 195 /* If the provided credentials already have one reference, use them. */ 196 if (cred->cr_refcnt == 1) 197 return (cred); 198 199 new_cred = kauth_cred_alloc(); 200 201 kauth_cred_clone(cred, new_cred); 202 203 kauth_cred_free(cred); 204 205 return (new_cred); 206 } 207 208 uid_t 209 kauth_cred_getuid(kauth_cred_t cred) 210 { 211 KASSERT(cred != NULL); 212 213 return (cred->cr_uid); 214 } 215 216 uid_t 217 kauth_cred_geteuid(kauth_cred_t cred) 218 { 219 KASSERT(cred != NULL); 220 221 return (cred->cr_euid); 222 } 223 224 uid_t 225 kauth_cred_getsvuid(kauth_cred_t cred) 226 { 227 KASSERT(cred != NULL); 228 229 return (cred->cr_svuid); 230 } 231 232 gid_t 233 kauth_cred_getgid(kauth_cred_t cred) 234 { 235 KASSERT(cred != NULL); 236 237 return (cred->cr_gid); 238 } 239 240 gid_t 241 kauth_cred_getegid(kauth_cred_t cred) 242 { 243 KASSERT(cred != NULL); 244 245 return (cred->cr_egid); 246 } 247 248 gid_t 249 kauth_cred_getsvgid(kauth_cred_t cred) 250 { 251 KASSERT(cred != NULL); 252 253 return (cred->cr_svgid); 254 } 255 256 void 257 kauth_cred_setuid(kauth_cred_t cred, uid_t uid) 258 { 259 KASSERT(cred != NULL); 260 KASSERT(cred->cr_refcnt == 1); 261 262 cred->cr_uid = uid; 263 } 264 265 void 266 kauth_cred_seteuid(kauth_cred_t cred, uid_t uid) 267 { 268 KASSERT(cred != NULL); 269 KASSERT(cred->cr_refcnt == 1); 270 271 cred->cr_euid = uid; 272 } 273 274 void 275 kauth_cred_setsvuid(kauth_cred_t cred, uid_t uid) 276 { 277 KASSERT(cred != NULL); 278 KASSERT(cred->cr_refcnt == 1); 279 280 cred->cr_svuid = uid; 281 } 282 283 void 284 kauth_cred_setgid(kauth_cred_t cred, gid_t gid) 285 { 286 KASSERT(cred != NULL); 287 KASSERT(cred->cr_refcnt == 1); 288 289 cred->cr_gid = gid; 290 } 291 292 void 293 kauth_cred_setegid(kauth_cred_t cred, gid_t gid) 294 { 295 KASSERT(cred != NULL); 296 KASSERT(cred->cr_refcnt == 1); 297 298 cred->cr_egid = gid; 299 } 300 301 void 302 kauth_cred_setsvgid(kauth_cred_t cred, gid_t gid) 303 { 304 KASSERT(cred != NULL); 305 KASSERT(cred->cr_refcnt == 1); 306 307 cred->cr_svgid = gid; 308 } 309 310 /* Checks if gid is a member of the groups in cred. */ 311 int 312 kauth_cred_ismember_gid(kauth_cred_t cred, gid_t gid, int *resultp) 313 { 314 int i; 315 316 KASSERT(cred != NULL); 317 KASSERT(resultp != NULL); 318 319 *resultp = 0; 320 321 for (i = 0; i < cred->cr_ngroups; i++) 322 if (cred->cr_groups[i] == gid) { 323 *resultp = 1; 324 break; 325 } 326 327 return (0); 328 } 329 330 u_int 331 kauth_cred_ngroups(kauth_cred_t cred) 332 { 333 KASSERT(cred != NULL); 334 335 return (cred->cr_ngroups); 336 } 337 338 /* 339 * Return the group at index idx from the groups in cred. 340 */ 341 gid_t 342 kauth_cred_group(kauth_cred_t cred, u_int idx) 343 { 344 KASSERT(cred != NULL); 345 KASSERT(idx < cred->cr_ngroups); 346 347 return (cred->cr_groups[idx]); 348 } 349 350 /* XXX elad: gmuid is unused for now. */ 351 int 352 kauth_cred_setgroups(kauth_cred_t cred, gid_t *grbuf, size_t len, uid_t gmuid) 353 { 354 KASSERT(cred != NULL); 355 KASSERT(cred->cr_refcnt == 1); 356 KASSERT(len <= sizeof(cred->cr_groups) / sizeof(cred->cr_groups[0])); 357 358 if (len) 359 memcpy(cred->cr_groups, grbuf, len * sizeof(cred->cr_groups[0])); 360 memset(cred->cr_groups + len, 0xff, 361 sizeof(cred->cr_groups) - (len * sizeof(cred->cr_groups[0]))); 362 363 cred->cr_ngroups = len; 364 365 return (0); 366 } 367 368 int 369 kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len) 370 { 371 KASSERT(cred != NULL); 372 KASSERT(len <= cred->cr_ngroups); 373 374 memset(grbuf, 0xff, sizeof(*grbuf) * len); 375 memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len); 376 377 return (0); 378 } 379 380 /* 381 * Match uids in two credentials. 382 */ 383 int 384 kauth_cred_uidmatch(kauth_cred_t cred1, kauth_cred_t cred2) 385 { 386 KASSERT(cred1 != NULL); 387 KASSERT(cred2 != NULL); 388 389 if (cred1->cr_uid == cred2->cr_uid || 390 cred1->cr_euid == cred2->cr_uid || 391 cred1->cr_uid == cred2->cr_euid || 392 cred1->cr_euid == cred2->cr_euid) 393 return (1); 394 395 return (0); 396 } 397 398 u_int 399 kauth_cred_getrefcnt(kauth_cred_t cred) 400 { 401 KASSERT(cred != NULL); 402 403 return (cred->cr_refcnt); 404 } 405 406 /* 407 * Convert userland credentials (struct uucred) to kauth_cred_t. 408 * XXX: For NFS & puffs 409 */ 410 void 411 kauth_uucred_to_cred(kauth_cred_t cred, const struct uucred *uuc) 412 { 413 KASSERT(cred != NULL); 414 KASSERT(uuc != NULL); 415 416 cred->cr_refcnt = 1; 417 cred->cr_uid = uuc->cr_uid; 418 cred->cr_euid = uuc->cr_uid; 419 cred->cr_svuid = uuc->cr_uid; 420 cred->cr_gid = uuc->cr_gid; 421 cred->cr_egid = uuc->cr_gid; 422 cred->cr_svgid = uuc->cr_gid; 423 cred->cr_ngroups = min(uuc->cr_ngroups, NGROUPS); 424 kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups), 425 cred->cr_ngroups, -1); 426 } 427 428 /* 429 * Convert kauth_cred_t to userland credentials (struct uucred). 430 * XXX: For NFS & puffs 431 */ 432 void 433 kauth_cred_to_uucred(struct uucred *uuc, const kauth_cred_t cred) 434 { 435 KASSERT(cred != NULL); 436 KASSERT(uuc != NULL); 437 int ng; 438 439 ng = min(cred->cr_ngroups, NGROUPS); 440 uuc->cr_uid = cred->cr_euid; 441 uuc->cr_gid = cred->cr_egid; 442 uuc->cr_ngroups = ng; 443 kauth_cred_getgroups(cred, uuc->cr_groups, ng); 444 } 445 446 /* 447 * Compare kauth_cred_t and uucred credentials. 448 * XXX: Modelled after crcmp() for NFS. 449 */ 450 int 451 kauth_cred_uucmp(kauth_cred_t cred, const struct uucred *uuc) 452 { 453 KASSERT(cred != NULL); 454 KASSERT(uuc != NULL); 455 456 if (cred->cr_euid == uuc->cr_uid && 457 cred->cr_egid == uuc->cr_gid && 458 cred->cr_ngroups == uuc->cr_ngroups) { 459 int i; 460 461 /* Check if all groups from uuc appear in cred. */ 462 for (i = 0; i < uuc->cr_ngroups; i++) { 463 int ismember; 464 465 ismember = 0; 466 if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i], 467 &ismember) != 0 || !ismember) 468 return (1); 469 } 470 471 return (0); 472 } 473 474 return (1); 475 } 476 477 /* 478 * Make a struct ucred out of a kauth_cred_t. For compatibility. 479 */ 480 void 481 kauth_cred_toucred(kauth_cred_t cred, struct ucred *uc) 482 { 483 KASSERT(cred != NULL); 484 KASSERT(uc != NULL); 485 486 uc->cr_ref = cred->cr_refcnt; 487 uc->cr_uid = cred->cr_euid; 488 uc->cr_gid = cred->cr_egid; 489 uc->cr_ngroups = min(cred->cr_ngroups, 490 sizeof(uc->cr_groups) / sizeof(uc->cr_groups[0])); 491 memcpy(uc->cr_groups, cred->cr_groups, 492 uc->cr_ngroups * sizeof(uc->cr_groups[0])); 493 } 494 495 /* 496 * Make a struct pcred out of a kauth_cred_t. For compatibility. 497 */ 498 void 499 kauth_cred_topcred(kauth_cred_t cred, struct pcred *pc) 500 { 501 KASSERT(cred != NULL); 502 KASSERT(pc != NULL); 503 504 pc->pc_ucred = NULL; 505 pc->p_ruid = cred->cr_uid; 506 pc->p_svuid = cred->cr_svuid; 507 pc->p_rgid = cred->cr_gid; 508 pc->p_svgid = cred->cr_svgid; 509 pc->p_refcnt = cred->cr_refcnt; 510 } 511 512 /* 513 * Return kauth_cred_t for the current LWP. 514 */ 515 kauth_cred_t 516 kauth_cred_get(void) 517 { 518 return (curlwp->l_cred); 519 } 520 521 /* 522 * Returns a scope matching the provided id. 523 * Requires the scope list lock to be held by the caller. 524 */ 525 static kauth_scope_t 526 kauth_ifindscope(const char *id) 527 { 528 kauth_scope_t scope; 529 530 /* XXX: assert lock on scope list? */ 531 532 scope = NULL; 533 SIMPLEQ_FOREACH(scope, &scope_list, next_scope) { 534 if (strcmp(scope->id, id) == 0) 535 break; 536 } 537 538 return (scope); 539 } 540 541 /* 542 * Register a new scope. 543 * 544 * id - identifier for the scope 545 * callback - the scope's default listener 546 * cookie - cookie to be passed to the listener(s) 547 */ 548 kauth_scope_t 549 kauth_register_scope(const char *id, kauth_scope_callback_t callback, 550 void *cookie) 551 { 552 kauth_scope_t scope; 553 kauth_listener_t listener = NULL; /* XXX gcc */ 554 555 /* Sanitize input */ 556 if (id == NULL) 557 return (NULL); 558 559 /* Allocate space for a new scope and listener. */ 560 scope = pool_get(&kauth_scope_pool, PR_WAITOK); 561 if (callback != NULL) { 562 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 563 } 564 565 /* Acquire scope list lock. */ 566 simple_lock(&scopes_lock); 567 568 /* Check we don't already have a scope with the same id */ 569 if (kauth_ifindscope(id) != NULL) { 570 simple_unlock(&scopes_lock); 571 572 pool_put(&kauth_scope_pool, scope); 573 if (callback != NULL) { 574 pool_put(&kauth_listener_pool, listener); 575 } 576 577 return (NULL); 578 } 579 580 /* Initialize new scope with parameters */ 581 scope->id = id; 582 scope->cookie = cookie; 583 scope->nlisteners = 1; 584 585 SIMPLEQ_INIT(&scope->listenq); 586 587 /* Add default listener */ 588 if (callback != NULL) { 589 listener->func = callback; 590 listener->scope = scope; 591 listener->refcnt = 0; 592 SIMPLEQ_INSERT_HEAD(&scope->listenq, listener, listener_next); 593 } 594 595 /* Insert scope to scopes list */ 596 SIMPLEQ_INSERT_TAIL(&scope_list, scope, next_scope); 597 598 simple_unlock(&scopes_lock); 599 600 return (scope); 601 } 602 603 /* 604 * Initialize the kernel authorization subsystem. 605 * 606 * Initialize the scopes list lock. 607 * Register built-in scopes: generic, process. 608 */ 609 void 610 kauth_init(void) 611 { 612 SIMPLEQ_INIT(&scope_list); 613 simple_lock_init(&scopes_lock); 614 615 /* Register generic scope. */ 616 kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC, 617 NULL, NULL); 618 619 /* Register system scope. */ 620 kauth_builtin_scope_system = kauth_register_scope(KAUTH_SCOPE_SYSTEM, 621 NULL, NULL); 622 623 /* Register process scope. */ 624 kauth_builtin_scope_process = kauth_register_scope(KAUTH_SCOPE_PROCESS, 625 NULL, NULL); 626 627 /* Register network scope. */ 628 kauth_builtin_scope_network = kauth_register_scope(KAUTH_SCOPE_NETWORK, 629 NULL, NULL); 630 631 /* Register machdep scope. */ 632 kauth_builtin_scope_machdep = kauth_register_scope(KAUTH_SCOPE_MACHDEP, 633 NULL, NULL); 634 635 /* Register device scope. */ 636 kauth_builtin_scope_device = kauth_register_scope(KAUTH_SCOPE_DEVICE, 637 NULL, NULL); 638 } 639 640 /* 641 * Deregister a scope. 642 * Requires scope list lock to be held by the caller. 643 * 644 * scope - the scope to deregister 645 */ 646 void 647 kauth_deregister_scope(kauth_scope_t scope) 648 { 649 if (scope != NULL) { 650 /* Remove scope from list */ 651 SIMPLEQ_REMOVE(&scope_list, scope, kauth_scope, next_scope); 652 } 653 } 654 655 /* 656 * Register a listener. 657 * 658 * id - scope identifier. 659 * callback - the callback routine for the listener. 660 * cookie - cookie to pass unmoidfied to the callback. 661 */ 662 kauth_listener_t 663 kauth_listen_scope(const char *id, kauth_scope_callback_t callback, 664 void *cookie) 665 { 666 kauth_scope_t scope; 667 kauth_listener_t listener; 668 669 /* Find scope struct */ 670 simple_lock(&scopes_lock); 671 scope = kauth_ifindscope(id); 672 simple_unlock(&scopes_lock); 673 if (scope == NULL) 674 return (NULL); 675 676 /* Allocate listener */ 677 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 678 679 /* Initialize listener with parameters */ 680 listener->func = callback; 681 listener->refcnt = 0; 682 683 /* Add listener to scope */ 684 SIMPLEQ_INSERT_TAIL(&scope->listenq, listener, listener_next); 685 686 /* Raise number of listeners on scope. */ 687 scope->nlisteners++; 688 listener->scope = scope; 689 690 listeners_have_been_loaded = TRUE; 691 692 return (listener); 693 } 694 695 /* 696 * Deregister a listener. 697 * 698 * listener - listener reference as returned from kauth_listen_scope(). 699 */ 700 void 701 kauth_unlisten_scope(kauth_listener_t listener) 702 { 703 if (listener != NULL) { 704 SIMPLEQ_REMOVE(&listener->scope->listenq, listener, 705 kauth_listener, listener_next); 706 listener->scope->nlisteners--; 707 } 708 } 709 710 /* 711 * Authorize a request. 712 * 713 * scope - the scope of the request as defined by KAUTH_SCOPE_* or as 714 * returned from kauth_register_scope(). 715 * credential - credentials of the user ("actor") making the request. 716 * action - request identifier. 717 * arg[0-3] - passed unmodified to listener(s). 718 */ 719 int 720 kauth_authorize_action(kauth_scope_t scope, kauth_cred_t cred, 721 kauth_action_t action, void *arg0, void *arg1, 722 void *arg2, void *arg3) 723 { 724 kauth_listener_t listener; 725 int error, allow, fail; 726 727 #if 0 /* defined(LOCKDEBUG) */ 728 spinlock_switchcheck(); 729 simple_lock_only_held(NULL, "kauth_authorize_action"); 730 #endif 731 732 KASSERT(cred != NULL); 733 KASSERT(action != 0); 734 735 /* Short-circuit requests coming from the kernel. */ 736 if (cred == NOCRED || cred == FSCRED) 737 return (0); 738 739 KASSERT(scope != NULL); 740 741 if (!listeners_have_been_loaded) { 742 KASSERT(SIMPLEQ_EMPTY(&scope->listenq)); 743 744 return (0); 745 } 746 747 fail = 0; 748 allow = 0; 749 SIMPLEQ_FOREACH(listener, &scope->listenq, listener_next) { 750 error = listener->func(cred, action, scope->cookie, arg0, 751 arg1, arg2, arg3); 752 753 if (error == KAUTH_RESULT_ALLOW) 754 allow = 1; 755 else if (error == KAUTH_RESULT_DENY) 756 fail = 1; 757 } 758 759 return ((allow && !fail) ? 0 : EPERM); 760 }; 761 762 /* 763 * Generic scope authorization wrapper. 764 */ 765 int 766 kauth_authorize_generic(kauth_cred_t cred, kauth_action_t action, void *arg0) 767 { 768 return (kauth_authorize_action(kauth_builtin_scope_generic, cred, 769 action, arg0, NULL, NULL, NULL)); 770 } 771 772 /* 773 * System scope authorization wrapper. 774 */ 775 int 776 kauth_authorize_system(kauth_cred_t cred, kauth_action_t action, 777 enum kauth_system_req req, void *arg1, void *arg2, void *arg3) 778 { 779 return (kauth_authorize_action(kauth_builtin_scope_system, cred, 780 action, (void *)req, arg1, arg2, arg3)); 781 } 782 783 /* 784 * Process scope authorization wrapper. 785 */ 786 int 787 kauth_authorize_process(kauth_cred_t cred, kauth_action_t action, 788 struct proc *p, void *arg1, void *arg2, void *arg3) 789 { 790 return (kauth_authorize_action(kauth_builtin_scope_process, cred, 791 action, p, arg1, arg2, arg3)); 792 } 793 794 /* 795 * Network scope authorization wrapper. 796 */ 797 int 798 kauth_authorize_network(kauth_cred_t cred, kauth_action_t action, 799 enum kauth_network_req req, void *arg1, void *arg2, void *arg3) 800 { 801 return (kauth_authorize_action(kauth_builtin_scope_network, cred, 802 action, (void *)req, arg1, arg2, arg3)); 803 } 804 805 int 806 kauth_authorize_machdep(kauth_cred_t cred, kauth_action_t action, 807 enum kauth_machdep_req req, void *arg1, void *arg2, void *arg3) 808 { 809 return (kauth_authorize_action(kauth_builtin_scope_machdep, cred, 810 action, (void *)req, arg1, arg2, arg3)); 811 } 812 813 int 814 kauth_authorize_device(kauth_cred_t cred, kauth_action_t action, 815 void *arg0, void *arg1, void *arg2, void *arg3) 816 { 817 return (kauth_authorize_action(kauth_builtin_scope_device, cred, 818 action, arg0, arg1, arg2, arg3)); 819 } 820 821 int 822 kauth_authorize_device_tty(kauth_cred_t cred, kauth_action_t action, 823 struct tty *tty) 824 { 825 return (kauth_authorize_action(kauth_builtin_scope_device, cred, 826 action, tty, NULL, NULL, NULL)); 827 } 828 829 int 830 kauth_authorize_device_spec(kauth_cred_t cred, enum kauth_device_req req, 831 struct vnode *vp) 832 { 833 return (kauth_authorize_action(kauth_builtin_scope_device, cred, 834 KAUTH_DEVICE_RAWIO_SPEC, (void *)req, vp, NULL, NULL)); 835 } 836 837 int 838 kauth_authorize_device_passthru(kauth_cred_t cred, dev_t dev, void *data) 839 { 840 return (kauth_authorize_action(kauth_builtin_scope_device, cred, 841 KAUTH_DEVICE_RAWIO_PASSTHRU, 0, (void *)(u_long)dev, data, 842 NULL)); 843 } 844