1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | #include <sys/wait.h> |
24 | |
25 | #include <err.h> |
26 | #include <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 | |
38 | void notify(struct passwd *, int, int); |
39 | void sanitise_stdfd(void); |
40 | FILE *runsendmail(struct passwd *, int *); |
41 | __dead void usage(void); |
42 | |
43 | void |
44 | sanitise_stdfd(void) |
45 | { |
46 | int nullfd, dupfd; |
47 | |
48 | if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { |
49 | fprintf(stderr, "Couldn't open /dev/null: %s\n", |
50 | strerror(errno)); |
51 | exit(1); |
52 | } |
53 | while (++dupfd <= STDERR_FILENO) { |
54 | |
55 | if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { |
56 | if (dup2(nullfd, dupfd) == -1) { |
57 | fprintf(stderr, "dup2: %s\n", strerror(errno)); |
58 | exit(1); |
59 | } |
60 | } |
61 | } |
62 | if (nullfd > STDERR_FILENO) |
63 | close(nullfd); |
64 | } |
65 | |
66 | int |
67 | main(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) == -1) |
| 1 | Assuming the condition is false | |
|
| |
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 = 0; |
91 | if ((limit = (int)strtol(optarg, NULL, 10)) == 0) |
92 | errno = ERANGE; |
93 | if (errno) { |
94 | warn("key limit"); |
95 | usage(); |
96 | } |
97 | break; |
98 | default: |
99 | usage(); |
100 | } |
101 | |
102 | if (iflag) { |
| |
103 | if (pledge("stdio rpath wpath flock getpw", NULL) == -1) |
104 | err(1, "pledge"); |
105 | } |
106 | |
107 | |
108 | if (iflag && fcntl(STDOUT_FILENO, F_GETFL) == -1 && errno == EBADF) |
109 | exit(1); |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | sanitise_stdfd(); |
116 | |
117 | if (argc - optind > 0) |
| 6 | | Assuming the condition is false | |
|
| |
118 | usage(); |
119 | |
120 | |
121 | (void)memset(&key, 0, sizeof(key)); |
122 | |
123 | left = 0; |
124 | if (aflag) { |
| |
125 | while ((ch = skeygetnext(&key)) == 0) { |
126 | left = key.n - 1; |
127 | if ((pw = getpwnam(key.logname)) == NULL) |
128 | continue; |
129 | if (left >= limit) |
130 | continue; |
131 | (void)fclose(key.keyfile); |
132 | key.keyfile = NULL; |
133 | notify(pw, left, iflag); |
134 | } |
135 | if (ch == -1) |
136 | errx(-1, "cannot open %s", _PATH_SKEYDIR); |
137 | } else { |
138 | if ((pw = getpwuid(getuid())) == NULL) |
| 9 | | Assuming the condition is false | |
|
| |
139 | errx(1, "no passwd entry for uid %u", getuid()); |
140 | if ((name = strdup(pw->pw_name)) == NULL) |
| 11 | | Assuming the condition is false | |
|
| |
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: |
146 | left = key.n - 1; |
147 | break; |
148 | case -1: |
149 | errx(1, "cannot open %s/%s", _PATH_SKEYDIR, |
150 | name); |
151 | break; |
152 | case 1: |
153 | errx(1, "user %s is not listed in %s", name, |
154 | _PATH_SKEYDIR); |
155 | } |
156 | (void)fclose(key.keyfile); |
157 | |
158 | if (left < limit) |
| |
159 | notify(pw, left, iflag); |
| |
160 | } |
161 | |
162 | exit(0); |
163 | } |
164 | |
165 | void |
166 | notify(struct passwd *pw, int seq, int interactive) |
167 | { |
168 | static char hostname[HOST_NAME_MAX+1]; |
169 | pid_t pid; |
| 16 | | 'pid' declared without an initial value | |
|
170 | FILE *out; |
171 | |
172 | |
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) |
| |
177 | out = stdout; |
178 | else |
179 | out = runsendmail(pw, &pid); |
| |
| 23 | | Returning from 'runsendmail' | |
|
180 | |
181 | if (!interactive) |
| |
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) |
| |
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\ |
190 | Your S/Key sequence number is now %d. When it reaches zero\n\ |
191 | you will no longer be able to use S/Key to log into the system.\n\n", |
192 | pw->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\ |
197 | At this point you can no longer use S/Key to log into the system.\n\n", |
198 | pw->pw_name, hostname); |
199 | (void)fprintf(out, |
200 | "Type \"skeyinit -s\" to reinitialize your sequence number.\n\n"); |
201 | |
202 | if (!interactive) { |
| |
203 | (void)fclose(out); |
204 | (void)waitpid(pid, NULL, 0); |
| 27 | | 1st function call argument is an uninitialized value |
|
205 | } |
206 | } |
207 | |
208 | FILE * |
209 | runsendmail(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 | |
|
| |
216 | return(NULL); |
| 22 | | Returning without writing to '*pidp' | |
|
217 | |
218 | switch (pid = fork()) { |
219 | case -1: |
220 | (void)close(pfd[0]); |
221 | (void)close(pfd[1]); |
222 | return(NULL); |
223 | case 0: |
224 | (void)close(pfd[1]); |
225 | (void)dup2(pfd[0], STDIN_FILENO); |
226 | (void)close(pfd[0]); |
227 | |
228 | |
229 | if (getuid() == 0 && |
230 | setusercontext(NULL, pw, pw->pw_uid, LOGIN_SETALL) != 0) { |
231 | warn("cannot set user context"); |
232 | _exit(127); |
233 | } |
234 | |
235 | execl(_PATH_SENDMAIL, "sendmail", "-t", (char *)NULL); |
236 | warn("cannot run \"%s -t\"", _PATH_SENDMAIL); |
237 | _exit(127); |
238 | } |
239 | |
240 | |
241 | *pidp = pid; |
242 | fp = fdopen(pfd[1], "w"); |
243 | (void)close(pfd[0]); |
244 | |
245 | return(fp); |
246 | } |
247 | |
248 | __dead void |
249 | usage(void) |
250 | { |
251 | extern char *__progname; |
252 | |
253 | (void)fprintf(stderr, "usage: %s [-ai] [-l limit]\n", |
254 | __progname); |
255 | exit(1); |
256 | } |