예제 #1
0
파일: lswconf.c 프로젝트: st3fan/libreswan
void lsw_conf_setdefault(void)
{
    char buf[PATH_MAX];
    char *ipsec_conf_dir = FINALCONFDIR;
    char *ipsecd_dir = FINALCONFDDIR;
    char *conffile   = FINALCONFFILE;
    char *var_dir    = FINALVARDIR;
    char *env;
#if 0
    char *exec_dir   = FINALLIBEXECDIR;
    char *lib_dir    = FINALLIBDIR;
    char *sbin_dir   = FINALSBINDIR;
#endif

    memset(&global_oco, 0, sizeof(global_oco));

    /* allocate them all to make it consistent */
    ipsec_conf_dir = clone_str(ipsec_conf_dir, "default conf ipsec_conf_dir");
    ipsecd_dir = clone_str(ipsecd_dir, "default conf ipsecd_dir");
    conffile   = clone_str(conffile, "default conf conffile");
    var_dir    = clone_str(var_dir, "default conf var_dir");
    
    global_oco.rootdir = "";
    global_oco.confddir= ipsecd_dir;
    global_oco.vardir  = var_dir;
    global_oco.confdir = ipsec_conf_dir;
    global_oco.conffile = conffile;

    /* path to NSS password file */
    snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir);
    NSSPassword.data = clone_str(buf, "nss password file path");
    NSSPassword.source =  PW_FROMFILE;
    /* DBG_log("default setting of ipsec.d to %s", global_oco.confddir); */
}
예제 #2
0
void lsw_init_ipsecdir(const char *ipsec_dir)
{
	if (!setup)
		lsw_conf_setdefault();
	global_oco.confddir = clone_str(ipsec_dir, "override ipsec.d");
	global_oco.nssdir = clone_str(ipsec_dir, "override nssdir");
	lsw_conf_calculate(&global_oco);
	setup = TRUE;

	libreswan_log("adjusting ipsec.d to %s", global_oco.confddir);
}
예제 #3
0
void osw_conf_setdefault(void)
{
    char buf[PATH_MAX];
    char *ipsec_conf_dir = FINALCONFDIR;
    char *ipsecd_dir = FINALCONFDDIR;
    char *conffile   = FINALCONFFILE;
    char *var_dir    = FINALVARDIR;
    char *env;
#if 0
    char *exec_dir   = FINALLIBEXECDIR;
    char *lib_dir    = FINALLIBDIR;
    char *sbin_dir   = FINALSBINDIR;
#endif

    memset(&global_oco, 0, sizeof(global_oco));

    /* allocate them all to make it consistent */
    ipsec_conf_dir = clone_str(ipsec_conf_dir, "default conf ipsec_conf_dir");
    ipsecd_dir = clone_str(ipsecd_dir, "default conf ipsecd_dir");
    conffile   = clone_str(conffile, "default conf conffile");
    var_dir    = clone_str(var_dir, "default conf var_dir");

    /* figure out what we are doing, look for variables in the environment */
    if((env = getenv("IPSEC_CONFS")) != NULL) {
        pfree(ipsec_conf_dir);
        ipsec_conf_dir = clone_str(env, "ipsec_confs");

        /* if they change IPSEC_CONFS, reassign ipsecd as well */
        snprintf(buf, sizeof(buf), "%s/ipsec.d", ipsec_conf_dir);
        pfree(ipsecd_dir);
        ipsecd_dir = clone_str(buf, "ipsecdir");

        /* if they change IPSEC_CONFS, reassign ipsec policies as well */
        snprintf(buf, sizeof(buf), "%s/ipsec.conf", ipsec_conf_dir);
        pfree(conffile);
        conffile = clone_str(buf, "ipsec.conf");
    }

    if((env = getenv("IPSEC_CONFFILE")) != NULL) {
        pfree(conffile);
        pfree(ipsec_conf_dir);
        conffile = clone_str(env, "ipsec.conf");
    }

    global_oco.rootdir = "";
    global_oco.confddir= ipsecd_dir;
    global_oco.vardir  = var_dir;
    global_oco.confdir = ipsec_conf_dir;
    global_oco.conffile = conffile;

#ifdef HAVE_LIBNSS
    /* path to NSS password file */
    snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir);
    NSSPassword.data = clone_str(buf, "nss password file path");
    NSSPassword.source =  PW_FROMFILE;
#endif
    /* DBG_log("default setting of ipsec.d to %s", global_oco.confddir); */
}
예제 #4
0
static void osw_conf_calculate(struct osw_conf_options *oco)
{
    char buf[PATH_MAX];

    /* calculate paths to certain subdirs */
    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/acerts"), oco->confddir);
    oco->acerts_dir = clone_str(buf, "acert path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/cacerts"), oco->confddir);
    oco->cacerts_dir = clone_str(buf, "cacert path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/crls"), oco->confddir);
    oco->crls_dir = clone_str(buf, "crls path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/private"), oco->confddir);
    oco->private_dir = clone_str(buf, "private path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/certs"), oco->confddir);
    oco->certs_dir = clone_str(buf, "certs path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/aacerts"), oco->confddir);
    oco->aacerts_dir = clone_str(buf, "aacerts path");

    snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/ocspcerts"), oco->confddir);
    oco->ocspcerts_dir = clone_str(buf, "ocspcerts path");

    snprintf(buf, sizeof(buf), "%s/policies", oco->confddir);
    oco->policies_dir = clone_str(buf, "policies path");
}
예제 #5
0
static void lsw_conf_calculate(struct lsw_conf_options *oco)
{
	char buf[PATH_MAX];

	/* will be phased out for NSS in the near future */
	snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/cacerts"), oco->confddir);
	oco->cacerts_dir = clone_str(buf, "cacert path");

	snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/crls"), oco->confddir);
	oco->crls_dir = clone_str(buf, "crls path");

	/* old OE policies - might get re-used in the near future */
	snprintf(buf, sizeof(buf), "%s/policies", oco->confddir);
	oco->policies_dir = clone_str(buf, "policies path");
}
예제 #6
0
static void key_add_continue(struct adns_continuation *ac, err_t ugh)
{
	struct key_add_continuation *kc = (void *) ac;
	struct key_add_common *oc = kc->common;

	passert(whack_log_fd == NULL_FD);
	whack_log_fd = oc->whack_fd;

	if (ugh != NULL)
	{
		oc->diag[kc->lookingfor] = clone_str(ugh);
	}
	else
	{
		oc->success = TRUE;
		transfer_to_public_keys(kc->ac.gateways_from_dns
#ifdef USE_KEYRR
			, &kc->ac.keys_from_dns
#endif /* USE_KEYRR */
			);
	}

	oc->refCount--;
	key_add_merge(oc, ac->id);
	whack_log_fd = NULL_FD;
}
예제 #7
0
static char * mapper_find_user(X509 *x509,void *context,int *mp) {
	if ( !x509 ) return NULL;
	if (match) {
	    *mp = 1;
	    return clone_str((char *)default_user);
	}
	return NULL;
}
예제 #8
0
const struct osw_conf_options *osw_init_rootdir(const char *root_dir)
{
    if(!setup) osw_conf_setdefault();
    global_oco.rootdir = clone_str(root_dir, "override /");
    osw_conf_calculate(&global_oco);
    setup = TRUE;

    return &global_oco;
}
예제 #9
0
파일: myid.c 프로젝트: yottanami/libreswan
static void calc_myid_str(enum myid_state s)
{
	/* preformat the ID name */
	char buf[IDTOA_BUF];

	idtoa(&myids[s], buf, IDTOA_BUF);
	/* replace() uses pfreeany() */
	replace(myid_str[s], clone_str(buf, "myid string"));
}
예제 #10
0
/* This is only used in testing/crypto (and formerly in testing/lib/libpluto) */
void lsw_init_rootdir(const char *root_dir)
{
	if (!setup)
		lsw_conf_setdefault();
	pfreeany(global_oco.rootdir);
	global_oco.rootdir = clone_str(root_dir, "override /");
	lsw_conf_calculate(&global_oco);
	setup = TRUE;
}
예제 #11
0
const struct osw_conf_options *osw_init_ipsecdir(const char *ipsec_dir)
{
    if(!setup) osw_conf_setdefault();
    global_oco.confddir = clone_str(ipsec_dir, "override ipsec.d");
    osw_conf_calculate(&global_oco);
    setup = TRUE;

    openswan_log("adjusting ipsec.d to %s", global_oco.confddir);

    return &global_oco;
}
예제 #12
0
/* Called to handle --interface <ifname>
 * Semantics: if specified, only these (real) interfaces are considered.
 */
bool use_interface(const char *rifn)
{
	if (pluto_ifn_inst[0] == '\0')
		pluto_ifn_inst = clone_str(rifn, "genifn");

	if (pluto_ifn_roof >= (int)elemsof(pluto_ifn)) {
		return FALSE;
	} else {
		pluto_ifn[pluto_ifn_roof++] = rifn;
		return TRUE;
	}
}
예제 #13
0
struct starter_conn *alloc_add_conn(struct starter_config *cfg, const char *name)
{
	struct starter_conn *conn = alloc_thing(struct starter_conn, "add_conn starter_conn");

	conn_default(conn, &cfg->conn_default);
	conn->name = clone_str(name, "add conn name");
	conn->desired_state = STARTUP_IGNORE;
	conn->state = STATE_FAILED;

	TAILQ_INIT(&conn->comments);

