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
main(int argc,char * argv[])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
pretty(struct passwd * pw)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
current(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
user(struct passwd * pw)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
group(struct passwd * pw,int nflag)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 *
who(char * u)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
usage(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