diff --git a/src/charon/control/interface_manager.c b/src/charon/control/interface_manager.c index c14903c7d..4d5aa2ea6 100644 --- a/src/charon/control/interface_manager.c +++ b/src/charon/control/interface_manager.c @@ -171,14 +171,11 @@ static bool initiate_listener(interface_bus_listener_t *this, signal_t signal, static status_t initiate_execute(interface_job_t *job) { ike_sa_t *ike_sa; - ike_cfg_t *ike_cfg; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, - ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg), - peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg)); + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); listener->ike_sa = ike_sa; if (ike_sa->get_peer_cfg(ike_sa) == NULL) @@ -435,15 +432,11 @@ static bool route_listener(interface_bus_listener_t *this, signal_t signal, static status_t route_execute(interface_job_t *job) { ike_sa_t *ike_sa; - ike_cfg_t *ike_cfg; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - - ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, - ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg), - peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg)); + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); listener->ike_sa = ike_sa; if (ike_sa->get_peer_cfg(ike_sa) == NULL) diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index b51d53ebd..3b4b246bd 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -535,6 +535,24 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) iterator = charon->backends->create_iterator(charon->backends); while (iterator->iterate(iterator, (void**)&peer_cfg)) { + host_t *my_vip_conf, *other_vip_conf; + bool my_vip_equals = FALSE, other_vip_equals = FALSE; + + my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg); + if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) || + (!my_vip_conf && !my_vip)) + { + my_vip_equals = TRUE; + } + DESTROY_IF(my_vip_conf); + other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL); + if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) || + (!other_vip_conf && !other_vip)) + { + other_vip_equals = TRUE; + } + DESTROY_IF(other_vip_conf); + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg)) && other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg)) @@ -545,7 +563,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type - && vendor == msg->add_conn.eap_vendor) + && vendor == msg->add_conn.eap_vendor + && my_vip_equals && other_vip_equals) { DBG1(DBG_CFG, "reusing existing configuration '%s'", peer_cfg->get_name(peer_cfg)); diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 5014ea0e2..5e7f78af0 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -483,16 +483,23 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, } /** - * Implementation of of ike_sa_manager.checkout_by_peer. + * Implementation of of ike_sa_manager.checkout_by_config. */ -static ike_sa_t* checkout_by_peer(private_ike_sa_manager_t *this, - host_t *my_host, host_t *other_host, - identification_t *my_id, - identification_t *other_id) +static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, + peer_cfg_t *peer_cfg) { iterator_t *iterator; entry_t *entry; ike_sa_t *ike_sa = NULL; + identification_t *my_id, *other_id; + host_t *my_host, *other_host; + ike_cfg_t *ike_cfg; + + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + my_host = ike_cfg->get_my_host(ike_cfg); + other_host = ike_cfg->get_other_host(ike_cfg); + my_id = peer_cfg->get_my_id(peer_cfg); + other_id = peer_cfg->get_other_id(peer_cfg); pthread_mutex_lock(&(this->mutex)); @@ -535,7 +542,9 @@ static ike_sa_t* checkout_by_peer(private_ike_sa_manager_t *this, (other_host->is_anyaddr(other_host) || other_host->ip_equals(other_host, found_other_host)) && found_my_id->matches(found_my_id, my_id, &wc) && - found_other_id->matches(found_other_id, other_id, &wc)) + found_other_id->matches(found_other_id, other_id, &wc) && + streq(peer_cfg->get_name(peer_cfg), + entry->ike_sa->get_name(entry->ike_sa))) { /* looks good, we take this one */ DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]", @@ -902,7 +911,7 @@ ike_sa_manager_t *ike_sa_manager_create() this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout; this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new; this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message; - this->public.checkout_by_peer = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_peer; + this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config; this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id; this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name; this->public.create_iterator = (iterator_t*(*)(ike_sa_manager_t*))create_iterator; diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h index 1125e5d16..a73a106ba 100644 --- a/src/charon/sa/ike_sa_manager.h +++ b/src/charon/sa/ike_sa_manager.h @@ -29,6 +29,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t; #include #include #include +#include /** * @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. @@ -94,25 +95,21 @@ struct ike_sa_manager_t { ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message); /** - * @brief Checkout an existing IKE_SA by hosts and identifications. + * @brief Checkout an IKE_SA for initiation by a peer_config. * - * Allows the lookup of an IKE_SA by user IDs and hosts. It returns the - * first found occurence, if there are multiple candidates. Supplied IDs - * may contain wildcards, hosts may be %any. + * To initiate, a CHILD_SA may be established within an existing IKE_SA. + * This call checks for an existing IKE_SA by comparing the configuration. + * If the CHILD_SA can be created in an existing IKE_SA, the matching SA + * is returned. * If no IKE_SA is found, a new one is created. This is also the case when * the found IKE_SA is in the DELETING state. * * @param this the manager object - * @param my_host address of our host - * @param other_id address of remote host - * @param my_id ID used by us - * @param other_id ID used by remote + * @param peer_cfg configuration used to find an existing IKE_SA * @return checked out/created IKE_SA */ - ike_sa_t* (*checkout_by_peer) (ike_sa_manager_t* this, - host_t *my_host, host_t* other_host, - identification_t *my_id, - identification_t *other_id); + ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this, + peer_cfg_t *peer_cfg); /** * @brief Check out an IKE_SA a unique ID.