	TAILQ_INSERT_TAIL(&cfg->conns, conn, link);
	return conn;
}
예제 #14
0
/*
parses the certificate and return the email entry found, or NULL
*/
static char * krb_mapper_find_user(X509 *x509, void *context, int *match) {
        char *res;
        char **entries= cert_info(x509,CERT_KPN,ALGORITHM_NULL);
        if (!entries) {
            DBG("get_krb_principalname() failed");
            return NULL;
        }
        DBG1("trying to map kpn entry '%s'",entries[0]);
        res = mapfile_find("none",entries[0],0,match);
        if (!res) {
            DBG("Error in map process");
            return NULL;
        }
        return clone_str(res);
}
예제 #15
0
/*
parses the certificate and return the map of the first UID entry found
If no UID found or map error, return NULL
*/
static char * uid_mapper_find_user(X509 *x509, void *context, int *match) {
	char *res;
	char **entries= cert_info(x509,CERT_UID,ALGORITHM_NULL);
        if (!entries) {
            DBG("get_unique_id() failed");
            return NULL;
        }
        DBG1("trying to map uid entry '%s'",entries[0]);
        res = mapfile_find(mapfile,entries[0],ignorecase,match);
	if (!res) {
	    DBG("Error in map process");
	    return NULL;
	}
	return clone_str(res);
}
예제 #16
0
struct starter_conn *alloc_add_conn(struct starter_config *cfg, char *name, err_t *perr)
{
    struct starter_conn *conn;

    conn = (struct starter_conn *)alloc_bytes(sizeof(struct starter_conn),"add_conn starter_conn");

    zero(conn);
    conn_default(name, conn, &cfg->conn_default);
    conn->name = clone_str(name, "conn name");
    conn->desired_state = STARTUP_NO;
    conn->state = STATE_FAILED;

    TAILQ_INIT(&conn->comments);

    TAILQ_INSERT_TAIL(&cfg->conns, conn, link);
    return conn;
}
예제 #17
0
/*
 * handles left|rightfirewall and left|rightupdown parameters
 */
static void handle_firewall(const char *label, starter_end_t *end,
							starter_config_t *cfg)
{
	if (end->firewall && (end->seen & LELEM(KW_FIREWALL - KW_END_FIRST)))
	{
		if (end->updown != NULL)
		{
			plog("# cannot have both %sfirewall and %supdown", label, label);
			cfg->err++;
		}
		else
		{
			end->updown = clone_str(firewall_defaults);
			end->firewall = FALSE;
		}
	}
}
예제 #18
0
static void lsw_conf_setdefault(void)
{
	char buf[PATH_MAX];
	static const struct lsw_conf_options zero_oco;	/* full of null pointers */

	global_oco = zero_oco;

	/* allocate them all to make it consistent */
	global_oco.rootdir = clone_str("","rootdir");
	global_oco.confddir = clone_str(IPSEC_CONFDDIR, "default conf ipsecd_dir");
	global_oco.vardir  = clone_str(IPSEC_VARDIR, "default vardir");
	global_oco.confdir = clone_str(IPSEC_CONFDIR, "default conf ipsec_conf_dir");
	global_oco.conffile = clone_str(IPSEC_CONF, "default conf conffile");
	global_oco.nssdir = clone_str(IPSEC_NSSDIR, "default nssdir");

	/* path to NSS password file */
	snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir);
	NSSPassword.data = clone_str(buf, "nss password file path");
	NSSPassword.source =  PW_FROMFILE;
}
예제 #19
0
/*
 * parse a conn section
 */
static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
{
	char *conn_name = (conn->name == NULL)? "%default":conn->name;

	for ( ; kw; kw = kw->next)
	{
		bool assigned = FALSE;

		kw_token_t token = kw->entry->token;

		if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
		{
			kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST
				,  kw, conn_name, cfg);
			continue;
		}
		else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
		{
			kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST
				 , kw, conn_name, cfg);
			continue;
		}

		if (token == KW_AUTO)
		{
			token = KW_CONN_SETUP;
		}
		else if (token == KW_ALSO)
		{
			if (cfg->parse_also)
			{
				also_t *also = malloc_thing(also_t);

				also->name = clone_str(kw->value);
				also->next = conn->also;
				conn->also = also;

				DBG(DBG_CONTROL,
					DBG_log("  also=%s", kw->value)
				)
			}
			continue;
		}

		if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
		{
			plog("# unsupported keyword '%s' in conn '%s'"
				, kw->entry->name, conn_name);
			cfg->err++;
			continue;
		}

		if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned))
		{
			plog("  bad argument value in conn '%s'", conn_name);
			cfg->err++;
			continue;
		}

		if (assigned)
			continue;

		switch (token)
		{
		case KW_TYPE:
			conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK);
			if (streq(kw->value, "tunnel"))
			{
				conn->policy |= POLICY_TUNNEL;
			}
			else if (streq(kw->value, "beet"))
			{
				conn->policy |= POLICY_BEET;
			}
			else if (streq(kw->value, "transport_proxy"))
			{
				conn->policy |= POLICY_PROXY;
			}
			else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
			{
				conn->policy |= POLICY_SHUNT_PASS;
			}
			else if (streq(kw->value, "drop"))
			{
				conn->policy |= POLICY_SHUNT_DROP;
			}
			else if (streq(kw->value, "reject"))
			{
				conn->policy |= POLICY_SHUNT_REJECT;
			}
			else if (strcmp(kw->value, "transport") != 0)
			{
				plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
				cfg->err++;
			}
			break;
		case KW_PFS:
			KW_POLICY_FLAG("yes", "no", POLICY_PFS)
			break;
		case KW_COMPRESS:
			KW_POLICY_FLAG("yes", "no", POLICY_COMPRESS)
			break;
		case KW_PMTUDISC:
			if (streq(kw->value, "no"))
			{
				conn->xfrm_flags |= XFRM_STATE_NOPMTUDISC;
			}
			break;
		case KW_IPSECDEV:
			conn->dev = get_ifindex(kw->value);
			if (conn->dev < 0) {
				cfg->err++;
			}
			break;
		case KW_ECN:
			if (streq(kw->value, "no"))
			{
				conn->xfrm_flags |= XFRM_STATE_NOECN;
			}
			break;
		case KW_AUTH:
			KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE)
			break;
		case KW_AUTHBY:
			conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT);

			if (!(streq(kw->value, "never") || streq(kw->value, "eap")))
			{
				char *value = kw->value;
				char *second = strchr(kw->value, '|');

				if (second != NULL)
				{
					*second = '\0';
				}

				/* also handles the cases secret|rsasig and rsasig|secret */
				for (;;)
				{
					if (streq(value, "rsa")   || streq(value, "rsasig")   ||
						streq(value, "ecdsa") || streq(value, "ecdsasig") ||
						streq(value, "pubkey"))
					{
						conn->policy |= POLICY_PUBKEY | POLICY_ENCRYPT;
					}
					else if (streq(value, "secret") || streq(value, "psk"))
					{
						conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
					}
					else if (streq(value, "xauthrsasig"))
					{
						conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
					}
					else if (streq(value, "xauthpsk"))
					{
						conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT;
					}
					else
					{
						plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
						cfg->err++;
						break;
					}
					if (second == NULL)
					{
						break;
					}
					value = second;
					second = NULL; /* traverse the loop no more than twice */
				}
			}
			break;
		case KW_EAP:
		{
			char *sep;

			/* check for vendor-type format */
			sep = strchr(kw->value, '-');
			if (sep)
			{
				*(sep++) = '\0';
				conn->eap_type = atoi(kw->value);
				conn->eap_vendor = atoi(sep);
				if (conn->eap_type == 0 || conn->eap_vendor == 0)
				{
					plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value);
					cfg->err++;
				}
				break;
			}
			if (streq(kw->value, "aka"))
			{
				conn->eap_type = 23;
			}
			else if (streq(kw->value, "sim"))
			{
				conn->eap_type = 18;
			}
			else if (streq(kw->value, "md5"))
			{
				conn->eap_type = 4;
			}
			else if (streq(kw->value, "gtc"))
			{
				conn->eap_type = 6;
			}
			else if (streq(kw->value, "mschapv2"))
			{
				conn->eap_type = 26;
			}
			else if (streq(kw->value, "radius"))
			{	/* pseudo-type */
				conn->eap_type = 253;
			}
			else
			{
				conn->eap_type = atoi(kw->value);
				if (conn->eap_type == 0)
				{
					plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value);
					cfg->err++;
				}
			}
			break;
		}
		case KW_KEYINGTRIES:
			if (streq(kw->value, "%forever"))
			{
				conn->sa_keying_tries = 0;
			}
			else
			{
				char *endptr;

				conn->sa_keying_tries = strtoul(kw->value, &endptr, 10);
				if (*endptr != '\0')
				{
					plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
		    		cfg->err++;
				}
			}
			break;
		case KW_REKEY:
			KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY)
			break;
		case KW_REAUTH:
			KW_POLICY_FLAG("no", "yes", POLICY_DONT_REAUTH)
			break;
		case KW_MOBIKE:
			KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE)
			break;
		case KW_FORCEENCAPS:
			KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP)
			break;
		case KW_MODECONFIG:
			KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH)
			break;
		case KW_XAUTH:
			KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER)
			break;
		default:
			break;
		}
	}
