GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/getent/getent.c Lines: 0 174 0.0 %
Date: 2016-12-06 Branches: 0 117 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: getent.c,v 1.14 2016/02/01 19:57:28 jca Exp $	*/
2
/*	$NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $	*/
3
4
/*-
5
 * Copyright (c) 2004 The NetBSD Foundation, Inc.
6
 * All rights reserved.
7
 *
8
 * This code is derived from software contributed to The NetBSD Foundation
9
 * by Luke Mewburn.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
36
#include <ctype.h>
37
#include <err.h>
38
#include <errno.h>
39
#include <grp.h>
40
#include <limits.h>
41
#include <netdb.h>
42
#include <pwd.h>
43
#include <stdio.h>
44
#include <stdarg.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include <unistd.h>
48
49
#include <net/if.h>
50
#include <netinet/in.h>		/* for INET6_ADDRSTRLEN */
51
#include <netinet/if_ether.h>
52
53
#include <arpa/inet.h>
54
#include <arpa/nameser.h>
55
56
#include <rpc/rpc.h>
57
58
static int	usage(void);
59
static int	ethers(int, char *[]);
60
static int	group(int, char *[]);
61
static int	hosts(int, char *[]);
62
static int	passwd(int, char *[]);
63
static int	protocols(int, char *[]);
64
static int	rpc(int, char *[]);
65
static int	services(int, char *[]);
66
static int	shells(int, char *[]);
67
extern char *__progname;
68
69
enum {
70
	RV_OK		= 0,
71
	RV_USAGE	= 1,
72
	RV_NOTFOUND	= 2,
73
	RV_NOENUM	= 3
74
};
75
76
static struct getentdb {
77
	const char	*name;
78
	int		(*fn)(int, char *[]);
79
	const char	*pledge;
80
} databases[] = {
81
	{	"ethers",	ethers,		"stdio rpath"	},
82
	{	"group",	group,		"stdio getpw"	},
83
	{	"hosts",	hosts,		"stdio dns"	},
84
	{	"passwd",	passwd,		"stdio getpw"	},
85
	{	"protocols",	protocols,	"stdio rpath"	},
86
	{	"rpc",		rpc,		"stdio rpath"	},
87
	{	"services",	services,	"stdio rpath"	},
88
	{	"shells",	shells,		"stdio rpath"	},
89
90
	{	NULL,		NULL,				},
91
};
92
93
int
94
main(int argc, char *argv[])
95
{
96
	struct getentdb	*curdb;
97
98
	if (pledge("stdio dns rpath getpw wpath cpath", NULL) == -1)
99
		err(1, "pledge");
100
101
	if (argc < 2)
102
		usage();
103
	for (curdb = databases; curdb->name != NULL; curdb++) {
104
		if (strcmp(curdb->name, argv[1]) == 0) {
105
			if (pledge(curdb->pledge, NULL) == -1)
106
				err(1, "pledge");
107
108
			exit(curdb->fn(argc, argv));
109
			break;
110
		}
111
	}
112
	fprintf(stderr, "%s: unknown database: %s\n", __progname, argv[1]);
113
	return RV_USAGE;
114
}
115
116
static int
117
usage(void)
118
{
119
	fprintf(stderr, "usage: %s database [key ...]\n", __progname);
120
	exit(RV_USAGE);
121
	/* NOTREACHED */
122
}
123
124
/*
125
 * printfmtstrings --
126
 *	vprintf(format, ...),
127
 *	then the aliases (beginning with prefix, separated by sep),
128
 *	then a newline
129
 */
130
static void
131
printfmtstrings(char *strings[], const char *prefix, const char *sep,
132
	const char *fmt, ...)
133
{
134
	va_list		ap;
135
	const char	*curpref;
136
	int		i;
137
138
	va_start(ap, fmt);
139
	vprintf(fmt, ap);
140
	va_end(ap);
141
142
	curpref = prefix;
143
	for (i = 0; strings[i] != NULL; i++) {
144
		printf("%s%s", curpref, strings[i]);
145
		curpref = sep;
146
	}
147
	printf("\n");
148
}
149
150
#define ETHERSPRINT	printf("%-17s  %s\n", ether_ntoa(eap), hp)
151
152
static int
153
ethers(int argc, char *argv[])
154
{
155
	char		hostname[HOST_NAME_MAX+1], *hp;
156
	int		i, rv = RV_OK;
157
	struct ether_addr ea, *eap;
158
159
	if (argc == 2) {
160
		fprintf(stderr, "%s: Enumeration not supported on ethers\n",
161
		    __progname);
162
		rv = RV_NOENUM;
163
	} else {
164
		for (i = 2; i < argc; i++) {
165
			if ((eap = ether_aton(argv[i])) == NULL) {
166
				eap = &ea;
167
				hp = argv[i];
168
				if (ether_hostton(hp, eap) != 0) {
169
					rv = RV_NOTFOUND;
170
					break;
171
				}
172
			} else {
173
				hp = hostname;
174
				if (ether_ntohost(hp, eap) != 0) {
175
					rv = RV_NOTFOUND;
176
					break;
177
				}
178
			}
179
			ETHERSPRINT;
180
		}
181
	}
182
	return rv;
183
}
184
185
#define GROUPPRINT	\
186
	printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \
