Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name isakmpd.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/isakmpd/isakmpd.c
1/* $OpenBSD: isakmpd.c,v 1.109 2023/03/08 04:43:06 guenther 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 default:
216 usage();
217 }
218 }
219 argc -= optind;
220 argv += optind;
Value stored to 'argv' is never read
221
222 if (argc > 0)
223 usage();
224
225 if (do_packetlog && !pcap_file)
226 pcap_file = PCAP_FILE_DEFAULT"/var/run/isakmpd.pcap";
227}
228
229static void
230sighup(int sig)
231{
232 sighupped = 1;
233}
234
235/* Report internal state on SIGUSR1. */
236static void
237report(void)
238{
239 FILE *rfp, *old;
240 mode_t old_umask;
241
242 old_umask = umask(S_IRWXG0000070 | S_IRWXO0000007);
243 rfp = monitor_fopen(report_file, "w");
244 umask(old_umask);
245
246 if (!rfp) {
247 log_error("report: fopen (\"%s\", \"w\") failed", report_file);
248 return;
249 }
250 /* Divert the log channel to the report file during the report. */
251 old = log_current();
252 log_to(rfp);
253 ui_report("r");
254 log_to(old);
255 fclose(rfp);
256}
257
258static void
259sigusr1(int sig)
260{
261 sigusr1ed = 1;
262}
263
264static int
265phase2_sa_check(struct sa *sa, void *arg)
266{
267 return sa->phase == 2;
268}
269
270static int
271phase1_sa_check(struct sa *sa, void *arg)
272{
273 return sa->phase == 1;
274}
275
276void
277set_slave_signals(void)
278{
279 int n;
280
281 for (n = 1; n < _NSIG33; n++)
282 signal(n, SIG_DFL(void (*)(int))0);
283
284 /*
285 * Do a clean daemon shutdown on TERM/INT. These signals must be
286 * initialized before monitor_init(). INT is only used with '-d'.
287 */
288 signal(SIGTERM15, daemon_shutdown_now);
289 if (debug == 1) /* i.e '-dd' will skip this. */
290 signal(SIGINT2, daemon_shutdown_now);
291
292 /* Reinitialize on HUP reception. */
293 signal(SIGHUP1, sighup);
294
295 /* Report state on USR1 reception. */
296 signal(SIGUSR130, sigusr1);
297}
298
299static void
300daemon_shutdown(void)
301{
302 /* Perform a (protocol-wise) clean shutdown of the daemon. */
303 struct sa *sa;
304
305 if (sigtermed == 1) {
306 log_print("isakmpd: shutting down...");
307
308 if (delete_sas &&
309 strncmp("no", conf_get_str("General", "Delete-SAs"), 2)) {
310 /*
311 * Delete all active SAs. First IPsec SAs, then
312 * ISAKMPD. Each DELETE is another (outgoing) message.
313 */
314 while ((sa = sa_find(phase2_sa_check, NULL((void *)0))))
315 sa_delete(sa, 1);
316
317 while ((sa = sa_find(phase1_sa_check, NULL((void *)0))))
318 sa_delete(sa, 1);
319 }
320
321 /* We only want to do this once. */
322 sigtermed++;
323 }
324 if (transport_prio_sendqs_empty()) {
325 /*
326 * When the prioritized transport sendq:s are empty, i.e all
327 * the DELETE notifications have been sent, we can shutdown.
328 */
329
330 log_packet_stop();
331 log_print("isakmpd: exit");
332 exit(0);
333 }
334}
335
336/* Called on SIGTERM, SIGINT or by ui_shutdown_daemon(). */
337void
338daemon_shutdown_now(int sig)
339{
340 sigtermed = 1;
341}
342
343/* Write pid file. */
344static void
345write_pid_file(void)
346{
347 FILE *fp;
348
349 unlink(pid_file);
350
351 fp = fopen(pid_file, "w");
352 if (fp != NULL((void *)0)) {
353 if (fprintf(fp, "%ld\n", (long) getpid()) < 0)
354 log_error("write_pid_file: failed to write PID to "
355 "\"%.100s\"", pid_file);
356 fclose(fp);
357 } else
358 log_fatal("write_pid_file: fopen (\"%.100s\", \"w\") failed",
359 pid_file);
360}
361
362void
363sanitise_stdfd(void)
364{
365 int nullfd, dupfd;
366
367 if ((nullfd = dupfd = open(_PATH_DEVNULL"/dev/null", O_RDWR0x0002)) == -1) {
368 fprintf(stderr(&__sF[2]), "Couldn't open /dev/null: %s\n",
369 strerror(errno(*__errno())));
370 exit(1);
371 }
372 while (++dupfd <= STDERR_FILENO2) {
373 /* Only populate closed fds */
374 if (fcntl(dupfd, F_GETFL3) == -1 && errno(*__errno()) == EBADF9) {
375 if (dup2(nullfd, dupfd) == -1) {
376 fprintf(stderr(&__sF[2]), "dup2: %s\n", strerror(errno(*__errno())));
377 exit(1);
378 }
379 }
380 }
381 if (nullfd > STDERR_FILENO2)
382 close(nullfd);
383}
384
385int
386main(int argc, char *argv[])
387{
388 fd_set *rfds, *wfds;
389 int n, m;
390 size_t mask_size;
391 struct timespec ts, *timeout;
392
393 closefrom(STDERR_FILENO2 + 1);
394
395 /*
396 * Make sure init() won't alloc fd 0, 1 or 2, as daemon() will close
397 * them.
398 */
399 sanitise_stdfd();
400
401 /* Log cmd line parsing and initialization errors to stderr. */
402 log_to(stderr(&__sF[2]));
403 parse_args(argc, argv);
404 log_init(debug);
405 log_print("isakmpd: starting");
406
407 /* Open protocols and services databases. */
408 setprotoent(1);
409 setservent(1);
410
411 /* Open command fifo */
412 ui_init();
413
414 set_slave_signals();
415 /* Daemonize before forking unpriv'ed child */
416 if (!debug)
417 if (daemon(0, 0))
418 log_fatal("main: daemon (0, 0) failed");
419
420 /* Set timezone before priv'separation */
421 tzset();
422
423 write_pid_file();
424
425 if (monitor_init(debug)) {
426 /* The parent, with privileges enters infinite monitor loop. */
427 monitor_loop(debug);
428 exit(0); /* Never reached. */
429 }
430 /* Child process only from this point on, no privileges left. */
431
432 init();
433
434 /* If we wanted IKE packet capture to file, initialize it now. */
435 if (pcap_file != 0)
436 log_packet_init(pcap_file);
437
438 /* Allocate the file descriptor sets just big enough. */
439 n = getdtablesize();
440 mask_size = howmany(n, NFDBITS)(((n) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned
)(sizeof(__fd_mask) * 8))))
* sizeof(fd_mask__fd_mask);
441 rfds = malloc(mask_size);
442 if (!rfds)
443 log_fatal("main: malloc (%lu) failed",
444 (unsigned long)mask_size);
445 wfds = malloc(mask_size);
446 if (!wfds)
447 log_fatal("main: malloc (%lu) failed",
448 (unsigned long)mask_size);
449
450 monitor_init_done();
451
452 while (1) {
453 /* If someone has sent SIGHUP to us, reconfigure. */
454 if (sighupped) {
455 sighupped = 0;
456 log_print("SIGHUP received");
457 reinit();
458 }
459 /* and if someone sent SIGUSR1, do a state report. */
460 if (sigusr1ed) {
461 sigusr1ed = 0;
462 log_print("SIGUSR1 received");
463 report();
464 }
465 /*
466 * and if someone set 'sigtermed' (SIGTERM, SIGINT or via the
467 * UI), this indicates we should start a controlled shutdown
468 * of the daemon.
469 *
470 * Note: Since _one_ message is sent per iteration of this
471 * enclosing while-loop, and we want to send a number of
472 * DELETE notifications, we must loop atleast this number of
473 * times. The daemon_shutdown() function starts by queueing
474 * the DELETEs, all other calls just increments the
475 * 'sigtermed' variable until it reaches a "safe" value, and
476 * the daemon exits.
477 */
478 if (sigtermed)
479 daemon_shutdown();
480
481 /* Setup the descriptors to look for incoming messages at. */
482 bzero(rfds, mask_size);
483 n = transport_fd_set(rfds);
484 FD_SET(ui_socket, rfds)__fd_set((ui_socket), (rfds));
485 if (ui_socket + 1 > n)
486 n = ui_socket + 1;
487
488 /*
489 * XXX Some day we might want to deal with an abstract
490 * application class instead, with many instantiations
491 * possible.
492 */
493 if (!app_none && app_socket >= 0) {
494 FD_SET(app_socket, rfds)__fd_set((app_socket), (rfds));
495 if (app_socket + 1 > n)
496 n = app_socket + 1;
497 }
498 /* Setup the descriptors that have pending messages to send. */
499 bzero(wfds, mask_size);
500 m = transport_pending_wfd_set(wfds);
501 if (m > n)
502 n = m;
503
504 /* Find out when the next timed event is. */
505 timeout = &ts;
506 timer_next_event(&timeout);
507
508 n = pselect(n, rfds, wfds, NULL((void *)0), timeout, NULL((void *)0));
509 if (n == -1) {
510 if (errno(*__errno()) != EINTR4) {
511 log_error("main: select");
512
513 /*
514 * In order to give the unexpected error
515 * condition time to resolve without letting
516 * this process eat up all available CPU
517 * we sleep for a short while.
518 */
519 sleep(1);
520 }
521 } else if (n) {
522 transport_handle_messages(rfds);
523 transport_send_messages(wfds);
524 if (FD_ISSET(ui_socket, rfds)__fd_isset((ui_socket), (rfds)))
525 ui_handler();
526 if (!app_none && app_socket >= 0 &&
527 FD_ISSET(app_socket, rfds)__fd_isset((app_socket), (rfds)))
528 app_handler();
529 }
530 timer_handle_expirations();
531 }
532}