예제 #20
0
static void default_values(starter_config_t *cfg)
{
	if (cfg == NULL)
		return;

	memset(cfg, 0, sizeof(struct starter_config));

    /* is there enough space for all seen flags? */
	assert(KW_SETUP_LAST - KW_SETUP_FIRST <
		sizeof(cfg->setup.seen) * BITS_PER_BYTE);
	assert(KW_CONN_LAST  - KW_CONN_FIRST <
		sizeof(cfg->conn_default.seen) * BITS_PER_BYTE);
	assert(KW_END_LAST - KW_END_FIRST <
		sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE);
	assert(KW_CA_LAST - KW_CA_FIRST <
		sizeof(cfg->ca_default.seen) * BITS_PER_BYTE);

	cfg->setup.seen        = LEMPTY;
	cfg->setup.fragicmp    = TRUE;
	cfg->setup.hidetos     = TRUE;
	cfg->setup.uniqueids   = TRUE;
	cfg->setup.interfaces  = new_list("%defaultroute");

#ifdef START_CHARON
	cfg->setup.charonstart = TRUE;
#endif
#ifdef START_PLUTO
	cfg->setup.plutostart  = TRUE;
#endif

	cfg->setup.pluto_ikeport = IKE_UDP_PORT;

	cfg->setup.ha_seqdiff_in  = 0xFFFFFFFF;
	cfg->setup.ha_seqdiff_out = 0xFFFFFFFF;

	cfg->conn_default.seen    = LEMPTY;
	cfg->conn_default.startup = STARTUP_NO;
	cfg->conn_default.state   = STATE_IGNORE;
	cfg->conn_default.policy  = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_PUBKEY |
								POLICY_PFS | POLICY_MOBIKE;

	cfg->conn_default.ike                   = clone_str(ike_defaults);
	cfg->conn_default.esp                   = clone_str(esp_defaults);
	cfg->conn_default.sa_ike_life_seconds   = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
	cfg->conn_default.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
	cfg->conn_default.sa_rekey_margin       = SA_REPLACEMENT_MARGIN_DEFAULT;
	cfg->conn_default.sa_rekey_fuzz         = SA_REPLACEMENT_FUZZ_DEFAULT;
	cfg->conn_default.sa_keying_tries       = SA_REPLACEMENT_RETRIES_DEFAULT;
	cfg->conn_default.addr_family           = AF_INET;
	cfg->conn_default.tunnel_addr_family    = AF_INET;
	cfg->conn_default.xfrm_flags            = 0;
	cfg->conn_default.install_policy	= TRUE;
	cfg->conn_default.dev			= 0;
	cfg->conn_default.dpd_delay		=  30; /* seconds */
	cfg->conn_default.dpd_timeout		= 150; /* seconds */

	cfg->conn_default.left.seen  = LEMPTY;
	cfg->conn_default.right.seen = LEMPTY;

	cfg->conn_default.left.sendcert  = CERT_SEND_IF_ASKED;
	cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;

	anyaddr(AF_INET, &cfg->conn_default.left.addr);
	anyaddr(AF_INET, &cfg->conn_default.left.nexthop);
	anyaddr(AF_INET, &cfg->conn_default.right.addr);
	anyaddr(AF_INET, &cfg->conn_default.right.nexthop);
	cfg->conn_default.left.ikeport = 500;
	cfg->conn_default.right.ikeport = 500;

	cfg->ca_default.seen = LEMPTY;
}
예제 #21
0
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
				   kw_list_t *kw, char *conn_name, starter_config_t *cfg)
{
	err_t ugh = NULL;
	bool assigned = FALSE;
	bool has_port_wildcard;        /* set if port is %any */

	char *name  = kw->entry->name;
	char *value = kw->value;

	if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
		goto err;

	/* post processing of some keywords that were assigned automatically */
	switch (token)
	{
	case KW_SUBNET:
		if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0)
		||  (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0))
		{
			/* used by pluto only */
			end->has_virt = TRUE;
		}
		else
		{
			ip_subnet net;
			char *pos;
			int len = 0;

			end->has_client = TRUE;
			conn->tunnel_addr_family = ip_version(value);

			pos = strchr(value, ',');
			if (pos)
			{
				len = pos - value;
			}
			ugh = ttosubnet(value, len, ip_version(value), &net);
			if (ugh != NULL)
			{
				plog("# bad subnet: %s=%s [%s]", name, value, ugh);
				goto err;
			}
		}
		break;
	case KW_SOURCEIP:
		if (end->has_natip)
		{
			plog("# natip and sourceip cannot be defined at the same time");
			goto err;
		}
		if (value[0] == '%')
		{
			if (streq(value, "%modeconfig") || streq(value, "%modecfg") ||
				streq(value, "%config") || streq(value, "%cfg"))
			{
				/* request ip via config payload */
				free(end->sourceip);
				end->sourceip = NULL;
				end->sourceip_mask = 1;
			}
			else
			{	/* %poolname, strip %, serve ip requests */
				free(end->sourceip);
				end->sourceip = clone_str(value+1);
				end->sourceip_mask = 0;
			}
			end->modecfg = TRUE;
		}
		else
		{
			char *pos;
			ip_address addr;
			ip_subnet net;

			conn->tunnel_addr_family = ip_version(value);
			pos = strchr(value, '/');

			if (pos)
			{	/* CIDR notation, address pool */
				ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net);
				if (ugh != NULL)
				{
					plog("# bad subnet: %s=%s [%s]", name, value, ugh);
					goto err;
				 }
				*pos = '\0';
				free(end->sourceip);
				end->sourceip = clone_str(value);
				end->sourceip_mask = atoi(pos + 1);
			}
			else
			{	/* fixed srcip */
				ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
				if (ugh != NULL)
				{
					plog("# bad addr: %s=%s [%s]", name, value, ugh);
					goto err;
				}
				end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ?
									  32 : 128;
			}
		}
		conn->policy |= POLICY_TUNNEL;
		break;
	case KW_SENDCERT:
		if (end->sendcert == CERT_YES_SEND)
		{
			end->sendcert = CERT_ALWAYS_SEND;
		}
		else if (end->sendcert == CERT_NO_SEND)
		{
			end->sendcert = CERT_NEVER_SEND;
		}
		break;
	default:
		break;
	}

	if (assigned)
		return;

	/* individual processing of keywords that were not assigned automatically */
	switch (token)
	{
	case KW_HOST:
		if (streq(value, "%defaultroute"))
		{
			if (cfg->defaultroute.defined)
			{
				end->addr    = cfg->defaultroute.addr;
				end->nexthop = cfg->defaultroute.nexthop;
			}
			else if (!cfg->defaultroute.supported)
			{
				plog("%%defaultroute not supported, fallback to %%any");
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else if (streq(value, "%any") || streq(value, "%any4"))
		{
			anyaddr(conn->addr_family, &end->addr);
		}
		else if (streq(value, "%any6"))
		{
			conn->addr_family = AF_INET6;
			anyaddr(conn->addr_family, &end->addr);
		}
		else if (streq(value, "%group"))
		{
			ip_address any;

			conn->policy |= POLICY_GROUP | POLICY_TUNNEL;
			anyaddr(conn->addr_family, &end->addr);
			anyaddr(conn->tunnel_addr_family, &any);
			end->has_client = TRUE;
		}
		else
		{
			/* check for allow_any prefix */
			if (value[0] == '%')
			{
				end->allow_any = TRUE;
				value++;
			}
			conn->addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->addr_family, &end->addr);
			if (ugh != NULL)
			{
				plog("# bad addr: %s=%s [%s]", name, value, ugh);
				if (streq(ugh, "does not look numeric and name lookup failed"))
				{
					end->dns_failed = TRUE;
					anyaddr(conn->addr_family, &end->addr);
				}
				else
				{
					goto err;
				}
			}
		}
		break;
	case KW_NEXTHOP:
		if (streq(value, "%defaultroute"))
		{
			if (cfg->defaultroute.defined)
			{
				end->nexthop = cfg->defaultroute.nexthop;
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else if (streq(value, "%direct"))
		{
			ugh = anyaddr(conn->addr_family, &end->nexthop);
		}
		else
		{
			conn->addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop);
		}
		if (ugh != NULL)
		{
			plog("# bad addr: %s=%s [%s]", name, value, ugh);
			goto err;
		}
		break;
	case KW_SUBNETWITHIN:
	{
		ip_subnet net;

		end->has_client = TRUE;
		end->has_client_wildcard = TRUE;
		conn->tunnel_addr_family = ip_version(value);

		ugh = ttosubnet(value, 0, ip_version(value), &net);
		if (ugh != NULL)
		{
			plog("# bad subnet: %s=%s [%s]", name, value, ugh);
			goto err;
		}
		end->subnet = clone_str(value);
		break;
	}
	case KW_PROTOPORT:
		ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard);
		end->has_port_wildcard = has_port_wildcard;
		break;
	case KW_NATIP:
		if (end->sourceip)
		{
			plog("# natip and sourceip cannot be defined at the same time");
			goto err;
		}
		if (streq(value, "%defaultroute"))
		{
			char buf[64];

			if (cfg->defaultroute.defined)
			{
				addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf));
				end->sourceip = clone_str(buf);
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else
		{
			ip_address addr;

			conn->tunnel_addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
			if (ugh != NULL)
			{
				plog("# bad addr: %s=%s [%s]", name, value, ugh);
				goto err;
			}
			end->sourceip = clone_str(value);
		}
		end->has_natip = TRUE;
		conn->policy |= POLICY_TUNNEL;
		break;
	default:
		break;
	}
	return;

err:
	plog("  bad argument value in conn '%s'", conn_name);
	cfg->err++;
}
예제 #22
0
static void key_add_request(const struct whack_message *msg)
{
	struct id keyid;
	err_t ugh = atoid(msg->keyid, &keyid, FALSE, FALSE);

	if (ugh != NULL) {
		loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
	} else {
		if (!msg->whack_addkey)
			delete_public_keys(&pluto_pubkeys, &keyid,
					   msg->pubkey_alg);

		if (msg->keyval.len == 0) {
			struct key_add_common *oc =
				alloc_thing(struct key_add_common,
					    "key add common things");
			enum key_add_attempt kaa;

			/* initialize state shared by queries */
			oc->refCount = 0;
			oc->whack_fd = dup_any(whack_log_fd);
			oc->success = FALSE;

			for (kaa = ka_TXT; kaa != ka_roof; kaa++) {
				struct key_add_continuation *kc =
					alloc_thing(
						struct key_add_continuation,
						"key add continuation");

				oc->diag[kaa] = NULL;
				oc->refCount++;
				kc->common = oc;
				kc->lookingfor = kaa;
				switch (kaa) {
				case ka_TXT:
					ugh = start_adns_query(&keyid,
							       &keyid, /* same */
							       ns_t_txt,
							       key_add_continue,
							       &kc->ac);
					break;
#ifdef USE_KEYRR
				case ka_KEY:
					ugh = start_adns_query(&keyid,
							       NULL,
							       ns_t_key,
							       key_add_continue,
							       &kc->ac);
					break;
#endif                                                  /* USE_KEYRR */
				default:
					bad_case(kaa);  /* suppress gcc warning */
				}
				if (ugh != NULL) {
					oc->diag[kaa] = clone_str(ugh,
								  "early key add failure");
					oc->refCount--;
				}
			}

			/* Done launching queries.
			 * Handle total failure case.
			 */
			key_add_merge(oc, &keyid);
		} else {
			ugh = add_public_key(&keyid, DAL_LOCAL,
					     msg->pubkey_alg,
					     &msg->keyval, &pluto_pubkeys);
			if (ugh != NULL)
				loglog(RC_LOG_SERIOUS, "%s", ugh);
		}
	}
예제 #23
0
static void key_add_request(const whack_message_t *msg)
{
	identification_t *key_id;

	key_id = identification_create_from_string(msg->keyid);

	if (!msg->whack_addkey)
	{
		delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
	}
	if (msg->keyval.len == 0)
	{
		struct key_add_common *oc = malloc_thing(struct key_add_common);
		enum key_add_attempt kaa;
		err_t ugh;

		/* initialize state shared by queries */
		oc->refCount = 0;
		oc->whack_fd = dup_any(whack_log_fd);
		oc->success = FALSE;

		for (kaa = ka_TXT; kaa != ka_roof; kaa++)
		{
			struct key_add_continuation *kc;

			oc->diag[kaa] = NULL;
			oc->refCount++;
			kc = malloc_thing(struct key_add_continuation);
			kc->common = oc;
			kc->lookingfor = kaa;

			switch (kaa)
			{
				case ka_TXT:
					ugh = start_adns_query(key_id
							, key_id        /* same */
							, T_TXT
							, key_add_continue
							, &kc->ac);
					break;
#ifdef USE_KEYRR
				case ka_KEY:
					ugh = start_adns_query(key_id
							, NULL
							, T_KEY
							, key_add_continue
							, &kc->ac);
					break;
#endif /* USE_KEYRR */
				default:
					bad_case(kaa);      /* suppress gcc warning */
			}
			if (ugh)
			{
				oc->diag[kaa] = clone_str(ugh);
				oc->refCount--;
			}
		}

		/* Done launching queries. Handle total failure case. */
		key_add_merge(oc, key_id);
	}
	else
	{
		if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
예제 #24
0
파일: addconn.c 프로젝트: saaros/libreswan
int main(int argc, char *argv[])
{
	int opt = 0;
	int autoall = 0;
	int configsetup = 0;
	int checkconfig = 0;
	char *export = "export"; /* display export before the foo=bar or not */
	int listroute = 0, liststart = 0, listignore = 0, listadd = 0,
		listall = 0, dolist = 0, liststack = 0;
	struct starter_config *cfg = NULL;
	err_t err = NULL;
	char *confdir = NULL;
	char *configfile = NULL;
	char *varprefix = "";
	int exit_status = 0;
	struct starter_conn *conn = NULL;
	char *ctlbase = NULL;
	bool resolvip = TRUE; /* default to looking up names */

#if 0
	/* efence settings */
	extern int EF_PROTECT_BELOW;
	extern int EF_PROTECT_FREE;

	EF_PROTECT_BELOW = 1;
	EF_PROTECT_FREE = 1;
#endif

	progname = argv[0];
	rootdir[0] = '\0';

	tool_init_log();

	while ((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) {
		switch (opt) {
		case 'h':
			/* usage: */
			usage();
			break;

		case 'a':
			autoall = 1;
			break;

		case 'D':
			verbose++;
			lex_verbosity++;
			break;

		case 'T':
			configsetup++;
			break;

		case 'K':
			checkconfig++;
			break;

		case 'N':
			export = "";
			break;

		case 'C':
			configfile = clone_str(optarg, "config file name");
			break;

		case 'c':
			ctlbase = clone_str(optarg, "control base");
			break;

		case 'L':
			listadd = 1;
			dolist = 1;
			break;

		case 'r':
			listroute = 1;
			dolist = 1;
			break;

		case 's':
			liststart = 1;
			dolist = 1;
			break;

		case 'S':
			liststack = 1;
			dolist = 1;
			break;

		case 'i':
			listignore = 1;
			dolist = 1;
			break;

		case 'A':
			listall = 1;
			dolist = 1;
			break;

		case 'P':
			varprefix = optarg;
			break;

		case 'R':
			printf("setting rootdir=%s\n", optarg);
			jam_str(rootdir, sizeof(rootdir), optarg);
			break;

		case 'd':
		case 'n':
			printf("Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n");
			break;

		default:
			usage();
		}
	}

	/* if nothing to add, then complain */
	if (optind == argc && !autoall && !dolist && !configsetup &&
		!checkconfig)
		usage();

	if (verbose > 3) {
		yydebug = 1;
	}

	/* find config file */
	if (confdir == NULL)
		confdir = IPSEC_CONFDIR;

	if (configfile == NULL) {
		/* ??? see code clone in programs/readwriteconf/readwriteconf.c */
		configfile = alloc_bytes(strlen(confdir) +
					 sizeof("/ipsec.conf"),
					 "conf file");

		/* calculate default value for configfile */
		strcpy(configfile, confdir);	/* safe: see allocation above */
		if (configfile[0] != '\0' && configfile[strlen(configfile) - 1] != '/')
			strcat(configfile, "/");	/* safe: see allocation above */
		strcat(configfile, "ipsec.conf");	/* safe: see allocation above */
	}

	if (verbose)
		printf("opening file: %s\n", configfile);

	starter_use_log(verbose != 0, TRUE, verbose == 0);

	err = NULL;	/* reset to no error */

	if (configsetup || checkconfig || dolist) {
		/* skip if we have no use for them... causes delays */
		resolvip = FALSE;
	}

	cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup);

	if (cfg == NULL) {
		fprintf(stderr, "cannot load config '%s': %s\n",
			configfile, err);
		exit(3);
	} else if (checkconfig) {
		confread_free(cfg);
		exit(0);
	}

	if (autoall) {
		if (verbose)
			printf("loading all conns according to their auto= settings\n");


		/*
		 * Load all conns marked as auto=add or better.
		 * First, do the auto=route and auto=add conns to quickly
		 * get routes in place, then do auto=start as these can be
		 * slower.
		 * This mimics behaviour of the old _plutoload
		 */
		if (verbose)
			printf("  Pass #1: Loading auto=add, auto=route and auto=start connections\n");


		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_ADD ||
				conn->desired_state == STARTUP_ONDEMAND ||
				conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				starter_whack_add_conn(cfg, conn);
			}
		}

		/*
		 * We loaded all connections. Now tell pluto to listen,
		 * then route the conns and resolve default route.
		 */
		starter_whack_listen(cfg);

		if (verbose)
			printf("  Pass #2: Routing auto=route and auto=start connections\n");

		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_ADD ||
				conn->desired_state == STARTUP_ONDEMAND ||
				conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				resolve_defaultroute(conn);
				if (conn->desired_state == STARTUP_ONDEMAND ||
				    conn->desired_state == STARTUP_START) {
					starter_whack_route_conn(cfg, conn);
				}
			}
		}

		if (verbose)
			printf("  Pass #3: Initiating auto=start connections\n");

		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next) {
			if (conn->desired_state == STARTUP_START) {
				if (verbose)
					printf(" %s", conn->name);
				starter_whack_initiate_conn(cfg, conn);
			}
		}

		if (verbose)
			printf("\n");
	} else {
		/* load named conns, regardless of their state */
		int connum;

		if (verbose)
			printf("loading named conns:");
		for (connum = optind; connum < argc; connum++) {
			char *connname = argv[connum];

			if (verbose)
				printf(" %s", connname);
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (streq(conn->name, connname)) {
					if (conn->state == STATE_ADDED) {
						printf("\nconn %s already added\n",
							conn->name);
					} else if (conn->state ==
						STATE_FAILED) {
						printf("\nconn %s did not load properly\n",
							conn->name);
					} else {
						resolve_defaultroute(conn);
						exit_status =
							starter_whack_add_conn(
								cfg,
								conn);
						conn->state = STATE_ADDED;
					}
					break;
				}
			}

			if (conn == NULL) {
				/*
				 * only if we don't find it, do we now look
				 * for aliases
				 */
				for (conn = cfg->conns.tqh_first;
					conn != NULL;
					conn = conn->link.tqe_next) {
					if (conn->strings_set[KSF_CONNALIAS] &&
						lsw_alias_cmp(connname,
							conn->
							strings[KSF_CONNALIAS]
							)) {

						if (conn->state ==
							STATE_ADDED) {
							printf("\nalias: %s conn %s already added\n",
								connname,
								conn->name);
						} else if (conn->state ==
							STATE_FAILED) {
							printf("\nalias: %s conn %s did not load properly\n",
								connname,
								conn->name);
						} else {
							resolve_defaultroute(
								conn);
							exit_status =
								starter_whack_add_conn(
									cfg,
									conn);
							conn->state =
								STATE_ADDED;
						}
						break;
					}
				}
			}

			if (conn == NULL) {
				exit_status++;
				if (!verbose) {
					printf("conn '%s': not found (tried aliases)\n",
						connname);
				} else {
					printf(" (notfound)\n");
				}
			}
		}
	}

	if (listall) {
		if (verbose)
			printf("listing all conns\n");
		for (conn = cfg->conns.tqh_first;
			conn != NULL;
			conn = conn->link.tqe_next)
			printf("%s ", conn->name);
		printf("\n");
	} else {

		if (listadd) {
			if (verbose)
				printf("listing all conns marked as auto=add\n");


			/* list all conns marked as auto=add */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_ADD)
					printf("%s ", conn->name);
			}
		}
		if (listroute) {
			if (verbose)
				printf("listing all conns marked as auto=route and auto=start\n");


			/*
			 * list all conns marked as auto=route or start or
			 * better
			 */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_START ||
					conn->desired_state == STARTUP_ONDEMAND)
					printf("%s ", conn->name);
			}
		}

		if (liststart && !listroute) {
			if (verbose)
				printf("listing all conns marked as auto=start\n");


			/* list all conns marked as auto=start */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_START)
					printf("%s ", conn->name);
			}
		}

		if (listignore) {
			if (verbose)
				printf("listing all conns marked as auto=ignore\n");


			/* list all conns marked as auto=start */
			for (conn = cfg->conns.tqh_first;
				conn != NULL;
				conn = conn->link.tqe_next) {
				if (conn->desired_state == STARTUP_IGNORE)
					printf("%s ", conn->name);
			}
			printf("\n");
		}
	}

	if (liststack) {
		const struct keyword_def *kd;

		for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) {
			if (strstr(kd->keyname, "protostack")) {
				if (cfg->setup.strings[kd->field])
					printf("%s\n",
						cfg->setup.strings[kd->field]);
				else
					/* implicit default */
					printf("netkey\n");
			}

		}
		confread_free(cfg);
		exit(0);
	}

	if (configsetup) {
		const struct keyword_def *kd;

		printf("%s %sconfreadstatus=''\n", export, varprefix);
		for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) {
			if ((kd->validity & kv_config) == 0)
				continue;

			switch (kd->type) {
			case kt_string:
			case kt_filename:
			case kt_dirname:
			case kt_loose_enum:
				if (cfg->setup.strings[kd->field]) {
					printf("%s %s%s='%s'\n",
						export, varprefix, kd->keyname,
						cfg->setup.strings[kd->field]);
				}
				break;

			case kt_bool:
				printf("%s %s%s='%s'\n", export, varprefix,
					kd->keyname,
					cfg->setup.options[kd->field] ?
					"yes" : "no");
				break;

			case kt_list:
				printf("%s %s%s='",
					export, varprefix, kd->keyname);
				confwrite_list(stdout, "",
					cfg->setup.options[kd->field],
					kd);
				printf("'\n");
				break;

			case kt_obsolete:
				printf("# obsolete option '%s%s' ignored\n",
					varprefix, kd->keyname);
				break;

			default:
				if (cfg->setup.options[kd->field] ||
					cfg->setup.options_set[kd->field]) {
					printf("%s %s%s='%d'\n",
						export, varprefix, kd->keyname,
						cfg->setup.options[kd->field]);
				}
				break;
			}
		}
