static void show_system_security(void) { int selinux = libreswan_selinux(); #ifdef FIPS_CHECK int fipsmode = libreswan_fipsmode(); #else int fipsmode = 0; #endif whack_log(RC_COMMENT, " "); /* spacer */ whack_log(RC_COMMENT, "fips mode=%s;", fipsmode == 0 ? "disabled" : fipsmode == 1 ? "enabled" : "error(disabled)"); whack_log(RC_COMMENT, "SElinux=%s", selinux == 0 ? "disabled" : selinux == 1 ? "enabled" : "indeterminate"); whack_log(RC_COMMENT, " "); /* spacer */ }
static bool load_conn(struct ub_ctx *dnsctx, struct starter_conn *conn, struct config_parsed *cfgp, struct section_list *sl, bool alsoprocessing, bool defaultconn, bool resolvip, err_t *perr) { bool err = FALSE; err |= load_conn_basic(conn, sl, defaultconn ? k_default : k_set, perr); move_comment_list(&conn->comments, &sl->comments); if (err) return err; if (conn->strings[KSF_ALSO] != NULL && !alsoprocessing) { starter_log(LOG_LEVEL_INFO, "also= is not valid in section '%s'", sl->name); return TRUE; /* error */ } /* now, process the also's */ if (conn->alsos) FREE_LIST(conn->alsos); conn->alsos = new_list(conn->strings[KSF_ALSO]); if (alsoprocessing && conn->alsos != NULL) { struct section_list *sl1; /* note: for the duration of this loop body * conn->alsos is migrated to local variable alsos. */ char **alsos = conn->alsos; int alsosize; int alsoplace; conn->alsos = NULL; /* reset all of the "beenhere" flags */ for (sl1 = cfgp->sections.tqh_first; sl1 != NULL; sl1 = sl1->link.tqe_next) sl1->beenhere = FALSE; sl->beenhere = TRUE; /* count them */ for (alsosize = 0; alsos[alsosize] != NULL; alsosize++) ; alsoplace = 0; while (alsoplace < alsosize && alsos[alsoplace] != NULL && alsoplace < ALSO_LIMIT) { /* * for each also= listed, go find this section's keyword list, and * load it as well. This may extend the also= list (and the end), * which we handle by zeroing the also list, and adding to it after * checking for duplicates. */ for (sl1 = cfgp->sections.tqh_first; sl1 != NULL && !streq(alsos[alsoplace], sl1->name); sl1 = sl1->link.tqe_next) ; starter_log(LOG_LEVEL_DEBUG, "\twhile loading conn '%s' also including '%s'", conn->name, alsos[alsoplace]); /* * if we found something that matches by name, and we haven't be * there, then process it. */ if (sl1 && !sl1->beenhere) { conn->strings_set[KSF_ALSO] = FALSE; pfreeany(conn->strings[KSF_ALSO]); conn->strings[KSF_ALSO] = NULL; sl1->beenhere = TRUE; /* translate things, but do not replace earlier settings!*/ err |= translate_conn(conn, sl1, k_set, perr); if (conn->strings[KSF_ALSO] != NULL) { /* now, check out the KSF_ALSO, and extend list if we need to */ char **newalsos = new_list( conn->strings[KSF_ALSO]); if (newalsos != NULL) { char **ra; int newalsoplace; /* count them */ for (newalsoplace = 0; newalsos[newalsoplace] != NULL; newalsoplace++) ; /* extend conn->alss */ ra = alloc_bytes((alsosize + newalsoplace + 1) * sizeof(char *), "conn->alsos"); memcpy(ra, alsos, alsosize * sizeof(char *)); pfree(alsos); alsos = ra; for (newalsoplace = 0; newalsos[newalsoplace] != NULL; newalsoplace++) { assert(conn != NULL); assert(conn->name != NULL); starter_log( LOG_LEVEL_DEBUG, "\twhile processing section '%s' added also=%s", sl1->name, newalsos[newalsoplace]); alsos[alsosize++] = clone_str(newalsos[newalsoplace], "alsos"); } alsos[alsosize] = NULL; } FREE_LIST(newalsos); } } alsoplace++; } /* migrate alsos back to conn->alsos */ conn->alsos = alsos; if (alsoplace >= ALSO_LIMIT) { starter_log(LOG_LEVEL_INFO, "while loading conn '%s', too many also= used at section %s. Limit is %d", conn->name, alsos[alsoplace], ALSO_LIMIT); return TRUE; /* error */ } } #ifdef PARSER_TYPE_DEBUG /* translate strings/numbers into conn items */ starter_log(LOG_LEVEL_DEBUG, "#checking options_set[KBF_TYPE,%d]=%d %d", KBF_TYPE, conn->options_set[KBF_TYPE], conn->options[KBF_TYPE]); #endif if (conn->options_set[KBF_TYPE]) { switch ((enum keyword_satype)conn->options[KBF_TYPE]) { case KS_TUNNEL: conn->policy |= POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_TRANSPORT: conn->policy &= ~POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_PASSTHROUGH: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_PASS; break; case KS_DROP: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_DROP; break; case KS_REJECT: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_REJECT; break; } } if (conn->options_set[KBF_FAILURESHUNT]) { conn->policy &= ~POLICY_FAIL_MASK; switch(conn->options[KBF_FAILURESHUNT]) { case KFS_FAIL_NONE: conn->policy |= POLICY_FAIL_NONE; break; case KFS_FAIL_PASS: conn->policy |= POLICY_FAIL_PASS; break; case KFS_FAIL_DROP: conn->policy |= POLICY_FAIL_DROP; break; case KFS_FAIL_REJECT: conn->policy |= POLICY_FAIL_REJECT; break; } } if (conn->options_set[KBF_NEGOTIATIONSHUNT]) { switch(conn->options[KBF_NEGOTIATIONSHUNT]) { case KNS_FAIL_PASS: conn->policy |= POLICY_NEGO_PASS; break; case KNS_FAIL_DROP: conn->policy &= ~POLICY_NEGO_PASS; break; } } KW_POLICY_FLAG(KBF_COMPRESS, POLICY_COMPRESS); KW_POLICY_FLAG(KBF_PFS, POLICY_PFS); /* reset authby flags */ if (conn->options_set[KBF_AUTHBY]) { conn->policy &= ~(POLICY_ID_AUTH_MASK); #ifdef FIPS_CHECK if (libreswan_fipsmode()) { if (LIN(POLICY_PSK, conn->options[KBF_AUTHBY])) { starter_log(LOG_LEVEL_INFO, "while loading conn '%s', PSK not allowed in FIPS mode with NSS", conn->name); return TRUE; /* error */ } } #endif conn->policy |= conn->options[KBF_AUTHBY]; #ifdef STARTER_POLICY_DEBUG starter_log(LOG_LEVEL_DEBUG, "%s: setting conn->policy=%08x (%08x)", conn->name, (unsigned int)conn->policy, conn->options[KBF_AUTHBY]); #endif } KW_POLICY_NEGATIVE_FLAG(KBF_IKEPAD, POLICY_NO_IKEPAD); KW_POLICY_NEGATIVE_FLAG(KBF_REKEY, POLICY_DONT_REKEY); KW_POLICY_FLAG(KBF_AGGRMODE, POLICY_AGGRESSIVE); KW_POLICY_FLAG(KBF_MODECONFIGPULL, POLICY_MODECFG_PULL); KW_POLICY_FLAG(KBF_OVERLAPIP, POLICY_OVERLAPIP); KW_POLICY_FLAG(KBF_IKEv2_ALLOW_NARROWING, POLICY_IKEV2_ALLOW_NARROWING); KW_POLICY_FLAG(KBF_IKEv2_PAM_AUTHORIZE, POLICY_IKEV2_PAM_AUTHORIZE); if (conn->strings_set[KSF_ESP]) conn->esp = clone_str(conn->strings[KSF_ESP],"KSF_ESP"); #ifdef HAVE_LABELED_IPSEC if (conn->strings_set[KSF_POLICY_LABEL]) conn->policy_label = clone_str(conn->strings[KSF_POLICY_LABEL],"KSF_POLICY_LABEL"); if (conn->policy_label != NULL) starter_log(LOG_LEVEL_DEBUG, "connection's policy label: %s", conn->policy_label); #endif if (conn->strings_set[KSF_IKE]) conn->ike = clone_str(conn->strings[KSF_IKE],"KSF_IKE"); if (conn->strings_set[KSF_MODECFGDNS1]) { conn->modecfg_dns1 = clone_str(conn->strings[KSF_MODECFGDNS1],"KSF_MODECFGDNS1"); } if (conn->strings_set[KSF_MODECFGDNS2]) { conn->modecfg_dns2 = clone_str(conn->strings[KSF_MODECFGDNS2], "KSF_MODECFGDNS2"); } if (conn->strings_set[KSF_MODECFGDOMAIN]) { conn->modecfg_domain = clone_str(conn->strings[KSF_MODECFGDOMAIN],"KSF_MODECFGDOMAIN"); } if (conn->strings_set[KSF_MODECFGBANNER]) { conn->modecfg_banner = clone_str(conn->strings[KSF_MODECFGBANNER],"KSF_MODECFGBANNER"); } if (conn->strings_set[KSF_CONNALIAS]) conn->connalias = clone_str(conn->strings[KSF_CONNALIAS],"KSF_CONNALIAS"); if (conn->options_set[KBF_PHASE2]) { conn->policy &= ~(POLICY_AUTHENTICATE | POLICY_ENCRYPT); conn->policy |= conn->options[KBF_PHASE2]; } if (conn->options_set[KBF_IKEv2]) { lset_t policy = LEMPTY; switch (conn->options[KBF_IKEv2]) { case fo_never: policy = POLICY_IKEV1_ALLOW; break; case fo_permit: /* this is the default for now */ policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW; break; case fo_propose: policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; case fo_insist: policy = POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; } conn->policy = (conn->policy & ~POLICY_IKEV2_MASK) | policy; } if (conn->options_set[KBF_IKE_FRAG]) { switch (conn->options[KBF_IKE_FRAG]) { case ynf_no: conn->policy &= ~POLICY_IKE_FRAG_ALLOW; conn->policy &= ~POLICY_IKE_FRAG_FORCE; break; case ynf_yes: /* this is the default */ conn->policy |= POLICY_IKE_FRAG_ALLOW; break; case ynf_force: conn->policy |= POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE; break; } } if (conn->options_set[KBF_SAREFTRACK]) { switch (conn->options[KBF_SAREFTRACK]) { case sat_yes: /* this is the default */ conn->policy |= POLICY_SAREF_TRACK; break; case sat_conntrack: conn->policy |= POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK; break; case sat_no: conn->policy &= ~POLICY_SAREF_TRACK; conn->policy &= ~POLICY_SAREF_TRACK_CONNTRACK; break; } } err |= validate_end(dnsctx, conn, &conn->left, "left", resolvip, perr); err |= validate_end(dnsctx, conn, &conn->right, "right", resolvip, perr); /* * TODO: * verify both ends are using the same inet family, if one end * is "%any" or "%defaultroute", then perhaps adjust it. * ensource this for left,leftnexthop,right,rightnexthop * Ideally, phase out connaddrfamily= which now wrongly assumes * left,leftnextop,leftsubnet are the same inet family * Currently, these tests are implicitely done, and wrongly * in case of 6in4 and 4in6 tunnels */ if (conn->options_set[KBF_AUTO]) conn->desired_state = conn->options[KBF_AUTO]; return err; }
int main(int argc, char **argv) { #if 0 NSS_NoDB_Init("."); if (!test_aes_cbc(&algo_aes_cbc)) { printf("aes-cbc failed\n"); } if (!test_camellia_cbc(&algo_camellia_cbc)) { printf("camellia-cbc failed\n"); } if (!test_aes_ctr(&algo_aes_ctr)) { printf("aes-ctr failed\n"); } exit(0); #endif int lockfd; /* * We read the intentions for how to log from command line options * and the config file. Then we prepare to be able to log, but until * then log to stderr (better then nothing). Once we are ready to * actually do loggin according to the methods desired, we set the * variables for those methods */ bool log_to_stderr_desired = FALSE; bool log_to_file_desired = FALSE; { int i; /* MUST BE BEFORE ANY allocs */ for (i = 1; i < argc; ++i) { if (streq(argv[i], "--leak-detective")) leak_detective = TRUE; } } pluto_name = argv[0]; coredir = clone_str("/var/run/pluto", "coredir in main()"); pluto_vendorid = clone_str(ipsec_version_vendorid(), "vendorid in main()"); /* set up initial defaults that need a cast */ pluto_shared_secrets_file = DISCARD_CONST(char *, SHARED_SECRETS_FILE); unsigned int keep_alive = 0; /* Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; libreswan_passert_fail = passert_fail; /* handle arguments */ for (;; ) { /* * Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int longindex = -1; int c = getopt_long(argc, argv, "", long_opts, &longindex); const char *optname = NULL; err_t ugh = NULL; /* complaint from case */ unsigned long u = 0; /* scratch for case */ if (longindex != -1) { const char *optmeta; optname = long_opts[longindex].name; optmeta = optname + strlen(optname) + 1; /* after '\0' */ switch (optmeta[0]) { case '_': libreswan_log("warning: option \"--%s\" with '_' in its name is obsolete; use '-'", optname); break; case '>': libreswan_log("warning: option \"--%s\" is obsolete; use \"--%s\"", optname, optmeta + 1); break; case '!': libreswan_log("warning: option \"--%s\" is obsolete; ignored", optname); continue; /* ignore it! */ } } /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* * Long option already handled by getopt_long. * Not currently used since we always set flag to NULL. */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ invocation_fail(NULL); break; case 'h': /* --help */ usage(); break; /* not actually reached */ case 'X': /* --leak-detective */ /* * This flag was already processed at the start of main() * because leak_detective must be immutable from before * the first alloc(). * If this option is specified, we must have already * set it at the start of main(), so assert it. */ passert(leak_detective); continue; case 'C': /* --coredir */ pfree(coredir); coredir = clone_str(optarg, "coredir via getopt"); continue; case 'V': /* --vendorid */ pfree(pluto_vendorid); coredir = clone_str(optarg, "pluto_vendorid via getopt"); continue; case 'S': /* --statsdir */ pfreeany(pluto_stats_binary); pluto_stats_binary = clone_str(optarg, "statsbin"); continue; case 'v': /* --version */ printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); /* not exit_pluto because we are not initialized yet */ exit(0); break; /* not actually reached */ case 'j': /* --nhelpers */ if (streq(optarg, "-1")) { nhelpers = -1; } else { ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; nhelpers = u; } continue; case 'c': /* --seedbits */ pluto_nss_seedbits = atoi(optarg); if (pluto_nss_seedbits == 0) { printf("pluto: seedbits must be an integer > 0"); /* not exit_pluto because we are not initialized yet */ exit(PLUTO_EXIT_NSS_FAIL); } continue; #ifdef HAVE_LABELED_IPSEC case 'w': /* --secctx-attr-type */ ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u); if (ugh != NULL) break; if (u != SECCTX && u != 10) { ugh = "must be a positive 32001 (default) or 10 (for backward compatibility)"; break; } secctx_attr_type = u; continue; #endif case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'g': /* --logfile */ pluto_log_file = optarg; log_to_file_desired = TRUE; continue; case 't': /* --log-no-time */ log_with_timestamp = FALSE; continue; case '7': /* --log-no-append */ log_append = FALSE; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg, 0, AF_UNSPEC, &lip); if (e != NULL) { /* *??? should we continue on failure? * If not, use ugh mechanism. */ libreswan_log( "invalid listen argument ignored: %s\n", e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); libreswan_log( "bind() will be filtered for %s\n", pluto_listen); } } continue; case 'M': /* --use-mast */ kern_interface = USE_MASTKLIPS; continue; case 'F': /* --use-bsdkame */ kern_interface = USE_BSDKAME; continue; case 'K': /* --use-netkey */ kern_interface = USE_NETKEY; continue; case 'n': /* --use-nostack */ kern_interface = NO_KERNEL; continue; case 'D': /* --force-busy */ pluto_ddos_mode = DDOS_FORCE_BUSY; continue; case 'U': /* --force-unlimited */ pluto_ddos_mode = DDOS_FORCE_UNLIMITED; continue; case 'Z': /* --curl-iface */ curl_iface = optarg; continue; case 'I': /* --curl-timeout */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u <= 0) { ugh = "must not be < 1"; break; } curl_timeout = u; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue; case 'o': strict_ocsp_policy = TRUE; continue; case 'O': ocsp_enable = TRUE; continue; case 'Y': ocsp_default_uri = optarg; continue; case 'J': ocsp_trust_name = optarg; continue; case 'T': /* --ocsp_timeout <seconds> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } ocsp_timeout = u; continue; case 'x': /* --crlcheckinterval <seconds> */ ugh = ttoulb(optarg, 0, 10, TIME_T_MAX, &u); if (ugh != NULL) break; crl_check_interval = deltatime(u); continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) { ugh = "too many --interface specifications"; break; } continue; /* * This option does not really work, as this is the "left" * site only, you also need --to --ikeport again later on * It will result in: yourport -> 500, still not bypassing * filters */ case 'p': /* --ikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_port = u; continue; case 'q': /* --natikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_nat_port = u; continue; case 'b': /* --ctlbase <path> */ /* * ??? work to be done here: * * snprintf returns the required space if there * isn't enough, not -1. * -1 indicates another kind of error. * * This appears to be the only place where the * ctlbase value is used yet it is set elsewhere. * (This isn't clear -- it may be OK.) */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path), "%s%s", ctlbase, CTL_SUFFIX) == -1) { ugh = "<path>" CTL_SUFFIX " too long for sun_path"; break; } if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path), "%s%s", ctlbase, INFO_SUFFIX) == -1) { ugh = "<path>" INFO_SUFFIX " too long for sun_path"; break; } if (snprintf(pluto_lock, sizeof(pluto_lock), "%s%s", ctlbase, LOCK_SUFFIX) == -1) { ugh = "<path>" LOCK_SUFFIX " must fit"; break; } continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ lsw_init_ipsecdir(optarg); continue; #ifdef USE_ADNS case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #endif case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': /* --perpeerlog */ log_to_perpeer = TRUE; continue; case '2': /* --keep-alive <delay_secs> */ ugh = ttoulb(optarg, 0, 10, secs_per_day, &u); if (ugh != NULL) break; keep_alive = u; continue; case '5': /* --debug-nat-t */ base_debugging |= DBG_NATT; continue; case '6': /* --virtual-private */ virtual_private = optarg; continue; case 'z': /* --config */ { /* * Config struct to variables mapper. This will * overwrite all previously set options. Keep this * in the same order as long_opts[] is. */ struct starter_config *cfg = read_cfg_file(optarg); /* leak */ set_cfg_string(&pluto_log_file, cfg->setup.strings[KSF_PLUTOSTDERRLOG]); if (pluto_log_file != NULL) log_to_syslog = FALSE; /* plutofork= no longer supported via config file */ log_with_timestamp = cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]; log_append = cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND]; pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE]; if (cfg->setup.options[KBF_FORCEBUSY]) { /* force-busy is obsoleted, translate to ddos-mode= */ pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE] = DDOS_FORCE_BUSY; } /* ddos-ike-treshold and max-halfopen-ike */ pluto_ddos_treshold = cfg->setup.options[KBF_DDOS_IKE_TRESHOLD]; pluto_max_halfopen = cfg->setup.options[KBF_MAX_HALFOPEN_IKE]; strict_crl_policy = cfg->setup.options[KBF_STRICTCRLPOLICY]; pluto_shunt_lifetime = deltatime(cfg->setup.options[KBF_SHUNTLIFETIME]); strict_ocsp_policy = cfg->setup.options[KBF_STRICTOCSPPOLICY]; ocsp_enable = cfg->setup.options[KBF_OCSPENABLE]; set_cfg_string(&ocsp_default_uri, cfg->setup.strings[KSF_OCSPURI]); ocsp_timeout = cfg->setup.options[KBF_OCSPTIMEOUT]; set_cfg_string(&ocsp_trust_name, cfg->setup.strings[KSF_OCSPTRUSTNAME]); crl_check_interval = deltatime( cfg->setup.options[KBF_CRLCHECKINTERVAL]); uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS]; /* * We don't check interfaces= here because that part * has been dealt with in _stackmanager before we * started */ set_cfg_string(&pluto_listen, cfg->setup.strings[KSF_LISTEN]); /* --ikeport */ pluto_port = cfg->setup.options[KBF_IKEPORT]; /* --nflog-all */ /* only causes nflog nmber to show in ipsec status */ pluto_nflog_group = cfg->setup.options[KBF_NFLOG_ALL]; /* only causes nflog nmber to show in ipsec status */ pluto_xfrmlifetime = cfg->setup.options[KBF_XFRMLIFETIME]; /* no config option: ctlbase */ /* --secrets */ set_cfg_string(&pluto_shared_secrets_file, cfg->setup.strings[KSF_SECRETSFILE]); if (cfg->setup.strings[KSF_IPSECDIR] != NULL && *cfg->setup.strings[KSF_IPSECDIR] != 0) { /* --ipsecdir */ lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]); } /* --perpeerlog */ log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG]; if (log_to_perpeer) { /* --perpeerlogbase */ if (cfg->setup.strings[KSF_PERPEERDIR]) { set_cfg_string(&base_perpeer_logdir, cfg->setup.strings[KSF_PERPEERDIR]); } else { base_perpeer_logdir = clone_str("/var/log/pluto/", "perpeer_logdir"); } } if (cfg->setup.strings[KSF_CURLIFACE]) { pfreeany(curl_iface); /* curl-iface= */ curl_iface = clone_str(cfg->setup.strings[KSF_CURLIFACE], "curl-iface= via --config"); } if (cfg->setup.options[KBF_CURLTIMEOUT]) curl_timeout = cfg->setup.options[KBF_CURLTIMEOUT]; if (cfg->setup.strings[KSF_DUMPDIR]) { pfree(coredir); /* dumpdir= */ coredir = clone_str(cfg->setup.strings[KSF_DUMPDIR], "coredir via --config"); } /* --vendorid */ if(cfg->setup.strings[KSF_MYVENDORID]) { pfree(pluto_vendorid); pluto_vendorid = clone_str(cfg->setup.strings[KSF_MYVENDORID], "pluto_vendorid via --config"); } /* no config option: pluto_adns_option */ if (cfg->setup.strings[KSF_STATSBINARY] != NULL) { if (access(cfg->setup.strings[KSF_STATSBINARY], X_OK) == 0) { pfreeany(pluto_stats_binary); /* statsbin= */ pluto_stats_binary = clone_str(cfg->setup.strings[KSF_STATSBINARY], "statsbin via --config"); libreswan_log("statsbinary set to %s", pluto_stats_binary); } else { libreswan_log("statsbinary= '%s' ignored - file does not exist or is not executable", pluto_stats_binary); } } pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS]; pluto_nat_port = cfg->setup.options[KBF_NATIKEPORT]; keep_alive = cfg->setup.options[KBF_KEEPALIVE]; set_cfg_string(&virtual_private, cfg->setup.strings[KSF_VIRTUALPRIVATE]); nhelpers = cfg->setup.options[KBF_NHELPERS]; #ifdef HAVE_LABELED_IPSEC secctx_attr_type = cfg->setup.options[KBF_SECCTX]; #endif base_debugging = cfg->setup.options[KBF_PLUTODEBUG]; char *protostack = cfg->setup.strings[KSF_PROTOSTACK]; if (protostack == NULL || *protostack == '\0') { kern_interface = USE_NETKEY; } else if (streq(protostack, "none")) { kern_interface = NO_KERNEL; } else if (streq(protostack, "auto")) { libreswan_log( "The option protostack=auto is obsoleted, falling back to protostack=netkey\n"); kern_interface = USE_NETKEY; } else if (streq(protostack, "klips")) { kern_interface = USE_KLIPS; } else if (streq(protostack, "mast")) { kern_interface = USE_MASTKLIPS; } else if (streq(protostack, "netkey") || streq(protostack, "native")) { kern_interface = USE_NETKEY; } else if (streq(protostack, "bsd") || streq(protostack, "kame") || streq(protostack, "bsdkame")) { kern_interface = USE_BSDKAME; } else if (streq(protostack, "win2k")) { kern_interface = USE_WIN2K; } confread_free(cfg); continue; } default: if (DBG_OFFSET <= c && c < DBG_OFFSET + IMPAIR_roof_IX) { base_debugging |= LELEM(c - DBG_OFFSET); continue; } bad_case(c); } /* if ugh is set, bail with diagnostic */ if (ugh != NULL) { char mess[200]; if (longindex == -1) { snprintf(mess, sizeof(mess), "unknown option: %s", ugh); } else if (optarg == NULL) { snprintf(mess, sizeof(mess), "--%s option: %s", optname, ugh); } else { snprintf(mess, sizeof(mess), "--%s \"%s\" option: %s", optname, optarg, ugh); } invocation_fail(mess); } break; } if (optind != argc) invocation_fail("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif if (chdir(coredir) == -1) { int e = errno; libreswan_log("pluto: warning: chdir(\"%s\") to dumpdir failed (%d: %s)", coredir, e, strerror(e)); } oco = lsw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired || log_to_file_desired) log_to_syslog = FALSE; if (!log_to_stderr_desired) log_to_stderr = FALSE; #if 0 if (kernel_ops->set_debug) (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); #endif /* * create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: FATAL: %s", ugh); exit_pluto(PLUTO_EXIT_SOCKET_FAIL); } } /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: FATAL: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } if (pid != 0) { /* * parent: die, after filling PID into lock * file. * must not use exit_pluto: lock would be * removed! */ exit(fill_lock(lockfd, pid) ? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "FATAL: setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FAIL); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); if (isatty(fileno(stdout))) { fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } } /* * Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) lsw_abort(); if (dup2(0, 1) != 1) lsw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) lsw_abort(); } init_constants(); pluto_init_log(); if (!pluto_init_nss(oco->nssdir)) { loglog(RC_LOG_SERIOUS, "FATAL: NSS initialization failure"); exit_pluto(10); } if (ocsp_enable) { if (!init_nss_ocsp(ocsp_default_uri, ocsp_trust_name, ocsp_timeout, strict_ocsp_policy)) { libreswan_log("Initializing NSS OCSP failed"); exit_pluto(10); } else { libreswan_log("NSS OCSP Enabled"); } } #ifdef HAVE_LIBCAP_NG /* * Drop capabilities - this generates a false positive valgrind warning * See: http://marc.info/?l=linux-security-module&m=125895232029657 * * We drop these after creating the pluto socket or else we can't * create a socket if the parent dir is non-root (eg openstack) */ capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, CAP_AUDIT_WRITE, /* for google authenticator pam */ CAP_SETGID, CAP_SETUID, -1); /* * We need to retain some capabilities for our children (updown): * CAP_NET_ADMIN to change routes * CAP_NET_RAW for iptables -t mangle * CAP_DAC_READ_SEARCH for pam / google authenticator */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_NET_RAW, CAP_DAC_READ_SEARCH, -1); capng_apply(CAPNG_SELECT_BOTH); libreswan_log("libcap-ng support [enabled]"); #else libreswan_log("libcap-ng support [disabled]"); #endif #ifdef FIPS_CHECK /* * FIPS Kernel mode: fips=1 kernel boot parameter * FIPS Product mode: dracut-fips is installed * * When FIPS Product mode and FIPS Kernel mode, abort on hmac failure. * Otherwise, just complain about failures. * * Product Mode detected with FIPSPRODUCTCHECK in Makefile.inc */ { int fips_kernel = libreswan_fipskernel(); int fips_product = libreswan_fipsproduct(); int fips_mode = libreswan_fipsmode(); int fips_files_check_ok = FIPSCHECK_verify_files(fips_package_files); if (DBGP(IMPAIR_FORCE_FIPS)) { libreswan_log("Setting all FIPS checks to true to emulate FIPS mode"); fips_kernel = fips_product = fips_mode = fips_files_check_ok = 1; } if (fips_mode == -1) { loglog(RC_LOG_SERIOUS, "ABORT: FIPS mode could not be determined"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); } if (fips_product == 1) libreswan_log("FIPS Product detected (%s)", FIPSPRODUCTCHECK); if (fips_kernel == 1) libreswan_log("FIPS Kernel Mode detected"); if (!fips_files_check_ok) { loglog(RC_LOG_SERIOUS, "FIPS HMAC integrity verification FAILURE"); /* * We ignore fips=1 kernel mode if we are not a 'fips product' */ if (fips_product && fips_kernel) { loglog(RC_LOG_SERIOUS, "ABORT: FIPS product and kernel in FIPS mode"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); } else if (fips_product) { libreswan_log("FIPS: FIPS product but kernel mode disabled - continuing"); } else if (fips_kernel) { libreswan_log("FIPS: not a FIPS product, kernel mode ignored - continuing"); } else { libreswan_log("FIPS: not a FIPS product and kernel not in FIPS mode - continuing"); } } else { libreswan_log("FIPS HMAC integrity verification test passed"); } if (fips_mode) { libreswan_log("FIPS: pluto daemon running in FIPS mode"); } else { libreswan_log("FIPS: pluto daemon NOT running in FIPS mode"); } } #else libreswan_log("FIPS HMAC integrity support [disabled]"); #endif #ifdef USE_LINUX_AUDIT linux_audit_init(); #else libreswan_log("Linux audit support [disabled]"); #endif { const char *vc = ipsec_version_code(); libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u", vc, compile_time_interop_options, getpid()); } libreswan_log("core dump dir: %s", coredir); if (pluto_shared_secrets_file) libreswan_log("secrets file: %s", pluto_shared_secrets_file); libreswan_log(leak_detective ? "leak-detective enabled" : "leak-detective disabled"); /* Check for SAREF support */ #ifdef KLIPS_MAST #include <ipsec_saref.h> { int e, sk, saref; saref = 1; errno = 0; sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAref support [disabled]: %s", strerror(errno)); else libreswan_log("SAref support [enabled]"); errno = 0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAbind support [disabled]: %s", strerror(errno)); else libreswan_log("SAbind support [enabled]"); close(sk); } #endif libreswan_log("NSS crypto [enabled]"); #ifdef XAUTH_HAVE_PAM libreswan_log("XAUTH PAM support [enabled]"); #else libreswan_log("XAUTH PAM support [disabled]"); #endif /* Log various impair-* functions if they were enabled */ if (DBGP(IMPAIR_BUST_MI2)) libreswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if (DBGP(IMPAIR_BUST_MR2)) libreswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if (DBGP(IMPAIR_SA_CREATION)) libreswan_log("Warning: IMPAIR_SA_CREATION enabled"); if (DBGP(IMPAIR_JACOB_TWO_TWO)) libreswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if (DBGP(IMPAIR_DIE_ONINFO)) libreswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if (DBGP(IMPAIR_MAJOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MAJOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_MINOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MINOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_RETRANSMITS)) libreswan_log("Warning: IMPAIR_RETRANSMITS enabled"); if (DBGP(IMPAIR_SEND_BOGUS_ISAKMP_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_ISAKMP_FLAG enabled"); if (DBGP(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_PAYLOAD_FLAG enabled"); if (DBGP(IMPAIR_SEND_IKEv2_KE)) libreswan_log("Warning: IMPAIR_SEND_IKEv2_KE enabled"); if (DBGP(IMPAIR_SEND_KEY_SIZE_CHECK)) libreswan_log("Warning: IMPAIR_SEND_KEY_SIZE_CHECK enabled"); if (DBGP(IMPAIR_SEND_NO_DELETE)) libreswan_log("Warning: IMPAIR_SEND_NO_DELETE enabled"); if (DBGP(IMPAIR_FORCE_FIPS)) libreswan_log("Warning: IMPAIR_FORCE_FIPS enabled"); if (DBGP(IMPAIR_SEND_NO_IKEV2_AUTH)) libreswan_log("Warning: IMPAIR_SEND_NO_IKEV2_AUTH enabled"); if (DBGP(IMPAIR_SEND_ZERO_GX)) libreswan_log("Warning: IMPAIR_SEND_ZERO_GX enabled"); /* Initialize all of the various features */ init_nat_traversal(keep_alive); init_virtual_ip(virtual_private); /* obsoleted by nss code init_rnd_pool(); */ init_event_base(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); init_demux(); init_kernel(); #ifdef USE_ADNS init_adns(); #endif init_id(); init_vendorid(); #if defined(LIBCURL) || defined(LDAP_VER) init_fetch(); #endif load_crls(); #ifdef HAVE_LABELED_IPSEC init_avc(); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }