aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/plugins/stroke
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/plugins/stroke')
-rw-r--r--src/charon/plugins/stroke/stroke_attribute.c4
-rw-r--r--src/charon/plugins/stroke/stroke_config.c696
-rw-r--r--src/charon/plugins/stroke/stroke_cred.c25
-rw-r--r--src/charon/plugins/stroke/stroke_list.c263
-rw-r--r--src/charon/plugins/stroke/stroke_socket.c10
5 files changed, 494 insertions, 504 deletions
diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c
index f850b5320..0ebc367fa 100644
--- a/src/charon/plugins/stroke/stroke_attribute.c
+++ b/src/charon/plugins/stroke/stroke_attribute.c
@@ -191,7 +191,7 @@ int host2offset(pool_t *pool, host_t *addr)
*/
static host_t* acquire_address(private_stroke_attribute_t *this,
char *name, identification_t *id,
- auth_info_t *auth, host_t *requested)
+ host_t *requested)
{
pool_t *pool;
uintptr_t offset = 0;
@@ -530,7 +530,7 @@ stroke_attribute_t *stroke_attribute_create()
{
private_stroke_attribute_t *this = malloc_thing(private_stroke_attribute_t);
- this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address;
+ this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool;
this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool;
diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c
index 59c58ca0d..4a0b1ff42 100644
--- a/src/charon/plugins/stroke/stroke_config.c
+++ b/src/charon/plugins/stroke/stroke_config.c
@@ -55,90 +55,21 @@ struct private_stroke_config_t {
};
/**
- * data to pass peer_filter
- */
-typedef struct {
- private_stroke_config_t *this;
- identification_t *me;
- identification_t *other;
-} peer_data_t;
-
-/**
- * destroy id enumerator data and unlock list
- */
-static void peer_data_destroy(peer_data_t *data)
-{
- data->this->mutex->unlock(data->this->mutex);
- free(data);
-}
-
-/**
- * filter function for peer configs
- */
-static bool peer_filter(peer_data_t *data, peer_cfg_t **in, peer_cfg_t **out)
-{
- bool match_me = FALSE, match_other = FALSE;
- identification_t *me, *other;
-
- me = (*in)->get_my_id(*in);
- other = (*in)->get_other_id(*in);
-
- /* own ID may have wildcards in data (no IDr payload) or in config */
- match_me = (!data->me || data->me->matches(data->me, me) ||
- me->matches(me, data->me));
- /* others ID has wildcards in config only */
- match_other = (!data->other || data->other->matches(data->other, other));
-
- if (match_me && match_other)
- {
- *out = *in;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
* Implementation of backend_t.create_peer_cfg_enumerator.
*/
static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this,
identification_t *me,
identification_t *other)
{
- peer_data_t *data;
-
- data = malloc_thing(peer_data_t);
- data->this = this;
- data->me = me;
- data->other = other;
-
this->mutex->lock(this->mutex);
- return enumerator_create_filter(this->list->create_enumerator(this->list),
- (void*)peer_filter, data,
- (void*)peer_data_destroy);
-}
-
-/**
- * data to pass ike_filter
- */
-typedef struct {
- private_stroke_config_t *this;
- host_t *me;
- host_t *other;
-} ike_data_t;
-
-/**
- * destroy id enumerator data and unlock list
- */
-static void ike_data_destroy(ike_data_t *data)
-{
- data->this->mutex->unlock(data->this->mutex);
- free(data);
+ return enumerator_create_cleaner(this->list->create_enumerator(this->list),
+ (void*)this->mutex->unlock, this->mutex);
}
/**
* filter function for ike configs
*/
-static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
+static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
{
*out = (*in)->get_ike_cfg(*in);
return TRUE;
@@ -150,17 +81,10 @@ static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this,
host_t *me, host_t *other)
{
- ike_data_t *data;
-
- data = malloc_thing(ike_data_t);
- data->this = this;
- data->me = me;
- data->other = other;
-
this->mutex->lock(this->mutex);
return enumerator_create_filter(this->list->create_enumerator(this->list),
- (void*)ike_filter, data,
- (void*)ike_data_destroy);
+ (void*)ike_filter, this->mutex,
+ (void*)this->mutex->unlock);
}
/**
@@ -171,34 +95,34 @@ static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *nam
enumerator_t *e1, *e2;
peer_cfg_t *current, *found = NULL;
child_cfg_t *child;
-
+
this->mutex->lock(this->mutex);
e1 = this->list->create_enumerator(this->list);
while (e1->enumerate(e1, &current))
{
- /* compare peer_cfgs name first */
- if (streq(current->get_name(current), name))
- {
- found = current;
- found->get_ref(found);
- break;
- }
- /* compare all child_cfg names otherwise */
- e2 = current->create_child_cfg_enumerator(current);
- while (e2->enumerate(e2, &child))
- {
- if (streq(child->get_name(child), name))
- {
- found = current;
- found->get_ref(found);
- break;
- }
- }
- e2->destroy(e2);
- if (found)
- {
- break;
- }
+ /* compare peer_cfgs name first */
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ /* compare all child_cfg names otherwise */
+ e2 = current->create_child_cfg_enumerator(current);
+ while (e2->enumerate(e2, &child))
+ {
+ if (streq(child->get_name(child), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (found)
+ {
+ break;
+ }
}
e1->destroy(e1);
this->mutex->unlock(this->mutex);
@@ -206,22 +130,6 @@ static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *nam
}
/**
- * check if a certificate has an ID
- */
-static identification_t *update_peerid(certificate_t *cert, identification_t *id)
-{
- if (id->get_type(id) == ID_ANY || !cert->has_subject(cert, id))
- {
- DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
- "defaulting to subject DN", id);
- id->destroy(id);
- id = cert->get_subject(cert);
- return id->clone(id);
- }
- return id;
-}
-
-/**
* parse a proposal string, either into ike_cfg or child_cfg
*/
static void add_proposals(private_stroke_config_t *this, char *string,
@@ -332,45 +240,303 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
+
/**
- * build a peer_cfg from a stroke msg
+ * Add CRL constraint to config
*/
-static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
- stroke_msg_t *msg, ike_cfg_t *ike_cfg,
- identification_t **my_issuer,
- identification_t **other_issuer)
+static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
{
- identification_t *me, *other, *peer_id = NULL;
- peer_cfg_t *mediated_by = NULL;
- host_t *vip = NULL;
- certificate_t *cert;
- unique_policy_t unique;
- u_int32_t rekey = 0, reauth = 0, over, jitter;
+ /* CRL/OCSP policy, for remote config only */
+ if (!local)
+ {
+ switch (policy)
+ {
+ case CRL_STRICT_YES:
+ /* if yes, we require a GOOD validation */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ break;
+ case CRL_STRICT_IFURI:
+ /* for ifuri, a SKIPPED validation is sufficient */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * build authentication config
+ */
+static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg, bool local, bool primary)
+{
+ identification_t *identity;
+ certificate_t *certificate;
+ char *auth, *id, *cert, *ca;
+ stroke_end_t *end, *other_end;
+ auth_cfg_t *cfg;
+ char eap_buf[32];
- me = identification_create_from_string(msg->add_conn.me.id ?
- msg->add_conn.me.id : msg->add_conn.me.address);
- if (!me)
+ /* select strings */
+ if (local)
{
- DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
- return NULL;
+ end = &msg->add_conn.me;
+ other_end = &msg->add_conn.other;
}
- other = identification_create_from_string(msg->add_conn.other.id ?
- msg->add_conn.other.id : msg->add_conn.other.address);
- if (!other)
+ else
{
- DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
- me->destroy(me);
- return NULL;
+ end = &msg->add_conn.other;
+ other_end = &msg->add_conn.me;
+ }
+ if (primary)
+ {
+ auth = end->auth;
+ id = end->id;
+ if (!id)
+ { /* leftid/rightid fallback to address */
+ id = end->address;
+ }
+ cert = end->cert;
+ ca = end->ca;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca;
+ }
+ }
+ else
+ {
+ auth = end->auth2;
+ id = end->id2;
+ if (local && !id)
+ { /* leftid2 falls back to leftid */
+ id = end->id;
+ }
+ cert = end->cert2;
+ ca = end->ca2;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca2;
+ }
}
+ if (!auth)
+ {
+ if (primary)
+ {
+ if (local)
+ { /* "leftauth" not defined, fall back to deprecated "authby" */
+ switch (msg->add_conn.auth_method)
+ {
+ default:
+ case AUTH_CLASS_PUBKEY:
+ auth = "pubkey";
+ break;
+ case AUTH_CLASS_PSK:
+ auth = "psk";
+ break;
+ case AUTH_CLASS_EAP:
+ auth = "eap";
+ break;
+ }
+ }
+ else
+ { /* "rightauth" not defined, fall back to deprecated "eap" */
+ if (msg->add_conn.eap_type)
+ {
+ if (msg->add_conn.eap_vendor)
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
+ msg->add_conn.eap_type,
+ msg->add_conn.eap_vendor);
+ }
+ else
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
+ msg->add_conn.eap_type);
+ }
+ auth = eap_buf;
+ }
+ else
+ { /* not EAP => no constraints for this peer */
+ auth = "any";
+ }
+ }
+ }
+ else
+ { /* no second authentication round, fine */
+ return NULL;
+ }
+ }
+
+ cfg = auth_cfg_create();
+
+ /* add identity and peer certifcate */
+ identity = identification_create_from_string(id);
+ if (cert)
+ {
+ certificate = this->cred->load_peer(this->cred, cert);
+ if (certificate)
+ {
+ if (local)
+ {
+ this->ca->check_for_hash_and_url(this->ca, certificate);
+ }
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ if (identity->get_type(identity) == ID_ANY ||
+ !certificate->has_subject(certificate, identity))
+ {
+ DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
+ "defaulting to subject DN: %D", identity,
+ certificate->get_subject(certificate));
+ identity->destroy(identity);
+ identity = certificate->get_subject(certificate);
+ identity = identity->clone(identity);
+ }
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+
+ /* CA constraint */
+ if (ca)
+ {
+ identity = identification_create_from_string(ca);
+ certificate = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, identity, TRUE);
+ identity->destroy(identity);
+ if (certificate)
+ {
+ cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "CA certificate %s not found, discarding CA "
+ "constraint", ca);
+ }
+ }
+
+ /* AC groups */
+ if (end->groups)
+ {
+ enumerator_t *enumerator;
+ char *group;
+
+ enumerator = enumerator_create_token(end->groups, ",", " ");
+ while (enumerator->enumerate(enumerator, &group))
+ {
+ identity = identification_create_from_encoding(ID_IETF_ATTR_STRING,
+ chunk_create(group, strlen(group)));
+ cfg->add(cfg, AUTH_RULE_AC_GROUP, identity);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* authentication metod (class, actually) */
+ if (streq(auth, "pubkey") ||
+ streq(auth, "rsasig") || streq(auth, "rsa") ||
+ streq(auth, "ecdsasig") || streq(auth, "ecdsa"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ else if (streq(auth, "psk") || streq(auth, "secret"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ }
+ else if (strneq(auth, "eap", 3))
+ {
+ enumerator_t *enumerator;
+ char *str;
+ int i = 0, type = 0, vendor;
+
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+ /* parse EAP string, format: eap[-type[-vendor]] */
+ enumerator = enumerator_create_token(auth, "-", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ switch (i)
+ {
+ case 1:
+ type = eap_type_from_string(str);
+ if (!type)
+ {
+ type = atoi(str);
+ if (!type)
+ {
+ DBG1(DBG_CFG, "unknown EAP method: %s", str);
+ break;
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ break;
+ case 2:
+ if (type)
+ {
+ vendor = atoi(str);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "unknown EAP vendor: %s", str);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ i++;
+ }
+ enumerator->destroy(enumerator);
+
+ if (msg->add_conn.eap_identity)
+ {
+ if (streq(msg->add_conn.eap_identity, "%identity"))
+ {
+ identity = identification_create_from_encoding(ID_ANY,
+ chunk_empty);
+ }
+ else
+ {
+ identity = identification_create_from_string(
+ msg->add_conn.eap_identity);
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
+ }
+ }
+ else
+ {
+ if (!streq(auth, "any"))
+ {
+ DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
+ auth);
+ }
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ return cfg;
+}
+
+/**
+ * build a peer_cfg from a stroke msg
+ */
+static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg, ike_cfg_t *ike_cfg)
+{
+ identification_t *peer_id = NULL;
+ peer_cfg_t *mediated_by = NULL;
+ host_t *vip = NULL;
+ unique_policy_t unique;
+ u_int32_t rekey = 0, reauth = 0, over, jitter;
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth_cfg;
#ifdef ME
if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
{
DBG1(DBG_CFG, "a mediation connection cannot be a"
" mediated connection at the same time, aborting");
- me->destroy(me);
- other->destroy(other);
return NULL;
}
@@ -388,8 +554,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
msg->add_conn.ikeme.mediated_by);
- me->destroy(me);
- other->destroy(other);
return NULL;
}
@@ -399,56 +563,19 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
"no mediation connection, aborting",
msg->add_conn.ikeme.mediated_by, msg->add_conn.name);
mediated_by->destroy(mediated_by);
- me->destroy(me);
- other->destroy(other);
return NULL;
}
- }
-
- if (msg->add_conn.ikeme.peerid)
- {
- peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
- if (!peer_id)
+ if (msg->add_conn.ikeme.peerid)
{
- DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.ikeme.peerid);
- mediated_by->destroy(mediated_by);
- me->destroy(me);
- other->destroy(other);
- return NULL;
+ peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
}
- }
- else
- {
- /* no peer ID supplied, assume right ID */
- peer_id = other->clone(other);
- }
-#endif /* ME */
-
- if (msg->add_conn.me.cert)
- {
- cert = this->cred->load_peer(this->cred, msg->add_conn.me.cert);
- if (cert)
+ else if (msg->add_conn.other.id)
{
- identification_t *issuer = cert->get_issuer(cert);
-
- *my_issuer = issuer->clone(issuer);
- this->ca->check_for_hash_and_url(this->ca, cert);
- me = update_peerid(cert, me);
- cert->destroy(cert);
- }
- }
- if (msg->add_conn.other.cert)
- {
- cert = this->cred->load_peer(this->cred, msg->add_conn.other.cert);
- if (cert)
- {
- identification_t *issuer = cert->get_issuer(cert);
-
- *other_issuer = issuer->clone(issuer);
- other = update_peerid(cert, other);
- cert->destroy(cert);
+ peer_id = identification_create_from_string(msg->add_conn.other.id);
}
}
+#endif /* ME */
+
jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
over = msg->add_conn.rekey.margin;
if (msg->add_conn.rekey.reauth)
@@ -512,179 +639,45 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
/* other.sourceip is managed in stroke_attributes. If it is set, we define
* the pool name as the connection name, which the attribute provider
* uses to serve pool addresses. */
- return peer_cfg_create(msg->add_conn.name,
- msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other,
+ peer_cfg = peer_cfg_create(msg->add_conn.name,
+ msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
msg->add_conn.me.sendcert, unique,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.dpd.delay,
vip, msg->add_conn.other.sourceip_size ?
msg->add_conn.name : msg->add_conn.other.sourceip,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
-}
-
-/**
- * fill in auth_info from stroke message
- */
-static void build_auth_info(private_stroke_config_t *this,
- stroke_msg_t *msg, auth_info_t *auth,
- identification_t *my_ca,
- identification_t *other_ca)
-{
- identification_t *id;
- bool my_ca_same = FALSE;
- bool other_ca_same = FALSE;
- cert_validation_t valid;
-
- switch (msg->add_conn.crl_policy)
- {
- case CRL_STRICT_YES:
- valid = VALIDATION_GOOD;
- auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
- break;
- case CRL_STRICT_IFURI:
- valid = VALIDATION_SKIPPED;
- auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
- break;
- default:
- break;
- }
- if (msg->add_conn.me.ca)
+ /* build leftauth= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
+ if (auth_cfg)
{
- if (my_ca)
- {
- my_ca->destroy(my_ca);
- my_ca = NULL;
- }
- if (streq(msg->add_conn.me.ca, "%same"))
- {
- my_ca_same = TRUE;
- }
- else
- {
- my_ca = identification_create_from_string(msg->add_conn.me.ca);
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
-
- if (msg->add_conn.other.ca)
- {
- if (other_ca)
- {
- other_ca->destroy(other_ca);
- other_ca = NULL;
- }
- if (streq(msg->add_conn.other.ca, "%same"))
- {
- other_ca_same = TRUE;
- }
- else
- {
- other_ca = identification_create_from_string(msg->add_conn.other.ca);
- }
- }
-
- if (other_ca_same && my_ca)
- {
- other_ca = my_ca->clone(my_ca);
- }
- else if (my_ca_same && other_ca)
- {
- my_ca = other_ca->clone(other_ca);
- }
-
- if (other_ca)
- {
- DBG2(DBG_CFG, " other ca: %D", other_ca);
- certificate_t *cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, other_ca, TRUE);
- if (cert)
- {
- auth->add_item(auth, AUTHZ_CA_CERT, cert);
- cert->destroy(cert);
- }
- else
- {
- auth->add_item(auth, AUTHZ_CA_CERT_NAME, other_ca);
- }
- other_ca->destroy(other_ca);
- }
-
- if (my_ca)
- {
- DBG2(DBG_CFG, " my ca: %D", my_ca);
- certificate_t *cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, my_ca, TRUE);
- if (cert)
- {
- auth->add_item(auth, AUTHN_CA_CERT, cert);
- cert->destroy(cert);
- }
- else
- {
- auth->add_item(auth, AUTHN_CA_CERT_NAME, my_ca);
- }
- my_ca->destroy(my_ca);
+ else
+ { /* we require at least one config on our side */
+ peer_cfg->destroy(peer_cfg);
+ return NULL;
}
- auth->add_item(auth, AUTHN_AUTH_CLASS, &msg->add_conn.auth_method);
- if (msg->add_conn.eap_type)
+ /* build leftauth2= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
+ if (auth_cfg)
{
- auth->add_item(auth, AUTHN_EAP_TYPE, &msg->add_conn.eap_type);
- if (msg->add_conn.eap_vendor)
- {
- auth->add_item(auth, AUTHN_EAP_VENDOR, &msg->add_conn.eap_vendor);
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
-
- if (msg->add_conn.eap_identity)
+ /* build rightauth= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
+ if (auth_cfg)
{
- if (streq(msg->add_conn.eap_identity, "%identity"))
- {
- id = identification_create_from_encoding(ID_ANY, chunk_empty);
- }
- else
- {
- id = identification_create_from_encoding(ID_EAP, chunk_create(
- msg->add_conn.eap_identity,
- strlen(msg->add_conn.eap_identity)));
- }
- auth->add_item(auth, AUTHN_EAP_IDENTITY, id);
- id->destroy(id);
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
-
- if (msg->add_conn.other.groups)
+ /* build rightauth2= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
+ if (auth_cfg)
{
- chunk_t line = { msg->add_conn.other.groups,
- strlen(msg->add_conn.other.groups) };
-
- while (eat_whitespace(&line))
- {
- chunk_t group;
-
- /* extract the next comma-separated group attribute */
- if (!extract_token(&group, ',', &line))
- {
- group = line;
- line.len = 0;
- }
-
- /* remove any trailing spaces */
- while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
- {
- group.len--;
- }
-
- /* add the group attribute to the list */
- if (group.len > 0)
- {
- identification_t *ac_group;
-
- ac_group = identification_create_from_encoding(
- ID_IETF_ATTR_STRING, group);
- auth->add_item(auth, AUTHZ_AC_GROUP, ac_group);
- ac_group->destroy(ac_group);
- }
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
+ return peer_cfg;
}
/**
@@ -799,7 +792,6 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
ike_cfg_t *ike_cfg, *existing_ike;
peer_cfg_t *peer_cfg, *existing;
child_cfg_t *child_cfg;
- identification_t *my_issuer = NULL, *other_issuer = NULL;
enumerator_t *enumerator;
bool use_existing = FALSE;
@@ -808,15 +800,13 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
{
return;
}
- peer_cfg = build_peer_cfg(this, msg, ike_cfg, &my_issuer, &other_issuer);
+ peer_cfg = build_peer_cfg(this, msg, ike_cfg);
if (!peer_cfg)
{
ike_cfg->destroy(ike_cfg);
return;
}
- build_auth_info(this, msg, peer_cfg->get_auth(peer_cfg),
- my_issuer, other_issuer);
enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
while (enumerator->enumerate(enumerator, &existing))
{
@@ -850,9 +840,7 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
else
{
/* add config to backend */
- DBG1(DBG_CFG, "added configuration '%s': %s[%D]...%s[%D]", msg->add_conn.name,
- ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
- ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
+ DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
this->mutex->lock(this->mutex);
this->list->insert_last(this->list, peer_cfg);
this->mutex->unlock(this->mutex);
diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index 434aec22b..7fb33da9e 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -905,26 +905,13 @@ static void load_secrets(private_stroke_cred_t *this)
continue;
}
- if (type == SHARED_EAP)
+ /* NULL terminate the ID string */
+ *(id.ptr + id.len) = '\0';
+ peer_id = identification_create_from_string(id.ptr);
+ if (peer_id->get_type(peer_id) == ID_ANY)
{
- /* we use a special EAP identity type for EAP secrets */
- peer_id = identification_create_from_encoding(ID_EAP, id);
- }
- else
- {
- /* NULL terminate the ID string */
- *(id.ptr + id.len) = '\0';
- peer_id = identification_create_from_string(id.ptr);
- if (peer_id == NULL)
- {
- DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
- goto error;
- }
- if (peer_id->get_type(peer_id) == ID_ANY)
- {
- peer_id->destroy(peer_id);
- continue;
- }
+ peer_id->destroy(peer_id);
+ continue;
}
shared_key->add_owner(shared_key, peer_id);
diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c
index 94b3def3a..9c98770dd 100644
--- a/src/charon/plugins/stroke/stroke_list.c
+++ b/src/charon/plugins/stroke/stroke_list.c
@@ -55,23 +55,6 @@ struct private_stroke_list_t {
};
/**
- * get the authentication class of a config
- */
-auth_class_t get_auth_class(peer_cfg_t *config)
-{
- auth_class_t *class;
- auth_info_t *auth_info;
-
- auth_info = config->get_auth(config);
- if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
- {
- return *class;
- }
- /* fallback to pubkey authentication */
- return AUTH_CLASS_PUBKEY;
-}
-
-/**
* log an IKE_SA to out
*/
static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
@@ -110,9 +93,11 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
{
time_t rekey, reauth;
+ peer_cfg_t *peer_cfg;
rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
if (rekey)
{
@@ -120,9 +105,24 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
}
if (reauth)
{
- fprintf(out, ", %N reauthentication in %V", auth_class_names,
- get_auth_class(ike_sa->get_peer_cfg(ike_sa)),
- &reauth, &now);
+ bool first = TRUE;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+
+ fprintf(out, ", ");
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ if (!first)
+ {
+ fprintf(out, "+");
+ }
+ first = FALSE;
+ fprintf(out, "%N", auth_class_names,
+ auth->get(auth, AUTH_RULE_AUTH_CLASS));
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, " reauthentication in %V", &reauth, &now);
}
if (!rekey && !reauth)
{
@@ -248,6 +248,107 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
/**
+ * Log a configs local or remote authentication config to out
+ */
+static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
+{
+ enumerator_t *enumerator, *rules;
+ auth_rule_t rule;
+ auth_cfg_t *auth;
+ auth_class_t auth_class;
+ identification_t *id;
+ certificate_t *cert;
+ cert_validation_t valid;
+ char *name;
+
+ name = peer_cfg->get_name(peer_cfg);
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ fprintf(out, "%12s: %s [%D] uses ", name, local ? "local: " : "remote:",
+ auth->get(auth, AUTH_RULE_IDENTITY));
+
+ auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ if (auth_class != AUTH_CLASS_EAP)
+ {
+ fprintf(out, "%N authentication\n", auth_class_names, auth_class);
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
+ {
+ fprintf(out, "EAP authentication");
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
+ {
+ fprintf(out, "EAP_%d-%d authentication",
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
+ }
+ else
+ {
+ fprintf(out, "%N authentication", eap_type_names,
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
+ }
+ }
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ fprintf(out, " with EAP identity '%D'", id);
+ }
+ fprintf(out, "\n");
+ }
+
+ cert = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: ca: \"%D\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_IM_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: im-ca: \"%D\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: cert: \"%D\"\n", name,
+ cert->get_subject(cert));
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &id))
+ {
+ if (rule == AUTH_RULE_AC_GROUP)
+ {
+ fprintf(out, "%12s: group: %D\n", name, id);
+ }
+ }
+ rules->destroy(rules);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* Implementation of stroke_list_t.status.
*/
static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
@@ -313,138 +414,42 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
enumerator->destroy(enumerator);
fprintf(out, "Connections:\n");
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
- while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
{
- void *ptr;
- certificate_t *cert;
- auth_item_t item;
- auth_info_t *auth;
- enumerator_t *auth_enumerator;
- identification_t *my_ca = NULL, *other_ca = NULL;
- identification_t *eap_identity = NULL;
- u_int32_t *eap_type = NULL;
- bool ac_groups = FALSE;
-
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
{
continue;
}
- /* determine any required CAs, EAP type, EAP identity,
- * and the presence of AC groups
- */
- auth = peer_cfg->get_auth(peer_cfg);
- auth_enumerator = auth->create_item_enumerator(auth);
- while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
- {
- switch (item)
- {
- case AUTHN_EAP_TYPE:
- eap_type = (u_int32_t *)ptr;
- break;
- case AUTHN_EAP_IDENTITY:
- eap_identity = (identification_t *)ptr;
- break;
- case AUTHN_CA_CERT:
- cert = (certificate_t *)ptr;
- my_ca = cert->get_subject(cert);
- break;
- case AUTHN_CA_CERT_NAME:
- my_ca = (identification_t *)ptr;
- break;
- case AUTHZ_CA_CERT:
- cert = (certificate_t *)ptr;
- other_ca = cert->get_subject(cert);
- break;
- case AUTHZ_CA_CERT_NAME:
- other_ca = (identification_t *)ptr;
- break;
- case AUTHZ_AC_GROUP:
- ac_groups = TRUE;
- break;
- default:
- break;
- }
- }
- auth_enumerator->destroy(auth_enumerator);
-
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
- fprintf(out, "%12s: %s[%D]...%s[%D]\n", peer_cfg->get_name(peer_cfg),
- ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
- ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
- if (my_ca || other_ca)
- {
- fprintf(out, "%12s: CAs: ", peer_cfg->get_name(peer_cfg));
- if (my_ca)
- {
- fprintf(out, "\"%D\"...", my_ca);
- }
- else
- {
- fprintf(out, "%%any...");
- }
- if (other_ca)
- {
- fprintf(out, "\"%D\"\n", other_ca);
- }
- else
- {
- fprintf(out, "%%any\n");
- }
- }
-
- if (ac_groups)
- {
- bool first = TRUE;
-
- fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg));
- auth_enumerator = auth->create_item_enumerator(auth);
- while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
- {
- if (item == AUTHZ_AC_GROUP)
- {
- identification_t *group = (identification_t *)ptr;
-
- fprintf(out, "%s%D", first? "":", ", group);
- first = FALSE;
- }
- }
- auth_enumerator->destroy(auth_enumerator);
- fprintf(out, "\n");
- }
-
- fprintf(out, "%12s: %N ", peer_cfg->get_name(peer_cfg),
- auth_class_names, get_auth_class(peer_cfg));
- if (eap_type)
- {
- fprintf(out, "and %N ", eap_type_names, *eap_type);
- }
- fprintf(out, "authentication");
- if (eap_identity)
- {
- fprintf(out, ", EAP identity: '%D'", eap_identity);
- }
+ fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
+ ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
+
dpd = peer_cfg->get_dpd(peer_cfg);
if (dpd)
{
fprintf(out, ", dpddelay=%us", dpd);
}
fprintf(out, "\n");
-
+
+ log_auth_cfgs(out, peer_cfg, TRUE);
+ log_auth_cfgs(out, peer_cfg, FALSE);
+
children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg))
{
linked_list_t *my_ts, *other_ts;
-
+
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
- fprintf(out, "%12s: %#R=== %#R", child_cfg->get_name(child_cfg),
+ fprintf(out, "%12s: child: %#R=== %#R", child_cfg->get_name(child_cfg),
my_ts, other_ts);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
-
+
if (dpd)
{
fprintf(out, ", dpdaction=%N", action_names,
diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c
index 53edde031..85f1e8f4e 100644
--- a/src/charon/plugins/stroke/stroke_socket.c
+++ b/src/charon/plugins/stroke/stroke_socket.c
@@ -143,18 +143,28 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->auth);
+ pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
+ pop_string(msg, &end->id2);
pop_string(msg, &end->cert);
+ pop_string(msg, &end->cert2);
pop_string(msg, &end->ca);
+ pop_string(msg, &end->ca2);
pop_string(msg, &end->groups);
pop_string(msg, &end->updown);
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
+ DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
+ DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
+ DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
DBG2(DBG_CFG, " %scert=%s", label, end->cert);
+ DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
+ DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
}