summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2008-06-24 14:29:46 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2008-06-24 14:29:46 +0000
commit3c299ffbcf5658385f822ec5be0eb9f422c756ff (patch)
tree01015121d27c673288316fd7baa7e6b797d3abca /lib/libc/gen
parent3c00af7e9ff7ae6d3fd059414ddfacb8b93b6254 (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.c25
-rw-r--r--lib/libc/gen/getgrouplist.c90
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;