peer_cfg lookup takes peer addresses into account
This commit is contained in:
@@ -48,6 +48,16 @@ struct private_backend_manager_t {
|
||||
mutex_t *mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* match of an ike_cfg
|
||||
*/
|
||||
typedef enum ike_cfg_match_t {
|
||||
MATCH_NONE = 0x00,
|
||||
MATCH_ANY = 0x01,
|
||||
MATCH_ME = 0x04,
|
||||
MATCH_OTHER = 0x08,
|
||||
} ike_cfg_match_t;
|
||||
|
||||
/**
|
||||
* data to pass nested IKE enumerator
|
||||
*/
|
||||
@@ -107,6 +117,48 @@ static enumerator_t *peer_enum_create_all(backend_t *backend)
|
||||
return backend->create_peer_cfg_enumerator(backend, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a match of a candidate ike_cfg for two hosts
|
||||
*/
|
||||
static ike_cfg_match_t get_match(ike_cfg_t *cand, host_t *me, host_t *other)
|
||||
{
|
||||
host_t *me_cand, *other_cand;
|
||||
ike_cfg_match_t match = MATCH_NONE;
|
||||
|
||||
me_cand = host_create_from_dns(cand->get_my_addr(cand),
|
||||
me->get_family(me), 0);
|
||||
if (!me_cand)
|
||||
{
|
||||
return MATCH_NONE;
|
||||
}
|
||||
if (me_cand->ip_equals(me_cand, me))
|
||||
{
|
||||
match += MATCH_ME;
|
||||
}
|
||||
else if (me_cand->is_anyaddr(me_cand))
|
||||
{
|
||||
match += MATCH_ANY;
|
||||
}
|
||||
me_cand->destroy(me_cand);
|
||||
|
||||
other_cand = host_create_from_dns(cand->get_other_addr(cand),
|
||||
other->get_family(other), 0);
|
||||
if (!other_cand)
|
||||
{
|
||||
return MATCH_NONE;
|
||||
}
|
||||
if (other_cand->ip_equals(other_cand, other))
|
||||
{
|
||||
match += MATCH_OTHER;
|
||||
}
|
||||
else if (other_cand->is_anyaddr(other_cand))
|
||||
{
|
||||
match += MATCH_ANY;
|
||||
}
|
||||
other_cand->destroy(other_cand);
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements backend_manager_t.get_ike_cfg.
|
||||
*/
|
||||
@@ -115,14 +167,8 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
|
||||
{
|
||||
ike_cfg_t *current, *found = NULL;
|
||||
enumerator_t *enumerator;
|
||||
host_t *my_candidate, *other_candidate;
|
||||
ike_cfg_match_t match, best = MATCH_ANY;
|
||||
ike_data_t *data;
|
||||
enum {
|
||||
MATCH_NONE = 0x00,
|
||||
MATCH_ANY = 0x01,
|
||||
MATCH_ME = 0x04,
|
||||
MATCH_OTHER = 0x08,
|
||||
} prio, best = MATCH_ANY;
|
||||
|
||||
data = malloc_thing(ike_data_t);
|
||||
data->this = this;
|
||||
@@ -137,51 +183,20 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
|
||||
(void*)ike_enum_create, data, (void*)ike_enum_destroy);
|
||||
while (enumerator->enumerate(enumerator, (void**)¤t))
|
||||
{
|
||||
prio = MATCH_NONE;
|
||||
|
||||
my_candidate = host_create_from_dns(current->get_my_addr(current),
|
||||
me->get_family(me), 0);
|
||||
if (!my_candidate)
|
||||
match = get_match(current, me, other);
|
||||
|
||||
if (match > MATCH_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (my_candidate->ip_equals(my_candidate, me))
|
||||
{
|
||||
prio += MATCH_ME;
|
||||
}
|
||||
else if (my_candidate->is_anyaddr(my_candidate))
|
||||
{
|
||||
prio += MATCH_ANY;
|
||||
}
|
||||
my_candidate->destroy(my_candidate);
|
||||
|
||||
other_candidate = host_create_from_dns(current->get_other_addr(current),
|
||||
other->get_family(other), 0);
|
||||
if (!other_candidate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (other_candidate->ip_equals(other_candidate, other))
|
||||
{
|
||||
prio += MATCH_OTHER;
|
||||
}
|
||||
else if (other_candidate->is_anyaddr(other_candidate))
|
||||
{
|
||||
prio += MATCH_ANY;
|
||||
}
|
||||
other_candidate->destroy(other_candidate);
|
||||
|
||||
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
|
||||
current->get_my_addr(current), current->get_other_addr(current),
|
||||
prio);
|
||||
|
||||
/* we require at least two MATCH_ANY */
|
||||
if (prio > best)
|
||||
{
|
||||
best = prio;
|
||||
DESTROY_IF(found);
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
|
||||
current->get_my_addr(current), current->get_other_addr(current),
|
||||
match);
|
||||
if (match > best)
|
||||
{
|
||||
best = match;
|
||||
DESTROY_IF(found);
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
@@ -202,22 +217,22 @@ static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this)
|
||||
/**
|
||||
* implements backend_manager_t.get_peer_cfg.
|
||||
*/
|
||||
static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this,
|
||||
identification_t *me, identification_t *other,
|
||||
auth_info_t *auth)
|
||||
static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me,
|
||||
host_t *other, identification_t *my_id,
|
||||
identification_t *other_id, auth_info_t *auth)
|
||||
{
|
||||
peer_cfg_t *current, *found = NULL;
|
||||
enumerator_t *enumerator;
|
||||
identification_t *my_candidate, *other_candidate;
|
||||
id_match_t best = ID_MATCH_NONE;
|
||||
id_match_t best_peer = ID_MATCH_NONE;
|
||||
ike_cfg_match_t best_ike = MATCH_NONE;
|
||||
peer_data_t *data;
|
||||
|
||||
DBG2(DBG_CFG, "looking for a config for %D...%D", me, other);
|
||||
DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
|
||||
|
||||
data = malloc_thing(peer_data_t);
|
||||
data->this = this;
|
||||
data->me = me;
|
||||
data->other = other;
|
||||
data->me = my_id;
|
||||
data->other = other_id;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
enumerator = enumerator_create_nested(
|
||||
@@ -225,34 +240,36 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this,
|
||||
(void*)peer_enum_create, data, (void*)peer_enum_destroy);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
id_match_t m1, m2, sum;
|
||||
identification_t *my_cand, *other_cand;
|
||||
id_match_t m1, m2, match_peer;
|
||||
ike_cfg_match_t match_ike;
|
||||
|
||||
my_candidate = current->get_my_id(current);
|
||||
other_candidate = current->get_other_id(current);
|
||||
my_cand = current->get_my_id(current);
|
||||
other_cand = current->get_other_id(current);
|
||||
|
||||
/* own ID may have wildcards in both, config and request (missing IDr) */
|
||||
m1 = my_candidate->matches(my_candidate, me);
|
||||
m1 = my_cand->matches(my_cand, my_id);
|
||||
if (!m1)
|
||||
{
|
||||
m1 = me->matches(me, my_candidate);
|
||||
m1 = my_id->matches(my_id, my_cand);
|
||||
}
|
||||
m2 = other->matches(other, other_candidate);
|
||||
sum = m1 + m2;
|
||||
m2 = other_id->matches(other_id, other_cand);
|
||||
|
||||
if (m1 && m2)
|
||||
match_peer = m1 + m2;
|
||||
match_ike = get_match(current->get_ike_cfg(current), me, other);
|
||||
|
||||
if (m1 && m2 && match_ike > MATCH_NONE &&
|
||||
auth->complies(auth, current->get_auth(current)))
|
||||
{
|
||||
if (auth->complies(auth, current->get_auth(current)))
|
||||
DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d",
|
||||
current->get_name(current), my_cand, other_cand, match_peer);
|
||||
if (match_peer >= best_peer && match_ike > best_ike)
|
||||
{
|
||||
DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d",
|
||||
current->get_name(current), my_candidate,
|
||||
other_candidate, sum);
|
||||
if (sum > best)
|
||||
{
|
||||
DESTROY_IF(found);
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
best = sum;
|
||||
}
|
||||
DESTROY_IF(found);
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
best_peer = match_peer;
|
||||
best_ike = match_ike;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,7 +277,7 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this,
|
||||
{
|
||||
DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d",
|
||||
found->get_name(found), found->get_my_id(found),
|
||||
found->get_other_id(found), best);
|
||||
found->get_other_id(found), best_peer);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->mutex->unlock(this->mutex);
|
||||
@@ -325,7 +342,7 @@ backend_manager_t *backend_manager_create()
|
||||
private_backend_manager_t *this = malloc_thing(private_backend_manager_t);
|
||||
|
||||
this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg;
|
||||
this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg;
|
||||
this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg;
|
||||
this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name;
|
||||
this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*))create_peer_cfg_enumerator;
|
||||
this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend;
|
||||
|
||||
@@ -66,12 +66,15 @@ struct backend_manager_t {
|
||||
/**
|
||||
* Get a peer_config identified by two IDs and authorization info.
|
||||
*
|
||||
* @param me own address
|
||||
* @param other peer address
|
||||
* @param my_id own ID
|
||||
* @param other_id peer ID
|
||||
* @param auth_info authorization info
|
||||
* @return matching peer_config, or NULL if none found
|
||||
*/
|
||||
peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, identification_t *my_id,
|
||||
peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, host_t *me,
|
||||
host_t *other, identification_t *my_id,
|
||||
identification_t *other_id, auth_info_t *auth);
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <sa/authenticators/eap_authenticator.h>
|
||||
|
||||
|
||||
|
||||
typedef struct private_ike_auth_t private_ike_auth_t;
|
||||
|
||||
/**
|
||||
@@ -586,6 +585,8 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
|
||||
}
|
||||
|
||||
config = charon->backends->get_peer_cfg(charon->backends,
|
||||
this->ike_sa->get_my_host(this->ike_sa),
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->ike_sa->get_my_id(this->ike_sa),
|
||||
this->ike_sa->get_other_id(this->ike_sa),
|
||||
this->ike_sa->get_other_auth(this->ike_sa));
|
||||
|
||||
Reference in New Issue
Block a user