1*2fe8fb19SBen Gras /* $NetBSD: getgroupmembership.c,v 1.4 2008/04/28 20:22:59 martin Exp $ */
2*2fe8fb19SBen Gras
3*2fe8fb19SBen Gras /*-
4*2fe8fb19SBen Gras * Copyright (c) 2004-2005 The NetBSD Foundation, Inc.
5*2fe8fb19SBen Gras * All rights reserved.
6*2fe8fb19SBen Gras *
7*2fe8fb19SBen Gras * This code is derived from software contributed to The NetBSD Foundation
8*2fe8fb19SBen Gras * by Luke Mewburn.
9*2fe8fb19SBen Gras *
10*2fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
11*2fe8fb19SBen Gras * modification, are permitted provided that the following conditions
12*2fe8fb19SBen Gras * are met:
13*2fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
14*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
15*2fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
16*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
17*2fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
18*2fe8fb19SBen Gras *
19*2fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*2fe8fb19SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*2fe8fb19SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*2fe8fb19SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*2fe8fb19SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*2fe8fb19SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*2fe8fb19SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*2fe8fb19SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*2fe8fb19SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*2fe8fb19SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*2fe8fb19SBen Gras * POSSIBILITY OF SUCH DAMAGE.
30*2fe8fb19SBen Gras */
31*2fe8fb19SBen Gras
32*2fe8fb19SBen Gras #include <sys/cdefs.h>
33*2fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
34*2fe8fb19SBen Gras __RCSID("$NetBSD: getgroupmembership.c,v 1.4 2008/04/28 20:22:59 martin Exp $");
35*2fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
36*2fe8fb19SBen Gras
37*2fe8fb19SBen Gras /*
38*2fe8fb19SBen Gras * calculate group access list
39*2fe8fb19SBen Gras */
40*2fe8fb19SBen Gras
41*2fe8fb19SBen Gras #include "namespace.h"
42*2fe8fb19SBen Gras #include "reentrant.h"
43*2fe8fb19SBen Gras
44*2fe8fb19SBen Gras #include <sys/param.h>
45*2fe8fb19SBen Gras
46*2fe8fb19SBen Gras #include <assert.h>
47*2fe8fb19SBen Gras #include <errno.h>
48*2fe8fb19SBen Gras #include <grp.h>
49*2fe8fb19SBen Gras #include <limits.h>
50*2fe8fb19SBen Gras #include <nsswitch.h>
51*2fe8fb19SBen Gras #include <stdarg.h>
52*2fe8fb19SBen Gras #include <stdio.h>
53*2fe8fb19SBen Gras #include <stdlib.h>
54*2fe8fb19SBen Gras #include <string.h>
55*2fe8fb19SBen Gras #include <unistd.h>
56*2fe8fb19SBen Gras
57*2fe8fb19SBen Gras #ifdef HESIOD
58*2fe8fb19SBen Gras #include <hesiod.h>
59*2fe8fb19SBen Gras #endif
60*2fe8fb19SBen Gras
61*2fe8fb19SBen Gras #include "gr_private.h"
62*2fe8fb19SBen Gras
63*2fe8fb19SBen Gras #ifdef __weak_alias
__weak_alias(getgroupmembership,_getgroupmembership)64*2fe8fb19SBen Gras __weak_alias(getgroupmembership,_getgroupmembership)
65*2fe8fb19SBen Gras #endif
66*2fe8fb19SBen Gras
67*2fe8fb19SBen Gras /*
68*2fe8fb19SBen Gras * __gr_addgid
69*2fe8fb19SBen Gras * Add gid to the groups array (of maxgrp size) at the position
70*2fe8fb19SBen Gras * indicated by *groupc, unless it already exists or *groupc is
71*2fe8fb19SBen Gras * past &groups[maxgrp].
72*2fe8fb19SBen Gras * Returns 1 upon success (including duplicate suppression), 0 otherwise.
73*2fe8fb19SBen Gras */
74*2fe8fb19SBen Gras static int
75*2fe8fb19SBen Gras __gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *groupc)
76*2fe8fb19SBen Gras {
77*2fe8fb19SBen Gras int ret, dupc;
78*2fe8fb19SBen Gras
79*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
80*2fe8fb19SBen Gras _DIAGASSERT(groups != NULL);
81*2fe8fb19SBen Gras
82*2fe8fb19SBen Gras /* skip duplicates */
83*2fe8fb19SBen Gras for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
84*2fe8fb19SBen Gras if (groups[dupc] == gid)
85*2fe8fb19SBen Gras return 1;
86*2fe8fb19SBen Gras }
87*2fe8fb19SBen Gras
88*2fe8fb19SBen Gras ret = 1;
89*2fe8fb19SBen Gras if (*groupc < maxgrp) /* add this gid */
90*2fe8fb19SBen Gras groups[*groupc] = gid;
91*2fe8fb19SBen Gras else
92*2fe8fb19SBen Gras ret = 0;
93*2fe8fb19SBen Gras (*groupc)++;
94*2fe8fb19SBen Gras return ret;
95*2fe8fb19SBen Gras }
96*2fe8fb19SBen Gras
97*2fe8fb19SBen Gras
98*2fe8fb19SBen Gras /*ARGSUSED*/
99*2fe8fb19SBen Gras static int
_files_getgroupmembership(void * retval,void * cb_data,va_list ap)100*2fe8fb19SBen Gras _files_getgroupmembership(void *retval, void *cb_data, va_list ap)
101*2fe8fb19SBen Gras {
102*2fe8fb19SBen Gras int *result = va_arg(ap, int *);
103*2fe8fb19SBen Gras const char *uname = va_arg(ap, const char *);
104*2fe8fb19SBen Gras gid_t agroup = va_arg(ap, gid_t);
105*2fe8fb19SBen Gras gid_t *groups = va_arg(ap, gid_t *);
106*2fe8fb19SBen Gras int maxgrp = va_arg(ap, int);
107*2fe8fb19SBen Gras int *groupc = va_arg(ap, int *);
108*2fe8fb19SBen Gras
109*2fe8fb19SBen Gras struct __grstate_files state;
110*2fe8fb19SBen Gras struct group grp;
111*2fe8fb19SBen Gras char grpbuf[_GETGR_R_SIZE_MAX];
112*2fe8fb19SBen Gras int rv, i;
113*2fe8fb19SBen Gras
114*2fe8fb19SBen Gras _DIAGASSERT(result != NULL);
115*2fe8fb19SBen Gras _DIAGASSERT(uname != NULL);
116*2fe8fb19SBen Gras /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
117*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
118*2fe8fb19SBen Gras
119*2fe8fb19SBen Gras /* install primary group */
120*2fe8fb19SBen Gras (void) __gr_addgid(agroup, groups, maxgrp, groupc);
121*2fe8fb19SBen Gras
122*2fe8fb19SBen Gras memset(&state, 0, sizeof(state));
123*2fe8fb19SBen Gras while (__grscan_files(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
124*2fe8fb19SBen Gras 0, NULL, 0) == NS_SUCCESS) {
125*2fe8fb19SBen Gras /* scan members */
126*2fe8fb19SBen Gras for (i = 0; grp.gr_mem[i]; i++) {
127*2fe8fb19SBen Gras if (strcmp(grp.gr_mem[i], uname) != 0)
128*2fe8fb19SBen Gras continue;
129*2fe8fb19SBen Gras if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
130*2fe8fb19SBen Gras *result = -1;
131*2fe8fb19SBen Gras break;
132*2fe8fb19SBen Gras }
133*2fe8fb19SBen Gras }
134*2fe8fb19SBen Gras __grend_files(&state);
135*2fe8fb19SBen Gras return NS_NOTFOUND;
136*2fe8fb19SBen Gras }
137*2fe8fb19SBen Gras
138*2fe8fb19SBen Gras
139*2fe8fb19SBen Gras #ifdef HESIOD
140*2fe8fb19SBen Gras
141*2fe8fb19SBen Gras /*ARGSUSED*/
142*2fe8fb19SBen Gras static int
_dns_getgroupmembership(void * retval,void * cb_data,va_list ap)143*2fe8fb19SBen Gras _dns_getgroupmembership(void *retval, void *cb_data, va_list ap)
144*2fe8fb19SBen Gras {
145*2fe8fb19SBen Gras int *result = va_arg(ap, int *);
146*2fe8fb19SBen Gras const char *uname = va_arg(ap, const char *);
147*2fe8fb19SBen Gras gid_t agroup = va_arg(ap, gid_t);
148*2fe8fb19SBen Gras gid_t *groups = va_arg(ap, gid_t *);
149*2fe8fb19SBen Gras int maxgrp = va_arg(ap, int);
150*2fe8fb19SBen Gras int *groupc = va_arg(ap, int *);
151*2fe8fb19SBen Gras
152*2fe8fb19SBen Gras struct __grstate_dns state;
153*2fe8fb19SBen Gras struct group grp;
154*2fe8fb19SBen Gras char grpbuf[_GETGR_R_SIZE_MAX];
155*2fe8fb19SBen Gras unsigned long id;
156*2fe8fb19SBen Gras void *context;
157*2fe8fb19SBen Gras char **hp, *cp, *ep;
158*2fe8fb19SBen Gras int rv, i;
159*2fe8fb19SBen Gras
160*2fe8fb19SBen Gras _DIAGASSERT(result != NULL);
161*2fe8fb19SBen Gras _DIAGASSERT(uname != NULL);
162*2fe8fb19SBen Gras /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
163*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
164*2fe8fb19SBen Gras
165*2fe8fb19SBen Gras /* install primary group */
166*2fe8fb19SBen Gras (void) __gr_addgid(agroup, groups, maxgrp, groupc);
167*2fe8fb19SBen Gras
168*2fe8fb19SBen Gras hp = NULL;
169*2fe8fb19SBen Gras rv = NS_NOTFOUND;
170*2fe8fb19SBen Gras
171*2fe8fb19SBen Gras if (hesiod_init(&context) == -1) /* setup hesiod */
172*2fe8fb19SBen Gras return NS_UNAVAIL;
173*2fe8fb19SBen Gras
174*2fe8fb19SBen Gras hp = hesiod_resolve(context, uname, "grplist"); /* find grplist */
175*2fe8fb19SBen Gras if (hp == NULL) {
176*2fe8fb19SBen Gras if (errno != ENOENT) { /* wasn't "not found"*/
177*2fe8fb19SBen Gras rv = NS_UNAVAIL;
178*2fe8fb19SBen Gras goto dnsgroupmembers_out;
179*2fe8fb19SBen Gras }
180*2fe8fb19SBen Gras /* grplist not found, fallback to _dns_grscan */
181*2fe8fb19SBen Gras memset(&state, 0, sizeof(state));
182*2fe8fb19SBen Gras while (__grscan_dns(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
183*2fe8fb19SBen Gras 0, NULL, 0) == NS_SUCCESS) {
184*2fe8fb19SBen Gras /* scan members */
185*2fe8fb19SBen Gras for (i = 0; grp.gr_mem[i]; i++) {
186*2fe8fb19SBen Gras if (strcmp(grp.gr_mem[i], uname) != 0)
187*2fe8fb19SBen Gras continue;
188*2fe8fb19SBen Gras if (! __gr_addgid(grp.gr_gid, groups, maxgrp,
189*2fe8fb19SBen Gras groupc))
190*2fe8fb19SBen Gras *result = -1;
191*2fe8fb19SBen Gras break;
192*2fe8fb19SBen Gras }
193*2fe8fb19SBen Gras }
194*2fe8fb19SBen Gras __grend_dns(&state);
195*2fe8fb19SBen Gras rv = NS_NOTFOUND;
196*2fe8fb19SBen Gras goto dnsgroupmembers_out;
197*2fe8fb19SBen Gras }
198*2fe8fb19SBen Gras
199*2fe8fb19SBen Gras if ((ep = strchr(hp[0], '\n')) != NULL)
200*2fe8fb19SBen Gras *ep = '\0'; /* clear trailing \n */
201*2fe8fb19SBen Gras
202*2fe8fb19SBen Gras for (cp = hp[0]; *cp != '\0'; ) { /* parse grplist */
203*2fe8fb19SBen Gras if ((cp = strchr(cp, ':')) == NULL) /* skip grpname */
204*2fe8fb19SBen Gras break;
205*2fe8fb19SBen Gras cp++;
206*2fe8fb19SBen Gras id = strtoul(cp, &ep, 10); /* parse gid */
207*2fe8fb19SBen Gras if (id > GID_MAX || (*ep != ':' && *ep != '\0')) {
208*2fe8fb19SBen Gras rv = NS_UNAVAIL;
209*2fe8fb19SBen Gras goto dnsgroupmembers_out;
210*2fe8fb19SBen Gras }
211*2fe8fb19SBen Gras cp = ep;
212*2fe8fb19SBen Gras if (*cp == ':')
213*2fe8fb19SBen Gras cp++;
214*2fe8fb19SBen Gras
215*2fe8fb19SBen Gras /* add gid */
216*2fe8fb19SBen Gras if (! __gr_addgid((gid_t)id, groups, maxgrp, groupc))
217*2fe8fb19SBen Gras *result = -1;
218*2fe8fb19SBen Gras }
219*2fe8fb19SBen Gras
220*2fe8fb19SBen Gras rv = NS_NOTFOUND;
221*2fe8fb19SBen Gras
222*2fe8fb19SBen Gras dnsgroupmembers_out:
223*2fe8fb19SBen Gras if (hp)
224*2fe8fb19SBen Gras hesiod_free_list(context, hp);
225*2fe8fb19SBen Gras hesiod_end(context);
226*2fe8fb19SBen Gras return rv;
227*2fe8fb19SBen Gras }
228*2fe8fb19SBen Gras
229*2fe8fb19SBen Gras #endif /* HESIOD */
230*2fe8fb19SBen Gras
231*2fe8fb19SBen Gras
232*2fe8fb19SBen Gras #ifdef YP
233*2fe8fb19SBen Gras
234*2fe8fb19SBen Gras /*ARGSUSED*/
235*2fe8fb19SBen Gras static int
_nis_getgroupmembership(void * retval,void * cb_data,va_list ap)236*2fe8fb19SBen Gras _nis_getgroupmembership(void *retval, void *cb_data, va_list ap)
237*2fe8fb19SBen Gras {
238*2fe8fb19SBen Gras int *result = va_arg(ap, int *);
239*2fe8fb19SBen Gras const char *uname = va_arg(ap, const char *);
240*2fe8fb19SBen Gras gid_t agroup = va_arg(ap, gid_t);
241*2fe8fb19SBen Gras gid_t *groups = va_arg(ap, gid_t *);
242*2fe8fb19SBen Gras int maxgrp = va_arg(ap, int);
243*2fe8fb19SBen Gras int *groupc = va_arg(ap, int *);
244*2fe8fb19SBen Gras
245*2fe8fb19SBen Gras struct __grstate_nis state;
246*2fe8fb19SBen Gras struct group grp;
247*2fe8fb19SBen Gras char grpbuf[_GETGR_R_SIZE_MAX];
248*2fe8fb19SBen Gras int rv, i;
249*2fe8fb19SBen Gras
250*2fe8fb19SBen Gras _DIAGASSERT(result != NULL);
251*2fe8fb19SBen Gras _DIAGASSERT(uname != NULL);
252*2fe8fb19SBen Gras /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
253*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
254*2fe8fb19SBen Gras
255*2fe8fb19SBen Gras /* install primary group */
256*2fe8fb19SBen Gras (void) __gr_addgid(agroup, groups, maxgrp, groupc);
257*2fe8fb19SBen Gras
258*2fe8fb19SBen Gras memset(&state, 0, sizeof(state));
259*2fe8fb19SBen Gras while (__grscan_nis(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
260*2fe8fb19SBen Gras 0, NULL, 0) == NS_SUCCESS) {
261*2fe8fb19SBen Gras /* scan members */
262*2fe8fb19SBen Gras for (i = 0; grp.gr_mem[i]; i++) {
263*2fe8fb19SBen Gras if (strcmp(grp.gr_mem[i], uname) != 0)
264*2fe8fb19SBen Gras continue;
265*2fe8fb19SBen Gras if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
266*2fe8fb19SBen Gras *result = -1;
267*2fe8fb19SBen Gras break;
268*2fe8fb19SBen Gras }
269*2fe8fb19SBen Gras }
270*2fe8fb19SBen Gras __grend_nis(&state);
271*2fe8fb19SBen Gras
272*2fe8fb19SBen Gras return NS_NOTFOUND;
273*2fe8fb19SBen Gras }
274*2fe8fb19SBen Gras
275*2fe8fb19SBen Gras #endif /* YP */
276*2fe8fb19SBen Gras
277*2fe8fb19SBen Gras
278*2fe8fb19SBen Gras #ifdef _GROUP_COMPAT
279*2fe8fb19SBen Gras
280*2fe8fb19SBen Gras struct __compatggm {
281*2fe8fb19SBen Gras const char *uname; /* user to search for */
282*2fe8fb19SBen Gras gid_t *groups;
283*2fe8fb19SBen Gras gid_t agroup;
284*2fe8fb19SBen Gras int maxgrp;
285*2fe8fb19SBen Gras int *groupc;
286*2fe8fb19SBen Gras };
287*2fe8fb19SBen Gras
288*2fe8fb19SBen Gras static int
_compat_ggm_search(void * cookie,struct group ** groupres)289*2fe8fb19SBen Gras _compat_ggm_search(void *cookie, struct group **groupres)
290*2fe8fb19SBen Gras {
291*2fe8fb19SBen Gras struct __compatggm *cp;
292*2fe8fb19SBen Gras int rerror, crv;
293*2fe8fb19SBen Gras
294*2fe8fb19SBen Gras static const ns_dtab dtab[] = {
295*2fe8fb19SBen Gras NS_FILES_CB(__grbad_compat, "files")
296*2fe8fb19SBen Gras NS_DNS_CB(_dns_getgroupmembership, NULL)
297*2fe8fb19SBen Gras NS_NIS_CB(_nis_getgroupmembership, NULL)
298*2fe8fb19SBen Gras NS_COMPAT_CB(__grbad_compat, "compat")
299*2fe8fb19SBen Gras NS_NULL_CB
300*2fe8fb19SBen Gras };
301*2fe8fb19SBen Gras
302*2fe8fb19SBen Gras *groupres = NULL; /* we don't care about this */
303*2fe8fb19SBen Gras cp = (struct __compatggm *)cookie;
304*2fe8fb19SBen Gras
305*2fe8fb19SBen Gras crv = nsdispatch(NULL, dtab,
306*2fe8fb19SBen Gras NSDB_GROUP_COMPAT, "getgroupmembership",
307*2fe8fb19SBen Gras __nsdefaultnis,
308*2fe8fb19SBen Gras &rerror, cp->uname, cp->agroup, cp->groups, cp->maxgrp, cp->groupc);
309*2fe8fb19SBen Gras
310*2fe8fb19SBen Gras if (crv == NS_SUCCESS)
311*2fe8fb19SBen Gras crv = NS_NOTFOUND; /* indicate "no more +: entries" */
312*2fe8fb19SBen Gras
313*2fe8fb19SBen Gras return crv;
314*2fe8fb19SBen Gras }
315*2fe8fb19SBen Gras
316*2fe8fb19SBen Gras /* ARGSUSED */
317*2fe8fb19SBen Gras static int
_compat_getgroupmembership(void * retval,void * cb_data,va_list ap)318*2fe8fb19SBen Gras _compat_getgroupmembership(void *retval, void *cb_data, va_list ap)
319*2fe8fb19SBen Gras {
320*2fe8fb19SBen Gras int *result = va_arg(ap, int *);
321*2fe8fb19SBen Gras const char *uname = va_arg(ap, const char *);
322*2fe8fb19SBen Gras gid_t agroup = va_arg(ap, gid_t);
323*2fe8fb19SBen Gras gid_t *groups = va_arg(ap, gid_t *);
324*2fe8fb19SBen Gras int maxgrp = va_arg(ap, int);
325*2fe8fb19SBen Gras int *groupc = va_arg(ap, int *);
326*2fe8fb19SBen Gras
327*2fe8fb19SBen Gras struct __grstate_compat state;
328*2fe8fb19SBen Gras struct __compatggm ggmstate;
329*2fe8fb19SBen Gras struct group grp;
330*2fe8fb19SBen Gras char grpbuf[_GETGR_R_SIZE_MAX];
331*2fe8fb19SBen Gras int rv, i;
332*2fe8fb19SBen Gras
333*2fe8fb19SBen Gras _DIAGASSERT(result != NULL);
334*2fe8fb19SBen Gras _DIAGASSERT(uname != NULL);
335*2fe8fb19SBen Gras /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
336*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
337*2fe8fb19SBen Gras
338*2fe8fb19SBen Gras /* install primary group */
339*2fe8fb19SBen Gras (void) __gr_addgid(agroup, groups, maxgrp, groupc);
340*2fe8fb19SBen Gras
341*2fe8fb19SBen Gras memset(&state, 0, sizeof(state));
342*2fe8fb19SBen Gras memset(&ggmstate, 0, sizeof(ggmstate));
343*2fe8fb19SBen Gras ggmstate.uname = uname;
344*2fe8fb19SBen Gras ggmstate.groups = groups;
345*2fe8fb19SBen Gras ggmstate.agroup = agroup;
346*2fe8fb19SBen Gras ggmstate.maxgrp = maxgrp;
347*2fe8fb19SBen Gras ggmstate.groupc = groupc;
348*2fe8fb19SBen Gras
349*2fe8fb19SBen Gras while (__grscan_compat(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
350*2fe8fb19SBen Gras 0, NULL, 0, _compat_ggm_search, &ggmstate)
351*2fe8fb19SBen Gras == NS_SUCCESS) {
352*2fe8fb19SBen Gras /* scan members */
353*2fe8fb19SBen Gras for (i = 0; grp.gr_mem[i]; i++) {
354*2fe8fb19SBen Gras if (strcmp(grp.gr_mem[i], uname) != 0)
355*2fe8fb19SBen Gras continue;
356*2fe8fb19SBen Gras if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
357*2fe8fb19SBen Gras *result = -1;
358*2fe8fb19SBen Gras break;
359*2fe8fb19SBen Gras }
360*2fe8fb19SBen Gras }
361*2fe8fb19SBen Gras
362*2fe8fb19SBen Gras __grend_compat(&state);
363*2fe8fb19SBen Gras return NS_NOTFOUND;
364*2fe8fb19SBen Gras }
365*2fe8fb19SBen Gras
366*2fe8fb19SBen Gras #endif /* _GROUP_COMPAT */
367*2fe8fb19SBen Gras
368*2fe8fb19SBen Gras
369*2fe8fb19SBen Gras int
getgroupmembership(const char * uname,gid_t agroup,gid_t * groups,int maxgrp,int * groupc)370*2fe8fb19SBen Gras getgroupmembership(const char *uname, gid_t agroup,
371*2fe8fb19SBen Gras gid_t *groups, int maxgrp, int *groupc)
372*2fe8fb19SBen Gras {
373*2fe8fb19SBen Gras int rerror;
374*2fe8fb19SBen Gras
375*2fe8fb19SBen Gras static const ns_dtab dtab[] = {
376*2fe8fb19SBen Gras NS_FILES_CB(_files_getgroupmembership, NULL)
377*2fe8fb19SBen Gras NS_DNS_CB(_dns_getgroupmembership, NULL)
378*2fe8fb19SBen Gras NS_NIS_CB(_nis_getgroupmembership, NULL)
379*2fe8fb19SBen Gras NS_COMPAT_CB(_compat_getgroupmembership, NULL)
380*2fe8fb19SBen Gras NS_NULL_CB
381*2fe8fb19SBen Gras };
382*2fe8fb19SBen Gras
383*2fe8fb19SBen Gras _DIAGASSERT(uname != NULL);
384*2fe8fb19SBen Gras /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
385*2fe8fb19SBen Gras _DIAGASSERT(groupc != NULL);
386*2fe8fb19SBen Gras
387*2fe8fb19SBen Gras *groupc = 0;
388*2fe8fb19SBen Gras
389*2fe8fb19SBen Gras mutex_lock(&__grmutex);
390*2fe8fb19SBen Gras /*
391*2fe8fb19SBen Gras * Call each backend.
392*2fe8fb19SBen Gras * For compatibility with getgrent(3) semantics,
393*2fe8fb19SBen Gras * a backend should return NS_NOTFOUND even upon
394*2fe8fb19SBen Gras * completion, to allow result merging to occur.
395*2fe8fb19SBen Gras */
396*2fe8fb19SBen Gras (void) nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
397*2fe8fb19SBen Gras __nsdefaultcompat,
398*2fe8fb19SBen Gras &rerror, uname, agroup, groups, maxgrp, groupc);
399*2fe8fb19SBen Gras mutex_unlock(&__grmutex);
400*2fe8fb19SBen Gras
401*2fe8fb19SBen Gras if (*groupc > maxgrp) /* too many groups found */
402*2fe8fb19SBen Gras return -1;
403*2fe8fb19SBen Gras else
404*2fe8fb19SBen Gras return 0;
405*2fe8fb19SBen Gras }
406