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