id.c revision 162578
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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1991, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)id.c 8.2 (Berkeley) 2/16/94"; 43#endif 44#endif /* not lint */ 45#include <sys/cdefs.h> 46__FBSDID("$FreeBSD: head/usr.bin/id/id.c 162578 2006-09-23 15:43:29Z rwatson $"); 47 48#include <sys/param.h> 49#include <sys/mac.h> 50 51#ifdef USE_BSM_AUDIT 52#include <bsm/audit.h> 53#endif 54 55#include <err.h> 56#include <errno.h> 57#include <grp.h> 58#include <pwd.h> 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62#include <unistd.h> 63 64void id_print(struct passwd *, int, int, int); 65void pline(struct passwd *); 66void pretty(struct passwd *); 67void auditid(void); 68void group(struct passwd *, int); 69void maclabel(void); 70void usage(void); 71struct passwd *who(char *); 72 73int isgroups, iswhoami; 74 75int 76main(int argc, char *argv[]) 77{ 78 struct group *gr; 79 struct passwd *pw; 80 int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag; 81 int Aflag; 82 const char *myname; 83 84 Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0; 85 Aflag = 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) ? "" : "APGMgnpru")) != -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 'g': 116 gflag = 1; 117 break; 118 case 'n': 119 nflag = 1; 120 break; 121 case 'p': 122 pflag = 1; 123 break; 124 case 'r': 125 rflag = 1; 126 break; 127 case 'u': 128 uflag = 1; 129 break; 130 case '?': 131 default: 132 usage(); 133 } 134 argc -= optind; 135 argv += optind; 136 137 if (iswhoami && argc > 0) 138 usage(); 139 140 switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) { 141 case 1: 142 break; 143 case 0: 144 if (!nflag && !rflag) 145 break; 146 /* FALLTHROUGH */ 147 default: 148 usage(); 149 } 150 151 pw = *argv ? who(*argv) : NULL; 152 153 if (Mflag && pw != NULL) 154 usage(); 155 156#ifdef USE_BSM_AUDIT 157 if (Aflag) { 158 auditid(); 159 exit(0); 160 } 161#endif 162 163 if (gflag) { 164 id = pw ? pw->pw_gid : rflag ? getgid() : getegid(); 165 if (nflag && (gr = getgrgid(id))) 166 (void)printf("%s\n", gr->gr_name); 167 else 168 (void)printf("%u\n", id); 169 exit(0); 170 } 171 172 if (uflag) { 173 id = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); 174 if (nflag && (pw = getpwuid(id))) 175 (void)printf("%s\n", pw->pw_name); 176 else 177 (void)printf("%u\n", id); 178 exit(0); 179 } 180 181 if (Gflag) { 182 group(pw, nflag); 183 exit(0); 184 } 185 186 if (Mflag) { 187 maclabel(); 188 exit(0); 189 } 190 191 if (Pflag) { 192 pline(pw); 193 exit(0); 194 } 195 196 if (pflag) { 197 pretty(pw); 198 exit(0); 199 } 200 201 if (pw) { 202 id_print(pw, 1, 0, 0); 203 } 204 else { 205 id = getuid(); 206 if ((pw = getpwuid(id)) != NULL) 207 id_print(pw, 0, 1, 1); 208 } 209 exit(0); 210} 211 212void 213pretty(struct passwd *pw) 214{ 215 struct group *gr; 216 u_int eid, rid; 217 char *login; 218 219 if (pw) { 220 (void)printf("uid\t%s\n", pw->pw_name); 221 (void)printf("groups\t"); 222 group(pw, 1); 223 } else { 224 if ((login = getlogin()) == NULL) 225 err(1, "getlogin"); 226 227 pw = getpwuid(rid = getuid()); 228 if (pw == NULL || strcmp(login, pw->pw_name)) 229 (void)printf("login\t%s\n", login); 230 if (pw) 231 (void)printf("uid\t%s\n", pw->pw_name); 232 else 233 (void)printf("uid\t%u\n", rid); 234 235 if ((eid = geteuid()) != rid) { 236 if ((pw = getpwuid(eid))) 237 (void)printf("euid\t%s\n", pw->pw_name); 238 else 239 (void)printf("euid\t%u\n", eid); 240 } 241 if ((rid = getgid()) != (eid = getegid())) { 242 if ((gr = getgrgid(rid))) 243 (void)printf("rgid\t%s\n", gr->gr_name); 244 else 245 (void)printf("rgid\t%u\n", rid); 246 } 247 (void)printf("groups\t"); 248 group(NULL, 1); 249 } 250} 251 252void 253id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid) 254{ 255 struct group *gr; 256 gid_t gid, egid, lastgid; 257 uid_t uid, euid; 258 int cnt, ngroups; 259 gid_t groups[NGROUPS + 1]; 260 const char *fmt; 261 262 uid = pw->pw_uid; 263 gid = pw->pw_gid; 264 265 if (use_ggl) { 266 ngroups = NGROUPS + 1; 267 getgrouplist(pw->pw_name, gid, groups, &ngroups); 268 } 269 else { 270 ngroups = getgroups(NGROUPS + 1, groups); 271 } 272 273 printf("uid=%u(%s)", uid, pw->pw_name); 274 printf(" gid=%u", gid); 275 if ((gr = getgrgid(gid))) 276 (void)printf("(%s)", gr->gr_name); 277 if (p_euid && (euid = geteuid()) != uid) { 278 (void)printf(" euid=%u", euid); 279 if ((pw = getpwuid(euid))) 280 (void)printf("(%s)", pw->pw_name); 281 } 282 if (p_egid && (egid = getegid()) != gid) { 283 (void)printf(" egid=%u", egid); 284 if ((gr = getgrgid(egid))) 285 (void)printf("(%s)", gr->gr_name); 286 } 287 fmt = " groups=%u"; 288 for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) { 289 if (lastgid == (gid = groups[cnt])) 290 continue; 291 printf(fmt, gid); 292 fmt = ", %u"; 293 if ((gr = getgrgid(gid))) 294 printf("(%s)", gr->gr_name); 295 lastgid = gid; 296 } 297 printf("\n"); 298} 299 300#ifdef USE_BSM_AUDIT 301void 302auditid(void) 303{ 304 auditinfo_t auditinfo; 305 306 if (getaudit(&auditinfo) < 0) 307 err(-1, "getauditinfo"); 308 printf("auid=%d\n", auditinfo.ai_auid); 309 printf("mask.success=0x%08x\n", auditinfo.ai_mask.am_success); 310 printf("mask.failure=0x%08x\n", auditinfo.ai_mask.am_failure); 311 printf("termid.port=0x%08x\n", auditinfo.ai_termid.port); 312 printf("asid=%d\n", auditinfo.ai_asid); 313} 314#endif 315 316void 317group(struct passwd *pw, int nflag) 318{ 319 struct group *gr; 320 int cnt, id, lastid, ngroups; 321 gid_t groups[NGROUPS + 1]; 322 const char *fmt; 323 324 if (pw) { 325 ngroups = NGROUPS + 1; 326 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 327 } else { 328 groups[0] = getgid(); 329 ngroups = getgroups(NGROUPS, groups + 1) + 1; 330 } 331 fmt = nflag ? "%s" : "%u"; 332 for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) { 333 if (lastid == (id = groups[cnt])) 334 continue; 335 if (nflag) { 336 if ((gr = getgrgid(id))) 337 (void)printf(fmt, gr->gr_name); 338 else 339 (void)printf(*fmt == ' ' ? " %u" : "%u", 340 id); 341 fmt = " %s"; 342 } else { 343 (void)printf(fmt, id); 344 fmt = " %u"; 345 } 346 lastid = id; 347 } 348 (void)printf("\n"); 349} 350 351void 352maclabel(void) 353{ 354 char *string; 355 mac_t label; 356 int error; 357 358 error = mac_prepare_process_label(&label); 359 if (error == -1) 360 errx(1, "mac_prepare_type: %s", strerror(errno)); 361 362 error = mac_get_proc(label); 363 if (error == -1) 364 errx(1, "mac_get_proc: %s", strerror(errno)); 365 366 error = mac_to_text(label, &string); 367 if (error == -1) 368 errx(1, "mac_to_text: %s", strerror(errno)); 369 370 (void)printf("%s\n", string); 371 mac_free(label); 372 free(string); 373} 374 375struct passwd * 376who(char *u) 377{ 378 struct passwd *pw; 379 long id; 380 char *ep; 381 382 /* 383 * Translate user argument into a pw pointer. First, try to 384 * get it as specified. If that fails, try it as a number. 385 */ 386 if ((pw = getpwnam(u))) 387 return(pw); 388 id = strtol(u, &ep, 10); 389 if (*u && !*ep && (pw = getpwuid(id))) 390 return(pw); 391 errx(1, "%s: no such user", u); 392 /* NOTREACHED */ 393} 394 395void 396pline(struct passwd *pw) 397{ 398 399 if (!pw) { 400 if ((pw = getpwuid(getuid())) == NULL) 401 err(1, "getpwuid"); 402 } 403 404 (void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, 405 pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, 406 (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos, 407 pw->pw_dir, pw->pw_shell); 408} 409 410 411void 412usage(void) 413{ 414 415 if (isgroups) 416 (void)fprintf(stderr, "usage: groups [user]\n"); 417 else if (iswhoami) 418 (void)fprintf(stderr, "usage: whoami\n"); 419 else 420 (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n", 421 "usage: id [user]", 422#ifdef USE_BSM_AUDIT 423 " id -A\n", 424#else 425 "", 426#endif 427 " id -G [-n] [user]", 428 " id -M", 429 " id -P [user]", 430 " id -g [-nr] [user]", 431 " id -p [user]", 432 " id -u [-nr] [user]"); 433 exit(1); 434} 435