diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 81 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_delete.c | 1 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_rekey.c | 62 |
3 files changed, 98 insertions, 46 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 896cabb2b..cac3bc0a2 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -478,6 +478,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh, bool ike_auth) { status_t status, status_i, status_o; + child_sa_outbound_state_t out_state; chunk_t nonce_i, nonce_r; chunk_t encr_i = chunk_empty, encr_r = chunk_empty; chunk_t integ_i = chunk_empty, integ_r = chunk_empty; @@ -678,29 +679,42 @@ static status_t select_and_install(private_child_create_t *this, status_i = this->child_sa->install(this->child_sa, encr_r, integ_r, this->my_spi, this->my_cpi, this->initiator, TRUE, this->tfcv3); - status_o = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->other_spi, this->other_cpi, this->initiator, - FALSE, this->tfcv3); } - else if (!this->rekey) + else { status_i = this->child_sa->install(this->child_sa, encr_i, integ_i, this->my_spi, this->my_cpi, this->initiator, TRUE, this->tfcv3); - status_o = this->child_sa->install(this->child_sa, encr_r, integ_r, + } + if (this->rekey) + { /* during rekeyings we install the outbound SA and/or policies + * separately: as responder when we receive the delete for the old + * SA, as initiator pretty much immediately in the ike-rekey task, + * unless there was a rekey collision that we lost */ + if (this->initiator) + { + status_o = this->child_sa->register_outbound(this->child_sa, + encr_i, integ_i, this->other_spi, this->other_cpi, + this->tfcv3); + } + else + { + status_o = this->child_sa->register_outbound(this->child_sa, + encr_r, integ_r, this->other_spi, this->other_cpi, + this->tfcv3); + } + } + else if (this->initiator) + { + status_o = this->child_sa->install(this->child_sa, encr_i, integ_i, this->other_spi, this->other_cpi, this->initiator, FALSE, this->tfcv3); } else - { /* as responder during a rekeying we only install the inbound - * SA now, the outbound SA and policies are installed when we - * receive the delete for the old SA */ - status_i = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->my_spi, this->my_cpi, this->initiator, - TRUE, this->tfcv3); - this->child_sa->register_outbound(this->child_sa, encr_r, integ_r, - this->other_spi, this->other_cpi, this->tfcv3); - status_o = SUCCESS; + { + status_o = this->child_sa->install(this->child_sa, encr_r, integ_r, + this->other_spi, this->other_cpi, this->initiator, + FALSE, this->tfcv3); } } @@ -745,20 +759,15 @@ static status_t select_and_install(private_child_create_t *this, charon->bus->child_keys(charon->bus, this->child_sa, this->initiator, this->dh, nonce_i, nonce_r); - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); - this->established = TRUE; - - schedule_inactivity_timeout(this); - my_ts = linked_list_create_from_enumerator( this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); other_ts = linked_list_create_from_enumerator( this->child_sa->create_ts_enumerator(this->child_sa, FALSE)); + out_state = this->child_sa->get_outbound_state(this->child_sa); DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established " "with SPIs %.8x_i %.8x_o and TS %#R === %#R", - this->rekey && !this->initiator ? "inbound " : "", + (out_state == CHILD_OUTBOUND_INSTALLED) ? "" : "inbound ", this->child_sa->get_name(this->child_sa), this->child_sa->get_unique_id(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), @@ -767,6 +776,12 @@ static status_t select_and_install(private_child_create_t *this, my_ts->destroy(my_ts); other_ts->destroy(other_ts); + + this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); + this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); + this->established = TRUE; + + schedule_inactivity_timeout(this); return SUCCESS; } @@ -1007,17 +1022,6 @@ METHOD(task_t, build_i, status_t, break; } - if (this->reqid) - { - DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}", - this->config->get_name(this->config), this->reqid); - } - else - { - DBG0(DBG_IKE, "establishing CHILD_SA %s", - this->config->get_name(this->config)); - } - /* check if we want a virtual IP, but don't have one */ list = linked_list_create(); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); @@ -1070,6 +1074,19 @@ METHOD(task_t, build_i, status_t, this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY), this->mark_in, this->mark_out); + if (this->reqid) + { + DBG0(DBG_IKE, "establishing CHILD_SA %s{%d} reqid %d", + this->child_sa->get_name(this->child_sa), + this->child_sa->get_unique_id(this->child_sa), this->reqid); + } + else + { + DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}", + this->child_sa->get_name(this->child_sa), + this->child_sa->get_unique_id(this->child_sa)); + } + if (!allocate_spi(this)) { DBG1(DBG_IKE, "unable to allocate SPIs from kernel"); diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c index 626796383..2217295b6 100644 --- a/src/libcharon/sa/ikev2/tasks/child_delete.c +++ b/src/libcharon/sa/ikev2/tasks/child_delete.c @@ -196,7 +196,6 @@ static void install_outbound(private_child_delete_t *this, /* FIXME: delete the new child_sa? */ return; } - child_sa->set_state(child_sa, CHILD_INSTALLED); my_ts = linked_list_create_from_enumerator( child_sa->create_ts_enumerator(child_sa, TRUE)); diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index 761c860e7..b67e9b80f 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 Tobias Brunner + * Copyright (C) 2009-2017 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * HSR Hochschule fuer Technik Rapperswil @@ -283,7 +283,8 @@ METHOD(task_t, build_r, status_t, /** * Handle a rekey collision */ -static child_sa_t *handle_collision(private_child_rekey_t *this) +static child_sa_t *handle_collision(private_child_rekey_t *this, + child_sa_t **to_install) { child_sa_t *to_delete; @@ -302,8 +303,11 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) { child_sa_t *child_sa; - DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child"); + *to_install = this->child_create->get_child(this->child_create); to_delete = this->child_sa; + DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child " + "%s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); /* don't touch child other created, it has already been deleted */ if (!this->other_child_destroyed) { @@ -321,9 +325,10 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) } else { - DBG1(DBG_IKE, "CHILD_SA rekey collision lost, " - "deleting rekeyed child"); to_delete = this->child_create->get_child(this->child_create); + DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant " + "child %s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } } else @@ -334,15 +339,17 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) * the CHILD_SA the other is not deleting. */ if (del->get_child(del) != this->child_sa) { - DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " - "deleting rekeyed child"); to_delete = this->child_sa; + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting old child " + "%s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } else { - DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " - "deleting redundant child"); to_delete = this->child_create->get_child(this->child_create); + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting redundant " + "child %s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } } return to_delete; @@ -353,7 +360,7 @@ METHOD(task_t, process_i, status_t, { protocol_id_t protocol; uint32_t spi; - child_sa_t *to_delete; + child_sa_t *to_delete, *to_install = NULL; if (message->get_notify(message, NO_ADDITIONAL_SAS)) { @@ -415,19 +422,48 @@ METHOD(task_t, process_i, status_t, /* check for rekey collisions */ if (this->collision) { - to_delete = handle_collision(this); + to_delete = handle_collision(this, &to_install); } else { + to_install = this->child_create->get_child(this->child_create); to_delete = this->child_sa; } - + if (to_install) + { + if (to_install->install_outbound(to_install) != SUCCESS) + { + DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel"); + charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED, + to_install); + /* FIXME: delete the child_sa? fail the task? */ + } + else + { + linked_list_t *my_ts, *other_ts; + + my_ts = linked_list_create_from_enumerator( + to_install->create_ts_enumerator(to_install, TRUE)); + other_ts = linked_list_create_from_enumerator( + to_install->create_ts_enumerator(to_install, FALSE)); + + DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established " + "with SPIs %.8x_i %.8x_o and TS %#R === %#R", + to_install->get_name(to_install), + to_install->get_unique_id(to_install), + ntohl(to_install->get_spi(to_install, TRUE)), + ntohl(to_install->get_spi(to_install, FALSE)), + my_ts, other_ts); + + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); + } + } if (to_delete != this->child_create->get_child(this->child_create)) { /* invoke rekey hook if rekeying successful */ charon->bus->child_rekey(charon->bus, this->child_sa, this->child_create->get_child(this->child_create)); } - if (to_delete == NULL) { return SUCCESS; |