Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/gen Reorganise the getting of grouplists for a user...
details: https://anonhg.NetBSD.org/src/rev/e2a331881cb9
branches: trunk
changeset: 543066:e2a331881cb9
user: elric <elric%NetBSD.org@localhost>
date: Sun Feb 16 01:22:44 2003 +0000
description:
Reorganise the getting of grouplists for a user so that Hesiod (and
potentially other name services) can directly query for a user's
grouplist rather than needing to iterate over the group map. This
is required for correct operation of Hesiod.
Reviewed by: lukem, christos
Addresses PR lib/20183
diffstat:
lib/libc/gen/getgrent.c | 170 ++++++++++++++++++++++++++++++++++++++-----
lib/libc/gen/getgrouplist.c | 34 ++++----
2 files changed, 167 insertions(+), 37 deletions(-)
diffs (truncated from 435 to 300 lines):
diff -r a47f1ad52d25 -r e2a331881cb9 lib/libc/gen/getgrent.c
--- a/lib/libc/gen/getgrent.c Sun Feb 16 00:22:37 2003 +0000
+++ b/lib/libc/gen/getgrent.c Sun Feb 16 01:22:44 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: getgrent.c,v 1.44 2003/02/03 04:22:20 elric Exp $ */
+/* $NetBSD: getgrent.c,v 1.45 2003/02/16 01:22:44 elric Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
#else
-__RCSID("$NetBSD: getgrent.c,v 1.44 2003/02/03 04:22:20 elric Exp $");
+__RCSID("$NetBSD: getgrent.c,v 1.45 2003/02/16 01:22:44 elric Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -72,6 +72,8 @@
#define _GROUP_COMPAT
#endif
+struct group *_getgrent_user(const char *);
+
#ifdef __weak_alias
__weak_alias(endgrent,_endgrent)
__weak_alias(getgrent,_getgrent)
@@ -87,9 +89,9 @@
static int _gr_filesdone;
static void grcleanup(void);
-static int grscan(int, gid_t, const char *);
+static int grscan(int, gid_t, const char *, const char *);
static int grstart(void);
-static int grmatchline(int, gid_t, const char *);
+static int grmatchline(int, gid_t, const char *, const char *);
#define MAXGRP 200
#define MAXLINELENGTH 1024
@@ -104,7 +106,10 @@
#endif
#ifdef HESIOD
-static int _gr_hesnum;
+static int _gr_hesnum;
+static struct group *_gr_hesgrplist = NULL;
+static int _gr_hesgrplistnum;
+static int _gr_hesgrplistmax;
#endif
#ifdef _GROUP_COMPAT
@@ -116,7 +121,22 @@
getgrent(void)
{
- if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL))
+ if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, NULL))
+ return (NULL);
+ return &_gr_group;
+}
+
+/*
+ * _getgrent_user() is desgined 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;
}
@@ -130,7 +150,7 @@
if (!grstart())
return NULL;
- rval = grscan(1, 0, name);
+ rval = grscan(1, 0, name, NULL);
if (!_gr_stayopen)
endgrent();
return (rval) ? &_gr_group : NULL;
@@ -143,7 +163,7 @@
if (!grstart())
return NULL;
- rval = grscan(1, gid, NULL);
+ rval = grscan(1, gid, NULL, NULL);
if (!_gr_stayopen)
endgrent();
return (rval) ? &_gr_group : NULL;
@@ -162,6 +182,11 @@
#endif
#ifdef HESIOD
_gr_hesnum = 0;
+ if (!_gr_hesgrplist)
+ free(_gr_hesgrplist);
+ _gr_hesgrplist = NULL;
+ _gr_hesgrplistnum = -1;
+ _gr_hesgrplistmax = 0;
#endif
#ifdef _GROUP_COMPAT
__grmode = GRMODE_NONE;
@@ -218,6 +243,7 @@
int search = va_arg(ap, int);
gid_t gid = va_arg(ap, gid_t);
const char *name = va_arg(ap, const char *);
+ const char *user = va_arg(ap, const char *);
if (_gr_filesdone)
return NS_NOTFOUND;
@@ -235,7 +261,7 @@
;
continue;
}
- if (grmatchline(search, gid, name))
+ if (grmatchline(search, gid, name, user))
return NS_SUCCESS;
}
/* NOTREACHED */
@@ -243,6 +269,7 @@
#ifdef HESIOD
static int _dns_grscan(void *, void *, va_list);
+static int _dns_grplist(const char *);
/*ARGSUSED*/
static int
@@ -251,12 +278,23 @@
int search = va_arg(ap, int);
gid_t gid = va_arg(ap, gid_t);
const char *name = va_arg(ap, const char *);
+ const char *user = va_arg(ap, const char *);
char **hp;
void *context;
int r;
r = NS_UNAVAIL;
+ if (!search && user && _gr_hesgrplistmax != -1) {
+ r = _dns_grplist(user);
+ /* if we did not find user.grplist, just iterate */
+ if (!_gr_hesgrplist) {
+ _gr_hesgrplistmax = -1;
+ if (r != NS_NOTFOUND)
+ return r;
+ } else
+ return r;
+ }
if (!search && _gr_hesnum == -1)
return NS_NOTFOUND;
if (hesiod_init(&context) == -1)
@@ -294,7 +332,7 @@
/* only check first elem */
strlcpy(line, hp[0], sizeof(line));
hesiod_free_list(context, hp);
- if (grmatchline(search, gid, name)) {
+ if (grmatchline(search, gid, name, user)) {
r = NS_SUCCESS;
break;
} else if (search) {
@@ -305,6 +343,88 @@
hesiod_end(context);
return (r);
}
+
+static int
+_dns_grplist(const char *user)
+{
+ void *context;
+ int r;
+ char **hp;
+ char *cp;
+
+ r = NS_UNAVAIL;
+ if (!_gr_hesgrplist) {
+ if (hesiod_init(&context) == -1)
+ return r;
+
+ _gr_hesgrplistnum = -1;
+ hp = hesiod_resolve(context, user, "grplist");
+ if (!hp) {
+ if (errno == ENOENT)
+ r = NS_NOTFOUND;
+ hesiod_end(context);
+ return r;
+ }
+
+ strlcpy(line, hp[0], sizeof(line));
+ hesiod_free_list(context, hp);
+
+ _gr_hesgrplistmax = 0;
+ for (cp=line; *cp; cp++)
+ if (*cp == ':')
+ _gr_hesgrplistmax++;
+ _gr_hesgrplistmax /= 2;
+ _gr_hesgrplistmax++;
+
+ _gr_hesgrplist = malloc(_gr_hesgrplistmax *
+ sizeof(*_gr_hesgrplist));
+ if (!_gr_hesgrplist) {
+ hesiod_end(context);
+ return NS_UNAVAIL;
+ }
+
+ cp = line;
+ _gr_hesgrplistmax = 0;
+ for (;;) {
+ char *name;
+ char *num;
+ gid_t gid;
+ char *ep;
+
+ /* XXXrcd: error handling */
+ if (!(name = strsep(&cp, ":")))
+ break;
+ if (!(num = strsep(&cp, ":")))
+ break;
+ gid = (gid_t) strtoul(num, &ep, 10);
+ if (gid > GID_MAX || *ep != '\0')
+ break;
+
+ _gr_hesgrplist[_gr_hesgrplistmax].gr_name = name;
+ _gr_hesgrplist[_gr_hesgrplistmax].gr_gid = gid;
+ _gr_hesgrplistmax++;
+ }
+
+ hesiod_end(context);
+ }
+
+ /* we assume that _gr_hesgrplist is now defined */
+ if (++_gr_hesgrplistnum >= _gr_hesgrplistmax)
+ return NS_NOTFOUND;
+
+ /*
+ * Now we copy the relevant information into _gr_group, so that
+ * it can be returned. Note that we only fill in the bare necessities
+ * as this will be used exclusively by getgrouplist(3) and we do
+ * not want to have to look up all of the information.
+ */
+ _gr_group.gr_name = _gr_hesgrplist[_gr_hesgrplistnum].gr_name;
+ _gr_group.gr_passwd = NULL;
+ _gr_group.gr_gid = _gr_hesgrplist[_gr_hesgrplistnum].gr_gid;
+ _gr_group.gr_mem = NULL;
+
+ return NS_SUCCESS;
+}
#endif /* HESIOD */
#ifdef YP
@@ -317,6 +437,7 @@
int search = va_arg(ap, int);
gid_t gid = va_arg(ap, gid_t);
const char *name = va_arg(ap, const char *);
+ const char *user = va_arg(ap, const char *);
char *key, *data;
int keylen, datalen;
@@ -357,7 +478,7 @@
data[datalen] = '\0'; /* clear trailing \n */
strlcpy(line, data, sizeof(line));
free(data);
- if (grmatchline(search, gid, name))
+ if (grmatchline(search, gid, name, user))
return NS_SUCCESS;
else
return NS_NOTFOUND;
@@ -406,7 +527,7 @@
data[datalen] = '\0'; /* clear trailing \n */
strlcpy(line, data, sizeof(line));
free(data);
- if (grmatchline(search, gid, name))
+ if (grmatchline(search, gid, name, user))
return NS_SUCCESS;
}
/* NOTREACHED */
@@ -442,10 +563,10 @@
* sense to lookup compat names from 'files' or 'compat'
*/
-static int __grscancompat(int, gid_t, const char *);
+static int __grscancompat(int, gid_t, const char *, const char *);
static int
-__grscancompat(int search, gid_t gid, const char *name)
+__grscancompat(int search, gid_t gid, const char *name, const char *user)
{
static const ns_dtab dtab[] = {
NS_FILES_CB(_bad_grscan, "files")
@@ -462,7 +583,7 @@
_DIAGASSERT(name != NULL);
return (nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "grscancompat",
- defaultnis, search, gid, name));
+ defaultnis, search, gid, name, user));
}
#endif /* GROUP_COMPAT */
Home |
Main Index |
Thread Index |
Old Index