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