diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-06-24 14:29:46 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-06-24 14:29:46 +0000 |
commit | 3c299ffbcf5658385f822ec5be0eb9f422c756ff (patch) | |
tree | 01015121d27c673288316fd7baa7e6b797d3abca /lib/libc/gen | |
parent | 3c00af7e9ff7ae6d3fd059414ddfacb8b93b6254 (diff) |
create a private getpwent()-like interface which does not walk the YP
groups map but instead tells us that it is there. then use this interface
in getgrouplist(), and do a single lookup against netid.byname instead to
get all the groups associated with that user
ok kurt, testing by many others
Diffstat (limited to 'lib/libc/gen')
-rw-r--r-- | lib/libc/gen/getgrent.c | 25 | ||||
-rw-r--r-- | lib/libc/gen/getgrouplist.c | 90 |
2 files changed, 99 insertions, 16 deletions
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c index 124a4034cee..6de1ad14f01 100644 --- a/lib/libc/gen/getgrent.c +++ b/lib/libc/gen/getgrent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getgrent.c,v 1.24 2007/05/16 04:14:23 ray Exp $ */ +/* $OpenBSD: getgrent.c,v 1.25 2008/06/24 14:29:45 deraadt Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -59,7 +59,8 @@ _THREAD_PRIVATE_KEY(gr); static FILE *_gr_fp; static struct group _gr_group; static int _gr_stayopen; -static int grscan(int, gid_t, const char *, struct group *, struct group_storage *); +static int grscan(int, gid_t, const char *, struct group *, struct group_storage *, + int *); static int start_gr(void); static void endgrent_basic(void); @@ -76,19 +77,25 @@ static int __ypcurrentlen; #endif struct group * -getgrent(void) +_getgrent_yp(int *foundyp) { struct group *p_gr = (struct group*)_THREAD_PRIVATE(gr, _gr_group, NULL); struct group_storage *gs = (struct group_storage *)_THREAD_PRIVATE(gr_storage, gr_storage, NULL); _THREAD_PRIVATE_MUTEX_LOCK(gr); - if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL, p_gr, gs)) + if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL, p_gr, gs, foundyp)) p_gr = NULL; _THREAD_PRIVATE_MUTEX_UNLOCK(gr); return (p_gr); } +struct group * +getgrent(void) +{ + return (_getgrent_yp(NULL)); +} + static struct group * getgrnam_gs(const char *name, struct group *p_gr, struct group_storage *gs) { @@ -98,7 +105,7 @@ getgrnam_gs(const char *name, struct group *p_gr, struct group_storage *gs) if (!start_gr()) rval = 0; else { - rval = grscan(1, 0, name, p_gr, gs); + rval = grscan(1, 0, name, p_gr, gs, NULL); if (!_gr_stayopen) endgrent_basic(); } @@ -144,7 +151,7 @@ getgrgid_gs(gid_t gid, struct group *p_gr, struct group_storage *gs) if (!start_gr()) rval = 0; else { - rval = grscan(1, gid, NULL, p_gr, gs); + rval = grscan(1, gid, NULL, p_gr, gs, NULL); if (!_gr_stayopen) endgrent_basic(); } @@ -245,7 +252,7 @@ endgrent(void) static int grscan(int search, gid_t gid, const char *name, struct group *p_gr, - struct group_storage *gs) + struct group_storage *gs, int *foundyp) { char *cp, **m; char *bp, *endp; @@ -349,6 +356,10 @@ grscan(int search, gid_t gid, const char *name, struct group *p_gr, } #ifdef YP if (line[0] == '+') { + if (foundyp) { + *foundyp = 1; + return (NULL); + } switch (line[1]) { case ':': case '\0': diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c index 800364c1a31..a3952c19055 100644 --- a/lib/libc/gen/getgrouplist.c +++ b/lib/libc/gen/getgrouplist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getgrouplist.c,v 1.12 2005/08/08 08:05:34 espie Exp $ */ +/* $OpenBSD: getgrouplist.c,v 1.13 2008/06/24 14:29:45 deraadt Exp $ */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. @@ -32,21 +32,23 @@ * get credential */ #include <sys/types.h> +#include <sys/limits.h> #include <string.h> #include <unistd.h> +#include <stdlib.h> #include <grp.h> +#include <pwd.h> + +#include <rpc/rpc.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> int getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) { + int i, ngroups = 0, ret = 0, maxgroups = *grpcnt, bail, foundyp = 0; + extern struct group *_getgrent_yp(int *); struct group *grp; - int i, ngroups; - int ret, maxgroups; - int bail; - - ret = 0; - ngroups = 0; - maxgroups = *grpcnt; /* * install primary group @@ -61,7 +63,7 @@ getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) * Scan the group file to find additional groups. */ setgrent(); - while ((grp = getgrent())) { + while ((grp = _getgrent_yp(&foundyp))) { if (grp->gr_gid == agroup) continue; for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) @@ -80,6 +82,76 @@ getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) } } } + +#ifdef YP + /* + * If we were told that there is a YP marker, look there now. + */ + if (foundyp) { + char buf[1024], *ypdata = NULL, *key, *p; + const char *errstr = NULL; + static char *__ypdomain; + struct passwd pwstore; + int r, ypdatalen; + gid_t gid; + uid_t uid; + + if (!__ypdomain) { + if (_yp_check(&__ypdomain) == 0) { + goto ypout; + } + } + + if (getpwnam_r(uname, &pwstore, buf, sizeof buf, NULL)) + goto ypout; + + asprintf(&key, "unix.%u@%s", pwstore.pw_uid, __ypdomain); + if (key == NULL) + goto ypout; + r = yp_match(__ypdomain, "netid.byname", key, + (int)strlen(key), &ypdata, &ypdatalen); + free(key); + if (r != 0) + goto ypout; + + /* Parse the "uid:gid[,gid,gid[,...]]" string. */ + p = strchr(ypdata, ':'); + if (!p) + goto ypout; + *p++ = '\0'; + uid = (uid_t)strtonum(ypdata, 0, UID_MAX, &errstr); + if (errstr || uid != pwstore.pw_uid) + goto ypout; + while (p && *p) { + char *start = p; + + p = strchr(start, ','); + if (p) + *p++ = '\0'; + gid = (uid_t)strtonum(start, 0, GID_MAX, &errstr); + if (errstr) + goto ypout; + + /* Add new groups to the group list */ + for (i = 0; i < ngroups; i++) { + if (groups[i] == gid) + break; + } + if (i == ngroups) { + if (ngroups >= maxgroups) { + ret = -1; + goto ypout; + } + groups[ngroups++] = gid; + } + } +ypout: + if (ypdata) + free(ypdata); + goto out; + } +#endif /* YP */ + out: endgrent(); *grpcnt = ngroups; |