xref: /illumos-gate/usr/src/cmd/ypcmd/revnetgroup/revnetgroup.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1994, by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * For SUNWnskit - version 1.1
29*7c478bd9Sstevel@tonic-gate  *
30*7c478bd9Sstevel@tonic-gate  * Based on:
31*7c478bd9Sstevel@tonic-gate  *	#pragma ident	"%Z%%M%	%I%	%E% SMI"	(SMI4.1 1.6)
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <stdio.h>
38*7c478bd9Sstevel@tonic-gate #include <ctype.h>
39*7c478bd9Sstevel@tonic-gate #include <pwd.h>
40*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
41*7c478bd9Sstevel@tonic-gate #include "util.h"
42*7c478bd9Sstevel@tonic-gate #include "table.h"
43*7c478bd9Sstevel@tonic-gate #include "getgroup.h"
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #define	MAXDOMAINLEN 256
46*7c478bd9Sstevel@tonic-gate #define	MAXGROUPLEN 1024
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * Reverse the netgroup file. A flag of "-u" means reverse by username,
50*7c478bd9Sstevel@tonic-gate  * one of "-h" means reverse by hostname. Each line in the output file
51*7c478bd9Sstevel@tonic-gate  * will begin with a key formed by concatenating the host or user name
52*7c478bd9Sstevel@tonic-gate  * with the domain name. The key will be followed by a tab, then the
53*7c478bd9Sstevel@tonic-gate  * comma-separated, newline-terminated list of groups to which the
54*7c478bd9Sstevel@tonic-gate  * user or host belongs.
55*7c478bd9Sstevel@tonic-gate  *
56*7c478bd9Sstevel@tonic-gate  * Exception: Groups to which everyone belongs (universal groups) will
57*7c478bd9Sstevel@tonic-gate  * not be included in the list.  The universal groups will be listed under
58*7c478bd9Sstevel@tonic-gate  * the special name "*".
59*7c478bd9Sstevel@tonic-gate  *
60*7c478bd9Sstevel@tonic-gate  * Thus to find out all the groups that user "foo" of domain "bar" is in,
61*7c478bd9Sstevel@tonic-gate  * lookup the groups under  foo.bar, foo.*, *.bar and *.*.
62*7c478bd9Sstevel@tonic-gate  *
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* Stores a list of strings */
68*7c478bd9Sstevel@tonic-gate typedef struct stringnode *stringlist;
69*7c478bd9Sstevel@tonic-gate struct stringnode {
70*7c478bd9Sstevel@tonic-gate     char *str;
71*7c478bd9Sstevel@tonic-gate     stringlist next;
72*7c478bd9Sstevel@tonic-gate };
73*7c478bd9Sstevel@tonic-gate typedef struct stringnode stringnode;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /* Stores a list of (name,list-of-groups) */
78*7c478bd9Sstevel@tonic-gate typedef struct groupentrynode *groupentrylist;
79*7c478bd9Sstevel@tonic-gate struct groupentrynode {
80*7c478bd9Sstevel@tonic-gate     char *name;
81*7c478bd9Sstevel@tonic-gate     stringlist groups;
82*7c478bd9Sstevel@tonic-gate     groupentrylist next;
83*7c478bd9Sstevel@tonic-gate };
84*7c478bd9Sstevel@tonic-gate typedef struct groupentrynode groupentrynode;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate stringtable ngtable;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static groupentrylist grouptable[TABLESIZE];
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate static char *nextgroup(void);
91*7c478bd9Sstevel@tonic-gate static void storegroup(char *group, struct grouplist *glist, int byuser);
92*7c478bd9Sstevel@tonic-gate static void enter(char *name, char *group);
93*7c478bd9Sstevel@tonic-gate static void appendgroup(groupentrylist grlist, char *group);
94*7c478bd9Sstevel@tonic-gate static groupentrylist newentry(char *name, char *group);
95*7c478bd9Sstevel@tonic-gate static void loadtable(FILE *nf);
96*7c478bd9Sstevel@tonic-gate static void dumptable(void);
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate int
99*7c478bd9Sstevel@tonic-gate main(argc, argv)
100*7c478bd9Sstevel@tonic-gate     int argc;
101*7c478bd9Sstevel@tonic-gate     char *argv[];
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	char *group;
104*7c478bd9Sstevel@tonic-gate 	struct grouplist *glist;
105*7c478bd9Sstevel@tonic-gate 	int byuser;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	loadtable(stdin);
108*7c478bd9Sstevel@tonic-gate 	if (argc == 2 && argv[1][0] == '-' &&
109*7c478bd9Sstevel@tonic-gate 			(argv[1][1] == 'u' || argv[1][1] == 'h')) {
110*7c478bd9Sstevel@tonic-gate 		byuser = (argv[1][1] == 'u');
111*7c478bd9Sstevel@tonic-gate 	} else {
112*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
113*7c478bd9Sstevel@tonic-gate 				"usage: %s -h (by host), %s -u (by user)\n",
114*7c478bd9Sstevel@tonic-gate 				argv[0], argv[0]);
115*7c478bd9Sstevel@tonic-gate 		exit(1);
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	while (group = nextgroup()) {
119*7c478bd9Sstevel@tonic-gate 		glist = my_getgroup(group);
120*7c478bd9Sstevel@tonic-gate 		storegroup(group, glist, byuser);
121*7c478bd9Sstevel@tonic-gate 	}
122*7c478bd9Sstevel@tonic-gate 	dumptable();
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	return (0);
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate /*
128*7c478bd9Sstevel@tonic-gate  *	Get the next netgroup from /etc/netgroup
129*7c478bd9Sstevel@tonic-gate  */
130*7c478bd9Sstevel@tonic-gate static char *
131*7c478bd9Sstevel@tonic-gate nextgroup(void)
132*7c478bd9Sstevel@tonic-gate {
133*7c478bd9Sstevel@tonic-gate 	static int index = -1;
134*7c478bd9Sstevel@tonic-gate 	static tablelist cur = NULL;
135*7c478bd9Sstevel@tonic-gate 	char *group;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	while (cur == NULL) {
138*7c478bd9Sstevel@tonic-gate 		if (++index == TABLESIZE) {
139*7c478bd9Sstevel@tonic-gate 			return (NULL);
140*7c478bd9Sstevel@tonic-gate 		}
141*7c478bd9Sstevel@tonic-gate 		cur = ngtable[index];
142*7c478bd9Sstevel@tonic-gate 	}
143*7c478bd9Sstevel@tonic-gate 	group = cur->key;
144*7c478bd9Sstevel@tonic-gate 	cur = cur->next;
145*7c478bd9Sstevel@tonic-gate 	return (group);
146*7c478bd9Sstevel@tonic-gate }
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate /*
151*7c478bd9Sstevel@tonic-gate  * Dump out all of the stored info into a file
152*7c478bd9Sstevel@tonic-gate  */
153*7c478bd9Sstevel@tonic-gate static void
154*7c478bd9Sstevel@tonic-gate dumptable(void)
155*7c478bd9Sstevel@tonic-gate {
156*7c478bd9Sstevel@tonic-gate 	int i;
157*7c478bd9Sstevel@tonic-gate 	groupentrylist entry;
158*7c478bd9Sstevel@tonic-gate 	stringlist groups;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < TABLESIZE; i++) {
161*7c478bd9Sstevel@tonic-gate 		if (entry = grouptable[i]) {
162*7c478bd9Sstevel@tonic-gate 			while (entry) {
163*7c478bd9Sstevel@tonic-gate 				fputs(entry->name, stdout);
164*7c478bd9Sstevel@tonic-gate 				putc('\t', stdout);
165*7c478bd9Sstevel@tonic-gate 				for (groups = entry->groups; groups;
166*7c478bd9Sstevel@tonic-gate 						groups = groups->next) {
167*7c478bd9Sstevel@tonic-gate 					fputs(groups->str, stdout);
168*7c478bd9Sstevel@tonic-gate 					if (groups->next) {
169*7c478bd9Sstevel@tonic-gate 						putc(',', stdout);
170*7c478bd9Sstevel@tonic-gate 					}
171*7c478bd9Sstevel@tonic-gate 				}
172*7c478bd9Sstevel@tonic-gate 				putc('\n', stdout);
173*7c478bd9Sstevel@tonic-gate 				entry = entry->next;
174*7c478bd9Sstevel@tonic-gate 			}
175*7c478bd9Sstevel@tonic-gate 		}
176*7c478bd9Sstevel@tonic-gate 	}
177*7c478bd9Sstevel@tonic-gate }
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate /*
183*7c478bd9Sstevel@tonic-gate  *	Add a netgroup to a user's list of netgroups
184*7c478bd9Sstevel@tonic-gate  */
185*7c478bd9Sstevel@tonic-gate static void
186*7c478bd9Sstevel@tonic-gate storegroup(char *group, struct grouplist *glist, int byuser)
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate 	char *name;	/* username or hostname */
189*7c478bd9Sstevel@tonic-gate 	char *domain;
190*7c478bd9Sstevel@tonic-gate 	char *key;
191*7c478bd9Sstevel@tonic-gate 	static char *universal = "*";
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	for (; glist; glist = glist->gl_nxt) {
194*7c478bd9Sstevel@tonic-gate 		name = byuser ? glist->gl_name : glist->gl_machine;
195*7c478bd9Sstevel@tonic-gate 		if (!name) {
196*7c478bd9Sstevel@tonic-gate 		    name = universal;
197*7c478bd9Sstevel@tonic-gate 		} else if (!isalnum(*name) && *name != '_') {
198*7c478bd9Sstevel@tonic-gate 		    continue;
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 		domain = glist->gl_domain;
201*7c478bd9Sstevel@tonic-gate 		if (!domain) {
202*7c478bd9Sstevel@tonic-gate 		    domain = universal;
203*7c478bd9Sstevel@tonic-gate 		}
204*7c478bd9Sstevel@tonic-gate 		key = malloc((unsigned) (strlen(name)+strlen(domain)+2));
205*7c478bd9Sstevel@tonic-gate 		(void) sprintf(key, "%s.%s", name, domain);
206*7c478bd9Sstevel@tonic-gate 		enter(key, group);
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate static groupentrylist
213*7c478bd9Sstevel@tonic-gate newentry(char *name, char *group)
214*7c478bd9Sstevel@tonic-gate {
215*7c478bd9Sstevel@tonic-gate 	groupentrylist new;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	new = MALLOC(groupentrynode);
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	STRCPY(new->name, name);
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	new->groups = MALLOC(stringnode);
222*7c478bd9Sstevel@tonic-gate 	new->groups->str = group;
223*7c478bd9Sstevel@tonic-gate 	new->groups->next = NULL;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	new->next = NULL;
226*7c478bd9Sstevel@tonic-gate 	return (new);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate static void
230*7c478bd9Sstevel@tonic-gate appendgroup(groupentrylist grlist, char *group)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate 	stringlist cur, prev;
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	for (cur = grlist->groups; cur; prev = cur, cur = cur->next) {
235*7c478bd9Sstevel@tonic-gate 		if (strcmp(group, cur->str) == 0) {
236*7c478bd9Sstevel@tonic-gate 		    return;
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate 	}
239*7c478bd9Sstevel@tonic-gate 	prev->next = MALLOC(stringnode);
240*7c478bd9Sstevel@tonic-gate 	cur = prev->next;
241*7c478bd9Sstevel@tonic-gate 	cur->str = group;
242*7c478bd9Sstevel@tonic-gate 	cur->next = NULL;
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate static void
246*7c478bd9Sstevel@tonic-gate enter(char *name, char *group)
247*7c478bd9Sstevel@tonic-gate {
248*7c478bd9Sstevel@tonic-gate 	int key;
249*7c478bd9Sstevel@tonic-gate 	groupentrylist gel;
250*7c478bd9Sstevel@tonic-gate 	groupentrylist gelprev;
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	key = tablekey(name);
253*7c478bd9Sstevel@tonic-gate 	if (grouptable[key] == NULL) {
254*7c478bd9Sstevel@tonic-gate 		grouptable[key] = newentry(name, group);
255*7c478bd9Sstevel@tonic-gate 	} else {
256*7c478bd9Sstevel@tonic-gate 		gel = grouptable[key];
257*7c478bd9Sstevel@tonic-gate 		while (gel && strcmp(gel->name, name)) {
258*7c478bd9Sstevel@tonic-gate 		    gelprev = gel;
259*7c478bd9Sstevel@tonic-gate 		    gel = gel->next;
260*7c478bd9Sstevel@tonic-gate 		}
261*7c478bd9Sstevel@tonic-gate 		if (gel) {
262*7c478bd9Sstevel@tonic-gate 		    appendgroup(gel, group);
263*7c478bd9Sstevel@tonic-gate 		} else {
264*7c478bd9Sstevel@tonic-gate 		    gelprev->next = newentry(name, group);
265*7c478bd9Sstevel@tonic-gate 		}
266*7c478bd9Sstevel@tonic-gate 	}
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate /*
270*7c478bd9Sstevel@tonic-gate  * Load up a hash table with the info in /etc/netgroup
271*7c478bd9Sstevel@tonic-gate  */
272*7c478bd9Sstevel@tonic-gate static void
273*7c478bd9Sstevel@tonic-gate loadtable(FILE *nf)
274*7c478bd9Sstevel@tonic-gate {
275*7c478bd9Sstevel@tonic-gate 	char buf[MAXGROUPLEN];
276*7c478bd9Sstevel@tonic-gate 	char *p;
277*7c478bd9Sstevel@tonic-gate 	char *group;
278*7c478bd9Sstevel@tonic-gate 	char *line;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	while (getline(buf, MAXGROUPLEN, nf)) {
281*7c478bd9Sstevel@tonic-gate 		for (p = buf; *p && isspace((int)*p); p++)
282*7c478bd9Sstevel@tonic-gate 			;	/* skip leading blanks */
283*7c478bd9Sstevel@tonic-gate 		for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++)
284*7c478bd9Sstevel@tonic-gate 			;
285*7c478bd9Sstevel@tonic-gate 		if (*p == EOS || *p == '#')
286*7c478bd9Sstevel@tonic-gate 			continue;
287*7c478bd9Sstevel@tonic-gate 		*p++ = EOS;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 		while (*p == ' ' || *p == '\t') {
290*7c478bd9Sstevel@tonic-gate 			p++;
291*7c478bd9Sstevel@tonic-gate 		}
292*7c478bd9Sstevel@tonic-gate 		if (*p == EOS || *p == '#')
293*7c478bd9Sstevel@tonic-gate 			continue;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 		STRCPY(group, buf);
296*7c478bd9Sstevel@tonic-gate 		STRCPY(line, p);
297*7c478bd9Sstevel@tonic-gate 		store(ngtable, group, line);
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate }
300