aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-03-21 12:18:12 +0100
committerTobias Brunner <tobias@strongswan.org>2017-05-23 18:46:06 +0200
commit9a5f7a30f8ca60c25ab7a46b3e6506028806d8db (patch)
tree460c87ca34399987e980e10feb7e2a7c84fe0ac4 /src/libcharon
parentdc3710e987b49c96ee2e81c1979fb2a6133bd30d (diff)
downloadstrongswan-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.c125
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);
}