diff options
author | Tobias Brunner <tobias@strongswan.org> | 2017-03-21 12:18:12 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2017-05-23 18:46:06 +0200 |
commit | 9a5f7a30f8ca60c25ab7a46b3e6506028806d8db (patch) | |
tree | 460c87ca34399987e980e10feb7e2a7c84fe0ac4 /src/libcharon | |
parent | dc3710e987b49c96ee2e81c1979fb2a6133bd30d (diff) | |
download | strongswan-9a5f7a30f8ca60c25ab7a46b3e6506028806d8db.tar.bz2 strongswan-9a5f7a30f8ca60c25ab7a46b3e6506028806d8db.tar.xz |
child-delete: Track flags per individual CHILD_SA
Diffstat (limited to 'src/libcharon')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_delete.c | 125 |
1 files changed, 78 insertions, 47 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c index d69f44b0d..6ab59962f 100644 --- a/src/libcharon/sa/ikev2/tasks/child_delete.c +++ b/src/libcharon/sa/ikev2/tasks/child_delete.c @@ -39,67 +39,79 @@ struct private_child_delete_t { ike_sa_t *ike_sa; /** - * Are we the initiator? + * Whether we are the initiator of the exchange */ bool initiator; /** - * Protocol of CHILD_SA to delete + * Protocol of CHILD_SA to delete (as initiator) */ protocol_id_t protocol; /** - * Inbound SPI of CHILD_SA to delete + * Inbound SPI of CHILD_SA to delete (as initiator) */ uint32_t spi; /** - * whether to enforce delete action policy - */ - bool check_delete_action; - - /** - * is this delete exchange following a rekey? - */ - bool rekeyed; - - /** - * CHILD_SA already expired? + * CHILD_SA already expired (as initiator) */ bool expired; /** - * CHILD_SAs which get deleted + * CHILD_SAs which get deleted, entry_t* */ linked_list_t *child_sas; }; /** + * Information about a deleted CHILD_SA + */ +typedef struct { + /** Deleted CHILD_SA */ + child_sa_t *child_sa; + /** Whether the CHILD_SA was rekeyed */ + bool rekeyed; + /** Whether to enforce any delete action policy */ + bool check_delete_action; +} entry_t; + +/** + * Check if the given entry is for the same CHILD_SA + */ +static bool match_child(entry_t *entry, child_sa_t *child_sa) +{ + return entry->child_sa == child_sa; +} + +/** * build the delete payloads from the listed child_sas */ static void build_payloads(private_child_delete_t *this, message_t *message) { delete_payload_t *ah = NULL, *esp = NULL; enumerator_t *enumerator; - child_sa_t *child_sa; + entry_t *entry; + protocol_id_t protocol; + uint32_t spi; enumerator = this->child_sas->create_enumerator(this->child_sas); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + while (enumerator->enumerate(enumerator, (void**)&entry)) { - protocol_id_t protocol = child_sa->get_protocol(child_sa); - uint32_t spi = child_sa->get_spi(child_sa, TRUE); + protocol = entry->child_sa->get_protocol(entry->child_sa); + spi = entry->child_sa->get_spi(entry->child_sa, TRUE); switch (protocol) { case PROTO_ESP: - if (esp == NULL) + if (!esp) { esp = delete_payload_create(PLV2_DELETE, PROTO_ESP); message->add_payload(message, (payload_t*)esp); } esp->add_spi(esp, spi); DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x", - protocol_id_names, protocol, ntohl(spi)); + protocol_id_names, protocol, ntohl(spi)); break; case PROTO_AH: if (ah == NULL) @@ -109,12 +121,12 @@ static void build_payloads(private_child_delete_t *this, message_t *message) } ah->add_spi(ah, spi); DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x", - protocol_id_names, protocol, ntohl(spi)); + protocol_id_names, protocol, ntohl(spi)); break; default: break; } - child_sa->set_state(child_sa, CHILD_DELETING); + entry->child_sa->set_state(entry->child_sa, CHILD_DELETING); } enumerator->destroy(enumerator); } @@ -208,6 +220,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message) uint32_t spi; protocol_id_t protocol; child_sa_t *child_sa; + entry_t *entry; payloads = message->create_payload_enumerator(message); while (payloads->enumerate(payloads, &payload)) @@ -225,27 +238,37 @@ static void process_payloads(private_child_delete_t *this, message_t *message) { child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE); - if (child_sa == NULL) + if (!child_sa) { - DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, " - "but no such SA", protocol_id_names, protocol, ntohl(spi)); + DBG1(DBG_IKE, "received DELETE for unknown %N CHILD_SA with" + " SPI %.8x", protocol_id_names, protocol, ntohl(spi)); continue; } DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x", protocol_id_names, protocol, ntohl(spi)); + if (this->child_sas->find_first(this->child_sas, + (void*)match_child, NULL, child_sa) == SUCCESS) + { + continue; + } + INIT(entry, + .child_sa = child_sa + ); switch (child_sa->get_state(child_sa)) { case CHILD_REKEYED: - this->rekeyed = TRUE; + entry->rekeyed = TRUE; break; case CHILD_DELETING: - /* we don't send back a delete if we initiated ourself */ + /* we don't send back a delete if we already initiated + * a delete ourself */ if (!this->initiator) { + free(entry); continue; } - /* fall through */ + break; case CHILD_REKEYING: /* we reply as usual, rekeying will fail */ case CHILD_INSTALLED_INBOUND: @@ -254,22 +277,18 @@ static void process_payloads(private_child_delete_t *this, message_t *message) { if (is_redundant(this, child_sa)) { - this->rekeyed = TRUE; + entry->rekeyed = TRUE; } else { - this->check_delete_action = TRUE; + entry->check_delete_action = TRUE; } } break; default: break; } - if (this->child_sas->find_first(this->child_sas, NULL, - (void**)&child_sa) != SUCCESS) - { - this->child_sas->insert_last(this->child_sas, child_sa); - } + this->child_sas->insert_last(this->child_sas, entry); } spis->destroy(spis); } @@ -283,6 +302,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message) static status_t destroy_and_reestablish(private_child_delete_t *this) { enumerator_t *enumerator; + entry_t *entry; child_sa_t *child_sa; child_cfg_t *child_cfg; protocol_id_t protocol; @@ -291,11 +311,12 @@ static status_t destroy_and_reestablish(private_child_delete_t *this) status_t status = SUCCESS; enumerator = this->child_sas->create_enumerator(this->child_sas); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + while (enumerator->enumerate(enumerator, (void**)&entry)) { + child_sa = entry->child_sa; /* signal child down event if we weren't rekeying */ protocol = child_sa->get_protocol(child_sa); - if (!this->rekeyed) + if (!entry->rekeyed) { charon->bus->child_updown(charon->bus, child_sa, FALSE); } @@ -313,7 +334,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this) child_cfg->get_ref(child_cfg); action = child_sa->get_close_action(child_sa); this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi); - if (this->check_delete_action) + if (entry->check_delete_action) { /* enforce child_cfg policy if deleted passively */ switch (action) { @@ -348,12 +369,14 @@ static void log_children(private_child_delete_t *this) { linked_list_t *my_ts, *other_ts; enumerator_t *enumerator; + entry_t *entry; child_sa_t *child_sa; uint64_t bytes_in, bytes_out; enumerator = this->child_sas->create_enumerator(this->child_sas); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + while (enumerator->enumerate(enumerator, (void**)&entry)) { + child_sa = entry->child_sa; my_ts = linked_list_create_from_enumerator( child_sa->create_ts_enumerator(child_sa, TRUE)); other_ts = linked_list_create_from_enumerator( @@ -388,6 +411,7 @@ METHOD(task_t, build_i, status_t, private_child_delete_t *this, message_t *message) { child_sa_t *child_sa; + entry_t *entry; child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, this->spi, TRUE); @@ -402,15 +426,18 @@ METHOD(task_t, build_i, status_t, /* we work only with the inbound SPI */ this->spi = child_sa->get_spi(child_sa, TRUE); } - this->child_sas->insert_last(this->child_sas, child_sa); + INIT(entry, + .child_sa = child_sa, + ); + this->child_sas->insert_last(this->child_sas, entry); if (child_sa->get_state(child_sa) == CHILD_REKEYED) { - this->rekeyed = TRUE; + entry->rekeyed = TRUE; } log_children(this); build_payloads(this, message); - if (!this->rekeyed && this->expired) + if (!entry->rekeyed && this->expired) { child_cfg_t *child_cfg; @@ -457,24 +484,28 @@ METHOD(child_delete_t , get_child, child_sa_t*, private_child_delete_t *this) { child_sa_t *child_sa = NULL; - this->child_sas->get_first(this->child_sas, (void**)&child_sa); + entry_t *entry; + + if (this->child_sas->get_first(this->child_sas, (void**)&entry) == SUCCESS) + { + child_sa = entry->child_sa; + } return child_sa; } METHOD(task_t, migrate, void, private_child_delete_t *this, ike_sa_t *ike_sa) { - this->check_delete_action = FALSE; this->ike_sa = ike_sa; - this->child_sas->destroy(this->child_sas); + this->child_sas->destroy_function(this->child_sas, free); this->child_sas = linked_list_create(); } METHOD(task_t, destroy, void, private_child_delete_t *this) { - this->child_sas->destroy(this->child_sas); + this->child_sas->destroy_function(this->child_sas, free); free(this); } |