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