Home | History | Annotate | Download | only in openssh
      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 #include "xmalloc.h"
     37 #include "groupaccess.h"
     38 #include "match.h"
     39 #include "log.h"
     40 
     41 static int ngroups;
     42 static char **groups_byname;
     43 
     44 /*
     45  * Initialize group access list for user with primary (base) and
     46  * supplementary groups.  Return the number of groups in the list.
     47  */
     48 int
     49 ga_init(const char *user, gid_t base)
     50 {
     51 #ifdef ANDROID
     52 	return 0;
     53 #else
     54 	gid_t *groups_bygid;
     55 	int i, j;
     56 	struct group *gr;
     57 
     58 	if (ngroups > 0)
     59 		ga_free();
     60 
     61 	ngroups = NGROUPS_MAX;
     62 #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
     63 	ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX));
     64 #endif
     65 
     66 	groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
     67 	groups_byname = xcalloc(ngroups, sizeof(*groups_byname));
     68 
     69 	if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
     70 		logit("getgrouplist: groups list too small");
     71 	for (i = 0, j = 0; i < ngroups; i++)
     72 		if ((gr = getgrgid(groups_bygid[i])) != NULL)
     73 			groups_byname[j++] = xstrdup(gr->gr_name);
     74 	xfree(groups_bygid);
     75 	return (ngroups = j);
     76 #endif
     77 }
     78 
     79 /*
     80  * Return 1 if one of user's groups is contained in groups.
     81  * Return 0 otherwise.  Use match_pattern() for string comparison.
     82  */
     83 int
     84 ga_match(char * const *groups, int n)
     85 {
     86 	int i, j;
     87 
     88 	for (i = 0; i < ngroups; i++)
     89 		for (j = 0; j < n; j++)
     90 			if (match_pattern(groups_byname[i], groups[j]))
     91 				return 1;
     92 	return 0;
     93 }
     94 
     95 /*
     96  * Return 1 if one of user's groups matches group_pattern list.
     97  * Return 0 on negated or no match.
     98  */
     99 int
    100 ga_match_pattern_list(const char *group_pattern)
    101 {
    102 	int i, found = 0;
    103 	size_t len = strlen(group_pattern);
    104 
    105 	for (i = 0; i < ngroups; i++) {
    106 		switch (match_pattern_list(groups_byname[i],
    107 		    group_pattern, len, 0)) {
    108 		case -1:
    109 			return 0;	/* Negated match wins */
    110 		case 0:
    111 			continue;
    112 		case 1:
    113 			found = 1;
    114 		}
    115 	}
    116 	return found;
    117 }
    118 
    119 /*
    120  * Free memory allocated for group access list.
    121  */
    122 void
    123 ga_free(void)
    124 {
    125 	int i;
    126 
    127 	if (ngroups > 0) {
    128 		for (i = 0; i < ngroups; i++)
    129 			xfree(groups_byname[i]);
    130 		ngroups = 0;
    131 		xfree(groups_byname);
    132 	}
    133 }
    134