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