GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ypserv/mknetid/mknetid.c Lines: 0 250 0.0 %
Date: 2017-11-13 Branches: 0 207 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mknetid.c,v 1.22 2015/02/09 23:00:15 deraadt Exp $ */
2
3
/*
4
 * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include <stdio.h>
30
#include <unistd.h>
31
#include <ctype.h>
32
#include <string.h>
33
#include <stdlib.h>
34
#include <pwd.h>
35
#include <grp.h>
36
#include <err.h>
37
#include <netdb.h>
38
#include <limits.h>
39
40
#include <rpcsvc/ypclnt.h>
41
42
struct user {
43
	char	*usr_name;		/* user name */
44
	int	usr_uid;		/* user uid */
45
	int	usr_gid;		/* user gid */
46
	int	gid_count;		/* number of gids */
47
	int	gid[NGROUPS_MAX];	/* additional gids */
48
	struct user *prev, *next;	/* links in read order */
49
	struct user *hprev, *hnext;	/* links in hash order */
50
};
51
52
char *HostFile = _PATH_HOSTS;
53
char *PasswdFile = _PATH_PASSWD;
54
char *MasterPasswdFile = _PATH_MASTERPASSWD;
55
char *GroupFile = _PATH_GROUP;
56
char *NetidFile = "/etc/netid";
57
58
#define HASHMAX 55
59
60
struct user *root = NULL, *tail = NULL;
61
struct user *hroot[HASHMAX], *htail[HASHMAX];
62
63
static int
64
read_line(FILE *fp, char *buf, int size)
65
{
66
	int done = 0;
67
68
	do {
69
		while (fgets(buf, size, fp)) {
70
			int len = strlen(buf);
71
72
			done += len;
73
			if (len > 1 && buf[len-2] == '\\' &&
74
			    buf[len-1] == '\n') {
75
				int ch;
76
77
				buf += len - 2;
78
				size -= len - 2;
79
				*buf = '\n'; buf[1] = '\0';
80
81
				/*
82
				 * Skip leading white space on next line
83
				 */
84
				while ((ch = getc(fp)) != EOF &&
85
				    isascii(ch) && isspace(ch))
86
					;
87
				(void) ungetc(ch, fp);
88
			} else {
89
				return done;
90
			}
91
		}
92
	} while (size > 0 && !feof(fp));
93
94
	return done;
95
}
96
97
static int
98
hashidx(char key)
99
{
100
	if (key < 'A')
101
		return (0);
102
	if (key <= 'Z')
103
		return (1 + key - 'A');
104
	if (key < 'a')
105
		return (27);
106
	if (key <= 'z')
107
		return (28 + key - 'a');
108
	return (54);
109
}
110
111
static void
112
add_user(char *username, char *uid, char *gid)
113
{
114
	struct user *u;
115
	int idx;
116
117
	u = malloc(sizeof(struct user));
118
	if (u == NULL)
119
		err(1, "malloc");
120
	bzero(u, sizeof(struct user));
121
	u->usr_name = strdup(username);
122
	if (u->usr_name == NULL)
123
		err(1, "strdup");
124
	u->usr_uid = atoi(uid);
125
	u->usr_gid = atoi(gid);
126
	u->gid_count = -1;
127
	if (root == NULL) {
128
		root = tail = u;
129
	} else {
130
		u->prev = tail;
131
		tail->next = u;
132
		tail = u;
133
	}
134
	idx = hashidx(username[0]);
135
	if (hroot[idx] == NULL) {
136
		hroot[idx] = htail[idx] = u;
137
	} else {
138
		u->hprev = htail[idx];
139
		htail[idx]->hnext = u;
140
		htail[idx] = u;
141
	}
142
}
143
144
static void
145
add_group(char *username, char *gid)
146
{
147
	struct user *u;
148
	int idx, g;
149
150
	idx = hashidx(username[0]);
151
	u = hroot[idx];
152
	g = atoi(gid);
153
154
	while (u != NULL) {
155
		if (strcmp(username, u->usr_name) == 0) {
156
			if (g != u->usr_gid) {
157
				u->gid_count++;
158
				if (u->gid_count < NGROUPS_MAX)
159
					u->gid[u->gid_count] = atoi(gid);
160
			}
161
			u = htail[idx];
162
		}
163
		u = u->hnext;
164
	}
165
}
166
167
static void
168
read_passwd(FILE *pfile, char *fname)
169
{
170
	char  line[1024], *p, *k, *u, *g;
171
	int   line_no = 0, len, colon;
172
173
	while (read_line(pfile, line, sizeof(line))) {
174
		line_no++;
175
		len = strlen(line);
176
177
		if (len > 0) {
178
			if (line[0] == '#')
179
				continue;
180
		}
181
182
		/*
183
		 * Check if we have the whole line
184
		 */
185
		if (line[len-1] != '\n') {
186
			fprintf(stderr, "line %d in \"%s\" is too long\n",
187
			    line_no, fname);
188
		} else {
189
			line[len-1] = '\0';
190
		}
191
192
		p = (char *)&line;
193
194
		k = p; colon = 0;
195
		while (*k != '\0') {
196
			if (*k == ':')
197
				colon++;
198
			k++;
199
		}
200
201
		if (colon > 0) {
202
			k = p;			/* save start of key  */
203
			while (*p != ':')
204
				p++;		/* find first "colon" */
205
			if (*p==':')
206
				*p++ = '\0';	/* terminate key */
207
			if (strlen(k) == 1) {
208
				if (*k == '+')
209
					continue;
210
			}
211
		}
212
213
		if (colon < 4) {
214
			fprintf(stderr, "syntax error at line %d in \"%s\"\n",
215
			    line_no, fname);
216
			continue;
217
		}
218
219
		while (*p != ':')
220
			p++;			/* find second "colon" */
221
		if (*p==':')
222
			*p++ = '\0';		/* terminate passwd */
223
		u = p;
224
		while (*p != ':')
225
			p++;			/* find third "colon" */
226
		if (*p==':')
227
			*p++ = '\0';		/* terminate uid */
228
		g = p;
229
		while (*p != ':')
230
			p++;			/* find fourth "colon" */
231
		if (*p==':')
232
			*p++ = '\0';		/* terminate gid */
233
		while (*p != '\0')
234
			p++;	/* find end of string */
235
236
		add_user(k, u, g);
237
	}
238
}
239
240
static int
241
isgsep(char ch)
242
{
243
	switch (ch)  {
244
	case ',':
245
	case ' ':
246
	case '\t':
247
	case '\0':
248
		return (1);
249
	default:
250
		return (0);
251
	}
252
}
253
254
static void
255
read_group(FILE *gfile, char *fname)
256
{
257
	char  line[2048], *p, *k, *u, *g;
258
	int   line_no = 0, len, colon;
259
260
	while (read_line(gfile, line, sizeof(line))) {
261
		line_no++;
262
		len = strlen(line);
263
264
		if (len > 0) {
265
			if (line[0] == '#')
266
				continue;
267
		}
268
269
		/*
270
		 * Check if we have the whole line
271
		 */
272
		if (line[len-1] != '\n') {
273
			fprintf(stderr, "line %d in \"%s\" is too long\n",
274
			    line_no, fname);
275
		} else {
276
			line[len-1] = '\0';
277
		}
278
279
		p = (char *)&line;
280
281
		k = p; colon = 0;
282
		while (*k != '\0') {
283
			if (*k == ':')
284
				colon++;
285
			k++;
286
		}
287
288
		if (colon > 0) {
289
			k = p;			/* save start of key  */
290
			while (*p != ':')
291
				p++;		/* find first "colon" */
292
			if (*p==':')
293
				*p++ = '\0';	/* terminate key */
294
			if (strlen(k) == 1) {
295
				if (*k == '+')
296
					continue;
297
			}
298
		}
299
300
		if (colon < 3) {
301
			fprintf(stderr, "syntax error at line %d in \"%s\"\n",
302
			    line_no, fname);
303
			continue;
304
		}
305
306
		while (*p != ':')
307
			p++;			/* find second "colon" */
308
		if (*p==':')
309
			*p++ = '\0';		/* terminate passwd */
310
		g = p;
311
		while (*p != ':')
312
			p++;			/* find third "colon" */
313
		if (*p==':')
314
			*p++ = '\0';		/* terminate gid */
315
316
		u = p;
317
318
		while (*u != '\0') {
319
			while (!isgsep(*p))
320
				p++;		/* find separator */
321
			if (*p != '\0') {
322
				*p = '\0';
323
				if (u != p)
324
					add_group(u, g);
325
				p++;
326
			} else {
327
				if (u != p)
328
					add_group(u, g);
329
			}
330
			u = p;
331
		}
332
	}
333
}
334
335
static void
336
print_passwd_group(int qflag, char *domain)
337
{
338
	struct user *u, *p;
339
	int i;
340
341
	u = root;
342
343
	while (u != NULL) {
344
		p = root;
345
		while (p->usr_uid != u->usr_uid)
346
			p = p->next;
347
348
		if (p != u) {
349
			if (!qflag) {
350
				fprintf(stderr, "mknetid: unix.%d@%s %s\n",
351
				    u->usr_uid, domain,
352
				    "multiply defined, other definitions ignored");
353
			}
354
		} else {
355
			printf("unix.%d@%s %d:%d",
356
			    u->usr_uid, domain, u->usr_uid, u->usr_gid);
357
			if (u->gid_count >= 0) {
358
				i = 0;
359
				while (i <= u->gid_count) {
360
					printf(",%d", u->gid[i]);
361
					i++;
362
				}
363
			}
364
			printf("\n");
365
		}
366
		u = u->next;
367
	}
368
}
369
370
static void
371
print_hosts(FILE *pfile, char *fname, char *domain)
372
{
373
	char  line[1024], *p, *u;
374
	int   line_no = 0, len;
375
376
	while (read_line(pfile, line, sizeof(line))) {
377
		line_no++;
378
		len = strlen(line);
379
380
		if (len > 0) {
381
			if (line[0] == '#')
382
				continue;
383
		}
384
385
		/*
386
		 * Check if we have the whole line
387
		 */
388
		if (line[len-1] != '\n') {
389
			fprintf(stderr, "line %d in \"%s\" is too long\n",
390
			    line_no, fname);
391
		} else {
392
			line[len-1] = '\0';
393
		}
394
395
		p = (char *)&line;
396
397
		while (!isspace((unsigned char)*p))
398
			p++;			/* find first "space" */
399
		while (isspace((unsigned char)*p))
400
			*p++ = '\0';		/* replace space with <NUL> */
401
402
		u = p;
403
		while (p != NULL) {
404
			if (*p == '\0') {
405
				p = NULL;
406
			} else {
407
				if (!isspace((unsigned char)*p)) {
408
					p++;
409
				} else {
410
					*p = '\0';
411
					p = NULL;
412
				}
413
			}
414
		}
415
416
		printf("unix.%s@%s 0:%s\n", u, domain, u);
417
	}
418
}
419
420
static void
421
print_netid(FILE *mfile, char *fname)
422
{
423
	char  line[1024], *p, *k, *u;
424
	int   line_no = 0, len;
425
426
	while (read_line(mfile, line, sizeof(line))) {
427
		line_no++;
428
		len = strlen(line);
429
430
		if (len > 0) {
431
			if (line[0] == '#')
432
				continue;
433
		}
434
435
		/*
436
		 * Check if we have the whole line
437
		 */
438
		if (line[len-1] != '\n') {
439
			fprintf(stderr, "line %d in \"%s\" is too long\n",
440
			    line_no, fname);
441
		} else {
442
			line[len-1] = '\0';
443
		}
444
445
		p = (char *)&line;
446
447
		k = p;				/* save start of key  */
448
		while (!isspace((unsigned char)*p))
449
			p++;			/* find first "space" */
450
		while (isspace((unsigned char)*p))
451
			*p++ = '\0';		/* replace space with <NUL> */
452
453
		u = p;
454
		while (p != NULL) {
455
			if (*p == '\0') {
456
				p = NULL;
457
			} else {
458
				if (!isspace((unsigned char)*p)) {
459
					p++;
460
				} else {
461
					*p = '\0';
462
					p = NULL;
463
				}
464
			}
465
		}
466
467
		printf("%s %s\n", k, u);
468
	}
469
}
470
471
static void
472
usage(void)
473
{
474
	fprintf(stderr, "usage: mknetid [-q] [-d domain] [-g groupfile] "
475
	    "[-h hostfile] [-m netidfile]\n"
476
	    "               [-P master.passwdfile] [-p passwdfile]\n");
477
	exit(1);
478
}
479
480
int
481
main(int argc, char *argv[])
482
{
483
	FILE   *pfile, *gfile, *hfile, *mfile;
484
	int	qflag = 0, ch;
485
	char   *domain = NULL;
486
487
	while ((ch = getopt(argc, argv, "d:g:h:m:p:P:q")) != -1)
488
		switch (ch) {
489
		case 'd':
490
			domain = optarg;
491
			break;
492
		case 'g':
493
			GroupFile = optarg;
494
			break;
495
		case 'h':
496
			HostFile = optarg;
497
			break;
498
		case 'm':
499
			NetidFile = optarg;
500
			break;
501
		case 'p':
502
			PasswdFile = optarg;
503
			break;
504
		case 'P':
505
			MasterPasswdFile = optarg;
506
			break;
507
		case 'q':
508
			qflag = 1;
509
			break;
510
		default:
511
			usage();
512
			break;
513
		}
514
515
	if (argc > optind)
516
		usage();
517
518
	if (domain == NULL)
519
		yp_get_default_domain(&domain);
520
521
	pfile = fopen(PasswdFile, "r");
522
	if (pfile == NULL)
523
		pfile = fopen(MasterPasswdFile, "r");
524
	if (pfile == NULL)
525
		err(1, "%s", MasterPasswdFile);
526
527
	gfile = fopen(GroupFile, "r");
528
	if (gfile == NULL)
529
		err(1, "%s", GroupFile);
530
531
	hfile = fopen(HostFile, "r");
532
	if (hfile == NULL)
533
		err(1, "%s", HostFile);
534
535
	mfile = fopen(NetidFile, "r");
536
537
	read_passwd(pfile, PasswdFile);
538
	read_group(gfile, GroupFile);
539
540
	print_passwd_group(qflag, domain);
541
	print_hosts(hfile, HostFile, domain);
542
543
	if (mfile != NULL)
544
		print_netid(mfile, NetidFile);
545
546
	return 0;
547
}