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