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>