prepare to upload
[debian/sudo] / compat / getgrouplist.c
1 /*
2  * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <stdio.h>
21 #ifdef STDC_HEADERS
22 # include <stdlib.h>
23 # include <stddef.h>
24 #else
25 # ifdef HAVE_STDLIB_H
26 #  include <stdlib.h>
27 # endif
28 #endif /* STDC_HEADERS */
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #endif /* HAVE_STRING_H */
32 #ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 #endif /* HAVE_STRINGS_H */
35 #include <grp.h>
36
37 #include "missing.h"
38
39 #ifdef HAVE_GETGRSET
40 /*
41  * BSD-compatible getgrouplist(3) using getgrset(3)
42  */
43 int
44 getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp)
45 {
46     char *cp, *grset = NULL;
47     int i, ngroups = 1;
48     int grpsize = *ngroupsp;
49     int rval = -1;
50     gid_t gid;
51
52     /* We support BSD semantics where the first element is the base gid */
53     if (grpsize <= 0)
54         return -1;
55     groups[0] = basegid;
56
57 #ifdef HAVE_SETAUTHDB
58     aix_setauthdb((char *) name);
59 #endif
60     if ((grset = getgrset(name)) != NULL) {
61         for (cp = strtok(grset, ","); cp != NULL; cp = strtok(NULL, ",")) {
62             gid = atoi(cp);
63             if (gid != basegid) {
64                 if (ngroups == grpsize)
65                     goto done;
66                 groups[ngroups++] = gid;
67             }
68         }
69     }
70     rval = 0;
71
72 done:
73     efree(grset);
74 #ifdef HAVE_SETAUTHDB
75     aix_restoreauthdb();
76 #endif
77     *ngroupsp = ngroups;
78
79     return rval;
80 }
81
82 #else /* HAVE_GETGRSET */
83
84 /*
85  * BSD-compatible getgrouplist(3) using getgrent(3)
86  */
87 int
88 getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp)
89 {
90     int i, ngroups = 1;
91     int grpsize = *ngroupsp;
92     int rval = -1;
93     struct group *grp;
94
95     /* We support BSD semantics where the first element is the base gid */
96     if (grpsize <= 0)
97         return -1;
98     groups[0] = basegid;
99
100     setgrent();
101     while ((grp = getgrent()) != NULL) {
102         if (grp->gr_gid == basegid)
103             continue;
104
105         for (i = 0; grp->gr_mem[i] != NULL; i++) {
106             if (strcmp(name, grp->gr_mem[i]) == 0)
107                 break;
108         }
109         if (grp->gr_mem[i] == NULL)
110             continue; /* user not found */
111
112         /* Only add if it is not the same as an existing gid */
113         for (i = 0; i < ngroups; i++) {
114             if (grp->gr_gid == groups[i])
115                 break;
116         }
117         if (i == ngroups) {
118             if (ngroups == grpsize)
119                 goto done;
120             groups[ngroups++] = grp->gr_gid;
121         }
122     }
123     rval = 0;
124
125 done:
126     endgrent();
127     *ngroupsp = ngroups;
128
129     return rval;
130 }
131 #endif /* HAVE_GETGRSET */