diff options
author | Martin Willi <martin@strongswan.org> | 2008-06-06 15:05:54 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-06-06 15:05:54 +0000 |
commit | 5a22a02156816fc9f56ca56c70fbfda6574b285d (patch) | |
tree | 061ab063820d3db0272c55083ff26ac6d170ce51 | |
parent | 1e9c46f13daced3199953f4d1758c7e03c935083 (diff) | |
download | strongswan-5a22a02156816fc9f56ca56c70fbfda6574b285d.tar.bz2 strongswan-5a22a02156816fc9f56ca56c70fbfda6574b285d.tar.xz |
DNS resolving of ike_cfg hosts dynamically on demand
-rw-r--r-- | src/charon/config/backend_manager.c | 22 | ||||
-rw-r--r-- | src/charon/config/ike_cfg.c | 35 | ||||
-rw-r--r-- | src/charon/config/ike_cfg.h | 14 | ||||
-rw-r--r-- | src/charon/plugins/medcli/medcli_config.c | 13 | ||||
-rw-r--r-- | src/charon/plugins/medsrv/medsrv_config.c | 3 | ||||
-rw-r--r-- | src/charon/plugins/sql/sql_config.c | 27 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_config.c | 104 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_list.c | 6 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 40 | ||||
-rw-r--r-- | src/charon/sa/ike_sa_manager.c | 98 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_init.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/host.c | 53 | ||||
-rw-r--r-- | src/libstrongswan/utils/host.h | 10 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 2 |
14 files changed, 238 insertions, 191 deletions
diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c index 7b2ddca90..41c26e1af 100644 --- a/src/charon/config/backend_manager.c +++ b/src/charon/config/backend_manager.c @@ -138,9 +138,13 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, while (enumerator->enumerate(enumerator, (void**)¤t)) { prio = MATCH_NONE; - my_candidate = current->get_my_host(current); - other_candidate = current->get_other_host(current); + my_candidate = host_create_from_dns(current->get_my_addr(current), + me->get_family(me), 0); + if (!my_candidate) + { + continue; + } if (my_candidate->ip_equals(my_candidate, me)) { prio += MATCH_ME; @@ -149,6 +153,14 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, { 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; @@ -157,9 +169,11 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, { prio += MATCH_ANY; } + other_candidate->destroy(other_candidate); - DBG2(DBG_CFG, " candidate: %H...%H, prio %d", - my_candidate, other_candidate, prio); + 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) diff --git a/src/charon/config/ike_cfg.c b/src/charon/config/ike_cfg.c index b92cb98c6..36f84147d 100644 --- a/src/charon/config/ike_cfg.c +++ b/src/charon/config/ike_cfg.c @@ -41,12 +41,12 @@ struct private_ike_cfg_t { /** * Address of local host */ - host_t *my_host; + char *me; /** * Address of remote host */ - host_t *other_host; + char *other; /** * should we send a certificate request? @@ -81,19 +81,19 @@ static bool force_encap_meth(private_ike_cfg_t *this) } /** - * Implementation of ike_cfg_t.get_my_host. + * Implementation of ike_cfg_t.get_my_addr. */ -static host_t *get_my_host (private_ike_cfg_t *this) +static char *get_my_addr(private_ike_cfg_t *this) { - return this->my_host; + return this->me; } /** - * Implementation of ike_cfg_t.get_other_host. + * Implementation of ike_cfg_t.get_other_addr. */ -static host_t *get_other_host (private_ike_cfg_t *this) +static char *get_other_addr(private_ike_cfg_t *this) { - return this->other_host; + return this->other; } /** @@ -219,8 +219,8 @@ static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other) return (eq && this->certreq == other->certreq && this->force_encap == other->force_encap && - this->my_host->equals(this->my_host, other->my_host) && - this->other_host->equals(this->other_host, other->other_host)); + streq(this->me, other->me) && + streq(this->other, other->other)); } /** @@ -241,8 +241,8 @@ static void destroy(private_ike_cfg_t *this) { this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - this->my_host->destroy(this->my_host); - this->other_host->destroy(this->other_host); + free(this->me); + free(this->other); free(this); } } @@ -251,15 +251,15 @@ static void destroy(private_ike_cfg_t *this) * Described in header. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host) + char *me, char *other) { private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t); /* public functions */ this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq; this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth; - this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host; - this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host; + this->public.get_my_addr = (char*(*)(ike_cfg_t*))get_my_addr; + this->public.get_other_addr = (char*(*)(ike_cfg_t*))get_other_addr; this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal; this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals; this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal; @@ -272,9 +272,8 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, this->refcount = 1; this->certreq = certreq; this->force_encap = force_encap; - this->my_host = my_host; - this->other_host = other_host; - + this->me = strdup(me); + this->other = strdup(other); this->proposals = linked_list_create(); return &this->public; diff --git a/src/charon/config/ike_cfg.h b/src/charon/config/ike_cfg.h index d1cae000b..e84246bac 100644 --- a/src/charon/config/ike_cfg.h +++ b/src/charon/config/ike_cfg.h @@ -43,16 +43,16 @@ struct ike_cfg_t { /** * Get own address. * - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_my_host) (ike_cfg_t *this); + char* (*get_my_addr) (ike_cfg_t *this); /** * Get peers address. * - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_other_host) (ike_cfg_t *this); + char* (*get_other_addr) (ike_cfg_t *this); /** * Adds a proposal to the list. @@ -136,11 +136,11 @@ struct ike_cfg_t { * @param name ike_cfg identifier * @param certreq TRUE to send a certificate request * @param force_encap enforce UDP encapsulation by faking NATD notify - * @param my_host host_t representing local address - * @param other_host host_t representing remote address + * @param me address/DNS name of local peer + * @param other address/DNS name of remote peer * @return ike_cfg_t object. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host); + char *me, char *other); #endif /* IKE_CFG_H_ @} */ diff --git a/src/charon/plugins/medcli/medcli_config.c b/src/charon/plugins/medcli/medcli_config.c index dff6c3dec..8a56bfefe 100644 --- a/src/charon/plugins/medcli/medcli_config.c +++ b/src/charon/plugins/medcli/medcli_config.c @@ -100,7 +100,6 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam child_cfg_t *child_cfg; chunk_t me, other; char *address, *local_net, *remote_net; - host_t *med; /* query mediation server config: * - build ike_cfg/peer_cfg for mediation connection on-the-fly @@ -114,14 +113,7 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam DESTROY_IF(e); return NULL; } - med = host_create_from_string(address, 500); - if (!med) - { - e->destroy(e); - return NULL; - } - ike_cfg = ike_cfg_create(FALSE, FALSE, - host_create_from_string("0.0.0.0", 500), med); + ike_cfg = ike_cfg_create(FALSE, FALSE, "0.0.0.0", address); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); DBG1(DBG_CFG, "mediation server id: %B", &other); med_cfg = peer_cfg_create( @@ -313,8 +305,7 @@ medcli_config_t *medcli_config_create(database_t *db) this->rekey = lib->settings->get_int(lib->settings, "medclient.rekey", 20) * 60; this->dpd = lib->settings->get_int(lib->settings, "medclient.dpd", 300); - this->ike = ike_cfg_create(FALSE, FALSE, host_create_any(AF_INET), - host_create_any(AF_INET)); + this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0"); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); return &this->public; diff --git a/src/charon/plugins/medsrv/medsrv_config.c b/src/charon/plugins/medsrv/medsrv_config.c index 8439c207b..04cb56930 100644 --- a/src/charon/plugins/medsrv/medsrv_config.c +++ b/src/charon/plugins/medsrv/medsrv_config.c @@ -139,8 +139,7 @@ medsrv_config_t *medsrv_config_create(database_t *db) this->rekey = lib->settings->get_int(lib->settings, "medmanager.rekey", 20) * 60; this->dpd = lib->settings->get_int(lib->settings, "medmanager.dpd", 300); - this->ike = ike_cfg_create(FALSE, FALSE, host_create_any(AF_INET), - host_create_any(AF_INET)); + this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0"); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); return &this->public; diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c index 06fd29850..7a2e96fe6 100644 --- a/src/charon/plugins/sql/sql_config.c +++ b/src/charon/plugins/sql/sql_config.c @@ -179,34 +179,9 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, while (e->enumerate(e, &certreq, &force_encap, &local, &remote)) { - host_t *me, *other; ike_cfg_t *ike_cfg; - me = host_create_from_string(local, 500); - if (!me) - { - continue; - } - if (my_host && !me->is_anyaddr(me) && - !me->ip_equals(me, my_host)) - { - me->destroy(me); - continue; - } - other = host_create_from_string(remote, 500); - if (!other) - { - me->destroy(me); - continue; - } - if (other_host && !other->is_anyaddr(other) && - !other->ip_equals(other, other_host)) - { - me->destroy(me); - other->destroy(other); - continue; - } - ike_cfg = ike_cfg_create(certreq, force_encap, me, other); + ike_cfg = ike_cfg_create(certreq, force_encap, local, remote); /* TODO: read proposal from db */ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); return ike_cfg; diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c index af196751e..0069191b5 100644 --- a/src/charon/plugins/stroke/stroke_config.c +++ b/src/charon/plugins/stroke/stroke_config.c @@ -139,20 +139,8 @@ static void ike_data_destroy(ike_data_t *data) */ static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out) { - ike_cfg_t *ike_cfg; - host_t *me, *other; - - ike_cfg = (*in)->get_ike_cfg(*in); - - me = ike_cfg->get_my_host(ike_cfg); - other = ike_cfg->get_other_host(ike_cfg); - if ((!data->me || me->is_anyaddr(me) || me->ip_equals(me, data->me)) && - (!data->other || other->is_anyaddr(other) || other->ip_equals(other, data->other))) - { - *out = ike_cfg; - return TRUE; - } - return FALSE; + *out = (*in)->get_ike_cfg(*in); + return TRUE; } /** @@ -296,58 +284,50 @@ static void add_proposals(private_stroke_config_t *this, char *string, */ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg) { - host_t *me = NULL, *other = NULL, *tmp; stroke_end_t tmp_end; ike_cfg_t *ike_cfg; char *interface; - - if (msg->add_conn.me.address) - { - me = host_create_from_string(msg->add_conn.me.address, IKEV2_UDP_PORT); - } - if (!me) - { - DBG1(DBG_CFG, "invalid left host: %s", msg->add_conn.me.address); - return NULL; - } - if (msg->add_conn.other.address) - { - other = host_create_from_string(msg->add_conn.other.address, IKEV2_UDP_PORT); - } - if (!other) - { - DBG1(DBG_CFG, "invalid right host: %s", msg->add_conn.other.address); - me->destroy(me); - return NULL; - } - interface = charon->kernel_interface->get_interface( - charon->kernel_interface, other); - if (interface) - { - DBG2(DBG_CFG, "left is other host, swapping ends"); - tmp = me; - me = other; - other = tmp; - tmp_end = msg->add_conn.me; - msg->add_conn.me = msg->add_conn.other; - msg->add_conn.other = tmp_end; - free(interface); - } - else + host_t *host; + + host = host_create_from_dns(msg->add_conn.other.address, 0, 0); + if (host) { interface = charon->kernel_interface->get_interface( - charon->kernel_interface, me); - if (!interface) + charon->kernel_interface, host); + host->destroy(host); + if (interface) { - DBG1(DBG_CFG, "left nor right host is our side, assuming left=local"); + DBG2(DBG_CFG, "left is other host, swapping ends"); + tmp_end = msg->add_conn.me; + msg->add_conn.me = msg->add_conn.other; + msg->add_conn.other = tmp_end; + free(interface); } else { - free(interface); + host = host_create_from_dns(msg->add_conn.me.address, 0, 0); + if (host) + { + interface = charon->kernel_interface->get_interface( + charon->kernel_interface, host); + host->destroy(host); + if (!interface) + { + DBG1(DBG_CFG, "left nor right host is our side, " + "assuming left=local"); + } + else + { + free(interface); + } + + } } } ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND, - msg->add_conn.force_encap, me, other); + msg->add_conn.force_encap, + msg->add_conn.me.address, + msg->add_conn.other.address); add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL); return ike_cfg; } @@ -485,8 +465,14 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, } else { - host_t* my_host = ike_cfg->get_my_host(ike_cfg); - vip = host_create_any(my_host->get_family(my_host)); + if (strchr(ike_cfg->get_my_addr(ike_cfg), ':')) + { + vip = host_create_any(AF_INET6); + } + else + { + vip = host_create_any(AF_INET); + } } } } @@ -777,9 +763,9 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg) else { /* add config to backend */ - DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]", msg->add_conn.name, - ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg), - ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg)); + 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)); 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_list.c b/src/charon/plugins/stroke/stroke_list.c index db9d829e1..4f0602498 100644 --- a/src/charon/plugins/stroke/stroke_list.c +++ b/src/charon/plugins/stroke/stroke_list.c @@ -229,9 +229,9 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo } ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg), - ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg), - ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(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)); /* TODO: list CAs and groups */ children = peer_cfg->create_child_cfg_enumerator(peer_cfg); while (children->enumerate(children, &child_cfg)) diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index e19b7be55..6dfc42ddc 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -410,18 +410,6 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); this->ike_cfg->get_ref(this->ike_cfg); } - - /* apply values, so we are ready to initate/acquire */ - if (this->my_host->is_anyaddr(this->my_host)) - { - host_t *me = this->ike_cfg->get_my_host(this->ike_cfg); - set_my_host(this, me->clone(me)); - } - if (this->other_host->is_anyaddr(this->other_host)) - { - host_t *other = this->ike_cfg->get_other_host(this->ike_cfg); - set_other_host(this, other->clone(other)); - } /* apply IDs if they are not already set */ if (this->my_id->contains_wildcards(this->my_id)) { @@ -1042,6 +1030,28 @@ static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *ot #endif /* ME */ /** + * Resolve DNS host in configuration + */ +static void resolve_hosts(private_ike_sa_t *this) +{ + host_t *host; + + host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg), 0, + IKEV2_UDP_PORT); + if (host) + { + set_my_host(this, host); + } + host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg), + this->my_host->get_family(this->my_host), + IKEV2_UDP_PORT); + if (host) + { + set_other_host(this, host); + } +} + +/** * Initiates a CHILD_SA using the appropriate reqid */ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid) @@ -1050,6 +1060,8 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c if (this->state == IKE_CREATED) { + resolve_hosts(this); + if (this->other_host->is_anyaddr(this->other_host) #ifdef ME && !this->peer_cfg->get_mediated_by(this->peer_cfg) @@ -2516,8 +2528,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) /* initialize private fields */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); this->child_sas = linked_list_create(); - this->my_host = host_create_any(AF_INET); - this->other_host = host_create_any(AF_INET); + this->my_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT); + this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT); this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty); this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty); this->extensions = 0; diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 5c84cf07d..d9983d85d 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -497,64 +497,70 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, 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); + my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0); + other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0); pthread_mutex_lock(&(this->mutex)); - enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); - while (enumerator->enumerate(enumerator, &entry)) + if (my_host && other_host) { - identification_t *found_my_id, *found_other_id; - host_t *found_my_host, *found_other_host; - - if (!wait_for_entry(this, entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { - continue; - } + identification_t *found_my_id, *found_other_id; + host_t *found_my_host, *found_other_host; - if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING) - { - /* skip IKE_SA which are not useable */ - continue; - } + if (!wait_for_entry(this, entry)) + { + continue; + } - found_my_id = entry->ike_sa->get_my_id(entry->ike_sa); - found_other_id = entry->ike_sa->get_other_id(entry->ike_sa); - found_my_host = entry->ike_sa->get_my_host(entry->ike_sa); - found_other_host = entry->ike_sa->get_other_host(entry->ike_sa); + if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING) + { + /* skip IKE_SA which are not useable */ + continue; + } - if (found_my_id->get_type(found_my_id) == ID_ANY && - found_other_id->get_type(found_other_id) == ID_ANY) - { - /* IKE_SA has no IDs yet, so we can't use it */ - continue; - } - DBG2(DBG_MGR, "candidate IKE_SA for \n\t%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]", - my_host, my_id, other_host, other_id, - found_my_host, found_my_id, found_other_host, found_other_id); - /* compare ID and hosts. Supplied ID may contain wildcards, and IP - * may be %any. */ - if ((my_host->is_anyaddr(my_host) || - my_host->ip_equals(my_host, found_my_host)) && - (other_host->is_anyaddr(other_host) || - other_host->ip_equals(other_host, found_other_host)) && - found_my_id->matches(found_my_id, my_id) && - found_other_id->matches(found_other_id, other_id) && - 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]", - my_host, my_id, other_host, other_id); - entry->checked_out = TRUE; - ike_sa = entry->ike_sa; - break; + found_my_id = entry->ike_sa->get_my_id(entry->ike_sa); + found_other_id = entry->ike_sa->get_other_id(entry->ike_sa); + found_my_host = entry->ike_sa->get_my_host(entry->ike_sa); + found_other_host = entry->ike_sa->get_other_host(entry->ike_sa); + + if (found_my_id->get_type(found_my_id) == ID_ANY && + found_other_id->get_type(found_other_id) == ID_ANY) + { + /* IKE_SA has no IDs yet, so we can't use it */ + continue; + } + DBG2(DBG_MGR, "candidate IKE_SA for \n\t" + "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]", + my_host, my_id, other_host, other_id, + found_my_host, found_my_id, found_other_host, found_other_id); + /* compare ID and hosts. Supplied ID may contain wildcards, and IP + * may be %any. */ + if ((my_host->is_anyaddr(my_host) || + my_host->ip_equals(my_host, found_my_host)) && + (other_host->is_anyaddr(other_host) || + other_host->ip_equals(other_host, found_other_host)) && + found_my_id->matches(found_my_id, my_id) && + found_other_id->matches(found_other_id, other_id) && + 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]", + my_host, my_id, other_host, other_id); + entry->checked_out = TRUE; + ike_sa = entry->ike_sa; + break; + } } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); + DESTROY_IF(my_host); + DESTROY_IF(other_host); if (!ike_sa) { diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index 8cb706a26..0bf8523c4 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -223,7 +223,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message) this->config = this->ike_sa->get_ike_cfg(this->ike_sa); SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H", this->ike_sa->get_name(this->ike_sa), - this->config->get_other_host(this->config)); + this->ike_sa->get_other_host(this->ike_sa)); this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); if (this->retry++ >= MAX_RETRIES) diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index a2fa57927..b60d532c7 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -18,11 +18,14 @@ * $Id$ */ +#define _GNU_SOURCE +#include <netdb.h> #include <string.h> #include <printf.h> #include "host.h" +#include <debug.h> typedef struct private_host_t private_host_t; @@ -451,6 +454,56 @@ host_t *host_create_from_string(char *string, u_int16_t port) /* * Described in header. */ +host_t *host_create_from_dns(char *string, int af, u_int16_t port) +{ + private_host_t *this; + struct hostent host, *ptr; + char buf[512]; + int err, ret; + + if (af) + { + ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err); + } + else + { + ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err); + } + if (ret != 0) + { + DBG1("resolving '%s' failed: %s", string, hstrerror(err)); + return NULL; + } + if (ptr == NULL) + { + DBG1("resolving '%s' failed", string); + } + this = host_create_empty(); + this->address.sa_family = host.h_addrtype; + switch (af) + { + case AF_INET: + memcpy(&this->address4.sin_addr.s_addr, + host.h_addr_list[0], host.h_length); + this->address4.sin_port = htons(port); + this->socklen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + memcpy(&this->address6.sin6_addr.s6_addr, + host.h_addr_list[0], host.h_length); + this->address6.sin6_port = htons(port); + this->socklen = sizeof(struct sockaddr_in6); + break; + default: + free(this); + return NULL; + } + return &this->public; +} + +/* + * Described in header. + */ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port) { private_host_t *this = host_create_empty(); diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h index fd2fe01b1..6a1d824c6 100644 --- a/src/libstrongswan/utils/host.h +++ b/src/libstrongswan/utils/host.h @@ -160,6 +160,16 @@ struct host_t { host_t *host_create_from_string(char *string, u_int16_t port); /** + * Constructor to create a host_t from a DNS name. + * + * @param string hostname to resolve + * @param family family to prefer, 0 for first match + * @param port port number + * @return host_t, NULL lookup failed + */ +host_t *host_create_from_dns(char *string, int family, u_int16_t port); + +/** * Constructor to create a host_t object from an address chunk * * @param family Address family, such as AF_INET or AF_INET6 diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 789c1496f..a28cac35d 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -250,6 +250,8 @@ char *whitelist[] = { "getprotobynumber", "getservbyport", "getservbyname", + "gethostbyname_r", + "gethostbyname2_r", "getpwnam_r", "getgrnam_r", "register_printf_function", |