Implement getgroupmembership(3). This is similar to getgrouplist(3), except
that the "int maxgroups" and "int *ngroups" parameters are separated into two separate parameters which makes it possible to call multiple nsswitch back-ends and have the results correctly merged. getgrouplist(3) is now implemented using getgroupmembership(3). Proposed on tech-userlevel on December 1, 2004.
This commit is contained in:
parent
337d8d731d
commit
a3665ef9cf
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: getgrent.c,v 1.8 2003/10/13 15:36:33 agc Exp $ */
|
||||
/* $NetBSD: getgrent.c,v 1.9 2005/01/06 15:10:45 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -69,6 +69,7 @@
|
|||
#define getgrnam _getgrnam
|
||||
#define setgrent _setgrent
|
||||
#define setgroupent _setgroupent
|
||||
#define getgroupmembership _getgroupmembership
|
||||
|
||||
__weak_alias(endgrent,_endgrent)
|
||||
__weak_alias(getgrent,_getgrent)
|
||||
|
@ -76,9 +77,10 @@ __weak_alias(getgrgid,_getgrgid)
|
|||
__weak_alias(getgrnam,_getgrnam)
|
||||
__weak_alias(setgrent,_setgrent)
|
||||
__weak_alias(setgroupent,_setgroupent)
|
||||
__weak_alias(getgroupmembership,_getgroupmembership)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
|
@ -86,8 +88,6 @@ __weak_alias(setgroupent,_setgroupent)
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct group *_getgrent_user(const char *);
|
||||
|
||||
static FILE *_gr_fp;
|
||||
static struct group _gr_group;
|
||||
static int _gr_stayopen;
|
||||
|
@ -112,21 +112,6 @@ getgrent(void)
|
|||
return &_gr_group;
|
||||
}
|
||||
|
||||
/*
|
||||
* _getgrent_user() is designed only to be called by getgrouplist(3) and
|
||||
* hence makes no guarantees about filling the entire structure that it
|
||||
* returns. It may only fill in the group name and gid fields.
|
||||
*/
|
||||
|
||||
struct group *
|
||||
_getgrent_user(const char *user)
|
||||
{
|
||||
|
||||
if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, user))
|
||||
return (NULL);
|
||||
return &_gr_group;
|
||||
}
|
||||
|
||||
struct group *
|
||||
getgrnam(const char *name)
|
||||
{
|
||||
|
@ -193,6 +178,53 @@ endgrent(void)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
getgroupmembership(const char *uname, gid_t agroup,
|
||||
gid_t *groups, int maxgroups, int *grpcnt)
|
||||
{
|
||||
struct group *grp;
|
||||
int i, ngroups, ret;
|
||||
|
||||
ret = 0;
|
||||
ngroups = 0;
|
||||
|
||||
/*
|
||||
* install primary group
|
||||
*/
|
||||
if (ngroups < maxgroups)
|
||||
groups[ngroups] = agroup;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
|
||||
/*
|
||||
* Scan the group file to find additional groups.
|
||||
*/
|
||||
setgrent();
|
||||
nextgroup:
|
||||
while ((grp = getgrent()) != NULL) {
|
||||
if (grp->gr_gid == agroup)
|
||||
continue;
|
||||
for (i = 0; grp->gr_mem[i]; i++) {
|
||||
if (strcmp(grp->gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
for (i = 0; i < MIN(ngroups, maxgroups); i++) {
|
||||
if (grp->gr_gid == groups[i])
|
||||
goto nextgroup;
|
||||
}
|
||||
if (ngroups < maxgroups)
|
||||
groups[ngroups] = grp->gr_gid;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endgrent();
|
||||
*grpcnt = ngroups;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
grscan(int search, gid_t gid, const char *name, const char *user)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: unistd.h,v 1.99 2004/06/01 16:10:29 kleink Exp $ */
|
||||
/* $NetBSD: unistd.h,v 1.100 2005/01/06 15:10:45 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
|
||||
|
@ -311,6 +311,7 @@ int fchroot __P((int));
|
|||
int fsync_range __P((int, int, off_t, off_t));
|
||||
int getdomainname __P((char *, size_t));
|
||||
int getgrouplist __P((const char *, gid_t, gid_t *, int *));
|
||||
int getgroupmembership __P((const char *, gid_t, gid_t *, int, int *));
|
||||
mode_t getmode __P((const void *, mode_t));
|
||||
int getsubopt __P((char **, char * const *, char **));
|
||||
__aconst char *getusershell __P((void));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile.inc,v 1.138 2005/01/02 16:43:26 thorpej Exp $
|
||||
# $NetBSD: Makefile.inc,v 1.139 2005/01/06 15:10:45 lukem Exp $
|
||||
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
|
||||
|
||||
# gen sources
|
||||
|
@ -10,8 +10,8 @@ SRCS+= _errno.c alarm.c arc4random.c assert.c basename.c clock.c closedir.c \
|
|||
execle.c execlp.c execv.c execvp.c extattr.c \
|
||||
fmtcheck.c fmtmsg.c fnmatch.c \
|
||||
fstab.c ftok.c __fts13.c fts.c getbsize.c getcap.c getcwd.c \
|
||||
getdevmajor.c \
|
||||
getdomainname.c getgrent.c getgrouplist.c gethostname.c \
|
||||
getdevmajor.c getdomainname.c getgrent.c \
|
||||
getgrouplist.c getgroupmembership.c gethostname.c \
|
||||
getloadavg.c getlogin.c getmntinfo.c __getmntinfo13.c \
|
||||
getnetgrent.c getpagesize.c \
|
||||
getpass.c getprogname.c getpwent.c getttyent.c \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: getgrouplist.c,v 1.20 2004/09/28 10:46:19 lukem Exp $ */
|
||||
/* $NetBSD: getgrouplist.c,v 1.21 2005/01/06 15:10:45 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2004-2005 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -36,41 +36,12 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)getgrouplist.c 8.2 (Berkeley) 12/8/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: getgrouplist.c,v 1.20 2004/09/28 10:46:19 lukem Exp $");
|
||||
__RCSID("$NetBSD: getgrouplist.c,v 1.21 2005/01/06 15:10:45 lukem Exp $");
|
||||
#endif
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
|
@ -82,158 +53,25 @@ __RCSID("$NetBSD: getgrouplist.c,v 1.20 2004/09/28 10:46:19 lukem Exp $");
|
|||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <nsswitch.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HESIOD
|
||||
#include <hesiod.h>
|
||||
#endif
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getgrouplist,_getgrouplist)
|
||||
#endif
|
||||
|
||||
#ifdef HESIOD
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
_nss_dns_getgrouplist(void *retval, void *cb_data, va_list ap)
|
||||
{
|
||||
int *result = va_arg(ap, int *);
|
||||
const char *uname = va_arg(ap, const char *);
|
||||
gid_t agroup = va_arg(ap, gid_t);
|
||||
gid_t *groups = va_arg(ap, gid_t *);
|
||||
int *grpcnt = va_arg(ap, int *);
|
||||
|
||||
unsigned long id;
|
||||
void *context;
|
||||
char **hp, *cp, *ep;
|
||||
int rv, ret, ngroups, maxgroups;
|
||||
|
||||
hp = NULL;
|
||||
rv = NS_NOTFOUND;
|
||||
ret = 0;
|
||||
|
||||
if (hesiod_init(&context) == -1) /* setup hesiod */
|
||||
return NS_UNAVAIL;
|
||||
|
||||
hp = hesiod_resolve(context, uname, "grplist"); /* find grplist */
|
||||
if (hp == NULL) {
|
||||
if (errno != ENOENT)
|
||||
rv = NS_NOTFOUND;
|
||||
goto dnsgrouplist_out;
|
||||
}
|
||||
|
||||
if ((ep = strchr(hp[0], '\n')) != NULL)
|
||||
*ep = '\0'; /* clear trailing \n */
|
||||
|
||||
ret = 0;
|
||||
ngroups = 0;
|
||||
maxgroups = *grpcnt;
|
||||
|
||||
if (ngroups < maxgroups) /* add primary gid */
|
||||
groups[ngroups] = agroup;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
|
||||
for (cp = hp[0]; *cp != '\0'; ) { /* parse grplist */
|
||||
if ((cp = strchr(cp, ':')) == NULL) /* skip grpname */
|
||||
break;
|
||||
cp++;
|
||||
id = strtoul(cp, &ep, 10); /* parse gid */
|
||||
if (id > GID_MAX || (*ep != ':' && *ep != '\0')) {
|
||||
rv = NS_UNAVAIL;
|
||||
goto dnsgrouplist_out;
|
||||
}
|
||||
cp = ep;
|
||||
if (*cp == ':')
|
||||
cp++;
|
||||
if (ngroups < maxgroups) /* add this gid */
|
||||
groups[ngroups] = (gid_t)id;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
}
|
||||
|
||||
*result = ret;
|
||||
*grpcnt = ngroups;
|
||||
rv = NS_SUCCESS;
|
||||
|
||||
dnsgrouplist_out:
|
||||
if (hp)
|
||||
hesiod_free_list(context, hp);
|
||||
hesiod_end(context);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* HESIOD */
|
||||
|
||||
int
|
||||
getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
|
||||
{
|
||||
struct group *grp;
|
||||
int i, ngroups, maxgroups, ret;
|
||||
|
||||
static const ns_dtab dtab[] = {
|
||||
NS_DNS_CB(_nss_dns_getgrouplist, NULL)
|
||||
{ 0 }
|
||||
};
|
||||
int rv, groupc;
|
||||
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with *grpcnt = 0 */
|
||||
_DIAGASSERT(grpcnt != NULL);
|
||||
|
||||
/* first, try source-specific optimized getgrouplist */
|
||||
i = nsdispatch(NULL, dtab, NSDB_GROUP, "getgrouplist",
|
||||
__nsdefaultsrc,
|
||||
&ret, uname, agroup, groups, grpcnt);
|
||||
if (i == NS_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* fallback to scan the group(5) database */
|
||||
ret = 0;
|
||||
ngroups = 0;
|
||||
maxgroups = *grpcnt;
|
||||
|
||||
/*
|
||||
* install primary group
|
||||
*/
|
||||
if (ngroups < maxgroups)
|
||||
groups[ngroups] = agroup;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
|
||||
/*
|
||||
* Scan the group file to find additional groups.
|
||||
*/
|
||||
setgrent();
|
||||
nextgroup:
|
||||
while ((grp = getgrent()) != NULL) {
|
||||
if (grp->gr_gid == agroup)
|
||||
continue;
|
||||
for (i = 0; grp->gr_mem[i]; i++) {
|
||||
if (strcmp(grp->gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
for (i = 0; i < MIN(ngroups, maxgroups); i++) {
|
||||
if (grp->gr_gid == groups[i])
|
||||
goto nextgroup;
|
||||
}
|
||||
if (ngroups < maxgroups)
|
||||
groups[ngroups] = grp->gr_gid;
|
||||
else
|
||||
ret = -1;
|
||||
ngroups++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endgrent();
|
||||
*grpcnt = ngroups;
|
||||
return ret;
|
||||
groupc = 0;
|
||||
rv = getgroupmembership(uname, agroup, groups, *grpcnt, &groupc);
|
||||
*grpcnt = groupc; /* set groupc to the actual # of groups */
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,411 @@
|
|||
/* $NetBSD: getgroupmembership.c,v 1.1 2005/01/06 15:10:45 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004-2005 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: getgroupmembership.c,v 1.1 2005/01/06 15:10:45 lukem Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/*
|
||||
* calculate group access list
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include <nsswitch.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HESIOD
|
||||
#include <hesiod.h>
|
||||
#endif
|
||||
|
||||
#include "gr_private.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getgroupmembership,_getgroupmembership)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __gr_addgid
|
||||
* Add gid to the groups array (of maxgrp size) at the position
|
||||
* indicated by *groupc, unless it already exists or *groupc is
|
||||
* past &groups[maxgrp].
|
||||
* Returns 1 upon success (including duplicate suppression), 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
__gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *groupc)
|
||||
{
|
||||
int ret, dupc;
|
||||
|
||||
_DIAGASSERT(grpcnt != NULL);
|
||||
|
||||
/* skip duplicates */
|
||||
for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
|
||||
if (groups[dupc] == gid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
if (*groupc < maxgrp) /* add this gid */
|
||||
groups[*groupc] = gid;
|
||||
else
|
||||
ret = 0;
|
||||
(*groupc)++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
_files_getgroupmembership(void *retval, void *cb_data, va_list ap)
|
||||
{
|
||||
int *result = va_arg(ap, int *);
|
||||
const char *uname = va_arg(ap, const char *);
|
||||
gid_t agroup = va_arg(ap, gid_t);
|
||||
gid_t *groups = va_arg(ap, gid_t *);
|
||||
int maxgrp = va_arg(ap, int);
|
||||
int *groupc = va_arg(ap, int *);
|
||||
|
||||
struct __grstate_files state;
|
||||
struct group grp;
|
||||
char grpbuf[_GETGR_R_SIZE_MAX];
|
||||
int rv, i;
|
||||
|
||||
_DIAGASSERT(result != NULL);
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
|
||||
_DIAGASSERT(groupc != NULL);
|
||||
|
||||
/* install primary group */
|
||||
(void) __gr_addgid(agroup, groups, maxgrp, groupc);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
while (__grscan_files(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
|
||||
0, NULL, 0) == NS_SUCCESS) {
|
||||
/* scan members */
|
||||
for (i = 0; grp.gr_mem[i]; i++) {
|
||||
if (strcmp(grp.gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
|
||||
*result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__grend_files(&state);
|
||||
return NS_NOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HESIOD
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
_dns_getgroupmembership(void *retval, void *cb_data, va_list ap)
|
||||
{
|
||||
int *result = va_arg(ap, int *);
|
||||
const char *uname = va_arg(ap, const char *);
|
||||
gid_t agroup = va_arg(ap, gid_t);
|
||||
gid_t *groups = va_arg(ap, gid_t *);
|
||||
int maxgrp = va_arg(ap, int);
|
||||
int *groupc = va_arg(ap, int *);
|
||||
|
||||
struct __grstate_dns state;
|
||||
struct group grp;
|
||||
char grpbuf[_GETGR_R_SIZE_MAX];
|
||||
unsigned long id;
|
||||
void *context;
|
||||
char **hp, *cp, *ep;
|
||||
int rv, i;
|
||||
|
||||
_DIAGASSERT(result != NULL);
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
|
||||
_DIAGASSERT(groupc != NULL);
|
||||
|
||||
/* install primary group */
|
||||
(void) __gr_addgid(agroup, groups, maxgrp, groupc);
|
||||
|
||||
hp = NULL;
|
||||
rv = NS_NOTFOUND;
|
||||
|
||||
if (hesiod_init(&context) == -1) /* setup hesiod */
|
||||
return NS_UNAVAIL;
|
||||
|
||||
hp = hesiod_resolve(context, uname, "grplist"); /* find grplist */
|
||||
if (hp == NULL) {
|
||||
if (errno != ENOENT) { /* wasn't "not found"*/
|
||||
rv = NS_UNAVAIL;
|
||||
goto dnsgroupmembers_out;
|
||||
}
|
||||
/* grplist not found, fallback to _dns_grscan */
|
||||
memset(&state, 0, sizeof(state));
|
||||
while (__grscan_dns(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
|
||||
0, NULL, 0) == NS_SUCCESS) {
|
||||
/* scan members */
|
||||
for (i = 0; grp.gr_mem[i]; i++) {
|
||||
if (strcmp(grp.gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
if (! __gr_addgid(grp.gr_gid, groups, maxgrp,
|
||||
groupc))
|
||||
*result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__grend_dns(&state);
|
||||
rv = NS_NOTFOUND;
|
||||
goto dnsgroupmembers_out;
|
||||
}
|
||||
|
||||
if ((ep = strchr(hp[0], '\n')) != NULL)
|
||||
*ep = '\0'; /* clear trailing \n */
|
||||
|
||||
for (cp = hp[0]; *cp != '\0'; ) { /* parse grplist */
|
||||
if ((cp = strchr(cp, ':')) == NULL) /* skip grpname */
|
||||
break;
|
||||
cp++;
|
||||
id = strtoul(cp, &ep, 10); /* parse gid */
|
||||
if (id > GID_MAX || (*ep != ':' && *ep != '\0')) {
|
||||
rv = NS_UNAVAIL;
|
||||
goto dnsgroupmembers_out;
|
||||
}
|
||||
cp = ep;
|
||||
if (*cp == ':')
|
||||
cp++;
|
||||
|
||||
/* add gid */
|
||||
if (! __gr_addgid((gid_t)id, groups, maxgrp, groupc))
|
||||
*result = -1;
|
||||
}
|
||||
|
||||
rv = NS_NOTFOUND;
|
||||
|
||||
dnsgroupmembers_out:
|
||||
if (hp)
|
||||
hesiod_free_list(context, hp);
|
||||
hesiod_end(context);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* HESIOD */
|
||||
|
||||
|
||||
#ifdef YP
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
_nis_getgroupmembership(void *retval, void *cb_data, va_list ap)
|
||||
{
|
||||
int *result = va_arg(ap, int *);
|
||||
const char *uname = va_arg(ap, const char *);
|
||||
gid_t agroup = va_arg(ap, gid_t);
|
||||
gid_t *groups = va_arg(ap, gid_t *);
|
||||
int maxgrp = va_arg(ap, int);
|
||||
int *groupc = va_arg(ap, int *);
|
||||
|
||||
struct __grstate_nis state;
|
||||
struct group grp;
|
||||
char grpbuf[_GETGR_R_SIZE_MAX];
|
||||
int rv, i;
|
||||
|
||||
_DIAGASSERT(result != NULL);
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
|
||||
_DIAGASSERT(groupc != NULL);
|
||||
|
||||
/* install primary group */
|
||||
(void) __gr_addgid(agroup, groups, maxgrp, groupc);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
while (__grscan_nis(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
|
||||
0, NULL, 0) == NS_SUCCESS) {
|
||||
/* scan members */
|
||||
for (i = 0; grp.gr_mem[i]; i++) {
|
||||
if (strcmp(grp.gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
|
||||
*result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__grend_nis(&state);
|
||||
|
||||
return NS_NOTFOUND;
|
||||
}
|
||||
|
||||
#endif /* YP */
|
||||
|
||||
|
||||
#ifdef _GROUP_COMPAT
|
||||
|
||||
struct __compatggm {
|
||||
const char *uname; /* user to search for */
|
||||
gid_t *groups;
|
||||
gid_t agroup;
|
||||
int maxgrp;
|
||||
int *groupc;
|
||||
};
|
||||
|
||||
static int
|
||||
_compat_ggm_search(void *cookie, struct group **groupres)
|
||||
{
|
||||
struct __compatggm *cp;
|
||||
int rerror, crv;
|
||||
|
||||
static const ns_dtab dtab[] = {
|
||||
NS_FILES_CB(__grbad_compat, "files")
|
||||
NS_DNS_CB(_dns_getgroupmembership, NULL)
|
||||
NS_NIS_CB(_nis_getgroupmembership, NULL)
|
||||
NS_COMPAT_CB(__grbad_compat, "compat")
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
*groupres = NULL; /* we don't care about this */
|
||||
cp = (struct __compatggm *)cookie;
|
||||
|
||||
crv = nsdispatch(NULL, dtab,
|
||||
NSDB_GROUP_COMPAT, "getgroupmembership",
|
||||
__nsdefaultnis,
|
||||
&rerror, cp->uname, cp->agroup, cp->groups, cp->maxgrp, cp->groupc);
|
||||
|
||||
if (crv == NS_SUCCESS)
|
||||
crv = NS_NOTFOUND; /* indicate "no more +: entries" */
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
_compat_getgroupmembership(void *retval, void *cb_data, va_list ap)
|
||||
{
|
||||
int *result = va_arg(ap, int *);
|
||||
const char *uname = va_arg(ap, const char *);
|
||||
gid_t agroup = va_arg(ap, gid_t);
|
||||
gid_t *groups = va_arg(ap, gid_t *);
|
||||
int maxgrp = va_arg(ap, int);
|
||||
int *groupc = va_arg(ap, int *);
|
||||
|
||||
struct __grstate_compat state;
|
||||
struct __compatggm ggmstate;
|
||||
struct group grp;
|
||||
char grpbuf[_GETGR_R_SIZE_MAX];
|
||||
int rv, i;
|
||||
|
||||
_DIAGASSERT(result != NULL);
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
|
||||
_DIAGASSERT(groupc != NULL);
|
||||
|
||||
/* install primary group */
|
||||
(void) __gr_addgid(agroup, groups, maxgrp, groupc);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
memset(&ggmstate, 0, sizeof(ggmstate));
|
||||
ggmstate.uname = uname;
|
||||
ggmstate.groups = groups;
|
||||
ggmstate.agroup = agroup;
|
||||
ggmstate.maxgrp = maxgrp;
|
||||
ggmstate.groupc = groupc;
|
||||
|
||||
while (__grscan_compat(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
|
||||
0, NULL, 0, _compat_ggm_search, &ggmstate)
|
||||
== NS_SUCCESS) {
|
||||
/* scan members */
|
||||
for (i = 0; grp.gr_mem[i]; i++) {
|
||||
if (strcmp(grp.gr_mem[i], uname) != 0)
|
||||
continue;
|
||||
if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
|
||||
*result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__grend_compat(&state);
|
||||
return NS_NOTFOUND;
|
||||
}
|
||||
|
||||
#endif /* _GROUP_COMPAT */
|
||||
|
||||
|
||||
int
|
||||
getgroupmembership(const char *uname, gid_t agroup,
|
||||
gid_t *groups, int maxgrp, int *groupc)
|
||||
{
|
||||
int rerror;
|
||||
|
||||
static const ns_dtab dtab[] = {
|
||||
NS_FILES_CB(_files_getgroupmembership, NULL)
|
||||
NS_DNS_CB(_dns_getgroupmembership, NULL)
|
||||
NS_NIS_CB(_nis_getgroupmembership, NULL)
|
||||
NS_COMPAT_CB(_compat_getgroupmembership, NULL)
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
_DIAGASSERT(uname != NULL);
|
||||
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
|
||||
_DIAGASSERT(groupc != NULL);
|
||||
|
||||
*groupc = 0;
|
||||
|
||||
mutex_lock(&__grmutex);
|
||||
/*
|
||||
* Call each backend.
|
||||
* For compatibility with getgrent(3) semantics,
|
||||
* a backend should return NS_NOTFOUND even upon
|
||||
* completion, to allow result merging to occur.
|
||||
*/
|
||||
(void) nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
|
||||
__nsdefaultcompat,
|
||||
&rerror, uname, agroup, groups, maxgrp, groupc);
|
||||
mutex_unlock(&__grmutex);
|
||||
|
||||
if (*groupc > maxgrp) /* too many groups found */
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: namespace.h,v 1.96 2004/12/16 12:30:04 kleink Exp $ */
|
||||
/* $NetBSD: namespace.h,v 1.97 2005/01/06 15:10:45 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
|
||||
|
@ -226,6 +226,7 @@
|
|||
#define getgrnam _getgrnam
|
||||
#define getgrnam_r _getgrnam_r
|
||||
#define getgrouplist _getgrouplist
|
||||
#define getgroupmembership _getgroupmembership
|
||||
#define gethostbyaddr _gethostbyaddr
|
||||
#define gethostbyname _gethostbyname
|
||||
#define gethostent _gethostent
|
||||
|
|
Loading…
Reference in New Issue