Bug Summary

File:src/usr.bin/skeyaudit/skeyaudit.c
Warning:line 204, column 9
1st function call argument is an uninitialized value

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 skeyaudit.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/skeyaudit/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/skeyaudit/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/skeyaudit/skeyaudit.c
1/* $OpenBSD: skeyaudit.c,v 1.29 2019/06/28 13:35:03 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1997, 2000, 2003 Todd C. Miller <millert@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#include <sys/wait.h>
24
25#include <err.h>
26#include <errno(*__errno()).h>
27#include <fcntl.h>
28#include <limits.h>
29#include <login_cap.h>
30#include <paths.h>
31#include <pwd.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <skey.h>
37
38void notify(struct passwd *, int, int);
39void sanitise_stdfd(void);
40FILE *runsendmail(struct passwd *, int *);
41__dead__attribute__((__noreturn__)) void usage(void);
42
43void
44sanitise_stdfd(void)
45{
46 int nullfd, dupfd;
47
48 if ((nullfd = dupfd = open(_PATH_DEVNULL"/dev/null", O_RDWR0x0002)) == -1) {
49 fprintf(stderr(&__sF[2]), "Couldn't open /dev/null: %s\n",
50 strerror(errno(*__errno())));
51 exit(1);
52 }
53 while (++dupfd <= STDERR_FILENO2) {
54 /* Only populate closed fds. */
55 if (fcntl(dupfd, F_GETFL3) == -1 && errno(*__errno()) == EBADF9) {
56 if (dup2(nullfd, dupfd) == -1) {
57 fprintf(stderr(&__sF[2]), "dup2: %s\n", strerror(errno(*__errno())));
58 exit(1);
59 }
60 }
61 }
62 if (nullfd > STDERR_FILENO2)
63 close(nullfd);
64}
65
66int
67main(int argc, char **argv)
68{
69 struct passwd *pw;
70 struct skey key;
71 char *name;
72 int ch, left, aflag, iflag, limit;
73
74 if (pledge("stdio rpath wpath flock getpw proc exec id", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
75 err(1, "pledge");
76
77 aflag = iflag = 0;
78 limit = 12;
79 while ((ch = getopt(argc, argv, "ail:")) != -1)
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 102
80 switch(ch) {
81 case 'a':
82 if (getuid() != 0)
83 errx(1, "only root may use the -a flag");
84 aflag = 1;
85 break;
86 case 'i':
87 iflag = 1;
88 break;
89 case 'l':
90 errno(*__errno()) = 0;
91 if ((limit = (int)strtol(optarg, NULL((void *)0), 10)) == 0)
92 errno(*__errno()) = ERANGE34;
93 if (errno(*__errno())) {
94 warn("key limit");
95 usage();
96 }
97 break;
98 default:
99 usage();
100 }
101
102 if (iflag
4.1
'iflag' is 0
) {
5
Taking false branch
103 if (pledge("stdio rpath wpath flock getpw", NULL((void *)0)) == -1)
104 err(1, "pledge");
105 }
106
107 /* If we are in interactive mode, STDOUT_FILENO *must* be open. */
108 if (iflag
5.1
'iflag' is 0
&& fcntl(STDOUT_FILENO1, F_GETFL3) == -1 && errno(*__errno()) == EBADF9)
109 exit(1);
110
111 /*
112 * Make sure STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO are open.
113 * If not, open /dev/null in their place or bail.
114 */
115 sanitise_stdfd();
116
117 if (argc - optind > 0)
6
Assuming the condition is false
7
Taking false branch
118 usage();
119
120 /* Need key.keyfile zero'd at the very least */
121 (void)memset(&key, 0, sizeof(key));
122
123 left = 0;
124 if (aflag
7.1
'aflag' is 0
) {
8
Taking false branch
125 while ((ch = skeygetnext(&key)) == 0) {
126 left = key.n - 1;
127 if ((pw = getpwnam(key.logname)) == NULL((void *)0))
128 continue;
129 if (left >= limit)
130 continue;
131 (void)fclose(key.keyfile);
132 key.keyfile = NULL((void *)0);
133 notify(pw, left, iflag);
134 }
135 if (ch == -1)
136 errx(-1, "cannot open %s", _PATH_SKEYDIR"/etc/skey");
137 } else {
138 if ((pw = getpwuid(getuid())) == NULL((void *)0))
9
Assuming the condition is false
10
Taking false branch
139 errx(1, "no passwd entry for uid %u", getuid());
140 if ((name = strdup(pw->pw_name)) == NULL((void *)0))
11
Assuming the condition is false
12
Taking false branch
141 err(1, "cannot allocate memory");
142 sevenbit(name);
143
144 switch (skeylookup(&key, name)) {
13
'Default' branch taken. Execution continues on line 156
145 case 0: /* Success! */
146 left = key.n - 1;
147 break;
148 case -1: /* File error */
149 errx(1, "cannot open %s/%s", _PATH_SKEYDIR"/etc/skey",
150 name);
151 break;
152 case 1: /* Unknown user */
153 errx(1, "user %s is not listed in %s", name,
154 _PATH_SKEYDIR"/etc/skey");
155 }
156 (void)fclose(key.keyfile);
157
158 if (left
13.1
'left' is < 'limit'
< limit)
14
Taking true branch
159 notify(pw, left, iflag);
15
Calling 'notify'
160 }
161
162 exit(0);
163}
164
165void
166notify(struct passwd *pw, int seq, int interactive)
167{
168 static char hostname[HOST_NAME_MAX255+1];
169 pid_t pid;
16
'pid' declared without an initial value
170 FILE *out;
171
172 /* Only set this once */
173 if (hostname[0] == '\0' && gethostname(hostname, sizeof(hostname)) == -1)
17
Assuming the condition is false
174 strlcpy(hostname, "unknown", sizeof(hostname));
175
176 if (interactive
17.1
'interactive' is 0
)
18
Taking false branch
177 out = stdout(&__sF[1]);
178 else
179 out = runsendmail(pw, &pid);
19
Calling 'runsendmail'
23
Returning from 'runsendmail'
180
181 if (!interactive
23.1
'interactive' is 0
)
24
Taking true branch
182 (void)fprintf(out,
183 "Auto-Submitted: auto-generated\n"
184 "To: %s\nSubject: IMPORTANT action required\n", pw->pw_name);
185
186 if (seq
24.1
'seq' is 0
)
25
Taking false branch
187 (void)fprintf(out,
188"\nYou are nearing the end of your current S/Key sequence for account\n\
189%s on system %s.\n\n\
190Your S/Key sequence number is now %d. When it reaches zero\n\
191you will no longer be able to use S/Key to log into the system.\n\n",
192pw->pw_name, hostname, seq);
193 else
194 (void)fprintf(out,
195"\nYou are at the end of your current S/Key sequence for account\n\
196%s on system %s.\n\n\
197At this point you can no longer use S/Key to log into the system.\n\n",
198pw->pw_name, hostname);
199 (void)fprintf(out,
200"Type \"skeyinit -s\" to reinitialize your sequence number.\n\n");
201
202 if (!interactive
25.1
'interactive' is 0
) {
26
Taking true branch
203 (void)fclose(out);
204 (void)waitpid(pid, NULL((void *)0), 0);
27
1st function call argument is an uninitialized value
205 }
206}
207
208FILE *
209runsendmail(struct passwd *pw, pid_t *pidp)
210{
211 FILE *fp;
212 int pfd[2];
213 pid_t pid;
214
215 if (pipe(pfd) == -1)
20
Assuming the condition is true
21
Taking true branch
216 return(NULL((void *)0));
22
Returning without writing to '*pidp'
217
218 switch (pid = fork()) {
219 case -1: /* fork(2) failed */
220 (void)close(pfd[0]);
221 (void)close(pfd[1]);
222 return(NULL((void *)0));
223 case 0: /* In child */
224 (void)close(pfd[1]);
225 (void)dup2(pfd[0], STDIN_FILENO0);
226 (void)close(pfd[0]);
227
228 /* Run sendmail as target user not root */
229 if (getuid() == 0 &&
230 setusercontext(NULL((void *)0), pw, pw->pw_uid, LOGIN_SETALL0x00ff) != 0) {
231 warn("cannot set user context");
232 _exit(127);
233 }
234
235 execl(_PATH_SENDMAIL"/usr/sbin/sendmail", "sendmail", "-t", (char *)NULL((void *)0));
236 warn("cannot run \"%s -t\"", _PATH_SENDMAIL"/usr/sbin/sendmail");
237 _exit(127);
238 }
239
240 /* In parent */
241 *pidp = pid;
242 fp = fdopen(pfd[1], "w");
243 (void)close(pfd[0]);
244
245 return(fp);
246}
247
248__dead__attribute__((__noreturn__)) void
249usage(void)
250{
251 extern char *__progname;
252
253 (void)fprintf(stderr(&__sF[2]), "usage: %s [-ai] [-l limit]\n",
254 __progname);
255 exit(1);
256}