1557f75e5SDag-Erling Smørgrav /* $OpenBSD: groupaccess.c,v 1.16 2015/05/04 06:10:48 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 30761efaa7SDag-Erling Smørgrav #include <grp.h> 31761efaa7SDag-Erling Smørgrav #include <unistd.h> 32761efaa7SDag-Erling Smørgrav #include <stdarg.h> 33e4a9863fSDag-Erling Smørgrav #include <stdlib.h> 34d4af9e69SDag-Erling Smørgrav #include <string.h> 35bc5531deSDag-Erling Smørgrav #include <limits.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; 53*2f513db7SEd Maste int i, j, retry = 0; 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)); 65*2f513db7SEd Maste while (getgrouplist(user, base, groups_bygid, &ngroups) == -1) { 66*2f513db7SEd Maste if (retry++ > 0) 67*2f513db7SEd Maste fatal("getgrouplist: groups list too small"); 68*2f513db7SEd Maste groups_bygid = xreallocarray(groups_bygid, ngroups, 69*2f513db7SEd Maste sizeof(*groups_bygid)); 70*2f513db7SEd Maste } 71761efaa7SDag-Erling Smørgrav groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 72efcad6b7SDag-Erling Smørgrav 731e8db6e2SBrian Feldman for (i = 0, j = 0; i < ngroups; i++) 741e8db6e2SBrian Feldman if ((gr = getgrgid(groups_bygid[i])) != NULL) 751e8db6e2SBrian Feldman groups_byname[j++] = xstrdup(gr->gr_name); 76e4a9863fSDag-Erling Smørgrav free(groups_bygid); 771e8db6e2SBrian Feldman return (ngroups = j); 781e8db6e2SBrian Feldman } 791e8db6e2SBrian Feldman 80ae1f160dSDag-Erling Smørgrav /* 81ae1f160dSDag-Erling Smørgrav * Return 1 if one of user's groups is contained in groups. 82ae1f160dSDag-Erling Smørgrav * Return 0 otherwise. Use match_pattern() for string comparison. 83ae1f160dSDag-Erling Smørgrav */ 841e8db6e2SBrian Feldman int 851e8db6e2SBrian Feldman ga_match(char * const *groups, int n) 861e8db6e2SBrian Feldman { 871e8db6e2SBrian Feldman int i, j; 881e8db6e2SBrian Feldman 891e8db6e2SBrian Feldman for (i = 0; i < ngroups; i++) 901e8db6e2SBrian Feldman for (j = 0; j < n; j++) 911e8db6e2SBrian Feldman if (match_pattern(groups_byname[i], groups[j])) 921e8db6e2SBrian Feldman return 1; 931e8db6e2SBrian Feldman return 0; 941e8db6e2SBrian Feldman } 951e8db6e2SBrian Feldman 96ae1f160dSDag-Erling Smørgrav /* 97d4af9e69SDag-Erling Smørgrav * Return 1 if one of user's groups matches group_pattern list. 98d4af9e69SDag-Erling Smørgrav * Return 0 on negated or no match. 99d4af9e69SDag-Erling Smørgrav */ 100d4af9e69SDag-Erling Smørgrav int 101d4af9e69SDag-Erling Smørgrav ga_match_pattern_list(const char *group_pattern) 102d4af9e69SDag-Erling Smørgrav { 103d4af9e69SDag-Erling Smørgrav int i, found = 0; 104d4af9e69SDag-Erling Smørgrav 105d4af9e69SDag-Erling Smørgrav for (i = 0; i < ngroups; i++) { 106557f75e5SDag-Erling Smørgrav switch (match_pattern_list(groups_byname[i], group_pattern, 0)) { 107d4af9e69SDag-Erling Smørgrav case -1: 108d4af9e69SDag-Erling Smørgrav return 0; /* Negated match wins */ 109d4af9e69SDag-Erling Smørgrav case 0: 110d4af9e69SDag-Erling Smørgrav continue; 111d4af9e69SDag-Erling Smørgrav case 1: 112d4af9e69SDag-Erling Smørgrav found = 1; 113d4af9e69SDag-Erling Smørgrav } 114d4af9e69SDag-Erling Smørgrav } 115d4af9e69SDag-Erling Smørgrav return found; 116d4af9e69SDag-Erling Smørgrav } 117d4af9e69SDag-Erling Smørgrav 118d4af9e69SDag-Erling Smørgrav /* 119ae1f160dSDag-Erling Smørgrav * Free memory allocated for group access list. 120ae1f160dSDag-Erling Smørgrav */ 1211e8db6e2SBrian Feldman void 1221e8db6e2SBrian Feldman ga_free(void) 1231e8db6e2SBrian Feldman { 1241e8db6e2SBrian Feldman int i; 1251e8db6e2SBrian Feldman 1261e8db6e2SBrian Feldman if (ngroups > 0) { 1271e8db6e2SBrian Feldman for (i = 0; i < ngroups; i++) 128e4a9863fSDag-Erling Smørgrav free(groups_byname[i]); 1291e8db6e2SBrian Feldman ngroups = 0; 130e4a9863fSDag-Erling Smørgrav free(groups_byname); 131*2f513db7SEd Maste groups_byname = NULL; 1321e8db6e2SBrian Feldman } 1331e8db6e2SBrian Feldman } 134