1 /* $OpenBSD: id.c,v 1.26 2015/10/09 01:37:07 deraadt Exp $ */ 2 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 #include <err.h> 33 #include <errno.h> 34 #include <grp.h> 35 #include <pwd.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <limits.h> 41 #include <login_cap.h> 42 43 void current(void); 44 void pretty(struct passwd *); 45 void group(struct passwd *, int); 46 void usage(void); 47 void user(struct passwd *); 48 struct passwd * 49 who(char *); 50 51 int 52 main(int argc, char *argv[]) 53 { 54 struct group *gr; 55 struct passwd *pw; 56 int ch, cflag, Gflag, gflag, nflag, pflag, rflag, uflag; 57 uid_t uid; 58 gid_t gid; 59 const char *opts; 60 61 if (pledge("stdio getpw", NULL) == -1) 62 err(1, "pledge"); 63 64 cflag = Gflag = gflag = nflag = pflag = rflag = uflag = 0; 65 66 if (strcmp(getprogname(), "groups") == 0) { 67 Gflag = 1; 68 nflag = 1; 69 opts = ""; 70 if (argc > 2) 71 usage(); 72 } else if (strcmp(getprogname(), "whoami") == 0) { 73 uflag = 1; 74 nflag = 1; 75 opts = ""; 76 if (argc > 1) 77 usage(); 78 } else 79 opts = "cGgnpru"; 80 81 while ((ch = getopt(argc, argv, opts)) != -1) 82 switch(ch) { 83 case 'c': 84 cflag = 1; 85 break; 86 case 'G': 87 Gflag = 1; 88 break; 89 case 'g': 90 gflag = 1; 91 break; 92 case 'n': 93 nflag = 1; 94 break; 95 case 'p': 96 pflag = 1; 97 break; 98 case 'r': 99 rflag = 1; 100 break; 101 case 'u': 102 uflag = 1; 103 break; 104 case '?': 105 default: 106 usage(); 107 } 108 argc -= optind; 109 argv += optind; 110 111 switch (cflag + Gflag + gflag + pflag + uflag) { 112 case 1: 113 break; 114 case 0: 115 if (!nflag && !rflag) 116 break; 117 /* FALLTHROUGH */ 118 default: 119 usage(); 120 } 121 122 if (strcmp(opts, "") != 0 && argc > 1) 123 usage(); 124 125 pw = *argv ? who(*argv) : NULL; 126 127 if (cflag) { 128 if (pw == NULL) 129 pw = getpwuid(getuid()); 130 if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0') 131 (void)printf("%s\n", pw->pw_class); 132 else 133 (void)printf("%s\n", LOGIN_DEFCLASS); 134 exit(0); 135 } 136 137 if (gflag) { 138 gid = pw ? pw->pw_gid : rflag ? getgid() : getegid(); 139 if (nflag && (gr = getgrgid(gid))) 140 (void)printf("%s\n", gr->gr_name); 141 else 142 (void)printf("%u\n", gid); 143 exit(0); 144 } 145 146 if (uflag) { 147 uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); 148 if (nflag && (pw = getpwuid(uid))) 149 (void)printf("%s\n", pw->pw_name); 150 else 151 (void)printf("%u\n", uid); 152 exit(0); 153 } 154 155 if (Gflag) { 156 group(pw, nflag); 157 exit(0); 158 } 159 160 if (pflag) { 161 pretty(pw); 162 exit(0); 163 } 164 165 if (pw) 166 user(pw); 167 else 168 current(); 169 exit(0); 170 } 171 172 void 173 pretty(struct passwd *pw) 174 { 175 struct group *gr; 176 uid_t eid, rid; 177 char *login; 178 179 if (pw) { 180 (void)printf("uid\t%s\n", pw->pw_name); 181 (void)printf("groups\t"); 182 group(pw, 1); 183 } else { 184 if ((login = getlogin()) == NULL) 185 err(1, "getlogin"); 186 187 pw = getpwuid(rid = getuid()); 188 if (pw == NULL || strcmp(login, pw->pw_name)) 189 (void)printf("login\t%s\n", login); 190 if (pw) 191 (void)printf("uid\t%s\n", pw->pw_name); 192 else 193 (void)printf("uid\t%u\n", rid); 194 195 if ((eid = geteuid()) != rid) { 196 if ((pw = getpwuid(eid))) 197 (void)printf("euid\t%s\n", pw->pw_name); 198 else 199 (void)printf("euid\t%u\n", eid); 200 } 201 if ((rid = getgid()) != (eid = getegid())) { 202 if ((gr = getgrgid(rid))) 203 (void)printf("rgid\t%s\n", gr->gr_name); 204 else 205 (void)printf("rgid\t%u\n", rid); 206 } 207 (void)printf("groups\t"); 208 group(NULL, 1); 209 } 210 if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0') 211 (void)printf("class\t%s\n", pw->pw_class); 212 } 213 214 void 215 current(void) 216 { 217 struct group *gr; 218 struct passwd *pw; 219 int cnt, ngroups; 220 uid_t uid, euid; 221 gid_t groups[NGROUPS_MAX], gid, egid, lastgid; 222 char *prefix; 223 224 uid = getuid(); 225 (void)printf("uid=%u", uid); 226 if ((pw = getpwuid(uid))) 227 (void)printf("(%s)", pw->pw_name); 228 if ((euid = geteuid()) != uid) { 229 (void)printf(" euid=%u", euid); 230 if ((pw = getpwuid(euid))) 231 (void)printf("(%s)", pw->pw_name); 232 } 233 gid = getgid(); 234 (void)printf(" gid=%u", gid); 235 if ((gr = getgrgid(gid))) 236 (void)printf("(%s)", gr->gr_name); 237 if ((egid = getegid()) != gid) { 238 (void)printf(" egid=%u", egid); 239 if ((gr = getgrgid(egid))) 240 (void)printf("(%s)", gr->gr_name); 241 } 242 if ((ngroups = getgroups(NGROUPS_MAX, groups))) { 243 for (prefix = " groups=", lastgid = (gid_t)-1, cnt = 0; 244 cnt < ngroups; prefix = ", ", lastgid = gid) { 245 gid = groups[cnt++]; 246 if (lastgid == gid) 247 continue; 248 (void)printf("%s%u", prefix, gid); 249 if ((gr = getgrgid(gid))) 250 (void)printf("(%s)", gr->gr_name); 251 } 252 } 253 (void)printf("\n"); 254 } 255 256 void 257 user(struct passwd *pw) 258 { 259 gid_t gid, groups[NGROUPS_MAX + 1]; 260 int cnt, ngroups; 261 uid_t uid; 262 struct group *gr; 263 char *prefix; 264 265 uid = pw->pw_uid; 266 (void)printf("uid=%u(%s)", uid, pw->pw_name); 267 (void)printf(" gid=%u", pw->pw_gid); 268 if ((gr = getgrgid(pw->pw_gid))) 269 (void)printf("(%s)", gr->gr_name); 270 ngroups = NGROUPS_MAX + 1; 271 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 272 prefix = " groups="; 273 for (cnt = 0; cnt < ngroups;) { 274 gid = groups[cnt]; 275 (void)printf("%s%u", prefix, gid); 276 prefix = ", "; 277 if ((gr = getgrgid(gid))) 278 (void)printf("(%s)", gr->gr_name); 279 /* Skip same gid entries. */ 280 while (++cnt < ngroups && gid == groups[cnt]) 281 ; 282 } 283 (void)printf("\n"); 284 } 285 286 void 287 group(struct passwd *pw, int nflag) 288 { 289 int cnt, ngroups; 290 gid_t gid, groups[NGROUPS_MAX + 1]; 291 struct group *gr; 292 char *prefix; 293 294 if (pw) { 295 ngroups = NGROUPS_MAX + 1; 296 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 297 } else { 298 groups[0] = getgid(); 299 ngroups = getgroups(NGROUPS_MAX, groups + 1) + 1; 300 } 301 prefix = ""; 302 for (cnt = 0; cnt < ngroups;) { 303 gid = groups[cnt]; 304 if (nflag) { 305 if ((gr = getgrgid(gid))) 306 (void)printf("%s%s", prefix, gr->gr_name); 307 else 308 (void)printf("%s%u", prefix, gid); 309 } else { 310 (void)printf("%s%u", prefix, gid); 311 } 312 prefix = " "; 313 /* Skip same gid entries. */ 314 while (++cnt < ngroups && gid == groups[cnt]) 315 ; 316 } 317 (void)printf("\n"); 318 } 319 320 struct passwd * 321 who(char *u) 322 { 323 struct passwd *pw; 324 uid_t uid; 325 const char *errstr; 326 327 /* 328 * Translate user argument into a pw pointer. First, try to 329 * get it as specified. If that fails, try it as a number. 330 */ 331 if ((pw = getpwnam(u))) 332 return(pw); 333 uid = strtonum(u, 0, UID_MAX, &errstr); 334 if (!errstr && (pw = getpwuid(uid))) 335 return(pw); 336 errx(1, "%s: No such user", u); 337 /* NOTREACHED */ 338 } 339 340 void 341 usage(void) 342 { 343 if (strcmp(getprogname(), "groups") == 0) { 344 (void)fprintf(stderr, "usage: groups [user]\n"); 345 } else if (strcmp(getprogname(), "whoami") == 0) { 346 (void)fprintf(stderr, "usage: whoami\n"); 347 } else { 348 (void)fprintf(stderr, "usage: id [user]\n"); 349 (void)fprintf(stderr, " id -c [user]\n"); 350 (void)fprintf(stderr, " id -G [-n] [user]\n"); 351 (void)fprintf(stderr, " id -g [-nr] [user]\n"); 352 (void)fprintf(stderr, " id -p [user]\n"); 353 (void)fprintf(stderr, " id -u [-nr] [user]\n"); 354 } 355 exit(1); 356 } 357