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 static void id_print(struct passwd *, int, int, int); 61 static void pline(struct passwd *); 62 static void pretty(struct passwd *); 63 #ifdef USE_BSM_AUDIT 64 static void auditid(void); 65 #endif 66 static void group(struct passwd *, int); 67 static void maclabel(void); 68 static void usage(void); 69 static struct passwd *who(char *); 70 71 static int isgroups, iswhoami; 72 73 int 74 main(int argc, char *argv[]) 75 { 76 struct group *gr; 77 struct passwd *pw; 78 int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag; 79 int Aflag, cflag; 80 int error; 81 const char *myname; 82 char loginclass[MAXLOGNAME]; 83 84 Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0; 85 Aflag = cflag = 0; 86 87 myname = strrchr(argv[0], '/'); 88 myname = (myname != NULL) ? myname + 1 : argv[0]; 89 if (strcmp(myname, "groups") == 0) { 90 isgroups = 1; 91 Gflag = nflag = 1; 92 } 93 else if (strcmp(myname, "whoami") == 0) { 94 iswhoami = 1; 95 uflag = nflag = 1; 96 } 97 98 while ((ch = getopt(argc, argv, 99 (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1) 100 switch(ch) { 101 #ifdef USE_BSM_AUDIT 102 case 'A': 103 Aflag = 1; 104 break; 105 #endif 106 case 'G': 107 Gflag = 1; 108 break; 109 case 'M': 110 Mflag = 1; 111 break; 112 case 'P': 113 Pflag = 1; 114 break; 115 case 'a': 116 break; 117 case 'c': 118 cflag = 1; 119 break; 120 case 'g': 121 gflag = 1; 122 break; 123 case 'n': 124 nflag = 1; 125 break; 126 case 'p': 127 pflag = 1; 128 break; 129 case 'r': 130 rflag = 1; 131 break; 132 case 'u': 133 uflag = 1; 134 break; 135 case '?': 136 default: 137 usage(); 138 } 139 argc -= optind; 140 argv += optind; 141 142 if (iswhoami && argc > 0) 143 usage(); 144 145 switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) { 146 case 1: 147 break; 148 case 0: 149 if (!nflag && !rflag) 150 break; 151 /* FALLTHROUGH */ 152 default: 153 usage(); 154 } 155 156 pw = *argv ? who(*argv) : NULL; 157 158 if (Mflag && pw != NULL) 159 usage(); 160 161 #ifdef USE_BSM_AUDIT 162 if (Aflag) { 163 auditid(); 164 exit(0); 165 } 166 #endif 167 168 if (cflag) { 169 error = getloginclass(loginclass, sizeof(loginclass)); 170 if (error != 0) 171 err(1, "loginclass"); 172 (void)printf("%s\n", loginclass); 173 exit(0); 174 } 175 176 if (gflag) { 177 id = pw ? pw->pw_gid : rflag ? getgid() : getegid(); 178 if (nflag && (gr = getgrgid(id))) 179 (void)printf("%s\n", gr->gr_name); 180 else 181 (void)printf("%u\n", id); 182 exit(0); 183 } 184 185 if (uflag) { 186 id = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); 187 if (nflag && (pw = getpwuid(id))) 188 (void)printf("%s\n", pw->pw_name); 189 else 190 (void)printf("%u\n", id); 191 exit(0); 192 } 193 194 if (Gflag) { 195 group(pw, nflag); 196 exit(0); 197 } 198 199 if (Mflag) { 200 maclabel(); 201 exit(0); 202 } 203 204 if (Pflag) { 205 pline(pw); 206 exit(0); 207 } 208 209 if (pflag) { 210 pretty(pw); 211 exit(0); 212 } 213 214 if (pw) { 215 id_print(pw, 1, 0, 0); 216 } 217 else { 218 id = getuid(); 219 pw = getpwuid(id); 220 id_print(pw, 0, 1, 1); 221 } 222 exit(0); 223 } 224 225 static void 226 pretty(struct passwd *pw) 227 { 228 struct group *gr; 229 u_int eid, rid; 230 char *login; 231 232 if (pw) { 233 (void)printf("uid\t%s\n", pw->pw_name); 234 (void)printf("groups\t"); 235 group(pw, 1); 236 } else { 237 if ((login = getlogin()) == NULL) 238 err(1, "getlogin"); 239 240 pw = getpwuid(rid = getuid()); 241 if (pw == NULL || strcmp(login, pw->pw_name)) 242 (void)printf("login\t%s\n", login); 243 if (pw) 244 (void)printf("uid\t%s\n", pw->pw_name); 245 else 246 (void)printf("uid\t%u\n", rid); 247 248 if ((eid = geteuid()) != rid) { 249 if ((pw = getpwuid(eid))) 250 (void)printf("euid\t%s\n", pw->pw_name); 251 else 252 (void)printf("euid\t%u\n", eid); 253 } 254 if ((rid = getgid()) != (eid = getegid())) { 255 if ((gr = getgrgid(rid))) 256 (void)printf("rgid\t%s\n", gr->gr_name); 257 else 258 (void)printf("rgid\t%u\n", rid); 259 } 260 (void)printf("groups\t"); 261 group(NULL, 1); 262 } 263 } 264 265 static void 266 id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid) 267 { 268 struct group *gr; 269 gid_t gid, egid, lastgid; 270 uid_t uid, euid; 271 int cnt, ngroups; 272 long ngroups_max; 273 gid_t *groups; 274 const char *fmt; 275 276 if (pw != NULL) { 277 uid = pw->pw_uid; 278 gid = pw->pw_gid; 279 } 280 else { 281 uid = getuid(); 282 gid = getgid(); 283 } 284 285 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; 286 if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) 287 err(1, "malloc"); 288 289 if (use_ggl && pw != NULL) { 290 ngroups = ngroups_max; 291 getgrouplist(pw->pw_name, gid, groups, &ngroups); 292 } 293 else { 294 ngroups = getgroups(ngroups_max, groups); 295 } 296 297 if (pw != NULL) 298 printf("uid=%u(%s)", uid, pw->pw_name); 299 else 300 printf("uid=%u", getuid()); 301 printf(" gid=%u", gid); 302 if ((gr = getgrgid(gid))) 303 (void)printf("(%s)", gr->gr_name); 304 if (p_euid && (euid = geteuid()) != uid) { 305 (void)printf(" euid=%u", euid); 306 if ((pw = getpwuid(euid))) 307 (void)printf("(%s)", pw->pw_name); 308 } 309 if (p_egid && (egid = getegid()) != gid) { 310 (void)printf(" egid=%u", egid); 311 if ((gr = getgrgid(egid))) 312 (void)printf("(%s)", gr->gr_name); 313 } 314 fmt = " groups=%u"; 315 for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) { 316 if (lastgid == (gid = groups[cnt])) 317 continue; 318 printf(fmt, gid); 319 fmt = ",%u"; 320 if ((gr = getgrgid(gid))) 321 printf("(%s)", gr->gr_name); 322 lastgid = gid; 323 } 324 printf("\n"); 325 free(groups); 326 } 327 328 #ifdef USE_BSM_AUDIT 329 static void 330 auditid(void) 331 { 332 auditinfo_t auditinfo; 333 auditinfo_addr_t ainfo_addr; 334 int ret, extended; 335 336 extended = 0; 337 ret = getaudit(&auditinfo); 338 if (ret < 0 && errno == E2BIG) { 339 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) 340 err(1, "getaudit_addr"); 341 extended = 1; 342 } else if (ret < 0) 343 err(1, "getaudit"); 344 if (extended != 0) { 345 (void) printf("auid=%d\n" 346 "mask.success=0x%08x\n" 347 "mask.failure=0x%08x\n" 348 "asid=%d\n" 349 "termid_addr.port=0x%08x\n" 350 "termid_addr.addr[0]=0x%08x\n" 351 "termid_addr.addr[1]=0x%08x\n" 352 "termid_addr.addr[2]=0x%08x\n" 353 "termid_addr.addr[3]=0x%08x\n", 354 ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success, 355 ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid, 356 ainfo_addr.ai_termid.at_port, 357 ainfo_addr.ai_termid.at_addr[0], 358 ainfo_addr.ai_termid.at_addr[1], 359 ainfo_addr.ai_termid.at_addr[2], 360 ainfo_addr.ai_termid.at_addr[3]); 361 } else { 362 (void) printf("auid=%d\n" 363 "mask.success=0x%08x\n" 364 "mask.failure=0x%08x\n" 365 "asid=%d\n" 366 "termid.port=0x%08x\n" 367 "termid.machine=0x%08x\n", 368 auditinfo.ai_auid, auditinfo.ai_mask.am_success, 369 auditinfo.ai_mask.am_failure, 370 auditinfo.ai_asid, auditinfo.ai_termid.port, 371 auditinfo.ai_termid.machine); 372 } 373 } 374 #endif 375 376 static void 377 group(struct passwd *pw, int nflag) 378 { 379 struct group *gr; 380 int cnt, id, lastid, ngroups; 381 long ngroups_max; 382 gid_t *groups; 383 const char *fmt; 384 385 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; 386 if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL) 387 err(1, "malloc"); 388 389 if (pw) { 390 ngroups = ngroups_max; 391 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 392 } else { 393 ngroups = getgroups(ngroups_max, groups); 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 free(groups); 414 } 415 416 static void 417 maclabel(void) 418 { 419 char *string; 420 mac_t label; 421 int error; 422 423 error = mac_prepare_process_label(&label); 424 if (error == -1) 425 errx(1, "mac_prepare_type: %s", strerror(errno)); 426 427 error = mac_get_proc(label); 428 if (error == -1) 429 errx(1, "mac_get_proc: %s", strerror(errno)); 430 431 error = mac_to_text(label, &string); 432 if (error == -1) 433 errx(1, "mac_to_text: %s", strerror(errno)); 434 435 (void)printf("%s\n", string); 436 mac_free(label); 437 free(string); 438 } 439 440 static struct passwd * 441 who(char *u) 442 { 443 struct passwd *pw; 444 long id; 445 char *ep; 446 447 /* 448 * Translate user argument into a pw pointer. First, try to 449 * get it as specified. If that fails, try it as a number. 450 */ 451 if ((pw = getpwnam(u))) 452 return(pw); 453 id = strtol(u, &ep, 10); 454 if (*u && !*ep && (pw = getpwuid(id))) 455 return(pw); 456 errx(1, "%s: no such user", u); 457 /* NOTREACHED */ 458 } 459 460 static void 461 pline(struct passwd *pw) 462 { 463 464 if (!pw) { 465 if ((pw = getpwuid(getuid())) == NULL) 466 err(1, "getpwuid"); 467 } 468 469 (void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, 470 pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, 471 (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos, 472 pw->pw_dir, pw->pw_shell); 473 } 474 475 476 static void 477 usage(void) 478 { 479 480 if (isgroups) 481 (void)fprintf(stderr, "usage: groups [user]\n"); 482 else if (iswhoami) 483 (void)fprintf(stderr, "usage: whoami\n"); 484 else 485 (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 486 "usage: id [user]", 487 #ifdef USE_BSM_AUDIT 488 " id -A\n", 489 #else 490 "", 491 #endif 492 " id -G [-n] [user]", 493 " id -M", 494 " id -P [user]", 495 " id -c", 496 " id -g [-nr] [user]", 497 " id -p [user]", 498 " id -u [-nr] [user]"); 499 exit(1); 500 } 501