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