17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate /*
247c478bd9Sstevel@tonic-gate  * Copyright (c) 1996, by Sun Microsystems, Inc.
257c478bd9Sstevel@tonic-gate  * All rights reserved.
267c478bd9Sstevel@tonic-gate  */
27*55fea89dSDan Cross 
287c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* SMI4.1 1.5 */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include "table.h"
347c478bd9Sstevel@tonic-gate #include "util.h"
357c478bd9Sstevel@tonic-gate #include "getgroup.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #define	MAXGROUPLEN 1024
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Stolen mostly, from getnetgrent.c
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * my_getgroup() performs the same function as _getgroup(), but operates
437c478bd9Sstevel@tonic-gate  * on /etc/netgroup directly, rather than doing yp lookups.
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  * /etc/netgroup must first loaded into a hash table so the matching
467c478bd9Sstevel@tonic-gate  * function can look up lines quickly.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /* To check for cycles in netgroups */
517c478bd9Sstevel@tonic-gate struct list {
527c478bd9Sstevel@tonic-gate 	char *name;
537c478bd9Sstevel@tonic-gate 	struct list *nxt;
547c478bd9Sstevel@tonic-gate };
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate extern stringtable ngtable; /* stored info from /etc/netgroup */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static struct grouplist *grouplist; /* stores a list of users in a group */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static char *any();
627c478bd9Sstevel@tonic-gate static char *match();
637c478bd9Sstevel@tonic-gate static char *fill();
647c478bd9Sstevel@tonic-gate static void freegrouplist();
657c478bd9Sstevel@tonic-gate static void doit();
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static void
freegrouplist()707c478bd9Sstevel@tonic-gate freegrouplist()
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	struct grouplist *gl;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	for (gl = grouplist; gl != NULL; gl = gl->gl_nxt) {
757c478bd9Sstevel@tonic-gate 		FREE(gl->gl_name);
767c478bd9Sstevel@tonic-gate 		FREE(gl->gl_domain);
777c478bd9Sstevel@tonic-gate 		FREE(gl->gl_machine);
787c478bd9Sstevel@tonic-gate 		FREE(gl);
797c478bd9Sstevel@tonic-gate 	}
807c478bd9Sstevel@tonic-gate 	grouplist = NULL;
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate struct grouplist *
my_getgroup(group)877c478bd9Sstevel@tonic-gate my_getgroup(group)
887c478bd9Sstevel@tonic-gate 	char *group;
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	freegrouplist();
917c478bd9Sstevel@tonic-gate 	doit(group, (struct list *) NULL);
927c478bd9Sstevel@tonic-gate 	return (grouplist);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * recursive function to find the members of netgroup "group". "list" is
1017c478bd9Sstevel@tonic-gate  * the path followed through the netgroups so far, to check for cycles.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate static void
doit(group,list)1047c478bd9Sstevel@tonic-gate doit(group, list)
1057c478bd9Sstevel@tonic-gate 	char *group;
1067c478bd9Sstevel@tonic-gate 	struct list *list;
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	register char *p, *q;
1097c478bd9Sstevel@tonic-gate 	register struct list *ls;
1107c478bd9Sstevel@tonic-gate 	struct list tmplist;
1117c478bd9Sstevel@tonic-gate 	char *val;
1127c478bd9Sstevel@tonic-gate 	struct grouplist *gpls;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/*
1167c478bd9Sstevel@tonic-gate 	 * check for non-existing groups
1177c478bd9Sstevel@tonic-gate 	 */
1187c478bd9Sstevel@tonic-gate 	if ((val = match(group)) == NULL) {
1197c478bd9Sstevel@tonic-gate 		return;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	/*
1247c478bd9Sstevel@tonic-gate 	 * check for cycles
1257c478bd9Sstevel@tonic-gate 	 */
1267c478bd9Sstevel@tonic-gate 	for (ls = list; ls != NULL; ls = ls->nxt) {
1277c478bd9Sstevel@tonic-gate 		if (strcmp(ls->name, group) == 0) {
1287c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1297c478bd9Sstevel@tonic-gate 				"Cycle detected in /etc/netgroup: %s.\n",
1307c478bd9Sstevel@tonic-gate 				group);
1317c478bd9Sstevel@tonic-gate 			return;
1327c478bd9Sstevel@tonic-gate 		}
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	ls = &tmplist;
1377c478bd9Sstevel@tonic-gate 	ls->name = group;
1387c478bd9Sstevel@tonic-gate 	ls->nxt = list;
1397c478bd9Sstevel@tonic-gate 	list = ls;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	p = val;
1427c478bd9Sstevel@tonic-gate 	while (p != NULL) {
1437c478bd9Sstevel@tonic-gate 		while (*p == ' ' || *p == '\t')
1447c478bd9Sstevel@tonic-gate 			p++;
1457c478bd9Sstevel@tonic-gate 		if (*p == EOS || *p == '#')
1467c478bd9Sstevel@tonic-gate 			break;
1477c478bd9Sstevel@tonic-gate 		if (*p == '(') {
1487c478bd9Sstevel@tonic-gate 			gpls = MALLOC(struct grouplist);
1497c478bd9Sstevel@tonic-gate 			p++;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 			if (!(p = fill(p, &gpls->gl_machine, ',')))  {
1527c478bd9Sstevel@tonic-gate 				goto syntax_error;
1537c478bd9Sstevel@tonic-gate 			}
1547c478bd9Sstevel@tonic-gate 			if (!(p = fill(p, &gpls->gl_name, ','))) {
1557c478bd9Sstevel@tonic-gate 				goto syntax_error;
1567c478bd9Sstevel@tonic-gate 			}
1577c478bd9Sstevel@tonic-gate 			if (!(p = fill(p, &gpls->gl_domain, ')'))) {
1587c478bd9Sstevel@tonic-gate 				goto syntax_error;
1597c478bd9Sstevel@tonic-gate 			}
1607c478bd9Sstevel@tonic-gate 			gpls->gl_nxt = grouplist;
1617c478bd9Sstevel@tonic-gate 			grouplist = gpls;
1627c478bd9Sstevel@tonic-gate 		} else {
1637c478bd9Sstevel@tonic-gate 			q = any(p, " \t\n#");
1647c478bd9Sstevel@tonic-gate 			if (q && *q == '#')
1657c478bd9Sstevel@tonic-gate 				break;
1667c478bd9Sstevel@tonic-gate 			*q = EOS;
1677c478bd9Sstevel@tonic-gate 			doit(p, list);
1687c478bd9Sstevel@tonic-gate 			*q = ' ';
1697c478bd9Sstevel@tonic-gate 		}
1707c478bd9Sstevel@tonic-gate 		p = any(p, " \t");
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	return;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate syntax_error:
1757c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "syntax error in /etc/netgroup\n");
1767c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "--- %s %s\n", group, val);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  * Fill a buffer "target" selectively from buffer "start".
1847c478bd9Sstevel@tonic-gate  * "termchar" terminates the information in start, and preceding
1857c478bd9Sstevel@tonic-gate  * or trailing white space is ignored.  If the buffer "start" is
1867c478bd9Sstevel@tonic-gate  * empty, "target" is filled with "*". The location just after the
1877c478bd9Sstevel@tonic-gate  * terminating character is returned.
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate static char *
fill(start,target,termchar)1907c478bd9Sstevel@tonic-gate fill(start, target, termchar)
1917c478bd9Sstevel@tonic-gate 	char *start;
1927c478bd9Sstevel@tonic-gate 	char **target;
1937c478bd9Sstevel@tonic-gate 	char termchar;
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	register char *p;
1967c478bd9Sstevel@tonic-gate 	register char *q;
1977c478bd9Sstevel@tonic-gate 	register char *r;
1987c478bd9Sstevel@tonic-gate 	int size;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	for (p = start; *p == ' ' || *p == '\t'; p++)
2017c478bd9Sstevel@tonic-gate 		;
2027c478bd9Sstevel@tonic-gate 	r = strchr(p, termchar);
2037c478bd9Sstevel@tonic-gate 	if (r == (char *)NULL) {
2047c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 	if (p == r) {
2077c478bd9Sstevel@tonic-gate 		*target = NULL;
2087c478bd9Sstevel@tonic-gate 	} else {
2097c478bd9Sstevel@tonic-gate 		for (q = r-1; *q == ' ' || *q == '\t'; q--)
2107c478bd9Sstevel@tonic-gate 			;
2117c478bd9Sstevel@tonic-gate 		size = q-p+1;
2127c478bd9Sstevel@tonic-gate 		STRNCPY(*target, p, size);
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 	return (r+1);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  * scans cp, looking for a match with any character
2207c478bd9Sstevel@tonic-gate  * in match.  Returns pointer to place in cp that matched
2217c478bd9Sstevel@tonic-gate  * (or NULL if no match)
2227c478bd9Sstevel@tonic-gate  */
2237c478bd9Sstevel@tonic-gate static char *
any(cp,match)2247c478bd9Sstevel@tonic-gate any(cp, match)
2257c478bd9Sstevel@tonic-gate 	register char *cp;
2267c478bd9Sstevel@tonic-gate 	char *match;
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	register char *mp, c;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	while (c = *cp) {
2317c478bd9Sstevel@tonic-gate 		for (mp = match; *mp; mp++)
2327c478bd9Sstevel@tonic-gate 			if (*mp == c)
2337c478bd9Sstevel@tonic-gate 				return (cp);
2347c478bd9Sstevel@tonic-gate 		cp++;
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 	return (NULL);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate  * The equivalent of yp_match. Returns the match, or NULL if there is none.
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate static char *
match(group)2457c478bd9Sstevel@tonic-gate match(group)
2467c478bd9Sstevel@tonic-gate 	char *group;
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	return (lookup(ngtable, group));
2497c478bd9Sstevel@tonic-gate }
250