Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/gen Try nsdispatch "getgrouplist" before iterating ...



details:   https://anonhg.NetBSD.org/src/rev/fd16f9af25b3
branches:  trunk
changeset: 570131:fd16f9af25b3
user:      lukem <lukem%NetBSD.org@localhost>
date:      Sat Sep 25 12:27:35 2004 +0000

description:
Try nsdispatch "getgrouplist" before iterating the getgrent() list.
Implement a dns (hesiod) backend which tries a grplist hesiod lookup.
Convert back to using getgrent() similar to rev 1.15, instead of
using the private _getgrent_user() from getgrent.c.

diffstat:

 lib/libc/gen/getgrouplist.c |  172 ++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 151 insertions(+), 21 deletions(-)

diffs (224 lines):

diff -r 51d9f03596ee -r fd16f9af25b3 lib/libc/gen/getgrouplist.c
--- a/lib/libc/gen/getgrouplist.c       Sat Sep 25 12:24:53 2004 +0000
+++ b/lib/libc/gen/getgrouplist.c       Sat Sep 25 12:27:35 2004 +0000
@@ -1,4 +1,40 @@
-/*     $NetBSD: getgrouplist.c,v 1.18 2004/09/25 02:55:25 lukem Exp $  */
+/*     $NetBSD: getgrouplist.c,v 1.19 2004/09/25 12:27:35 lukem Exp $  */
+
+/*-
+ * Copyright (c) 2004 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.
+ */
 
 /*
  * Copyright (c) 1991, 1993
@@ -34,43 +70,132 @@
 #if 0
 static char sccsid[] = "@(#)getgrouplist.c     8.2 (Berkeley) 12/8/94";
 #else
-__RCSID("$NetBSD: getgrouplist.c,v 1.18 2004/09/25 02:55:25 lukem Exp $");
+__RCSID("$NetBSD: getgrouplist.c,v 1.19 2004/09/25 12:27:35 lukem Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
 /*
- * get credential
+ * calculate group access list
  */
+
 #include "namespace.h"
 #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
 
-/*
- * _getgrent_user() is a libc-private function defined in getgrent.c which
- * use because certain name service types such as Hesiod lookup grouplists
- * by username rather than just iterating over the list of groups.
- */
-struct group *_getgrent_user(const char *);
+#ifdef HESIOD
+
+/*ARGSUSED*/
+static int
+_nss_dns_getgrouplist(void *retval, void *cb_data, va_list ap)
+{
+       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++;
+       }
+
+       *(int *)retval = 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;
-       int ret, maxgroups;
+       int i, ngroups, maxgroups, ret, glretval;
+
+       static const ns_dtab dtab[] = {
+               NS_DNS_CB(_nss_dns_getgrouplist, NULL)
+               { 0 }
+       };
 
        _DIAGASSERT(uname != NULL);
        _DIAGASSERT(groups != NULL);
        _DIAGASSERT(grpcnt != NULL);
 
+                       /* first, try source-specific optimized getgrouplist */
+       ret = nsdispatch(&glretval, dtab, NSDB_GROUP, "getgrouplist",
+           __nsdefaultsrc,
+           uname, agroup, groups, grpcnt);
+       if (ret == NS_SUCCESS)
+               return glretval;
+
+                       /* fallback to scan the group(5) database */
        ret = 0;
        ngroups = 0;
        maxgroups = *grpcnt;
@@ -89,20 +214,25 @@
         */
        setgrent();
  nextgroup:
-       while ((grp = _getgrent_user(uname)) != NULL) {
+       while ((grp = getgrent()) != NULL) {
                if (grp->gr_gid == agroup)
                        continue;
-               for (i = 0; i < MIN(ngroups, maxgroups); i++) {
-                       if (grp->gr_gid == groups[i])
-                               goto nextgroup;
+               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;
                }
-               if (ngroups < maxgroups)
-                       groups[ngroups] = grp->gr_gid;
-               else
-                       ret = -1;
-               ngroups++;
        }
        endgrent();
        *grpcnt = ngroups;
-       return (ret);
+       return ret;
 }



Home | Main Index | Thread Index | Old Index