예제 #25
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 */
}
예제 #26
0
static int ldap_mapper_match_user(X509 *x509, const char *login, void *context) {
	int match_found = 0;
	int i=0;

	if ( 1 != ldap_get_certificate(login)){
		DBG("ldap_get_certificate() failed");
		match_found = 0;
	} else {
		/* TODO: maybe compare public keys instead of hashes */
		while( i<certcnt && !match_found ) {
#ifdef HAVE_NSS
			if ( x509 == ldap_x509[i]) {
#else
			if ( 0 == X509_cmp(x509, ldap_x509[i])) {
#endif
				DBG1("Certificate %d is matching", i);
				match_found = 1;
			} else {
				DBG1("Certificate %d is NOT matching", i);
			}
			i++;
		}
		if (certcnt)
		{
#ifdef HAVE_NSS
			int rv;

			for (rv=0; rv<certcnt; rv++)
				if (ldap_x509[rv])
					CERT_DestroyCertificate(ldap_x509[rv]);
#endif
			free(ldap_x509);
		}
		certcnt=0;
	}
	return match_found;
}

static char * ldap_mapper_find_user(X509 *x509, void *context, int *match) {
	struct passwd *pw = NULL;
	char *found=NULL;
	setpwent();
	while( (pw=getpwent()) !=NULL) {
	    int res;
	    DBG1("Trying to match certificate with user: '******'",pw->pw_name);
	    res= ldap_mapper_match_user(x509,pw->pw_name,context);
	    if (res) {
		DBG1("Certificate maps to user '%s'",pw->pw_name);
		found= clone_str(pw->pw_name);
		*match = 1;
		break;
	    } else {
		DBG1("Certificate map to user '%s' failed",pw->pw_name);
	    }
	}
	endpwent();

#ifdef false
	int res;
	res= ldap_mapper_match_user(x509,"wefel",context);
	if (res) {
			DBG("Certificate maps to user wefel");
			found= clone_str("wefel");
	} else {
			DBG("Certificate map to user wefel failed");
	}
#endif

	return found;
}

static mapper_module * init_mapper_st(scconf_block *blk, const char *name) {
	mapper_module *pt= malloc(sizeof(mapper_module));
	if (!pt) return NULL;
	pt->name = name;
	pt->block = blk;
	pt->context = NULL;
	pt->entries = ldap_mapper_find_entries;
	pt->finder = ldap_mapper_find_user;
	pt->matcher = ldap_mapper_match_user;
	pt->deinit = mapper_module_end;

	return pt;
}
예제 #27
0
static bool load_conn(struct ub_ctx *dnsctx,
		     struct starter_conn *conn,
		     struct config_parsed *cfgp,
		     struct section_list *sl,
		     bool alsoprocessing,
		     bool defaultconn,
		     bool resolvip,
		     err_t *perr)
{
	bool err = FALSE;

	err |= load_conn_basic(conn, sl,
			       defaultconn ? k_default : k_set, perr);

	move_comment_list(&conn->comments, &sl->comments);

	if (err)
		return err;

	if (conn->strings[KSF_ALSO] != NULL &&
	    !alsoprocessing) {
		starter_log(LOG_LEVEL_INFO,
			    "also= is not valid in section '%s'",
			    sl->name);
		return TRUE;	/* error */
	}

	/* now, process the also's */
	if (conn->alsos)
		FREE_LIST(conn->alsos);
	conn->alsos = new_list(conn->strings[KSF_ALSO]);

	if (alsoprocessing && conn->alsos != NULL) {
		struct section_list *sl1;
		/* note: for the duration of this loop body
		 * conn->alsos is migrated to local variable alsos.
		 */
		char **alsos = conn->alsos;
		int alsosize;
		int alsoplace;

		conn->alsos = NULL;

		/* reset all of the "beenhere" flags */
		for (sl1 = cfgp->sections.tqh_first; sl1 != NULL;
		     sl1 = sl1->link.tqe_next)
			sl1->beenhere = FALSE;
		sl->beenhere = TRUE;

		/* count them */
		for (alsosize = 0; alsos[alsosize] != NULL; alsosize++)
			;

		alsoplace = 0;
		while (alsoplace < alsosize && alsos[alsoplace] != NULL &&
		       alsoplace < ALSO_LIMIT) {
			/*
			 * for each also= listed, go find this section's keyword list, and
			 * load it as well. This may extend the also= list (and the end),
			 * which we handle by zeroing the also list, and adding to it after
			 * checking for duplicates.
			 */
			for (sl1 = cfgp->sections.tqh_first;
			     sl1 != NULL &&
			     !streq(alsos[alsoplace], sl1->name);
			     sl1 = sl1->link.tqe_next)
				;

			starter_log(LOG_LEVEL_DEBUG,
				    "\twhile loading conn '%s' also including '%s'",
				    conn->name, alsos[alsoplace]);

			/*
			 * if we found something that matches by name, and we haven't be
			 * there, then process it.
			 */
			if (sl1 && !sl1->beenhere) {
				conn->strings_set[KSF_ALSO] = FALSE;
				pfreeany(conn->strings[KSF_ALSO]);
				conn->strings[KSF_ALSO] = NULL;
				sl1->beenhere = TRUE;

				/* translate things, but do not replace earlier settings!*/
				err |= translate_conn(conn, sl1, k_set, perr);

				if (conn->strings[KSF_ALSO] != NULL) {
					/* now, check out the KSF_ALSO, and extend list if we need to */
					char **newalsos = new_list(
						conn->strings[KSF_ALSO]);

					if (newalsos != NULL) {
						char **ra;
						int newalsoplace;

						/* count them */
						for (newalsoplace = 0;
						     newalsos[newalsoplace] !=
						     NULL;
						     newalsoplace++)
							;

						/* extend conn->alss */
						ra = alloc_bytes((alsosize +
							newalsoplace + 1) *
							sizeof(char *),
							"conn->alsos");
						memcpy(ra, alsos, alsosize * sizeof(char *));
						pfree(alsos);
						alsos = ra;
						for (newalsoplace = 0;
						     newalsos[newalsoplace] !=
						     NULL;
						     newalsoplace++) {
							assert(conn != NULL);
							assert(conn->name !=
								NULL);
							starter_log(
								LOG_LEVEL_DEBUG,
								"\twhile processing section '%s' added also=%s",
								sl1->name,
								newalsos[newalsoplace]);

							alsos[alsosize++] =
								clone_str(newalsos[newalsoplace],
									"alsos");
						}
						alsos[alsosize] = NULL;
					}

					FREE_LIST(newalsos);
				}
			}
			alsoplace++;
		}

		/* migrate alsos back to conn->alsos */
		conn->alsos = alsos;

		if (alsoplace >= ALSO_LIMIT) {
			starter_log(LOG_LEVEL_INFO,
				    "while loading conn '%s', too many also= used at section %s. Limit is %d",
				    conn->name,
				    alsos[alsoplace],
				    ALSO_LIMIT);
			return TRUE;	/* error */
		}
	}

#ifdef PARSER_TYPE_DEBUG
	/* translate strings/numbers into conn items */
	starter_log(LOG_LEVEL_DEBUG,
		    "#checking options_set[KBF_TYPE,%d]=%d %d",
		    KBF_TYPE,
		    conn->options_set[KBF_TYPE], conn->options[KBF_TYPE]);
#endif

	if (conn->options_set[KBF_TYPE]) {
		switch ((enum keyword_satype)conn->options[KBF_TYPE]) {
		case KS_TUNNEL:
			conn->policy |= POLICY_TUNNEL;
			conn->policy &= ~POLICY_SHUNT_MASK;
			break;

		case KS_TRANSPORT:
			conn->policy &= ~POLICY_TUNNEL;
			conn->policy &= ~POLICY_SHUNT_MASK;
			break;

		case KS_PASSTHROUGH:
			conn->policy &=
				~(POLICY_ENCRYPT | POLICY_AUTHENTICATE |
				  POLICY_TUNNEL | POLICY_RSASIG);
			conn->policy &= ~POLICY_SHUNT_MASK;
			conn->policy |= POLICY_SHUNT_PASS;
			break;

		case KS_DROP:
			conn->policy &=
				~(POLICY_ENCRYPT | POLICY_AUTHENTICATE |
				  POLICY_TUNNEL | POLICY_RSASIG);
			conn->policy &= ~POLICY_SHUNT_MASK;
			conn->policy |= POLICY_SHUNT_DROP;
			break;

		case KS_REJECT:
			conn->policy &=
				~(POLICY_ENCRYPT | POLICY_AUTHENTICATE |
				  POLICY_TUNNEL | POLICY_RSASIG);
			conn->policy &= ~POLICY_SHUNT_MASK;
			conn->policy |= POLICY_SHUNT_REJECT;
			break;
		}
	}

	if (conn->options_set[KBF_FAILURESHUNT]) {
		conn->policy &= ~POLICY_FAIL_MASK;
		switch(conn->options[KBF_FAILURESHUNT]) {
		case KFS_FAIL_NONE:
			conn->policy |= POLICY_FAIL_NONE;
			break;
		case KFS_FAIL_PASS:
			conn->policy |= POLICY_FAIL_PASS;
			break;
		case KFS_FAIL_DROP:
			conn->policy |= POLICY_FAIL_DROP;
			break;
		case KFS_FAIL_REJECT:
			conn->policy |= POLICY_FAIL_REJECT;
			break;
		}
	}

	if (conn->options_set[KBF_NEGOTIATIONSHUNT]) {
		switch(conn->options[KBF_NEGOTIATIONSHUNT]) {
		case KNS_FAIL_PASS:
			conn->policy |= POLICY_NEGO_PASS;
			break;
		case KNS_FAIL_DROP:
			conn->policy &= ~POLICY_NEGO_PASS;
			break;
		}
	}

	KW_POLICY_FLAG(KBF_COMPRESS, POLICY_COMPRESS);
	KW_POLICY_FLAG(KBF_PFS,  POLICY_PFS);

	/* reset authby flags */
	if (conn->options_set[KBF_AUTHBY]) {
		conn->policy &= ~(POLICY_ID_AUTH_MASK);

#ifdef FIPS_CHECK
		if (libreswan_fipsmode()) {
			if (LIN(POLICY_PSK, conn->options[KBF_AUTHBY])) {
				starter_log(LOG_LEVEL_INFO,
					    "while loading conn '%s', PSK not allowed in FIPS mode with NSS",
					    conn->name);
				return TRUE;	/* error */
			}
		}
#endif

		conn->policy |= conn->options[KBF_AUTHBY];

#ifdef STARTER_POLICY_DEBUG
		starter_log(LOG_LEVEL_DEBUG,
			    "%s: setting conn->policy=%08x (%08x)",
			    conn->name,
			    (unsigned int)conn->policy,
			    conn->options[KBF_AUTHBY]);
#endif
	}

	KW_POLICY_NEGATIVE_FLAG(KBF_IKEPAD, POLICY_NO_IKEPAD);

	KW_POLICY_NEGATIVE_FLAG(KBF_REKEY, POLICY_DONT_REKEY);

	KW_POLICY_FLAG(KBF_AGGRMODE, POLICY_AGGRESSIVE);

	KW_POLICY_FLAG(KBF_MODECONFIGPULL, POLICY_MODECFG_PULL);

	KW_POLICY_FLAG(KBF_OVERLAPIP, POLICY_OVERLAPIP);

	KW_POLICY_FLAG(KBF_IKEv2_ALLOW_NARROWING,
		       POLICY_IKEV2_ALLOW_NARROWING);

	KW_POLICY_FLAG(KBF_IKEv2_PAM_AUTHORIZE,
		       POLICY_IKEV2_PAM_AUTHORIZE);

	if (conn->strings_set[KSF_ESP])
		conn->esp = clone_str(conn->strings[KSF_ESP],"KSF_ESP");

#ifdef HAVE_LABELED_IPSEC
	if (conn->strings_set[KSF_POLICY_LABEL])
		conn->policy_label = clone_str(conn->strings[KSF_POLICY_LABEL],"KSF_POLICY_LABEL");
	if (conn->policy_label != NULL)
		starter_log(LOG_LEVEL_DEBUG, "connection's  policy label: %s",
				conn->policy_label);
#endif

	if (conn->strings_set[KSF_IKE])
		conn->ike = clone_str(conn->strings[KSF_IKE],"KSF_IKE");

	if (conn->strings_set[KSF_MODECFGDNS1]) {
		conn->modecfg_dns1 = clone_str(conn->strings[KSF_MODECFGDNS1],"KSF_MODECFGDNS1");
	}
	if (conn->strings_set[KSF_MODECFGDNS2]) {
		conn->modecfg_dns2 = clone_str(conn->strings[KSF_MODECFGDNS2], "KSF_MODECFGDNS2");
	}
	if (conn->strings_set[KSF_MODECFGDOMAIN]) {
		conn->modecfg_domain = clone_str(conn->strings[KSF_MODECFGDOMAIN],"KSF_MODECFGDOMAIN");
	}
	if (conn->strings_set[KSF_MODECFGBANNER]) {
		conn->modecfg_banner = clone_str(conn->strings[KSF_MODECFGBANNER],"KSF_MODECFGBANNER");
	}

	if (conn->strings_set[KSF_CONNALIAS])
		conn->connalias = clone_str(conn->strings[KSF_CONNALIAS],"KSF_CONNALIAS");

	if (conn->options_set[KBF_PHASE2]) {
		conn->policy &= ~(POLICY_AUTHENTICATE | POLICY_ENCRYPT);
		conn->policy |= conn->options[KBF_PHASE2];
	}

	if (conn->options_set[KBF_IKEv2]) {
		lset_t policy = LEMPTY;

		switch (conn->options[KBF_IKEv2]) {
		case fo_never:
			policy = POLICY_IKEV1_ALLOW;
			break;

		case fo_permit:
			/* this is the default for now */
			policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW;
			break;

		case fo_propose:
			policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE;
			break;

		case fo_insist:
			policy =                      POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE;
			break;
		}
		conn->policy = (conn->policy & ~POLICY_IKEV2_MASK) | policy;
	}

	if (conn->options_set[KBF_IKE_FRAG]) {
		switch (conn->options[KBF_IKE_FRAG]) {
		case ynf_no:
			conn->policy &= ~POLICY_IKE_FRAG_ALLOW;
			conn->policy &= ~POLICY_IKE_FRAG_FORCE;
			break;

		case ynf_yes:
			/* this is the default */
			conn->policy |= POLICY_IKE_FRAG_ALLOW;
			break;

		case ynf_force:
			conn->policy |= POLICY_IKE_FRAG_ALLOW |
					POLICY_IKE_FRAG_FORCE;
			break;
		}
	}

	if (conn->options_set[KBF_SAREFTRACK]) {
		switch (conn->options[KBF_SAREFTRACK]) {
		case sat_yes:
			/* this is the default */
			conn->policy |= POLICY_SAREF_TRACK;
			break;

		case sat_conntrack:
			conn->policy |= POLICY_SAREF_TRACK |
					POLICY_SAREF_TRACK_CONNTRACK;
			break;

		case sat_no:
			conn->policy &= ~POLICY_SAREF_TRACK;
			conn->policy &= ~POLICY_SAREF_TRACK_CONNTRACK;
			break;
		}
	}

	err |= validate_end(dnsctx, conn, &conn->left,  "left",  resolvip, perr);
	err |= validate_end(dnsctx, conn, &conn->right, "right", resolvip, perr);
	/*
	 * TODO:
	 * verify both ends are using the same inet family, if one end
	 * is "%any" or "%defaultroute", then perhaps adjust it.
	 * ensource this for left,leftnexthop,right,rightnexthop
	 * Ideally, phase out connaddrfamily= which now wrongly assumes
	 * left,leftnextop,leftsubnet are the same inet family
	 * Currently, these tests are implicitely done, and wrongly
	 * in case of 6in4 and 4in6 tunnels
	 */

	if (conn->options_set[KBF_AUTO])
		conn->desired_state = conn->options[KBF_AUTO];

	return err;
}
예제 #28
0
/**
 * Set up hardcoded defaults, from data in programs/pluto/constants.h
 *
 * @param cfg starter_config struct
 * @return void
 */
void ipsecconf_default_values(struct starter_config *cfg)
{
	zero(cfg);	/* ??? pointer fields might not be NULLed */

	TAILQ_INIT(&cfg->conns);

	/* config setup */
	cfg->setup.options[KBF_FRAGICMP] = FALSE; /* see sysctl_ipsec_icmp in ipsec_proc.c */
	cfg->setup.options[KBF_HIDETOS]  = TRUE;
	cfg->setup.options[KBF_PLUTORESTARTONCRASH]  = TRUE;
	cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]  = TRUE;
	cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND]  = TRUE;
	cfg->setup.options[KBF_UNIQUEIDS] = TRUE;
	cfg->setup.options[KBF_PERPEERLOG] = FALSE;
	cfg->setup.options[KBF_IKEPORT] = IKE_UDP_PORT;
	cfg->setup.options[KBF_NFLOG_ALL] = 0; /* disabled per default */
	cfg->setup.options[KBF_XFRMLIFETIME] = 300; /* not used by pluto itself */
	cfg->setup.options[KBF_NHELPERS] = -1; /* see also plutomain.c */

	cfg->setup.options[KBF_KEEPALIVE] = 0;                  /* config setup */
	cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT;
	cfg->setup.options[KBF_DDOS_IKE_TRESHOLD] = DEFAULT_IKE_SA_DDOS_TRESHOLD;
	cfg->setup.options[KBF_MAX_HALFOPEN_IKE] = DEFAULT_MAXIMUM_HALFOPEN_IKE_SA;
	cfg->setup.options[KBF_SHUNTLIFETIME] = PLUTO_SHUNT_LIFE_DURATION_DEFAULT;
	/* Don't inflict BSI requirements on everyone */
	cfg->setup.options[KBF_SEEDBITS] = 0;

