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