From c1343b3278cdf99533b7902744d15969f9d6fdc1 Mon Sep 17 00:00:00 2001 From: Yves-Alexis Perez Date: Wed, 2 Jan 2013 14:18:20 +0100 Subject: Imported Upstream version 5.0.1 --- src/libcharon/config/backend_manager.c | 109 ++++++++++++++--------- src/libcharon/config/backend_manager.h | 4 +- src/libcharon/config/child_cfg.c | 79 +++++++++-------- src/libcharon/config/child_cfg.h | 4 +- src/libcharon/config/ike_cfg.c | 29 +++++- src/libcharon/config/ike_cfg.h | 57 ++++++------ src/libcharon/config/peer_cfg.c | 155 +++++++++++++++++++++++++-------- src/libcharon/config/peer_cfg.h | 112 +++++++++++++++++------- src/libcharon/config/proposal.c | 81 ++++++++--------- src/libcharon/config/proposal.h | 3 +- 10 files changed, 415 insertions(+), 218 deletions(-) (limited to 'src/libcharon/config') diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c index a93457ea4..09e123e67 100644 --- a/src/libcharon/config/backend_manager.c +++ b/src/libcharon/config/backend_manager.c @@ -78,12 +78,14 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data) static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { host_t *me_cand, *other_cand; + char *my_addr, *other_addr; + bool my_allow_any, other_allow_any; ike_cfg_match_t match = MATCH_NONE; if (me) { - me_cand = host_create_from_dns(cand->get_my_addr(cand), - me->get_family(me), 0); + my_addr = cand->get_my_addr(cand, &my_allow_any); + me_cand = host_create_from_dns(my_addr, me->get_family(me), 0); if (!me_cand) { return MATCH_NONE; @@ -92,7 +94,7 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_ME; } - else if (me_cand->is_anyaddr(me_cand)) + else if (my_allow_any || me_cand->is_anyaddr(me_cand)) { match += MATCH_ANY; } @@ -110,8 +112,8 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) if (other) { - other_cand = host_create_from_dns(cand->get_other_addr(cand), - other->get_family(other), 0); + other_addr = cand->get_other_addr(cand, &other_allow_any); + other_cand = host_create_from_dns(other_addr, other->get_family(other), 0); if (!other_cand) { return MATCH_NONE; @@ -120,7 +122,7 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_OTHER; } - else if (other_cand->is_anyaddr(other_cand)) + else if (other_allow_any || other_cand->is_anyaddr(other_cand)) { match += MATCH_ANY; } @@ -142,14 +144,17 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, private_backend_manager_t *this, host_t *me, host_t *other) { ike_cfg_t *current, *found = NULL; + char *my_addr, *other_addr; + bool my_allow_any, other_allow_any; enumerator_t *enumerator; ike_cfg_match_t match, best = MATCH_ANY; ike_data_t *data; - data = malloc_thing(ike_data_t); - data->this = this; - data->me = me; - data->other = other; + INIT(data, + .this = this, + .me = me, + .other = other, + ); DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other); @@ -160,12 +165,14 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, while (enumerator->enumerate(enumerator, (void**)¤t)) { match = get_ike_match(current, me, other); - + DBG3(DBG_CFG, "ike config match: %d (%H %H)", match, me, other); if (match) { - DBG2(DBG_CFG, " candidate: %s...%s, prio %d", - current->get_my_addr(current), - current->get_other_addr(current), match); + my_addr = current->get_my_addr(current, &my_allow_any); + other_addr = current->get_other_addr(current, &other_allow_any); + DBG2(DBG_CFG, " candidate: %s%s...%s%s, prio %d", + my_allow_any ? "%":"", my_addr, + other_allow_any ? "%":"", other_addr, match); if (match > best) { DESTROY_IF(found); @@ -179,8 +186,11 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, this->lock->unlock(this->lock); if (found) { - DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d", - found->get_my_addr(found), found->get_other_addr(found), best); + my_addr = found->get_my_addr(found, &my_allow_any); + other_addr = found->get_other_addr(found, &other_allow_any); + DBG2(DBG_CFG, "found matching ike config: %s%s...%s%s with prio %d", + my_allow_any ? "%":"", my_addr, + other_allow_any ? "%":"", other_addr, best); } return found; } @@ -195,9 +205,13 @@ static id_match_t get_peer_match(identification_t *id, auth_cfg_t *auth; identification_t *candidate; id_match_t match = ID_MATCH_NONE; + char *where = local ? "local" : "remote"; + chunk_t data; if (!id) { + DBG3(DBG_CFG, "peer config match %s: %d (%N)", + where, ID_MATCH_ANY, id_type_names, ID_ANY); return ID_MATCH_ANY; } @@ -221,9 +235,29 @@ static id_match_t get_peer_match(identification_t *id, } } enumerator->destroy(enumerator); + + data = id->get_encoding(id); + DBG3(DBG_CFG, "peer config match %s: %d (%N -> %#B)", + where, match, id_type_names, id->get_type(id), &data); return match; } +/** + * Get match quality of IKE version + */ +static int get_version_match(ike_version_t cfg, ike_version_t req) +{ + if (req == IKE_ANY || cfg == IKE_ANY) + { + return 1; + } + if (req == cfg) + { + return 2; + } + return 0; +} + /** * data to pass nested peer enumerator */ @@ -317,17 +351,18 @@ static void insert_sorted(match_entry_t *entry, linked_list_t *list, METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*, private_backend_manager_t *this, host_t *me, host_t *other, - identification_t *my_id, identification_t *other_id) + identification_t *my_id, identification_t *other_id, ike_version_t version) { enumerator_t *enumerator; peer_data_t *data; peer_cfg_t *cfg; linked_list_t *configs, *helper; - data = malloc_thing(peer_data_t); - data->lock = this->lock; - data->me = my_id; - data->other = other_id; + INIT(data, + .lock = this->lock, + .me = my_id, + .other = other_id, + ); /* create a sorted list with all matches */ this->lock->read_lock(this->lock); @@ -340,9 +375,6 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*, return enumerator; } - DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]", - me, my_id, other, other_id); - configs = linked_list_create(); /* only once allocated helper list for sorting */ helper = linked_list_create(); @@ -350,29 +382,26 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*, { id_match_t match_peer_me, match_peer_other; ike_cfg_match_t match_ike; + int match_version; match_entry_t *entry; - chunk_t data; match_peer_me = get_peer_match(my_id, cfg, TRUE); - data = my_id->get_encoding(my_id); - DBG3(DBG_CFG, "match_peer_me: %d (%N -> %#B)", match_peer_me, - id_type_names, my_id->get_type(my_id), &data); match_peer_other = get_peer_match(other_id, cfg, FALSE); - data = other_id->get_encoding(other_id); - DBG3(DBG_CFG, "match_peer_other: %d (%N -> %#B)", match_peer_other, - id_type_names, other_id->get_type(other_id), &data); match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other); - DBG3(DBG_CFG, "match_ike: %d (%H %H)", match_ike, me, other); + match_version = get_version_match(cfg->get_ike_version(cfg), version); + DBG3(DBG_CFG, "ike config match: %d (%H %H)", match_ike, me, other); - if (match_peer_me && match_peer_other && match_ike) + if (match_peer_me && match_peer_other && match_ike && match_version) { - DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)", - cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike); - - entry = malloc_thing(match_entry_t); - entry->match_peer = match_peer_me + match_peer_other; - entry->match_ike = match_ike; - entry->cfg = cfg->get_ref(cfg); + DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d/%d " + "(me/other/ike/version)", cfg->get_name(cfg), + match_peer_me, match_peer_other, match_ike, match_version); + + INIT(entry, + .match_peer = match_peer_me + match_peer_other, + .match_ike = match_ike, + .cfg = cfg->get_ref(cfg), + ); insert_sorted(entry, configs, helper); } } diff --git a/src/libcharon/config/backend_manager.h b/src/libcharon/config/backend_manager.h index 5b394f791..de263365b 100644 --- a/src/libcharon/config/backend_manager.h +++ b/src/libcharon/config/backend_manager.h @@ -56,6 +56,7 @@ struct backend_manager_t { * * @param my_host address of own host * @param other_host address of remote host + * @param version IKE version to get a config for * @return matching ike_config, or NULL if none found */ ike_cfg_t* (*get_ike_cfg)(backend_manager_t *this, @@ -79,11 +80,12 @@ struct backend_manager_t { * @param other remote address * @param my_id IDr in first authentication round * @param other_id IDi in first authentication round + * @param version IKE version to get a config for * @return enumerator over peer_cfg_t */ enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this, host_t *me, host_t *other, identification_t *my_id, - identification_t *other_id); + identification_t *other_id, ike_version_t version); /** * Register a backend on the manager. * diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 74949be3c..b675c908f 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -171,6 +171,8 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*, } enumerator->destroy(enumerator); + DBG2(DBG_CFG, "configured proposals: %#P", proposals); + return proposals; } @@ -235,12 +237,16 @@ METHOD(child_cfg_t, add_traffic_selector, void, } METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, - private_child_cfg_t *this, bool local, linked_list_t *supplied, host_t *host) + private_child_cfg_t *this, bool local, linked_list_t *supplied, + linked_list_t *hosts) { enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; - linked_list_t *result = linked_list_create(); + linked_list_t *result, *derived; + host_t *host; + result = linked_list_create(); + derived = linked_list_create(); if (local) { e1 = this->my_ts->create_enumerator(this->my_ts); @@ -249,42 +255,46 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, { e1 = this->other_ts->create_enumerator(this->other_ts); } - - /* no list supplied, just fetch the stored traffic selectors */ - if (supplied == NULL) + /* In a first step, replace "dynamic" TS with the host list */ + while (e1->enumerate(e1, &ts1)) { - DBG2(DBG_CFG, "proposing traffic selectors for %s:", - local ? "us" : "other"); - while (e1->enumerate(e1, &ts1)) + if (hosts && hosts->get_count(hosts) && + ts1->is_dynamic(ts1)) { - /* we make a copy of the TS, this allows us to update dynamic TS' */ - selected = ts1->clone(ts1); - if (host) + e2 = hosts->create_enumerator(hosts); + while (e2->enumerate(e2, &host)) { - selected->set_address(selected, host); + ts2 = ts1->clone(ts1); + ts2->set_address(ts2, host); + derived->insert_last(derived, ts2); } - DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1); - result->insert_last(result, selected); + e2->destroy(e2); + } + else + { + derived->insert_last(derived, ts1->clone(ts1)); + } + } + e1->destroy(e1); + + DBG2(DBG_CFG, "%s traffic selectors for %s:", + supplied ? "selecting" : "proposing", local ? "us" : "other"); + if (supplied == NULL) + { + while (derived->remove_first(derived, (void**)&ts1) == SUCCESS) + { + DBG2(DBG_CFG, " %R", ts1); + result->insert_last(result, ts1); } - e1->destroy(e1); } else { - DBG2(DBG_CFG, "selecting traffic selectors for %s:", - local ? "us" : "other"); - e2 = supplied->create_enumerator(supplied); - /* iterate over all stored selectors */ - while (e1->enumerate(e1, &ts1)) + e1 = supplied->create_enumerator(supplied); + /* enumerate all configured/derived selectors */ + while (derived->remove_first(derived, (void**)&ts1) == SUCCESS) { - /* we make a copy of the TS, as we have to update dynamic TS' */ - ts1 = ts1->clone(ts1); - if (host) - { - ts1->set_address(ts1, host); - } - - /* iterate over all supplied traffic selectors */ - while (e2->enumerate(e2, &ts2)) + /* enumerate all supplied traffic selectors */ + while (e1->enumerate(e1, &ts2)) { selected = ts1->get_subset(ts1, ts2); if (selected) @@ -299,13 +309,12 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, ts1, ts2); } } - e2->destroy(e2); - e2 = supplied->create_enumerator(supplied); + supplied->reset_enumerator(supplied, e1); ts1->destroy(ts1); } e1->destroy(e1); - e2->destroy(e2); } + derived->destroy(derived); /* remove any redundant traffic selectors in the list */ e1 = result->create_enumerator(result); @@ -320,16 +329,14 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, { result->remove_at(result, e2); ts2->destroy(ts2); - e1->destroy(e1); - e1 = result->create_enumerator(result); + result->reset_enumerator(result, e1); break; } if (ts1->is_contained_in(ts1, ts2)) { result->remove_at(result, e1); ts1->destroy(ts1); - e2->destroy(e2); - e2 = result->create_enumerator(result); + result->reset_enumerator(result, e2); break; } } diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 370ff9d58..6e8829a47 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -129,12 +129,12 @@ struct child_cfg_t { * * @param local TRUE for TS on local side, FALSE for remote * @param supplied list with TS to select from, or NULL - * @param host address to use for narrowing "dynamic" TS', or NULL + * @param hosts addresses to use for narrowing "dynamic" TS', host_t * @return list containing the traffic selectors */ linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local, linked_list_t *supplied, - host_t *host); + linked_list_t *hosts); /** * Get the updown script to run for the CHILD_SA. * diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index 342b9ddbe..acf4b6141 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -48,6 +48,16 @@ struct private_ike_cfg_t { */ char *other; + /** + * Allow override of local address + */ + bool my_allow_any; + + /** + * Allow override of remote address + */ + bool other_allow_any; + /** * our source port */ @@ -87,14 +97,22 @@ METHOD(ike_cfg_t, force_encap_, bool, } METHOD(ike_cfg_t, get_my_addr, char*, - private_ike_cfg_t *this) + private_ike_cfg_t *this, bool *allow_any) { + if (allow_any) + { + *allow_any = this->my_allow_any; + } return this->me; } METHOD(ike_cfg_t, get_other_addr, char*, - private_ike_cfg_t *this) + private_ike_cfg_t *this, bool *allow_any) { + if (allow_any) + { + *allow_any = this->other_allow_any; + } return this->other; } @@ -132,6 +150,8 @@ METHOD(ike_cfg_t, get_proposals, linked_list_t*, } enumerator->destroy(enumerator); + DBG2(DBG_CFG, "configured proposals: %#P", proposals); + return proposals; } @@ -260,7 +280,8 @@ METHOD(ike_cfg_t, destroy, void, * Described in header. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - char *me, u_int16_t my_port, char *other, u_int16_t other_port) + char *me, bool my_allow_any, u_int16_t my_port, + char *other, bool other_allow_any, u_int16_t other_port) { private_ike_cfg_t *this; @@ -285,6 +306,8 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, .force_encap = force_encap, .me = strdup(me), .other = strdup(other), + .my_allow_any = my_allow_any, + .other_allow_any = other_allow_any, .my_port = my_port, .other_port = other_port, .proposals = linked_list_create(), diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index f1edde255..691d223a3 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -41,28 +41,30 @@ struct ike_cfg_t { /** * Get own address. * - * @return string of address/DNS name + * @param allow_any allow any address to match + * @return string of address/DNS name */ - char* (*get_my_addr) (ike_cfg_t *this); + char* (*get_my_addr) (ike_cfg_t *this, bool *allow_any); /** - * Get peers address. + * Get peer's address. * - * @return string of address/DNS name + * @param allow_any allow any address to match + * @return string of address/DNS name */ - char* (*get_other_addr) (ike_cfg_t *this); + char* (*get_other_addr) (ike_cfg_t *this, bool *allow_any); /** * Get the port to use as our source port. * - * @return source address port, host order + * @return source address port, host order */ u_int16_t (*get_my_port)(ike_cfg_t *this); /** * Get the port to use as destination port. * - * @return destination address, host order + * @return destination address, host order */ u_int16_t (*get_other_port)(ike_cfg_t *this); @@ -72,7 +74,7 @@ struct ike_cfg_t { * The first added proposal has the highest priority, the last * added the lowest. * - * @param proposal proposal to add + * @param proposal proposal to add */ void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal); @@ -81,7 +83,7 @@ struct ike_cfg_t { * * Returned list and its proposals must be destroyed after use. * - * @return list containing all the proposals + * @return list containing all the proposals */ linked_list_t* (*get_proposals) (ike_cfg_t *this); @@ -90,9 +92,9 @@ struct ike_cfg_t { * * Returned proposal must be destroyed after use. * - * @param proposals list of proposals to select from - * @param private accept algorithms from a private range - * @return selected proposal, or NULL if none matches. + * @param proposals list of proposals to select from + * @param private accept algorithms from a private range + * @return selected proposal, or NULL if none matches. */ proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals, bool private); @@ -100,36 +102,36 @@ struct ike_cfg_t { /** * Should we send a certificate request in IKE_SA_INIT? * - * @return certificate request sending policy + * @return certificate request sending policy */ bool (*send_certreq) (ike_cfg_t *this); /** * Enforce UDP encapsulation by faking NATD notifies? * - * @return TRUE to enfoce UDP encapsulation + * @return TRUE to enfoce UDP encapsulation */ bool (*force_encap) (ike_cfg_t *this); /** * Get the DH group to use for IKE_SA setup. * - * @return dh group to use for initialization + * @return dh group to use for initialization */ diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this); /** * Check if two IKE configs are equal. * - * @param other other to check for equality - * @return TRUE if other equal to this + * @param other other to check for equality + * @return TRUE if other equal to this */ bool (*equals)(ike_cfg_t *this, ike_cfg_t *other); /** * Increase reference count. * - * @return reference to this + * @return reference to this */ ike_cfg_t* (*get_ref) (ike_cfg_t *this); @@ -147,15 +149,18 @@ struct ike_cfg_t { * * Supplied hosts become owned by ike_cfg, the name gets cloned. * - * @param certreq TRUE to send a certificate request - * @param force_encap enforce UDP encapsulation by faking NATD notify - * @param me address/DNS name of local peer - * @param my_port IKE port to use as source, 500 uses IKEv2 port floating - * @param other address/DNS name of remote peer - * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating - * @return ike_cfg_t object. + * @param certreq TRUE to send a certificate request + * @param force_encap enforce UDP encapsulation by faking NATD notify + * @param me address/DNS name of local peer + * @param my_allow_any allow override of local address by any address + * @param my_port IKE port to use as source, 500 uses IKEv2 port floating + * @param other address/DNS name of remote peer + * @param other_allow_any allow override of remote address by any address + * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating + * @return ike_cfg_t object. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - char *me, u_int16_t my_port, char *other, u_int16_t other_port); + char *me, bool my_allow_any, u_int16_t my_port, + char *other, bool other_allow_any, u_int16_t other_port); #endif /** IKE_CFG_H_ @}*/ diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index c623cbc9b..01ca026e1 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -25,6 +25,12 @@ #include #include +ENUM(ike_version_names, IKE_ANY, IKEV2, + "IKEv1/2", + "IKEv1", + "IKEv2", +); + ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND, "CERT_ALWAYS_SEND", "CERT_SEND_IF_ASKED", @@ -62,7 +68,7 @@ struct private_peer_cfg_t { /** * IKE version to use for initiation */ - u_int ike_version; + ike_version_t ike_version; /** * IKE config associated to this peer config @@ -99,6 +105,11 @@ struct private_peer_cfg_t { */ bool use_mobike; + /** + * Use aggressive mode? + */ + bool aggressive; + /** * Time before starting rekeying */ @@ -125,14 +136,19 @@ struct private_peer_cfg_t { u_int32_t dpd; /** - * virtual IP to use locally + * DPD timeout intervall (used for IKEv1 only) + */ + u_int32_t dpd_timeout; + + /** + * List of virtual IPs (host_t*) to request */ - host_t *virtual_ip; + linked_list_t *vips; /** - * pool to acquire configuration attributes from + * List of pool names to use for virtual IP lookup */ - char *pool; + linked_list_t *pools; /** * local authentication configs (rulesets) @@ -169,7 +185,7 @@ METHOD(peer_cfg_t, get_name, char*, return this->name; } -METHOD(peer_cfg_t, get_ike_version, u_int, +METHOD(peer_cfg_t, get_ike_version, ike_version_t, private_peer_cfg_t *this) { return this->ike_version; @@ -240,7 +256,7 @@ METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*, * Check how good a list of TS matches a given child config */ static int get_ts_match(child_cfg_t *cfg, bool local, - linked_list_t *sup_list, host_t *host) + linked_list_t *sup_list, linked_list_t *hosts) { linked_list_t *cfg_list; enumerator_t *sup_enum, *cfg_enum; @@ -248,7 +264,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local, int match = 0, round; /* fetch configured TS list, narrowing dynamic TS */ - cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, host); + cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts); /* use a round counter to rate leading TS with higher priority */ round = sup_list->get_count(sup_list); @@ -281,7 +297,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local, METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*, private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts, - host_t *my_host, host_t *other_host) + linked_list_t *my_hosts, linked_list_t *other_hosts) { child_cfg_t *current, *found = NULL; enumerator_t *enumerator; @@ -293,8 +309,8 @@ METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*, { int my_prio, other_prio; - my_prio = get_ts_match(current, TRUE, my_ts, my_host); - other_prio = get_ts_match(current, FALSE, other_ts, other_host); + my_prio = get_ts_match(current, TRUE, my_ts, my_hosts); + other_prio = get_ts_match(current, FALSE, other_ts, other_hosts); if (my_prio && other_prio) { @@ -336,13 +352,13 @@ METHOD(peer_cfg_t, get_keyingtries, u_int32_t, } METHOD(peer_cfg_t, get_rekey_time, u_int32_t, - private_peer_cfg_t *this) + private_peer_cfg_t *this, bool jitter) { if (this->rekey_time == 0) { return 0; } - if (this->jitter_time == 0) + if (this->jitter_time == 0 || !jitter) { return this->rekey_time; } @@ -350,13 +366,13 @@ METHOD(peer_cfg_t, get_rekey_time, u_int32_t, } METHOD(peer_cfg_t, get_reauth_time, u_int32_t, - private_peer_cfg_t *this) + private_peer_cfg_t *this, bool jitter) { if (this->reauth_time == 0) { return 0; } - if (this->jitter_time == 0) + if (this->jitter_time == 0 || !jitter) { return this->reauth_time; } @@ -375,22 +391,46 @@ METHOD(peer_cfg_t, use_mobike, bool, return this->use_mobike; } +METHOD(peer_cfg_t, use_aggressive, bool, + private_peer_cfg_t *this) +{ + return this->aggressive; +} + METHOD(peer_cfg_t, get_dpd, u_int32_t, private_peer_cfg_t *this) { return this->dpd; } -METHOD(peer_cfg_t, get_virtual_ip, host_t*, +METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t, private_peer_cfg_t *this) { - return this->virtual_ip; + return this->dpd_timeout; +} + +METHOD(peer_cfg_t, add_virtual_ip, void, + private_peer_cfg_t *this, host_t *vip) +{ + this->vips->insert_last(this->vips, vip); +} + +METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*, + private_peer_cfg_t *this) +{ + return this->vips->create_enumerator(this->vips); +} + +METHOD(peer_cfg_t, add_pool, void, + private_peer_cfg_t *this, char *name) +{ + this->pools->insert_last(this->pools, strdup(name)); } -METHOD(peer_cfg_t, get_pool, char*, +METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*, private_peer_cfg_t *this) { - return this->pool; + return this->pools->create_enumerator(this->pools); } METHOD(peer_cfg_t, add_auth_cfg, void, @@ -493,6 +533,10 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other) METHOD(peer_cfg_t, equals, bool, private_peer_cfg_t *this, private_peer_cfg_t *other) { + enumerator_t *e1, *e2; + host_t *vip1, *vip2; + char *pool1, *pool2; + if (this == other) { return TRUE; @@ -502,6 +546,43 @@ METHOD(peer_cfg_t, equals, bool, return FALSE; } + if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips)) + { + return FALSE; + } + e1 = create_virtual_ip_enumerator(this); + e2 = create_virtual_ip_enumerator(other); + if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2)) + { + if (!vip1->ip_equals(vip1, vip2)) + { + e1->destroy(e1); + e2->destroy(e2); + return FALSE; + } + } + e1->destroy(e1); + e2->destroy(e2); + + if (this->pools->get_count(this->pools) != + other->pools->get_count(other->pools)) + { + return FALSE; + } + e1 = create_pool_enumerator(this); + e2 = create_pool_enumerator(other); + if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2)) + { + if (!streq(pool1, pool2)) + { + e1->destroy(e1); + e2->destroy(e2); + return FALSE; + } + } + e1->destroy(e1); + e2->destroy(e2); + return ( this->ike_version == other->ike_version && this->cert_policy == other->cert_policy && @@ -513,11 +594,6 @@ METHOD(peer_cfg_t, equals, bool, this->jitter_time == other->jitter_time && this->over_time == other->over_time && this->dpd == other->dpd && - (this->virtual_ip == other->virtual_ip || - (this->virtual_ip && other->virtual_ip && - this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) && - (this->pool == other->pool || - (this->pool && other->pool && streq(this->pool, other->pool))) && auth_cfg_equal(this, other) #ifdef ME && this->mediation == other->mediation && @@ -544,18 +620,18 @@ METHOD(peer_cfg_t, destroy, void, this->ike_cfg->destroy(this->ike_cfg); this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy)); - DESTROY_IF(this->virtual_ip); this->local_auth->destroy_offset(this->local_auth, offsetof(auth_cfg_t, destroy)); this->remote_auth->destroy_offset(this->remote_auth, offsetof(auth_cfg_t, destroy)); + this->vips->destroy_offset(this->vips, offsetof(host_t, destroy)); + this->pools->destroy_function(this->pools, free); #ifdef ME DESTROY_IF(this->mediated_by); DESTROY_IF(this->peer_id); #endif /* ME */ this->mutex->destroy(this->mutex); free(this->name); - free(this->pool); free(this); } } @@ -563,12 +639,13 @@ METHOD(peer_cfg_t, destroy, void, /* * Described in header-file */ -peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, - cert_policy_t cert_policy, unique_policy_t unique, - u_int32_t keyingtries, u_int32_t rekey_time, - u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, u_int32_t dpd, - host_t *virtual_ip, char *pool, +peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version, + ike_cfg_t *ike_cfg, cert_policy_t cert_policy, + unique_policy_t unique, u_int32_t keyingtries, + u_int32_t rekey_time, u_int32_t reauth_time, + u_int32_t jitter_time, u_int32_t over_time, + bool mobike, bool aggressive, u_int32_t dpd, + u_int32_t dpd_timeout, bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id) { @@ -599,9 +676,13 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, .get_reauth_time = _get_reauth_time, .get_over_time = _get_over_time, .use_mobike = _use_mobike, + .use_aggressive = _use_aggressive, .get_dpd = _get_dpd, - .get_virtual_ip = _get_virtual_ip, - .get_pool = _get_pool, + .get_dpd_timeout = _get_dpd_timeout, + .add_virtual_ip = _add_virtual_ip, + .create_virtual_ip_enumerator = _create_virtual_ip_enumerator, + .add_pool = _add_pool, + .create_pool_enumerator = _create_pool_enumerator, .add_auth_cfg = _add_auth_cfg, .create_auth_cfg_enumerator = _create_auth_cfg_enumerator, .equals = (void*)_equals, @@ -626,9 +707,11 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, .jitter_time = jitter_time, .over_time = over_time, .use_mobike = mobike, + .aggressive = aggressive, .dpd = dpd, - .virtual_ip = virtual_ip, - .pool = strdupnull(pool), + .dpd_timeout = dpd_timeout, + .vips = linked_list_create(), + .pools = linked_list_create(), .local_auth = linked_list_create(), .remote_auth = linked_list_create(), .refcount = 1, diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index f644fb547..97089e1b0 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -23,6 +23,7 @@ #ifndef PEER_CFG_H_ #define PEER_CFG_H_ +typedef enum ike_version_t ike_version_t; typedef enum cert_policy_t cert_policy_t; typedef enum unique_policy_t unique_policy_t; typedef struct peer_cfg_t peer_cfg_t; @@ -34,10 +35,25 @@ typedef struct peer_cfg_t peer_cfg_t; #include #include #include -#include -#include #include +/** + * IKE version. + */ +enum ike_version_t { + /** any version */ + IKE_ANY = 0, + /** IKE version 1 */ + IKEV1 = 1, + /** IKE version 2 */ + IKEV2 = 2, +}; + +/** + * enum strings fro ike_version_t + */ +extern enum_name_t *ike_version_names; + /** * Certificate sending policy. This is also used for certificate * requests when using this definition for the other peer. If @@ -65,11 +81,13 @@ extern enum_name_t *cert_policy_names; * Uniqueness of an IKE_SA, used to drop multiple connections with one peer. */ enum unique_policy_t { - /** do not check for client uniqueness */ + /** never check for client uniqueness */ + UNIQUE_NEVER, + /** only check for client uniqueness when receiving an INITIAL_CONTACT */ UNIQUE_NO, - /** replace unique IKE_SAs if new ones get established */ + /** replace existing IKE_SAs when new ones get established by a client */ UNIQUE_REPLACE, - /** keep existing IKE_SAs, close the new ones on connection attept */ + /** keep existing IKE_SAs, close the new ones on connection attempt */ UNIQUE_KEEP, }; @@ -130,7 +148,7 @@ struct peer_cfg_t { * * @return IKE major version */ - u_int (*get_ike_version)(peer_cfg_t *this); + ike_version_t (*get_ike_version)(peer_cfg_t *this); /** * Get the IKE config to use for initiaton. @@ -165,13 +183,13 @@ struct peer_cfg_t { * * @param my_ts TS for local side * @param other_ts TS for remote side - * @param my_host host to narrow down dynamic TS for local side - * @param other_host host to narrow down dynamic TS for remote side + * @param my_hosts hosts to narrow down dynamic TS for local side + * @param other_hosts hosts to narrow down dynamic TS for remote side * @return selected CHILD config, or NULL if no match found */ - child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, linked_list_t *my_ts, - linked_list_t *other_ts, host_t *my_host, - host_t *other_host); + child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, + linked_list_t *my_ts, linked_list_t *other_ts, + linked_list_t *my_hosts, linked_list_t *other_hosts); /** * Add an authentication config to the peer configuration. @@ -211,18 +229,20 @@ struct peer_cfg_t { u_int32_t (*get_keyingtries) (peer_cfg_t *this); /** - * Get a time to start rekeying (is randomized with jitter). + * Get a time to start rekeying. * + * @param jitter remove a jitter value to randomize time * @return time in s when to start rekeying, 0 disables rekeying */ - u_int32_t (*get_rekey_time)(peer_cfg_t *this); + u_int32_t (*get_rekey_time)(peer_cfg_t *this, bool jitter); /** - * Get a time to start reauthentication (is randomized with jitter). + * Get a time to start reauthentication. * + * @param jitter remove a jitter value to randomize time * @return time in s when to start reauthentication, 0 disables it */ - u_int32_t (*get_reauth_time)(peer_cfg_t *this); + u_int32_t (*get_reauth_time)(peer_cfg_t *this, bool jitter); /** * Get the timeout of a rekeying/reauthenticating SA. @@ -238,6 +258,13 @@ struct peer_cfg_t { */ bool (*use_mobike) (peer_cfg_t *this); + /** + * Use/Accept aggressive mode with IKEv1?. + * + * @return TRUE to use aggressive mode + */ + bool (*use_aggressive)(peer_cfg_t *this); + /** * Get the DPD check interval. * @@ -246,23 +273,41 @@ struct peer_cfg_t { u_int32_t (*get_dpd) (peer_cfg_t *this); /** - * Get a virtual IP for the local peer. + * Get the DPD timeout interval (IKEv1 only) * - * If no virtual IP should be used, NULL is returned. %any means to request - * a virtual IP using configuration payloads. A specific address is also - * used for a request and may be changed by the server. + * @return dpd_timeout in seconds + */ + u_int32_t (*get_dpd_timeout) (peer_cfg_t *this); + + /** + * Add a virtual IP to request as initiator. + * + * @param vip virtual IP to request, may be %any or %any6 + */ + void (*add_virtual_ip)(peer_cfg_t *this, host_t *vip); + + /** + * Create an enumerator over virtual IPs to request. + * + * The returned enumerator enumerates over IPs added with add_virtual_ip(). + * + * @return enumerator over host_t* + */ + enumerator_t* (*create_virtual_ip_enumerator)(peer_cfg_t *this); + + /** + * Add a pool name this configuration uses to select virtual IPs. * - * @param suggestion NULL, %any or specific - * @return virtual IP, %any or NULL + * @param name pool name to use for virtual IP lookup */ - host_t* (*get_virtual_ip) (peer_cfg_t *this); + void (*add_pool)(peer_cfg_t *this, char *name); /** - * Get the name of the pool to acquire configuration attributes from. + * Create an enumerator over pool names of this config. * - * @return pool name, NULL if none defined + * @return enumerator over char* */ - char* (*get_pool)(peer_cfg_t *this); + enumerator_t* (*create_pool_enumerator)(peer_cfg_t *this); #ifdef ME /** @@ -339,20 +384,21 @@ struct peer_cfg_t { * @param jitter_time timerange to randomly subtract from rekey/reauth time * @param over_time maximum overtime before closing a rekeying/reauth SA * @param mobike use MOBIKE (RFC4555) if peer supports it + * @param aggressive use/accept aggressive mode with IKEv1 * @param dpd DPD check interval, 0 to disable - * @param virtual_ip virtual IP for local host, or NULL - * @param pool pool name to get configuration attributes from, or NULL + * @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies * @param mediation TRUE if this is a mediation connection * @param mediated_by peer_cfg_t of the mediation connection to mediate through * @param peer_id ID that identifies our peer at the mediation server * @return peer_cfg_t object */ -peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, - cert_policy_t cert_policy, unique_policy_t unique, - u_int32_t keyingtries, u_int32_t rekey_time, - u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, u_int32_t dpd, - host_t *virtual_ip, char *pool, +peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version, + ike_cfg_t *ike_cfg, cert_policy_t cert_policy, + unique_policy_t unique, u_int32_t keyingtries, + u_int32_t rekey_time, u_int32_t reauth_time, + u_int32_t jitter_time, u_int32_t over_time, + bool mobike, bool aggressive, u_int32_t dpd, + u_int32_t dpd_timeout, bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id); diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index d3c60a469..43b467f46 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2012 Tobias Brunner * Copyright (C) 2006-2010 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -21,18 +21,18 @@ #include #include #include -#include + #include #include #include #include -#include -ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP, +ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP, "PROTO_NONE", "IKE", "AH", "ESP", + "IPCOMP", ); typedef struct private_proposal_t private_proposal_t; @@ -559,14 +559,15 @@ static void check_proposal(private_proposal_t *this) /** * add a algorithm identified by a string to the proposal. */ -static status_t add_string_algo(private_proposal_t *this, chunk_t alg) +static bool add_string_algo(private_proposal_t *this, const char *alg) { - const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len); + const proposal_token_t *token; + token = lib->proposal->get_token(lib->proposal, alg); if (token == NULL) { - DBG1(DBG_CFG, "algorithm '%.*s' not recognized", alg.len, alg.ptr); - return FAILED; + DBG1(DBG_CFG, "algorithm '%s' not recognized", alg); + return FALSE; } add_algorithm(this, token->type, token->algorithm, token->keysize); @@ -609,13 +610,13 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); } } - return SUCCESS; + return TRUE; } /** * print all algorithms of a kind to buffer */ -static int print_alg(private_proposal_t *this, char **dst, size_t *len, +static int print_alg(private_proposal_t *this, printf_hook_data_t *data, u_int kind, void *names, bool *first) { enumerator_t *enumerator; @@ -627,16 +628,16 @@ static int print_alg(private_proposal_t *this, char **dst, size_t *len, { if (*first) { - written += print_in_hook(*dst, *len, "%N", names, alg); + written += print_in_hook(data, "%N", names, alg); *first = FALSE; } else { - written += print_in_hook(*dst, *len, "/%N", names, alg); + written += print_in_hook(data, "/%N", names, alg); } if (size) { - written += print_in_hook(*dst, *len, "_%u", size); + written += print_in_hook(data, "_%u", size); } } enumerator->destroy(enumerator); @@ -646,7 +647,7 @@ static int print_alg(private_proposal_t *this, char **dst, size_t *len, /** * Described in header. */ -int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec, +int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, const void *const *args) { private_proposal_t *this = *((private_proposal_t**)(args[0])); @@ -657,7 +658,7 @@ int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec, if (this == NULL) { - return print_in_hook(dst, len, "(null)"); + return print_in_hook(data, "(null)"); } if (spec->hash) @@ -667,28 +668,28 @@ int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec, { /* call recursivly */ if (first) { - written += print_in_hook(dst, len, "%P", this); + written += print_in_hook(data, "%P", this); first = FALSE; } else { - written += print_in_hook(dst, len, ", %P", this); + written += print_in_hook(data, ", %P", this); } } enumerator->destroy(enumerator); return written; } - written = print_in_hook(dst, len, "%N:", protocol_id_names, this->protocol); - written += print_alg(this, &dst, &len, ENCRYPTION_ALGORITHM, + written = print_in_hook(data, "%N:", protocol_id_names, this->protocol); + written += print_alg(this, data, ENCRYPTION_ALGORITHM, encryption_algorithm_names, &first); - written += print_alg(this, &dst, &len, INTEGRITY_ALGORITHM, + written += print_alg(this, data, INTEGRITY_ALGORITHM, integrity_algorithm_names, &first); - written += print_alg(this, &dst, &len, PSEUDO_RANDOM_FUNCTION, + written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION, pseudo_random_function_names, &first); - written += print_alg(this, &dst, &len, DIFFIE_HELLMAN_GROUP, + written += print_alg(this, data, DIFFIE_HELLMAN_GROUP, diffie_hellman_group_names, &first); - written += print_alg(this, &dst, &len, EXTENDED_SEQUENCE_NUMBERS, + written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS, extended_sequence_numbers_names, &first); return written; } @@ -840,6 +841,7 @@ static void proposal_add_supported_ike(private_proposal_t *this) case MODP_1024_BIT: case MODP_1536_BIT: case MODP_2048_BIT: + case MODP_3072_BIT: case MODP_4096_BIT: case MODP_8192_BIT: case ECP_256_BIT: @@ -899,28 +901,27 @@ proposal_t *proposal_create_default(protocol_id_t protocol) */ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs) { - private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0); - chunk_t string = {(void*)algs, strlen(algs)}; - chunk_t alg; - status_t status = SUCCESS; + private_proposal_t *this; + enumerator_t *enumerator; + bool failed = TRUE; + char *alg; - eat_whitespace(&string); - if (string.len < 1) - { - destroy(this); - return NULL; - } + this = (private_proposal_t*)proposal_create(protocol, 0); /* get all tokens, separated by '-' */ - while (extract_token(&alg, '-', &string)) - { - status |= add_string_algo(this, alg); - } - if (string.len) + enumerator = enumerator_create_token(algs, "-", " "); + while (enumerator->enumerate(enumerator, &alg)) { - status |= add_string_algo(this, string); + if (!add_string_algo(this, alg)) + { + failed = TRUE; + break; + } + failed = FALSE; } - if (status != SUCCESS) + enumerator->destroy(enumerator); + + if (failed) { destroy(this); return NULL; diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h index 8f54d7e6e..33abf006c 100644 --- a/src/libcharon/config/proposal.h +++ b/src/libcharon/config/proposal.h @@ -43,6 +43,7 @@ enum protocol_id_t { PROTO_IKE = 1, PROTO_AH = 2, PROTO_ESP = 3, + PROTO_IPCOMP = 4, /* IKEv1 only */ }; /** @@ -215,7 +216,7 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs * With the #-specifier, arguments are: * linked_list_t *list containing proposal_t* */ -int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec, +int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, const void *const *args); #endif /** PROPOSAL_H_ @}*/ -- cgit v1.2.3