Bug Summary

File:src/sbin/isakmpd/isakmpd.c
Warning:line 221, column 2
Value stored to 'argv' is never read

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 isakmpd.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/sbin/isakmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/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/sbin/isakmpd/isakmpd.c
1/* $OpenBSD: isakmpd.c,v 1.107 2018/01/15 09:54:48 mpi Exp $ */
2/* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */
3
4/*
5 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved.
6 * Copyright (c) 1999, 2000 Angelos D. Keromytis. All rights reserved.
7 * Copyright (c) 1999, 2000, 2001 Håkan Olsson. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * This code was written under funding by Ericsson Radio Systems.
32 */
33
34#include <errno(*__errno()).h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <signal.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h>
42#include <netdb.h>
43#include <unistd.h>
44#include <fcntl.h>
45#include <paths.h>
46
47#include "app.h"
48#include "conf.h"
49#include "connection.h"
50#include "init.h"
51#include "libcrypto.h"
52#include "log.h"
53#include "message.h"
54#include "monitor.h"
55#include "nat_traversal.h"
56#include "sa.h"
57#include "timer.h"
58#include "transport.h"
59#include "udp.h"
60#include "udp_encap.h"
61#include "ui.h"
62#include "util.h"
63#include "cert.h"
64
65#include "policy.h"
66
67static void usage(void);
68
69/*
70 * Set if -d is given, currently just for running in the foreground and log
71 * to stderr instead of syslog.
72 */
73int debug = 0;
74
75/* Set when no policy file shall be used. */
76int acquire_only = 0;
77
78/* Set when SAs shall be deleted on shutdown. */
79int delete_sas = 1;
80
81/*
82 * If we receive a SIGHUP signal, this flag gets set to show we need to
83 * reconfigure ASAP.
84 */
85volatile sig_atomic_t sighupped = 0;
86
87/*
88 * If we receive a USR1 signal, this flag gets set to show we need to dump
89 * a report over our internal state ASAP. The file to report to is settable
90 * via the -R parameter.
91 */
92volatile sig_atomic_t sigusr1ed = 0;
93static char *report_file = "/var/run/isakmpd.report";
94
95/*
96 * If we receive a TERM signal, perform a "clean shutdown" of the daemon.
97 * This includes to send DELETE notifications for all our active SAs.
98 * Also on recv of an INT signal (Ctrl-C out of an '-d' session, typically).
99 */
100volatile sig_atomic_t sigtermed = 0;
101void daemon_shutdown_now(int);
102void set_slave_signals(void);
103void sanitise_stdfd(void);
104
105/* The default path of the PID file. */
106char *pid_file = "/var/run/isakmpd.pid";
107
108/* The path of the IKE packet capture log file. */
109static char *pcap_file = 0;
110
111static void
112usage(void)
113{
114 extern char *__progname;
115
116 fprintf(stderr(&__sF[2]),
117 "usage: %s [-46adKLnSTv] [-c config-file] [-D class=level] [-f fifo]\n"
118 " [-i pid-file] [-l packetlog-file] [-N udpencap-port]\n"
119 " [-p listen-port] [-R report-file]\n",
120 __progname);
121 exit(1);
122}
123
124static void
125parse_args(int argc, char *argv[])
126{
127 int ch;
128 int cls, level;
129 int do_packetlog = 0;
130
131 while ((ch = getopt(argc, argv, "46ac:dD:f:i:KnN:p:Ll:R:STv")) != -1) {
132 switch (ch) {
133 case '4':
134 bind_family |= BIND_FAMILY_INET40x0001;
135 break;
136
137 case '6':
138 bind_family |= BIND_FAMILY_INET60x0002;
139 break;
140
141 case 'a':
142 acquire_only = 1;
143 break;
144
145 case 'c':
146 conf_path = optarg;
147 break;
148
149 case 'd':
150 debug++;
151 break;
152
153 case 'D':
154 if (sscanf(optarg, "%d=%d", &cls, &level) != 2) {
155 if (sscanf(optarg, "A=%d", &level) == 1) {
156 for (cls = 0; cls < LOG_ENDCLASS;
157 cls++)
158 log_debug_cmd(cls, level);
159 } else
160 log_print("parse_args: -D argument "
161 "unparseable: %s", optarg);
162 } else
163 log_debug_cmd(cls, level);
164 break;
165
166 case 'f':
167 ui_fifo = optarg;
168 break;
169
170 case 'i':
171 pid_file = optarg;
172 break;
173
174 case 'K':
175 ignore_policy++;
176 break;
177
178 case 'n':
179 app_none++;
180 break;
181
182 case 'N':
183 udp_encap_default_port = optarg;
184 break;
185
186 case 'p':
187 udp_default_port = optarg;
188 break;
189
190 case 'l':
191 pcap_file = optarg;
192 /* FALLTHROUGH */
193
194 case 'L':
195 do_packetlog++;
196 break;
197
198 case 'R':
199 report_file = optarg;
200 break;
201
202 case 'S':
203 delete_sas = 0;
204 ui_daemon_passive = 1;
205 break;
206
207 case 'T':
208 disable_nat_t = 1;
209 break;
210
211 case 'v':
212 verbose_logging = 1;
213 break;
214
215 case '?':
216 default:
217 usage();
218 }
219 }
220 argc -= optind;
221 argv += optind;
Value stored to 'argv' is never read
222
223 if (argc > 0)
224 usage();
225
226 if (do_packetlog && !pcap_file)
227 pcap_file = PCAP_FILE_DEFAULT"/var/run/isakmpd.pcap";
228}
229
230/* ARGSUSED */
231static void
232sighup(int sig)
233{
234 sighupped = 1;
235}
236
237/* Report internal state on SIGUSR1. */
238static void
239report(void)
240{
241 FILE *rfp, *old;
242 mode_t old_umask;
243
244 old_umask = umask(S_IRWXG0000070 | S_IRWXO0000007);
245 rfp = monitor_fopen(report_file, "w");
246 umask(old_umask);
247
248 if (!rfp) {
249 log_error("report: fopen (\"%s\", \"w\") failed", report_file);
250 return;
251 }
252 /* Divert the log channel to the report file during the report. */
253 old = log_current();
254 log_to(rfp);
255 ui_report("r");
256 log_to(old);
257 fclose(rfp);
258}
259
260static void
261sigusr1(int sig)
262{
263 sigusr1ed = 1;
264}
265
266static int
267phase2_sa_check(struct sa *sa, void *arg)
268{
269 return sa->phase == 2;
270}
271
272static int
273phase1_sa_check(struct sa *sa, void *arg)
274{
275 return sa->phase == 1;
276}
277
278void
279set_slave_signals(void)
280{
281 int n;
282
283 for (n = 1; n < _NSIG33; n++)
284 signal(n, SIG_DFL(void (*)(int))0);
285
286 /*
287 * Do a clean daemon shutdown on TERM/INT. These signals must be
288 * initialized before monitor_init(). INT is only used with '-d'.
289 */
290 signal(SIGTERM15, daemon_shutdown_now);
291 if (debug == 1) /* i.e '-dd' will skip this. */
292 signal(SIGINT2, daemon_shutdown_now);
293
294 /* Reinitialize on HUP reception. */
295 signal(SIGHUP1, sighup);
296
297 /* Report state on USR1 reception. */
298 signal(SIGUSR130, sigusr1);
299}
300
301static void
302daemon_shutdown(void)
303{
304 /* Perform a (protocol-wise) clean shutdown of the daemon. */
305 struct sa *sa;
306
307 if (sigtermed == 1) {
308 log_print("isakmpd: shutting down...");
309
310 if (delete_sas &&
311 strncmp("no", conf_get_str("General", "Delete-SAs"), 2)) {
312 /*
313 * Delete all active SAs. First IPsec SAs, then
314 * ISAKMPD. Each DELETE is another (outgoing) message.
315 */
316 while ((sa = sa_find(phase2_sa_check, NULL((void*)0))))
317 sa_delete(sa, 1);
318
319 while ((sa = sa_find(phase1_sa_check, NULL((void*)0))))
320 sa_delete(sa, 1);
321 }
322
323 /* We only want to do this once. */
324 sigtermed++;
325 }
326 if (transport_prio_sendqs_empty()) {
327 /*
328 * When the prioritized transport sendq:s are empty, i.e all
329 * the DELETE notifications have been sent, we can shutdown.
330 */
331
332 log_packet_stop();
333 log_print("isakmpd: exit");
334 exit(0);
335 }
336}
337
338/* Called on SIGTERM, SIGINT or by ui_shutdown_daemon(). */
339/* ARGSUSED */
340void
341daemon_shutdown_now(int sig)
342{
343 sigtermed = 1;
344}
345
346/* Write pid file. */
347static void
348write_pid_file(void)
349{
350 FILE *fp;
351
352 unlink(pid_file);
353
354 fp = fopen(pid_file, "w");
355 if (fp != NULL((void*)0)) {
356 if (fprintf(fp, "%ld\n", (long) getpid()) < 0)
357 log_error("write_pid_file: failed to write PID to "
358 "\"%.100s\"", pid_file);
359 fclose(fp);
360 } else
361 log_fatal("write_pid_file: fopen (\"%.100s\", \"w\") failed",
362 pid_file);
363}
364
365void
366sanitise_stdfd(void)
367{
368 int nullfd, dupfd;
369
370 if ((nullfd = dupfd = open(_PATH_DEVNULL"/dev/null", O_RDWR0x0002)) == -1) {
371 fprintf(stderr(&__sF[2]), "Couldn't open /dev/null: %s\n",
372 strerror(errno(*__errno())));
373 exit(1);
374 }
375 while (++dupfd <= STDERR_FILENO2) {
376 /* Only populate closed fds */
377 if (fcntl(dupfd, F_GETFL3) == -1 && errno(*__errno()) == EBADF9) {
378 if (dup2(nullfd, dupfd) == -1) {
379 fprintf(stderr(&__sF[2]), "dup2: %s\n", strerror(errno(*__errno())));
380 exit(1);
381 }
382 }
383 }
384 if (nullfd > STDERR_FILENO2)
385 close(nullfd);
386}
387
388int
389main(int argc, char *argv[])
390{
391 fd_set *rfds, *wfds;
392 int n, m;
393 size_t mask_size;
394 struct timespec ts, *timeout;
395
396 closefrom(STDERR_FILENO2 + 1);
397
398 /*
399 * Make sure init() won't alloc fd 0, 1 or 2, as daemon() will close
400 * them.
401 */
402 sanitise_stdfd();
403
404 /* Log cmd line parsing and initialization errors to stderr. */
405 log_to(stderr(&__sF[2]));
406 parse_args(argc, argv);
407 log_init(debug);
408 log_print("isakmpd: starting");
409
410 /* Open protocols and services databases. */
411 setprotoent(1);
412 setservent(1);
413
414 /* Open command fifo */
415 ui_init();
416
417 set_slave_signals();
418 /* Daemonize before forking unpriv'ed child */
419 if (!debug)
420 if (daemon(0, 0))
421 log_fatal("main: daemon (0, 0) failed");
422
423 /* Set timezone before priv'separation */
424 tzset();
425
426 write_pid_file();
427
428 if (monitor_init(debug)) {
429 /* The parent, with privileges enters infinite monitor loop. */
430 monitor_loop(debug);
431 exit(0); /* Never reached. */
432 }
433 /* Child process only from this point on, no privileges left. */
434
435 init();
436
437 /* If we wanted IKE packet capture to file, initialize it now. */
438 if (pcap_file != 0)
439 log_packet_init(pcap_file);
440
441 /* Allocate the file descriptor sets just big enough. */
442 n = getdtablesize();
443 mask_size = howmany(n, NFDBITS)(((n) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned
)(sizeof(__fd_mask) * 8))))
* sizeof(fd_mask__fd_mask);
444 rfds = malloc(mask_size);
445 if (!rfds)
446 log_fatal("main: malloc (%lu) failed",
447 (unsigned long)mask_size);
448 wfds = malloc(mask_size);
449 if (!wfds)
450 log_fatal("main: malloc (%lu) failed",
451 (unsigned long)mask_size);
452
453 monitor_init_done();
454
455 while (1) {
456 /* If someone has sent SIGHUP to us, reconfigure. */
457 if (sighupped) {
458 sighupped = 0;
459 log_print("SIGHUP received");
460 reinit();
461 }
462 /* and if someone sent SIGUSR1, do a state report. */
463 if (sigusr1ed) {
464 sigusr1ed = 0;
465 log_print("SIGUSR1 received");
466 report();
467 }
468 /*
469 * and if someone set 'sigtermed' (SIGTERM, SIGINT or via the
470 * UI), this indicates we should start a controlled shutdown
471 * of the daemon.
472 *
473 * Note: Since _one_ message is sent per iteration of this
474 * enclosing while-loop, and we want to send a number of
475 * DELETE notifications, we must loop atleast this number of
476 * times. The daemon_shutdown() function starts by queueing
477 * the DELETEs, all other calls just increments the
478 * 'sigtermed' variable until it reaches a "safe" value, and
479 * the daemon exits.
480 */
481 if (sigtermed)
482 daemon_shutdown();
483
484 /* Setup the descriptors to look for incoming messages at. */
485 bzero(rfds, mask_size);
486 n = transport_fd_set(rfds);
487 FD_SET(ui_socket, rfds)__fd_set((ui_socket), (rfds));
488 if (ui_socket + 1 > n)
489 n = ui_socket + 1;
490
491 /*
492 * XXX Some day we might want to deal with an abstract
493 * application class instead, with many instantiations
494 * possible.
495 */
496 if (!app_none && app_socket >= 0) {
497 FD_SET(app_socket, rfds)__fd_set((app_socket), (rfds));
498 if (app_socket + 1 > n)
499 n = app_socket + 1;
500 }
501 /* Setup the descriptors that have pending messages to send. */
502 bzero(wfds, mask_size);
503 m = transport_pending_wfd_set(wfds);
504 if (m > n)
505 n = m;
506
507 /* Find out when the next timed event is. */
508 timeout = &ts;
509 timer_next_event(&timeout);
510
511 n = pselect(n, rfds, wfds, NULL((void*)0), timeout, NULL((void*)0));
512 if (n == -1) {
513 if (errno(*__errno()) != EINTR4) {
514 log_error("main: select");
515
516 /*
517 * In order to give the unexpected error
518 * condition time to resolve without letting
519 * this process eat up all available CPU
520 * we sleep for a short while.
521 */
522 sleep(1);
523 }
524 } else if (n) {
525 transport_handle_messages(rfds);
526 transport_send_messages(wfds);
527 if (FD_ISSET(ui_socket, rfds)__fd_isset((ui_socket), (rfds)))
528 ui_handler();
529 if (!app_none && app_socket >= 0 &&
530 FD_ISSET(app_socket, rfds)__fd_isset((app_socket), (rfds)))
531 app_handler();
532 }
533 timer_handle_expirations();
534 }
535}