1*e4a9863fSDag-Erling Smørgrav /* $OpenBSD: groupaccess.c,v 1.14 2013/05/17 00:13:13 djm Exp $ */ 21e8db6e2SBrian Feldman /* 31e8db6e2SBrian Feldman * Copyright (c) 2001 Kevin Steves. All rights reserved. 41e8db6e2SBrian Feldman * 51e8db6e2SBrian Feldman * Redistribution and use in source and binary forms, with or without 61e8db6e2SBrian Feldman * modification, are permitted provided that the following conditions 71e8db6e2SBrian Feldman * are met: 81e8db6e2SBrian Feldman * 1. Redistributions of source code must retain the above copyright 91e8db6e2SBrian Feldman * notice, this list of conditions and the following disclaimer. 101e8db6e2SBrian Feldman * 2. Redistributions in binary form must reproduce the above copyright 111e8db6e2SBrian Feldman * notice, this list of conditions and the following disclaimer in the 121e8db6e2SBrian Feldman * documentation and/or other materials provided with the distribution. 131e8db6e2SBrian Feldman * 141e8db6e2SBrian Feldman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 151e8db6e2SBrian Feldman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 161e8db6e2SBrian Feldman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 171e8db6e2SBrian Feldman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 181e8db6e2SBrian Feldman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 191e8db6e2SBrian Feldman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 201e8db6e2SBrian Feldman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 211e8db6e2SBrian Feldman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 221e8db6e2SBrian Feldman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 231e8db6e2SBrian Feldman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 241e8db6e2SBrian Feldman */ 251e8db6e2SBrian Feldman 261e8db6e2SBrian Feldman #include "includes.h" 271e8db6e2SBrian Feldman 28761efaa7SDag-Erling Smørgrav #include <sys/types.h> 29761efaa7SDag-Erling Smørgrav #include <sys/param.h> 30761efaa7SDag-Erling Smørgrav 31761efaa7SDag-Erling Smørgrav #include <grp.h> 32761efaa7SDag-Erling Smørgrav #include <unistd.h> 33761efaa7SDag-Erling Smørgrav #include <stdarg.h> 34*e4a9863fSDag-Erling Smørgrav #include <stdlib.h> 35d4af9e69SDag-Erling Smørgrav #include <string.h> 36761efaa7SDag-Erling Smørgrav 371e8db6e2SBrian Feldman #include "xmalloc.h" 38761efaa7SDag-Erling Smørgrav #include "groupaccess.h" 391e8db6e2SBrian Feldman #include "match.h" 401e8db6e2SBrian Feldman #include "log.h" 411e8db6e2SBrian Feldman 421e8db6e2SBrian Feldman static int ngroups; 43efcad6b7SDag-Erling Smørgrav static char **groups_byname; 441e8db6e2SBrian Feldman 45ae1f160dSDag-Erling Smørgrav /* 46ae1f160dSDag-Erling Smørgrav * Initialize group access list for user with primary (base) and 47ae1f160dSDag-Erling Smørgrav * supplementary groups. Return the number of groups in the list. 48ae1f160dSDag-Erling Smørgrav */ 491e8db6e2SBrian Feldman int 501e8db6e2SBrian Feldman ga_init(const char *user, gid_t base) 511e8db6e2SBrian Feldman { 52efcad6b7SDag-Erling Smørgrav gid_t *groups_bygid; 531e8db6e2SBrian Feldman int i, j; 541e8db6e2SBrian Feldman struct group *gr; 551e8db6e2SBrian Feldman 561e8db6e2SBrian Feldman if (ngroups > 0) 571e8db6e2SBrian Feldman ga_free(); 581e8db6e2SBrian Feldman 59efcad6b7SDag-Erling Smørgrav ngroups = NGROUPS_MAX; 60efcad6b7SDag-Erling Smørgrav #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) 61efcad6b7SDag-Erling Smørgrav ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); 62efcad6b7SDag-Erling Smørgrav #endif 63efcad6b7SDag-Erling Smørgrav 64761efaa7SDag-Erling Smørgrav groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); 65761efaa7SDag-Erling Smørgrav groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 66efcad6b7SDag-Erling Smørgrav 671e8db6e2SBrian Feldman if (getgrouplist(user, base, groups_bygid, &ngroups) == -1) 68d95e11bfSDag-Erling Smørgrav logit("getgrouplist: groups list too small"); 691e8db6e2SBrian Feldman for (i = 0, j = 0; i < ngroups; i++) 701e8db6e2SBrian Feldman if ((gr = getgrgid(groups_bygid[i])) != NULL) 711e8db6e2SBrian Feldman groups_byname[j++] = xstrdup(gr->gr_name); 72*e4a9863fSDag-Erling Smørgrav free(groups_bygid); 731e8db6e2SBrian Feldman return (ngroups = j); 741e8db6e2SBrian Feldman } 751e8db6e2SBrian Feldman 76ae1f160dSDag-Erling Smørgrav /* 77ae1f160dSDag-Erling Smørgrav * Return 1 if one of user's groups is contained in groups. 78ae1f160dSDag-Erling Smørgrav * Return 0 otherwise. Use match_pattern() for string comparison. 79ae1f160dSDag-Erling Smørgrav */ 801e8db6e2SBrian Feldman int 811e8db6e2SBrian Feldman ga_match(char * const *groups, int n) 821e8db6e2SBrian Feldman { 831e8db6e2SBrian Feldman int i, j; 841e8db6e2SBrian Feldman 851e8db6e2SBrian Feldman for (i = 0; i < ngroups; i++) 861e8db6e2SBrian Feldman for (j = 0; j < n; j++) 871e8db6e2SBrian Feldman if (match_pattern(groups_byname[i], groups[j])) 881e8db6e2SBrian Feldman return 1; 891e8db6e2SBrian Feldman return 0; 901e8db6e2SBrian Feldman } 911e8db6e2SBrian Feldman 92ae1f160dSDag-Erling Smørgrav /* 93d4af9e69SDag-Erling Smørgrav * Return 1 if one of user's groups matches group_pattern list. 94d4af9e69SDag-Erling Smørgrav * Return 0 on negated or no match. 95d4af9e69SDag-Erling Smørgrav */ 96d4af9e69SDag-Erling Smørgrav int 97d4af9e69SDag-Erling Smørgrav ga_match_pattern_list(const char *group_pattern) 98d4af9e69SDag-Erling Smørgrav { 99d4af9e69SDag-Erling Smørgrav int i, found = 0; 100d4af9e69SDag-Erling Smørgrav size_t len = strlen(group_pattern); 101d4af9e69SDag-Erling Smørgrav 102d4af9e69SDag-Erling Smørgrav for (i = 0; i < ngroups; i++) { 103d4af9e69SDag-Erling Smørgrav switch (match_pattern_list(groups_byname[i], 104d4af9e69SDag-Erling Smørgrav group_pattern, len, 0)) { 105d4af9e69SDag-Erling Smørgrav case -1: 106d4af9e69SDag-Erling Smørgrav return 0; /* Negated match wins */ 107d4af9e69SDag-Erling Smørgrav case 0: 108d4af9e69SDag-Erling Smørgrav continue; 109d4af9e69SDag-Erling Smørgrav case 1: 110d4af9e69SDag-Erling Smørgrav found = 1; 111d4af9e69SDag-Erling Smørgrav } 112d4af9e69SDag-Erling Smørgrav } 113d4af9e69SDag-Erling Smørgrav return found; 114d4af9e69SDag-Erling Smørgrav } 115d4af9e69SDag-Erling Smørgrav 116d4af9e69SDag-Erling Smørgrav /* 117ae1f160dSDag-Erling Smørgrav * Free memory allocated for group access list. 118ae1f160dSDag-Erling Smørgrav */ 1191e8db6e2SBrian Feldman void 1201e8db6e2SBrian Feldman ga_free(void) 1211e8db6e2SBrian Feldman { 1221e8db6e2SBrian Feldman int i; 1231e8db6e2SBrian Feldman 1241e8db6e2SBrian Feldman if (ngroups > 0) { 1251e8db6e2SBrian Feldman for (i = 0; i < ngroups; i++) 126*e4a9863fSDag-Erling Smørgrav free(groups_byname[i]); 1271e8db6e2SBrian Feldman ngroups = 0; 128*e4a9863fSDag-Erling Smørgrav free(groups_byname); 1291e8db6e2SBrian Feldman } 1301e8db6e2SBrian Feldman } 131