1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 /* 6 * Copyright (c) 2001 Kevin Steves. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "includes.h" 30 RCSID("$OpenBSD: groupaccess.c,v 1.5 2002/03/04 17:27:39 stevesk Exp $"); 31 32 #include "groupaccess.h" 33 #include "xmalloc.h" 34 #include "match.h" 35 #include "log.h" 36 #include <alloca.h> 37 38 static int ngroups, ngroups_lim; 39 static char **groups_byname; 40 41 /* 42 * Initialize group access list for user with primary (base) and 43 * supplementary groups. Return the number of groups in the list. 44 */ 45 int 46 ga_init(const char *user, gid_t base) 47 { 48 gid_t *groups_bygid; 49 int i, j; 50 struct group *gr; 51 52 if (ngroups_lim == 0) { 53 /* Add one for the base gid */ 54 ngroups_lim = sysconf(_SC_NGROUPS_MAX) + 1; 55 groups_byname = malloc(sizeof (char *) * ngroups_lim); 56 } else if (ngroups > 0) 57 ga_free(); 58 59 groups_bygid = alloca(ngroups_lim * sizeof (gid_t)); 60 61 ngroups = ngroups_lim; 62 if (getgrouplist(user, base, groups_bygid, &ngroups) == -1) 63 log("getgrouplist: groups list too small"); 64 for (i = 0, j = 0; i < ngroups; i++) 65 if ((gr = getgrgid(groups_bygid[i])) != NULL) 66 groups_byname[j++] = xstrdup(gr->gr_name); 67 return (ngroups = j); 68 } 69 70 /* 71 * Return 1 if one of user's groups is contained in groups. 72 * Return 0 otherwise. Use match_pattern() for string comparison. 73 */ 74 int 75 ga_match(char * const *groups, int n) 76 { 77 int i, j; 78 79 for (i = 0; i < ngroups; i++) 80 for (j = 0; j < n; j++) 81 if (match_pattern(groups_byname[i], groups[j])) 82 return (1); 83 return (0); 84 } 85 86 /* 87 * Return 1 if one of user's groups matches group_pattern list. 88 * Return 0 on negated or no match. 89 */ 90 int 91 ga_match_pattern_list(const char *group_pattern) 92 { 93 int i, found = 0; 94 size_t len = strlen(group_pattern); 95 96 for (i = 0; i < ngroups; i++) { 97 switch (match_pattern_list(groups_byname[i], 98 group_pattern, len, 0)) { 99 case -1: 100 return (0); /* Negated match wins */ 101 case 0: 102 continue; 103 case 1: 104 found = 1; 105 } 106 } 107 return (found); 108 } 109 110 /* 111 * Free memory allocated for group access list. 112 */ 113 void 114 ga_free(void) 115 { 116 int i; 117 118 if (ngroups > 0) { 119 for (i = 0; i < ngroups; i++) 120 xfree(groups_byname[i]); 121 ngroups = 0; 122 } 123 } 124