1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License").  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24#if !defined(lint) && defined(SCCSIDS)
25static	char sccsid[] = "@(#)innetgr.c	1.2 90/07/20 4.1NFSSRC; from 1.17 88/02/08 SMI Copyr 1985 Sun Micro";
26#endif
27
28/*
29 * Copyright (c) 1990 by Sun Microsystems, Inc.
30 */
31
32#include <stdio.h>
33#include <ctype.h>
34#include <stdlib.h>
35#include <string.h>
36#include <rpcsvc/ypclnt.h>
37
38/*
39 * innetgr: test whether I'm in /etc/netgroup
40 *
41 */
42
43
44struct innetgrdata {
45	char	*name;
46	char	*machine;
47	char	*domain;
48	char	**list;
49#define	LISTSIZE 200			/* recursion limit */
50	char	**listp;		/* pointer into list */
51	char	*thisdomain;
52};
53
54static int lookup(char *, char *, char *, char *, char *, int *);
55static int doit(register struct innetgrdata *, char *);
56static void makekey(char *, char *, char *);
57
58int _old_innetgr(group, machine, name, domain)
59	char *group, *machine, *name, *domain;
60{
61	int res;
62	register struct innetgrdata *d;
63	char *thisdomain;
64
65	(void) yp_get_default_domain(&thisdomain);
66	if (domain) {
67		if (name && !machine) {
68			if (lookup(thisdomain,
69			    "netgroup.byuser",group,name,domain,&res)) {
70				return(res);
71			}
72		} else if (machine && !name) {
73			if (lookup(thisdomain,
74			    "netgroup.byhost",group,machine,domain,&res)) {
75				return(res);
76			}
77		}
78	}
79	d = (struct innetgrdata *)malloc(sizeof (struct innetgrdata));
80	if (d == 0)
81		return (0);
82	d->machine = machine;
83	d->name = name;
84	d->domain = domain;
85	d->thisdomain = thisdomain;
86	d->list = (char **)calloc(LISTSIZE, sizeof (char *));
87	d->listp = d->list;
88	if (d->list == 0) {
89		free(d);
90		return (0);
91	}
92	res = doit(d, group);
93	free(d->list);
94	free(d);
95	return (res);
96}
97
98/*
99 * calls itself recursively
100 */
101static int
102doit(d, group)
103	register struct innetgrdata *d;
104	char *group;
105{
106	char *key, *val;
107	int vallen,keylen;
108	char *r;
109	int match;
110	register char *p, *q;
111	register char **lp;
112	int err;
113
114	*d->listp++ = group;
115	if (d->listp > d->list + LISTSIZE) {
116		(void) fprintf(stderr, "innetgr: recursive overflow\r\n");
117		d->listp--;
118		return (0);
119	}
120	key = group;
121	keylen = strlen(group);
122	err = yp_match(d->thisdomain, "netgroup", key, keylen, &val, &vallen);
123	if (err) {
124#ifdef DEBUG
125		if (err == YPERR_KEY)
126			(void) fprintf(stderr,
127			    "innetgr: no such netgroup as %s\n", group);
128		else
129			(void) fprintf(stderr, "innetgr: yp_match, %s\n",yperr_string(err));
130#endif
131		d->listp--;
132		return(0);
133	}
134	/*
135	 * check for recursive loops
136	 */
137	for (lp = d->list; lp < d->listp-1; lp++)
138		if (strcmp(*lp, group) == 0) {
139			(void) fprintf(stderr,
140			    "innetgr: netgroup %s called recursively\r\n",
141			    group);
142			d->listp--;
143			free(val);
144			return(0);
145		}
146
147	p = val;
148	p[vallen] = 0;
149	while (p != NULL) {
150		match = 0;
151		while (*p == ' ' || *p == '\t')
152			p++;
153		if (*p == 0 || *p == '#')
154			break;
155		if (*p == '(') {
156			p++;
157			while (*p == ' ' || *p == '\t')
158				p++;
159			r = q = index(p, ',');
160			if (q == NULL) {
161				(void) fprintf(stderr,
162				    "innetgr: syntax error in /etc/netgroup\r\n");
163				d->listp--;
164				free(val);
165				return(0);
166			}
167			if (p == q || d->machine == NULL)
168				match++;
169			else {
170				while (*(q-1) == ' ' || *(q-1) == '\t')
171					q--;
172				if (strncmp(d->machine, p, q-p) == 0)
173					match++;
174			}
175			p = r+1;
176
177			while (*p == ' ' || *p == '\t')
178				p++;
179			r = q = index(p, ',');
180			if (q == NULL) {
181				(void) fprintf(stderr,
182				    "innetgr: syntax error in /etc/netgroup\r\n");
183				d->listp--;
184				free(val);
185				return(0);
186			}
187			if (p == q || d->name == NULL)
188				match++;
189			else {
190				while (*(q-1) == ' ' || *(q-1) == '\t')
191					q--;
192				if (strncmp(d->name, p, q-p) == 0)
193					match++;
194			}
195			p = r+1;
196
197			while (*p == ' ' || *p == '\t')
198				p++;
199			r = q = index(p, ')');
200			if (q == NULL) {
201				(void) fprintf(stderr,
202				    "innetgr: syntax error in /etc/netgroup\r\n");
203				d->listp--;
204				free(val);
205				return(0);
206			}
207			if (p == q || d->domain == NULL)
208				match++;
209			else {
210				while (*(q-1) == ' ' || *(q-1) == '\t')
211					q--;
212				if (strncmp(d->domain, p, q-p) == 0)
213					match++;
214			}
215			p = r+1;
216			if (match == 3) {
217				free(val);
218				d->listp--;
219				return 1;
220			}
221		}
222		else {
223			q = strpbrk(p, " \t\n#");
224			if (q && *q == '#')
225				break;
226			if (q)
227				*q = 0;
228			if (doit(d, p)) {
229				free(val);
230				d->listp--;
231				return 1;
232			}
233			if (q)
234				*q = ' ';
235		}
236		p = strpbrk(p, " \t");
237	}
238	free(val);
239	d->listp--;
240	return 0;
241}
242
243/*
244 * return 1 if "what" is in the comma-separated, newline-terminated "d->list"
245 */
246static int
247inlist(what,list)
248	char *what;
249	char *list;
250{
251#	define TERMINATOR(c)    (c == ',' || c == '\n')
252
253	register char *p;
254	int len;
255
256	len = strlen(what);
257	p = list;
258	do {
259		if (strncmp(what,p,len) == 0 && TERMINATOR(p[len])) {
260			return(1);
261		}
262		while (!TERMINATOR(*p)) {
263			p++;
264		}
265		p++;
266	} while (*p);
267	return(0);
268}
269
270
271
272
273/*
274 * Lookup a host or user name in a NIS map.  Set result to 1 if group in the
275 * lookup list of groups. Return 1 if the map was found.
276 */
277static int
278lookup(thisdomain,map,group,name,domain,res)
279	char *thisdomain;
280	char *map;
281	char *group;
282	char *name;
283	char *domain;
284	int *res;
285{
286	int err;
287	char *val;
288	int vallen;
289	char key[256];
290	char *wild = "*";
291	int i;
292
293	for (i = 0; i < 4; i++) {
294		switch (i) {
295		case 0: makekey(key,name,domain); break;
296		case 1: makekey(key,wild,domain); break;
297		case 2: makekey(key,name,wild); break;
298		case 3: makekey(key,wild,wild); break;
299		}
300		err  = yp_match(thisdomain,map,key,strlen(key),&val,&vallen);
301		if (!err) {
302			*res = inlist(group,val);
303			free(val);
304			if (*res) {
305				return(1);
306			}
307		} else {
308#ifdef DEBUG
309			(void) fprintf(stderr,
310				"yp_match(%s,%s) failed: %s.\n",map,key,yperr_string(err));
311#endif
312			if (err != YPERR_KEY)  {
313				return(0);
314			}
315		}
316	}
317	*res = 0;
318	return(1);
319}
320
321
322
323/*
324 * Generate a key for a netgroup.byXXXX NIS map
325 */
326static void
327makekey(key,name,domain)
328	register char *key;
329	register char *name;
330	register char *domain;
331{
332	while ((*key++ = *name++))
333		;
334	*(key-1) = '.';
335	while ((*key++ = *domain++))
336		;
337}
338