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