1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright (c) 1996, by Sun Microsystems, Inc.
25  * All rights reserved.
26  */
27 
28 #ident	"%Z%%M%	%I%	%E% SMI"	/* SMI4.1 1.5 */
29 
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include "table.h"
34 #include "util.h"
35 #include "getgroup.h"
36 
37 #define	MAXGROUPLEN 1024
38 
39 /*
40  * Stolen mostly, from getnetgrent.c
41  *
42  * my_getgroup() performs the same function as _getgroup(), but operates
43  * on /etc/netgroup directly, rather than doing yp lookups.
44  *
45  * /etc/netgroup must first loaded into a hash table so the matching
46  * function can look up lines quickly.
47  */
48 
49 
50 /* To check for cycles in netgroups */
51 struct list {
52 	char *name;
53 	struct list *nxt;
54 };
55 
56 
57 extern stringtable ngtable; /* stored info from /etc/netgroup */
58 
59 static struct grouplist *grouplist; /* stores a list of users in a group */
60 
61 static char *any();
62 static char *match();
63 static char *fill();
64 static void freegrouplist();
65 static void doit();
66 
67 
68 
69 static void
freegrouplist()70 freegrouplist()
71 {
72 	struct grouplist *gl;
73 
74 	for (gl = grouplist; gl != NULL; gl = gl->gl_nxt) {
75 		FREE(gl->gl_name);
76 		FREE(gl->gl_domain);
77 		FREE(gl->gl_machine);
78 		FREE(gl);
79 	}
80 	grouplist = NULL;
81 }
82 
83 
84 
85 
86 struct grouplist *
my_getgroup(group)87 my_getgroup(group)
88 	char *group;
89 {
90 	freegrouplist();
91 	doit(group, (struct list *) NULL);
92 	return (grouplist);
93 }
94 
95 
96 
97 
98 
99 /*
100  * recursive function to find the members of netgroup "group". "list" is
101  * the path followed through the netgroups so far, to check for cycles.
102  */
103 static void
doit(group,list)104 doit(group, list)
105 	char *group;
106 	struct list *list;
107 {
108 	register char *p, *q;
109 	register struct list *ls;
110 	struct list tmplist;
111 	char *val;
112 	struct grouplist *gpls;
113 
114 
115 	/*
116 	 * check for non-existing groups
117 	 */
118 	if ((val = match(group)) == NULL) {
119 		return;
120 	}
121 
122 
123 	/*
124 	 * check for cycles
125 	 */
126 	for (ls = list; ls != NULL; ls = ls->nxt) {
127 		if (strcmp(ls->name, group) == 0) {
128 			(void) fprintf(stderr,
129 				"Cycle detected in /etc/netgroup: %s.\n",
130 				group);
131 			return;
132 		}
133 	}
134 
135 
136 	ls = &tmplist;
137 	ls->name = group;
138 	ls->nxt = list;
139 	list = ls;
140 
141 	p = val;
142 	while (p != NULL) {
143 		while (*p == ' ' || *p == '\t')
144 			p++;
145 		if (*p == EOS || *p == '#')
146 			break;
147 		if (*p == '(') {
148 			gpls = MALLOC(struct grouplist);
149 			p++;
150 
151 			if (!(p = fill(p, &gpls->gl_machine, ',')))  {
152 				goto syntax_error;
153 			}
154 			if (!(p = fill(p, &gpls->gl_name, ','))) {
155 				goto syntax_error;
156 			}
157 			if (!(p = fill(p, &gpls->gl_domain, ')'))) {
158 				goto syntax_error;
159 			}
160 			gpls->gl_nxt = grouplist;
161 			grouplist = gpls;
162 		} else {
163 			q = any(p, " \t\n#");
164 			if (q && *q == '#')
165 				break;
166 			*q = EOS;
167 			doit(p, list);
168 			*q = ' ';
169 		}
170 		p = any(p, " \t");
171 	}
172 	return;
173 
174 syntax_error:
175 	(void) fprintf(stderr, "syntax error in /etc/netgroup\n");
176 	(void) fprintf(stderr, "--- %s %s\n", group, val);
177 }
178 
179 
180 
181 
182 /*
183  * Fill a buffer "target" selectively from buffer "start".
184  * "termchar" terminates the information in start, and preceding
185  * or trailing white space is ignored.  If the buffer "start" is
186  * empty, "target" is filled with "*". The location just after the
187  * terminating character is returned.
188  */
189 static char *
fill(start,target,termchar)190 fill(start, target, termchar)
191 	char *start;
192 	char **target;
193 	char termchar;
194 {
195 	register char *p;
196 	register char *q;
197 	register char *r;
198 	int size;
199 
200 	for (p = start; *p == ' ' || *p == '\t'; p++)
201 		;
202 	r = strchr(p, termchar);
203 	if (r == (char *)NULL) {
204 		return ((char *)NULL);
205 	}
206 	if (p == r) {
207 		*target = NULL;
208 	} else {
209 		for (q = r-1; *q == ' ' || *q == '\t'; q--)
210 			;
211 		size = q-p+1;
212 		STRNCPY(*target, p, size);
213 	}
214 	return (r+1);
215 }
216 
217 
218 /*
219  * scans cp, looking for a match with any character
220  * in match.  Returns pointer to place in cp that matched
221  * (or NULL if no match)
222  */
223 static char *
any(cp,match)224 any(cp, match)
225 	register char *cp;
226 	char *match;
227 {
228 	register char *mp, c;
229 
230 	while (c = *cp) {
231 		for (mp = match; *mp; mp++)
232 			if (*mp == c)
233 				return (cp);
234 		cp++;
235 	}
236 	return (NULL);
237 }
238 
239 
240 
241 /*
242  * The equivalent of yp_match. Returns the match, or NULL if there is none.
243  */
244 static char *
match(group)245 match(group)
246 	char *group;
247 {
248 	return (lookup(ngtable, group));
249 }
250