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