xref: /titanic_52/usr/src/cmd/ypcmd/mknetid/mknetid.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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  * Copyright (C) 1990-2000, Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 
28 #ident	"%Z%%M%	%I%	%E% SMI"	/* SMI4.1 1.5 */
29 
30 /*
31  * Network name to unix credential database generator.
32  * Uses /etc/passwd, /etc/group, /etc/hosts and /etc/netid to
33  * create the database.
34  *
35  * If some user appears in passwd, they get an entry like:
36  *	sun.<uid>@<domainname>	<uid>:<gid1>,<gid2>,...
37  * If some host appears in hosts, it gets an entry like:
38  *	sun.<hostname>@<domainname>	0:<hostname>
39  *
40  * The file /etc/netid is used to add other domains (possibly non-unix)
41  * to the database.
42  */
43 #include <stdio.h>
44 #include <pwd.h>
45 #include <limits.h>
46 #include <sys/param.h>
47 #include <rpc/rpc.h>
48 #include <rpc/key_prot.h>
49 
50 
51 #define	MAXNAMELEN	256
52 #define	MAXLINELEN	1024
53 #define	MAXDOMAINLEN	32
54 
55 #define	GRPTABSIZE	256		/* size of group table */
56 #define	PRNTABSIZE	4096		/* size of printed item table */
57 
58 #define	NUMGIDS	(NGROUPS_MAX + 1)	/* group-access-list + gid */
59 
60 extern char **getline();
61 extern char *malloc();
62 extern char *strcpy();
63 
64 /*
65  * The group list
66  * Store username and groups to which he/she belongs
67  */
68 struct group_list {
69 	char *user;
70 	int group_len;
71 	int groups[NUMGIDS];
72 	struct group_list *next;
73 };
74 
75 /*
76  * General purpose list of strings
77  */
78 struct string_list {
79 	char *str;
80 	struct string_list *next;
81 };
82 
83 static FILE *openfile();
84 static char *scanargs();
85 static int atoi();
86 
87 static char *cmdname;	/* name of this program */
88 static int quietmode;	/* quiet mode: don't print error messages */
89 static char *curfile;	/* name of file we are parsing */
90 static int curline;		/* current line parsed in this file */
91 
92 static struct group_list *groups[GRPTABSIZE];	/* group table */
93 static struct string_list *printed[PRNTABSIZE];	/* printed item table */
94 static char domain[MAXDOMAINLEN];	/* name of our domain */
95 
96 static char PASSWD[] = "/etc/passwd";	/* default passwd database */
97 static char IDMAP[] = "/etc/idmap";	/* default net-id map database */
98 static char GROUP[] = "/etc/group";	/* default group database */
99 static char HOSTS[] = "/etc/hosts";	/* default hosts database */
100 
101 static char *pwdfile = PASSWD;	/* password file to parse */
102 static char *grpfile = GROUP;	/* group file */
103 static char *hostfile = HOSTS;	/* hosts file */
104 static char *mapfile = IDMAP;	/* network id file */
105 
106 /*
107  * Various separaters
108  */
109 static char WHITE[] = "\t ";
110 static char COLON[] = ":";
111 static char COMMA[] = ",";
112 
113 main(argc, argv)
114 	int argc;
115 	char *argv[];
116 {
117 	FILE *pf, *mf, *gf, *hf;
118 
119 	cmdname = argv[0];
120 	if (!parseargs(argc, argv)) {
121 		(void) fprintf(stderr,
122 			"usage: %s [-q] [-pghm filename]\n", cmdname);
123 		exit(1);
124 	}
125 	(void) getdomainname(domain, sizeof (domain));
126 
127 	pf = openfile(pwdfile);
128 	gf = openfile(grpfile);
129 	hf = openfile(hostfile);
130 	mf = fopen(mapfile, "r");
131 
132 
133 	if (mf != NULL) {
134 		domapfile(mapfile, mf);
135 	}
136 	dogrpfile(grpfile, gf);
137 	dopwdfile(pwdfile, pf);
138 	dohostfile(hostfile, hf);
139 
140 	exit(0);
141 	/* NOTREACHED */
142 }
143 
144 /*
145  * Parse the network id mapping file
146  */
147 domapfile(mapfile, mf)
148 	char *mapfile;
149 	FILE *mf;
150 {
151 	char **lp;
152 	char line[MAXLINELEN];
153 	char name[MAXNAMELEN];
154 	int uid, gid;
155 
156 	curfile = mapfile;
157 	curline = 0;
158 	while (lp = getline(line, sizeof (line), mf, &curline, "#")) {
159 		check_getname(lp, name, WHITE, WHITE, "#");
160 		if (wasprinted(name)) {
161 			multdef(name);
162 			continue;
163 		}
164 		put_s(name);
165 		(void) putchar(' ');
166 		check_getname(lp, name, WHITE, COLON, "#");
167 		uid = Atoi(name);
168 		put_d(uid);
169 		(void) putchar(':');
170 		if (uid == 0) {
171 			check_getname(lp, name, WHITE, "\t\n ", "#");
172 			put_s(name);
173 			(void) putchar(' ');
174 		} else {
175 			check_getname(lp, name, WHITE, ",\n", "#");
176 			gid = Atoi(name);
177 			put_d(gid);
178 			while (getname(name, sizeof (name), WHITE, ",\n", lp,
179 					"#") >= 0) {
180 				gid = Atoi(name);
181 				(void) putchar(',');
182 				put_d(gid);
183 			}
184 		}
185 		(void) putchar('\n');
186 	}
187 }
188 
189 
190 /*
191  * Parse the groups file
192  */
193 dogrpfile(grpfile, gf)
194 	char *grpfile;
195 	FILE *gf;
196 {
197 	char **lp;
198 	char line[MAXLINELEN];
199 	char name[MAXNAMELEN];
200 	int gid;
201 
202 	curfile = grpfile;
203 	curline = 0;
204 	while (lp = getline(line, sizeof (line), gf, &curline, "")) {
205 		check_getname(lp, name, WHITE, COLON, "");
206 		if (name[0] == '+') {
207 			continue;
208 		}
209 		check_getname(lp, name, WHITE, COLON, ""); /* ignore passwd */
210 		check_getname(lp, name, WHITE, COLON, "");
211 		gid = Atoi(name);
212 		while (getname(name, sizeof (name), WHITE, COMMA, lp,
213 				"") >= 0) {
214 			storegid(gid, name);
215 		}
216 	}
217 }
218 
219 
220 /*
221  * Parse the password file
222  */
223 dopwdfile(pwdfile, pf)
224 	char *pwdfile;
225 	FILE *pf;
226 {
227 	char **lp;
228 	char line[MAXLINELEN];
229 	char name[MAXNAMELEN];
230 	char user[MAXNAMELEN];
231 	int uid, gid;
232 
233 	curfile = pwdfile;
234 	curline = 0;
235 
236 	while (lp = getline(line, sizeof (line), pf, &curline, "")) {
237 		check_getname(lp, user, WHITE, COLON, ""); 	/* username */
238 		if (user[0] == '-' || user[0] == '+') {
239 			continue;	/* NIS entry */
240 		}
241 		check_getname(lp, name, WHITE, COLON, ""); /* ignore passwd */
242 		check_getname(lp, name, WHITE, COLON, ""); /* but get uid */
243 		uid = Atoi(name);
244 		user2netname(name, uid, domain);
245 		if (wasprinted(name)) {
246 			multdef(name);
247 			continue;
248 		}
249 		put_s(name);
250 		(void) putchar(' ');
251 		check_getname(lp, name, WHITE, COLON, "");
252 		gid = Atoi(name);
253 		put_d(uid);
254 		(void) putchar(':');
255 		printgroups(user, gid);
256 	}
257 }
258 
259 
260 /*
261  * Parse the hosts file
262  */
263 dohostfile(hostfile, hf)
264 	char *hostfile;
265 	FILE *hf;
266 {
267 	char **lp;
268 	char line[MAXLINELEN];
269 	char name[MAXNAMELEN];
270 	char netname[MAXNETNAMELEN];
271 
272 	curfile = hostfile;
273 	curline = 0;
274 	while (lp = getline(line, sizeof (line), hf, &curline, "#")) {
275 		check_getname(lp, name, WHITE, WHITE, "#");
276 		if (getname(name, MAXNAMELEN, WHITE, WHITE, lp, "#") != 1) {
277 			continue;
278 		}
279 		host2netname(netname, name, domain);
280 		if (wasprinted(netname)) {
281 			multdef(netname);
282 			continue;
283 		}
284 		(void) printf("%s 0:%.*s\n", netname, sizeof (name), name);
285 	}
286 }
287 
288 /*
289  * Open a file, exit on failure
290  */
291 static FILE *
292 openfile(fname)
293 	char *fname;
294 {
295 	FILE *f;
296 
297 	f = fopen(fname, "r");
298 	if (f == NULL) {
299 		(void) fprintf(stderr, "%s: can't open %s\n", cmdname, fname);
300 		exit(1);
301 	}
302 	return (f);
303 }
304 
305 /*
306  * Print syntax error message, then exit
307  */
308 syntaxerror()
309 {
310 	(void) fprintf(stderr, "%s: syntax error in file \"%s\", line %d\n",
311 	    cmdname, curfile, curline);
312 	exit(1);
313 }
314 
315 
316 /*
317  * an atoi() that prints a message and exits upong failure
318  */
319 static int
320 Atoi(str)
321 	char *str;
322 {
323 	int res;
324 
325 	if (!sscanf(str, "%d", &res)) {
326 		syntaxerror();
327 	}
328 	return (res);
329 }
330 
331 
332 /*
333  * Attempt to get a token from a file, print a message and exit upon failure
334  */
335 check_getname(lp, name, skip, term, com)
336 	char **lp;
337 	char *name;
338 	char *skip;
339 	char *term;
340 	char *com;
341 {
342 	if (getname(name, MAXNAMELEN, skip, term, lp, com) != 1) {
343 		syntaxerror();
344 	}
345 }
346 
347 /*
348  * Something was defined more than once
349  */
350 multdef(name)
351 	char *name;
352 {
353 	if (!quietmode) {
354 		(void) fprintf(stderr,
355 			"%s: %s multiply defined, other definitions ignored\n",
356 			cmdname, name);
357 	}
358 }
359 
360 static
361 hash(str, size)
362 	unsigned char *str;
363 	int size;
364 {
365 	unsigned val;
366 	int flip;
367 
368 	val = 0;
369 	flip = 0;
370 	while (*str) {
371 		if (flip) {
372 			val ^= (*str++ << 6);
373 		} else {
374 			val ^= *str++;
375 		}
376 		flip = !flip;
377 	}
378 	return (val % size);
379 }
380 
381 
382 /*
383  * Check if an item has been printed
384  * If not, store the item into the printed item table
385  */
386 static
387 wasprinted(name)
388 	char *name;
389 {
390 	struct string_list *s;
391 	int val;
392 
393 	val = hash((unsigned char *) name, PRNTABSIZE);
394 	for (s = printed[val]; s != NULL && strcmp(s->str, name); s = s->next)
395 		;
396 	if (s != NULL) {
397 		return (1);
398 	}
399 	s = (struct string_list *)malloc(sizeof (struct string_list));
400 	s->str = malloc((unsigned)strlen(name) + 1);
401 	(void) strcpy(s->str, name);
402 	s->next = printed[val];
403 	printed[val] = s;
404 	return (0);
405 }
406 
407 /*
408  * Add gid to the list of a user's groups
409  */
410 storegid(gid, user)
411 	int gid;
412 	char *user;
413 {
414 	struct group_list *g;
415 	int i;
416 	int val;
417 
418 	val = hash((unsigned char *) user, GRPTABSIZE);
419 	for (g = groups[val]; g != NULL && strcmp(g->user, user); g = g->next)
420 		;
421 	if (g == NULL) {
422 		g = (struct group_list *)malloc(sizeof (struct group_list));
423 		g->user = malloc((unsigned)strlen(user) + 1);
424 		(void) strcpy(g->user, user);
425 		g->group_len = 1;
426 		g->groups[0] = gid;
427 		g->next = groups[val];
428 		groups[val] = g;
429 	} else {
430 		for (i = 0; i < g->group_len; i++) {
431 			if (g->groups[i] == gid) {
432 				return;
433 			}
434 		}
435 		if (g->group_len >= NUMGIDS) {
436 			(void) fprintf(stderr, "%s: %s's groups exceed %d\n",
437 				cmdname, user, NGROUPS_MAX);
438 			return;
439 		}
440 		g->groups[g->group_len++] = gid;
441 	}
442 }
443 
444 /*
445  * print out a user's groups
446  */
447 printgroups(user, gid)
448 	char *user;
449 	int gid;
450 {
451 	struct group_list *g;
452 	int i;
453 	int val;
454 
455 	val = hash((unsigned char *) user, GRPTABSIZE);
456 	for (g = groups[val]; g != NULL && strcmp(g->user, user); g = g->next)
457 		;
458 	put_d(gid);
459 	if (g != NULL) {
460 		for (i = 0; i < g->group_len; i++) {
461 			if (gid != g->groups[i]) {
462 				(void) putchar(',');
463 				put_d(g->groups[i]);
464 			}
465 		}
466 	}
467 	(void) putchar('\n');
468 }
469 
470 
471 /*
472  * Parse command line arguments
473  */
474 parseargs(argc, argv)
475 	int argc;
476 	char *argv[];
477 {
478 	int i;
479 	int j;
480 	static struct {
481 		char letter;
482 		char *standard;
483 		char **filename;
484 	} whattodo[] = {
485 		{ 'p', PASSWD, &pwdfile },
486 		{ 'g', GROUP, &grpfile },
487 		{ 'm', IDMAP, &mapfile },
488 		{ 'h', HOSTS, &hostfile }
489 	};
490 
491 #define	TABSIZE  sizeof (whattodo)/sizeof (whattodo[0])
492 
493 	for (i = 1; i < argc; i++) {
494 		if (argv[i][0] == '-') {
495 			if (argv[i][2] != 0) {
496 				return (0);
497 			}
498 			if (argv[i][1] == 'q') {
499 				quietmode = 1;
500 				continue;
501 			}
502 			for (j = 0; j < TABSIZE; j++) {
503 				if (whattodo[j].letter == argv[i][1]) {
504 					if (*whattodo[j].filename !=
505 							whattodo[j].standard) {
506 						return (0);
507 					}
508 					if (++i == argc) {
509 						return (0);
510 					}
511 					*whattodo[j].filename = argv[i];
512 					break;
513 				}
514 			}
515 			if (j == TABSIZE) {
516 				return (0);
517 			}
518 		}
519 	}
520 	return (1);
521 }
522 
523 /*
524  * Print a string, quickly
525  */
526 put_s(s)
527 	char *s;
528 {
529 	(void) fwrite(s, strlen(s), 1, stdout);
530 }
531 
532 /*
533  * Print an integer, quickly
534  */
535 put_d(d)
536 	int d;
537 {
538 	char buf[20];
539 	char *p;
540 
541 	if (d == 0) {
542 		(void) putchar('0');
543 		return;
544 	}
545 	if (d < 0) {
546 		(void) putchar('-');
547 		d = -d;
548 	}
549 	p = buf + sizeof (buf);
550 	*--p = 0;
551 	while (d > 0) {
552 		*--p = (d % 10) + '0';
553 		d /= 10;
554 	}
555 	put_s(p);
556 }
557