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