From 07ce6b44c55475134e1a09332837fb7234a3fbb9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 Jul 2024 18:23:03 +0200 Subject: [PATCH 1/4] testing: Enable IPv6 guest-to-guest communication Not sure what changed, but without this setting, ND packets would not get through to other hosts connected to the same bridge. --- testing/config/kvm/vnet1.xml | 2 +- testing/config/kvm/vnet2.xml | 2 +- testing/config/kvm/vnet3.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testing/config/kvm/vnet1.xml b/testing/config/kvm/vnet1.xml index 94097ab6f0..fd7453a5c6 100644 --- a/testing/config/kvm/vnet1.xml +++ b/testing/config/kvm/vnet1.xml @@ -1,4 +1,4 @@ - + vnet1 1d6ac7c7-60d9-56c1-a7df-210d3d0cc6d1 diff --git a/testing/config/kvm/vnet2.xml b/testing/config/kvm/vnet2.xml index b21e7ed1fc..331ffaaeb1 100644 --- a/testing/config/kvm/vnet2.xml +++ b/testing/config/kvm/vnet2.xml @@ -1,4 +1,4 @@ - + vnet2 b5147a7d-e184-5c9e-3838-4621796ba95c diff --git a/testing/config/kvm/vnet3.xml b/testing/config/kvm/vnet3.xml index f46d9ec093..8b6a4d3ce8 100644 --- a/testing/config/kvm/vnet3.xml +++ b/testing/config/kvm/vnet3.xml @@ -1,4 +1,4 @@ - + vnet3 5c537abc-c116-90e9-a0ef-886340d4c356 From da00a04f601df0ad989f20f15c20949e29f11ff3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 Jul 2024 14:43:37 +0200 Subject: [PATCH 2/4] ike-sa-manager: Avoid initiating CHILD_SAs on IKE_SAs with queued DELETE The IKE_SA might be busy with a different task while a request to terminate it is getting queued, we don't want to use such an IKE_SA to initiate new CHILD_SAs as these tasks will get lost once the IKE_SA is terminated. --- src/libcharon/sa/ike_sa.c | 13 +++++++------ src/libcharon/sa/ike_sa.h | 16 ++++++++++++---- src/libcharon/sa/ike_sa_manager.c | 5 +++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 758a4cdba3..a8cda54bf2 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2020 Tobias Brunner + * Copyright (C) 2006-2024 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -2012,12 +2012,13 @@ static bool is_child_queued(private_ike_sa_t *this, task_queue_t queue) this->version == IKEV1 ? TASK_QUICK_MODE : TASK_CHILD_CREATE); } -/** - * Check if any tasks to delete the IKE_SA are queued in the given queue. +/* + * Described in header */ -static bool is_delete_queued(private_ike_sa_t *this, task_queue_t queue) +bool ike_sa_is_delete_queued(ike_sa_t *ike_sa) { - return is_task_queued(this, queue, + private_ike_sa_t *this = (private_ike_sa_t*)ike_sa; + return is_task_queued(this, TASK_QUEUE_QUEUED, this->version == IKEV1 ? TASK_ISAKMP_DELETE : TASK_IKE_DELETE); } @@ -2101,7 +2102,7 @@ METHOD(ike_sa_t, reestablish, status_t, bool restart = FALSE; status_t status = FAILED; - if (is_delete_queued(this, TASK_QUEUE_QUEUED)) + if (ike_sa_is_delete_queued((ike_sa_t*)this)) { /* don't reestablish IKE_SAs that have explicitly been deleted in the * mean time */ return FAILED; diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index 47c37ff642..1c5333db87 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2020 Tobias Brunner + * Copyright (C) 2006-2024 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -1261,7 +1261,7 @@ struct ike_sa_t { * @param ike_sa_id ike_sa_id_t to associate with new IKE_SA/ISAKMP_SA * @param initiator TRUE to create this IKE_SA as initiator * @param version IKE version of this SA - * @return ike_sa_t object + * @return ike_sa_t object */ ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, ike_version_t version); @@ -1271,16 +1271,24 @@ ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, * parameters or the authentication method prevent it. * * @param this IKE_SA to check - * @return TRUE if active reauthentication is possible + * @return TRUE if active reauthentication is possible */ bool ike_sa_can_reauthenticate(ike_sa_t *this); +/** + * Check if a task to delete this IKE_SA is queued. + * + * @param this IKE_SA to check + * @return TRUE if a task is queued + */ +bool ike_sa_is_delete_queued(ike_sa_t *this); + /** * Get hosts, virtual or physical, for deriving dynamic traffic selectors. * * @param this IKE_SA to retrieve addresses from * @param local TRUE to get local hosts - * @return list of hosts (internal objects) + * @return list of hosts (internal objects) */ linked_list_t *ike_sa_get_dynamic_hosts(ike_sa_t *this, bool local); diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index d59fdb7f52..c128cc0787 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2022 Tobias Brunner + * Copyright (C) 2008-2024 Tobias Brunner * Copyright (C) 2005-2011 Martin Willi * Copyright (C) 2005 Jan Hutter * @@ -1562,7 +1562,8 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, continue; } if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING || - entry->ike_sa->get_state(entry->ike_sa) == IKE_REKEYED) + entry->ike_sa->get_state(entry->ike_sa) == IKE_REKEYED || + ike_sa_is_delete_queued(entry->ike_sa)) { /* skip IKE_SAs which are not usable, wake other waiting threads */ entry->condvar->signal(entry->condvar); continue; From 7bfaa9acb6f533d68da389d38d2aceb3c6f29daa Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 4 Jul 2024 16:17:43 +0200 Subject: [PATCH 3/4] vici: Improve handling of start action when reloading configs The previous code had some issues because it handled each child config separately. Not only was this quite inefficient because all IKE_SAs had to be enumerated for every config, it also caused problems with the check for other CHILD_SAs in order to decide whether to delete the IKE_SA or not. Because CHILD_SAs are deleted with an INFORMATIONAL exchange, they are not immediately gone. This caused a race condition and with more than one child config and SAs the IKE_SA could be kept because it could appear as if other, unrelated CHILD_SAs were still there. Another race condition, which is fixed by the previous commit, occurred when only changing child configs. Then it could happen that the code deemed the IKE_SA empty and a delete for it was queued. If that happened while the IKE_SA was deleting one of the CHILD_SAs (or was busy with some other exchange), the IKE_SA was not switched to IKE_DELETING. So it looked usable and create-child tasks for the updated configs might have gotten queued. Unfortunately, once the ike-delete task is eventually executed, these tasks would be gone and the replacement CHILD_SAs never created. This commit additionally avoids actually deleting the IKE_SA even if all child configs change or get removed if any new CHILD_SAs are to be initiated. --- src/libcharon/plugins/vici/vici_config.c | 275 ++++++++++++++--------- 1 file changed, 171 insertions(+), 104 deletions(-) diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c index c858e9945c..c46b8872b9 100644 --- a/src/libcharon/plugins/vici/vici_config.c +++ b/src/libcharon/plugins/vici/vici_config.c @@ -2257,7 +2257,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg, if (action & ACTION_TRAP) { - DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg)); + DBG1(DBG_CFG, "vici installing '%s'", child_cfg->get_name(child_cfg)); switch (child_cfg->get_mode(child_cfg)) { case MODE_PASS: @@ -2274,7 +2274,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg, if (action & ACTION_START) { - DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg)); + DBG1(DBG_CFG, "vici initiating '%s'", child_cfg->get_name(child_cfg)); charon->controller->initiate(charon->controller, peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg), NULL, NULL, 0, 0, FALSE); @@ -2282,25 +2282,116 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg, } /** - * Undo start actions associated with a child config + * Type to keep track of unique IDs and names of CHILD_SAs to terminate. */ -static void clear_start_action(private_vici_config_t *this, char *peer_name, - child_cfg_t *child_cfg) +typedef struct { + uint32_t id; + char *name; +} child_name_id_t; + +/** + * Terminate given CHILD_SAs and optionally terminate any IKE_SA without other + * children. + */ +static void terminate_for_action(private_vici_config_t *this, char *peer_name, + hashtable_t *to_terminate, bool delete_ike) { enumerator_t *enumerator, *children; child_sa_t *child_sa; ike_sa_t *ike_sa; - uint32_t id = 0, others; + child_name_id_t child_id; + uint32_t id; array_t *ids = NULL, *ikeids = NULL; + bool others; + + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (!streq(ike_sa->get_name(ike_sa), peer_name)) + { + continue; + } + + others = FALSE; + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, &child_sa)) + { + if (child_sa->get_state(child_sa) != CHILD_DELETING && + child_sa->get_state(child_sa) != CHILD_DELETED && + !to_terminate->get(to_terminate, child_sa->get_name(child_sa))) + { + others = TRUE; + break; + } + } + children->destroy(children); + + if (delete_ike && (!others || !ike_sa->get_child_count(ike_sa))) + { + /* found no children or only matching, delete IKE_SA */ + id = ike_sa->get_unique_id(ike_sa); + array_insert_create_value(&ikeids, sizeof(id), + ARRAY_TAIL, &id); + continue; + } + + /* otherwise, delete only the matching CHILD_SAs */ + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, &child_sa)) + { + child_id.name = child_sa->get_name(child_sa); + + if (child_sa->get_state(child_sa) != CHILD_DELETING && + child_sa->get_state(child_sa) != CHILD_DELETED && + to_terminate->get(to_terminate, child_id.name)) + { + child_id.id = child_sa->get_unique_id(child_sa); + child_id.name = strdup(child_id.name); + array_insert_create_value(&ids, sizeof(child_id), + ARRAY_TAIL, &child_id); + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + + while (array_remove(ids, ARRAY_HEAD, &child_id)) + { + DBG1(DBG_CFG, "vici closing CHILD_SA '%s' #%u", child_id.name, + child_id.id); + charon->controller->terminate_child(charon->controller, + child_id.id, NULL, NULL, 0, 0); + free(child_id.name); + } + array_destroy(ids); + + while (array_remove(ikeids, ARRAY_HEAD, &id)) + { + DBG1(DBG_CFG, "vici closing IKE_SA '%s' #%u", peer_name, id); + charon->controller->terminate_ike(charon->controller, id, + FALSE, NULL, NULL, 0, 0); + } + array_destroy(ikeids); +} + +/** + * Clear the start action associated with the given child config. To reduce the + * overhead when terminating active SAs, only collect the name. + * + * Note: The lock must be unlocked when calling this. + */ +static void clear_start_action(private_vici_config_t *this, char *peer_name, + child_cfg_t *child_cfg, hashtable_t *to_terminate) +{ action_t action; char *name; name = child_cfg->get_name(child_cfg); action = child_cfg->get_start_action(child_cfg); - if (action & ACTION_TRAP) { - DBG1(DBG_CFG, "uninstalling '%s'", name); + DBG1(DBG_CFG, "vici uninstalling '%s'", name); switch (child_cfg->get_mode(child_cfg)) { case MODE_PASS: @@ -2313,111 +2404,51 @@ static void clear_start_action(private_vici_config_t *this, char *peer_name, break; } } - if (action & ACTION_START) { - enumerator = charon->controller->create_ike_sa_enumerator( - charon->controller, TRUE); - while (enumerator->enumerate(enumerator, &ike_sa)) - { - if (!streq(ike_sa->get_name(ike_sa), peer_name)) - { - continue; - } - others = id = 0; - children = ike_sa->create_child_sa_enumerator(ike_sa); - while (children->enumerate(children, &child_sa)) - { - if (child_sa->get_state(child_sa) != CHILD_DELETING && - child_sa->get_state(child_sa) != CHILD_DELETED) - { - if (streq(name, child_sa->get_name(child_sa))) - { - id = child_sa->get_unique_id(child_sa); - } - else - { - others++; - } - } - } - children->destroy(children); - - if (!ike_sa->get_child_count(ike_sa) || (id && !others)) - { - /* found no children or only matching, delete IKE_SA */ - id = ike_sa->get_unique_id(ike_sa); - array_insert_create_value(&ikeids, sizeof(id), - ARRAY_TAIL, &id); - } - else - { - children = ike_sa->create_child_sa_enumerator(ike_sa); - while (children->enumerate(children, &child_sa)) - { - if (streq(name, child_sa->get_name(child_sa))) - { - id = child_sa->get_unique_id(child_sa); - array_insert_create_value(&ids, sizeof(id), - ARRAY_TAIL, &id); - } - } - children->destroy(children); - } - } - enumerator->destroy(enumerator); - - if (array_count(ids)) - { - while (array_remove(ids, ARRAY_HEAD, &id)) - { - DBG1(DBG_CFG, "closing '%s' #%u", name, id); - charon->controller->terminate_child(charon->controller, - id, NULL, NULL, 0, 0); - } - array_destroy(ids); - } - if (array_count(ikeids)) - { - while (array_remove(ikeids, ARRAY_HEAD, &id)) - { - DBG1(DBG_CFG, "closing IKE_SA #%u", id); - charon->controller->terminate_ike(charon->controller, id, - FALSE, NULL, NULL, 0, 0); - } - array_destroy(ikeids); - } + to_terminate->put(to_terminate, name, name); } } /** - * Run or undo a start actions associated with a child config + * Clear start actions associated with a list of child configs, optionally + * deletes empty IKE_SAs. */ -static void handle_start_action(private_vici_config_t *this, - peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - bool undo) +static void clear_start_actions(private_vici_config_t *this, + peer_cfg_t *peer_cfg, array_t *child_cfgs, + bool delete_ike) { + enumerator_t *enumerator; + hashtable_t *to_terminate; + child_cfg_t *child_cfg; + char *peer_name; + this->handling_actions = TRUE; this->lock->unlock(this->lock); - if (undo) + to_terminate = hashtable_create(hashtable_hash_str, + hashtable_equals_str, 8); + peer_name = peer_cfg->get_name(peer_cfg); + + enumerator = array_create_enumerator(child_cfgs); + while (enumerator->enumerate(enumerator, &child_cfg)) { - clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg); - } - else - { - run_start_action(this, peer_cfg, child_cfg); + clear_start_action(this, peer_name, child_cfg, to_terminate); } + enumerator->destroy(enumerator); + + terminate_for_action(this, peer_name, to_terminate, delete_ike); + to_terminate->destroy(to_terminate); this->lock->write_lock(this->lock); this->handling_actions = FALSE; } /** - * Run or undo start actions associated with all child configs of a peer config + * Run start actions associated with a list of child configs. */ -static void handle_start_actions(private_vici_config_t *this, - peer_cfg_t *peer_cfg, bool undo) +static void run_start_actions(private_vici_config_t *this, + peer_cfg_t *peer_cfg, array_t *child_cfgs) { enumerator_t *enumerator; child_cfg_t *child_cfg; @@ -2425,17 +2456,10 @@ static void handle_start_actions(private_vici_config_t *this, this->handling_actions = TRUE; this->lock->unlock(this->lock); - enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + enumerator = array_create_enumerator(child_cfgs); while (enumerator->enumerate(enumerator, &child_cfg)) { - if (undo) - { - clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg); - } - else - { - run_start_action(this, peer_cfg, child_cfg); - } + run_start_action(this, peer_cfg, child_cfg); } enumerator->destroy(enumerator); @@ -2443,6 +2467,30 @@ static void handle_start_actions(private_vici_config_t *this, this->handling_actions = FALSE; } +/** + * Run or undo start actions for all child configs of the given peer config + * after it has changed. + */ +static void handle_start_actions(private_vici_config_t *this, + peer_cfg_t *peer_cfg, bool undo) +{ + array_t *child_cfgs; + + child_cfgs = array_create(0, 0); + array_insert_enumerator(child_cfgs, ARRAY_TAIL, + peer_cfg->create_child_cfg_enumerator(peer_cfg)); + if (undo) + { + /* the peer config has changed, so allow IKE_SAs to get terminated */ + clear_start_actions(this, peer_cfg, child_cfgs, TRUE); + } + else + { + run_start_actions(this, peer_cfg, child_cfgs); + } + array_destroy(child_cfgs); +} + /** * Replace children of a peer config by a new config */ @@ -2451,13 +2499,31 @@ static void replace_children(private_vici_config_t *this, { enumerator_t *enumerator; child_cfg_t *child; - bool added; + array_t *to_run = NULL, *to_clear = NULL; + bool added, any_to_initiate = FALSE; enumerator = to->replace_child_cfgs(to, from); while (enumerator->enumerate(enumerator, &child, &added)) { - handle_start_action(this, to, child, !added); + if (added) + { + array_insert_create(&to_run, ARRAY_TAIL, child); + + if (child->get_start_action(child) & ACTION_START) + { + any_to_initiate = TRUE; + } + } + else + { + array_insert_create(&to_clear, ARRAY_TAIL, child); + } } + /* keep empty IKE_SAs only if we are to initiate any CHILD_SAs */ + clear_start_actions(this, to, to_clear, !any_to_initiate); + run_start_actions(this, to, to_run); + array_destroy(to_clear); + array_destroy(to_run); enumerator->destroy(enumerator); } @@ -2796,6 +2862,7 @@ CALLBACK(unload_conn, vici_message_t*, cfg = this->conns->remove(this->conns, conn_name); if (cfg) { + DBG1(DBG_CFG, "removed vici connection: %s", cfg->get_name(cfg)); handle_start_actions(this, cfg, TRUE); cfg->destroy(cfg); } From 56b6eeb385df87b39e48a5c07d2ff304811ff222 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Jul 2024 16:56:32 +0200 Subject: [PATCH 4/4] testing: Add ikev2/start-action-start scenario This tests the behavior for configs with start_action=start during reloads of the config (updates/removal). --- .../ikev2/start-action-start/description.txt | 3 + .../ikev2/start-action-start/evaltest.dat | 56 ++++++ .../hosts/moon/etc/strongswan.conf | 5 + .../moon/etc/swanctl/conf.d/swanctl-base.conf | 161 ++++++++++++++++++ .../moon/etc/swanctl/swanctl-remove.conf | 75 ++++++++ .../moon/etc/swanctl/swanctl-update.conf | 56 ++++++ .../hosts/moon/etc/swanctl/swanctl.conf | 2 + .../hosts/sun/etc/strongswan.conf | 8 + .../hosts/sun/etc/swanctl/swanctl.conf | 143 ++++++++++++++++ .../ikev2/start-action-start/posttest.dat | 5 + .../ikev2/start-action-start/pretest.dat | 6 + .../tests/ikev2/start-action-start/test.conf | 25 +++ 12 files changed, 545 insertions(+) create mode 100644 testing/tests/ikev2/start-action-start/description.txt create mode 100644 testing/tests/ikev2/start-action-start/evaltest.dat create mode 100644 testing/tests/ikev2/start-action-start/hosts/moon/etc/strongswan.conf create mode 100755 testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/conf.d/swanctl-base.conf create mode 100755 testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-remove.conf create mode 100755 testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-update.conf create mode 100755 testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl.conf create mode 100644 testing/tests/ikev2/start-action-start/hosts/sun/etc/strongswan.conf create mode 100755 testing/tests/ikev2/start-action-start/hosts/sun/etc/swanctl/swanctl.conf create mode 100644 testing/tests/ikev2/start-action-start/posttest.dat create mode 100644 testing/tests/ikev2/start-action-start/pretest.dat create mode 100644 testing/tests/ikev2/start-action-start/test.conf diff --git a/testing/tests/ikev2/start-action-start/description.txt b/testing/tests/ikev2/start-action-start/description.txt new file mode 100644 index 0000000000..a755f1ef92 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/description.txt @@ -0,0 +1,3 @@ +This scenario tests start_action=start and its behavior when reloading the +config. To distinguish the different CHILD_SAs, arbitrary TCP ports are used in +the traffic selectors. diff --git a/testing/tests/ikev2/start-action-start/evaltest.dat b/testing/tests/ikev2/start-action-start/evaltest.dat new file mode 100644 index 0000000000..5eeac52c8a --- /dev/null +++ b/testing/tests/ikev2/start-action-start/evaltest.dat @@ -0,0 +1,56 @@ +moon::cat /var/log/daemon.log::vici initiating 'one-start'::YES +moon::cat /var/log/daemon.log::vici initiating 'two-start-.'::2 +moon::cat /var/log/daemon.log::vici initiating 'four-start-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'one-start-child'::YES +moon::cat /var/log/daemon.log::vici initiating 'two-start-child-.'::2 +moon::cat /var/log/daemon.log::vici initiating 'four-start-child-.'::4 +moon::mv /etc/swanctl/swanctl-update.conf /etc/swanctl/conf.d/ +moon::systemctl reload strongswan +moon::sleep 3 +moon::cat /var/log/daemon.log::replaced vici connection: one-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'one-start'::YES +moon::cat /var/log/daemon.log::replaced vici connection: two-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'two-start'::YES +moon::cat /var/log/daemon.log::replaced vici connection: four-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'four-start'::YES +moon::cat /var/log/daemon.log::updated vici connection: one-start-child::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'one-start-child'::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'one-start-child'::YES +moon::cat /var/log/daemon.log::updated vici connection: two-start-child::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'two-start-child'::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'two-start-child-.'::2 +moon::cat /var/log/daemon.log::updated vici connection: four-start-child::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'four-start-child'::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'four-start-child-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'one-start'::2 +moon::cat /var/log/daemon.log::vici initiating 'two-start-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'four-start-.'::8 +moon::cat /var/log/daemon.log::vici initiating 'one-start-child'::2 +moon::cat /var/log/daemon.log::vici initiating 'two-start-child-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'four-start-child-.'::8 +moon::rm /etc/swanctl/conf.d/* +moon::mv /etc/swanctl/swanctl-remove.conf /etc/swanctl/conf.d/ +moon::systemctl reload strongswan +moon::sleep 3 +moon::cat /var/log/daemon.log::removed vici connection: one-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'one-start'::2 +moon::cat /var/log/daemon.log::removed vici connection: two-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'two-start'::2 +moon::cat /var/log/daemon.log::removed vici connection: four-start::YES +moon::cat /var/log/daemon.log::vici closing IKE_SA 'four-start'::2 +moon::cat /var/log/daemon.log::updated vici connection: one-start-child::2 +moon::cat /var/log/daemon.log::vici closing IKE_SA 'one-start-child'::YES +moon::cat /var/log/daemon.log::updated vici connection: two-start-child::2 +moon::cat /var/log/daemon.log::vici closing IKE_SA 'two-start-child'::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'two-start-child-1' #..::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'two-start-child-2' #..::YES +moon::cat /var/log/daemon.log::updated vici connection: four-start-child::2 +moon::cat /var/log/daemon.log::vici closing IKE_SA 'four-start-child'::NO +moon::cat /var/log/daemon.log::vici closing CHILD_SA 'four-start-child-.'::8 +# only the last one here should change +moon::cat /var/log/daemon.log::vici initiating 'one-start'::2 +moon::cat /var/log/daemon.log::vici initiating 'two-start-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'four-start-.'::8 +moon::cat /var/log/daemon.log::vici initiating 'one-start-child'::2 +moon::cat /var/log/daemon.log::vici initiating 'two-start-child-.'::4 +moon::cat /var/log/daemon.log::vici initiating 'four-start-child-.'::10 diff --git a/testing/tests/ikev2/start-action-start/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/start-action-start/hosts/moon/etc/strongswan.conf new file mode 100644 index 0000000000..b4864e158d --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/moon/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon-systemd { + load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/conf.d/swanctl-base.conf b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/conf.d/swanctl-base.conf new file mode 100755 index 0000000000..6cac0d73a8 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/conf.d/swanctl-base.conf @@ -0,0 +1,161 @@ +# basic settings for these test configs +base-conn { + local_addrs = 192.168.0.1 + remote_addrs = 192.168.0.2 + + local { + auth = psk + } + remote { + auth = psk + } +} + +connections { + + # when updating, we'll change ike/peer parameters for these + + one-start : base-conn { + local { + id = moon-one + } + remote { + id = sun-one + } + children { + one-start { + local_ts = dynamic[tcp/1001] + remote_ts = dynamic[tcp/1001] + start_action = start + } + } + } + + two-start : base-conn { + local { + id = moon-two + } + remote { + id = sun-two + } + children { + two-start-1 { + local_ts = dynamic[tcp/2001] + remote_ts = dynamic[tcp/2001] + start_action = start + } + two-start-2 { + local_ts = dynamic[tcp/2002] + remote_ts = dynamic[tcp/2002] + start_action = start + } + } + } + + four-start : base-conn { + local { + id = moon-four + } + remote { + id = sun-four + } + children { + four-start-1 { + local_ts = dynamic[tcp/4001] + remote_ts = dynamic[tcp/4001] + start_action = start + } + four-start-2 { + local_ts = dynamic[tcp/4002] + remote_ts = dynamic[tcp/4002] + start_action = start + } + four-start-3 { + local_ts = dynamic[tcp/4003] + remote_ts = dynamic[tcp/4003] + start_action = start + } + four-start-4 { + local_ts = dynamic[tcp/4004] + remote_ts = dynamic[tcp/4004] + start_action = start + } + } + } + + # when updating, we'll change only child parameters for these + + one-start-child : base-conn { + local { + id = moon-one-child + } + remote { + id = sun-one-child + } + children { + one-start-child { + local_ts = dynamic[tcp/1101] + remote_ts = dynamic[tcp/1101] + start_action = start + } + } + } + + two-start-child : base-conn { + local { + id = moon-two-child + } + remote { + id = sun-two-child + } + children { + two-start-child-1 { + local_ts = dynamic[tcp/2201] + remote_ts = dynamic[tcp/2201] + start_action = start + } + two-start-child-2 { + local_ts = dynamic[tcp/2202] + remote_ts = dynamic[tcp/2202] + start_action = start + } + } + } + + four-start-child : base-conn { + local { + id = moon-four-child + } + remote { + id = sun-four-child + } + children { + four-start-child-1 { + local_ts = dynamic[tcp/4401] + remote_ts = dynamic[tcp/4401] + start_action = start + } + four-start-child-2 { + local_ts = dynamic[tcp/4402] + remote_ts = dynamic[tcp/4402] + start_action = start + } + four-start-child-3 { + local_ts = dynamic[tcp/4403] + remote_ts = dynamic[tcp/4403] + start_action = start + } + four-start-child-4 { + local_ts = dynamic[tcp/4404] + remote_ts = dynamic[tcp/4404] + start_action = start + } + } + } +} + +secrets { + ike { + secret = 0sv+NkxY9LLZvwj4qCC2o/gGrWDF2d21jL + } +} diff --git a/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-remove.conf b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-remove.conf new file mode 100755 index 0000000000..476b784bce --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-remove.conf @@ -0,0 +1,75 @@ +# basic settings for these test configs +base-conn { + local_addrs = 192.168.0.1 + remote_addrs = 192.168.0.2 + + local { + auth = psk + } + remote { + auth = psk + } +} + +connections { + + # the initial connections are removed completely + + # here all child configs are removed + one-start-child : base-conn { + local { + id = moon-one-child + } + remote { + id = sun-one-child + } + } + + # here only one is removed, the other remains unchanged + two-start-child : base-conn { + local { + id = moon-two-child + } + remote { + id = sun-two-child + } + children { + two-start-child-1 { + local_ts = dynamic[tcp/2201] + remote_ts = dynamic[tcp/2201] + rekey_time = 42m + start_action = start + } + } + } + + # here two are removed, the others are updated + four-start-child : base-conn { + local { + id = moon-four-child + } + remote { + id = sun-four-child + } + children { + four-start-child-1 { + local_ts = dynamic[tcp/4401] + remote_ts = dynamic[tcp/4401] + rekey_time = 420m + start_action = start + } + four-start-child-2 { + local_ts = dynamic[tcp/4402] + remote_ts = dynamic[tcp/4402] + rekey_time = 420m + start_action = start + } + } + } +} + +secrets { + ike { + secret = 0sv+NkxY9LLZvwj4qCC2o/gGrWDF2d21jL + } +} diff --git a/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-update.conf b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-update.conf new file mode 100755 index 0000000000..fc2497f984 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl-update.conf @@ -0,0 +1,56 @@ +connections { + + # update the rekey time for the IKE_SA for the first connections, so they + # get replaced completely + + one-start { + rekey_time = 42m + } + + two-start { + rekey_time = 42m + } + + four-start { + rekey_time = 42m + } + + # for these connections, the rekey time for the children is updated, so the + # IKE_SAs should remain + + one-start-child { + children { + one-start-child { + rekey_time = 42m + } + } + } + + two-start-child { + children { + two-start-child-1 { + rekey_time = 42m + } + two-start-child-2 { + rekey_time = 42m + } + } + } + + four-start-child { + children { + four-start-child-1 { + rekey_time = 42m + } + four-start-child-2 { + rekey_time = 42m + } + four-start-child-3 { + rekey_time = 42m + } + four-start-child-4 { + rekey_time = 42m + } + } + } +} diff --git a/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl.conf new file mode 100755 index 0000000000..94b1a419cd --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/moon/etc/swanctl/swanctl.conf @@ -0,0 +1,2 @@ +# include config files from conf.d/ +include conf.d/*.conf diff --git a/testing/tests/ikev2/start-action-start/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/start-action-start/hosts/sun/etc/strongswan.conf new file mode 100644 index 0000000000..b21f14de58 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/sun/etc/strongswan.conf @@ -0,0 +1,8 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon-systemd { + load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default updown + + # disable DoS protection as the initator will create a lot of IKE_SAs in this scenario + dos_protection = no +} diff --git a/testing/tests/ikev2/start-action-start/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/ikev2/start-action-start/hosts/sun/etc/swanctl/swanctl.conf new file mode 100755 index 0000000000..6550cce0fd --- /dev/null +++ b/testing/tests/ikev2/start-action-start/hosts/sun/etc/swanctl/swanctl.conf @@ -0,0 +1,143 @@ +# basic settings for these test configs +base-conn { + local_addrs = 192.168.0.2 + remote_addrs = 192.168.0.1 + + local { + auth = psk + } + remote { + auth = psk + } +} + +connections { + + one-start : base-conn { + local { + id = sun-one + } + remote { + id = moon-one + } + children { + one-start { + local_ts = dynamic[tcp/1001] + remote_ts = dynamic[tcp/1001] + } + } + } + + two-start : base-conn { + local { + id = sun-two + } + remote { + id = moon-two + } + children { + two-start-1 { + local_ts = dynamic[tcp/2001] + remote_ts = dynamic[tcp/2001] + } + two-start-2 { + local_ts = dynamic[tcp/2002] + remote_ts = dynamic[tcp/2002] + } + } + } + + four-start : base-conn { + local { + id = sun-four + } + remote { + id = moon-four + } + children { + four-start-1 { + local_ts = dynamic[tcp/4001] + remote_ts = dynamic[tcp/4001] + } + four-start-2 { + local_ts = dynamic[tcp/4002] + remote_ts = dynamic[tcp/4002] + } + four-start-3 { + local_ts = dynamic[tcp/4003] + remote_ts = dynamic[tcp/4003] + } + four-start-4 { + local_ts = dynamic[tcp/4004] + remote_ts = dynamic[tcp/4004] + } + } + } + + one-start-child : base-conn { + local { + id = sun-one-child + } + remote { + id = moon-one-child + } + children { + one-start-child { + local_ts = dynamic[tcp/1101] + remote_ts = dynamic[tcp/1101] + } + } + } + + two-start-child : base-conn { + local { + id = sun-two-child + } + remote { + id = moon-two-child + } + children { + two-start-child-1 { + local_ts = dynamic[tcp/2201] + remote_ts = dynamic[tcp/2201] + } + two-start-child-2 { + local_ts = dynamic[tcp/2202] + remote_ts = dynamic[tcp/2202] + } + } + } + + four-start-child : base-conn { + local { + id = sun-four-child + } + remote { + id = moon-four-child + } + children { + four-start-child-1 { + local_ts = dynamic[tcp/4401] + remote_ts = dynamic[tcp/4401] + } + four-start-child-2 { + local_ts = dynamic[tcp/4402] + remote_ts = dynamic[tcp/4402] + } + four-start-child-3 { + local_ts = dynamic[tcp/4403] + remote_ts = dynamic[tcp/4403] + } + four-start-child-4 { + local_ts = dynamic[tcp/4404] + remote_ts = dynamic[tcp/4404] + } + } + } +} + +secrets { + ike { + secret = 0sv+NkxY9LLZvwj4qCC2o/gGrWDF2d21jL + } +} diff --git a/testing/tests/ikev2/start-action-start/posttest.dat b/testing/tests/ikev2/start-action-start/posttest.dat new file mode 100644 index 0000000000..61ea51e535 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/posttest.dat @@ -0,0 +1,5 @@ +sun::systemctl stop strongswan +moon::systemctl stop strongswan +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush +moon::rm -rf /etc/swanctl/conf.d/ diff --git a/testing/tests/ikev2/start-action-start/pretest.dat b/testing/tests/ikev2/start-action-start/pretest.dat new file mode 100644 index 0000000000..be5c90b080 --- /dev/null +++ b/testing/tests/ikev2/start-action-start/pretest.dat @@ -0,0 +1,6 @@ +moon::iptables-restore < /etc/iptables.rules +sun::iptables-restore < /etc/iptables.rules +sun::systemctl start strongswan +sun::expect-connection four-start-child +moon::systemctl start strongswan +moon::sleep 3 diff --git a/testing/tests/ikev2/start-action-start/test.conf b/testing/tests/ikev2/start-action-start/test.conf new file mode 100644 index 0000000000..d3016a886c --- /dev/null +++ b/testing/tests/ikev2/start-action-start/test.conf @@ -0,0 +1,25 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon winnetou sun bob" + +# Corresponding block diagram +# +DIAGRAM="a-m-w-s-b.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon sun" + +# charon controlled by swanctl +# +SWANCTL=1