#ifdef HAVE_LABELED_IPSEC
	cfg->setup.options[KBF_SECCTX] = SECCTX;
#endif
	cfg->setup.options[KBF_DDOS_MODE] = DDOS_AUTO;

	/* conn %default */
	cfg->conn_default.options[KBF_NAT_KEEPALIVE] = TRUE;    /* per conn */
	cfg->conn_default.options[KBF_TYPE] = KS_TUNNEL;

	cfg->conn_default.options[KBF_INITIAL_CONTACT] = FALSE;
	cfg->conn_default.options[KBF_CISCO_UNITY] = FALSE;
	cfg->conn_default.options[KBF_SEND_VENDORID] = FALSE;

	cfg->conn_default.options[KBF_REMOTEPEERTYPE] = NON_CISCO;

	cfg->conn_default.options[KBF_SHA2_TRUNCBUG] = FALSE;

	cfg->conn_default.options[KBF_IKEPAD] = TRUE;

	cfg->conn_default.options[KBF_IKEV1_NATT] = natt_both;

	/* Network Manager support */
#ifdef HAVE_NM
	cfg->conn_default.options[KBF_NMCONFIGURED] = FALSE;
#endif

#ifdef HAVE_LABELED_IPSEC
	cfg->conn_default.options[KBF_LABELED_IPSEC] = FALSE;
