summaryrefslogtreecommitdiff
path: root/lib/libc/gen/getnetgrent.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /lib/libc/gen/getnetgrent.c
initial import of NetBSD tree
Diffstat (limited to 'lib/libc/gen/getnetgrent.c')
-rw-r--r--lib/libc/gen/getnetgrent.c735
1 files changed, 735 insertions, 0 deletions
diff --git a/lib/libc/gen/getnetgrent.c b/lib/libc/gen/getnetgrent.c
new file mode 100644
index 00000000000..19e25321227
--- /dev/null
+++ b/lib/libc/gen/getnetgrent.c
@@ -0,0 +1,735 @@
+/* $NetBSD: getnetgrent.c,v 1.8 1995/02/25 08:51:19 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * 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 Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$NetBSD: getnetgrent.c,v 1.8 1995/02/25 08:51:19 cgd Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <netgroup.h>
+#include <string.h>
+#include <fcntl.h>
+#include <err.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <db.h>
+
+#define _NG_STAR(s) (((s) == NULL || *(s) == '\0') ? _ngstar : s)
+#define _NG_ISSPACE(p) (isspace((unsigned char) (p)) || (p) == '\n')
+
+static const char _ngstar[] = "*";
+static const char _ngoomem[] = "netgroup: %m";
+static struct netgroup *_nghead = (struct netgroup *)NULL;
+static struct netgroup *_nglist = (struct netgroup *)NULL;
+static DB *_ng_db;
+
+/*
+ * Simple string list
+ */
+struct stringlist {
+ char **sl_str;
+ size_t sl_max;
+ size_t sl_cur;
+};
+
+static int getstring __P((char **, int, char **));
+static struct netgroup *getnetgroup __P((char **));
+static int lookup __P((const char *, char *, char **, int));
+static void addgroup __P((char *, struct stringlist *, char *));
+static int in_check __P((const char *, const char *,
+ const char *, struct netgroup *));
+static int in_find __P((char *, struct stringlist *,
+ char *, const char *,
+ const char *, const char *));
+static char *in_lookup1 __P((const char *, const char *,
+ const char *, int));
+static int in_lookup __P((const char *, const char *,
+ const char *, const char *, int));
+
+/*
+ * _ng_sl_init(): Initialize a string list
+ */
+struct stringlist *
+_ng_sl_init()
+{
+ struct stringlist *sl = malloc(sizeof(struct stringlist));
+ if (sl == NULL)
+ _err(1, _ngoomem);
+
+ sl->sl_cur = 0;
+ sl->sl_max = 20;
+ sl->sl_str = malloc(sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL)
+ _err(1, _ngoomem);
+ return sl;
+}
+
+
+/*
+ * _ng_sl_add(): Add an item to the string list
+ */
+void
+_ng_sl_add(sl, name)
+ struct stringlist *sl;
+ char *name;
+{
+ if (sl->sl_cur == sl->sl_max - 1) {
+ sl->sl_max += 20;
+ sl->sl_str = realloc(sl->sl_str, sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL)
+ _err(1, _ngoomem);
+ }
+ sl->sl_str[sl->sl_cur++] = name;
+}
+
+
+/*
+ * _ng_sl_free(): Free a stringlist
+ */
+void
+_ng_sl_free(sl, all)
+ struct stringlist *sl;
+ int all;
+{
+ size_t i;
+
+ if (all)
+ for (i = 0; i < sl->sl_cur; i++)
+ free(sl->sl_str[i]);
+ free(sl->sl_str);
+ free(sl);
+}
+
+
+/*
+ * sl_find(): Find a name in the string list
+ */
+char *
+_ng_sl_find(sl, name)
+ struct stringlist *sl;
+ char *name;
+{
+ size_t i;
+
+ for (i = 0; i < sl->sl_cur; i++)
+ if (strcmp(sl->sl_str[i], name) == 0)
+ return sl->sl_str[i];
+
+ return NULL;
+}
+
+
+/*
+ * getstring(): Get a string delimited by the character, skipping leading and
+ * trailing blanks and advancing the pointer
+ */
+static int
+getstring(pp, del, str)
+ char **pp;
+ int del;
+ char **str;
+{
+ char *sp, *ep, *dp;
+
+ /* skip leading blanks */
+ for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
+ continue;
+
+ /* accumulate till delimiter or space */
+ for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
+ continue;
+
+ /* hunt for the delimiter */
+ for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
+ continue;
+
+ if (*dp != del) {
+ *str = NULL;
+ return 0;
+ }
+
+ *pp = ++dp;
+
+ del = (ep - sp) + 1;
+ if (del > 1) {
+ dp = malloc(del);
+ if (dp == NULL)
+ _err(1, _ngoomem);
+ memcpy(dp, sp, del);
+ dp[del - 1] = '\0';
+ } else
+ dp = NULL;
+
+ *str = dp;
+ return 1;
+}
+
+
+/*
+ * getnetgroup(): Parse a netgroup, and advance the pointer
+ */
+static struct netgroup *
+getnetgroup(pp)
+ char **pp;
+{
+ struct netgroup *ng = malloc(sizeof(struct netgroup));
+
+ if (ng == NULL)
+ _err(1, _ngoomem);
+
+ (*pp)++; /* skip '(' */
+ if (!getstring(pp, ',', &ng->ng_host))
+ goto badhost;
+
+ if (!getstring(pp, ',', &ng->ng_user))
+ goto baduser;
+
+ if (!getstring(pp, ')', &ng->ng_domain))
+ goto baddomain;
+
+#ifdef DEBUG_NG
+ (void) fprintf(stderr, "netgroup(%s,%s,%s)\n",
+ _NG_STAR(ng->ng_host), _NG_STAR(ng->ng_user),
+ _NG_STAR(ng->ng_domain));
+#endif
+ return ng;
+
+baddomain:
+ if (ng->ng_user)
+ free(ng->ng_user);
+baduser:
+ if (ng->ng_host)
+ free(ng->ng_host);
+badhost:
+ free(ng);
+ return NULL;
+}
+
+
+/*
+ * lookup(): Find the given key in the database or yp, and return its value
+ * in *line; returns 1 if key was found, 0 otherwise
+ */
+static int
+lookup(ypdom, name, line, bywhat)
+ const char *ypdom;
+ char *name;
+ char **line;
+ int bywhat;
+{
+#ifdef YP
+ int i;
+ char *map = NULL;
+#endif
+
+ if (_ng_db) {
+ DBT key, data;
+ size_t len = strlen(name) + 2;
+ char *ks = malloc(len);
+
+ ks[0] = bywhat;
+ memcpy(&ks[1], name, len - 1);
+
+ key.data = (u_char *) ks;
+ key.size = len;
+
+ switch ((_ng_db->get) (_ng_db, &key, &data, 0)) {
+ case 0:
+ free(ks);
+ *line = strdup(data.data);
+ if (*line == NULL)
+ _err(1, _ngoomem);
+ return 1;
+
+ case 1:
+ break;
+
+ case -1:
+ _warn("netgroup: db get");
+ break;
+ }
+ free(ks);
+ }
+#ifdef YP
+ if (ypdom) {
+ switch (bywhat) {
+ case _NG_KEYBYNAME:
+ map = "netgroup";
+ break;
+
+ case _NG_KEYBYUSER:
+ map = "netgroup.byuser";
+ break;
+
+ case _NG_KEYBYHOST:
+ map = "netgroup.byhost";
+ break;
+
+ default:
+ abort();
+ break;
+ }
+
+
+ if (yp_match(ypdom, map, name, strlen(name), line, &i) == 0)
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+
+/*
+ * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
+ * line was empty or a comment _NG_GROUP: line had a netgroup definition,
+ * returned in ng _NG_NAME: line had a netgroup name, returned in name
+ *
+ * Public since used by netgroup_mkdb
+ */
+int
+_ng_parse(p, name, ng)
+ char **p;
+ char **name;
+ struct netgroup **ng;
+{
+ while (**p) {
+ if (**p == '#')
+ /* comment */
+ return _NG_NONE;
+
+ while (**p && _NG_ISSPACE(**p))
+ /* skipblank */
+ (*p)++;
+
+ if (**p == '(') {
+ if ((*ng = getnetgroup(p)) == NULL) {
+ _warnx("netgroup: Syntax error `%s'", *p);
+ return _NG_ERROR;
+ }
+ return _NG_GROUP;
+ } else {
+ char *np;
+ int i;
+
+ for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
+ continue;
+ if (np != *p) {
+ i = (*p - np) + 1;
+ *name = malloc(i);
+ if (*name == NULL)
+ _err(1, _ngoomem);
+ memcpy(*name, np, i);
+ (*name)[i - 1] = '\0';
+ return _NG_NAME;
+ }
+ }
+ }
+ return _NG_NONE;
+}
+
+
+/*
+ * addgroup(): Recursively add all the members of the netgroup to this group
+ */
+static void
+addgroup(ypdom, sl, grp)
+ char *ypdom;
+ struct stringlist *sl;
+ char *grp;
+{
+ char *line, *p;
+ struct netgroup *ng;
+ char *name;
+
+#ifdef DEBUG_NG
+ (void) fprintf(stderr, "addgroup(%s)\n", grp);
+#endif
+ /* check for cycles */
+ if (_ng_sl_find(sl, grp) != NULL) {
+ free(grp);
+ _warnx("netgroup: Cycle in group `%s'", grp);
+ return;
+ }
+ _ng_sl_add(sl, grp);
+
+ /* Lookup this netgroup */
+ if (!lookup(ypdom, grp, &line, _NG_KEYBYNAME))
+ return;
+
+ p = line;
+
+ for (;;) {
+ switch (_ng_parse(&p, &name, &ng)) {
+ case _NG_NONE:
+ /* Done with the line */
+ free(line);
+ return;
+
+ case _NG_GROUP:
+ /* new netgroup */
+ /* add to the list */
+ ng->ng_next = _nglist;
+ _nglist = ng;
+ break;
+
+ case _NG_NAME:
+ /* netgroup name */
+ addgroup(ypdom, sl, name);
+ break;
+
+ case _NG_ERROR:
+ return;
+
+ default:
+ abort();
+ return;
+ }
+ }
+}
+
+
+/*
+ * in_check(): Compare the spec with the netgroup
+ */
+static int
+in_check(host, user, domain, ng)
+ const char *host;
+ const char *user;
+ const char *domain;
+ struct netgroup *ng;
+{
+ if ((host != NULL) && (ng->ng_host != NULL)
+ && strcmp(ng->ng_host, host) != 0)
+ return 0;
+
+ if ((user != NULL) && (ng->ng_user != NULL)
+ && strcmp(ng->ng_user, user) != 0)
+ return 0;
+
+ if ((domain != NULL) && (ng->ng_domain != NULL)
+ && strcmp(ng->ng_domain, domain) != 0)
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * in_find(): Find a match for the host, user, domain spec
+ */
+static int
+in_find(ypdom, sl, grp, host, user, domain)
+ char *ypdom;
+ struct stringlist *sl;
+ char *grp;
+ const char *host;
+ const char *user;
+ const char *domain;
+{
+ char *line, *p;
+ int i;
+ struct netgroup *ng;
+ char *name;
+
+#ifdef DEBUG_NG
+ (void) fprintf(stderr, "in_find(%s)\n", grp);
+#endif
+ /* check for cycles */
+ if (_ng_sl_find(sl, grp) != NULL) {
+ free(grp);
+ _warnx("netgroup: Cycle in group `%s'", grp);
+ return 0;
+ }
+ _ng_sl_add(sl, grp);
+
+ /* Lookup this netgroup */
+ if (!lookup(ypdom, grp, &line, _NG_KEYBYNAME))
+ return 0;
+
+ p = line;
+
+ for (;;) {
+ switch (_ng_parse(&p, &name, &ng)) {
+ case _NG_NONE:
+ /* Done with the line */
+ free(line);
+ return 0;
+
+ case _NG_GROUP:
+ /* new netgroup */
+ i = in_check(host, user, domain, ng);
+ if (ng->ng_host != NULL)
+ free(ng->ng_host);
+ if (ng->ng_user != NULL)
+ free(ng->ng_user);
+ if (ng->ng_domain != NULL)
+ free(ng->ng_domain);
+ free(ng);
+ if (i) {
+ free(line);
+ return 1;
+ }
+ break;
+
+ case _NG_NAME:
+ /* netgroup name */
+ if (in_find(ypdom, sl, name, host, user, domain)) {
+ free(line);
+ return 1;
+ }
+ break;
+
+ case _NG_ERROR:
+ free(line);
+ return 0;
+
+ default:
+ abort();
+ return 0;
+ }
+ }
+}
+
+
+/*
+ * _ng_makekey(): Make a key from the two names given. The key is of the form
+ * <name1>.<name2> Names strings are replaced with * if they are empty;
+ */
+char *
+_ng_makekey(s1, s2, len)
+ const char *s1, *s2;
+ size_t len;
+{
+ char *buf = malloc(len);
+ if (buf == NULL)
+ _err(1, _ngoomem);
+ (void) snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
+ return buf;
+}
+
+
+/*
+ * in_lookup1(): Fast lookup for a key in the appropriate map
+ */
+static char *
+in_lookup1(ypdom, key, domain, map)
+ const char *ypdom;
+ const char *key;
+ const char *domain;
+ int map;
+{
+ char *line;
+ size_t len;
+ char *ptr;
+ int res;
+
+ len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2;
+ ptr = _ng_makekey(key, domain, len);
+ res = lookup(ypdom, ptr, &line, map);
+ free(ptr);
+ return res ? line : NULL;
+}
+
+
+/*
+ * in_lookup(): Fast lookup for a key in the appropriate map
+ */
+static int
+in_lookup(ypdom, group, key, domain, map)
+ const char *ypdom;
+ const char *group;
+ const char *key;
+ const char *domain;
+ int map;
+{
+ size_t len;
+ char *ptr, *line;
+
+ if (domain != NULL) {
+ /* Domain specified; look in "group.domain" and "*.domain" */
+ if ((line = in_lookup1(ypdom, key, domain, map)) == NULL)
+ line = in_lookup1(ypdom, NULL, domain, map);
+ }
+ else
+ line = NULL;
+
+ if (line == NULL) {
+ /*
+ * domain not specified or domain lookup failed; look in
+ * "group.*" and "*.*"
+ */
+ if (((line = in_lookup1(ypdom, key, NULL, map)) == NULL) &&
+ ((line = in_lookup1(ypdom, NULL, NULL, map)) == NULL))
+ return 0;
+ }
+
+ len = strlen(group);
+
+ for (ptr = line; (ptr = strstr(ptr, group)) != NULL;)
+ /* Make sure we did not find a substring */
+ if ((ptr != line && ptr[-1] != ',') ||
+ (ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL))
+ ptr++;
+ else {
+ free(line);
+ return 1;
+ }
+
+ free(line);
+ return 0;
+}
+
+
+void
+endnetgrent()
+{
+ for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) {
+ _nghead = _nglist->ng_next;
+ if (_nglist->ng_host != NULL)
+ free(_nglist->ng_host);
+ if (_nglist->ng_user != NULL)
+ free(_nglist->ng_user);
+ if (_nglist->ng_domain != NULL)
+ free(_nglist->ng_domain);
+ free(_nglist);
+ }
+
+ if (_ng_db) {
+ (void) (_ng_db->close) (_ng_db);
+ _ng_db = NULL;
+ }
+}
+
+
+void
+setnetgrent(ng)
+ const char *ng;
+{
+ struct stringlist *sl = _ng_sl_init();
+#ifdef YP
+ char *line;
+#endif
+ char *ng_copy, *ypdom = NULL;
+
+ /* Cleanup any previous storage */
+ if (_nghead != NULL)
+ endnetgrent();
+
+ if (_ng_db == NULL)
+ _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
+
+#ifdef YP
+ /*
+ * We use yp if there is a "+" in the netgroup file, or if there is
+ * no netgroup file at all
+ */
+ if (_ng_db == NULL || lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0)
+ yp_get_default_domain(&ypdom);
+ else
+ free(line);
+#endif
+ ng_copy = strdup(ng);
+ if (ng_copy == NULL)
+ _err(1, _ngoomem);
+ addgroup(ypdom, sl, ng_copy);
+ _nghead = _nglist;
+ _ng_sl_free(sl, 1);
+}
+
+
+int
+getnetgrent(host, user, domain)
+ const char **host;
+ const char **user;
+ const char **domain;
+{
+ if (_nglist == NULL)
+ return 0;
+
+ *host = _nglist->ng_host;
+ *user = _nglist->ng_user;
+ *domain = _nglist->ng_domain;
+
+ _nglist = _nglist->ng_next;
+
+ return 1;
+}
+
+
+int
+innetgr(grp, host, user, domain)
+ const char *grp, *host, *user, *domain;
+{
+ char *ypdom = NULL;
+#ifdef YP
+ char *line;
+#endif
+ int found;
+ struct stringlist *sl;
+
+ if (_ng_db == NULL)
+ _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL);
+
+#ifdef YP
+ /*
+ * We use yp if there is a "+" in the netgroup file, or if there is
+ * no netgroup file at all
+ */
+ if (_ng_db == NULL)
+ yp_get_default_domain(&ypdom);
+ else if (lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0) {
+ yp_get_default_domain(&ypdom);
+ free(line);
+ }
+#endif
+
+ /* Try the fast lookup first */
+ if (host != NULL && user == NULL) {
+ if (in_lookup(ypdom, grp, host, domain, _NG_KEYBYHOST))
+ return 1;
+ } else if (host == NULL && user != NULL) {
+ if (in_lookup(ypdom, grp, user, domain, _NG_KEYBYUSER))
+ return 1;
+ }
+ /* If a domainname is given, we would have found a match */
+ if (domain != NULL)
+ return 0;
+
+ /* Too bad need the slow recursive way */
+ sl = _ng_sl_init();
+ found = in_find(ypdom, sl, strdup(grp), host, user, domain);
+ _ng_sl_free(sl, 1);
+
+ return found;
+}