id.c revision 194494
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 * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3527418Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1991, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4127418Scharnier#if 0
421590Srgrimesstatic char sccsid[] = "@(#)id.c	8.2 (Berkeley) 2/16/94";
4327418Scharnier#endif
441590Srgrimes#endif /* not lint */
4599112Sobrien#include <sys/cdefs.h>
4699112Sobrien__FBSDID("$FreeBSD: head/usr.bin/id/id.c 194494 2009-06-19 15:58:24Z brooks $");
471590Srgrimes
481590Srgrimes#include <sys/param.h>
49128900Srwatson#include <sys/mac.h>
501590Srgrimes
51162571Srwatson#ifdef USE_BSM_AUDIT
52162571Srwatson#include <bsm/audit.h>
53162571Srwatson#endif
54162571Srwatson
5527418Scharnier#include <err.h>
56128900Srwatson#include <errno.h>
571590Srgrimes#include <grp.h>
581590Srgrimes#include <pwd.h>
591590Srgrimes#include <stdio.h>
601590Srgrimes#include <stdlib.h>
611590Srgrimes#include <string.h>
621590Srgrimes#include <unistd.h>
631590Srgrimes
64145672Srobertvoid	id_print(struct passwd *, int, int, int);
6592920Simpvoid	pline(struct passwd *);
6692920Simpvoid	pretty(struct passwd *);
67162571Srwatsonvoid	auditid(void);
6892920Simpvoid	group(struct passwd *, int);
69128900Srwatsonvoid	maclabel(void);
7092920Simpvoid	usage(void);
71145628Srobertstruct passwd *who(char *);
721590Srgrimes
7383452Sruint isgroups, iswhoami;
7483452Sru
751590Srgrimesint
76102944Sdwmalonemain(int argc, char *argv[])
771590Srgrimes{
781590Srgrimes	struct group *gr;
791590Srgrimes	struct passwd *pw;
80128900Srwatson	int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
81162578Srwatson	int Aflag;
8283452Sru	const char *myname;
831590Srgrimes
84128900Srwatson	Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
85162578Srwatson	Aflag = 0;
8683452Sru
8783452Sru	myname = strrchr(argv[0], '/');
8883452Sru	myname = (myname != NULL) ? myname + 1 : argv[0];
8983452Sru	if (strcmp(myname, "groups") == 0) {
9083452Sru		isgroups = 1;
9183452Sru		Gflag = nflag = 1;
9283452Sru	}
9383452Sru	else if (strcmp(myname, "whoami") == 0) {
9483452Sru		iswhoami = 1;
9583452Sru		uflag = nflag = 1;
9683452Sru	}
9783452Sru
9883452Sru	while ((ch = getopt(argc, argv,
99162672Sceri	    (isgroups || iswhoami) ? "" : "APGMagnpru")) != -1)
1001590Srgrimes		switch(ch) {
101162578Srwatson#ifdef USE_BSM_AUDIT
102162578Srwatson		case 'A':
103162578Srwatson			Aflag = 1;
104162578Srwatson			break;
105162578Srwatson#endif
1061590Srgrimes		case 'G':
1071590Srgrimes			Gflag = 1;
1081590Srgrimes			break;
109128900Srwatson		case 'M':
110128900Srwatson			Mflag = 1;
111128900Srwatson			break;
11238468Sobrien		case 'P':
11338468Sobrien			Pflag = 1;
11438468Sobrien			break;
115162672Sceri		case 'a':
116162672Sceri			break;
1171590Srgrimes		case 'g':
1181590Srgrimes			gflag = 1;
1191590Srgrimes			break;
1201590Srgrimes		case 'n':
1211590Srgrimes			nflag = 1;
1221590Srgrimes			break;
1231590Srgrimes		case 'p':
1241590Srgrimes			pflag = 1;
1251590Srgrimes			break;
1261590Srgrimes		case 'r':
1271590Srgrimes			rflag = 1;
1281590Srgrimes			break;
1291590Srgrimes		case 'u':
1301590Srgrimes			uflag = 1;
1311590Srgrimes			break;
1321590Srgrimes		case '?':
1331590Srgrimes		default:
1341590Srgrimes			usage();
1351590Srgrimes		}
1361590Srgrimes	argc -= optind;
1371590Srgrimes	argv += optind;
1381590Srgrimes
13983452Sru	if (iswhoami && argc > 0)
14083452Sru		usage();
14183452Sru
142162578Srwatson	switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
1431590Srgrimes	case 1:
1441590Srgrimes		break;
1451590Srgrimes	case 0:
1461590Srgrimes		if (!nflag && !rflag)
1471590Srgrimes			break;
1481590Srgrimes		/* FALLTHROUGH */
1491590Srgrimes	default:
1501590Srgrimes		usage();
1511590Srgrimes	}
1521590Srgrimes
1531590Srgrimes	pw = *argv ? who(*argv) : NULL;
1541590Srgrimes
155128900Srwatson	if (Mflag && pw != NULL)
156128900Srwatson		usage();
157128900Srwatson
158162571Srwatson#ifdef USE_BSM_AUDIT
159162578Srwatson	if (Aflag) {
160162571Srwatson		auditid();
161162571Srwatson		exit(0);
162162571Srwatson	}
163162571Srwatson#endif
164162571Srwatson
1651590Srgrimes	if (gflag) {
1661590Srgrimes		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
1671590Srgrimes		if (nflag && (gr = getgrgid(id)))
1681590Srgrimes			(void)printf("%s\n", gr->gr_name);
1691590Srgrimes		else
1701590Srgrimes			(void)printf("%u\n", id);
1711590Srgrimes		exit(0);
1721590Srgrimes	}
1731590Srgrimes
1741590Srgrimes	if (uflag) {
1751590Srgrimes		id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
1761590Srgrimes		if (nflag && (pw = getpwuid(id)))
1771590Srgrimes			(void)printf("%s\n", pw->pw_name);
1781590Srgrimes		else
1791590Srgrimes			(void)printf("%u\n", id);
1801590Srgrimes		exit(0);
1811590Srgrimes	}
1821590Srgrimes
1831590Srgrimes	if (Gflag) {
1841590Srgrimes		group(pw, nflag);
1851590Srgrimes		exit(0);
1861590Srgrimes	}
1871590Srgrimes
188128900Srwatson	if (Mflag) {
189128900Srwatson		maclabel();
190128900Srwatson		exit(0);
191128900Srwatson	}
192128900Srwatson
19338468Sobrien	if (Pflag) {
19438468Sobrien		pline(pw);
19538468Sobrien		exit(0);
19638468Sobrien	}
19738468Sobrien
1981590Srgrimes	if (pflag) {
1991590Srgrimes		pretty(pw);
2001590Srgrimes		exit(0);
2011590Srgrimes	}
2021590Srgrimes
203145628Srobert	if (pw) {
204145672Srobert		id_print(pw, 1, 0, 0);
205145628Srobert	}
206145628Srobert	else {
207145628Srobert		id = getuid();
208165028Smpp		pw = getpwuid(id);
209165028Smpp		id_print(pw, 0, 1, 1);
210145628Srobert	}
2111590Srgrimes	exit(0);
2121590Srgrimes}
2131590Srgrimes
2141590Srgrimesvoid
215102944Sdwmalonepretty(struct passwd *pw)
2161590Srgrimes{
2171590Srgrimes	struct group *gr;
2181590Srgrimes	u_int eid, rid;
2191590Srgrimes	char *login;
2201590Srgrimes
2211590Srgrimes	if (pw) {
2221590Srgrimes		(void)printf("uid\t%s\n", pw->pw_name);
2231590Srgrimes		(void)printf("groups\t");
2241590Srgrimes		group(pw, 1);
2251590Srgrimes	} else {
2261590Srgrimes		if ((login = getlogin()) == NULL)
22727418Scharnier			err(1, "getlogin");
2281590Srgrimes
2291590Srgrimes		pw = getpwuid(rid = getuid());
2301590Srgrimes		if (pw == NULL || strcmp(login, pw->pw_name))
2311590Srgrimes			(void)printf("login\t%s\n", login);
2321590Srgrimes		if (pw)
2331590Srgrimes			(void)printf("uid\t%s\n", pw->pw_name);
2341590Srgrimes		else
2351590Srgrimes			(void)printf("uid\t%u\n", rid);
2368874Srgrimes
23748566Sbillf		if ((eid = geteuid()) != rid) {
23827418Scharnier			if ((pw = getpwuid(eid)))
23933576Ssteve				(void)printf("euid\t%s\n", pw->pw_name);
2401590Srgrimes			else
24133576Ssteve				(void)printf("euid\t%u\n", eid);
24248566Sbillf		}
24348566Sbillf		if ((rid = getgid()) != (eid = getegid())) {
24427418Scharnier			if ((gr = getgrgid(rid)))
2451590Srgrimes				(void)printf("rgid\t%s\n", gr->gr_name);
2461590Srgrimes			else
2471590Srgrimes				(void)printf("rgid\t%u\n", rid);
24848566Sbillf		}
2491590Srgrimes		(void)printf("groups\t");
2501590Srgrimes		group(NULL, 1);
2511590Srgrimes	}
2521590Srgrimes}
2531590Srgrimes
2541590Srgrimesvoid
255145672Srobertid_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
2561590Srgrimes{
2571590Srgrimes	struct group *gr;
258145628Srobert	gid_t gid, egid, lastgid;
259145628Srobert	uid_t uid, euid;
260145628Srobert	int cnt, ngroups;
261194494Sbrooks	long ngroups_max;
262194494Sbrooks	gid_t *groups;
26377314Sdd	const char *fmt;
2641590Srgrimes
265165028Smpp	if (pw != NULL) {
266165028Smpp		uid = pw->pw_uid;
267165028Smpp		gid = pw->pw_gid;
268165028Smpp	}
269165028Smpp	else {
270165028Smpp		uid = getuid();
271165028Smpp		gid = getgid();
272165028Smpp	}
273145628Srobert
274194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
275194494Sbrooks	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
276194494Sbrooks		err(1, "malloc");
277194494Sbrooks
278165028Smpp	if (use_ggl && pw != NULL) {
279194494Sbrooks		ngroups = ngroups_max;
280145672Srobert		getgrouplist(pw->pw_name, gid, groups, &ngroups);
281145672Srobert	}
282145672Srobert	else {
283194494Sbrooks		ngroups = getgroups(ngroups_max, groups);
284145672Srobert	}
285145628Srobert
286165028Smpp	if (pw != NULL)
287165028Smpp		printf("uid=%u(%s)", uid, pw->pw_name);
288165028Smpp	else
289165028Smpp		printf("uid=%u", getuid());
290159008Sstefanf	printf(" gid=%u", gid);
291159008Sstefanf	if ((gr = getgrgid(gid)))
292159008Sstefanf		(void)printf("(%s)", gr->gr_name);
293145628Srobert	if (p_euid && (euid = geteuid()) != uid) {
294145628Srobert		(void)printf(" euid=%u", euid);
295145628Srobert		if ((pw = getpwuid(euid)))
2961590Srgrimes			(void)printf("(%s)", pw->pw_name);
2971590Srgrimes	}
298145628Srobert	if (p_egid && (egid = getegid()) != gid) {
299145628Srobert		(void)printf(" egid=%u", egid);
300145628Srobert		if ((gr = getgrgid(egid)))
3011590Srgrimes			(void)printf("(%s)", gr->gr_name);
3021590Srgrimes	}
3031590Srgrimes	fmt = " groups=%u";
30410359Sdg	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
30510359Sdg		if (lastgid == (gid = groups[cnt]))
3061590Srgrimes			continue;
307145628Srobert		printf(fmt, gid);
308165626Sstefanf		fmt = ",%u";
30927418Scharnier		if ((gr = getgrgid(gid)))
310145628Srobert			printf("(%s)", gr->gr_name);
31110359Sdg		lastgid = gid;
3121590Srgrimes	}
313145628Srobert	printf("\n");
314194494Sbrooks	free(groups);
3151590Srgrimes}
3161590Srgrimes
317162571Srwatson#ifdef USE_BSM_AUDIT
3181590Srgrimesvoid
319162571Srwatsonauditid(void)
320162571Srwatson{
321162571Srwatson	auditinfo_t auditinfo;
322172621Scsjp	auditinfo_addr_t ainfo_addr;
323172621Scsjp	int ret, extended;
324162571Srwatson
325172621Scsjp	extended = 0;
326172621Scsjp	ret = getaudit(&auditinfo);
327172621Scsjp	if (ret < 0 && errno == E2BIG) {
328172621Scsjp		if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0)
329172621Scsjp			err(1, "getaudit_addr");
330172621Scsjp		extended = 1;
331172621Scsjp	} else if (ret < 0)
332162656Sru		err(1, "getaudit");
333172621Scsjp	if (extended != 0) {
334172621Scsjp		(void) printf("auid=%d\n"
335172621Scsjp		    "mask.success=0x%08x\n"
336172621Scsjp		    "mask.failure=0x%08x\n"
337172621Scsjp		    "asid=%d\n"
338172621Scsjp		    "termid_addr.port=0x%08x\n"
339172621Scsjp		    "termid_addr.addr[0]=0x%08x\n"
340172621Scsjp		    "termid_addr.addr[1]=0x%08x\n"
341172621Scsjp		    "termid_addr.addr[2]=0x%08x\n"
342172621Scsjp		    "termid_addr.addr[3]=0x%08x\n",
343172621Scsjp			ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success,
344172621Scsjp			ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid,
345172621Scsjp			ainfo_addr.ai_termid.at_port,
346172621Scsjp			ainfo_addr.ai_termid.at_addr[0],
347172621Scsjp			ainfo_addr.ai_termid.at_addr[1],
348172621Scsjp			ainfo_addr.ai_termid.at_addr[2],
349172621Scsjp			ainfo_addr.ai_termid.at_addr[3]);
350172621Scsjp	} else {
351172621Scsjp		(void) printf("auid=%d\n"
352172621Scsjp		    "mask.success=0x%08x\n"
353172621Scsjp		    "mask.failure=0x%08x\n"
354172621Scsjp		    "asid=%d\n"
355172621Scsjp		    "termid.port=0x%08x\n"
356172621Scsjp		    "termid.machine=0x%08x\n",
357172621Scsjp			auditinfo.ai_auid, auditinfo.ai_mask.am_success,
358172621Scsjp			auditinfo.ai_mask.am_failure,
359172621Scsjp			auditinfo.ai_asid, auditinfo.ai_termid.port,
360172621Scsjp			auditinfo.ai_termid.machine);
361172621Scsjp	}
362162571Srwatson}
363162571Srwatson#endif
364162571Srwatson
365162571Srwatsonvoid
366102944Sdwmalonegroup(struct passwd *pw, int nflag)
3671590Srgrimes{
3681590Srgrimes	struct group *gr;
3691590Srgrimes	int cnt, id, lastid, ngroups;
370194494Sbrooks	long ngroups_max;
371194494Sbrooks	gid_t *groups;
37277314Sdd	const char *fmt;
3731590Srgrimes
374194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
375194494Sbrooks	if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL)
376194494Sbrooks		err(1, "malloc");
377194494Sbrooks
3781590Srgrimes	if (pw) {
379194494Sbrooks		ngroups = ngroups_max;
3801590Srgrimes		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
3811590Srgrimes	} else {
382194494Sbrooks		ngroups = getgroups(ngroups_max, groups);
3831590Srgrimes	}
3841590Srgrimes	fmt = nflag ? "%s" : "%u";
3851590Srgrimes	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
3861590Srgrimes		if (lastid == (id = groups[cnt]))
3871590Srgrimes			continue;
3881590Srgrimes		if (nflag) {
38927418Scharnier			if ((gr = getgrgid(id)))
3901590Srgrimes				(void)printf(fmt, gr->gr_name);
3911590Srgrimes			else
3921590Srgrimes				(void)printf(*fmt == ' ' ? " %u" : "%u",
3931590Srgrimes				    id);
3941590Srgrimes			fmt = " %s";
3951590Srgrimes		} else {
3961590Srgrimes			(void)printf(fmt, id);
3971590Srgrimes			fmt = " %u";
3981590Srgrimes		}
3991590Srgrimes		lastid = id;
4001590Srgrimes	}
4011590Srgrimes	(void)printf("\n");
402194494Sbrooks	free(groups);
4031590Srgrimes}
4041590Srgrimes
405128900Srwatsonvoid
406128900Srwatsonmaclabel(void)
407128900Srwatson{
408128900Srwatson	char *string;
409128900Srwatson	mac_t label;
410128900Srwatson	int error;
411128900Srwatson
412128900Srwatson	error = mac_prepare_process_label(&label);
413128900Srwatson	if (error == -1)
414128900Srwatson		errx(1, "mac_prepare_type: %s", strerror(errno));
415128900Srwatson
416128900Srwatson	error = mac_get_proc(label);
417128900Srwatson	if (error == -1)
418128900Srwatson		errx(1, "mac_get_proc: %s", strerror(errno));
419128900Srwatson
420128900Srwatson	error = mac_to_text(label, &string);
421128900Srwatson	if (error == -1)
422128900Srwatson		errx(1, "mac_to_text: %s", strerror(errno));
423128900Srwatson
424128900Srwatson	(void)printf("%s\n", string);
425128900Srwatson	mac_free(label);
426128900Srwatson	free(string);
427128900Srwatson}
428128900Srwatson
4291590Srgrimesstruct passwd *
430102944Sdwmalonewho(char *u)
4311590Srgrimes{
4321590Srgrimes	struct passwd *pw;
4331590Srgrimes	long id;
4341590Srgrimes	char *ep;
4351590Srgrimes
4361590Srgrimes	/*
4371590Srgrimes	 * Translate user argument into a pw pointer.  First, try to
4381590Srgrimes	 * get it as specified.  If that fails, try it as a number.
4391590Srgrimes	 */
44027418Scharnier	if ((pw = getpwnam(u)))
4411590Srgrimes		return(pw);
4421590Srgrimes	id = strtol(u, &ep, 10);
4431590Srgrimes	if (*u && !*ep && (pw = getpwuid(id)))
4441590Srgrimes		return(pw);
44527418Scharnier	errx(1, "%s: no such user", u);
4461590Srgrimes	/* NOTREACHED */
4471590Srgrimes}
4481590Srgrimes
4491590Srgrimesvoid
450102944Sdwmalonepline(struct passwd *pw)
45138468Sobrien{
45238468Sobrien
45338468Sobrien	if (!pw) {
454144840Sstefanf		if ((pw = getpwuid(getuid())) == NULL)
45538468Sobrien			err(1, "getpwuid");
45638468Sobrien	}
45738468Sobrien
45851032Sbillf	(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
45938468Sobrien			pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
46051032Sbillf			(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
46138468Sobrien			pw->pw_dir, pw->pw_shell);
46238468Sobrien}
46338468Sobrien
46438468Sobrien
46538468Sobrienvoid
466102944Sdwmaloneusage(void)
4671590Srgrimes{
46883452Sru
46983452Sru	if (isgroups)
47083452Sru		(void)fprintf(stderr, "usage: groups [user]\n");
47183452Sru	else if (iswhoami)
47283452Sru		(void)fprintf(stderr, "usage: whoami\n");
47383452Sru	else
474162578Srwatson		(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n",
47583452Sru		    "usage: id [user]",
476162571Srwatson#ifdef USE_BSM_AUDIT
477162578Srwatson		    "       id -A\n",
478162571Srwatson#else
479162571Srwatson		    "",
480162571Srwatson#endif
481162578Srwatson		    "       id -G [-n] [user]",
482162578Srwatson		    "       id -M",
483162578Srwatson		    "       id -P [user]",
48483452Sru		    "       id -g [-nr] [user]",
48583452Sru		    "       id -p [user]",
48683452Sru		    "       id -u [-nr] [user]");
4871590Srgrimes	exit(1);
4881590Srgrimes}
489