1 /* $OpenBSD: id.c,v 1.29 2022/12/04 23:50:48 cheloha 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 default: 111 usage(); 112 } 113 argc -= optind; 114 argv += optind; 115 116 switch (cflag + Gflag + gflag + pflag + Rflag + uflag) { 117 case 1: 118 break; 119 case 0: 120 if (!nflag && !rflag) 121 break; 122 /* FALLTHROUGH */ 123 default: 124 usage(); 125 } 126 127 if (strcmp(opts, "") != 0 && argc > 1) 128 usage(); 129 130 if (Rflag) { 131 printf("%d\n", getrtable()); 132 exit(0); 133 } 134 135 pw = *argv ? who(*argv) : NULL; 136 137 if (cflag) { 138 if (pw == NULL) 139 pw = getpwuid(getuid()); 140 if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0') 141 (void)printf("%s\n", pw->pw_class); 142 else 143 (void)printf("%s\n", LOGIN_DEFCLASS); 144 exit(0); 145 } 146 147 if (gflag) { 148 gid = pw ? pw->pw_gid : rflag ? getgid() : getegid(); 149 if (nflag && (gr = getgrgid(gid))) 150 (void)printf("%s\n", gr->gr_name); 151 else 152 (void)printf("%u\n", gid); 153 exit(0); 154 } 155 156 if (uflag) { 157 uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); 158 if (nflag && (pw = getpwuid(uid))) 159 (void)printf("%s\n", pw->pw_name); 160 else 161 (void)printf("%u\n", uid); 162 exit(0); 163 } 164 165 if (Gflag) { 166 group(pw, nflag); 167 exit(0); 168 } 169 170 if (pflag) { 171 pretty(pw); 172 exit(0); 173 } 174 175 if (pw) 176 user(pw); 177 else 178 current(); 179 exit(0); 180 } 181 182 void 183 pretty(struct passwd *pw) 184 { 185 struct group *gr; 186 uid_t eid, rid; 187 char *login; 188 189 if (pw) { 190 (void)printf("uid\t%s\n", pw->pw_name); 191 (void)printf("groups\t"); 192 group(pw, 1); 193 } else { 194 if ((login = getlogin()) == NULL) 195 err(1, "getlogin"); 196 197 pw = getpwuid(rid = getuid()); 198 if (pw == NULL || strcmp(login, pw->pw_name)) 199 (void)printf("login\t%s\n", login); 200 if (pw) 201 (void)printf("uid\t%s\n", pw->pw_name); 202 else 203 (void)printf("uid\t%u\n", rid); 204 205 if ((eid = geteuid()) != rid) { 206 if ((pw = getpwuid(eid))) 207 (void)printf("euid\t%s\n", pw->pw_name); 208 else 209 (void)printf("euid\t%u\n", eid); 210 } 211 if ((rid = getgid()) != (eid = getegid())) { 212 if ((gr = getgrgid(rid))) 213 (void)printf("rgid\t%s\n", gr->gr_name); 214 else 215 (void)printf("rgid\t%u\n", rid); 216 } 217 (void)printf("groups\t"); 218 group(NULL, 1); 219 } 220 if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0') 221 (void)printf("class\t%s\n", pw->pw_class); 222 } 223 224 void 225 current(void) 226 { 227 struct group *gr; 228 struct passwd *pw; 229 int cnt, ngroups; 230 uid_t uid, euid; 231 gid_t groups[NGROUPS_MAX], gid, egid, lastgid; 232 char *prefix; 233 234 uid = getuid(); 235 (void)printf("uid=%u", uid); 236 if ((pw = getpwuid(uid))) 237 (void)printf("(%s)", pw->pw_name); 238 if ((euid = geteuid()) != uid) { 239 (void)printf(" euid=%u", euid); 240 if ((pw = getpwuid(euid))) 241 (void)printf("(%s)", pw->pw_name); 242 } 243 gid = getgid(); 244 (void)printf(" gid=%u", gid); 245 if ((gr = getgrgid(gid))) 246 (void)printf("(%s)", gr->gr_name); 247 if ((egid = getegid()) != gid) { 248 (void)printf(" egid=%u", egid); 249 if ((gr = getgrgid(egid))) 250 (void)printf("(%s)", gr->gr_name); 251 } 252 if ((ngroups = getgroups(NGROUPS_MAX, groups))) { 253 for (prefix = " groups=", lastgid = (gid_t)-1, cnt = 0; 254 cnt < ngroups; prefix = ", ", lastgid = gid) { 255 gid = groups[cnt++]; 256 if (lastgid == gid) 257 continue; 258 (void)printf("%s%u", prefix, gid); 259 if ((gr = getgrgid(gid))) 260 (void)printf("(%s)", gr->gr_name); 261 } 262 } 263 (void)printf("\n"); 264 } 265 266 void 267 user(struct passwd *pw) 268 { 269 gid_t gid, groups[NGROUPS_MAX + 1]; 270 int cnt, ngroups; 271 uid_t uid; 272 struct group *gr; 273 char *prefix; 274 275 uid = pw->pw_uid; 276 (void)printf("uid=%u(%s)", uid, pw->pw_name); 277 (void)printf(" gid=%u", pw->pw_gid); 278 if ((gr = getgrgid(pw->pw_gid))) 279 (void)printf("(%s)", gr->gr_name); 280 ngroups = NGROUPS_MAX + 1; 281 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 282 prefix = " groups="; 283 for (cnt = 0; cnt < ngroups;) { 284 gid = groups[cnt]; 285 (void)printf("%s%u", prefix, gid); 286 prefix = ", "; 287 if ((gr = getgrgid(gid))) 288 (void)printf("(%s)", gr->gr_name); 289 /* Skip same gid entries. */ 290 while (++cnt < ngroups && gid == groups[cnt]) 291 ; 292 } 293 (void)printf("\n"); 294 } 295 296 void 297 group(struct passwd *pw, int nflag) 298 { 299 int cnt, ngroups; 300 gid_t gid, groups[NGROUPS_MAX + 1]; 301 struct group *gr; 302 char *prefix; 303 304 if (pw) { 305 ngroups = NGROUPS_MAX + 1; 306 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); 307 } else { 308 groups[0] = getgid(); 309 ngroups = getgroups(NGROUPS_MAX, groups + 1) + 1; 310 } 311 prefix = ""; 312 for (cnt = 0; cnt < ngroups;) { 313 gid = groups[cnt]; 314 if (nflag) { 315 if ((gr = getgrgid(gid))) 316 (void)printf("%s%s", prefix, gr->gr_name); 317 else 318 (void)printf("%s%u", prefix, gid); 319 } else { 320 (void)printf("%s%u", prefix, gid); 321 } 322 prefix = " "; 323 /* Skip same gid entries. */ 324 while (++cnt < ngroups && gid == groups[cnt]) 325 ; 326 } 327 (void)printf("\n"); 328 } 329 330 struct passwd * 331 who(char *u) 332 { 333 struct passwd *pw; 334 uid_t uid; 335 const char *errstr; 336 337 /* 338 * Translate user argument into a pw pointer. First, try to 339 * get it as specified. If that fails, try it as a number. 340 */ 341 if ((pw = getpwnam(u))) 342 return(pw); 343 uid = strtonum(u, 0, UID_MAX, &errstr); 344 if (!errstr && (pw = getpwuid(uid))) 345 return(pw); 346 errx(1, "%s: No such user", u); 347 /* NOTREACHED */ 348 } 349 350 void 351 usage(void) 352 { 353 if (strcmp(getprogname(), "groups") == 0) { 354 (void)fprintf(stderr, "usage: groups [user]\n"); 355 } else if (strcmp(getprogname(), "whoami") == 0) { 356 (void)fprintf(stderr, "usage: whoami\n"); 357 } else { 358 (void)fprintf(stderr, "usage: id [user]\n"); 359 (void)fprintf(stderr, " id -c [user]\n"); 360 (void)fprintf(stderr, " id -G [-n] [user]\n"); 361 (void)fprintf(stderr, " id -g [-nr] [user]\n"); 362 (void)fprintf(stderr, " id -p [user]\n"); 363 (void)fprintf(stderr, " id -R\n"); 364 (void)fprintf(stderr, " id -u [-nr] [user]\n"); 365 } 366 exit(1); 367 } 368