summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ike_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ike_sa.c')
-rw-r--r--src/libcharon/sa/ike_sa.c237
1 files changed, 136 insertions, 101 deletions
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 7536662ca..a4e4028ab 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -24,8 +24,8 @@
#include "ike_sa.h"
#include <library.h>
-#include <daemon.h>
#include <hydra.h>
+#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
#include <sa/task_manager.h>
@@ -470,8 +470,8 @@ METHOD(ike_sa_t, send_keepalive, void,
diff = 0;
}
job = send_keepalive_job_create(this->ike_sa_id);
- charon->scheduler->schedule_job(charon->scheduler, (job_t*)job,
- this->keepalive_interval - diff);
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
+ this->keepalive_interval - diff);
}
METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*,
@@ -605,7 +605,7 @@ METHOD(ike_sa_t, send_dpd, status_t,
}
/* recheck in "interval" seconds */
job = (job_t*)send_dpd_job_create(this->ike_sa_id);
- charon->scheduler->schedule_job(charon->scheduler, job, delay - diff);
+ lib->scheduler->schedule_job(lib->scheduler, job, delay - diff);
return SUCCESS;
}
@@ -644,7 +644,7 @@ METHOD(ike_sa_t, set_state, void,
{
this->stats[STAT_REKEY] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, FALSE);
- charon->scheduler->schedule_job(charon->scheduler, job, t);
+ lib->scheduler->schedule_job(lib->scheduler, job, t);
DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
}
t = this->peer_cfg->get_reauth_time(this->peer_cfg);
@@ -653,7 +653,7 @@ METHOD(ike_sa_t, set_state, void,
{
this->stats[STAT_REAUTH] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
- charon->scheduler->schedule_job(charon->scheduler, job, t);
+ lib->scheduler->schedule_job(lib->scheduler, job, t);
DBG1(DBG_IKE, "scheduling reauthentication in %ds", t);
}
t = this->peer_cfg->get_over_time(this->peer_cfg);
@@ -675,7 +675,7 @@ METHOD(ike_sa_t, set_state, void,
this->stats[STAT_DELETE] += t;
t = this->stats[STAT_DELETE] - this->stats[STAT_ESTABLISHED];
job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
- charon->scheduler->schedule_job(charon->scheduler, job, t);
+ lib->scheduler->schedule_job(lib->scheduler, job, t);
DBG1(DBG_IKE, "maximum IKE_SA lifetime %ds", t);
}
@@ -688,8 +688,8 @@ METHOD(ike_sa_t, set_state, void,
{
/* delete may fail if a packet gets lost, so set a timeout */
job_t *job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
- charon->scheduler->schedule_job(charon->scheduler, job,
- HALF_OPEN_IKE_SA_TIMEOUT);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ HALF_OPEN_IKE_SA_TIMEOUT);
break;
}
default:
@@ -730,14 +730,14 @@ METHOD(ike_sa_t, set_virtual_ip, void,
if (local)
{
DBG1(DBG_IKE, "installing new virtual IP %H", ip);
- if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
- this->my_host) == SUCCESS)
+ if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip,
+ this->my_host) == SUCCESS)
{
if (this->my_virtual_ip)
{
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
- charon->kernel_interface->del_ip(charon->kernel_interface,
- this->my_virtual_ip);
+ hydra->kernel_interface->del_ip(hydra->kernel_interface,
+ this->my_virtual_ip);
}
DESTROY_IF(this->my_virtual_ip);
this->my_virtual_ip = ip->clone(ip);
@@ -810,6 +810,20 @@ METHOD(ike_sa_t, get_pending_updates, u_int32_t,
return this->pending_updates;
}
+METHOD(ike_sa_t, float_ports, void,
+ private_ike_sa_t *this)
+{
+ /* do not switch if we have a custom port from MOBIKE/NAT */
+ if (this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT)
+ {
+ this->my_host->set_port(this->my_host, IKEV2_NATT_PORT);
+ }
+ if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT)
+ {
+ this->other_host->set_port(this->other_host, IKEV2_NATT_PORT);
+ }
+}
+
METHOD(ike_sa_t, update_hosts, void,
private_ike_sa_t *this, host_t *me, host_t *other)
{
@@ -843,10 +857,8 @@ METHOD(ike_sa_t, update_hosts, void,
if (!other->equals(other, this->other_host))
{
- /* update others adress if we are NOT NATed,
- * and allow port changes if we are NATed */
- if (!has_condition(this, COND_NAT_HERE) ||
- other->ip_equals(other, this->other_host))
+ /* update others adress if we are NOT NATed */
+ if (!has_condition(this, COND_NAT_HERE))
{
set_other_host(this, other->clone(other));
update = TRUE;
@@ -882,8 +894,7 @@ METHOD(ike_sa_t, generate_message, status_t,
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
return message->generate(message,
- this->keymat->get_crypter(this->keymat, FALSE),
- this->keymat->get_signer(this->keymat, FALSE), packet);
+ this->keymat->get_aead(this->keymat, FALSE), packet);
}
/**
@@ -1049,8 +1060,8 @@ static void resolve_hosts(private_ike_sa_t *this)
!this->other_host->is_anyaddr(this->other_host))
{
host->destroy(host);
- host = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, this->other_host, NULL);
+ host = hydra->kernel_interface->get_source_addr(
+ hydra->kernel_interface, this->other_host, NULL);
if (host)
{
host->set_port(host, this->ike_cfg->get_my_port(this->ike_cfg));
@@ -1150,7 +1161,7 @@ METHOD(ike_sa_t, initiate, status_t,
{
/* mediated connection, initiate mediation process */
job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id);
- charon->processor->queue_job(charon->processor, job);
+ lib->processor->queue_job(lib->processor, job);
return SUCCESS;
}
#endif /* ME */
@@ -1173,8 +1184,7 @@ METHOD(ike_sa_t, process_message, status_t,
is_request = message->get_request(message);
status = message->parse_body(message,
- this->keymat->get_crypter(this->keymat, TRUE),
- this->keymat->get_signer(this->keymat, TRUE));
+ this->keymat->get_aead(this->keymat, TRUE));
if (status != SUCCESS)
{
@@ -1229,15 +1239,12 @@ METHOD(ike_sa_t, process_message, status_t,
}
else
{
- host_t *me, *other;
-
- me = message->get_destination(message);
- other = message->get_source(message);
-
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_cfg == NULL)
{
job_t *job;
+ host_t *me = message->get_destination(message),
+ *other = message->get_source(message);
this->ike_cfg = charon->backends->get_ike_cfg(charon->backends,
me, other);
if (this->ike_cfg == NULL)
@@ -1250,20 +1257,12 @@ METHOD(ike_sa_t, process_message, status_t,
}
/* add a timeout if peer does not establish it completely */
job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE);
- charon->scheduler->schedule_job(charon->scheduler, job,
- HALF_OPEN_IKE_SA_TIMEOUT);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ HALF_OPEN_IKE_SA_TIMEOUT);
}
this->stats[STAT_INBOUND] = time_monotonic(NULL);
- /* check if message is trustworthy, and update host information */
- if (this->state == IKE_CREATED || this->state == IKE_CONNECTING ||
- message->get_exchange_type(message) != IKE_SA_INIT)
- {
- if (!supports_extension(this, EXT_MOBIKE))
- { /* with MOBIKE, we do no implicit updates */
- update_hosts(this, me, other);
- }
- }
- status = this->task_manager->process_message(this->task_manager, message);
+ status = this->task_manager->process_message(this->task_manager,
+ message);
if (message->get_exchange_type(message) == IKE_AUTH &&
this->state == IKE_ESTABLISHED &&
lib->settings->get_bool(lib->settings,
@@ -1697,7 +1696,7 @@ METHOD(ike_sa_t, set_auth_lifetime, void,
{
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
lifetime);
- charon->processor->queue_job(charon->processor,
+ lib->processor->queue_job(lib->processor,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
}
else if (this->stats[STAT_REAUTH] == 0 ||
@@ -1706,7 +1705,7 @@ METHOD(ike_sa_t, set_auth_lifetime, void,
this->stats[STAT_REAUTH] = reauth_time;
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
" in %ds", lifetime, lifetime - reduction);
- charon->scheduler->schedule_job(charon->scheduler,
+ lib->scheduler->schedule_job(lib->scheduler,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
lifetime - reduction);
}
@@ -1718,10 +1717,65 @@ METHOD(ike_sa_t, set_auth_lifetime, void,
}
}
+/**
+ * Check if the current combination of source and destination address is still
+ * valid.
+ */
+static bool is_current_path_valid(private_ike_sa_t *this)
+{
+ bool valid = FALSE;
+ host_t *src;
+ src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+ this->other_host, this->my_host);
+ if (src)
+ {
+ if (src->ip_equals(src, this->my_host))
+ {
+ valid = TRUE;
+ }
+ src->destroy(src);
+ }
+ return valid;
+}
+
+/**
+ * Check if we have any path avialable for this IKE SA.
+ */
+static bool is_any_path_valid(private_ike_sa_t *this)
+{
+ bool valid = FALSE;
+ enumerator_t *enumerator;
+ host_t *src, *addr;
+ DBG1(DBG_IKE, "old path is not available anymore, try to find another");
+ src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+ this->other_host, NULL);
+ if (!src)
+ {
+ enumerator = this->additional_addresses->create_enumerator(
+ this->additional_addresses);
+ while (enumerator->enumerate(enumerator, &addr))
+ {
+ DBG1(DBG_IKE, "looking for a route to %H ...", addr);
+ src = hydra->kernel_interface->get_source_addr(
+ hydra->kernel_interface, addr, NULL);
+ if (src)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ if (src)
+ {
+ valid = TRUE;
+ src->destroy(src);
+ }
+ return valid;
+}
+
METHOD(ike_sa_t, roam, status_t,
private_ike_sa_t *this, bool address)
{
- host_t *src;
ike_mobike_t *mobike;
switch (this->state)
@@ -1734,81 +1788,61 @@ METHOD(ike_sa_t, roam, status_t,
default:
break;
}
- /* responder just updates the peer about changed address config */
- if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
+
+ /* keep existing path if possible */
+ if (is_current_path_valid(this))
{
+ DBG2(DBG_IKE, "keeping connection path %H - %H",
+ this->my_host, this->other_host);
+ set_condition(this, COND_STALE, FALSE);
+
if (supports_extension(this, EXT_MOBIKE) && address)
- {
+ { /* if any addresses changed, send an updated list */
DBG1(DBG_IKE, "sending address list update using MOBIKE");
mobike = ike_mobike_create(&this->public, TRUE);
- this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
+ mobike->addresses(mobike);
+ this->task_manager->queue_task(this->task_manager,
+ (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
return SUCCESS;
}
- /* keep existing path if possible */
- src = charon->kernel_interface->get_source_addr(charon->kernel_interface,
- this->other_host, this->my_host);
- if (src)
+ if (!is_any_path_valid(this))
{
- if (src->ip_equals(src, this->my_host))
- {
- DBG2(DBG_IKE, "keeping connection path %H - %H",
- src, this->other_host);
- src->destroy(src);
- set_condition(this, COND_STALE, FALSE);
- return SUCCESS;
- }
- src->destroy(src);
-
- }
- else
- {
- /* check if we find a route at all */
- enumerator_t *enumerator;
- host_t *addr;
-
- src = charon->kernel_interface->get_source_addr(charon->kernel_interface,
- this->other_host, NULL);
- if (!src)
- {
- enumerator = this->additional_addresses->create_enumerator(
- this->additional_addresses);
- while (enumerator->enumerate(enumerator, &addr))
- {
- DBG1(DBG_IKE, "looking for a route to %H ...", addr);
- src = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, addr, NULL);
- if (src)
- {
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
- if (!src)
- {
- DBG1(DBG_IKE, "no route found to reach %H, MOBIKE update deferred",
- this->other_host);
- set_condition(this, COND_STALE, TRUE);
- return SUCCESS;
- }
- src->destroy(src);
+ DBG1(DBG_IKE, "no route found to reach %H, MOBIKE update deferred",
+ this->other_host);
+ set_condition(this, COND_STALE, TRUE);
+ return SUCCESS;
}
set_condition(this, COND_STALE, FALSE);
/* update addresses with mobike, if supported ... */
if (supports_extension(this, EXT_MOBIKE))
{
- DBG1(DBG_IKE, "requesting address change using MOBIKE");
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR))
+ { /* responder updates the peer about changed address config */
+ DBG1(DBG_IKE, "sending address list update using MOBIKE, "
+ "implicitly requesting an address change");
+ address = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "requesting address change using MOBIKE");
+ }
mobike = ike_mobike_create(&this->public, TRUE);
mobike->roam(mobike, address);
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
- DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
+
/* ... reauth if not */
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR))
+ { /* responder does not reauthenticate */
+ set_condition(this, COND_STALE, TRUE);
+ return SUCCESS;
+ }
+ DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
return reauth(this);
}
@@ -1907,9 +1941,9 @@ METHOD(ike_sa_t, inherit, status_t,
this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;
DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
"lifetime reduced to %ds", reauth, delete);
- charon->scheduler->schedule_job(charon->scheduler,
+ lib->scheduler->schedule_job(lib->scheduler,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE), reauth);
- charon->scheduler->schedule_job(charon->scheduler,
+ lib->scheduler->schedule_job(lib->scheduler,
(job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE), delete);
}
/* we have to initate here, there may be new tasks to handle */
@@ -1946,8 +1980,8 @@ METHOD(ike_sa_t, destroy, void,
if (this->my_virtual_ip)
{
- charon->kernel_interface->del_ip(charon->kernel_interface,
- this->my_virtual_ip);
+ hydra->kernel_interface->del_ip(hydra->kernel_interface,
+ this->my_virtual_ip);
this->my_virtual_ip->destroy(this->my_virtual_ip);
}
if (this->other_virtual_ip)
@@ -2025,6 +2059,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.get_other_host = _get_other_host,
.set_other_host = _set_other_host,
.set_message_id = _set_message_id,
+ .float_ports = _float_ports,
.update_hosts = _update_hosts,
.get_my_id = _get_my_id,
.set_my_id = _set_my_id,