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