The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_auth.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f6258c7fd4525f3022a965efb2794520


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.