aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa')
-rw-r--r--src/charon/sa/child_sa.c118
-rw-r--r--src/charon/sa/child_sa.h5
-rw-r--r--src/charon/sa/ike_sa.c11
-rw-r--r--src/charon/sa/tasks/child_create.c18
-rw-r--r--src/charon/sa/tasks/ike_mobike.c15
-rw-r--r--src/charon/sa/tasks/task.c23
6 files changed, 106 insertions, 84 deletions
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 24d91a5da..95c7735de 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -30,6 +30,7 @@
ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"CREATED",
"ROUTED",
+ "INSTALLING",
"INSTALLED",
"UPDATING",
"REKEYING",
@@ -444,7 +445,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in)
{
u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
- u_int32_t spi, cpi, soft, hard, now;
+ u_int32_t spi, soft, hard, now;
host_t *src, *dst;
status_t status;
@@ -461,7 +462,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
if (this->alloc_ah_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_ah_spi, 0, PROTO_AH);
}
}
else
@@ -470,7 +471,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
if (this->alloc_esp_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->alloc_esp_spi, 0, PROTO_ESP);
}
}
spi = this->my_spi;
@@ -491,16 +492,6 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* we install an additional IPComp SA */
- cpi = htonl(ntohs(in ? this->my_cpi : this->other_cpi));
- charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
- ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
- mode, this->ipcomp, FALSE, in);
- }
-
proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size);
proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size);
@@ -509,7 +500,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
status = charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, spi, this->protocol, this->reqid,
in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
- mode, IPCOMP_NONE, this->encap, in);
+ mode, this->ipcomp, in ? this->my_cpi : this->other_cpi,
+ this->encap, in);
now = time(NULL);
this->rekey_time = now + soft;
@@ -588,12 +580,8 @@ static status_t add_policies(private_child_sa_t *this,
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
status_t status = SUCCESS;
- bool high_prio = TRUE;
+ bool routed = (this->state == CHILD_CREATED);
- if (this->state == CHILD_CREATED)
- { /* use low prio for ROUTED policies */
- high_prio = FALSE;
- }
if (this->protocol == PROTO_NONE)
{ /* update if not set yet */
this->protocol = proto;
@@ -622,17 +610,20 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
-
+ this->other_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->other_cpi, routed);
+
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
if (mode == MODE_TUNNEL)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
}
if (status != SUCCESS)
@@ -682,26 +673,23 @@ static status_t update_hosts(private_child_sa_t *this,
old = this->state;
set_state(this, CHILD_UPDATING);
- this->encap = encap;
-
- if (this->ipcomp != IPCOMP_NONE)
+ /* update our (initator) SA */
+ if (charon->kernel_interface->update_sa(charon->kernel_interface, this->my_spi,
+ this->protocol, this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ this->other_addr, this->my_addr, other, me,
+ this->encap, encap) == NOT_SUPPORTED)
{
- /* update our (initator) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface,
- htonl(ntohs(this->my_cpi)), IPPROTO_COMP,
- this->other_addr, this->my_addr, other, me, FALSE);
- /* update his (responder) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface,
- htonl(ntohs(this->other_cpi)), IPPROTO_COMP,
- this->my_addr, this->other_addr, me, other, FALSE);
+ return NOT_SUPPORTED;
}
- /* update our (initator) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->my_spi,
- this->protocol, this->other_addr, this->my_addr, other, me, encap);
/* update his (responder) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
- this->protocol, this->my_addr, this->other_addr, me, other, encap);
+ if (charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
+ this->protocol, this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ this->my_addr, this->other_addr, me, other,
+ this->encap, encap) == NOT_SUPPORTED)
+ {
+ return NOT_SUPPORTED;
+ }
if (this->config->install_policy(this->config))
{
@@ -718,13 +706,13 @@ static status_t update_hosts(private_child_sa_t *this,
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT);
+ my_ts, other_ts, POLICY_OUT, FALSE);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN);
+ other_ts, my_ts, POLICY_IN, FALSE);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD);
+ other_ts, my_ts, POLICY_FWD, FALSE);
}
/* check whether we have to update a "dynamic" traffic selector */
@@ -749,16 +737,19 @@ static status_t update_hosts(private_child_sa_t *this,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
- me, other, my_ts, other_ts, POLICY_OUT, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_IN, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_FWD, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
}
}
enumerator->destroy(enumerator);
@@ -779,6 +770,8 @@ static status_t update_hosts(private_child_sa_t *this,
this->other_addr = other->clone(other);
}
}
+ this->encap = encap;
+
set_state(this, old);
return SUCCESS;
@@ -815,6 +808,7 @@ static void destroy(private_child_sa_t *this)
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
+ bool unrouted = (this->state == CHILD_ROUTED);
set_state(this, CHILD_DESTROYING);
@@ -822,32 +816,24 @@ static void destroy(private_child_sa_t *this)
if (this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->my_spi, this->protocol);
+ this->my_addr, this->my_spi, this->protocol,
+ this->my_cpi);
}
if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->alloc_esp_spi, PROTO_ESP, 0);
}
if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_ah_spi, PROTO_AH, 0);
}
if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other_addr, this->other_spi, this->protocol);
- }
- if (this->my_cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, htonl(ntohs(this->my_cpi)), IPPROTO_COMP);
- }
- if (this->other_cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other_addr, htonl(ntohs(this->other_cpi)), IPPROTO_COMP);
+ this->other_addr, this->other_spi, this->protocol,
+ this->other_cpi);
}
if (this->config->install_policy(this->config))
@@ -857,13 +843,13 @@ static void destroy(private_child_sa_t *this)
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT);
+ my_ts, other_ts, POLICY_OUT, unrouted);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN);
+ other_ts, my_ts, POLICY_IN, unrouted);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD);
+ other_ts, my_ts, POLICY_FWD, unrouted);
}
}
enumerator->destroy(enumerator);
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index e9ad4ac8d..202573a23 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -50,6 +50,11 @@ enum child_sa_state_t {
CHILD_ROUTED,
/**
+ * Installing an in-use CHILD_SA
+ */
+ CHILD_INSTALLING,
+
+ /**
* Installed an in-use CHILD_SA
*/
CHILD_INSTALLED,
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index ab2a789d0..80e42d924 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -898,8 +898,14 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa, this->my_host, this->other_host,
- this->my_virtual_ip, has_condition(this, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa, this->my_host,
+ this->other_host, this->my_virtual_ip,
+ has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->public.rekey_child_sa(&this->public,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
@@ -1314,6 +1320,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
}
else
{
+ child_sa->destroy(child_sa);
DBG1(DBG_IKE, "routing CHILD_SA failed");
}
return status;
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index 628d1397c..02664338a 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -327,20 +327,14 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+
if (this->ipcomp != IPCOMP_NONE)
{
this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
this->other_cpi);
}
- status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
- this->mode, this->proposal->get_protocol(this->proposal));
- if (status != SUCCESS)
- {
- DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
- return NOT_FOUND;
- }
-
status = FAILED;
if (this->keymat->derive_child_keys(this->keymat, this->proposal,
this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
@@ -367,6 +361,14 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
return FAILED;
}
+ status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
+ this->mode, this->proposal->get_protocol(this->proposal));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
+ return NOT_FOUND;
+ }
+
charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
nonce_i, nonce_r);
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index b3bffd670..026190b80 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -251,11 +251,16 @@ static void update_children(private_ike_mobike_t *this)
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa,
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
- this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->ike_sa->rekey_child_sa(this->ike_sa,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c
index 4ff50a610..0a5e753ec 100644
--- a/src/charon/sa/tasks/task.c
+++ b/src/charon/sa/tasks/task.c
@@ -18,6 +18,7 @@
#include "task.h"
+#ifdef ME
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_INIT",
"IKE_NATD",
@@ -31,11 +32,27 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DPD",
-#ifdef ME
"IKE_ME",
-#endif /* ME */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
);
-
+#else
+ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ "IKE_INIT",
+ "IKE_NATD",
+ "IKE_MOBIKE",
+ "IKE_AUTHENTICATE",
+ "IKE_AUTH_LIFETIME",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
+ "IKE_CONFIG",
+ "IKE_REKEY",
+ "IKE_REAUTH",
+ "IKE_DELETE",
+ "IKE_DPD",
+ "CHILD_CREATE",
+ "CHILD_DELETE",
+ "CHILD_REKEY",
+);
+#endif /* ME */