xref: /freebsd/usr.bin/id/id.c (revision aa0a1e58)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #ifndef lint
31 static const char copyright[] =
32 "@(#) Copyright (c) 1991, 1993\n\
33 	The Regents of the University of California.  All rights reserved.\n";
34 #endif /* not lint */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)id.c	8.2 (Berkeley) 2/16/94";
39 #endif
40 #endif /* not lint */
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43 
44 #include <sys/param.h>
45 #include <sys/mac.h>
46 
47 #ifdef USE_BSM_AUDIT
48 #include <bsm/audit.h>
49 #endif
50 
51 #include <err.h>
52 #include <errno.h>
53 #include <grp.h>
54 #include <pwd.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59 
60 void	id_print(struct passwd *, int, int, int);
61 void	pline(struct passwd *);
62 void	pretty(struct passwd *);
63 void	auditid(void);
64 void	group(struct passwd *, int);
65 void	maclabel(void);
66 void	usage(void);
67 struct passwd *who(char *);
68 
69 int isgroups, iswhoami;
70 
71 int
72 main(int argc, char *argv[])
73 {
74 	struct group *gr;
75 	struct passwd *pw;
76 	int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
77 	int Aflag, cflag;
78 	int error;
79 	const char *myname;
80 	char loginclass[MAXLOGNAME];
81 
82 	Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
83 	Aflag = cflag = 0;
84 
85 	myname = strrchr(argv[0], '/');
86 	myname = (myname != NULL) ? myname + 1 : argv[0];
87 	if (strcmp(myname, "groups") == 0) {
88 		isgroups = 1;
89 		Gflag = nflag = 1;
90 	}
91 	else if (strcmp(myname, "whoami") == 0) {
92 		iswhoami = 1;
93 		uflag = nflag = 1;
94 	}
95 
96 	while ((ch = getopt(argc, argv,
97 	    (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
98 		switch(ch) {
99 #ifdef USE_BSM_AUDIT
100 		case 'A':
101 			Aflag = 1;
102 			break;
103 #endif
104 		case 'G':
105 			Gflag = 1;
106 			break;
107 		case 'M':
108 			Mflag = 1;
109 			break;
110 		case 'P':
111 			Pflag = 1;
112 			break;
113 		case 'a':
114 			break;
115 		case 'c':
116 			cflag = 1;
117 			break;
118 		case 'g':
119 			gflag = 1;
120 			break;
121 		case 'n':
122 			nflag = 1;
123 			break;
124 		case 'p':
125 			pflag = 1;
126 			break;
127 		case 'r':
128 			rflag = 1;
129 			break;
130 		case 'u':
131 			uflag = 1;
132 			break;
133 		case '?':
134 		default:
135 			usage();
136 		}
137 	argc -= optind;
138 	argv += optind;
139 
140 	if (iswhoami && argc > 0)
141 		usage();
142 
143 	switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
144 	case 1:
145 		break;
146 	case 0:
147 		if (!nflag && !rflag)
148 			break;
149 		/* FALLTHROUGH */
150 	default:
151 		usage();
152 	}
153 
154 	pw = *argv ? who(*argv) : NULL;
155 
156 	if (Mflag && pw != NULL)
157 		usage();
158 
159 #ifdef USE_BSM_AUDIT
160 	if (Aflag) {
161 		auditid();
162 		exit(0);
163 	}
164 #endif
165 
166 	if (cflag) {
167 		error = getloginclass(loginclass, sizeof(loginclass));
168 		if (error != 0)
169 			err(1, "loginclass");
170 		(void)printf("%s\n", loginclass);
171 		exit(0);
172 	}
173 
174 	if (gflag) {
175 		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
176 		if (nflag && (gr = getgrgid(id)))
177 			(void)printf("%s\n", gr->gr_name);
178 		else
179 			(void)printf("%u\n", id);
180 		exit(0);
181 	}
182 
183 	if (uflag) {
184 		id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
185 		if (nflag && (pw = getpwuid(id)))
186 			(void)printf("%s\n", pw->pw_name);
187 		else
188 			(void)printf("%u\n", id);
189 		exit(0);
190 	}
191 
192 	if (Gflag) {
193 		group(pw, nflag);
194 		exit(0);
195 	}
196 
197 	if (Mflag) {
198 		maclabel();
199 		exit(0);
200 	}
201 
202 	if (Pflag) {
203 		pline(pw);
204 		exit(0);
205 	}
206 
207 	if (pflag) {
208 		pretty(pw);
209 		exit(0);
210 	}
211 
212 	if (pw) {
213 		id_print(pw, 1, 0, 0);
214 	}
215 	else {
216 		id = getuid();
217 		pw = getpwuid(id);
218 		id_print(pw, 0, 1, 1);
219 	}
220 	exit(0);
221 }
222 
223 void
224 pretty(struct passwd *pw)
225 {
226 	struct group *gr;
227 	u_int eid, rid;
228 	char *login;
229 
230 	if (pw) {
231 		(void)printf("uid\t%s\n", pw->pw_name);
232 		(void)printf("groups\t");
233 		group(pw, 1);
234 	} else {
235 		if ((login = getlogin()) == NULL)
236 			err(1, "getlogin");
237 
238 		pw = getpwuid(rid = getuid());
239 		if (pw == NULL || strcmp(login, pw->pw_name))
240 			(void)printf("login\t%s\n", login);
241 		if (pw)
242 			(void)printf("uid\t%s\n", pw->pw_name);
243 		else
244 			(void)printf("uid\t%u\n", rid);
245 
246 		if ((eid = geteuid()) != rid) {
247 			if ((pw = getpwuid(eid)))
248 				(void)printf("euid\t%s\n", pw->pw_name);
249 			else
250 				(void)printf("euid\t%u\n", eid);
251 		}
252 		if ((rid = getgid()) != (eid = getegid())) {
253 			if ((gr = getgrgid(rid)))
254 				(void)printf("rgid\t%s\n", gr->gr_name);
255 			else
256 				(void)printf("rgid\t%u\n", rid);
257 		}
258 		(void)printf("groups\t");
259 		group(NULL, 1);
260 	}
261 }
262 
263 void
264 id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
265 {
266 	struct group *gr;
267 	gid_t gid, egid, lastgid;
268 	uid_t uid, euid;
269 	int cnt, ngroups;
270 	long ngroups_max;
271 	gid_t *groups;
272 	const char *fmt;
273 
274 	if (pw != NULL) {
275 		uid = pw->pw_uid;
276 		gid = pw->pw_gid;
277 	}
278 	else {
279 		uid = getuid();
280 		gid = getgid();
281 	}
282 
283 	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
284 	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
285 		err(1, "malloc");
286 
287 	if (use_ggl && pw != NULL) {
288 		ngroups = ngroups_max;
289 		getgrouplist(pw->pw_name, gid, groups, &ngroups);
290 	}
291 	else {
292 		ngroups = getgroups(ngroups_max, groups);
293 	}
294 
295 	if (pw != NULL)
296 		printf("uid=%u(%s)", uid, pw->pw_name);
297 	else
298 		printf("uid=%u", getuid());
299 	printf(" gid=%u", gid);
300 	if ((gr = getgrgid(gid)))
301 		(void)printf("(%s)", gr->gr_name);
302 	if (p_euid && (euid = geteuid()) != uid) {
303 		(void)printf(" euid=%u", euid);
304 		if ((pw = getpwuid(euid)))
305 			(void)printf("(%s)", pw->pw_name);
306 	}
307 	if (p_egid && (egid = getegid()) != gid) {
308 		(void)printf(" egid=%u", egid);
309 		if ((gr = getgrgid(egid)))
310 			(void)printf("(%s)", gr->gr_name);
311 	}
312 	fmt = " groups=%u";
313 	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
314 		if (lastgid == (gid = groups[cnt]))
315 			continue;
316 		printf(fmt, gid);
317 		fmt = ",%u";
318 		if ((gr = getgrgid(gid)))
319 			printf("(%s)", gr->gr_name);
320 		lastgid = gid;
321 	}
322 	printf("\n");
323 	free(groups);
324 }
325 
326 #ifdef USE_BSM_AUDIT
327 void
328 auditid(void)
329 {
330 	auditinfo_t auditinfo;
331 	auditinfo_addr_t ainfo_addr;
332 	int ret, extended;
333 
334 	extended = 0;
335 	ret = getaudit(&auditinfo);
336 	if (ret < 0 && errno == E2BIG) {
337 		if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0)
338 			err(1, "getaudit_addr");
339 		extended = 1;
340 	} else if (ret < 0)
341 		err(1, "getaudit");
342 	if (extended != 0) {
343 		(void) printf("auid=%d\n"
344 		    "mask.success=0x%08x\n"
345 		    "mask.failure=0x%08x\n"
346 		    "asid=%d\n"
347 		    "termid_addr.port=0x%08x\n"
348 		    "termid_addr.addr[0]=0x%08x\n"
349 		    "termid_addr.addr[1]=0x%08x\n"
350 		    "termid_addr.addr[2]=0x%08x\n"
351 		    "termid_addr.addr[3]=0x%08x\n",
352 			ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success,
353 			ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid,
354 			ainfo_addr.ai_termid.at_port,
355 			ainfo_addr.ai_termid.at_addr[0],
356 			ainfo_addr.ai_termid.at_addr[1],
357 			ainfo_addr.ai_termid.at_addr[2],
358 			ainfo_addr.ai_termid.at_addr[3]);
359 	} else {
360 		(void) printf("auid=%d\n"
361 		    "mask.success=0x%08x\n"
362 		    "mask.failure=0x%08x\n"
363 		    "asid=%d\n"
364 		    "termid.port=0x%08x\n"
365 		    "termid.machine=0x%08x\n",
366 			auditinfo.ai_auid, auditinfo.ai_mask.am_success,
367 			auditinfo.ai_mask.am_failure,
368 			auditinfo.ai_asid, auditinfo.ai_termid.port,
369 			auditinfo.ai_termid.machine);
370 	}
371 }
372 #endif
373 
374 void
375 group(struct passwd *pw, int nflag)
376 {
377 	struct group *gr;
378 	int cnt, id, lastid, ngroups;
379 	long ngroups_max;
380 	gid_t *groups;
381 	const char *fmt;
382 
383 	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
384 	if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL)
385 		err(1, "malloc");
386 
387 	if (pw) {
388 		ngroups = ngroups_max;
389 		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
390 	} else {
391 		ngroups = getgroups(ngroups_max, groups);
392 	}
393 	fmt = nflag ? "%s" : "%u";
394 	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
395 		if (lastid == (id = groups[cnt]))
396 			continue;
397 		if (nflag) {
398 			if ((gr = getgrgid(id)))
399 				(void)printf(fmt, gr->gr_name);
400 			else
401 				(void)printf(*fmt == ' ' ? " %u" : "%u",
402 				    id);
403 			fmt = " %s";
404 		} else {
405 			(void)printf(fmt, id);
406 			fmt = " %u";
407 		}
408 		lastid = id;
409 	}
410 	(void)printf("\n");
411 	free(groups);
412 }
413 
414 void
415 maclabel(void)
416 {
417 	char *string;
418 	mac_t label;
419 	int error;
420 
421 	error = mac_prepare_process_label(&label);
422 	if (error == -1)
423 		errx(1, "mac_prepare_type: %s", strerror(errno));
424 
425 	error = mac_get_proc(label);
426 	if (error == -1)
427 		errx(1, "mac_get_proc: %s", strerror(errno));
428 
429 	error = mac_to_text(label, &string);
430 	if (error == -1)
431 		errx(1, "mac_to_text: %s", strerror(errno));
432 
433 	(void)printf("%s\n", string);
434 	mac_free(label);
435 	free(string);
436 }
437 
438 struct passwd *
439 who(char *u)
440 {
441 	struct passwd *pw;
442 	long id;
443 	char *ep;
444 
445 	/*
446 	 * Translate user argument into a pw pointer.  First, try to
447 	 * get it as specified.  If that fails, try it as a number.
448 	 */
449 	if ((pw = getpwnam(u)))
450 		return(pw);
451 	id = strtol(u, &ep, 10);
452 	if (*u && !*ep && (pw = getpwuid(id)))
453 		return(pw);
454 	errx(1, "%s: no such user", u);
455 	/* NOTREACHED */
456 }
457 
458 void
459 pline(struct passwd *pw)
460 {
461 
462 	if (!pw) {
463 		if ((pw = getpwuid(getuid())) == NULL)
464 			err(1, "getpwuid");
465 	}
466 
467 	(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
468 			pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
469 			(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
470 			pw->pw_dir, pw->pw_shell);
471 }
472 
473 
474 void
475 usage(void)
476 {
477 
478 	if (isgroups)
479 		(void)fprintf(stderr, "usage: groups [user]\n");
480 	else if (iswhoami)
481 		(void)fprintf(stderr, "usage: whoami\n");
482 	else
483 		(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
484 		    "usage: id [user]",
485 #ifdef USE_BSM_AUDIT
486 		    "       id -A\n",
487 #else
488 		    "",
489 #endif
490 		    "       id -G [-n] [user]",
491 		    "       id -M",
492 		    "       id -P [user]",
493 		    "       id -c",
494 		    "       id -g [-nr] [user]",
495 		    "       id -p [user]",
496 		    "       id -u [-nr] [user]");
497 	exit(1);
498 }
499