diff options
Diffstat (limited to 'src/libcharon/config/backend_manager.c')
-rw-r--r-- | src/libcharon/config/backend_manager.c | 122 |
1 files changed, 77 insertions, 45 deletions
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c index a93457ea4..f47d5715a 100644 --- a/src/libcharon/config/backend_manager.c +++ b/src/libcharon/config/backend_manager.c @@ -18,7 +18,7 @@ #include <sys/types.h> #include <daemon.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <threading/rwlock.h> @@ -49,10 +49,16 @@ struct private_backend_manager_t { * match of an ike_cfg */ typedef enum ike_cfg_match_t { - MATCH_NONE = 0x00, - MATCH_ANY = 0x01, - MATCH_ME = 0x04, - MATCH_OTHER = 0x08, + /* doesn't match at all */ + MATCH_NONE = 0x00, + /* match for a %any host. For both hosts, hence skip 0x02 */ + MATCH_ANY = 0x01, + /* IKE version matches exactly (config is not for any version) */ + MATCH_VERSION = 0x04, + /* local identity matches */ + MATCH_ME = 0x08, + /* remote identity matches */ + MATCH_OTHER = 0x10, } ike_cfg_match_t; /** @@ -75,15 +81,24 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data) /** * get a match of a candidate ike_cfg for two hosts */ -static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) +static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other, + ike_version_t version) { 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 (cand->get_version(cand) != IKE_ANY && + version != cand->get_version(cand)) + { + return 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 +107,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 +125,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 +135,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; } @@ -135,21 +150,31 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_ANY; } + + if (match != MATCH_NONE && + cand->get_version(cand) != IKE_ANY) + { /* if we have a match, improve it if candidate version specified */ + match += MATCH_VERSION; + } return match; } METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, - private_backend_manager_t *this, host_t *me, host_t *other) + private_backend_manager_t *this, host_t *me, host_t *other, + ike_version_t version) { 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); @@ -159,13 +184,16 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, (void*)ike_enum_create, data, (void*)free); while (enumerator->enumerate(enumerator, (void**)¤t)) { - match = get_ike_match(current, me, other); - + match = get_ike_match(current, me, other, version); + DBG3(DBG_CFG, "ike config match: %d (%H %H %N)", + match, me, other, ike_version_names, version); 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 +207,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 +226,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,6 +256,10 @@ 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; } @@ -317,17 +356,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 +380,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(); @@ -351,28 +388,23 @@ 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; 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_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other, version); + DBG3(DBG_CFG, "ike config match: %d (%H %H %N)", + match_ike, me, other, ike_version_names, version); if (match_peer_me && match_peer_other && match_ike) { 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); + INIT(entry, + .match_peer = match_peer_me + match_peer_other, + .match_ike = match_ike, + .cfg = cfg->get_ref(cfg), + ); insert_sorted(entry, configs, helper); } } |