187
	    gr->gr_name, gr->gr_passwd, gr->gr_gid)
188
189
static int
190
group(int argc, char *argv[])
191
{
192
	int		i, rv = RV_OK;
193
	struct group	*gr;
194
195
	setgroupent(1);
196
	if (argc == 2) {
197
		while ((gr = getgrent()) != NULL)
198
			GROUPPRINT;
199
	} else {
200
		for (i = 2; i < argc; i++) {
201
			const char	*err;
202
			long long id = strtonum(argv[i], 0, UINT_MAX, &err);
203
204
			if (!err)
205
				gr = getgrgid((gid_t)id);
206
			else
207
				gr = getgrnam(argv[i]);
208
			if (gr != NULL)
209
				GROUPPRINT;
210
			else {
211
				rv = RV_NOTFOUND;
212
				break;
213
			}
214
		}
215
	}
216
	endgrent();
217
	return rv;
218
}
219
220
static void
221
hostsprint(const struct hostent *he)
222
{
223
	char	buf[INET6_ADDRSTRLEN];
224
225
	if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
226
		strlcpy(buf, "# unknown", sizeof(buf));
227
	printfmtstrings(he->h_aliases, "  ", " ", "%-16s  %s", buf, he->h_name);
228
}
229
static int
230
hostsaddrinfo(char* name)
231
{
232
	struct addrinfo	 hints, *res, *res0;
233
	void		*src;
234
	int		 rv;
235
	char		 buf[INET6_ADDRSTRLEN];
236
237
	rv = RV_NOTFOUND;
238
	memset(buf, 0, sizeof(buf));
239
	memset(&hints, 0, sizeof(hints));
240
	hints.ai_family = PF_UNSPEC;
241
	hints.ai_socktype = SOCK_DGRAM;
242
243
	if (getaddrinfo(name, NULL, &hints, &res0) == 0) {
244
		for (res = res0; res; res = res->ai_next) {
245
			switch (res->ai_family) {
246
			case AF_INET:
247
				src = &((struct sockaddr_in*)
248
				    res->ai_addr)->sin_addr;
249
				break;
250
			case AF_INET6:
251
				src = &((struct sockaddr_in6*)
252
				    res->ai_addr)->sin6_addr;
253
				break;
254
			default: /* not reached */
255
				src = NULL;
256
			}
257
			if (src==NULL || inet_ntop(res->ai_family, src, buf,
258
			    sizeof(buf)) == NULL)
259
				strlcpy(buf, "# unknown", sizeof(buf));
260
			else
261
				rv = RV_OK;
262
			printf("%-39s %s\n", buf, name);
263
		}
264
		freeaddrinfo(res0);
265
	}
266
267
	return (rv);
268
}
269
270
static int
271
hosts(int argc, char *argv[])
272
{
273
	char		addr[IN6ADDRSZ];
274
	int		i, rv = RV_OK;
275
	struct hostent	*he;
276
277
	if (argc == 2) {
278
		fprintf(stderr, "%s: Enumeration not supported on hosts\n",
279
		    __progname);
280
		rv = RV_NOENUM;
281
	} else {
282
		for (i = 2; i < argc; i++) {
283
			he = NULL;
284
			if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
285
				he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
286
			else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
287
				he = gethostbyaddr(addr, INADDRSZ, AF_INET);
288
			if (he != NULL)
289
				hostsprint(he);
290
			else if ((rv = hostsaddrinfo(argv[i])) == RV_NOTFOUND)
291
				break;
292
		}
293
	}
294
	return rv;
295
}
296
297
#define PASSWDPRINT	\
298
	printf("%s:%s:%u:%u:%s:%s:%s\n", \
299
	    pw->pw_name, pw->pw_passwd, pw->pw_uid, \
300
	    pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
301
302
static int
303
passwd(int argc, char *argv[])
304
{
305
	int		i, rv = RV_OK;
306
	struct passwd	*pw;
307
308
	setpassent(1);
309
	if (argc == 2) {
310
		while ((pw = getpwent()) != NULL)
311
			PASSWDPRINT;
312
	} else {
313
		for (i = 2; i < argc; i++) {
314
			const char	*err;
315
			long long id = strtonum(argv[i], 0, UINT_MAX, &err);
316
317
			if (!err)
318
				pw = getpwuid((uid_t)id);
319
			else
320
				pw = getpwnam(argv[i]);
321
			if (pw != NULL)
322
				PASSWDPRINT;
323
			else {
324
				rv = RV_NOTFOUND;
325
				break;
326
			}
327
		}
328
	}
329
	endpwent();
330
	return rv;
331
}
332
333
#define PROTOCOLSPRINT	\
334
	printfmtstrings(pe->p_aliases, "  ", " ", \
335
	    "%-16s  %5d", pe->p_name, pe->p_proto)
336
337
static int
338
protocols(int argc, char *argv[])
339
{
340
	struct protoent	*pe;
341
	int		i, rv = RV_OK;
342
343
	setprotoent(1);
344
	if (argc == 2) {
345
		while ((pe = getprotoent()) != NULL)
346
			PROTOCOLSPRINT;
347
	} else {
348
		for (i = 2; i < argc; i++) {
349
			const char	*err;
350
			long long id = strtonum(argv[i], 0, UINT_MAX, &err);
351
352
			if (!err)
353
				pe = getprotobynumber((int)id);
354
			else
355
				pe = getprotobyname(argv[i]);
356
			if (pe != NULL)
357
				PROTOCOLSPRINT;
358
			else {
359
				rv = RV_NOTFOUND;
360
				break;
361
			}
362
		}
363
	}
364
	endprotoent();
365
	return rv;
366
}
367
368
#define RPCPRINT	\
369
	printfmtstrings(re->r_aliases, "  ", " ", \
370
	    "%-16s  %6d", re->r_name, re->r_number)
371
372
static int
373
rpc(int argc, char *argv[])
374
{
375
	struct rpcent	*re;
376
	int		i, rv = RV_OK;
377
378
	setrpcent(1);
379
	if (argc == 2) {
380
		while ((re = getrpcent()) != NULL)
381
			RPCPRINT;
382
	} else {
383
		for (i = 2; i < argc; i++) {
384
			const char	*err;
385
			long long id = strtonum(argv[i], 0, UINT_MAX, &err);
386
387
			if (!err)
388
				re = getrpcbynumber((int)id);
389
			else
390
				re = getrpcbyname(argv[i]);
391
			if (re != NULL)
392
				RPCPRINT;
393
			else {
394
				rv = RV_NOTFOUND;
395
				break;
396
			}
397
		}
398
	}
399
	endrpcent();
400
	return rv;
401
}
402
403
#define SERVICESPRINT	\
404
	printfmtstrings(se->s_aliases, "  ", " ", \
405
	    "%-16s  %5d/%s", se->s_name, ntohs(se->s_port), se->s_proto)
406
407
static int
408
services(int argc, char *argv[])
409
{
410
	struct servent	*se;
411
	int		i, rv = RV_OK;
412
413
	setservent(1);
414
	if (argc == 2) {
415
		while ((se = getservent()) != NULL)
416
			SERVICESPRINT;
417
	} else {
418
		for (i = 2; i < argc; i++) {
419
			const char	*err;
420
			long long	id;
421
			char *proto = strchr(argv[i], '/');
422
423
			if (proto != NULL)
424
				*proto++ = '\0';
425
			id = strtonum(argv[i], 0, UINT_MAX, &err);
426
			if (!err)
427
				se = getservbyport(htons((u_short)id), proto);
428
			else
429
				se = getservbyname(argv[i], proto);
430
			if (se != NULL)
431
				SERVICESPRINT;
432
			else {
433
				rv = RV_NOTFOUND;
434
				break;
435
			}
436
		}
437
	}
438
	endservent();
439
	return rv;
440
}
441
442
#define SHELLSPRINT	printf("%s\n", sh)
443
444
static int
445
shells(int argc, char *argv[])
446
{
447
	const char	*sh;
448
	int		i, rv = RV_OK;
449
450
	setusershell();
451
	if (argc == 2) {
452
		while ((sh = getusershell()) != NULL)
453
			SHELLSPRINT;
454
	} else {
455
		for (i = 2; i < argc; i++) {
456
			setusershell();
457
			while ((sh = getusershell()) != NULL) {
458
				if (strcmp(sh, argv[i]) == 0) {
459
					SHELLSPRINT;
460
					break;
461
				}
462
			}
463
			if (sh == NULL) {
464
				rv = RV_NOTFOUND;
465
				break;
466
			}
467
		}
468
	}
469
	endusershell();
470
	return rv;
471
}