[BACK]Return to kern_auth.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_auth.c, Revision 1.3.2.6

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

CVSweb <webmaster@jp.NetBSD.org>