1/* $OpenBSD: groupaccess.c,v 1.13 2008/07/04 03:44:59 djm Exp $ */ 2/* 3 * Copyright (c) 2001 Kevin Steves. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "includes.h" 27 28#include <sys/types.h> 29#include <sys/param.h> 30 31#include <grp.h> 32#include <unistd.h> 33#include <stdarg.h> 34#include <string.h> 35 36#ifdef __APPLE_MEMBERSHIP__ 37#include <membership.h> 38#endif 39 40#include "xmalloc.h" 41#include "groupaccess.h" 42#include "match.h" 43#include "log.h" 44 45#ifdef __APPLE_MEMBERSHIP__ 46// SPI for 5235093 47int32_t getgrouplist_2(const char *, gid_t, gid_t **); 48int32_t getgroupcount(const char *, gid_t); 49#endif 50 51static int ngroups; 52static char **groups_byname; 53#ifdef __APPLE_MEMBERSHIP__ 54uuid_t u_uuid; 55#endif 56 57/* 58 * Initialize group access list for user with primary (base) and 59 * supplementary groups. Return the number of groups in the list. 60 */ 61int 62ga_init(struct passwd *pw) 63{ 64 gid_t *groups_bygid = NULL; 65 int i, j; 66 struct group *gr; 67 68#ifdef __APPLE_MEMBERSHIP__ 69 if (0 != mbr_uid_to_uuid(pw->pw_uid, u_uuid)) 70 return 0; 71#endif 72 73 if (ngroups > 0) 74 ga_free(); 75 76#ifndef __APPLE_MEMBERSHIP__ 77 ngroups = NGROUPS_MAX; 78#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) 79 ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); 80#endif 81 groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); 82#else 83 if (-1 == (ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid, 84 &groups_bygid))) { 85 logit("getgrouplist_2 failed"); 86 /* 87 * getgrouplist_2 only fails on memory error; in which case 88 * groups_bygid will be left NULL so no need to free. 89 */ 90 return 0; 91 } 92#endif 93 groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 94#ifndef __APPLE_MEMBERSHIP__ 95 if (getgrouplist(pw->pw_name, pw->pw_gid, groups_bygid, &ngroups) == -1) { 96 logit("getgrouplist: groups list too small"); 97 xfree(groups_bygid); 98 return 0; 99 } 100#endif 101 for (i = 0, j = 0; i < ngroups; i++) 102 if ((gr = getgrgid(groups_bygid[i])) != NULL) 103 groups_byname[j++] = xstrdup(gr->gr_name); 104 xfree(groups_bygid); 105 return (ngroups = j); 106} 107 108/* 109 * Return 1 if one of user's groups is contained in groups. 110 * Return 0 otherwise. Use match_pattern() for string comparison. 111 * Use mbr_check_membership() for membership checking on Mac OS X. 112 */ 113int 114ga_match(char * const *groups, int n) 115{ 116 int i, j; 117 118 for (i = 0; i < ngroups; i++) 119 for (j = 0; j < n; j++) 120 if (match_pattern(groups_byname[i], groups[j])) 121 return 1; 122 return 0; 123} 124 125/* 126 * Return 1 if one of user's groups matches group_pattern list. 127 * Return 0 on negated or no match. 128 */ 129int 130ga_match_pattern_list(const char *group_pattern) 131{ 132 int i, found = 0; 133 size_t len = strlen(group_pattern); 134 135 for (i = 0; i < ngroups; i++) { 136 switch (match_pattern_list(groups_byname[i], 137 group_pattern, len, 0)) { 138 case -1: 139 return 0; /* Negated match wins */ 140 case 0: 141 continue; 142 case 1: 143 found = 1; 144 } 145 } 146 return found; 147} 148 149/* 150 * Free memory allocated for group access list. 151 */ 152void 153ga_free(void) 154{ 155 int i; 156 157 if (ngroups > 0) { 158 for (i = 0; i < ngroups; i++) 159 xfree(groups_byname[i]); 160 ngroups = 0; 161 xfree(groups_byname); 162 } 163} 164