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