11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1991, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3127418Scharnierstatic const char copyright[] =
321590Srgrimes"@(#) Copyright (c) 1991, 1993\n\
331590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
341590Srgrimes#endif /* not lint */
351590Srgrimes
361590Srgrimes#ifndef lint
3727418Scharnier#if 0
381590Srgrimesstatic char sccsid[] = "@(#)id.c	8.2 (Berkeley) 2/16/94";
3927418Scharnier#endif
401590Srgrimes#endif /* not lint */
4199112Sobrien#include <sys/cdefs.h>
4299112Sobrien__FBSDID("$FreeBSD$");
431590Srgrimes
441590Srgrimes#include <sys/param.h>
45128900Srwatson#include <sys/mac.h>
461590Srgrimes
47162571Srwatson#ifdef USE_BSM_AUDIT
48162571Srwatson#include <bsm/audit.h>
49162571Srwatson#endif
50162571Srwatson
5127418Scharnier#include <err.h>
52128900Srwatson#include <errno.h>
531590Srgrimes#include <grp.h>
541590Srgrimes#include <pwd.h>
55275855Sgleb#include <stdint.h>
561590Srgrimes#include <stdio.h>
571590Srgrimes#include <stdlib.h>
581590Srgrimes#include <string.h>
591590Srgrimes#include <unistd.h>
601590Srgrimes
61227166Sedstatic void	id_print(struct passwd *, int, int, int);
62227166Sedstatic void	pline(struct passwd *);
63227166Sedstatic void	pretty(struct passwd *);
64227203Sed#ifdef USE_BSM_AUDIT
65227166Sedstatic void	auditid(void);
66227203Sed#endif
67227166Sedstatic void	group(struct passwd *, int);
68227166Sedstatic void	maclabel(void);
69227166Sedstatic void	usage(void);
70227166Sedstatic struct passwd *who(char *);
711590Srgrimes
72227166Sedstatic int isgroups, iswhoami;
7383452Sru
741590Srgrimesint
75102944Sdwmalonemain(int argc, char *argv[])
761590Srgrimes{
771590Srgrimes	struct group *gr;
781590Srgrimes	struct passwd *pw;
79128900Srwatson	int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
80219304Strasz	int Aflag, cflag;
81219304Strasz	int error;
8283452Sru	const char *myname;
83219304Strasz	char loginclass[MAXLOGNAME];
841590Srgrimes
85128900Srwatson	Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
86219304Strasz	Aflag = cflag = 0;
8783452Sru
8883452Sru	myname = strrchr(argv[0], '/');
8983452Sru	myname = (myname != NULL) ? myname + 1 : argv[0];
9083452Sru	if (strcmp(myname, "groups") == 0) {
9183452Sru		isgroups = 1;
9283452Sru		Gflag = nflag = 1;
9383452Sru	}
9483452Sru	else if (strcmp(myname, "whoami") == 0) {
9583452Sru		iswhoami = 1;
9683452Sru		uflag = nflag = 1;
9783452Sru	}
9883452Sru
9983452Sru	while ((ch = getopt(argc, argv,
100219304Strasz	    (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
1011590Srgrimes		switch(ch) {
102162578Srwatson#ifdef USE_BSM_AUDIT
103162578Srwatson		case 'A':
104162578Srwatson			Aflag = 1;
105162578Srwatson			break;
106162578Srwatson#endif
1071590Srgrimes		case 'G':
1081590Srgrimes			Gflag = 1;
1091590Srgrimes			break;
110128900Srwatson		case 'M':
111128900Srwatson			Mflag = 1;
112128900Srwatson			break;
11338468Sobrien		case 'P':
11438468Sobrien			Pflag = 1;
11538468Sobrien			break;
116162672Sceri		case 'a':
117162672Sceri			break;
118219304Strasz		case 'c':
119219304Strasz			cflag = 1;
120219304Strasz			break;
1211590Srgrimes		case 'g':
1221590Srgrimes			gflag = 1;
1231590Srgrimes			break;
1241590Srgrimes		case 'n':
1251590Srgrimes			nflag = 1;
1261590Srgrimes			break;
1271590Srgrimes		case 'p':
1281590Srgrimes			pflag = 1;
1291590Srgrimes			break;
1301590Srgrimes		case 'r':
1311590Srgrimes			rflag = 1;
1321590Srgrimes			break;
1331590Srgrimes		case 'u':
1341590Srgrimes			uflag = 1;
1351590Srgrimes			break;
1361590Srgrimes		case '?':
1371590Srgrimes		default:
1381590Srgrimes			usage();
1391590Srgrimes		}
1401590Srgrimes	argc -= optind;
1411590Srgrimes	argv += optind;
1421590Srgrimes
14383452Sru	if (iswhoami && argc > 0)
14483452Sru		usage();
14583452Sru
146162578Srwatson	switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
1471590Srgrimes	case 1:
1481590Srgrimes		break;
1491590Srgrimes	case 0:
1501590Srgrimes		if (!nflag && !rflag)
1511590Srgrimes			break;
1521590Srgrimes		/* FALLTHROUGH */
1531590Srgrimes	default:
1541590Srgrimes		usage();
1551590Srgrimes	}
1561590Srgrimes
1571590Srgrimes	pw = *argv ? who(*argv) : NULL;
1581590Srgrimes
159128900Srwatson	if (Mflag && pw != NULL)
160128900Srwatson		usage();
161128900Srwatson
162162571Srwatson#ifdef USE_BSM_AUDIT
163162578Srwatson	if (Aflag) {
164162571Srwatson		auditid();
165162571Srwatson		exit(0);
166162571Srwatson	}
167162571Srwatson#endif
168162571Srwatson
169219304Strasz	if (cflag) {
170219304Strasz		error = getloginclass(loginclass, sizeof(loginclass));
171219304Strasz		if (error != 0)
172219304Strasz			err(1, "loginclass");
173219304Strasz		(void)printf("%s\n", loginclass);
174219304Strasz		exit(0);
175219304Strasz	}
176219304Strasz
1771590Srgrimes	if (gflag) {
1781590Srgrimes		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
1791590Srgrimes		if (nflag && (gr = getgrgid(id)))
1801590Srgrimes			(void)printf("%s\n", gr->gr_name);
1811590Srgrimes		else
1821590Srgrimes			(void)printf("%u\n", id);
1831590Srgrimes		exit(0);
1841590Srgrimes	}
1851590Srgrimes
1861590Srgrimes	if (uflag) {
1871590Srgrimes		id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
1881590Srgrimes		if (nflag && (pw = getpwuid(id)))
1891590Srgrimes			(void)printf("%s\n", pw->pw_name);
1901590Srgrimes		else
1911590Srgrimes			(void)printf("%u\n", id);
1921590Srgrimes		exit(0);
1931590Srgrimes	}
1941590Srgrimes
1951590Srgrimes	if (Gflag) {
1961590Srgrimes		group(pw, nflag);
1971590Srgrimes		exit(0);
1981590Srgrimes	}
1991590Srgrimes
200128900Srwatson	if (Mflag) {
201128900Srwatson		maclabel();
202128900Srwatson		exit(0);
203128900Srwatson	}
204128900Srwatson
20538468Sobrien	if (Pflag) {
20638468Sobrien		pline(pw);
20738468Sobrien		exit(0);
20838468Sobrien	}
20938468Sobrien
2101590Srgrimes	if (pflag) {
2111590Srgrimes		pretty(pw);
2121590Srgrimes		exit(0);
2131590Srgrimes	}
2141590Srgrimes
215145628Srobert	if (pw) {
216145672Srobert		id_print(pw, 1, 0, 0);
217145628Srobert	}
218145628Srobert	else {
219145628Srobert		id = getuid();
220165028Smpp		pw = getpwuid(id);
221165028Smpp		id_print(pw, 0, 1, 1);
222145628Srobert	}
2231590Srgrimes	exit(0);
2241590Srgrimes}
2251590Srgrimes
226227166Sedstatic void
227102944Sdwmalonepretty(struct passwd *pw)
2281590Srgrimes{
2291590Srgrimes	struct group *gr;
2301590Srgrimes	u_int eid, rid;
2311590Srgrimes	char *login;
2321590Srgrimes
2331590Srgrimes	if (pw) {
2341590Srgrimes		(void)printf("uid\t%s\n", pw->pw_name);
2351590Srgrimes		(void)printf("groups\t");
2361590Srgrimes		group(pw, 1);
2371590Srgrimes	} else {
2381590Srgrimes		if ((login = getlogin()) == NULL)
23927418Scharnier			err(1, "getlogin");
2401590Srgrimes
2411590Srgrimes		pw = getpwuid(rid = getuid());
2421590Srgrimes		if (pw == NULL || strcmp(login, pw->pw_name))
2431590Srgrimes			(void)printf("login\t%s\n", login);
2441590Srgrimes		if (pw)
2451590Srgrimes			(void)printf("uid\t%s\n", pw->pw_name);
2461590Srgrimes		else
2471590Srgrimes			(void)printf("uid\t%u\n", rid);
2488874Srgrimes
24948566Sbillf		if ((eid = geteuid()) != rid) {
25027418Scharnier			if ((pw = getpwuid(eid)))
25133576Ssteve				(void)printf("euid\t%s\n", pw->pw_name);
2521590Srgrimes			else
25333576Ssteve				(void)printf("euid\t%u\n", eid);
25448566Sbillf		}
25548566Sbillf		if ((rid = getgid()) != (eid = getegid())) {
25627418Scharnier			if ((gr = getgrgid(rid)))
2571590Srgrimes				(void)printf("rgid\t%s\n", gr->gr_name);
2581590Srgrimes			else
2591590Srgrimes				(void)printf("rgid\t%u\n", rid);
26048566Sbillf		}
2611590Srgrimes		(void)printf("groups\t");
2621590Srgrimes		group(NULL, 1);
2631590Srgrimes	}
2641590Srgrimes}
2651590Srgrimes
266227166Sedstatic void
267145672Srobertid_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
2681590Srgrimes{
2691590Srgrimes	struct group *gr;
270145628Srobert	gid_t gid, egid, lastgid;
271145628Srobert	uid_t uid, euid;
272145628Srobert	int cnt, ngroups;
273194494Sbrooks	long ngroups_max;
274194494Sbrooks	gid_t *groups;
27577314Sdd	const char *fmt;
2761590Srgrimes
277165028Smpp	if (pw != NULL) {
278165028Smpp		uid = pw->pw_uid;
279165028Smpp		gid = pw->pw_gid;
280165028Smpp	}
281165028Smpp	else {
282165028Smpp		uid = getuid();
283165028Smpp		gid = getgid();
284165028Smpp	}
285145628Srobert
286194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
287194494Sbrooks	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
288194494Sbrooks		err(1, "malloc");
289194494Sbrooks
290165028Smpp	if (use_ggl && pw != NULL) {
291194494Sbrooks		ngroups = ngroups_max;
292145672Srobert		getgrouplist(pw->pw_name, gid, groups, &ngroups);
293145672Srobert	}
294145672Srobert	else {
295194494Sbrooks		ngroups = getgroups(ngroups_max, groups);
296145672Srobert	}
297145628Srobert
298165028Smpp	if (pw != NULL)
299165028Smpp		printf("uid=%u(%s)", uid, pw->pw_name);
300165028Smpp	else
301165028Smpp		printf("uid=%u", getuid());
302159008Sstefanf	printf(" gid=%u", gid);
303159008Sstefanf	if ((gr = getgrgid(gid)))
304159008Sstefanf		(void)printf("(%s)", gr->gr_name);
305145628Srobert	if (p_euid && (euid = geteuid()) != uid) {
306145628Srobert		(void)printf(" euid=%u", euid);
307145628Srobert		if ((pw = getpwuid(euid)))
3081590Srgrimes			(void)printf("(%s)", pw->pw_name);
3091590Srgrimes	}
310145628Srobert	if (p_egid && (egid = getegid()) != gid) {
311145628Srobert		(void)printf(" egid=%u", egid);
312145628Srobert		if ((gr = getgrgid(egid)))
3131590Srgrimes			(void)printf("(%s)", gr->gr_name);
3141590Srgrimes	}
3151590Srgrimes	fmt = " groups=%u";
31610359Sdg	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
31710359Sdg		if (lastgid == (gid = groups[cnt]))
3181590Srgrimes			continue;
319145628Srobert		printf(fmt, gid);
320165626Sstefanf		fmt = ",%u";
32127418Scharnier		if ((gr = getgrgid(gid)))
322145628Srobert			printf("(%s)", gr->gr_name);
32310359Sdg		lastgid = gid;
3241590Srgrimes	}
325145628Srobert	printf("\n");
326194494Sbrooks	free(groups);
3271590Srgrimes}
3281590Srgrimes
329162571Srwatson#ifdef USE_BSM_AUDIT
330227166Sedstatic void
331162571Srwatsonauditid(void)
332162571Srwatson{
333162571Srwatson	auditinfo_t auditinfo;
334172621Scsjp	auditinfo_addr_t ainfo_addr;
335172621Scsjp	int ret, extended;
336162571Srwatson
337172621Scsjp	extended = 0;
338172621Scsjp	ret = getaudit(&auditinfo);
339172621Scsjp	if (ret < 0 && errno == E2BIG) {
340172621Scsjp		if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0)
341172621Scsjp			err(1, "getaudit_addr");
342172621Scsjp		extended = 1;
343172621Scsjp	} else if (ret < 0)
344162656Sru		err(1, "getaudit");
345172621Scsjp	if (extended != 0) {
346172621Scsjp		(void) printf("auid=%d\n"
347172621Scsjp		    "mask.success=0x%08x\n"
348172621Scsjp		    "mask.failure=0x%08x\n"
349172621Scsjp		    "asid=%d\n"
350275855Sgleb		    "termid_addr.port=0x%08jx\n"
351172621Scsjp		    "termid_addr.addr[0]=0x%08x\n"
352172621Scsjp		    "termid_addr.addr[1]=0x%08x\n"
353172621Scsjp		    "termid_addr.addr[2]=0x%08x\n"
354172621Scsjp		    "termid_addr.addr[3]=0x%08x\n",
355172621Scsjp			ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success,
356172621Scsjp			ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid,
357275855Sgleb			(uintmax_t)ainfo_addr.ai_termid.at_port,
358172621Scsjp			ainfo_addr.ai_termid.at_addr[0],
359172621Scsjp			ainfo_addr.ai_termid.at_addr[1],
360172621Scsjp			ainfo_addr.ai_termid.at_addr[2],
361172621Scsjp			ainfo_addr.ai_termid.at_addr[3]);
362172621Scsjp	} else {
363172621Scsjp		(void) printf("auid=%d\n"
364172621Scsjp		    "mask.success=0x%08x\n"
365172621Scsjp		    "mask.failure=0x%08x\n"
366172621Scsjp		    "asid=%d\n"
367275855Sgleb		    "termid.port=0x%08jx\n"
368172621Scsjp		    "termid.machine=0x%08x\n",
369172621Scsjp			auditinfo.ai_auid, auditinfo.ai_mask.am_success,
370172621Scsjp			auditinfo.ai_mask.am_failure,
371275855Sgleb			auditinfo.ai_asid, (uintmax_t)auditinfo.ai_termid.port,
372172621Scsjp			auditinfo.ai_termid.machine);
373172621Scsjp	}
374162571Srwatson}
375162571Srwatson#endif
376162571Srwatson
377227166Sedstatic void
378102944Sdwmalonegroup(struct passwd *pw, int nflag)
3791590Srgrimes{
3801590Srgrimes	struct group *gr;
3811590Srgrimes	int cnt, id, lastid, ngroups;
382194494Sbrooks	long ngroups_max;
383194494Sbrooks	gid_t *groups;
38477314Sdd	const char *fmt;
3851590Srgrimes
386194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
387194494Sbrooks	if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL)
388194494Sbrooks		err(1, "malloc");
389194494Sbrooks
3901590Srgrimes	if (pw) {
391194494Sbrooks		ngroups = ngroups_max;
3921590Srgrimes		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
3931590Srgrimes	} else {
394194494Sbrooks		ngroups = getgroups(ngroups_max, groups);
3951590Srgrimes	}
3961590Srgrimes	fmt = nflag ? "%s" : "%u";
3971590Srgrimes	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
3981590Srgrimes		if (lastid == (id = groups[cnt]))
3991590Srgrimes			continue;
4001590Srgrimes		if (nflag) {
40127418Scharnier			if ((gr = getgrgid(id)))
4021590Srgrimes				(void)printf(fmt, gr->gr_name);
4031590Srgrimes			else
4041590Srgrimes				(void)printf(*fmt == ' ' ? " %u" : "%u",
4051590Srgrimes				    id);
4061590Srgrimes			fmt = " %s";
4071590Srgrimes		} else {
4081590Srgrimes			(void)printf(fmt, id);
4091590Srgrimes			fmt = " %u";
4101590Srgrimes		}
4111590Srgrimes		lastid = id;
4121590Srgrimes	}
4131590Srgrimes	(void)printf("\n");
414194494Sbrooks	free(groups);
4151590Srgrimes}
4161590Srgrimes
417227166Sedstatic void
418128900Srwatsonmaclabel(void)
419128900Srwatson{
420128900Srwatson	char *string;
421128900Srwatson	mac_t label;
422128900Srwatson	int error;
423128900Srwatson
424128900Srwatson	error = mac_prepare_process_label(&label);
425128900Srwatson	if (error == -1)
426128900Srwatson		errx(1, "mac_prepare_type: %s", strerror(errno));
427128900Srwatson
428128900Srwatson	error = mac_get_proc(label);
429128900Srwatson	if (error == -1)
430128900Srwatson		errx(1, "mac_get_proc: %s", strerror(errno));
431128900Srwatson
432128900Srwatson	error = mac_to_text(label, &string);
433128900Srwatson	if (error == -1)
434128900Srwatson		errx(1, "mac_to_text: %s", strerror(errno));
435128900Srwatson
436128900Srwatson	(void)printf("%s\n", string);
437128900Srwatson	mac_free(label);
438128900Srwatson	free(string);
439128900Srwatson}
440128900Srwatson
441227166Sedstatic struct passwd *
442102944Sdwmalonewho(char *u)
4431590Srgrimes{
4441590Srgrimes	struct passwd *pw;
4451590Srgrimes	long id;
4461590Srgrimes	char *ep;
4471590Srgrimes
4481590Srgrimes	/*
4491590Srgrimes	 * Translate user argument into a pw pointer.  First, try to
4501590Srgrimes	 * get it as specified.  If that fails, try it as a number.
4511590Srgrimes	 */
45227418Scharnier	if ((pw = getpwnam(u)))
4531590Srgrimes		return(pw);
4541590Srgrimes	id = strtol(u, &ep, 10);
4551590Srgrimes	if (*u && !*ep && (pw = getpwuid(id)))
4561590Srgrimes		return(pw);
45727418Scharnier	errx(1, "%s: no such user", u);
4581590Srgrimes	/* NOTREACHED */
4591590Srgrimes}
4601590Srgrimes
461227166Sedstatic void
462102944Sdwmalonepline(struct passwd *pw)
46338468Sobrien{
46438468Sobrien
46538468Sobrien	if (!pw) {
466144840Sstefanf		if ((pw = getpwuid(getuid())) == NULL)
46738468Sobrien			err(1, "getpwuid");
46838468Sobrien	}
46938468Sobrien
47051032Sbillf	(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
47138468Sobrien			pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
47251032Sbillf			(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
47338468Sobrien			pw->pw_dir, pw->pw_shell);
47438468Sobrien}
47538468Sobrien
47638468Sobrien
477227166Sedstatic void
478102944Sdwmaloneusage(void)
4791590Srgrimes{
48083452Sru
48183452Sru	if (isgroups)
48283452Sru		(void)fprintf(stderr, "usage: groups [user]\n");
48383452Sru	else if (iswhoami)
48483452Sru		(void)fprintf(stderr, "usage: whoami\n");
48583452Sru	else
486219304Strasz		(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
48783452Sru		    "usage: id [user]",
488162571Srwatson#ifdef USE_BSM_AUDIT
489162578Srwatson		    "       id -A\n",
490162571Srwatson#else
491162571Srwatson		    "",
492162571Srwatson#endif
493162578Srwatson		    "       id -G [-n] [user]",
494162578Srwatson		    "       id -M",
495162578Srwatson		    "       id -P [user]",
496219304Strasz		    "       id -c",
49783452Sru		    "       id -g [-nr] [user]",
49883452Sru		    "       id -p [user]",
49983452Sru		    "       id -u [-nr] [user]");
5001590Srgrimes	exit(1);
5011590Srgrimes}
502