Bug Summary

File:programs/pluto/plutomain.c
Warning:line 242, column 6
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name plutomain.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 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D HAVE_NM -D USE_PAM_AUTH -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/plutomain.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/plutomain.c
1/*
2 * Pluto main program
3 *
4 * Copyright (C) 1997 Angelos D. Keromytis.
5 * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier <hugh@mimosa.com>
6 * Copyright (C) 2003-2008 Michael C Richardson <mcr@xelerance.com>
7 * Copyright (C) 2003-2010 Paul Wouters <paul@xelerance.com>
8 * Copyright (C) 2007 Ken Bantoft <ken@xelerance.com>
9 * Copyright (C) 2008-2009 David McCullough <david_mccullough@securecomputing.com>
10 * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com>
11 * Copyright (C) 2009-2016 Tuomo Soini <tis@foobar.fi>
12 * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com>
13 * Copyright (C) 2012-2016 Paul Wouters <paul@libreswan.org>
14 * Copyright (C) 2012 Kim B. Heino <b@bbbs.net>
15 * Copyright (C) 2012 Philippe Vouters <Philippe.Vouters@laposte.net>
16 * Copyright (C) 2012 Wes Hardaker <opensource@hardakers.net>
17 * Copyright (C) 2013 David McCullough <ucdevel@gmail.com>
18 * Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org>
19 * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com>
20 *
21 * This program is free software; you can redistribute it and/or modify it
22 * under the terms of the GNU General Public License as published by the
23 * Free Software Foundation; either version 2 of the License, or (at your
24 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
25 *
26 * This program is distributed in the hope that it will be useful, but
27 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 * for more details.
30 */
31
32#include <pthread.h> /* Must be the first include file */
33#include <stdio.h>
34#include <stdlib.h>
35#include <errno(*__errno_location ()).h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <sys/un.h>
39#include <fcntl.h>
40#include <getopt.h>
41#include <unistd.h> /* for unlink(), write(), close(), access(), et.al. */
42
43#include "lswconf.h"
44#include "lswfips.h"
45#include "lswnss.h"
46#include "defs.h"
47#include "nss_ocsp.h"
48#include "server_fork.h" /* for init_server_fork() */
49#include "server.h"
50#include "kernel.h" /* needs connections.h */
51#include "log.h"
52#include "keys.h"
53#include "secrets.h" /* for free_remembered_public_keys() */
54#include "rnd.h"
55#include "fetch.h"
56#include "ipsecconf/confread.h"
57#include "crypto.h"
58#include "vendor.h"
59#include "enum_names.h"
60#include "virtual_ip.h"
61#include "state_db.h" /* for init_state_db() */
62#include "revival.h" /* for init_revival() */
63#include "connection_db.h" /* for connection_state_db() */
64#include "nat_traversal.h"
65#include "ike_alg.h"
66#include "ikev2_redirect.h"
67#include "root_certs.h" /* for init_root_certs() */
68#include "host_pair.h" /* for init_host_pair() */
69#include "ikev1.h" /* for init_ikev1() */
70#include "ikev2.h" /* for init_ikev2() */
71#include "crypt_symkey.h" /* for init_crypt_symkey() */
72#include "crl_queue.h" /* for free_crl_queue() */
73#include "iface.h"
74#include "server_pool.h"
75
76#ifndef IPSECDIR"/etc/ipsec.d"
77#define IPSECDIR"/etc/ipsec.d" "/etc/ipsec.d"
78#endif
79
80#ifdef HAVE_LIBCAP_NG1
81# include <cap-ng.h> /* from libcap-ng devel */
82#endif
83
84#include "labeled_ipsec.h" /* for init_labeled_ipsec() */
85
86# include "pluto_sd.h" /* for pluto_sd_init() */
87
88#ifdef USE_DNSSEC1
89#include "dnssec.h"
90#endif
91
92#ifdef HAVE_SECCOMP1
93#include "pluto_seccomp.h"
94#endif
95
96static void fatal_opt(int longindex, struct logger *logger, const char *fmt, ...) PRINTF_LIKE(3)__attribute__ ((format(printf, 3, 3 + 1))) NEVER_RETURNS__attribute__ ((noreturn));
97
98static const char *pluto_name; /* name (path) we were invoked with */
99
100static pthread_t main_thread;
101
102bool_Bool in_main_thread(void)
103{
104 return pthread_equal(pthread_self(), main_thread);
105}
106
107static char *rundir = NULL((void*)0);
108char *pluto_listen = NULL((void*)0);
109static bool_Bool fork_desired = USE_FORK1 || USE_DAEMON0;
110static bool_Bool selftest_only = false0;
111
112#ifdef FIPS_CHECK
113# include <fipscheck.h> /* from fipscheck devel */
114static const char *fips_package_files[] = { IPSEC_EXECDIR"/usr/local/libexec/ipsec" "/pluto", NULL((void*)0) };
115#endif
116
117/* pulled from main for show_setup_plutomain() */
118static const struct lsw_conf_options *oco;
119static char *coredir;
120static char *conffile;
121static int pluto_nss_seedbits;
122static int nhelpers = -1;
123static bool_Bool do_dnssec = false0;
124static char *pluto_dnssec_rootfile = NULL((void*)0);
125static char *pluto_dnssec_trusted = NULL((void*)0);
126
127static char *ocsp_uri = NULL((void*)0);
128static char *ocsp_trust_name = NULL((void*)0);
129static int ocsp_timeout = OCSP_DEFAULT_TIMEOUT2;
130static int ocsp_method = OCSP_METHOD_GET;
131static int ocsp_cache_size = OCSP_DEFAULT_CACHE_SIZE1000;
132static int ocsp_cache_min_age = OCSP_DEFAULT_CACHE_MIN_AGE3600;
133static int ocsp_cache_max_age = OCSP_DEFAULT_CACHE_MAX_AGE24 * 3600;
134
135static char *pluto_lock_filename = NULL((void*)0);
136static bool_Bool pluto_lock_created = false0;
137
138void free_pluto_main(void)
139{
140 /* Some values can be NULL if not specified as pluto argument */
141 pfree(pluto_lock_filename);
142 pfree(coredir);
143 pfree(conffile);
144 pfreeany(pluto_stats_binary){ typeof(pluto_stats_binary) *pp_ = &(pluto_stats_binary)
; if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
145 pfreeany(pluto_listen){ typeof(pluto_listen) *pp_ = &(pluto_listen); if (*pp_ !=
((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
146 pfree(pluto_vendorid);
147 pfreeany(ocsp_uri){ typeof(ocsp_uri) *pp_ = &(ocsp_uri); if (*pp_ != ((void
*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
148 pfreeany(ocsp_trust_name){ typeof(ocsp_trust_name) *pp_ = &(ocsp_trust_name); if (
*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
149 pfreeany(curl_iface){ typeof(curl_iface) *pp_ = &(curl_iface); if (*pp_ != ((
void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
150 pfreeany(pluto_log_file){ typeof(pluto_log_file) *pp_ = &(pluto_log_file); if (*pp_
!= ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
151 pfreeany(pluto_dnssec_rootfile){ typeof(pluto_dnssec_rootfile) *pp_ = &(pluto_dnssec_rootfile
); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
152 pfreeany(pluto_dnssec_trusted){ typeof(pluto_dnssec_trusted) *pp_ = &(pluto_dnssec_trusted
); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
153 pfreeany(rundir){ typeof(rundir) *pp_ = &(rundir); if (*pp_ != ((void*)0)
) { pfree(*pp_); *pp_ = ((void*)0); } }
;
154 free_global_redirect_dests();
155}
156
157/* string naming compile-time options that have interop implications */
158static const char compile_time_interop_options[] = ""
159 " IKEv2"
160#ifdef USE_IKEv11
161 " IKEv1"
162#endif
163#ifdef XFRM_SUPPORT1
164 " XFRM"
165#endif
166#ifdef USE_XFRM_INTERFACE1
167 " XFRMI"
168#endif
169 " esp-hw-offload"
170#if USE_FORK1
171 " FORK"
172#endif
173#if USE_VFORK0
174 " VFORK"
175#endif
176#if USE_DAEMON0
177 " DAEMON"
178#endif
179#if USE_PTHREAD_SETSCHEDPRIO1
180 " PTHREAD_SETSCHEDPRIO"
181#endif
182#if defined __GNUC__4 && defined __EXCEPTIONS
183 " GCC_EXCEPTIONS"
184#endif
185#ifdef HAVE_BROKEN_POPEN
186 " BROKEN_POPEN"
187#endif
188 " NSS"
189#ifdef NSS_REQ_AVA_COPY
190 " (AVA copy)"
191#endif
192#ifdef NSS_IPSEC_PROFILE1
193 " (IPsec profile)"
194#endif
195#ifdef USE_NSS_KDF1
196 " (NSS-PRF)"
197#else
198 " (native-PRF)"
199#endif
200#ifdef USE_DNSSEC1
201 " DNSSEC"
202#endif
203#ifdef USE_SYSTEMD_WATCHDOG
204 " SYSTEMD_WATCHDOG"
205#endif
206#ifdef FIPS_CHECK
207 " FIPS_BINCHECK"
208#endif
209#ifdef HAVE_LABELED_IPSEC1
210 " LABELED_IPSEC"
211 " (SELINUX)"
212#endif
213#ifdef HAVE_SECCOMP1
214 " SECCOMP"
215#endif
216#ifdef HAVE_LIBCAP_NG1
217 " LIBCAP_NG"
218#endif
219#ifdef USE_LINUX_AUDIT1
220 " LINUX_AUDIT"
221#endif
222#ifdef USE_PAM_AUTH1
223 " AUTH_PAM"
224#endif
225#ifdef HAVE_NM1
226 " NETWORKMANAGER"
227#endif
228#ifdef LIBCURL1
229 " CURL(non-NSS)"
230#endif
231#ifdef LIBLDAP
232 " LDAP(non-NSS)"
233#endif
234#ifdef USE_EFENCE
235 " EFENCE"
236#endif
237;
238
239/* create lockfile, or die in the attempt */
240static int create_lock(struct logger *logger)
241{
242 if (mkdir(rundir, 0755) != 0) {
21
Null pointer passed to 1st parameter expecting 'nonnull'
243 if (errno(*__errno_location ()) != EEXIST17) {
244 fatal_errno(PLUTO_EXIT_LOCK_FAIL, logger, errno(*__errno_location ()),
245 "unable to create lock dir: \"%s\"", rundir);
246 }
247 }
248
249 unsigned attempt;
250 for (attempt = 0; attempt < 2; attempt++) {
251 int fd = open(pluto_lock_filename, O_WRONLY01 | O_CREAT0100 | O_EXCL0200 | O_TRUNC01000,
252 S_IRUSR0400 | S_IRGRP(0400 >> 3) | S_IROTH((0400 >> 3) >> 3));
253 if (fd >= 0) {
254 pluto_lock_created = true1;
255 return fd;
256 }
257 if (errno(*__errno_location ()) != EEXIST17) {
258 fatal_errno(PLUTO_EXIT_LOCK_FAIL, logger, errno(*__errno_location ()),
259 "unable to create lock file \"%s\"", pluto_lock_filename);
260 }
261 if (fork_desired) {
262 fatal(PLUTO_EXIT_LOCK_FAIL, logger,
263 "lock file \"%s\" already exists", pluto_lock_filename);
264 }
265 /*
266 * if we did not fork, then we don't really need the pid to
267 * control, so wipe it
268 */
269 if (unlink(pluto_lock_filename) == -1) {
270 fatal_errno(PLUTO_EXIT_LOCK_FAIL, logger, errno(*__errno_location ()),
271 "lock file \"%s\" already exists and could not be removed",
272 pluto_lock_filename);
273 }
274 /*
275 * lock file removed, try creating it
276 * again ...
277 */
278 }
279 fatal(PLUTO_EXIT_LOCK_FAIL, logger, "lock file \"%s\" could not be created after %u attempts",
280 pluto_lock_filename, attempt);
281}
282
283/*
284 * fill_lock - Populate the lock file with pluto's PID
285 *
286 * @param lockfd File Descriptor for the lock file
287 * @param pid PID (pid_t struct) to be put into the lock file
288 * @return bool True if successful
289 */
290static bool_Bool fill_lock(int lockfd, pid_t pid)
291{
292 char buf[30]; /* holds "<pid>\n" */
293 int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid);
294 bool_Bool ok = len > 0 && write(lockfd, buf, len) == len;
295
296 close(lockfd);
297 return ok;
298}
299
300/*
301 * delete_lock - Delete the lock file
302 */
303void delete_lock(void)
304{
305 if (pluto_lock_created) {
306 delete_ctl_socket();
307 unlink(pluto_lock_filename); /* is noting failure useful? */
308 }
309}
310
311/*
312 * parser.l and keywords.c need these global variables
313 * FIXME: move them to confread_load() parameters
314 */
315int verbose = 0;
316
317/* Read config file. exit() on error. */
318static struct starter_config *read_cfg_file(char *configfile, long longindex, struct logger *logger)
319{
320 struct starter_config *cfg = NULL((void*)0);
321 starter_errors_t errl = { NULL((void*)0) };
322
323 cfg = confread_load(configfile, &errl, NULL((void*)0) /* ctl_addr.sun_path? */, true1, logger);
324 if (cfg == NULL((void*)0)) {
325 /*
326 * note: fatal_opt() never returns so we will have a
327 * technical leak of errl.errors
328 */
329 fatal_opt(longindex, logger, "%s", errl.errors);
330 }
331
332 if (errl.errors != NULL((void*)0)) {
333 llog(RC_LOG, logger, "pluto --config '%s', ignoring: %s",
334 configfile, errl.errors);
335 pfree(errl.errors);
336 }
337
338 return cfg;
339}
340
341/*
342 * Helper function for config file mapper: set string option value.
343 * Values passed in are expected to have been allocated using our
344 * own functions.
345 */
346static void set_cfg_string(char **target, char *value)
347{
348 /* Do nothing if value is unset. */
349 if (value == NULL((void*)0) || *value == '\0')
350 return;
351
352 /* Don't free previous target, it might be statically set. */
353 *target = clone_str(value, "(ignore) set_cfg_string item")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen
((value)) + 1, ("(ignore) set_cfg_string item")))
;
354}
355
356/*
357 * This function MUST NOT be used for anything else!
358 * It is used to seed the NSS PRNG based on --seedbits pluto argument
359 * or the seedbits= * config setup option in ipsec.conf.
360 * Everything else that needs random MUST use get_rnd_bytes()
361 * This function MUST NOT be changed to use /dev/urandom.
362 */
363static void get_bsi_random(size_t nbytes, unsigned char *buf, struct logger *logger)
364{
365 size_t ndone;
366 int dev;
367 ssize_t got;
368 const char *device = "/dev/random";
369
370 dev = open(device, 0);
371 if (dev < 0) {
372 fatal_errno(PLUTO_EXIT_NSS_FAIL, logger, errno(*__errno_location ()),
373 "could not open %s", device);
374 }
375
376 ndone = 0;
377 dbg("need %d bits random for extra seeding of the NSS PRNG",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("need %d bits random for extra seeding of the NSS PRNG"
, (int) nbytes * 8); } }
378 (int) nbytes * BITS_PER_BYTE){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("need %d bits random for extra seeding of the NSS PRNG"
, (int) nbytes * 8); } }
;
379
380 while (ndone < nbytes) {
381 got = read(dev, buf + ndone, nbytes - ndone);
382 if (got < 0) {
383 fatal_errno(PLUTO_EXIT_NSS_FAIL, logger, errno(*__errno_location ()),
384 "read error on %s", device);
385 }
386 if (got == 0) {
387 fatal(PLUTO_EXIT_NSS_FAIL, logger, "EOF on %s!?!\n", device);
388 }
389 ndone += got;
390 }
391 close(dev);
392 dbg("read %zu bytes from /dev/random for NSS PRNG", nbytes){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("read %zu bytes from /dev/random for NSS PRNG"
, nbytes); } }
;
393}
394
395static void pluto_init_nss(const char *nssdir, struct logger *logger)
396{
397 diag_t d = lsw_nss_setup(nssdir, LSW_NSS_READONLY, logger);
398 if (d != NULL((void*)0)) {
399 fatal_diag(PLUTO_EXIT_NSS_FAIL, logger, &d, "%s", "");
400 }
401 llog(RC_LOG, logger, "NSS crypto library initialized");
402
403 /*
404 * This exists purely to make the BSI happy.
405 * We do not inflict this on other users
406 */
407 if (pluto_nss_seedbits != 0) {
408 int seedbytes = BYTES_FOR_BITS(pluto_nss_seedbits)(((pluto_nss_seedbits) + 8 - 1) / 8);
409 unsigned char *buf = alloc_bytes(seedbytes, "TLA seedmix");
410
411 get_bsi_random(seedbytes, buf, logger); /* much TLA, very blocking */
412 SECStatus rv = PK11_RandomUpdate(buf, seedbytes);
413 llog(RC_LOG, logger, "seeded %d bytes into the NSS PRNG", seedbytes);
414 passert(rv == SECSuccess)({ _Bool assertion__ = rv == SECSuccess; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/plutomain.c", .line = 414, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "rv == SECSuccess"); } (void
) 1; })
;
415 messupn(buf, seedbytes)memset((buf), 0xFB, (seedbytes));
416 pfree(buf);
417 }
418}
419
420/* 0 is special and default: do not check crls dynamically */
421deltatime_t crl_check_interval = DELTATIME_INIT(0){ .dt = { .tv_sec = (0), } };
422
423/*
424 * Attribute Type "constant" for Security Context
425 *
426 * Originally, we assigned the value 10, but that properly belongs to ECN_TUNNEL.
427 * We then assigned 32001 which is in the private range RFC 2407.
428 * Unfortunately, we feel we have to support 10 as an option for backward
429 * compatibility.
430 * This variable specifies (globally!!) which we support: 10 or 32001.
431 * That makes migration to 32001 all or nothing.
432 */
433uint16_t secctx_attr_type = SECCTX;
434
435/*
436 * Table of Pluto command-line options.
437 *
438 * For getopt_long(3), but with twists.
439 *
440 * We never find that letting getopt set an option makes sense
441 * so flag is always NULL.
442 *
443 * Trick: we split each "name" string with an explicit '\0'.
444 * Before the '\0' is the option name, as seen by getopt_long.
445 * After the '\0' is meta-information:
446 * - _ means: obsolete due to _ in name: replace _ with -
447 * - > means: obsolete spelling; use spelling from rest of string
448 * - ! means: obsolete and ignored (no replacement)
449 * - anything else is a description of the options argument (printed by --help)
450 * If it starts with ^, that means start a newline in the --help output.
451 *
452 * The table should be ordered to maximize the clarity of --help.
453 *
454 */
455
456enum {
457 OPT_OFFSET = 256, /* larger than largest char */
458 OPT_EFENCE_PROTECT,
459 OPT_DEBUG,
460 OPT_IMPAIR,
461 OPT_DNSSEC_ROOTKEY_FILE,
462 OPT_DNSSEC_TRUSTED,
463};
464
465static const struct option long_opts[] = {
466 /* name, has_arg, flag, val */
467 { "help\0", no_argument0, NULL((void*)0), 'h' },
468 { "version\0", no_argument0, NULL((void*)0), 'v' },
469 { "config\0<filename>", required_argument1, NULL((void*)0), 'z' },
470 { "nofork\0", no_argument0, NULL((void*)0), '0' },
471 { "stderrlog\0", no_argument0, NULL((void*)0), 'e' },
472 { "logfile\0<filename>", required_argument1, NULL((void*)0), 'g' },
473#ifdef USE_DNSSEC1
474 { "dnssec-rootkey-file\0<filename>", required_argument1, NULL((void*)0),
475 OPT_DNSSEC_ROOTKEY_FILE },
476 { "dnssec-trusted\0<filename>", required_argument1, NULL((void*)0),
477 OPT_DNSSEC_TRUSTED },
478#endif
479 { "log-no-time\0", no_argument0, NULL((void*)0), 't' }, /* was --plutostderrlogtime */
480 { "log-no-append\0", no_argument0, NULL((void*)0), '7' },
481 { "log-no-ip\0", no_argument0, NULL((void*)0), '<' },
482 { "log-no-audit\0", no_argument0, NULL((void*)0), 'a' },
483 { "force-busy\0", no_argument0, NULL((void*)0), 'D' },
484 { "force-unlimited\0", no_argument0, NULL((void*)0), 'U' },
485 { "crl-strict\0", no_argument0, NULL((void*)0), 'r' },
486 { "ocsp-strict\0", no_argument0, NULL((void*)0), 'o' },
487 { "ocsp-enable\0", no_argument0, NULL((void*)0), 'O' },
488 { "ocsp-uri\0", required_argument1, NULL((void*)0), 'Y' },
489 { "ocsp-timeout\0", required_argument1, NULL((void*)0), 'T' },
490 { "ocsp-trustname\0", required_argument1, NULL((void*)0), 'J' },
491 { "ocsp-cache-size\0", required_argument1, NULL((void*)0), 'E' },
492 { "ocsp-cache-min-age\0", required_argument1, NULL((void*)0), 'G' },
493 { "ocsp-cache-max-age\0", required_argument1, NULL((void*)0), 'H' },
494 { "ocsp-method\0", required_argument1, NULL((void*)0), 'B' },
495 { "crlcheckinterval\0", required_argument1, NULL((void*)0), 'x' },
496 { "uniqueids\0", no_argument0, NULL((void*)0), 'u' },
497 { "no-dnssec\0", no_argument0, NULL((void*)0), 'R' },
498 { "use-xfrm\0", no_argument0, NULL((void*)0), 'K' },
499 { "use-bsdkame\0", no_argument0, NULL((void*)0), 'F' },
500 { "interface\0<ifname|ifaddr>", required_argument1, NULL((void*)0), 'i' },
501 { "curl-iface\0<ifname|ifaddr>", required_argument1, NULL((void*)0), 'Z' },
502 { "curl-timeout\0<secs>", required_argument1, NULL((void*)0), 'I' },
503 { "listen\0<ifaddr>", required_argument1, NULL((void*)0), 'L' },
504 { "listen-tcp\0", no_argument0, NULL((void*)0), 'm' },
505 { "no-listen-udp\0", no_argument0, NULL((void*)0), 'p' },
506 { "ike-socket-bufsize\0<buf-size>", required_argument1, NULL((void*)0), 'W' },
507 { "ike-socket-no-errqueue\0", no_argument0, NULL((void*)0), '1' },
508 { "nflog-all\0<group-number>", required_argument1, NULL((void*)0), 'G' },
509 { "rundir\0<path>", required_argument1, NULL((void*)0), 'b' }, /* was ctlbase */
510 { "secretsfile\0<secrets-file>", required_argument1, NULL((void*)0), 's' },
511 { "global-redirect\0", required_argument1, NULL((void*)0), 'Q'},
512 { "global-redirect-to\0", required_argument1, NULL((void*)0), 'y'},
513 { "coredir\0>dumpdir", required_argument1, NULL((void*)0), 'C' }, /* redundant spelling */
514 { "dumpdir\0<dirname>", required_argument1, NULL((void*)0), 'C' },
515 { "statsbin\0<filename>", required_argument1, NULL((void*)0), 'S' },
516 { "ipsecdir\0<ipsec-dir>", required_argument1, NULL((void*)0), 'f' },
517 { "foodgroupsdir\0>ipsecdir", required_argument1, NULL((void*)0), 'f' }, /* redundant spelling */
518 { "nssdir\0<path>", required_argument1, NULL((void*)0), 'd' }, /* nss-tools use -d */
519 { "keep-alive\0<delay_secs>", required_argument1, NULL((void*)0), '2' },
520 { "virtual-private\0<network_list>", required_argument1, NULL((void*)0), '6' },
521 { "nhelpers\0<number>", required_argument1, NULL((void*)0), 'j' },
522 { "expire-shunt-interval\0<secs>", required_argument1, NULL((void*)0), '9' },
523 { "seedbits\0<number>", required_argument1, NULL((void*)0), 'c' },
524 /* really an attribute type, not a value */
525 { "ikev1-secctx-attr-type\0<number>", required_argument1, NULL((void*)0), 'w' },
526 { "ikev1-reject\0", no_argument0, NULL((void*)0), 'k' },
527 { "ikev1-drop\0", no_argument0, NULL((void*)0), 'l' },
528#ifdef HAVE_SECCOMP1
529 { "seccomp-enabled\0", no_argument0, NULL((void*)0), '3' },
530 { "seccomp-tolerant\0", no_argument0, NULL((void*)0), '4' },
531#endif
532 { "vendorid\0<vendorid>", required_argument1, NULL((void*)0), 'V' },
533
534 { "selftest\0", no_argument0, NULL((void*)0), '5' },
535
536 { "leak-detective\0", no_argument0, NULL((void*)0), 'X' },
537 { "efence-protect\0", required_argument1, NULL((void*)0), OPT_EFENCE_PROTECT, },
538 { "debug-none\0^", no_argument0, NULL((void*)0), 'N' },
539 { "debug-all\0", no_argument0, NULL((void*)0), 'A' },
540 { "debug\0", required_argument1, NULL((void*)0), OPT_DEBUG, },
541 { "impair\0", required_argument1, NULL((void*)0), OPT_IMPAIR, },
542
543 { 0, 0, 0, 0 }
544};
545
546/*
547 * HACK: check UGH, and if it is bad, log it along with the option.
548 */
549
550static void fatal_opt(int longindex, struct logger *logger, const char *fmt, ...)
551{
552 passert(longindex >= 0)({ _Bool assertion__ = longindex >= 0; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/plutomain.c", .line = 552,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "longindex >= 0"); } (
void) 1; })
;
553 const char *optname = long_opts[longindex].name;
554 LLOG_JAMBUF(RC_LOG, logger, buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (({ if (((RC_LOG) &
NO_PREFIX) == ((lset_t)0) && (((RC_LOG) & STREAM_MASK
) != DEBUG_STREAM || (cur_debugging & (((lset_t)1 <<
(DBG_ADD_PREFIX_IX)))))) { (logger)->object_vec->jam_object_prefix
(buf, (logger)->object); } }); buf != ((void*)0); jambuf_to_logger
(buf, (logger), RC_LOG), buf = ((void*)0))
{
555 if (optarg == NULL((void*)0)) {
556 jam(buf, "option --%s invalid: ", optname);
557 } else {
558 jam(buf, "option --%s \"%s\" invalid: ", optname, optarg);
559 }
560 va_list ap;
561 va_start(ap, fmt)__builtin_va_start(ap, fmt);
562 jam_va_list(buf, fmt, ap);
563 va_end(ap)__builtin_va_end(ap);
564 }
565 /* not exit_pluto as pluto isn't yet up and running? */
566 exit(PLUTO_EXIT_FAIL);
567}
568
569static void check_err(err_t ugh, int longindex, struct logger *logger)
570{
571 if (ugh != NULL((void*)0)) {
572 fatal_opt(longindex, logger, "%s", ugh);
573 }
574}
575
576/* print full usage (from long_opts[]) */
577static void usage(FILE *stream)
578{
579 const struct option *opt;
580 char line[72];
581 size_t lw;
582
583 snprintf(line, sizeof(line), "Usage: %s", pluto_name);
584 lw = strlen(line);
585
586 for (opt = long_opts; opt->name != NULL((void*)0); opt++) {
587 const char *nm = opt->name;
588 const char *meta = nm + strlen(nm) + 1;
589 bool_Bool force_nl = false0;
590 char chunk[sizeof(line) - 1];
591 int cw;
592
593 switch (*meta) {
594 case '_':
595 case '>':
596 case '!':
597 /* ignore these entries */
598 break;
599 case '^':
600 force_nl = true1;
601 meta++; /* eat ^ */
602 /* FALL THROUGH */
603 default:
604 if (*meta == '\0')
605 snprintf(chunk, sizeof(chunk), "[--%s]", nm);
606 else
607 snprintf(chunk, sizeof(chunk), "[--%s %s]", nm, meta);
608 cw = strlen(chunk);
609
610 if (force_nl || lw + cw + 2 >= sizeof(line)) {
611 fprintf(stream, "%s\n", line);
612 line[0] = '\t';
613 lw = 1;
614 } else {
615 line[lw++] = ' ';
616 }
617 passert(lw + cw + 1 < sizeof(line))({ _Bool assertion__ = lw + cw + 1 < sizeof(line); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/plutomain.c", .line = 617
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "lw + cw + 1 < sizeof(line)"
); } (void) 1; })
;
618 strcpy(&line[lw], chunk);
619 lw += cw;
620 }
621 }
622
623 fprintf(stream, "%s\n", line);
624
625 fprintf(stream, "Libreswan %s\n", ipsec_version_code());
626}
627
628#ifdef USE_DNSSEC1
629static void set_dnssec_file_names (struct starter_config *cfg)
630{
631 if (cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE][0] != '\0') {
632 pfreeany(pluto_dnssec_rootfile){ typeof(pluto_dnssec_rootfile) *pp_ = &(pluto_dnssec_rootfile
); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
633 set_cfg_string(&pluto_dnssec_rootfile,
634 cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE]);
635 } else {
636 /* unset the global one config file unset it */
637 pfreeany(pluto_dnssec_rootfile){ typeof(pluto_dnssec_rootfile) *pp_ = &(pluto_dnssec_rootfile
); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
638 pluto_dnssec_rootfile = NULL((void*)0);
639 }
640 if (cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS] != NULL((void*)0) &&
641 cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS][0] != '\0') {
642 set_cfg_string(&pluto_dnssec_trusted,
643 cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS]);
644 }
645}
646#endif
647
648#ifdef USE_EFENCE
649extern int EF_PROTECT_BELOW;
650extern int EF_PROTECT_FREE;
651#endif
652
653int main(int argc, char **argv)
654{
655 struct log_param log_param = default_log_param;
656
657 /*
658 * Some options should to be processed before the first
659 * malloc() call, so scan for them here.
660 *
661 * - leak-detective is immutable, it must come before the
662 * first malloc()
663 *
664 * - efence-protect seems to be less strict, but enabling it
665 * early must be a good thing (TM) right
666 */
667 for (int i = 1; i < argc; ++i) {
1
Assuming 'i' is >= 'argc'
2
Loop condition is false. Execution continues on line 684
668 if (streq(argv[i], "--leak-detective")(strcmp((argv[i]), ("--leak-detective")) == 0))
669 leak_detective = true1;
670#ifdef USE_EFENCE
671 else if (streq(argv[i], "--efence-protect")(strcmp((argv[i]), ("--efence-protect")) == 0)) {
672 EF_PROTECT_BELOW = 1;
673 EF_PROTECT_FREE = 1;
674 }
675#endif
676 }
677
678 /*
679 * Identify the main thread.
680 *
681 * Also used as a reserved thread for code wanting to
682 * determine if it is running on an aux thread.
683 */
684 main_thread = pthread_self();
685
686 int lockfd;
687
688 /*
689 * We read the intentions for how to log from command line options
690 * and the config file. Then we prepare to be able to log, but until
691 * then log to stderr (better then nothing). Once we are ready to
692 * actually do logging according to the methods desired, we set the
693 * variables for those methods
694 */
695 bool_Bool log_to_stderr_desired = false0;
696 bool_Bool log_to_file_desired = false0;
697
698 /*
699 * Start with the program name logger.
700 */
701 pluto_name = argv[0];
702 struct logger *logger = string_logger(null_fd((struct fd *) ((void*)0)), HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/plutomain.c", .line = 702, }; &here; }
)
, "%s: ", pluto_name); /* must free */
703
704 conffile = clone_str(IPSEC_CONF, "conffile in main()")(("/etc/ipsec.conf") == ((void*)0) ? ((void*)0) : clone_bytes
(("/etc/ipsec.conf"), strlen(("/etc/ipsec.conf")) + 1, ("conffile in main()"
)))
;
3
'?' condition is false
705 coredir = clone_str(DEFAULT_RUNDIR, "coredir in main()")(("/run/pluto") == ((void*)0) ? ((void*)0) : clone_bytes(("/run/pluto"
), strlen(("/run/pluto")) + 1, ("coredir in main()")))
;
4
'?' condition is false
706 rundir = clone_str(DEFAULT_RUNDIR, "rundir")(("/run/pluto") == ((void*)0) ? ((void*)0) : clone_bytes(("/run/pluto"
), strlen(("/run/pluto")) + 1, ("rundir")))
;
5
'?' condition is false
707 pluto_vendorid = clone_str(ipsec_version_vendorid(), "vendorid in main()")((ipsec_version_vendorid()) == ((void*)0) ? ((void*)0) : clone_bytes
((ipsec_version_vendorid()), strlen((ipsec_version_vendorid()
)) + 1, ("vendorid in main()")))
;
6
Null pointer value stored to 'rundir'
7
Assuming the condition is true
8
'?' condition is true
708#ifdef USE_DNSSEC1
709 pluto_dnssec_rootfile = clone_str(DEFAULT_DNSSEC_ROOTKEY_FILE, "root.key file")(("/var/lib/unbound/root.key") == ((void*)0) ? ((void*)0) : clone_bytes
(("/var/lib/unbound/root.key"), strlen(("/var/lib/unbound/root.key"
)) + 1, ("root.key file")))
;
9
'?' condition is false
710#endif
711 pluto_lock_filename = clone_str(DEFAULT_RUNDIR "/pluto.pid", "lock file")(("/run/pluto" "/pluto.pid") == ((void*)0) ? ((void*)0) : clone_bytes
(("/run/pluto" "/pluto.pid"), strlen(("/run/pluto" "/pluto.pid"
)) + 1, ("lock file")))
;
10
'?' condition is false
712
713 deltatime_t keep_alive = DELTATIME_INIT(0){ .dt = { .tv_sec = (0), } };
714
715 /* Overridden by virtual_private= in ipsec.conf */
716 char *virtual_private = NULL((void*)0);
717
718 /* handle arguments */
719 for (;; ) {
11
Loop condition is true. Entering loop body
720 /*
721 * Note: we don't like the way short options get parsed
722 * by getopt_long, so we simply pass an empty string as
723 * the list. It could be "hvdenp:l:s:" "NARXPECK".
724 */
725 int longindex = -1;
726 int c = getopt_long(argc, argv, "", long_opts, &longindex);
727 if (c < 0)
12
Assuming 'c' is < 0
13
Taking true branch
728 break;
14
Execution continues on line 1428
729
730 if (longindex >= 0) {
731 passert(c != '?' && c != ':')({ _Bool assertion__ = c != '?' && c != ':'; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/plutomain.c", .line = 731
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "c != '?' && c != ':'"
); } (void) 1; })
; /* no error */
732 const char *optname = long_opts[longindex].name;
733 const char *optmeta = optname + strlen(optname) + 1; /* after '\0' */
734 switch (optmeta[0]) {
735 case '_':
736 llog(RC_LOG, logger,
737 "warning: option \"--%s\" with '_' in its name is obsolete; use '-'",
738 optname);
739 break;
740 case '>':
741 llog(RC_LOG, logger,
742 "warning: option \"--%s\" is obsolete; use \"--%s\"", optname, optmeta + 1);
743 break;
744 case '!':
745 llog(RC_LOG, logger,
746 "warning: option \"--%s\" is obsolete; ignored", optname);
747 continue; /* ignore it! */
748 }
749 }
750
751 switch (c) {
752
753 case 0:
754 /*
755 * Long option already handled by getopt_long.
756 * Not currently used since we always set flag to NULL.
757 */
758 passert_failllog_passert(logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/plutomain.c", .line = 758, }; &here; }
)
, "unexpected 0 returned by getopt_long()");
759
760 case ':': /* diagnostic already printed by getopt_long */
761 case '?': /* diagnostic already printed by getopt_long */
762 fprintf(stderrstderr, "For usage information: %s --help\n", pluto_name);
763 fprintf(stderrstderr, "Libreswan %s\n", ipsec_version_code());
764 exit(PLUTO_EXIT_FAIL);
765
766 case 'h': /* --help */
767 usage(stdoutstdout); /* so <<| more>> works */
768 exit(PLUTO_EXIT_OK);
769
770 case 'X': /* --leak-detective */
771 /*
772 * This flag was already processed at the start of main()
773 * because leak_detective must be immutable from before
774 * the first alloc().
775 * If this option is specified, we must have already
776 * set it at the start of main(), so assert it.
777 */
778 passert(leak_detective)({ _Bool assertion__ = leak_detective; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/plutomain.c", .line = 778, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "leak_detective"); } (void
) 1; })
;
779 continue;
780
781 case 'C': /* --coredir */
782 pfree(coredir);
783 coredir = clone_str(optarg, "coredir via getopt")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("coredir via getopt")))
;
784 continue;
785
786 case 'V': /* --vendorid */
787 pfree(pluto_vendorid);
788 pluto_vendorid = clone_str(optarg, "pluto_vendorid via getopt")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("pluto_vendorid via getopt")))
;
789 continue;
790
791 case 'S': /* --statsdir */
792 pfreeany(pluto_stats_binary){ typeof(pluto_stats_binary) *pp_ = &(pluto_stats_binary)
; if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
793 pluto_stats_binary = clone_str(optarg, "statsbin")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("statsbin")))
;
794 continue;
795
796 case 'v': /* --version */
797 printf("%s%s\n", ipsec_version_string(), /* ok */
798 compile_time_interop_options);
799 /* not exit_pluto because we are not initialized yet */
800 exit(PLUTO_EXIT_OK);
801
802 case 'j': /* --nhelpers */
803 if (streq(optarg, "-1")(strcmp((optarg), ("-1")) == 0)) {
804 nhelpers = -1;
805 } else {
806 unsigned long u;
807 check_err(ttoulb(optarg, 0, 10, 1000, &u),
808 longindex, logger);
809 nhelpers = u;
810 }
811 continue;
812
813 case 'c': /* --seedbits */
814 pluto_nss_seedbits = atoi(optarg);
815 if (pluto_nss_seedbits == 0) {
816 llog(RC_LOG, logger, "seedbits must be an integer > 0");
817 /* not exit_pluto because we are not initialized yet */
818 exit(PLUTO_EXIT_NSS_FAIL);
819 }
820 continue;
821
822#ifdef HAVE_LABELED_IPSEC1
823 case 'w': /* --secctx-attr-type */
824 {
825 unsigned long u;
826 check_err(ttoulb(optarg, 0, 0, 0xFFFF, &u),
827 longindex, logger);
828 if (u != SECCTX && u != ECN_TUNNEL_or_old_SECCTX) {
829 fatal_opt(longindex, logger,
830 "must be a positive 32001 (default) or 10 (for backward compatibility)");
831 }
832 secctx_attr_type = u;
833 continue;
834 }
835#endif
836
837 case 'k': /* --ikev1-reject */
838 pluto_ikev1_pol = GLOBAL_IKEv1_REJECT;
839 continue;
840
841 case 'l': /* --ikev1-drop */
842 pluto_ikev1_pol = GLOBAL_IKEv1_DROP;
843 continue;
844
845 case '0': /* --nofork*/
846 fork_desired = false0;
847 continue;
848
849 case 'e': /* --stderrlog */
850 log_to_stderr_desired = true1;
851 continue;
852
853 case 'g': /* --logfile */
854 pluto_log_file = clone_str(optarg, "pluto_log_file")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("pluto_log_file")))
;
855 log_to_file_desired = true1;
856 continue;
857#ifdef USE_DNSSEC1
858 case OPT_DNSSEC_ROOTKEY_FILE: /* --dnssec-rootkey-file */
859 if (optarg[0] != '\0') {
860 pfree(pluto_dnssec_rootfile);
861 pluto_dnssec_rootfile = clone_str(optarg,((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("dnssec_rootkey_file")))
862 "dnssec_rootkey_file")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("dnssec_rootkey_file")))
;
863 }
864 continue;
865
866 case OPT_DNSSEC_TRUSTED: /* --dnssec-trusted */
867 pluto_dnssec_trusted = clone_str(optarg, "pluto_dnssec_trusted")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("pluto_dnssec_trusted")))
;
868 continue;
869#endif /* USE_DNSSEC */
870
871 case 't': /* --log-no-time */
872 log_param.log_with_timestamp = false0;
873 continue;
874
875 case '7': /* --log-no-append */
876 log_append = false0;
877 continue;
878
879 case '<': /* --log-no-ip */
880 log_ip = false0;
881 continue;
882
883 case 'a': /* --log-no-audit */
884 log_to_audit = false0;
885 continue;
886
887 case '8': /* --drop-oppo-null */
888 pluto_drop_oppo_null = true1;
889 continue;
890
891 case '9': /* --expire-shunt-interval <interval> */
892 {
893 unsigned long d = 0;
894 check_err(ttoulb(optarg, 0, 10, 1000, &d), longindex, logger);
895 bare_shunt_interval = deltatime(d);
896 continue;
897 }
898
899 case 'L': /* --listen ip_addr */
900 {
901 ip_address lip;
902 err_t e = ttoaddress_num(shunk1(optarg), NULL((void*)0)/*UNSPEC*/, &lip);
903
904 if (e != NULL((void*)0)) {
905 /*
906 * ??? should we continue on failure?
907 */
908 llog(RC_LOG, logger,
909 "invalid listen argument ignored: %s\n", e);
910 } else {
911 pluto_listen = clone_str(optarg, "pluto_listen")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("pluto_listen")))
;
912 llog(RC_LOG, logger,
913 "bind() will be filtered for %s\n",
914 pluto_listen);
915 }
916 continue;
917 }
918
919 case 'F': /* --use-bsdkame */
920#ifdef BSDKAME_SUPPORT
921 kernel_ops = &bsdkame_kernel_ops;
922#else
923 llog(RC_LOG, logger, "--use-bsdkame not supported");
924#endif
925 continue;
926
927 case 'K': /* --use-netkey */
928#ifdef XFRM_SUPPORT1
929 kernel_ops = &xfrm_kernel_ops;
930#else
931 llog(RC_LOG, logger, "--use-xfrm not supported");
932#endif
933 continue;
934
935 case 'D': /* --force-busy */
936 pluto_ddos_mode = DDOS_FORCE_BUSY;
937 continue;
938 case 'U': /* --force-unlimited */
939 pluto_ddos_mode = DDOS_FORCE_UNLIMITED;
940 continue;
941
942#ifdef HAVE_SECCOMP1
943 case '3': /* --seccomp-enabled */
944 pluto_seccomp_mode = SECCOMP_ENABLED;
945 continue;
946 case '4': /* --seccomp-tolerant */
947 pluto_seccomp_mode = SECCOMP_TOLERANT;
948 continue;
949#endif
950
951 case 'Z': /* --curl-iface */
952 curl_iface = clone_str(optarg, "curl_iface")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("curl_iface")))
;
953 continue;
954
955 case 'I': /* --curl-timeout */
956 {
957 unsigned long u;
958 check_err(ttoulb(optarg, /*not lower-bound*/0, 10, 0xFFFF, &u),
959 longindex, logger);
960 if (u == 0) {
961 fatal_opt(longindex, logger, "must not be < 1");
962 }
963 curl_timeout = u;
964 continue;
965 }
966
967 case 'r': /* --crl-strict */
968 crl_strict = true1;
969 continue;
970
971 case 'x': /* --crlcheckinterval <seconds> */
972 {
973 unsigned long u;
974 check_err(ttoulb(optarg, /*not lower-bound*/0, 10, (unsigned long) TIME_T_MAX((time_t) ((1ull << (sizeof(time_t) * 8 - 1)) - 1)), &u),
975 longindex, logger);
976 crl_check_interval = deltatime(u);
977 continue;
978 }
979
980 case 'o':
981 ocsp_strict = true1;
982 continue;
983
984 case 'O':
985 ocsp_enable = true1;
986 continue;
987
988 case 'Y':
989 ocsp_uri = clone_str(optarg, "ocsp_uri")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("ocsp_uri")))
;
990 continue;
991
992 case 'J':
993 ocsp_trust_name = clone_str(optarg, "ocsp_trust_name")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("ocsp_trust_name")))
;
994 continue;
995
996 case 'T': /* --ocsp_timeout <seconds> */
997 {
998 unsigned long u;
999 check_err(ttoulb(optarg, /*not-lower-bound*/0, 10, 0xFFFF, &u),
1000 longindex, logger);
1001 if (u == 0) {
1002 fatal_opt(longindex, logger, "must not be 0");
1003 continue;
1004 }
1005 ocsp_timeout = u;
1006 continue;
1007 }
1008
1009 case 'E': /* --ocsp-cache-size <entries> */
1010 {
1011 unsigned long u;
1012 check_err(ttoulb(optarg, 0, 10, 0xFFFF, &u), longindex, logger);
1013 ocsp_cache_size = u;
1014 continue;
1015 }
1016
1017 case 'G': /* --ocsp-cache-min-age <seconds> */
1018 {
1019 unsigned long u;
1020 check_err(ttoulb(optarg, 0, 10, 0xFFFF, &u), longindex, logger);
1021 ocsp_cache_min_age = u;
1022 continue;
1023 }
1024
1025 case 'H': /* --ocsp-cache-max-age <seconds> */
1026 {
1027 unsigned long u;
1028 check_err(ttoulb(optarg, 0, 10, 0xFFFF, &u), longindex, logger);
1029 ocsp_cache_max_age = u;
1030 continue;
1031 }
1032
1033 case 'B': /* --ocsp-method get|post */
1034 if (streq(optarg, "post")(strcmp((optarg), ("post")) == 0)) {
1035 ocsp_method = OCSP_METHOD_POST;
1036 ocsp_post = true1;
1037 } else {
1038 if (streq(optarg, "get")(strcmp((optarg), ("get")) == 0)) {
1039 ocsp_method = OCSP_METHOD_GET;
1040 } else {
1041 fatal_opt(longindex, logger, "ocsp-method is either 'post' or 'get'");
1042 }
1043 }
1044 continue;
1045
1046 case 'u': /* --uniqueids */
1047 uniqueIDs = true1;
1048 continue;
1049
1050 case 'R': /* --no-dnssec */
1051 do_dnssec = false0;
1052 continue;
1053
1054 case 'i': /* --interface <ifname|ifaddr> */
1055 if (!use_interface(optarg)) {
1056 fatal_opt(longindex, logger, "too many --interface specifications");
1057 }
1058 continue;
1059
1060 case '1': /* --ike-socket-no-errqueue */
1061 pluto_sock_errqueue = false0;
1062 continue;
1063
1064 case 'W': /* --ike-socket-bufsize <bufsize> */
1065 {
1066 unsigned long u;
1067 check_err(ttoulb(optarg, 0, 10, 0xFFFF, &u), longindex, logger);
1068 if (u == 0) {
1069 fatal_opt(longindex, logger, "must not be 0");
1070 }
1071 pluto_sock_bufsize = u;
1072 continue;
1073 }
1074
1075 case 'p': /* --no-listen-udp */
1076 pluto_listen_udp = false0;
1077 continue;
1078
1079 case 'm': /* --listen-tcp */
1080 pluto_listen_tcp = true1;
1081 continue;
1082
1083 case 'b': /* --rundir <path> */
1084 /*
1085 * ??? work to be done here:
1086 *
1087 * snprintf returns the required space if there
1088 * isn't enough, not -1.
1089 * -1 indicates another kind of error.
1090 */
1091 if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path),
1092 "%s/pluto.ctl", optarg) == -1) {
1093 fatal_opt(longindex, logger, "--rundir argument is invalid for sun_path socket");
1094 }
1095
1096 pfree(pluto_lock_filename);
1097 pluto_lock_filename = alloc_printf("%s/pluto.pid", optarg);
1098 pfreeany(rundir){ typeof(rundir) *pp_ = &(rundir); if (*pp_ != ((void*)0)
) { pfree(*pp_); *pp_ = ((void*)0); } }
;
1099 rundir = clone_str(optarg, "rundir")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("rundir")))
;
1100 continue;
1101
1102 case 's': /* --secretsfile <secrets-file> */
1103 lsw_conf_secretsfile(optarg);
1104 continue;
1105
1106 case 'f': /* --ipsecdir <ipsec-dir> */
1107 lsw_conf_confddir(optarg, logger);
1108 continue;
1109
1110 case 'd': /* --nssdir <path> */
1111 lsw_conf_nssdir(optarg, logger);
1112 continue;
1113
1114 case 'N': /* --debug-none */
1115 cur_debugging = DBG_NONE0;
1116 continue;
1117
1118 case 'A': /* --debug-all */
1119 cur_debugging = DBG_ALL(((lset_t)1 << (DBG_BASE_IX)) | ((lset_t)1 << (DBG_CPU_USAGE_IX
)) | ((lset_t)1 << (DBG_REFCNT_IX)))
;
1120 continue;
1121
1122 case 'y': /* --global-redirect-to */
1123 {
1124 ip_address rip;
1125 check_err(ttoaddress_dns(shunk1(optarg), NULL((void*)0)/*UNSPEC*/, &rip),
1126 longindex, logger);
1127 set_global_redirect_dests(optarg);
1128 llog(RC_LOG, logger,
1129 "all IKE_SA_INIT requests will from now on be redirected to: %s\n",
1130 optarg);
1131 continue;
1132 }
1133
1134 case 'Q': /* --global-redirect */
1135 {
1136 if (streq(optarg, "yes")(strcmp((optarg), ("yes")) == 0)) {
1137 global_redirect = GLOBAL_REDIRECT_YES;
1138 } else if (streq(optarg, "no")(strcmp((optarg), ("no")) == 0)) {
1139 global_redirect = GLOBAL_REDIRECT_NO;
1140 } else if (streq(optarg, "auto")(strcmp((optarg), ("auto")) == 0)) {
1141 global_redirect = GLOBAL_REDIRECT_AUTO;
1142 } else {
1143 llog(RC_LOG, logger,
1144 "invalid option argument for global-redirect (allowed arguments: yes, no, auto)");
1145 }
1146 continue;
1147 }
1148
1149 case '2': /* --keep-alive <delay_secs> */
1150 {
1151 unsigned long u;
1152 check_err(ttoulb(optarg, 0, 10, secs_per_day, &u), longindex, logger);
1153 keep_alive = deltatime(u);
1154 continue;
1155 }
1156
1157 case '5': /* --selftest */
1158 selftest_only = true1;
1159 log_to_stderr_desired = true1;
1160 log_param.log_with_timestamp = false0;
1161 fork_desired = false0;
1162 continue;
1163
1164 case '6': /* --virtual-private */
1165 virtual_private = clone_str(optarg, "virtual_private")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("virtual_private")))
;
1166 continue;
1167
1168 case 'z': /* --config */
1169 {
1170 /*
1171 * Config struct to variables mapper. This will
1172 * overwrite all previously set options. Keep this
1173 * in the same order as long_opts[] is.
1174 */
1175 pfree(conffile);
1176 conffile = clone_str(optarg, "conffile via getopt")((optarg) == ((void*)0) ? ((void*)0) : clone_bytes((optarg), strlen
((optarg)) + 1, ("conffile via getopt")))
;
1177 /* may not return */
1178 struct starter_config *cfg = read_cfg_file(conffile, longindex, logger);
1179
1180 /* leak */
1181 set_cfg_string(&pluto_log_file,
1182 cfg->setup.strings[KSF_LOGFILE]);
1183#ifdef USE_DNSSEC1
1184 set_dnssec_file_names(cfg);
1185#endif
1186
1187 if (pluto_log_file != NULL((void*)0))
1188 log_to_syslog = false0;
1189 /* plutofork= no longer supported via config file */
1190 log_param.log_with_timestamp = cfg->setup.options[KBF_LOGTIME];
1191 log_append = cfg->setup.options[KBF_LOGAPPEND];
1192 log_ip = cfg->setup.options[KBF_LOGIP];
1193 log_to_audit = cfg->setup.options[KBF_AUDIT_LOG];
1194 pluto_drop_oppo_null = cfg->setup.options[KBF_DROP_OPPO_NULL];
1195 pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE];
1196 pluto_ikev1_pol = cfg->setup.options[KBF_GLOBAL_IKEv1];
1197#ifndef USE_IKEv11
1198 if (pluto_ikev1_pol != GLOBAL_IKEv1_ACCEPT) {
1199 llog(RC_LOG, logger, "ignoring ikev1-policy= as IKEv1 support is not compiled in. Incoming IKEv1 packets are silently dropped");
1200 pluto_ikev1_pol = GLOBAL_IKEv1_DROP;
1201 }
1202#endif
1203#ifdef HAVE_SECCOMP1
1204 pluto_seccomp_mode = cfg->setup.options[KBF_SECCOMP];
1205#endif
1206 if (cfg->setup.options[KBF_FORCEBUSY]) {
1207 /* force-busy is obsoleted, translate to ddos-mode= */
1208 pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE] = DDOS_FORCE_BUSY;
1209 }
1210 /* ddos-ike-threshold and max-halfopen-ike */
1211 pluto_ddos_threshold = cfg->setup.options[KBF_DDOS_IKE_THRESHOLD];
1212 pluto_max_halfopen = cfg->setup.options[KBF_MAX_HALFOPEN_IKE];
1213
1214 crl_strict = cfg->setup.options[KBF_CRL_STRICT];
1215
1216 pluto_shunt_lifetime = deltatime(cfg->setup.options[KBF_SHUNTLIFETIME]);
1217
1218 ocsp_enable = cfg->setup.options[KBF_OCSP_ENABLE];
1219 ocsp_strict = cfg->setup.options[KBF_OCSP_STRICT];
1220 ocsp_timeout = cfg->setup.options[KBF_OCSP_TIMEOUT];
1221 ocsp_method = cfg->setup.options[KBF_OCSP_METHOD];
1222 ocsp_post = (ocsp_method == OCSP_METHOD_POST);
1223 ocsp_cache_size = cfg->setup.options[KBF_OCSP_CACHE_SIZE];
1224 ocsp_cache_min_age = cfg->setup.options[KBF_OCSP_CACHE_MIN];
1225 ocsp_cache_max_age = cfg->setup.options[KBF_OCSP_CACHE_MAX];
1226
1227 set_cfg_string(&ocsp_uri,
1228 cfg->setup.strings[KSF_OCSP_URI]);
1229 set_cfg_string(&ocsp_trust_name,
1230 cfg->setup.strings[KSF_OCSP_TRUSTNAME]);
1231
1232 char *tmp_global_redirect = cfg->setup.strings[KSF_GLOBAL_REDIRECT];
1233 if (tmp_global_redirect == NULL((void*)0) || streq(tmp_global_redirect, "no")(strcmp((tmp_global_redirect), ("no")) == 0)) {
1234 /* NULL means it is not specified so default is no */
1235 global_redirect = GLOBAL_REDIRECT_NO;
1236 } else if (streq(tmp_global_redirect, "yes")(strcmp((tmp_global_redirect), ("yes")) == 0)) {
1237 global_redirect = GLOBAL_REDIRECT_YES;
1238 } else if (streq(tmp_global_redirect, "auto")(strcmp((tmp_global_redirect), ("auto")) == 0)) {
1239 global_redirect = GLOBAL_REDIRECT_AUTO;
1240 } else {
1241 global_redirect = GLOBAL_REDIRECT_NO;
1242 llog(RC_LOG, logger, "unknown argument for global-redirect option");
1243 }
1244
1245 crl_check_interval = deltatime(
1246 cfg->setup.options[KBF_CRL_CHECKINTERVAL]);
1247 uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS];
1248#ifdef USE_DNSSEC1
1249 do_dnssec = cfg->setup.options[KBF_DO_DNSSEC];
1250#else
1251 do_dnssec = false0;
1252#endif
1253 /*
1254 * We don't check interfaces= here because that part
1255 * has been dealt with in _stackmanager before we
1256 * started
1257 */
1258 set_cfg_string(&pluto_listen,
1259 cfg->setup.strings[KSF_LISTEN]);
1260
1261 /* ike-socket-bufsize= */
1262 pluto_sock_bufsize = cfg->setup.options[KBF_IKEBUF];
1263 pluto_sock_errqueue = cfg->setup.options[KBF_IKE_ERRQUEUE];
1264
1265 /* listen-tcp= / listen-udp= */
1266 pluto_listen_tcp = cfg->setup.options[KBF_LISTEN_TCP];
1267 pluto_listen_udp = cfg->setup.options[KBF_LISTEN_UDP];
1268
1269 /* nflog-all= */
1270 /* only causes nflog nmber to show in ipsec status */
1271 pluto_nflog_group = cfg->setup.options[KBF_NFLOG_ALL];
1272
1273 /* only causes nflog nmber to show in ipsec status */
1274 pluto_xfrmlifetime = cfg->setup.options[KBF_XFRMLIFETIME];
1275
1276 /* no config option: rundir */
1277 /* secretsfile= */
1278 if (cfg->setup.strings[KSF_SECRETSFILE] &&
1279 *cfg->setup.strings[KSF_SECRETSFILE]) {
1280 lsw_conf_secretsfile(cfg->setup.strings[KSF_SECRETSFILE]);
1281 }
1282 if (cfg->setup.strings[KSF_IPSECDIR] != NULL((void*)0) &&
1283 *cfg->setup.strings[KSF_IPSECDIR] != 0) {
1284 /* ipsecdir= */
1285 lsw_conf_confddir(cfg->setup.strings[KSF_IPSECDIR], logger);
1286 }
1287
1288 if (cfg->setup.strings[KSF_NSSDIR] != NULL((void*)0) &&
1289 *cfg->setup.strings[KSF_NSSDIR] != 0) {
1290 /* nssdir= */
1291 lsw_conf_nssdir(cfg->setup.strings[KSF_NSSDIR], logger);
1292 }
1293
1294 if (cfg->setup.strings[KSF_CURLIFACE]) {
1295 pfreeany(curl_iface){ typeof(curl_iface) *pp_ = &(curl_iface); if (*pp_ != ((
void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }
;
1296 /* curl-iface= */
1297 curl_iface = clone_str(cfg->setup.strings[KSF_CURLIFACE],((cfg->setup.strings[KSF_CURLIFACE]) == ((void*)0) ? ((void
*)0) : clone_bytes((cfg->setup.strings[KSF_CURLIFACE]), strlen
((cfg->setup.strings[KSF_CURLIFACE])) + 1, ("curl-iface= via --config"
)))
1298 "curl-iface= via --config")((cfg->setup.strings[KSF_CURLIFACE]) == ((void*)0) ? ((void
*)0) : clone_bytes((cfg->setup.strings[KSF_CURLIFACE]), strlen
((cfg->setup.strings[KSF_CURLIFACE])) + 1, ("curl-iface= via --config"
)))
;
1299 }
1300
1301 if (cfg->setup.options[KBF_CURLTIMEOUT])
1302 curl_timeout = cfg->setup.options[KBF_CURLTIMEOUT];
1303
1304 if (cfg->setup.strings[KSF_DUMPDIR]) {
1305 pfree(coredir);
1306 /* dumpdir= */
1307 coredir = clone_str(cfg->setup.strings[KSF_DUMPDIR],((cfg->setup.strings[KSF_DUMPDIR]) == ((void*)0) ? ((void*
)0) : clone_bytes((cfg->setup.strings[KSF_DUMPDIR]), strlen
((cfg->setup.strings[KSF_DUMPDIR])) + 1, ("coredir via --config"
)))
1308 "coredir via --config")((cfg->setup.strings[KSF_DUMPDIR]) == ((void*)0) ? ((void*
)0) : clone_bytes((cfg->setup.strings[KSF_DUMPDIR]), strlen
((cfg->setup.strings[KSF_DUMPDIR])) + 1, ("coredir via --config"
)))
;
1309 }
1310 /* vendorid= */
1311 if (cfg->setup.strings[KSF_MYVENDORID]) {
1312 pfree(pluto_vendorid);
1313 pluto_vendorid = clone_str(cfg->setup.strings[KSF_MYVENDORID],((cfg->setup.strings[KSF_MYVENDORID]) == ((void*)0) ? ((void
*)0) : clone_bytes((cfg->setup.strings[KSF_MYVENDORID]), strlen
((cfg->setup.strings[KSF_MYVENDORID])) + 1, ("pluto_vendorid via --config"
)))
1314 "pluto_vendorid via --config")((cfg->setup.strings[KSF_MYVENDORID]) == ((void*)0) ? ((void
*)0) : clone_bytes((cfg->setup.strings[KSF_MYVENDORID]), strlen
((cfg->setup.strings[KSF_MYVENDORID])) + 1, ("pluto_vendorid via --config"
)))
;
1315 }
1316
1317 if (cfg->setup.strings[KSF_STATSBINARY] != NULL((void*)0)) {
1318 if (access(cfg->setup.strings[KSF_STATSBINARY], X_OK1) == 0) {
1319 pfreeany(pluto_stats_binary){ typeof(pluto_stats_binary) *pp_ = &(pluto_stats_binary)
; if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); }
}
;
1320 /* statsbin= */
1321 pluto_stats_binary = clone_str(cfg->setup.strings[KSF_STATSBINARY], "statsbin via --config")((cfg->setup.strings[KSF_STATSBINARY]) == ((void*)0) ? ((void
*)0) : clone_bytes((cfg->setup.strings[KSF_STATSBINARY]), strlen
((cfg->setup.strings[KSF_STATSBINARY])) + 1, ("statsbin via --config"
)))
;
1322 llog(RC_LOG, logger, "statsbinary set to %s", pluto_stats_binary);
1323 } else {
1324 llog(RC_LOG, logger, "statsbinary= '%s' ignored - file does not exist or is not executable",
1325 pluto_stats_binary);
1326 }
1327 }
1328
1329 pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS];
1330 keep_alive = deltatime(cfg->setup.options[KBF_KEEPALIVE]);
1331
1332 set_cfg_string(&virtual_private,
1333 cfg->setup.strings[KSF_VIRTUALPRIVATE]);
1334
1335 set_global_redirect_dests(cfg->setup.strings[KSF_GLOBAL_REDIRECT_TO]);
1336
1337 nhelpers = cfg->setup.options[KBF_NHELPERS];
1338 secctx_attr_type = cfg->setup.options[KBF_SECCTX];
1339 cur_debugging = cfg->setup.options[KBF_PLUTODEBUG];
1340
1341 char *protostack = cfg->setup.strings[KSF_PROTOSTACK];
1342 passert(kernel_ops != NULL)({ _Bool assertion__ = kernel_ops != ((void*)0); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/plutomain.c", .line = 1342
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "kernel_ops != ((void*)0)"
); } (void) 1; })
;
1343
1344 if (!(protostack == NULL((void*)0) || *protostack == '\0')) {
1345 if (streq(protostack, "auto")(strcmp((protostack), ("auto")) == 0) || streq(protostack, "native")(strcmp((protostack), ("native")) == 0) ||
1346 streq(protostack, "nokernel")(strcmp((protostack), ("nokernel")) == 0)) {
1347
1348 llog(RC_LOG, logger, "the option protostack=%s is obsoleted, falling back to protostack=%s",
1349 protostack, kernel_ops->kern_name);
1350 } else if (streq(protostack, "klips")(strcmp((protostack), ("klips")) == 0)) {
1351 fatal(PLUTO_EXIT_KERNEL_FAIL, logger,
1352 "protostack=klips is obsoleted, please migrate to protostack=xfrm");
1353#ifdef XFRM_SUPPORT1
1354 } else if (streq(protostack, "xfrm")(strcmp((protostack), ("xfrm")) == 0) ||
1355 streq(protostack, "netkey")(strcmp((protostack), ("netkey")) == 0)) {
1356 kernel_ops = &xfrm_kernel_ops;
1357#endif
1358#ifdef BSD_KAME
1359 } else if (streq(protostack, "bsd")(strcmp((protostack), ("bsd")) == 0) ||
1360 streq(protostack, "kame")(strcmp((protostack), ("kame")) == 0) ||
1361 streq(protostack, "bsdkame")(strcmp((protostack), ("bsdkame")) == 0)) {
1362 kernel_ops = &bsdkame_kernel_ops;
1363#endif
1364 } else {
1365 llog(RC_LOG, logger, "protostack=%s ignored, using default protostack=%s",
1366 protostack, kernel_ops->kern_name);
1367 }
1368 }
1369
1370 confread_free(cfg);
1371 continue;
1372 }
1373
1374 case OPT_EFENCE_PROTECT:
1375#ifdef USE_EFENCE
1376 /*
1377 * This flag was already processed at the
1378 * start of main(). While it isn't immutable,
1379 * having it apply to all mallocs() is
1380 * presumably better.
1381 */
1382 passert(EF_PROTECT_BELOW)({ _Bool assertion__ = EF_PROTECT_BELOW; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/plutomain.c", .line = 1382, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "EF_PROTECT_BELOW"); } (void
) 1; })
;
1383 passert(EF_PROTECT_FREE)({ _Bool assertion__ = EF_PROTECT_FREE; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/plutomain.c", .line = 1383, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "EF_PROTECT_FREE"); } (void
) 1; })
;
1384#else
1385 llog(RC_LOG, logger, "efence support is not enabled; option --efence-protect ignored");
1386#endif
1387 continue;
1388
1389 case OPT_DEBUG:
1390 {
1391 lmod_t mod = empty_lmod;
1392 if (lmod_arg(&mod, &debug_lmod_info, optarg, true1/*enable*/)) {
1393 cur_debugging = lmod(cur_debugging, mod);
1394 } else {
1395 llog(RC_LOG, logger, "unrecognized --debug '%s' option ignored",
1396 optarg);
1397 }
1398 continue;
1399 }
1400
1401 case OPT_IMPAIR:
1402 {
1403 struct whack_impair impairment;
1404 switch (parse_impair(optarg, &impairment, true1, logger)) {
1405 case IMPAIR_OK:
1406 if (!process_impair(&impairment, NULL((void*)0), true1, logger)) {
1407 fatal_opt(longindex, logger, "not valid from the command line");
1408 }
1409 continue;
1410 case IMPAIR_ERROR:
1411 /* parse_impair() printed error */
1412 exit(PLUTO_EXIT_FAIL);
1413 case IMPAIR_HELP:
1414 /* parse_impair() printed error */
1415 exit(PLUTO_EXIT_OK);
1416 }
1417 continue;
1418 }
1419
1420 default:
1421 bad_case(c)libreswan_bad_case("c", (c), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/plutomain.c", .
line = 1421, }; &here; }))
;
1422 }
1423 }
1424
1425 /*
1426 * Anything (aka an argument) after all options consumed?
1427 */
1428 if (optind != argc) {
15
Assuming 'optind' is equal to 'argc'
16
Taking false branch
1429 llog(RC_LOG, logger, "unexpected trailing argument: %s", argv[optind]);
1430 /* not exit_pluto because we are not initialized yet */
1431 exit(PLUTO_EXIT_FAIL);
1432 }
1433
1434 if (chdir(coredir) == -1) {
17
Assuming the condition is false
18
Taking false branch
1435 int e = errno(*__errno_location ());
1436
1437 llog(RC_LOG, logger, "pluto: warning: chdir(\"%s\") to dumpdir failed (%d: %s)",
1438 coredir, e, strerror(e));
1439 }
1440
1441 oco = lsw_init_options();
1442
1443 if (!selftest_only
18.1
'selftest_only' is false
)
19
Taking true branch
1444 lockfd = create_lock(logger);
20
Calling 'create_lock'
1445 else
1446 lockfd = 0;
1447
1448 /* select between logging methods */
1449
1450 if (log_to_stderr_desired || log_to_file_desired)
1451 log_to_syslog = false0;
1452 if (!log_to_stderr_desired)
1453 log_to_stderr = false0;
1454
1455 /*
1456 * create control socket.
1457 * We must create it before the parent process returns so that
1458 * there will be no race condition in using it. The easiest
1459 * place to do this is before the daemon fork.
1460 */
1461 if (!selftest_only) {
1462 diag_t d = init_ctl_socket(logger);
1463 if (d != NULL((void*)0)) {
1464 fatal_diag(PLUTO_EXIT_SOCKET_FAIL, logger, &d, "%s", "");
1465 }
1466 }
1467
1468 /* If not suppressed, do daemon fork */
1469 if (fork_desired) {
1470#if USE_DAEMON0
1471 if (daemon(TRUE1, true1) < 0) {
1472 fatal_errno(PLUTO_EXIT_FORK_FAIL, logger, "daemon failed");
1473 }
1474 /*
1475 * Parent just exits, so need to fill in our own PID
1476 * file. This is racy, since the file won't be
1477 * created until after the parent has exited.
1478 *
1479 * Since "ipsec start" invokes pluto with --nofork, it
1480 * is probably safer to leave this feature disabled
1481 * then implement it using the daemon call.
1482 */
1483 (void) fill_lock(lockfd, getpid());
1484#elif USE_FORK1
1485 {
1486 pid_t pid = fork();
1487
1488 if (pid < 0) {
1489 fatal_errno(PLUTO_EXIT_FORK_FAIL, logger, errno(*__errno_location ()),
1490 "fork failed");
1491 }
1492
1493 if (pid == 0) {
1494 /*
1495 * parent fills in the PID.
1496 */
1497 close(lockfd);
1498 } else {
1499 /*
1500 * parent: die, after filling PID into lock
1501 * file.
1502 * must not use exit_pluto: lock would be
1503 * removed!
1504 */
1505 exit(fill_lock(lockfd, pid) ? 0 : 1);
1506 }
1507 }
1508#else
1509 fatal(PLUTO_EXIT_FORK_FAIL, logger, "fork/daemon not supported; specify --nofork");
1510#endif
1511 if (setsid() < 0) {
1512 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
1513 "setsid() failed in main()");
1514 }
1515 } else {
1516 /* no daemon fork: we have to fill in lock file */
1517 (void) fill_lock(lockfd, getpid());
1518
1519 if (isatty(fileno(stdoutstdout))) {
1520 fprintf(stdoutstdout, "Pluto initialized\n");
1521 fflush(stdoutstdout);
1522 }
1523 }
1524
1525 /*
1526 * Close stdin, stdout, and when not needed, stderr. This
1527 * should just leave CTL_FD.
1528 *
1529 * Follow that by directing the closed file descriptors at
1530 * /dev/null. UNIX always uses the lowest file descriptor
1531 * when opening a file.
1532 */
1533 close(STDIN_FILENO0);/*stdin*/
1534 close(STDOUT_FILENO1);/*stdout*/
1535 if (!log_to_stderr) {
1536 close(STDERR_FILENO2); /*stderr*/
1537 }
1538 /* make sure that stdin, stdout, stderr are reserved */
1539 passert(open("/dev/null", O_RDONLY) == STDIN_FILENO)({ _Bool assertion__ = open("/dev/null", 00) == 0; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/plutomain.c", .line = 1539
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "open(\"/dev/null\", 00) == 0"
); } (void) 1; })
;
1540 /* open("/dev/null", O_WRONLY) == STDOUT_FILENO? */
1541 passert(dup2(0, STDOUT_FILENO) == STDOUT_FILENO)({ _Bool assertion__ = dup2(0, 1) == 1; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/plutomain.c", .line = 1541, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "dup2(0, 1) == 1"); } (void
) 1; })
;
1542 /* dup2(STDOUT_FILENO, STDERR_FILENO) == STDERR_FILENO? */
1543 passert(log_to_stderr || dup2(0, STDERR_FILENO) == STDERR_FILENO)({ _Bool assertion__ = log_to_stderr || dup2(0, 2) == 2; if (
!assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/plutomain.c", .
line = 1543, }; &here; }); const struct logger *logger_ =
&failsafe_logger; llog_passert(logger_, here, "%s", "log_to_stderr || dup2(0, 2) == 2"
); } (void) 1; })
;
1544
1545 /*
1546 * Check for no unexpected file descriptors.
1547 */
1548 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {/* even set? */
1549 for (int fd = getdtablesize() - 1; fd >= 0; fd--) {
1550 if (fd == ctl_fd ||
1551 fd == STDIN_FILENO0 ||
1552 fd == STDOUT_FILENO1 ||
1553 fd == STDERR_FILENO2) {
1554 continue;
1555 }
1556 struct stat s;
1557 if (fstat(fd, &s) == 0) {
1558 llog(RC_LOG_SERIOUS, logger, "pluto: unexpected open file descriptor %d", fd);
1559 }
1560 }
1561 }
1562
1563 /*
1564 * Initialize logging then switch to the real logger.
1565 */
1566 pluto_init_log(log_param);
1567 struct logger global_logger = GLOBAL_LOGGER(null_fd)(struct logger) { .where = ({ static const struct where here =
{ .func = __func__, .file = "programs/pluto/plutomain.c", .line
= 1567, }; &here; }), .global_whackfd = ((struct fd *) (
(void*)0)), .object = ((void*)0), .object_vec = &logger_global_vec
, }
;
1568 /*
1569 * The string_logger() dbg_alloc() message went down a rabit
1570 * hole (aka the console) so fake one up here.
1571 */
1572 dbg_alloc("logger", logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/plutomain.c", .line = 1572, }; &here; }
)
);
1573 free_logger(&logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/plutomain.c", .line = 1573, }; &here; }
)
);
1574 logger = &global_logger;
1575
1576 init_constants();
1577 init_pluto_constants();
1578
1579 pluto_init_nss(oco->nssdir, logger);
1580 if (libreswan_fipsmode()) {
1581 /*
1582 * clear out --debug-crypt if set
1583 *
1584 * impairs are also not allowed but cannot come in via
1585 * ipsec.conf, only whack
1586 */
1587 if (cur_debugging & DBG_PRIVATE((lset_t)1 << (DBG_PRIVATE_IX))) {
1588 cur_debugging &= ~DBG_PRIVATE((lset_t)1 << (DBG_PRIVATE_IX));
1589 llog(RC_LOG_SERIOUS, logger, "FIPS mode: debug-private disabled as such logging is not allowed");
1590 }
1591 /*
1592 * clear out --debug-crypt if set
1593 *
1594 * impairs are also not allowed but cannot come in via
1595 * ipsec.conf, only whack
1596 */
1597 if (cur_debugging & DBG_CRYPT((lset_t)1 << (DBG_CRYPT_IX))) {
1598 cur_debugging &= ~DBG_CRYPT((lset_t)1 << (DBG_CRYPT_IX));
1599 llog(RC_LOG_SERIOUS, logger, "FIPS mode: debug-crypt disabled as such logging is not allowed");
1600 }
1601 }
1602
1603 init_crypt_symkey(logger);
1604
1605 /*
1606 * If impaired, force the mode change; and verify the
1607 * consequences. Always run the tests as combinations such as
1608 * NSS in fips mode but as out of it could be bad.
1609 */
1610
1611 if (impair.force_fips) {
1612 llog(RC_LOG, logger, "IMPAIR: forcing FIPS checks to true to emulate FIPS mode");
1613 lsw_set_fips_mode(LSW_FIPS_ON);
1614 }
1615
1616 bool_Bool nss_fips_mode = PK11_IsFIPS();
1617 if (libreswan_fipsmode()) {
1618 llog(RC_LOG, logger, "FIPS mode enabled for pluto daemon");
1619 if (nss_fips_mode) {
1620 llog(RC_LOG, logger, "NSS library is running in FIPS mode");
1621 } else {
1622 fatal(PLUTO_EXIT_FIPS_FAIL, logger, "pluto in FIPS mode but NSS library is not");
1623 }
1624 } else {
1625 llog(RC_LOG, logger, "FIPS mode disabled for pluto daemon");
1626 if (nss_fips_mode) {
1627 llog(RC_LOG_SERIOUS, logger, "Warning: NSS library is running in FIPS mode");
1628 }
1629 }
1630
1631 if (ocsp_enable) {
1632 /* may not return */
1633 diag_t d = init_nss_ocsp(ocsp_uri, ocsp_trust_name,
1634 ocsp_timeout, ocsp_strict, ocsp_cache_size,
1635 ocsp_cache_min_age, ocsp_cache_min_age,
1636 (ocsp_method == OCSP_METHOD_POST), logger);
1637 if (d != NULL((void*)0)) {
1638 fatal_diag(PLUTO_EXIT_NSS_FAIL, logger, &d, "initializing NSS OCSP failed: ");
1639 }
1640 llog(RC_LOG, logger, "NSS OCSP started");
1641 }
1642
1643#ifdef FIPS_CHECK
1644 llog(RC_LOG, logger, "FIPS HMAC integrity support [enabled]");
1645 bool_Bool fips_files = FIPSCHECK_verify_files(fips_package_files);
1646 if (fips_files) {
1647 llog(RC_LOG, logger, "FIPS HMAC integrity verification self-test passed");
1648 } else if (libreswan_fipsmode()) {
1649 fatal(PLUTO_EXIT_FIPS_FAIL, logger, "FIPS HMAC integrity verification self-test FAILED");
1650 } else {
1651 llog(RC_LOG_SERIOUS, logger, "FIPS HMAC integrity verification self-test FAILED");
1652 }
1653#else
1654 llog(RC_LOG, logger, "FIPS HMAC integrity support [disabled]");
1655#endif
1656
1657#ifdef HAVE_LIBCAP_NG1
1658 /*
1659 * Drop capabilities - this generates a false positive valgrind warning
1660 * See: http://marc.info/?l=linux-security-module&m=125895232029657
1661 *
1662 * We drop these after creating the pluto socket or else we can't
1663 * create a socket if the parent dir is non-root (eg openstack)
1664 */
1665 capng_clear(CAPNG_SELECT_BOTH);
1666
1667 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
1668 CAP_NET_BIND_SERVICE10, CAP_NET_ADMIN12, CAP_NET_RAW13,
1669 CAP_IPC_LOCK14, CAP_AUDIT_WRITE29,
1670 /* for google authenticator pam */
1671 CAP_SETGID6, CAP_SETUID7,
1672 CAP_DAC_READ_SEARCH2,
1673 -1);
1674 /*
1675 * We need to retain some capabilities for our children (updown):
1676 * CAP_NET_ADMIN to change routes
1677 * (we also need it for some setsockopt() calls in main process)
1678 * CAP_NET_RAW for iptables -t mangle
1679 * CAP_DAC_READ_SEARCH for pam / google authenticator
1680 *
1681 */
1682 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN12, CAP_NET_RAW13,
1683 CAP_DAC_READ_SEARCH2, -1);
1684 capng_apply(CAPNG_SELECT_BOTH);
1685 llog(RC_LOG, logger, "libcap-ng support [enabled]");
1686#else
1687 llog(RC_LOG, logger, "libcap-ng support [disabled]");
1688#endif
1689
1690#ifdef USE_LINUX_AUDIT1
1691 linux_audit_init(log_to_audit, logger);
1692#else
1693 llog(RC_LOG, logger, "Linux audit support [disabled]");
1694#endif
1695
1696 {
1697 const char *vc = ipsec_version_code();
1698 llog(RC_LOG, logger, "Starting Pluto (Libreswan Version %s%s) pid:%u",
1699 vc, compile_time_interop_options, getpid());
1700 }
1701
1702 llog(RC_LOG, logger, "core dump dir: %s", coredir);
1703 if (oco->secretsfile && *oco->secretsfile)
1704 llog(RC_LOG, logger, "secrets file: %s", oco->secretsfile);
1705
1706 llog(RC_LOG, logger, leak_detective ?
1707 "leak-detective enabled" : "leak-detective disabled");
1708
1709 llog(RC_LOG, logger, "NSS crypto [enabled]");
1710
1711#ifdef USE_PAM_AUTH1
1712 llog(RC_LOG, logger, "XAUTH PAM support [enabled]");
1713#else
1714 llog(RC_LOG, logger, "XAUTH PAM support [disabled]");
1715#endif
1716
1717 /*
1718 * Log impair-* functions that were enabled
1719 */
1720 if (have_impairments()) {
1721 LLOG_JAMBUF(RC_LOG, logger, buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (({ if (((RC_LOG) &
NO_PREFIX) == ((lset_t)0) && (((RC_LOG) & STREAM_MASK
) != DEBUG_STREAM || (cur_debugging & (((lset_t)1 <<
(DBG_ADD_PREFIX_IX)))))) { (logger)->object_vec->jam_object_prefix
(buf, (logger)->object); } }); buf != ((void*)0); jambuf_to_logger
(buf, (logger), RC_LOG), buf = ((void*)0))
{
1722 jam(buf, "Warning: impairments enabled: ");
1723 jam_impairments(buf, "+");
1724 }
1725 }
1726
1727/* Initialize all of the various features */
1728
1729 init_state_db();
1730 init_connection_db();
1731 init_server_fork();
1732 init_server(logger);
1733
1734 init_rate_log();
1735 init_nat_traversal(keep_alive, logger);
1736
1737 init_virtual_ip(virtual_private, logger);
1738 /* obsoleted by nss code: init_rnd_pool(); */
1739 init_root_certs();
1740 init_secret(logger);
1741#ifdef USE_IKEv11
1742 init_ikev1(logger);
1743#endif
1744 init_ikev2();
1745 init_states();
1746 init_revival();
1747 init_connections();
1748 init_host_pair();
1749 init_ike_alg(logger);
1750 test_ike_alg(logger);
1751
1752 if (selftest_only) {
1753 /*
1754 * skip pluto_exit()
1755 * Not all components were initialized and
1756 * no lock files were created.
1757 */
1758 exit(PLUTO_EXIT_OK);
1759 }
1760
1761 start_server_helpers(nhelpers, logger);
1762 init_kernel(logger);
1763 init_vendorid(logger);
1764#if defined(LIBCURL1) || defined(LIBLDAP)
1765 start_crl_fetch_helper(logger);
1766#endif
1767 init_labeled_ipsec(logger);
1768#ifdef USE_SYSTEMD_WATCHDOG
1769 pluto_sd_init(logger);
1770#endif
1771
1772#ifdef USE_DNSSEC1
1773 {
1774 diag_t d = unbound_event_init(get_pluto_event_base(), do_dnssec,
1775 pluto_dnssec_rootfile, pluto_dnssec_trusted,
1776 logger/*for-warnings*/);
1777 if (d != NULL((void*)0)) {
1778 fatal_diag(PLUTO_EXIT_UNBOUND_FAIL, logger, &d, "%s", "");
1779 }
1780 }
1781#endif
1782
1783 run_server(conffile, logger);
1784}
1785
1786void show_setup_plutomain(struct show *s)
1787{
1788 show_separator(s);
1789 show_comment(s, "config setup options:");
1790 show_separator(s);
1791 show_comment(s, "configdir=%s, configfile=%s, secrets=%s, ipsecdir=%s",
1792 oco->confdir,
1793 conffile, /* oco contains only a copy of hardcoded default */
1794 oco->secretsfile,
1795 oco->confddir);
1796
1797 show_comment(s, "nssdir=%s, dumpdir=%s, statsbin=%s",
1798 oco->nssdir,
1799 coredir,
1800 pluto_stats_binary == NULL((void*)0) ? "unset" : pluto_stats_binary);
1801
1802#ifdef USE_DNSSEC1
1803 show_comment(s, "dnssec-rootkey-file=%s, dnssec-trusted=%s",
1804 pluto_dnssec_rootfile == NULL((void*)0) ? "<unset>" : pluto_dnssec_rootfile,
1805 pluto_dnssec_trusted == NULL((void*)0) ? "<unset>" : pluto_dnssec_trusted);
1806#endif
1807
1808 show_comment(s, "sbindir=%s, libexecdir=%s",
1809 IPSEC_SBINDIR"/usr/local/sbin",
1810 IPSEC_EXECDIR"/usr/local/libexec/ipsec");
1811
1812 show_comment(s, "pluto_version=%s, pluto_vendorid=%s, audit-log=%s",
1813 ipsec_version_code(),
1814 pluto_vendorid,
1815 bool_str(log_to_audit));
1816
1817 show_comment(s,
1818 "nhelpers=%d, uniqueids=%s, "
1819 "dnssec-enable=%s, "
1820 "logappend=%s, logip=%s, shuntlifetime=%jds, xfrmlifetime=%jds",
1821 nhelpers,
1822 bool_str(uniqueIDs),
1823 bool_str(do_dnssec),
1824 bool_str(log_append),
1825 bool_str(log_ip),
1826 deltasecs(pluto_shunt_lifetime),
1827 (intmax_t) pluto_xfrmlifetime
1828 );
1829
1830 show_comment(s,
1831 "ddos-cookies-threshold=%d, ddos-max-halfopen=%d, ddos-mode=%s, ikev1-policy=%s",
1832 pluto_ddos_threshold,
1833 pluto_max_halfopen,
1834 (pluto_ddos_mode == DDOS_AUTO) ? "auto" :
1835 (pluto_ddos_mode == DDOS_FORCE_BUSY) ? "busy" : "unlimited",
1836 pluto_ikev1_pol == GLOBAL_IKEv1_ACCEPT ? "accept" :
1837 pluto_ikev1_pol == GLOBAL_IKEv1_REJECT ? "reject" : "drop");
1838
1839 show_comment(s,
1840 "ikebuf=%d, msg_errqueue=%s, crl-strict=%s, crlcheckinterval=%jd, listen=%s, nflog-all=%d",
1841 pluto_sock_bufsize,
1842 bool_str(pluto_sock_errqueue),
1843 bool_str(crl_strict),
1844 deltasecs(crl_check_interval),
1845 pluto_listen != NULL((void*)0) ? pluto_listen : "<any>",
1846 pluto_nflog_group
1847 );
1848
1849 show_comment(s,
1850 "ocsp-enable=%s, ocsp-strict=%s, ocsp-timeout=%d, ocsp-uri=%s",
1851 bool_str(ocsp_enable),
1852 bool_str(ocsp_strict),
1853 ocsp_timeout,
1854 ocsp_uri != NULL((void*)0) ? ocsp_uri : "<unset>"
1855 );
1856 show_comment(s,
1857 "ocsp-trust-name=%s",
1858 ocsp_trust_name != NULL((void*)0) ? ocsp_trust_name : "<unset>"
1859 );
1860
1861 show_comment(s,
1862 "ocsp-cache-size=%d, ocsp-cache-min-age=%d, ocsp-cache-max-age=%d, ocsp-method=%s",
1863 ocsp_cache_size, ocsp_cache_min_age, ocsp_cache_max_age,
1864 ocsp_method == OCSP_METHOD_GET ? "get" : "post"
1865 );
1866
1867 show_comment(s,
1868 "global-redirect=%s, global-redirect-to=%s",
1869 enum_name(&allow_global_redirect_names, global_redirect),
1870 strlen(global_redirect_to()) > 0 ? global_redirect_to() : "<unset>"
1871 );
1872
1873#ifdef HAVE_LABELED_IPSEC1
1874 show_comment(s, "secctx-attr-type=%d", secctx_attr_type);
1875#else
1876 show_comment(s, "secctx-attr-type=<unsupported>");
1877#endif
1878}