#endif

	cfg->conn_default.options[KBF_XAUTHBY] = XAUTHBY_FILE;
	cfg->conn_default.options[KBF_XAUTHFAIL] = XAUTHFAIL_HARD;

	cfg->conn_default.policy = POLICY_RSASIG | POLICY_TUNNEL |
				   POLICY_ENCRYPT | POLICY_PFS;
	cfg->conn_default.policy |= POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW;	/* ikev2=permit */
	cfg->conn_default.policy |= POLICY_SAREF_TRACK;         /* sareftrack=yes */
	cfg->conn_default.policy |= POLICY_IKE_FRAG_ALLOW;      /* ike_frag=yes */

	cfg->conn_default.options[KBF_IKELIFETIME] =
		OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;

	cfg->conn_default.options[KBF_RETRANSMIT_TIMEOUT] = RETRANSMIT_TIMEOUT_DEFAULT;
	cfg->conn_default.options[KBF_RETRANSMIT_INTERVAL] = RETRANSMIT_INTERVAL_DEFAULT;

	cfg->conn_default.options[KBF_SALIFETIME]  = SA_LIFE_DURATION_DEFAULT;
	cfg->conn_default.options[KBF_REKEYMARGIN] =
		SA_REPLACEMENT_MARGIN_DEFAULT;
	cfg->conn_default.options[KBF_REKEYFUZZ]   =
		SA_REPLACEMENT_FUZZ_DEFAULT;
	cfg->conn_default.options[KBF_KEYINGTRIES] =
		SA_REPLACEMENT_RETRIES_DEFAULT;

	/* now here is a sticker.. we want it on. But pluto has to be smarter first */
	cfg->conn_default.options[KBF_OPPOENCRYPT] = FALSE;

	cfg->conn_default.options[KBF_CONNADDRFAMILY] = AF_INET;

	cfg->conn_default.left.addr_family = AF_INET;
	anyaddr(AF_INET, &cfg->conn_default.left.addr);
	cfg->conn_default.left.nexttype  = KH_NOTSET;
	anyaddr(AF_INET, &cfg->conn_default.left.nexthop);

	cfg->conn_default.right.addr_family = AF_INET;
	anyaddr(AF_INET, &cfg->conn_default.right.addr);
	cfg->conn_default.right.nexttype = KH_NOTSET;
	anyaddr(AF_INET, &cfg->conn_default.right.nexthop);

	/* default is NOT to look in DNS */
	cfg->conn_default.left.key_from_DNS_on_demand = FALSE;
	cfg->conn_default.right.key_from_DNS_on_demand = FALSE;

	cfg->conn_default.options[KBF_AUTO] = STARTUP_IGNORE;
	cfg->conn_default.state = STATE_LOADED;

	cfg->ctlbase = clone_str(CTL_FILE, "default base");
}
예제 #29
0
/**
 * Take keywords from ipsec.conf syntax and load into a conn struct
 *
 *
 * @param conn a connection definition
 * @param sl a section_list
 * @param assigned_value is set to either k_set, or k_default.
 *        k_default is used when we are loading a conn that should be
 *        considered to be a "default" value, and that replacing this
 *        value is considered acceptable.
 * @return bool TRUE if unsuccessfull
 */
