diff options
Diffstat (limited to 'src/charon/sa')
-rw-r--r-- | src/charon/sa/child_sa.c | 118 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 5 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 11 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_create.c | 18 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 15 | ||||
-rw-r--r-- | src/charon/sa/tasks/task.c | 23 |
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 */ |