Bug Summary

File:src/usr.bin/id/id.c
Warning:line 212, column 28
Although the value stored to 'eid' is used in the enclosing expression, the value is never actually read from 'eid'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name id.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/id/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/id/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/id/id.c
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(*__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
46void current(void);
47void pretty(struct passwd *);
48void group(struct passwd *, int);
49void usage(void);
50void user(struct passwd *);
51struct passwd *
52 who(char *);
53
54int
55main(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((void *)0)) == -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((void *)0);
137
138 if (cflag) {
139 if (pw == NULL((void *)0))
140 pw = getpwuid(getuid());
141 if (pw != NULL((void *)0) && pw->pw_class != NULL((void *)0) && *pw->pw_class != '\0')
142 (void)printf("%s\n", pw->pw_class);
143 else
144 (void)printf("%s\n", LOGIN_DEFCLASS"default");
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
183void
184pretty(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((void *)0))
196 err(1, "getlogin");
197
198 pw = getpwuid(rid = getuid());
199 if (pw == NULL((void *)0) || 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())) {
Although the value stored to 'eid' is used in the enclosing expression, the value is never actually read from 'eid'
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((void *)0), 1);
220 }
221 if (pw != NULL((void *)0) && pw->pw_class != NULL((void *)0) && *pw->pw_class != '\0')
222 (void)printf("class\t%s\n", pw->pw_class);
223}
224
225void
226current(void)
227{
228 struct group *gr;
229 struct passwd *pw;
230 int cnt, ngroups;
231 uid_t uid, euid;
232 gid_t groups[NGROUPS_MAX16], 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_MAX16, 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
267void
268user(struct passwd *pw)
269{
270 gid_t gid, groups[NGROUPS_MAX16 + 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_MAX16 + 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
297void
298group(struct passwd *pw, int nflag)
299{
300 int cnt, ngroups;
301 gid_t gid, groups[NGROUPS_MAX16 + 1];
302 struct group *gr;
303 char *prefix;
304
305 if (pw) {
306 ngroups = NGROUPS_MAX16 + 1;
307 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
308 } else {
309 groups[0] = getgid();
310 ngroups = getgroups(NGROUPS_MAX16, 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
331struct passwd *
332who(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(2147483647 *2U +1U), &errstr);
345 if (!errstr && (pw = getpwuid(uid)))
346 return(pw);
347 errx(1, "%s: No such user", u);
348 /* NOTREACHED */
349}
350
351void
352usage(void)
353{
354 if (strcmp(getprogname(), "groups") == 0) {
355 (void)fprintf(stderr(&__sF[2]), "usage: groups [user]\n");
356 } else if (strcmp(getprogname(), "whoami") == 0) {
357 (void)fprintf(stderr(&__sF[2]), "usage: whoami\n");
358 } else {
359 (void)fprintf(stderr(&__sF[2]), "usage: id [user]\n");
360 (void)fprintf(stderr(&__sF[2]), " id -c [user]\n");
361 (void)fprintf(stderr(&__sF[2]), " id -G [-n] [user]\n");
362 (void)fprintf(stderr(&__sF[2]), " id -g [-nr] [user]\n");
363 (void)fprintf(stderr(&__sF[2]), " id -p [user]\n");
364 (void)fprintf(stderr(&__sF[2]), " id -R\n");
365 (void)fprintf(stderr(&__sF[2]), " id -u [-nr] [user]\n");
366 }
367 exit(1);
368}