static bool translate_conn(struct starter_conn *conn,
		    struct section_list *sl,
		    enum keyword_set assigned_value,
		    err_t *error)
{
	bool err = FALSE;
	struct kw_list *kw;

	for (kw = sl->kw; kw; kw = kw->next) {
		ksf *the_strings = &conn->strings;
		str_set *set_strings = &conn->strings_set;
		knf *the_options = &conn->options;
		int_set *set_options = &conn->options_set;
		unsigned int field;

		if ((kw->keyword.keydef->validity & kv_conn) == 0) {
			/* this isn't valid in a conn! */
			*error = (const char *)tmp_err;

			snprintf(tmp_err, sizeof(tmp_err),
				 "keyword '%s' is not valid in a conn (%s)\n",
				 kw->keyword.keydef->keyname, sl->name);
			starter_log(LOG_LEVEL_INFO, "%s", tmp_err);
			continue;
		}

		if (kw->keyword.keydef->validity & kv_leftright) {
			if (kw->keyword.keyleft) {
				the_strings = &conn->left.strings;
				the_options = &conn->left.options;
				set_strings = &conn->left.strings_set;
				set_options = &conn->left.options_set;
			} else {
				the_strings = &conn->right.strings;
				the_options = &conn->right.options;
				set_strings = &conn->right.strings_set;
				set_options = &conn->right.options_set;
			}
		}

		field = kw->keyword.keydef->field;

#ifdef PARSER_TYPE_DEBUG
		starter_log(LOG_LEVEL_DEBUG, "#analyzing %s[%d] kwtype=%d",
			    kw->keyword.keydef->keyname, field,
			    kw->keyword.keydef->type);
#endif

		assert(kw->keyword.keydef != NULL);
		switch (kw->keyword.keydef->type) {
		case kt_string:
		case kt_filename:
		case kt_dirname:
		case kt_bitstring:
		case kt_ipaddr:
		case kt_range:
		case kt_subnet:
		case kt_idtype:
			/* all treated as strings for now */
			assert(kw->keyword.keydef->field < KEY_STRINGS_MAX);
			if ((*set_strings)[field] == k_set) {
				*error = tmp_err;

				snprintf(tmp_err, sizeof(tmp_err),
					 "duplicate key '%s' in conn %s while processing def %s",
					 kw->keyword.keydef->keyname,
					 conn->name,
					 sl->name);

				starter_log(LOG_LEVEL_INFO, "%s", tmp_err);
				if (kw->keyword.string == NULL ||
				    (*the_strings)[field] == NULL ||
				    !streq(kw->keyword.string,
					   (*the_strings)[field])) {
					err = TRUE;
					break;
				}
			}
			pfreeany((*the_strings)[field]);

			if (kw->string == NULL) {
				*error = tmp_err;

				snprintf(tmp_err, sizeof(tmp_err),
					 "Invalid %s value",
					 kw->keyword.keydef->keyname);
				err = TRUE;
				break;
			}

			(*the_strings)[field] = clone_str(kw->string,"kt_idtype kw->string");
			(*set_strings)[field] = assigned_value;
			break;

		case kt_appendstring:
		case kt_appendlist:
			/* implicitly, this field can have multiple values */
			assert(kw->keyword.keydef->field < KEY_STRINGS_MAX);
			if ((*the_strings)[field] == NULL) {
				(*the_strings)[field] = clone_str(kw->string, "kt_appendlist kw->string");
			} else {
				char *s = (*the_strings)[field];
				size_t old_len = strlen(s);	/* excludes '\0' */
				size_t new_len = strlen(kw->string);
				char *n;

				n = alloc_bytes(old_len + 1 + new_len + 1, "kt_appendlist");
				memcpy(n, s, old_len);
				n[old_len] = ' ';
				memcpy(n + old_len + 1, kw->string, new_len + 1);	/* includes '\0' */
				(*the_strings)[field] = n;
				pfree(s);
			}
			(*set_strings)[field] = TRUE;
			break;

		case kt_rsakey:
		case kt_loose_enum:
			assert(field < KEY_STRINGS_MAX);
			assert(field < KEY_NUMERIC_MAX);

			if ((*set_options)[field] == k_set) {
				*error = tmp_err;
				snprintf(tmp_err, sizeof(tmp_err),
					 "duplicate key '%s' in conn %s while processing def %s",
					 kw->keyword.keydef->keyname,
					 conn->name,
					 sl->name);

				starter_log(LOG_LEVEL_INFO, "%s", tmp_err);

				/* only fatal if we try to change values */
				if ((*the_options)[field] != (int)kw->number ||
				    !((*the_options)[field] ==
				      LOOSE_ENUM_OTHER &&
				      kw->number == LOOSE_ENUM_OTHER &&
				      kw->keyword.string != NULL &&
				      (*the_strings)[field] != NULL &&
				      streq(kw->keyword.string,
					     (*the_strings)[field]))) {
					err = TRUE;
					break;
				}
			}

			(*the_options)[field] = kw->number;
			if (kw->number == LOOSE_ENUM_OTHER) {
				assert(kw->keyword.string != NULL);
				pfreeany((*the_strings)[field]);
				(*the_strings)[field] = clone_str(
					kw->keyword.string, "kt_loose_enum kw->keyword.string");
			}
			(*set_options)[field] = assigned_value;
			break;

		case kt_list:
		case kt_bool:
		case kt_invertbool:
		case kt_enum:
		case kt_number:
		case kt_time:
		case kt_percent:
			/* all treated as a number for now */
			assert(field < KEY_NUMERIC_MAX);

			if ((*set_options)[field] == k_set) {
				*error = tmp_err;
				snprintf(tmp_err, sizeof(tmp_err),
					 "duplicate key '%s' in conn %s while processing def %s",
					 kw->keyword.keydef->keyname,
					 conn->name,
					 sl->name);
				starter_log(LOG_LEVEL_INFO, "%s", tmp_err);
				if ((*the_options)[field] != (int)kw->number) {
					err = TRUE;
					break;
				}
			}

#if 0
			starter_log(LOG_LEVEL_DEBUG, "#setting %s[%d]=%u",
				    kw->keyword.keydef->keyname, field,
				    kw->number);
#endif
			(*the_options)[field] = kw->number;
			(*set_options)[field] = assigned_value;
			break;

		case kt_comment:
			break;
		case kt_obsolete:
			starter_log(LOG_LEVEL_INFO,
				    "Warning: obsolete keyword '%s' ignored",
				    kw->keyword.keydef->keyname);
			break;
		case kt_obsolete_quiet:
			starter_log(LOG_LEVEL_DEBUG,
				    "Warning: obsolete keyword '%s' ignored",
				    kw->keyword.keydef->keyname);
			break;
		}
	}
	return err;
}
예제 #30
0
static bool validate_end(struct ub_ctx *dnsctx ,
#endif
			struct starter_conn *conn_st,
			struct starter_end *end,
			const char *leftright,
			bool resolvip UNUSED,
			err_t *perr)
{
	err_t er = NULL;
	char *err_str = NULL;
	int family = conn_st->options[KBF_CONNADDRFAMILY];
	bool err = FALSE;

#  define ERR_FOUND(...) { err |= error_append(&err_str, __VA_ARGS__); }

	if (!end->options_set[KNCF_IP])
		conn_st->state = STATE_INCOMPLETE;

	end->addrtype = end->options[KNCF_IP];
	end->addr_family = family;

	/* validate the KSCF_IP/KNCF_IP */
	switch (end->addrtype) {
	case KH_ANY:
		anyaddr(family, &(end->addr));
		break;

	case KH_IFACE:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright);
		break;

	case KH_IPADDR:
		assert(end->strings[KSCF_IP] != NULL);

		if (end->strings[KSCF_IP][0] == '%') {
			pfree(end->iface);
			end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface");
			if (!starter_iface_find(end->iface, family,
					       &end->addr,
					       &end->nexthop))
				conn_st->state = STATE_INVALID;
			/* not numeric, so set the type to the iface type */
			end->addrtype = KH_IFACE;
			break;
		}

		er = ttoaddr_num(end->strings[KNCF_IP], 0, family,
				    &(end->addr));
		if (er != NULL) {
			/* not numeric, so set the type to the string type */
			end->addrtype = KH_IPHOSTNAME;
		}

		if (end->id == NULL) {
			ipstr_buf b;

			end->id = clone_str(ipstr(&end->addr, &b), "end if");
		}
		break;

	case KH_OPPO:
		conn_st->policy |= POLICY_OPPORTUNISTIC;
		break;

	case KH_OPPOGROUP:
		conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP;
		break;

	case KH_GROUP:
		conn_st->policy |= POLICY_GROUP;
		break;

	case KH_IPHOSTNAME:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_IPHOSTNAME", leftright);
		break;

	case KH_DEFAULTROUTE:
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_DEFAULTROUTE", leftright);
		break;

	case KH_NOTSET:
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright);
		break;
	}

	/* validate the KSCF_SUBNET */
	if (end->strings_set[KSCF_SUBNET]) {
		char *value = end->strings[KSCF_SUBNET];

		if (end->strings_set[KSCF_ADDRESSPOOL]) {
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright,
				leftright);
		}

		if (startswith(value, "vhost:") || startswith(value, "vnet:")) {
			er = NULL;
			end->virt = clone_str(value, "validate_end item");
		} else {
			end->has_client = TRUE;
			er = ttosubnet(value, 0, family, &(end->subnet));
		}
		if (er != NULL)
			ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright,
				  value, er);
	}

	/* set nexthop address to something consistent, by default */
	anyaddr(family, &end->nexthop);
	anyaddr(addrtypeof(&end->addr), &end->nexthop);

	/* validate the KSCF_NEXTHOP */
	if (end->strings_set[KSCF_NEXTHOP]) {
		char *value = end->strings[KSCF_NEXTHOP];

		if (strcaseeq(value, "%defaultroute")) {
			end->nexttype = KH_DEFAULTROUTE;
		} else {
			if (tnatoaddr(value, strlen(value), AF_INET,
				      &(end->nexthop)) != NULL &&
			    tnatoaddr(value, strlen(value), AF_INET6,
				      &(end->nexthop)) != NULL) {
#ifdef DNSSEC
				starter_log(LOG_LEVEL_DEBUG,
					    "Calling unbound_resolve() for %snexthop value",
					    leftright);
				if (!unbound_resolve(dnsctx, value,
						strlen(value), AF_INET,
						&(end->nexthop)) &&
				    !unbound_resolve(dnsctx, value,
						strlen(value), AF_INET6,
						&(end->nexthop)))
					ERR_FOUND("bad value for %snexthop=%s\n",
						leftright, value);
#else
				er = ttoaddr(value, 0, family,
						&(end->nexthop));
				if (er != NULL)
					ERR_FOUND("bad value for %snexthop=%s [%s]",
						leftright, value,
						er);
#endif
			}
			end->nexttype = KH_IPADDR;
		}
	} else {
#if 0
		if (conn_st->policy & POLICY_OPPORTUNISTIC)
			end->nexttype = KH_DEFAULTROUTE;
#endif
		anyaddr(family, &end->nexthop);

		if (end->addrtype == KH_DEFAULTROUTE) {
			end->nexttype = KH_DEFAULTROUTE;
		}
	}

	/* validate the KSCF_ID */
	if (end->strings_set[KSCF_ID]) {
		char *value = end->strings[KSCF_ID];

		pfreeany(end->id);
		end->id = clone_str(value, "end->id");
	}

	if (end->options_set[KSCF_RSAKEY1]) {
		end->rsakey1_type = end->options[KSCF_RSAKEY1];
		end->rsakey2_type = end->options[KSCF_RSAKEY2];

		switch (end->options[KSCF_RSAKEY1]) {
		case PUBKEY_DNS:
		case PUBKEY_DNSONDEMAND:
			end->key_from_DNS_on_demand = TRUE;
			break;

		default:
			end->key_from_DNS_on_demand = FALSE;
			/* validate the KSCF_RSAKEY1/RSAKEY2 */
			if (end->strings[KSCF_RSAKEY1] != NULL) {
				char *value = end->strings[KSCF_RSAKEY1];

				pfreeany(end->rsakey1);
				end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1");
			}
			if (end->strings[KSCF_RSAKEY2] != NULL) {
				char *value = end->strings[KSCF_RSAKEY2];

				pfreeany(end->rsakey2);
				end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2");
			}
		}
	}

	/* validate the KSCF_SOURCEIP, if any, and if set,
	 * set the subnet to same value, if not set.
	 */
	if (end->strings_set[KSCF_SOURCEIP]) {
		char *value = end->strings[KSCF_SOURCEIP];

		if (tnatoaddr(value, strlen(value), AF_INET,
			      &(end->sourceip)) != NULL &&
		    tnatoaddr(value, strlen(value), AF_INET6,
			      &(end->sourceip)) != NULL) {
#ifdef DNSSEC
			starter_log(LOG_LEVEL_DEBUG,
				    "Calling unbound_resolve() for %ssourceip value",
				    leftright);
			if (!unbound_resolve(dnsctx, value,
					strlen(value), AF_INET,
					&(end->sourceip)) &&
			    !unbound_resolve(dnsctx, value,
					strlen(value), AF_INET6,
					&(end->sourceip)))
				ERR_FOUND("bad value for %ssourceip=%s\n",
					  leftright, value);
#else
			er = ttoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad addr %ssourceip=%s [%s]",
					  leftright, value, er);
#endif
		} else {
			er = tnatoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad numerical addr %ssourceip=%s [%s]",
					leftright, value, er);
		}
		if (!end->has_client) {
			starter_log(LOG_LEVEL_INFO,
				    "%ssourceip= used but not %ssubnet= defined, defaulting %ssubnet to %s",
				    leftright, leftright, leftright, value);
			er = addrtosubnet(&end->sourceip, &end->subnet);
			if (er != NULL) {
				ERR_FOUND("attempt to default %ssubnet from %s failed: %s",
					leftright, value, er);
			}
			end->has_client = TRUE;
			end->has_client_wildcard = FALSE;
		}
	}

	/* copy certificate path name */
	if (end->strings_set[KSCF_CERT])
		end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT");

	if (end->strings_set[KSCF_CA])
		end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA");

	if (end->strings_set[KSCF_UPDOWN])
		end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN");

	if (end->strings_set[KSCF_PROTOPORT]) {
		err_t ugh;
		char *value = end->strings[KSCF_PROTOPORT];

		ugh = ttoprotoport(value, 0, &end->protocol, &end->port,
				   &end->has_port_wildcard);

		if (ugh != NULL)
			ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value,
				  ugh);
	}

	if (end->strings_set[KSCF_ADDRESSPOOL]) {
		char *addresspool = end->strings[KSCF_ADDRESSPOOL];

		if (end->strings_set[KSCF_SUBNET])
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=",
				leftright, leftright);
		starter_log(LOG_LEVEL_DEBUG,
			    "connection's  %saddresspool set to: %s",
			    leftright, end->strings[KSCF_ADDRESSPOOL] );

		er = ttorange(addresspool, 0, AF_INET, &end->pool_range, TRUE);
		if (er != NULL)
			ERR_FOUND("bad %saddresspool=%s [%s]", leftright,
					addresspool, er);
	}

	if (end->options_set[KNCF_XAUTHSERVER] ||
	    end->options_set[KNCF_XAUTHCLIENT])
		conn_st->policy |= POLICY_XAUTH;

	/*
	   KSCF_SUBNETWITHIN    --- not sure what to do with it.
	   KSCF_ESPENCKEY       --- todo (manual keying)
	   KSCF_ESPAUTHKEY      --- todo (manual keying)
	   KSCF_SOURCEIP     = 16,
	   KSCF_MAX          = 19
	 */

	if (err)
		*perr = err_str;
	return err;
#  undef ERR_FOUND
}