void parent_init(int reqfd, int msgfd, pid_t child) { // events struct event ev_cmd, ev_msg; struct event ev_sigchld, ev_sigint, ev_sigterm, ev_sighup; #ifdef HAVE_LIBCAP // capabilities cap_t caps; #endif /* HAVE_LIBCAP */ // init the queues TAILQ_INIT(&rawfds); // proctitle setproctitle("parent [priv]"); // setup global sockets sock = my_socket(AF_INET, SOCK_DGRAM, 0); mfd = msgfd; // debug if (options & OPT_DEBUG) { dfd = STDOUT_FILENO; my_pcap_init(dfd); #if HAVE_LIBCAP_NG } else { capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_KILL, CAP_NET_ADMIN, CAP_NET_RAW, CAP_NET_BROADCAST, -1); if (capng_apply(CAPNG_SELECT_BOTH) == -1) my_fatal("unable to set capabilities"); #elif HAVE_LIBCAP } else {
/** * \brief Drop all the previliges of the given thread */ void SCDropAllCaps() { capng_clear(CAPNG_SELECT_BOTH); if (capng_apply(CAPNG_SELECT_BOTH) < 0) { SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "failed in dropping the caps"); exit(EXIT_FAILURE); } }
/** * This function will drop all capabilities. */ static int drop_caps() { if (capng_have_capabilities(cap_set) == CAPNG_NONE) return 0; capng_clear(cap_set); if (capng_lock() == -1 || capng_apply(cap_set) == -1) { fprintf(stderr, _("Failed to drop all capabilities\n")); return -1; } return 0; }
void secure_capng_apply(capng_select_t set) { if (!( (set==CAPNG_SELECT_CAPS)||(set==CAPNG_SELECT_BOUNDS)||(set==CAPNG_SELECT_BOTH) )) { std::ostringstream oss; oss<<"Error: " << "invalid input" << " in " << __func__ << ": set="<<set<<"." ; throw capmodpp_error(oss.str()); } auto ret = int { capng_apply(set) }; bool fail = (ret != 0); bool badval = false; if (fail||badval) { std::ostringstream oss; oss<<"Error: " << (fail ? "FAILED":"") << " " << (badval ? "BAD-VALUE":"") << " (ret="<<ret<<") in " << __func__ << " for set="<<set<<"."; throw capmodpp_error(oss.str()); } }
static int lxcControllerClearCapabilities(void) { #if HAVE_CAPNG int ret; capng_clear(CAPNG_SELECT_BOTH); if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { lxcError(VIR_ERR_INTERNAL_ERROR, _("failed to apply capabilities: %d"), ret); return -1; } #else VIR_WARN0("libcap-ng support not compiled in, unable to clear capabilities"); #endif return 0; }
// Update the capabilities of the running process to include the given // capability in the Ambient set. static void set_ambient_cap(cap_value_t cap) { capng_get_caps_process(); if (capng_update(CAPNG_ADD, CAPNG_INHERITABLE, (unsigned long) cap)) { perror("cannot raise the capability into the Inheritable set\n"); exit(1); } capng_apply(CAPNG_SELECT_CAPS); if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long) cap, 0, 0)) { perror("cannot raise the capability into the Ambient set\n"); exit(1); } }
void SCDropCaps(ThreadVars *tv) { #if 0 capng_clear(CAPNG_SELECT_BOTH); capng_apply(CAPNG_SELECT_BOTH); if (tv->cap_flags & SC_CAP_IPC_LOCK) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name); } if (tv->cap_flags & SC_CAP_NET_ADMIN) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name); } if (tv->cap_flags & SC_CAP_NET_BIND_SERVICE) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name); } if (tv->cap_flags & SC_CAP_NET_BROADCAST) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name); } if (tv->cap_flags & SC_CAP_NET_RAW) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name); } if (tv->cap_flags & SC_CAP_SYS_ADMIN) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name); } if (tv->cap_flags & SC_CAP_SYS_RAW_IO) { capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO); capng_apply(CAPNG_SELECT_CAPS); SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name); } #endif }
/* * This is running as the 'init' process insid the container. * It removes some capabilities that could be dangerous to * host system, since they are not currently "containerized" */ static int lxcContainerDropCapabilities(void) { #if HAVE_CAPNG int ret; capng_get_caps_process(); if ((ret = capng_updatev(CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE | CAPNG_BOUNDING_SET, CAP_SYS_BOOT, /* No use of reboot */ CAP_SYS_MODULE, /* No kernel module loading */ CAP_SYS_TIME, /* No changing the clock */ CAP_AUDIT_CONTROL, /* No messing with auditing status */ CAP_MAC_ADMIN, /* No messing with LSM config */ -1 /* sentinal */)) < 0) { lxcError(VIR_ERR_INTERNAL_ERROR, _("Failed to remove capabilities: %d"), ret); return -1; } if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { lxcError(VIR_ERR_INTERNAL_ERROR, _("Failed to apply capabilities: %d"), ret); return -1; } /* We do not need to call capng_lock() in this case. The bounding * set restriction will prevent them reacquiring sys_boot/module/time, * etc which is all that matters for the container. Once inside the * container it is fine for SECURE_NOROOT / SECURE_NO_SETUID_FIXUP to * be unmasked - they can never escape the bounding set. */ #else VIR_WARN0("libcap-ng support not compiled in, unable to clear capabilities"); #endif return 0; }
/*! \brief POSIX 1003.1e capabilities. */ static void setup_capabilities(void) { #ifdef HAVE_CAP_NG_H /* Drop all capabilities. */ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) { capng_clear(CAPNG_SELECT_BOTH); /* Retain ability to set capabilities and FS access. */ capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED; capng_update(CAPNG_ADD, tp, CAP_SETPCAP); capng_update(CAPNG_ADD, tp, CAP_DAC_OVERRIDE); capng_update(CAPNG_ADD, tp, CAP_CHOWN); /* Storage ownership. */ /* Allow binding to privileged ports. * (Not inheritable) */ capng_update(CAPNG_ADD, tp, CAP_NET_BIND_SERVICE); /* Allow setuid/setgid. */ capng_update(CAPNG_ADD, tp, CAP_SETUID); capng_update(CAPNG_ADD, tp, CAP_SETGID); /* Allow priorities changing. */ capng_update(CAPNG_ADD, tp, CAP_SYS_NICE); /* Apply. */ if (capng_apply(CAPNG_SELECT_BOTH) < 0) { log_error("failed to set process capabilities (%s)", strerror(errno)); } } else { log_info("user UID %d is not allowed to set capabilities, " "skipping", getuid()); } #endif /* HAVE_CAP_NG_H */ }
int main(int argc, char **argv) { int lockfd; int nhelpers = -1; char *coredir; const struct lsw_conf_options *oco; /* * 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; coredir = NULL; /* set up initial defaults that need a cast */ pluto_shared_secrets_file = DISCARD_CONST(char *, SHARED_SECRETS_FILE); #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #ifdef LEAK_DETECTIVE leak_detective=1; #else leak_detective=0; #endif #ifdef HAVE_LIBCAP_NG /* Drop capabilities */ 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, -1); /* our children must be able to CAP_NET_ADMIN to change routes. */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, -1); capng_apply(CAPNG_SELECT_BOTH); #endif #ifdef DEBUG libreswan_passert_fail = passert_fail; #endif if(getenv("PLUTO_WAIT_FOR_GDB")) { sleep(120); } /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "config", required_argument, NULL, 'z' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "logfile", required_argument, NULL, 'g' }, { "plutostderrlogtime", no_argument, NULL, 't' }, { "noklips", no_argument, NULL, 'n' }, { "use-nostack", no_argument, NULL, 'n' }, { "use-none", no_argument, NULL, 'n' }, { "force_busy", no_argument, NULL, 'D' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "uniqueids", no_argument, NULL, 'u' }, { "useklips", no_argument, NULL, 'k' }, { "use-klips", no_argument, NULL, 'k' }, { "use-auto", no_argument, NULL, 'G' }, { "usenetkey", no_argument, NULL, 'K' }, { "use-netkey", no_argument, NULL, 'K' }, { "use-mast", no_argument, NULL, 'M' }, { "use-mastklips", no_argument, NULL, 'M' }, { "use-bsdkame", no_argument, NULL, 'F' }, { "interface", required_argument, NULL, 'i' }, { "listen", required_argument, NULL, 'L' }, { "ikeport", required_argument, NULL, 'p' }, { "natikeport", required_argument, NULL, 'q' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "coredir", required_argument, NULL, 'C' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "adns", required_argument, NULL, 'a' }, #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, { "debug-nattraversal", no_argument, NULL, '5' }, { "debug-nat-t", no_argument, NULL, '5' }, #endif { "virtual_private", required_argument, NULL, '6' }, { "nhelpers", required_argument, NULL, 'j' }, #ifdef HAVE_LABELED_IPSEC { "secctx_attr_value", required_argument, NULL, 'w' }, #endif #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET }, { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET }, { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET }, { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET }, { "impair-major-version-bump", no_argument, NULL, IMPAIR_MAJOR_VERSION_BUMP + DBG_OFFSET }, { "impair-minor-version-bump", no_argument, NULL, IMPAIR_MINOR_VERSION_BUMP + DBG_OFFSET }, { "impair-retransmits", no_argument, NULL, IMPAIR_RETRANSMITS + DBG_OFFSET }, { "impair-send-bogus-isakmp-flag", no_argument, NULL, IMPAIR_SEND_BOGUS_ISAKMP_FLAG + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* 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 c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'C': coredir = clone_str(optarg, "coredir"); continue; case 'v': /* --version */ { printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); } exit(0); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case 'j': /* --nhelpers */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing number of pluto helpers"); { char *endptr; long count = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || count < -1) usage("<nhelpers> must be a positive number, 0 or -1"); nhelpers = count; } continue; #ifdef HAVE_LABELED_IPSEC case 'w': /* --secctx_attr_value*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing (positive integer) value of secctx_attr_value (needed only if using labeled ipsec)"); { char *endptr; long value = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || (value != SECCTX && value !=10) ) usage("<secctx_attr_value> must be a positive number (32001 by default, 10 for backward compatibility, or any other future number assigned by IANA)"); secctx_attr_value = (u_int16_t)value; } 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': /* --plutostderrlogtime */ log_with_timestamp = TRUE; continue; case 'G': /* --use-auto */ libreswan_log("The option --use-auto is obsoleted, falling back to --use-netkey\n"); kern_interface = USE_NETKEY; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg,0,0,&lip); if(e) { 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 */ force_busy = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) usage("too many --interface specifications"); 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> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; #ifdef NAT_TRAVERSAL case 'q': /* --natikeport <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_natt_float_port = port; } continue; #endif case 'b': /* --ctlbase <path> */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", ctlbase, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", ctlbase, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", ctlbase, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ (void)lsw_init_ipsecdir(optarg); continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; #ifdef DEBUG case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #endif 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 than */ /* long_opts[] is. */ struct starter_config *cfg = read_cfg_file(optarg); set_cfg_string(&pluto_log_file, cfg->setup.strings[KSF_PLUTOSTDERRLOG]); fork_desired = cfg->setup.options[KBF_PLUTOFORK]; /* plutofork= */ log_with_timestamp = cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]; force_busy = cfg->setup.options[KBF_FORCEBUSY]; strict_crl_policy = cfg->setup.options[KBF_STRICTCRLPOLICY]; crl_check_interval = 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]); pluto_port = cfg->setup.options[KBF_IKEPORT]; /* --ikeport */ /* no config option: ctlbase */ set_cfg_string(&pluto_shared_secrets_file, cfg->setup.strings[KSF_SECRETSFILE]); /* --secrets */ if(cfg->setup.strings[KSF_IPSECDIR] != NULL && *cfg->setup.strings[KSF_IPSECDIR] != 0) { lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]); /* --ipsecdir */ } set_cfg_string(&base_perpeer_logdir, cfg->setup.strings[KSF_PERPEERDIR]); /* --perpeerlogbase */ log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG]; /* --perpeerlog */ no_retransmits = !cfg->setup.options[KBF_RETRANSMITS]; /* --noretransmits */ set_cfg_string(&coredir, cfg->setup.strings[KSF_DUMPDIR]); /* --dumpdir */ /* no config option: pluto_adns_option */ #ifdef NAT_TRAVERSAL pluto_natt_float_port = cfg->setup.options[KBF_NATIKEPORT]; nat_traversal = cfg->setup.options[KBF_NATTRAVERSAL]; keep_alive = cfg->setup.options[KBF_KEEPALIVE]; force_keepalive = cfg->setup.options[KBF_FORCE_KEEPALIVE]; nat_t_spf = !cfg->setup.options[KBF_DISABLEPORTFLOATING]; #endif set_cfg_string(&virtual_private, cfg->setup.strings[KSF_VIRTUALPRIVATE]); nhelpers = cfg->setup.options[KBF_NHELPERS]; #ifdef HAVE_LABELED_IPSEC secctx_attr_value = cfg->setup.options[KBF_SECCTX]; #endif #ifdef DEBUG base_debugging = cfg->setup.options[KBF_PLUTODEBUG]; #endif char *protostack = cfg->setup.strings[KSF_PROTOSTACK]; if (protostack == NULL || *protostack == 0) kern_interface = USE_NETKEY; else if (strcmp(protostack, "none") == 0) kern_interface = NO_KERNEL; else if (strcmp(protostack, "auto") == 0) { libreswan_log("The option protostack=auto is obsoleted, falling back to protostack=netkey\n"); kern_interface = USE_NETKEY; } else if (strcmp(protostack, "klips") == 0) kern_interface = USE_KLIPS; else if (strcmp(protostack, "mast") == 0) kern_interface = USE_MASTKLIPS; else if (strcmp(protostack, "netkey") == 0 || strcmp(protostack, "native") == 0) kern_interface = USE_NETKEY; else if (strcmp(protostack, "bsd") == 0 || strcmp(protostack, "kame") == 0 || strcmp(protostack, "bsdkame") == 0) kern_interface = USE_BSDKAME; else if (strcmp(protostack, "win2k") == 0) kern_interface = USE_WIN2K; confread_free(cfg); continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif /* default coredir to location compatible with SElinux */ if(!coredir) { coredir = clone_str("/var/run/pluto", "coredir"); } if(chdir(coredir) == -1) { int e = errno; libreswan_log("pluto: chdir() do dumpdir failed (%d: %s)\n", 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; #ifdef DEBUG #if 0 if(kernel_ops->set_debug) { (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); } #endif #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: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } 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, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } 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(); pluto_init_nss(oco->confddir); #ifdef FIPS_CHECK const char *package_files[]= { IPSECLIBDIR"/setup", IPSECLIBDIR"/addconn", IPSECLIBDIR"/auto", IPSECLIBDIR"/barf", IPSECLIBDIR"/eroute", IPSECLIBDIR"/ikeping", IPSECLIBDIR"/readwriteconf", IPSECLIBDIR"/_keycensor", IPSECLIBDIR"/klipsdebug", IPSECLIBDIR"/look", IPSECLIBDIR"/newhostkey", IPSECLIBDIR"/pf_key", IPSECLIBDIR"/_pluto_adns", IPSECLIBDIR"/_plutorun", IPSECLIBDIR"/ranbits", IPSECLIBDIR"/_realsetup", IPSECLIBDIR"/rsasigkey", IPSECLIBDIR"/pluto", IPSECLIBDIR"/_secretcensor", IPSECLIBDIR"/secrets", IPSECLIBDIR"/showhostkey", IPSECLIBDIR"/spi", IPSECLIBDIR"/spigrp", IPSECLIBDIR"/_stackmanager", IPSECLIBDIR"/tncfg", IPSECLIBDIR"/_updown", IPSECLIBDIR"/_updown.klips", IPSECLIBDIR"/_updown.mast", IPSECLIBDIR"/_updown.netkey", IPSECLIBDIR"/verify", IPSECLIBDIR"/whack", IPSECSBINDIR"/ipsec", NULL }; if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) { loglog(RC_LOG_SERIOUS, "FATAL: FIPS integrity verification test failed"); exit_pluto(10); } #else libreswan_log("FIPS integrity support [disabled]"); #endif #ifdef HAVE_LIBCAP_NG libreswan_log("libcap-ng support [enabled]"); #else libreswan_log("libcap-ng support [disabled]"); #endif #ifdef USE_LINUX_AUDIT libreswan_log("Linux audit support [enabled]"); /* test and log if audit is enabled on the system */ int audit_fd, rc; audit_fd = audit_open(); if (audit_fd < 0) { if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { loglog(RC_LOG_SERIOUS, "Warning: kernel has no audit support"); } else { loglog(RC_LOG_SERIOUS, "FATAL (SOON): audit_open() failed : %s", strerror(errno)); /* temp disabled exit_pluto(10); */ } } rc = audit_log_acct_message(audit_fd, AUDIT_USER_START, NULL, "starting pluto daemon", NULL, -1, NULL, NULL, NULL, 1); close(audit_fd); if (rc < 0) { loglog(RC_LOG_SERIOUS, "FATAL: audit_log_acct_message failed: %s", strerror(errno)); exit_pluto(10); } #else libreswan_log("Linux audit support [disabled]"); #endif /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { const char *vc = ipsec_version_code(); #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); libreswan_log("Starting Pluto (Libreswan Version %s%s; Vendor ID %s) pid:%u" , vc, compile_time_interop_options, v, getpid()); #else libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u" , vc, compile_time_interop_options, getpid()); #endif if(Pluto_IsFIPS()) { libreswan_log("Pluto is running in FIPS mode"); } else { libreswan_log("Pluto is NOT running in FIPS mode"); } if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') || (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) { /* * when people build RPMs from CVS or GIT, make sure they * get blamed appropriately, and that we get some way to * identify who did it, and when they did it. Use string concat, * so that strings the binary can or classic SCCS "what", will find * stuff too. */ libreswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER); } #if defined(USE_1DES) libreswan_log("WARNING: 1DES is enabled"); #endif } if(coredir) { libreswan_log("core dump dir: %s", coredir); } if(pluto_shared_secrets_file) { libreswan_log("secrets file: %s", pluto_shared_secrets_file); } #ifdef LEAK_DETECTIVE libreswan_log("LEAK_DETECTIVE support [enabled]"); #else libreswan_log("LEAK_DETECTIVE support [disabled]"); #endif #ifdef HAVE_OCF { struct stat buf; errno=0; if( stat("/dev/crypto",&buf) != -1) libreswan_log("OCF support for IKE via /dev/crypto [enabled]"); else libreswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno)); } #else libreswan_log("OCF support for IKE [disabled]"); #endif /* 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 #ifdef HAVE_STATSD libreswan_log("HAVE_STATSD notification via /bin/libreswan-statsd enabled"); #else libreswan_log("HAVE_STATSD notification 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_DELAY_ADNS_KEY_ANSWER)) libreswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled"); if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER)) libreswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled"); /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif init_virtual_ip(virtual_private); /* obsoletd by nss code init_rnd_pool(); */ init_timer(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); load_lswcrypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef TPM init_tpm(); #endif #if defined(LIBCURL) || defined(LDAP_VER) init_fetch(); #endif /* loading X.509 CA certificates */ load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA); #if 0 /* unused */ /* loading X.509 AA certificates */ load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA); #endif /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); /*Loading CA certs from NSS DB*/ load_authcerts_from_nss("CA cert", AUTH_CA); #ifdef HAVE_LABELED_IPSEC init_avc(); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { bool fork_desired = TRUE; int lockfd; char* ocspuri = NULL; int nhelpers = -1; char *coredir; const struct osw_conf_options *oco; #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #ifdef LEAK_DETECTIVE leak_detective=1; #else leak_detective=0; #endif #ifdef HAVE_LIBCAP_NG /* Drop capabilities */ 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, -1); /* our children must be able to CAP_NET_ADMIN to change routes. */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, -1); capng_apply(CAPNG_SELECT_BOTH); #endif global_argv = argv; global_argc = argc; #ifdef DEBUG openswan_passert_fail = passert_fail; #endif /* see if there is an environment variable */ coredir = getenv("PLUTO_CORE_DIR"); if(getenv("PLUTO_WAIT_FOR_GDB")) { sleep(120); } /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "use-nostack", no_argument, NULL, 'n' }, { "use-none", no_argument, NULL, 'n' }, { "force_busy", no_argument, NULL, 'D' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "ocsprequestcert", required_argument, NULL, 'q'}, { "ocspuri", required_argument, NULL, 'o'}, { "uniqueids", no_argument, NULL, 'u' }, { "useklips", no_argument, NULL, 'k' }, { "use-klips", no_argument, NULL, 'k' }, { "use-auto", no_argument, NULL, 'G' }, { "usenetkey", no_argument, NULL, 'K' }, { "use-netkey", no_argument, NULL, 'K' }, { "use-mast", no_argument, NULL, 'M' }, { "use-mastklips", no_argument, NULL, 'M' }, { "use-bsdkame", no_argument, NULL, 'F' }, { "interface", required_argument, NULL, 'i' }, { "listen", required_argument, NULL, 'L' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "coredir", required_argument, NULL, 'C' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, { "debug-nattraversal", no_argument, NULL, '5' }, { "debug-nat-t", no_argument, NULL, '5' }, #endif { "virtual_private", required_argument, NULL, '6' }, { "nhelpers", required_argument, NULL, 'j' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET }, { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET }, { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET }, { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* 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 c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'C': coredir = clone_str(optarg, "coredir"); break; case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit(0); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'j': /* --nhelpers */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing number of pluto helpers"); { char *endptr; long count = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || count < -1) usage("<nhelpers> must be a positive number, 0 or -1"); nhelpers = count; } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'G': /* --use-auto */ kern_interface = AUTO_PICK; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg,0,0,&lip); if(e) { openswan_log("invalid listen argument ignored: %s\n",e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); openswan_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 */ force_busy = TRUE; continue ; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'o': /* --ocspuri */ ocspuri = optarg; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) usage("too many --interface specifications"); 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> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", ctlbase, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", ctlbase, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", ctlbase, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ (void)osw_init_ipsecdir(optarg); continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; #ifdef DEBUG case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #endif case '6': /* --virtual_private */ virtual_private = optarg; continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif /* if a core dir was set, chdir there */ if(coredir) if(chdir(coredir) == -1) { int e = errno; openswan_log("pluto: chdir() do dumpdir failed (%d %s)\n", e, strerror(e)); } oco = osw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; #ifdef DEBUG #if 0 if(kernel_ops->set_debug) { (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); } #endif #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: %s", ugh); exit_pluto(1); } } #ifdef IPSECPOLICY /* create info socket. */ { err_t ugh = init_info_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #endif /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } 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, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); 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) #ifdef IPSECPOLICY && i != info_fd #endif && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) osw_abort(); if (dup2(0, 1) != 1) osw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) osw_abort(); } init_constants(); pluto_init_log(); #ifdef HAVE_LIBNSS char buf[100]; snprintf(buf, sizeof(buf), "%s",oco->confddir); loglog(RC_LOG_SERIOUS,"nss directory plutomain: %s",buf); SECStatus nss_init_status= NSS_InitReadWrite(buf); if (nss_init_status != SECSuccess) { loglog(RC_LOG_SERIOUS, "NSS initialization failed (err %d)\n", PR_GetError()); exit_pluto(10); } else { loglog(RC_LOG_SERIOUS, "NSS Initialized"); PK11_SetPasswordFunc(getNSSPassword); #ifdef FIPS_CHECK const char *package_files[]= { IPSECLIBDIR"/setup", IPSECLIBDIR"/addconn", IPSECLIBDIR"/auto", IPSECLIBDIR"/barf", IPSECLIBDIR"/_copyright", IPSECLIBDIR"/eroute", IPSECLIBDIR"/ikeping", IPSECLIBDIR"/_include", IPSECLIBDIR"/_keycensor", IPSECLIBDIR"/klipsdebug", IPSECLIBDIR"/look", IPSECLIBDIR"/newhostkey", IPSECLIBDIR"/pf_key", IPSECLIBDIR"/_pluto_adns", IPSECLIBDIR"/_plutoload", IPSECLIBDIR"/_plutorun", IPSECLIBDIR"/ranbits", IPSECLIBDIR"/_realsetup", IPSECLIBDIR"/rsasigkey", IPSECLIBDIR"/pluto", IPSECLIBDIR"/_secretcensor", IPSECLIBDIR"/secrets", IPSECLIBDIR"/showdefaults", IPSECLIBDIR"/showhostkey", IPSECLIBDIR"/showpolicy", IPSECLIBDIR"/spi", IPSECLIBDIR"/spigrp", IPSECLIBDIR"/_startklips", IPSECLIBDIR"/_startnetkey", IPSECLIBDIR"/tncfg", IPSECLIBDIR"/_updown", IPSECLIBDIR"/_updown.klips", IPSECLIBDIR"/_updown.mast", IPSECLIBDIR"/_updown.netkey", IPSECLIBDIR"/verify", IPSECLIBDIR"/whack", IPSECSBINDIR"/ipsec", NULL }; if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) { loglog(RC_LOG_SERIOUS, "FIPS integrity verification test failed"); exit_pluto(10); } #endif } #endif /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { const char *vc = ipsec_version_code(); #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s) pid:%u" , vc, compile_time_interop_options, v, getpid()); #else openswan_log("Starting Pluto (Openswan Version %s%s) pid:%u" , vc, compile_time_interop_options, getpid()); #endif #ifdef HAVE_LIBNSS if(Pluto_IsFIPS()) { openswan_log("Pluto is running in FIPS mode"); } #endif if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') || (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) { /* * when people build RPMs from CVS or GIT, make sure they * get blamed appropriately, and that we get some way to * identify who did it, and when they did it. Use string concat, * so that strings the binary can or classic SCCS "what", will find * stuff too. */ openswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER); } #if defined(USE_1DES) openswan_log("WARNING: 1DES is enabled"); #endif } if(coredir) { openswan_log("core dump dir: %s", coredir); } #ifdef LEAK_DETECTIVE openswan_log("LEAK_DETECTIVE support [enabled]"); #else openswan_log("LEAK_DETECTIVE support [disabled]"); #endif #ifdef HAVE_OCF { struct stat buf; errno=0; if( stat("/dev/crypto",&buf) != -1) openswan_log("OCF support for IKE via /dev/crypto [enabled]"); else openswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno)); } #else openswan_log("OCF support for IKE [disabled]"); #endif /* 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 ) { openswan_log("SAref support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAref support [enabled]"); } errno=0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) { openswan_log("SAbind support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAbind support [enabled]"); } close(sk); } #endif #ifdef HAVE_LIBNSS openswan_log("NSS support [enabled]"); #else openswan_log("NSS support [disabled]"); #endif #ifdef HAVE_STATSD openswan_log("HAVE_STATSD notification via /bin/openswan-statsd enabled"); #else openswan_log("HAVE_STATSD notification support not compiled in"); #endif /** Log various impair-* functions if they were enabled */ if(DBGP(IMPAIR_BUST_MI2)) openswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if(DBGP(IMPAIR_BUST_MR2)) openswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if(DBGP(IMPAIR_SA_CREATION)) openswan_log("Warning: IMPAIR_SA_CREATION enabled"); if(DBGP(IMPAIR_JACOB_TWO_TWO)) openswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if(DBGP(IMPAIR_DIE_ONINFO)) openswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if(DBGP(IMPAIR_DELAY_ADNS_KEY_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled"); if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled"); /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif init_virtual_ip(virtual_private); init_rnd_pool(); init_timer(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); load_oswcrypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef TPM init_tpm(); #endif #ifdef HAVE_THREADS init_fetch(); #endif ocsp_set_default_uri(ocspuri); /* loading X.509 CA certificates */ load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA); /* loading X.509 AA certificates */ load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA); /* loading X.509 OCSP certificates */ load_authcerts("OCSP cert", oco->ocspcerts_dir, AUTH_OCSP); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); #ifdef HAVE_LIBNSS /*Loading CA certs from NSS DB*/ load_authcerts_from_nss("CA cert", AUTH_CA); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char *argv[]) { char *unikernel; enum { QEMU, KVM, UKVM, UNIX } hypervisor; if (argc < 3) { fprintf(stderr, "usage: runner HYPERVISOR UNIKERNEL [ ARGS... ]\n"); fprintf(stderr, "HYPERVISOR: qemu | kvm | ukvm | unix\n"); return 1; } if (strcmp(argv[1], "qemu") == 0) hypervisor = QEMU; else if (strcmp(argv[1], "kvm") == 0) hypervisor = KVM; else if (strcmp(argv[1], "ukvm") == 0) hypervisor = UKVM; else if (strcmp(argv[1], "unix") == 0) hypervisor = UNIX; else { warnx("error: Invalid hypervisor: %s", argv[1]); return 1; } unikernel = argv[2]; /* * Remaining arguments are to be passed on to the unikernel. */ argv += 3; argc -= 3; /* * Check we have CAP_NET_ADMIN. */ if (capng_get_caps_process() != 0) { warnx("error: capng_get_caps_process() failed"); return 1; } if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_ADMIN)) { warnx("error: CAP_NET_ADMIN is required"); return 1; } /* * Connect to netlink, load link cache from kernel. */ struct nl_sock *sk; struct nl_cache *link_cache; int err; sk = nl_socket_alloc(); assert(sk); err = nl_connect(sk, NETLINK_ROUTE); if (err < 0) { warnx("nl_connect() failed: %s", nl_geterror(err)); return 1; } err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); if (err < 0) { warnx("rtnl_link_alloc_cache() failed: %s", nl_geterror(err)); return 1; } /* * Retrieve container network configuration -- IP address and * default gateway. */ struct rtnl_link *l_veth; l_veth = rtnl_link_get_by_name(link_cache, VETH_LINK_NAME); if (l_veth == NULL) { warnx("error: Could not get link information for %s", VETH_LINK_NAME); return 1; } struct nl_addr *veth_addr; err = get_link_inet_addr(sk, l_veth, &veth_addr); if (err) { warnx("error: Unable to determine IP address of %s", VETH_LINK_NAME); return 1; } struct nl_addr *gw_addr; err = get_default_gw_inet_addr(sk, &gw_addr); if (err) { warnx("error: get_deGfault_gw_inet_addr() failed"); return 1; } if (gw_addr == NULL) { warnx("error: No default gateway found. This is currently " "not supported"); return 1; } /* * Create bridge and tap interface, enslave veth and tap interfaces to * bridge. */ err = create_bridge_link(sk, BRIDGE_LINK_NAME); if (err < 0) { warnx("create_bridge_link(%s) failed: %s", BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } int tap_fd; if (hypervisor == UKVM) err = create_tap_link(TAP_LINK_NAME, &tap_fd); else err = create_tap_link(TAP_LINK_NAME, NULL); if (err != 0) { warnx("create_tap_link(%s) failed: %s", TAP_LINK_NAME, strerror(err)); return 1; } /* Refill link cache with newly-created interfaces */ nl_cache_refill(sk, link_cache); struct rtnl_link *l_bridge; l_bridge = rtnl_link_get_by_name(link_cache, BRIDGE_LINK_NAME); if (l_bridge == NULL) { warnx("error: Could not get link information for %s", BRIDGE_LINK_NAME); return 1; } struct rtnl_link *l_tap; l_tap = rtnl_link_get_by_name(link_cache, TAP_LINK_NAME); if (l_tap == NULL) { warnx("error: Could not get link information for %s", TAP_LINK_NAME); return 1; } err = rtnl_link_enslave(sk, l_bridge, l_veth); if (err < 0) { warnx("error: Unable to enslave %s to %s: %s", VETH_LINK_NAME, BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } err = rtnl_link_enslave(sk, l_bridge, l_tap); if (err < 0) { warnx("error: Unable to enslave %s to %s: %s", TAP_LINK_NAME, BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } /* * Flush all IPv4 addresses from the veth interface. This is now safe * as we are good to commit and have retrieved the existing configuration. */ struct rtnl_addr *flush_addr; flush_addr = rtnl_addr_alloc(); assert(flush_addr); rtnl_addr_set_ifindex(flush_addr, rtnl_link_get_ifindex(l_veth)); rtnl_addr_set_family(flush_addr, AF_INET); rtnl_addr_set_local(flush_addr, veth_addr); err = rtnl_addr_delete(sk, flush_addr, 0); if (err < 0) { warnx("error: Could not flush addresses on %s: %s", VETH_LINK_NAME, nl_geterror(err)); return 1; } rtnl_addr_put(flush_addr); /* * Bring up the tap and bridge interfaces. */ struct rtnl_link *l_up; l_up = rtnl_link_alloc(); assert(l_up); /* You'd think set_operstate was the thing to do here. It's not. */ rtnl_link_set_flags(l_up, IFF_UP); err = rtnl_link_change(sk, l_tap, l_up, 0); if (err < 0) { warnx("error: rtnl_link_change(%s, UP) failed: %s", TAP_LINK_NAME, nl_geterror(err)); return 1; } err = rtnl_link_change(sk, l_bridge, l_up, 0); if (err < 0) { warnx("error: rtnl_link_change(%s, UP) failed: %s", BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } rtnl_link_put(l_up); /* * Collect network configuration data. */ char ip[AF_INET_BUFSIZE]; if (inet_ntop(AF_INET, nl_addr_get_binary_addr(veth_addr), ip, sizeof ip) == NULL) { perror("inet_ntop()"); return 1; } char uarg_ip[AF_INET_BUFSIZE]; unsigned int prefixlen = nl_addr_get_prefixlen(veth_addr); snprintf(uarg_ip, sizeof uarg_ip, "%s/%u", ip, prefixlen); char uarg_gw[AF_INET_BUFSIZE]; if (inet_ntop(AF_INET, nl_addr_get_binary_addr(gw_addr), uarg_gw, sizeof uarg_gw) == NULL) { perror("inet_ntop()"); return 1; } /* * Build unikernel and hypervisor arguments. */ ptrvec* uargpv = pvnew(); char *uarg_buf; /* * QEMU/KVM: * /usr/bin/qemu-system-x86_64 <qemu args> -kernel <unikernel> -append "<unikernel args>" */ if (hypervisor == QEMU || hypervisor == KVM) { pvadd(uargpv, "/usr/bin/qemu-system-x86_64"); pvadd(uargpv, "-nodefaults"); pvadd(uargpv, "-no-acpi"); pvadd(uargpv, "-display"); pvadd(uargpv, "none"); pvadd(uargpv, "-serial"); pvadd(uargpv, "stdio"); pvadd(uargpv, "-m"); pvadd(uargpv, "512"); if (hypervisor == KVM) { pvadd(uargpv, "-enable-kvm"); pvadd(uargpv, "-cpu"); pvadd(uargpv, "host"); } else { /* * Required for AESNI use in Mirage. */ pvadd(uargpv, "-cpu"); pvadd(uargpv, "Westmere"); } pvadd(uargpv, "-device"); char *guest_mac = generate_mac(); assert(guest_mac); err = asprintf(&uarg_buf, "virtio-net-pci,netdev=n0,mac=%s", guest_mac); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "-netdev"); err = asprintf(&uarg_buf, "tap,id=n0,ifname=%s,script=no,downscript=no", TAP_LINK_NAME); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "-kernel"); pvadd(uargpv, unikernel); pvadd(uargpv, "-append"); /* * TODO: Replace any occurences of ',' with ',,' in -append, because * QEMU arguments are insane. */ char cmdline[1024]; char *cmdline_p = cmdline; size_t cmdline_free = sizeof cmdline; for (; *argv; argc--, argv++) { size_t alen = snprintf(cmdline_p, cmdline_free, "%s%s", *argv, (argc > 1) ? " " : ""); if (alen >= cmdline_free) { warnx("error: Command line too long"); return 1; } cmdline_free -= alen; cmdline_p += alen; } size_t alen = snprintf(cmdline_p, cmdline_free, "--ipv4=%s --ipv4-gateway=%s", uarg_ip, uarg_gw); if (alen >= cmdline_free) { warnx("error: Command line too long"); return 1; } pvadd(uargpv, cmdline); } /* * UKVM: * /unikernel/ukvm <ukvm args> <unikernel> -- <unikernel args> */ else if (hypervisor == UKVM) { pvadd(uargpv, "/unikernel/ukvm"); err = asprintf(&uarg_buf, "--net=@%d", tap_fd); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "--"); pvadd(uargpv, unikernel); for (; *argv; argc--, argv++) { pvadd(uargpv, *argv); } err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip); assert(err != -1); pvadd(uargpv, uarg_buf); err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw); assert(err != -1); pvadd(uargpv, uarg_buf); } /* * UNIX: * <unikernel> <unikernel args> */ else if (hypervisor == UNIX) { pvadd(uargpv, unikernel); err = asprintf(&uarg_buf, "--interface=%s", TAP_LINK_NAME); assert(err != -1); pvadd(uargpv, uarg_buf); for (; *argv; argc--, argv++) { pvadd(uargpv, *argv); } err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip); assert(err != -1); pvadd(uargpv, uarg_buf); err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw); assert(err != -1); pvadd(uargpv, uarg_buf); } char **uargv = (char **)pvfinal(uargpv); /* * Done with netlink, free all resources and close socket. */ rtnl_link_put(l_veth); rtnl_link_put(l_bridge); rtnl_link_put(l_tap); nl_addr_put(veth_addr); nl_addr_put(gw_addr); nl_cache_free(link_cache); nl_close(sk); nl_socket_free(sk); /* * Drop all capabilities except CAP_NET_BIND_SERVICE. */ capng_clear(CAPNG_SELECT_BOTH); capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); if (capng_apply(CAPNG_SELECT_BOTH) != 0) { warnx("error: Could not drop capabilities"); return 1; } /* * Run the unikernel. */ err = execv(uargv[0], uargv); warn("error: execv() of %s failed", uargv[0]); return 1; }
int main(int argc, char *argv[]) { int rc; const char *cpath; char buf[1024]; struct sigaction sa; sigset_t ss; auparse_state_t *au; ssize_t len; mypid = getpid(); log_info("starting with pid=%d", mypid); /* * install signal handlers */ sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = term_handler; sigaction(SIGTERM, &sa, NULL); sa.sa_handler = hup_handler; sigaction(SIGHUP, &sa, NULL); sa.sa_handler = alarm_handler; sigaction(SIGALRM, &sa, NULL); /* * the main program accepts a single (optional) argument: * it's configuration file (this is NOT the plugin configuration * usually located at /etc/audisp/plugin.d) * We use the default (def_config_file) if no arguments are given */ if (argc == 1) { cpath = def_config_file; log_warn("No configuration file specified - using default (%s)", cpath); } else if (argc == 2) { cpath = argv[1]; log_info("Using configuration file: %s", cpath); } else { log_err("Error - invalid number of parameters passed. Aborting"); return 1; } /* initialize record counter */ conf.counter = 1; /* initialize configuration with default values */ plugin_clear_config(&conf); /* initialize the submission queue */ if (init_queue(conf.q_depth) != 0) { log_err("Error - Can't initialize event queue. Aborting"); return -1; } #ifdef HAVE_LIBCAP_NG // Drop all capabilities capng_clear(CAPNG_SELECT_BOTH); capng_apply(CAPNG_SELECT_BOTH); #endif /* set stdin to O_NONBLOCK */ if (fcntl(0, F_SETFL, O_NONBLOCK) == -1) { log_err("Error - Can't set input to Non-blocking mode: %s. Aborting", strerror(errno)); return -1; } do { hup = 0; /* don't flush unless hup == 1 */ /* * initialization is done in 4 steps: */ /* * load configuration and * increase queue depth if needed */ rc = plugin_load_config(&conf, cpath); if (rc != 0) { log_err("Error - Can't load configuration. Aborting"); return -1; } increase_queue_depth(conf.q_depth); /* 1 */ /* initialize auparse */ au = auparse_init(AUSOURCE_FEED, 0); /* 2 */ if (au == NULL) { log_err("Error - exiting due to auparse init errors"); return -1; } /* * Block signals for everyone, * Initialize submission thread, and * Unblock signals for this thread */ sigfillset(&ss); pthread_sigmask(SIG_BLOCK, &ss, NULL); pthread_create(&submission_thread, NULL, submission_thread_main, NULL); pthread_sigmask(SIG_UNBLOCK, &ss, NULL); /* 3 */ /* add our event consumer callback */ auparse_add_callback(au, push_event, NULL, NULL); /* 4 */ /* main loop */ while (hup == 0 && stop == 0) { fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; rc = select(1, &rfds, NULL, NULL, &tv); if (rc == -1) { if (errno == EINTR) { log_debug("Select call interrupted"); continue; } else { log_err("Error - Fatal error while monitoring input: %s. Aborting", strerror(errno)); stop = 1; } } else if (rc) { len = read(0, buf, 1024); if (len > 0) /* let our callback know of the new data */ auparse_feed(au, buf, len); else if (len == 0) { log_debug("End of input - Exiting"); stop = 1; } else { /* ignore interrupted call or empty pipe */ if (errno != EINTR && errno != EAGAIN) { log_err("Error - Fatal error while reading input: %s. Aborting", strerror(errno)); stop = 1; } else { log_debug("Ignoring read interruption: %s", strerror(errno)); } } } } /* flush everything, in order */ auparse_flush_feed(au); /* 4 */ alarm(10); /* 10 seconds to clear the queue */ pthread_join(submission_thread, NULL); /* 3 */ alarm(0); /* cancel any pending alarm */ auparse_destroy(au); /* 2 */ plugin_free_config(&conf); /* 1 */ } while (hup && stop == 0); /* destroy queue before leaving */ destroy_queue(); log_info("Exiting"); return 0; }
int main(int argc, char *argv[]) { int which = 0, i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--text") == 0) text = 1; else if (strcmp(argv[i], "--no-child") == 0) no_child = 1; else if (strcmp(argv[i], "--lock") == 0) lock = 1; else if (strcmp(argv[i], "--drop-all") == 0) which = 1; else if (strcmp(argv[i], "--drop-caps") == 0) which = 2; else if (strcmp(argv[i], "--id") == 0) which = 3; else if (strcmp(argv[i], "--init-grp") == 0) which = 4; else { usage(); return 0; } } switch (which) { case 1: capng_clear(CAPNG_SELECT_BOTH); if (lock) capng_lock(); capng_apply(CAPNG_SELECT_BOTH); report(); break; case 2: capng_clear(CAPNG_SELECT_CAPS); if (lock) capng_lock(); capng_apply(CAPNG_SELECT_CAPS); report(); break; case 3: case 4: { int rc; capng_clear(CAPNG_SELECT_BOTH); capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_CHOWN); if (which == 4) rc = capng_change_id(99, 99, CAPNG_INIT_SUPP_GRP | CAPNG_CLEAR_BOUNDING); else rc = capng_change_id(99, 99, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING); if (rc < 0) { printf("Error changing uid: %d\n", rc); capng_print_caps_text(CAPNG_PRINT_STDOUT, CAPNG_EFFECTIVE); printf("\n"); exit(1); } printf("Keeping CAP_CHOWN to show capabilities across uid change.\n"); report(); } break; case 0: if (lock) capng_lock(); report(); break; } return 0; }
VError XPosixDaemon::Daemonize() { #if defined(HAVE_CAP_NG) && (!defined(XTOOLBOX_AS_STANDALONE) || !XTOOLBOX_AS_STANDALONE) //Nice page on capabilities : //https://people.redhat.com/sgrubb/libcap-ng/ //Check if we have any capabilities if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE) { capng_clear(CAPNG_SELECT_BOTH); capng_type_t type = static_cast<capng_type_t>(CAPNG_EFFECTIVE|CAPNG_PERMITTED); int res = capng_updatev(CAPNG_ADD, type, CAP_NET_BIND_SERVICE, // Allows binding to TCP/UDP sockets below 1024 CAP_NET_BROADCAST, // Allow broadcasting, listen to multicast -1); if (res != 0) { std::cerr << "error: capng: impossible to update the stored capabilities settings\n"; return VE_FAIL_TO_DAEMONIZE; } res = capng_apply(CAPNG_SELECT_BOTH); if (res != 0) { std::cerr << "error: capng: impossible to apply the stored capabilities settings\n"; return VE_FAIL_TO_DAEMONIZE; } } #endif // HAVE_CAP_NG std::cout << "entering in daemon-mode\n"; pid_t pid = fork(); // Parent process should now quit asap, with no side effects // on ressources shared with its child (eg. do not corrupt files). // As it turns out, it's not so easy to properly quit a process // that is not fully initialized : QuitAsynchronously() and exit() // end in a crash. // Two good candidates to quickly quit with no crash are _exit() and kill(). if (pid > 0) _exit(0); // in the parent process if (pid < 0) // error { int err = errno; std::cerr << "error: failed to daemonize (errno: " << err << ")\n"; return VE_FAIL_TO_DAEMONIZE; } // The child process becomes a session leader if (setsid() < 0) { std::cerr << "error: failed to creates a session and sets the process group ID\n"; return VE_FAIL_TO_DAEMONIZE; } //Ignore a few signals - Might need some refinement ! signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); //Reset umask to some permissive and known value umask(0); //Reset current working directory to some known value chdir("/"); //Close standard file descriptors ::close(STDIN_FILENO); ::close(STDOUT_FILENO); ::close(STDERR_FILENO); return VE_OK; }
int main(int argc, char **argv) { enum { NNP = CHAR_MAX + 1, RUID, EUID, RGID, EGID, REUID, REGID, CLEAR_GROUPS, KEEP_GROUPS, GROUPS, INHCAPS, LISTCAPS, CAPBSET, SECUREBITS, SELINUX_LABEL, APPARMOR_PROFILE }; static const struct option longopts[] = { {"dump", no_argument, 0, 'd'}, {"nnp", no_argument, 0, NNP}, {"no-new-privs", no_argument, 0, NNP}, {"inh-caps", required_argument, 0, INHCAPS}, {"list-caps", no_argument, 0, LISTCAPS}, {"ruid", required_argument, 0, RUID}, {"euid", required_argument, 0, EUID}, {"rgid", required_argument, 0, RGID}, {"egid", required_argument, 0, EGID}, {"reuid", required_argument, 0, REUID}, {"regid", required_argument, 0, REGID}, {"clear-groups", no_argument, 0, CLEAR_GROUPS}, {"keep-groups", no_argument, 0, KEEP_GROUPS}, {"groups", required_argument, 0, GROUPS}, {"bounding-set", required_argument, 0, CAPBSET}, {"securebits", required_argument, 0, SECUREBITS}, {"selinux-label", required_argument, 0, SELINUX_LABEL}, {"apparmor-profile", required_argument, 0, APPARMOR_PROFILE}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {NULL, 0, 0, 0} }; static const ul_excl_t excl[] = { /* keep in same order with enum definitions */ {CLEAR_GROUPS, KEEP_GROUPS, GROUPS}, {0} }; int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; int c; struct privctx opts; int dumplevel = 0; int total_opts = 0; int list_caps = 0; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); memset(&opts, 0, sizeof(opts)); while ((c = getopt_long(argc, argv, "+dhV", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); total_opts++; switch (c) { case 'd': dumplevel++; break; case NNP: if (opts.nnp) errx(EXIT_FAILURE, _("duplicate --no-new-privs option")); opts.nnp = 1; break; case RUID: if (opts.have_ruid) errx(EXIT_FAILURE, _("duplicate ruid")); opts.have_ruid = 1; opts.ruid = get_user(optarg, _("failed to parse ruid")); break; case EUID: if (opts.have_euid) errx(EXIT_FAILURE, _("duplicate euid")); opts.have_euid = 1; opts.euid = get_user(optarg, _("failed to parse euid")); break; case REUID: if (opts.have_ruid || opts.have_euid) errx(EXIT_FAILURE, _("duplicate ruid or euid")); opts.have_ruid = opts.have_euid = 1; opts.ruid = opts.euid = get_user(optarg, _("failed to parse reuid")); break; case RGID: if (opts.have_rgid) errx(EXIT_FAILURE, _("duplicate rgid")); opts.have_rgid = 1; opts.rgid = get_group(optarg, _("failed to parse rgid")); break; case EGID: if (opts.have_egid) errx(EXIT_FAILURE, _("duplicate egid")); opts.have_egid = 1; opts.egid = get_group(optarg, _("failed to parse egid")); break; case REGID: if (opts.have_rgid || opts.have_egid) errx(EXIT_FAILURE, _("duplicate rgid or egid")); opts.have_rgid = opts.have_egid = 1; opts.rgid = opts.egid = get_group(optarg, _("failed to parse regid")); break; case CLEAR_GROUPS: if (opts.clear_groups) errx(EXIT_FAILURE, _("duplicate --clear-groups option")); opts.clear_groups = 1; break; case KEEP_GROUPS: if (opts.keep_groups) errx(EXIT_FAILURE, _("duplicate --keep-groups option")); opts.keep_groups = 1; break; case GROUPS: if (opts.have_groups) errx(EXIT_FAILURE, _("duplicate --groups option")); parse_groups(&opts, optarg); break; case LISTCAPS: list_caps = 1; break; case INHCAPS: if (opts.caps_to_inherit) errx(EXIT_FAILURE, _("duplicate --inh-caps option")); opts.caps_to_inherit = optarg; break; case CAPBSET: if (opts.bounding_set) errx(EXIT_FAILURE, _("duplicate --bounding-set option")); opts.bounding_set = optarg; break; case SECUREBITS: if (opts.have_securebits) errx(EXIT_FAILURE, _("duplicate --securebits option")); parse_securebits(&opts, optarg); break; case SELINUX_LABEL: if (opts.selinux_label) errx(EXIT_FAILURE, _("duplicate --selinux-label option")); opts.selinux_label = optarg; break; case APPARMOR_PROFILE: if (opts.apparmor_profile) errx(EXIT_FAILURE, _("duplicate --apparmor-profile option")); opts.apparmor_profile = optarg; break; case 'h': usage(stdout); case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case '?': usage(stderr); default: errx(EXIT_FAILURE, _("unrecognized option '%c'"), c); } } if (dumplevel) { if (total_opts != dumplevel || optind < argc) errx(EXIT_FAILURE, _("--dump is incompatible with all other options")); dump(dumplevel); return EXIT_SUCCESS; } if (list_caps) { if (total_opts != 1 || optind < argc) errx(EXIT_FAILURE, _("--list-caps must be specified alone")); list_known_caps(); return EXIT_SUCCESS; } if (argc <= optind) errx(EXIT_FAILURE, _("No program specified")); if ((opts.have_rgid || opts.have_egid) && !opts.keep_groups && !opts.clear_groups && !opts.have_groups) errx(EXIT_FAILURE, _("--[re]gid requires --keep-groups, --clear-groups, or --groups")); if (opts.nnp) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) err(EXIT_FAILURE, _("disallow granting new privileges failed")); if (opts.selinux_label) do_selinux_label(opts.selinux_label); if (opts.apparmor_profile) do_apparmor_profile(opts.apparmor_profile); if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) err(EXIT_FAILURE, _("keep process capabilities failed")); /* We're going to want CAP_SETPCAP, CAP_SETUID, and CAP_SETGID if * possible. */ bump_cap(CAP_SETPCAP); bump_cap(CAP_SETUID); bump_cap(CAP_SETGID); if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("activate capabilities")); if (opts.have_ruid || opts.have_euid) { do_setresuid(&opts); /* KEEPCAPS doesn't work for the effective mask. */ if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("reactivate capabilities")); } if (opts.have_rgid || opts.have_egid) do_setresgid(&opts); if (opts.have_groups) { if (setgroups(opts.num_groups, opts.groups) != 0) err(SETPRIV_EXIT_PRIVERR, _("setgroups failed")); } else if (opts.clear_groups) { gid_t x = 0; if (setgroups(0, &x) != 0) err(SETPRIV_EXIT_PRIVERR, _("setgroups failed")); } if (opts.have_securebits) if (prctl(PR_SET_SECUREBITS, opts.securebits, 0, 0, 0) != 0) err(SETPRIV_EXIT_PRIVERR, _("set process securebits failed")); if (opts.bounding_set) { do_caps(CAPNG_BOUNDING_SET, opts.bounding_set); errno = EPERM; /* capng doesn't set errno if we're missing CAP_SETPCAP */ if (capng_apply(CAPNG_SELECT_BOUNDS) != 0) err(SETPRIV_EXIT_PRIVERR, _("apply bounding set")); } if (opts.caps_to_inherit) { do_caps(CAPNG_INHERITABLE, opts.caps_to_inherit); if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("apply capabilities")); } execvp(argv[optind], argv + optind); err(EXIT_FAILURE, _("cannot execute: %s"), argv[optind]); }
/*! * \brief Thread entrypoint function. * * When a thread is created and started, it immediately enters this function. * Depending on thread state, it either enters runnable or * blocks until it is awakened. * * This function also handles "ThreadIdle" state to quickly suspend and resume * threads and mitigate thread creation costs. Also, thread runnable may * be changed to alter the thread behavior on runtime */ static void *thread_ep(void *data) { // Check data dthread_t *thread = (dthread_t *)data; if (thread == 0) { return 0; } // Check if is a member of unit dt_unit_t *unit = thread->unit; if (unit == 0) { return 0; } // Unblock SIGALRM sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGALRM); pthread_sigmask(SIG_UNBLOCK, &mask, NULL); rcu_register_thread(); dbg_dt("dthreads: [%p] entered ep\n", thread); /* Drop capabilities except FS access. */ #ifdef HAVE_CAP_NG_H if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) { capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED; capng_clear(CAPNG_SELECT_BOTH); capng_update(CAPNG_ADD, tp, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); } #endif /* HAVE_CAP_NG_H */ // Run loop for (;;) { // Check thread state lock_thread_rw(thread); if (thread->state == ThreadDead) { dbg_dt("dthreads: [%p] marked as dead\n", thread); unlock_thread_rw(thread); break; } // Update data thread->data = thread->_adata; runnable_t _run = thread->run; // Start runnable if thread is marked Active if ((thread->state == ThreadActive) && (thread->run != 0)) { unlock_thread_rw(thread); dbg_dt("dthreads: [%p] entering runnable\n", thread); _run(thread); dbg_dt("dthreads: [%p] exited runnable\n", thread); } else { unlock_thread_rw(thread); } // If the runnable was cancelled, start new iteration lock_thread_rw(thread); if (thread->state & ThreadCancelled) { dbg_dt("dthreads: [%p] cancelled\n", thread); thread->state &= ~ThreadCancelled; unlock_thread_rw(thread); continue; } unlock_thread_rw(thread); // Runnable finished without interruption, mark as Idle pthread_mutex_lock(&unit->_notify_mx); lock_thread_rw(thread); if (thread->state & ThreadActive) { thread->state &= ~ThreadActive; thread->state |= ThreadIdle; } // Go to sleep if idle if (thread->state & ThreadIdle) { unlock_thread_rw(thread); // Signalize state change unit_signalize_change(unit); // Wait for notification from unit dbg_dt("dthreads: [%p] going idle\n", thread); pthread_cond_wait(&unit->_notify, &unit->_notify_mx); pthread_mutex_unlock(&unit->_notify_mx); dbg_dt("dthreads: [%p] resumed from idle\n", thread); } else { unlock_thread_rw(thread); pthread_mutex_unlock(&unit->_notify_mx); } } // Thread destructor if (thread->destruct) { dbg_dt("dthreads: [%p] entering destructor\n", thread); thread->destruct(thread); dbg_dt("dthreads: [%p] exited destructor\n", thread); } // Report thread state change dbg_dt("dthreads: [%p] thread finished\n", thread); unit_signalize_change(unit); dbg_dt("dthreads: [%p] thread exited ep\n", thread); lock_thread_rw(thread); thread->state |= ThreadJoinable; unlock_thread_rw(thread); rcu_unregister_thread(); // Return return 0; }
int main(int argc, char *argv[]) { GOptionContext *context; GError *err = NULL; struct sigaction sa; #ifdef HAVE_CAPNG /* Drop capabilities */ 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, -1); capng_apply(CAPNG_SELECT_BOTH); #endif context = g_option_context_new(NULL); g_option_context_add_main_entries(context, options, NULL); if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) { if (err != NULL) { g_printerr("%s\n", err->message); g_error_free(err); } else g_printerr("An unknown error occurred\n"); exit(1); } g_option_context_free(context); if (option_detach == TRUE) { if (daemon(0, 0)) { perror("Can't start daemon"); exit(1); } } umask(0077); openlog("hcitrace", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); syslog(LOG_INFO, "HCI trace deamon %s", VERSION); memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = sig_term; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sa.sa_handler = sig_debug; sigaction(SIGUSR2, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); if (option_debug == TRUE) { syslog(LOG_INFO, "Enabling debug information"); } event_loop = g_main_loop_new(NULL, FALSE); debug("Entering main loop"); g_main_loop_run(event_loop); g_main_loop_unref(event_loop); syslog(LOG_INFO, "Exit"); closelog(); return 0; }
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()"); 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 != ECN_TUNNEL_or_old_SECCTX) { 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 '8': /* --drop-oppo-null */ pluto_drop_oppo_null = TRUE; continue; case '9': /* --expire-bare-shunt <interval> */ ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; bare_shunt_interval = u; 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> */ lsw_conf_secretsfile(optarg); continue; case 'f': /* --ipsecdir <ipsec-dir> */ lsw_init_ipsecdir(optarg); continue; 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_drop_oppo_null = cfg->setup.options[KBF_DROP_OPPO_NULL]; 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-threshold and max-halfopen-ike */ pluto_ddos_threshold = cfg->setup.options[KBF_DDOS_IKE_THRESHOLD]; 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 */ if (cfg->setup.strings[KSF_SECRETSFILE] && *cfg->setup.strings[KSF_SECRETSFILE]) { lsw_conf_secretsfile(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(); 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 != NULL) (*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) { #if USE_DAEMON if (daemon(TRUE, TRUE) < 0) { fprintf(stderr, "pluto: FATAL: daemon failed (%d %s)\n", errno, strerror(errno)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } /* * Parent just exits, so need to fill in our own PID * file. This is racy, since the file won't be * created until after the parent has exited. * * Since "ipsec start" invokes pluto with --nofork, it * is probably safer to leave this feature disabled * then implement it using the daemon call. */ (void) fill_lock(lockfd, getpid()); #elif USE_FORK { 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); } } #else fprintf(stderr, "pluto: FATAL: fork/daemon not supported\n"); exit_pluto(PLUTO_EXIT_FORK_FAIL); #endif 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(); init_pluto_constants(); pluto_init_log(); if (!pluto_init_nss(oco->nssdb)) { loglog(RC_LOG_SERIOUS, "FATAL: NSS initialization failure"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } libreswan_log("NSS crypto library initialized"); if (ocsp_enable) { if (!init_nss_ocsp(ocsp_default_uri, ocsp_trust_name, ocsp_timeout, strict_ocsp_policy)) { loglog(RC_LOG_SERIOUS, "Initializing NSS OCSP failed"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } 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, CAP_DAC_READ_SEARCH, -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 libreswan_log("FIPS HMAC integrity support [enabled]"); /* * FIPS mode requires two conditions to be true: * - FIPS Kernel mode: fips=1 kernel boot parameter * - FIPS Product mode: See FIPSPRODUCTCHECK in Makefile.inc * (in RHEL/Fedora, dracut-fips installs $FIPSPRODUCTCHECK) * * When FIPS mode, abort on self-check hmac failure. Otherwise, complain */ { if (DBGP(IMPAIR_FORCE_FIPS)) { libreswan_log("Forcing FIPS checks to true to emulate FIPS mode"); lsw_set_fips_mode(LSW_FIPS_ON); } enum lsw_fips_mode pluto_fips_mode = lsw_get_fips_mode(); bool nss_fips_mode = PK11_IsFIPS(); /* * Now verify the consequences. Always run the tests * as combinations such as NSS in fips mode but as out * of it could be bad. */ switch (pluto_fips_mode) { case LSW_FIPS_UNKNOWN: loglog(RC_LOG_SERIOUS, "ABORT: pluto FIPS mode could not be determined"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); break; case LSW_FIPS_ON: libreswan_log("FIPS mode enabled for pluto daemon"); if (nss_fips_mode) { libreswan_log("NSS library is running in FIPS mode"); } else { loglog(RC_LOG_SERIOUS, "ABORT: pluto in FIPS mode but NSS library is not"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); } break; case LSW_FIPS_OFF: libreswan_log("FIPS mode disabled for pluto daemon"); if (nss_fips_mode) { loglog(RC_LOG_SERIOUS, "Warning: NSS library is running in FIPS mode"); } break; case LSW_FIPS_UNSET: default: bad_case(pluto_fips_mode); } /* always run hmac check so we can print diagnostic */ bool fips_files = FIPSCHECK_verify_files(fips_package_files); if (fips_files) { libreswan_log("FIPS HMAC integrity verification self-test passed"); } else { loglog(RC_LOG_SERIOUS, "FIPS HMAC integrity verification self-test FAILED"); } if (pluto_fips_mode == LSW_FIPS_ON && !fips_files) { exit_pluto(PLUTO_EXIT_FIPS_FAIL); } } #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 (oco->secretsfile && *oco->secretsfile) libreswan_log("secrets file: %s", oco->secretsfile); 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"); if (DBGP(IMPAIR_SEND_BOGUS_DCOOKIE)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_DCOOKIE 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(); 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(); #ifdef USE_SYSTEMD_WATCHDOG pluto_sd_init(); #endif call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char** argv) { if (argc>1 && strstr(argv[1],"debug")) debug_mode=1; if (argc>1 && strstr(argv[1],"oneshot")) one_shot_mode=1; if (getenv("IRQBALANCE_BANNED_CPUS")) { cpumask_parse_user(getenv("IRQBALANCE_BANNED_CPUS"), strlen(getenv("IRQBALANCE_BANNED_CPUS")), banned_cpus); } if (getenv("IRQBALANCE_ONESHOT")) one_shot_mode=1; if (getenv("IRQBALANCE_DEBUG")) debug_mode=1; parse_cpu_tree(); /* On single core UP systems irqbalance obviously has no work to do */ if (core_count<2) exit(EXIT_SUCCESS); /* On dual core/hyperthreading shared cache systems just do a one shot setup */ if (cache_domain_count==1) one_shot_mode = 1; if (!debug_mode) if (daemon(0,0)) exit(EXIT_FAILURE); #ifdef HAVE_LIBCAP_NG // Drop capabilities capng_clear(CAPNG_SELECT_BOTH); capng_lock(); capng_apply(CAPNG_SELECT_BOTH); #endif parse_proc_interrupts(); sleep(SLEEP_INTERVAL/4); reset_counts(); parse_proc_interrupts(); pci_numa_scan(); calculate_workload(); sort_irq_list(); if (debug_mode) dump_workloads(); while (1) { sleep_approx(SLEEP_INTERVAL); if (debug_mode) printf("\n\n\n-----------------------------------------------------------------------------\n"); check_power_mode(); parse_proc_interrupts(); /* cope with cpu hotplug -- detected during /proc/interrupts parsing */ if (need_cpu_rescan) { need_cpu_rescan = 0; /* if there's a hotplug event we better turn off power mode for a bit until things settle */ power_mode = 0; if (debug_mode) printf("Rescanning cpu topology \n"); reset_counts(); clear_work_stats(); clear_cpu_tree(); parse_cpu_tree(); } /* deal with NAPI */ account_for_nic_stats(); calculate_workload(); /* to cope with dynamic configurations we scan for new numa information * once every 5 minutes */ if (counter % NUMA_REFRESH_INTERVAL == 16) pci_numa_scan(); calculate_placement(); activate_mapping(); if (debug_mode) dump_tree(); if (one_shot_mode) break; counter++; } return EXIT_SUCCESS; }