1294336Sdes/* $OpenBSD: groupaccess.c,v 1.16 2015/05/04 06:10:48 djm Exp $ */ 276259Sgreen/* 376259Sgreen * Copyright (c) 2001 Kevin Steves. All rights reserved. 476259Sgreen * 576259Sgreen * Redistribution and use in source and binary forms, with or without 676259Sgreen * modification, are permitted provided that the following conditions 776259Sgreen * are met: 876259Sgreen * 1. Redistributions of source code must retain the above copyright 976259Sgreen * notice, this list of conditions and the following disclaimer. 1076259Sgreen * 2. Redistributions in binary form must reproduce the above copyright 1176259Sgreen * notice, this list of conditions and the following disclaimer in the 1276259Sgreen * documentation and/or other materials provided with the distribution. 1376259Sgreen * 1476259Sgreen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1576259Sgreen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1676259Sgreen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1776259Sgreen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1876259Sgreen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1976259Sgreen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2076259Sgreen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2176259Sgreen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2276259Sgreen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2376259Sgreen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2476259Sgreen */ 2576259Sgreen 2676259Sgreen#include "includes.h" 2776259Sgreen 28162852Sdes#include <sys/types.h> 29162852Sdes 30162852Sdes#include <grp.h> 31162852Sdes#include <unistd.h> 32162852Sdes#include <stdarg.h> 33255767Sdes#include <stdlib.h> 34181111Sdes#include <string.h> 35294332Sdes#include <limits.h> 36162852Sdes 37162852Sdes#include "xmalloc.h" 3876259Sgreen#include "groupaccess.h" 3976259Sgreen#include "match.h" 4076259Sgreen#include "log.h" 4176259Sgreen 4276259Sgreenstatic int ngroups; 43126274Sdesstatic char **groups_byname; 4476259Sgreen 4592555Sdes/* 4692555Sdes * Initialize group access list for user with primary (base) and 4792555Sdes * supplementary groups. Return the number of groups in the list. 4892555Sdes */ 4976259Sgreenint 5076259Sgreenga_init(const char *user, gid_t base) 5176259Sgreen{ 52126274Sdes gid_t *groups_bygid; 5376259Sgreen int i, j; 5476259Sgreen struct group *gr; 5576259Sgreen 5676259Sgreen if (ngroups > 0) 5776259Sgreen ga_free(); 5876259Sgreen 59126274Sdes ngroups = NGROUPS_MAX; 60126274Sdes#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) 61126274Sdes ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); 62126274Sdes#endif 63126274Sdes 64162852Sdes groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); 65162852Sdes groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 66126274Sdes 6776259Sgreen if (getgrouplist(user, base, groups_bygid, &ngroups) == -1) 68124208Sdes logit("getgrouplist: groups list too small"); 6976259Sgreen for (i = 0, j = 0; i < ngroups; i++) 7076259Sgreen if ((gr = getgrgid(groups_bygid[i])) != NULL) 7176259Sgreen groups_byname[j++] = xstrdup(gr->gr_name); 72255767Sdes free(groups_bygid); 7376259Sgreen return (ngroups = j); 7476259Sgreen} 7576259Sgreen 7692555Sdes/* 7792555Sdes * Return 1 if one of user's groups is contained in groups. 7892555Sdes * Return 0 otherwise. Use match_pattern() for string comparison. 7992555Sdes */ 8076259Sgreenint 8176259Sgreenga_match(char * const *groups, int n) 8276259Sgreen{ 8376259Sgreen int i, j; 8476259Sgreen 8576259Sgreen for (i = 0; i < ngroups; i++) 8676259Sgreen for (j = 0; j < n; j++) 8776259Sgreen if (match_pattern(groups_byname[i], groups[j])) 8876259Sgreen return 1; 8976259Sgreen return 0; 9076259Sgreen} 9176259Sgreen 9292555Sdes/* 93181111Sdes * Return 1 if one of user's groups matches group_pattern list. 94181111Sdes * Return 0 on negated or no match. 95181111Sdes */ 96181111Sdesint 97181111Sdesga_match_pattern_list(const char *group_pattern) 98181111Sdes{ 99181111Sdes int i, found = 0; 100181111Sdes 101181111Sdes for (i = 0; i < ngroups; i++) { 102294336Sdes switch (match_pattern_list(groups_byname[i], group_pattern, 0)) { 103181111Sdes case -1: 104181111Sdes return 0; /* Negated match wins */ 105181111Sdes case 0: 106181111Sdes continue; 107181111Sdes case 1: 108181111Sdes found = 1; 109181111Sdes } 110181111Sdes } 111181111Sdes return found; 112181111Sdes} 113181111Sdes 114181111Sdes/* 11592555Sdes * Free memory allocated for group access list. 11692555Sdes */ 11776259Sgreenvoid 11876259Sgreenga_free(void) 11976259Sgreen{ 12076259Sgreen int i; 12176259Sgreen 12276259Sgreen if (ngroups > 0) { 12376259Sgreen for (i = 0; i < ngroups; i++) 124255767Sdes free(groups_byname[i]); 12576259Sgreen ngroups = 0; 126255767Sdes free(groups_byname); 12776259Sgreen } 12876259Sgreen} 129