diff options
Diffstat (limited to 'src/charon/plugins/stroke')
-rw-r--r-- | src/charon/plugins/stroke/stroke_attribute.c | 4 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_config.c | 696 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_cred.c | 25 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_list.c | 263 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_socket.c | 10 |
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, ¤t)) { - /* 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); } |