summaryrefslogtreecommitdiff
path: root/src/libcharon/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/tests')
-rw-r--r--src/libcharon/tests/Makefile.in2
-rw-r--r--src/libcharon/tests/suites/test_child_rekey.c617
-rw-r--r--src/libcharon/tests/utils/exchange_test_asserts.c57
-rw-r--r--src/libcharon/tests/utils/exchange_test_asserts.h61
-rw-r--r--src/libcharon/tests/utils/mock_ipsec.c179
-rw-r--r--src/libcharon/tests/utils/mock_ipsec.h11
-rw-r--r--src/libcharon/tests/utils/sa_asserts.h32
7 files changed, 813 insertions, 146 deletions
diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in
index e922a7171..3070f429b 100644
--- a/src/libcharon/tests/Makefile.in
+++ b/src/libcharon/tests/Makefile.in
@@ -380,6 +380,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -402,6 +403,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/tests/suites/test_child_rekey.c b/src/libcharon/tests/suites/test_child_rekey.c
index fcac49388..76b23f589 100644
--- a/src/libcharon/tests/suites/test_child_rekey.c
+++ b/src/libcharon/tests/suites/test_child_rekey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,7 +28,23 @@
assert_hook_not_called(child_updown); \
assert_hook_not_called(child_rekey); \
call_ikesa(sa, rekey_child_sa, PROTO_ESP, spi); \
- assert_child_sa_state(sa, spi, CHILD_REKEYING); \
+ assert_child_sa_state(sa, spi, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); \
+ assert_hook(); \
+ assert_hook(); \
+})
+
+/**
+ * Destroy a rekeyed CHILD_SA that was kept around to accept inbound traffic.
+ * Simulates the job that's scheduled to do this.
+ */
+#define destroy_rekeyed(sa, spi) ({ \
+ assert_hook_not_called(child_updown); \
+ assert_hook_not_called(child_rekey); \
+ assert_no_jobs_scheduled(); \
+ assert_child_sa_state(sa, spi, CHILD_DELETING, CHILD_OUTBOUND_NONE); \
+ call_ikesa(sa, delete_child_sa, PROTO_ESP, spi, FALSE); \
+ assert_child_sa_not_exists(sa, spi); \
+ assert_scheduler(); \
assert_hook(); \
assert_hook(); \
})
@@ -53,6 +69,7 @@ START_TEST(test_regular)
&a, &b, NULL);
}
initiate_rekey(a, spi_a);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -61,33 +78,51 @@ START_TEST(test_regular)
assert_hook_called(child_rekey);
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, spi_b, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, spi_a, spi_b, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
assert_hook_called(child_rekey);
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, spi_a, spi_b, 3, 4);
assert_hook();
/* INFORMATIONAL { D } --> */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, spi_b, 3, 4);
+ assert_scheduler();
assert_hook();
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, spi_a, 3, 4);
+ assert_scheduler();
assert_hook();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, spi_a);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, spi_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+
/* child_updown */
assert_hook();
@@ -125,6 +160,7 @@ START_TEST(test_regular_ke_invalid)
&a, &b, &conf);
}
initiate_rekey(a, spi_a);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -135,6 +171,7 @@ START_TEST(test_regular_ke_invalid)
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, spi_b, CHILD_INSTALLED);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, spi_a, spi_b);
assert_hook();
/* <-- CREATE_CHILD_SA { N(INVAL_KE) } */
@@ -143,6 +180,7 @@ START_TEST(test_regular_ke_invalid)
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, spi_a, CHILD_REKEYING);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
assert_hook();
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
@@ -150,7 +188,8 @@ START_TEST(test_regular_ke_invalid)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, spi_b, CHILD_REKEYED);
- assert_child_sa_state(b, 6, CHILD_INSTALLED);
+ assert_child_sa_state(b, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, spi_a, spi_b, 6);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -158,24 +197,37 @@ START_TEST(test_regular_ke_invalid)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, spi_a, CHILD_DELETING);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, spi_a, spi_b, 5, 6);
assert_hook();
/* INFORMATIONAL { D } --> */
assert_hook_not_called(child_rekey);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 6, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 6, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, spi_b, 5, 6);
assert_hook();
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_NONE);
assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, spi_a, 5, 6);
assert_hook();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, spi_a);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 5, 6);
+ destroy_rekeyed(b, spi_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 5, 6);
+
/* child_updown */
assert_hook();
@@ -195,6 +247,7 @@ START_TEST(test_regular_responder_ignore_soft_expire)
exchange_test_helper->establish_sa(exchange_test_helper,
&a, &b, NULL);
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -204,7 +257,8 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -212,7 +266,8 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, 1, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
assert_hook();
/* we don't expect this to get called anymore */
@@ -223,15 +278,31 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_child_sa_state(b, 2, CHILD_REKEYED);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 3, 4);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 3, 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, 2);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 3, 4);
/* child_rekey/child_updown */
assert_hook();
@@ -254,6 +325,7 @@ START_TEST(test_regular_responder_handle_hard_expire)
exchange_test_helper->establish_sa(exchange_test_helper,
&a, &b, NULL);
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -263,7 +335,8 @@ START_TEST(test_regular_responder_handle_hard_expire)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -271,7 +344,8 @@ START_TEST(test_regular_responder_handle_hard_expire)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, 1, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
assert_hook();
/* we don't expect this to get called anymore */
@@ -279,28 +353,51 @@ START_TEST(test_regular_responder_handle_hard_expire)
/* this is similar to a regular delete collision */
assert_single_payload(OUT, PLV2_DELETE);
call_ikesa(b, delete_child_sa, PROTO_ESP, 2, TRUE);
- assert_child_sa_state(b, 2, CHILD_DELETING);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ /* since the SAs expired they would not actually be installed in the kernel
+ * anymore and since we have not yet installed a new outbound SA this
+ * will result in dropped packets and possibly acquires */
+ assert_ipsec_sas_installed(b, 1, 2, 4);
/* INFORMATIONAL { D } --> */
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_state(a, 2, CHILD_DELETING);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
/* <-- INFORMATIONAL { D } */
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_state(a, 1, CHILD_DELETING);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
/* <-- INFORMATIONAL { } */
+ assert_jobs_scheduled(1);
assert_message_empty(IN);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 3, 4);
+ assert_scheduler();
/* INFORMATIONAL { } --> */
+ assert_jobs_scheduled(1);
assert_message_empty(IN);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 3, 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 3, 4);
/* child_rekey/child_updown */
assert_hook();
@@ -350,8 +447,10 @@ START_TEST(test_collision)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -360,15 +459,17 @@ START_TEST(test_collision)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 5);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 5, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 5);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 6);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 6, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -378,53 +479,113 @@ START_TEST(test_collision)
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
if (data[_i].spi_del_b == 2)
{
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_ipsec_sas_installed(b, 2, 4, 5, 6,
+ data[_i].spi_del_b == 2 ? 1 : 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 5, 6,
+ data[_i].spi_del_a == 1 ? 2 : 4);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 6,
+ data[_i].spi_del_a == 1 ? 5 : 4);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_ipsec_sas_installed(b, 2, 4, 5,
+ data[_i].spi_del_b == 2 ? 6 : 3);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -483,8 +644,10 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -493,15 +656,17 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 5);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 5, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 5);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 6);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 6, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
assert_hook();
/* delay the CREATE_CHILD_SA response from b to a */
@@ -513,35 +678,68 @@ START_TEST(test_collision_delayed_response)
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
if (data[_i].spi_del_b == 2)
{
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 4, 6);
}
else
{
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
}
+ assert_child_sa_count(a, 2);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ if (data[_i].spi_del_b == 2)
+ {
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 2, 4, 5, 6);
+ }
+ else
+ {
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
+ }
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } (delayed) */
@@ -557,20 +755,54 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->process_message(exchange_test_helper, a, msg);
assert_hook();
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 3, 5, 6,
+ data[_i].spi_del_a == 1 ? 2 : 4);
+ assert_child_sa_count(a, 3);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 2, 4, 5,
+ data[_i].spi_del_b == 2 ? 6 : 3);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 6,
+ data[_i].spi_del_a == 1 ? 5 : 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -621,8 +853,10 @@ START_TEST(test_collision_delayed_request)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* delay the CREATE_CHILD_SA request from a to b */
msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
@@ -634,14 +868,16 @@ START_TEST(test_collision_delayed_request)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 5);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 5);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 4);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
assert_hook();
/* we don't expect this hook to get called anymore */
@@ -650,25 +886,43 @@ START_TEST(test_collision_delayed_request)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> (delayed) */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
+ assert_scheduler();
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 4, 5);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 4, 5);
/* child_rekey/child_updown */
assert_hook();
@@ -722,8 +976,10 @@ START_TEST(test_collision_delayed_request_more)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* delay the CREATE_CHILD_SA request from a to b */
msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
@@ -735,40 +991,62 @@ START_TEST(test_collision_delayed_request_more)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 5);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 5);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 4);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
assert_hook();
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
+ assert_scheduler();
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_single_notify(OUT, CHILD_SA_NOT_FOUND);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
/* <-- CREATE_CHILD_SA { N(NO_CHILD_SA) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
assert_scheduler();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 4, 5);
+ destroy_rekeyed(b, 2);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 4, 5);
+
/* child_rekey/child_updown */
assert_hook();
assert_hook();
@@ -842,13 +1120,13 @@ START_TEST(test_collision_ke_invalid)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
@@ -857,7 +1135,7 @@ START_TEST(test_collision_ke_invalid)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
/* CREATE_CHILD_SA { N(INVAL_KE) } --> */
@@ -865,7 +1143,7 @@ START_TEST(test_collision_ke_invalid)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
@@ -873,15 +1151,15 @@ START_TEST(test_collision_ke_invalid)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 9);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 9, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 9, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 10);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a,10, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a,10, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -891,49 +1169,99 @@ START_TEST(test_collision_ke_invalid)
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
if (data[_i].spi_del_b == 2)
{
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -1004,13 +1332,13 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
@@ -1019,7 +1347,7 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
/* CREATE_CHILD_SA { N(INVAL_KE) } --> */
@@ -1027,7 +1355,7 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
@@ -1038,14 +1366,14 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 9);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 8);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* we don't expect this hook to get called anymore */
@@ -1054,25 +1382,40 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> (delayed) */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_scheduler();
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 8, 9);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 8, 9);
/* child_rekey/child_updown */
assert_hook();
@@ -1114,7 +1457,7 @@ START_TEST(test_collision_delete)
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1129,7 +1472,7 @@ START_TEST(test_collision_delete)
assert_notify(IN, REKEY_SA);
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* RFC 7296, 2.25.1: If a peer receives a request to delete a CHILD_SA that
@@ -1201,7 +1544,7 @@ START_TEST(test_collision_delete_drop_delete)
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1216,7 +1559,7 @@ START_TEST(test_collision_delete_drop_delete)
assert_notify(IN, REKEY_SA);
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* delay the DELETE request */
@@ -1227,7 +1570,7 @@ START_TEST(test_collision_delete_drop_delete)
/* we expect a job to retry the rekeying is scheduled */
assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_scheduler();
assert_hook();
@@ -1286,7 +1629,7 @@ END_TEST
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1419,13 +1762,13 @@ START_TEST(test_collision_ike_rekey)
/* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_REKEYING);
+ assert_child_sa_state(a, spi_a, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
/* we expect a job to retry the rekeying is scheduled */
assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_scheduler();
/* CREATE_CHILD_SA { N(TEMP_FAIL) } --> */
diff --git a/src/libcharon/tests/utils/exchange_test_asserts.c b/src/libcharon/tests/utils/exchange_test_asserts.c
index 2602b97b7..8042d0b63 100644
--- a/src/libcharon/tests/utils/exchange_test_asserts.c
+++ b/src/libcharon/tests/utils/exchange_test_asserts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
#include <test_suite.h>
#include "exchange_test_asserts.h"
+#include "mock_ipsec.h"
/*
* Described in header
@@ -180,3 +181,57 @@ bool exchange_test_asserts_message(listener_t *listener, ike_sa_t *ike_sa,
}
return TRUE;
}
+
+/**
+ * Compare two SPIs
+ */
+static int spis_cmp(const void *a, const void *b)
+{
+ return *(const uint32_t*)a - *(const uint32_t*)b;
+}
+
+/**
+ * Compare two SPIs to sort them
+ */
+static int spis_sort(const void *a, const void *b, void *data)
+{
+ return spis_cmp(a, b);
+}
+
+
+/*
+ * Described in header
+ */
+void exchange_test_asserts_ipsec_sas(ipsec_sas_assert_t *sas)
+{
+ enumerator_t *enumerator;
+ array_t *spis;
+ ike_sa_t *ike_sa;
+ uint32_t spi;
+ int i;
+
+ spis = array_create(sizeof(uint32_t), 0);
+ for (i = 0; i < sas->count; i++)
+ {
+ array_insert(spis, ARRAY_TAIL, &sas->spis[i]);
+ }
+ array_sort(spis, spis_sort, NULL);
+
+ enumerator = mock_ipsec_create_sa_enumerator();
+ while (enumerator->enumerate(enumerator, &ike_sa, &spi))
+ {
+ if (ike_sa == sas->ike_sa)
+ {
+ i = array_bsearch(spis, &spi, spis_cmp, NULL);
+ assert_listener_msg(i != -1, sas, "unexpected IPsec SA %.8x", spi);
+ array_remove(spis, i, NULL);
+ }
+ }
+ enumerator->destroy(enumerator);
+ for (i = 0; i < array_count(spis); i++)
+ {
+ array_get(spis, i, &spi);
+ assert_listener_msg(!spi, sas, "expected IPsec SA %.8x not found", spi);
+ }
+ array_destroy(spis);
+}
diff --git a/src/libcharon/tests/utils/exchange_test_asserts.h b/src/libcharon/tests/utils/exchange_test_asserts.h
index 32afcc2e4..4d363edfd 100644
--- a/src/libcharon/tests/utils/exchange_test_asserts.h
+++ b/src/libcharon/tests/utils/exchange_test_asserts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,7 +14,7 @@
*/
/**
- * Special assertions using listener_t.
+ * Special assertions using listener_t etc.
*
* @defgroup exchange_test_asserts exchange_test_asserts
* @{ @ingroup test_utils_c
@@ -28,6 +28,7 @@
typedef struct listener_hook_assert_t listener_hook_assert_t;
typedef struct listener_message_assert_t listener_message_assert_t;
typedef struct listener_message_rule_t listener_message_rule_t;
+typedef struct ipsec_sas_assert_t ipsec_sas_assert_t;
struct listener_hook_assert_t {
@@ -340,4 +341,60 @@ bool exchange_test_asserts_message(listener_t *this, ike_sa_t *ike_sa,
exchange_test_helper->add_listener(exchange_test_helper, &_listener.listener); \
})
+/**
+ * Data used to check IPsec SAs
+ */
+struct ipsec_sas_assert_t {
+
+ /**
+ * Original source file
+ */
+ const char *file;
+
+ /**
+ * Source line
+ */
+ int line;
+
+ /**
+ * IKE_SA that installed the IPsec SAs
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * SPIs to check
+ */
+ uint32_t *spis;
+
+ /**
+ * Number of SPIs for IPsec SAs to check
+ */
+ int count;
+};
+
+/**
+ * Assert that all given IPsec SAs (and only these) are installed for the given
+ * IKE_SA.
+ */
+void exchange_test_asserts_ipsec_sas(ipsec_sas_assert_t *sas);
+
+/**
+ * Assert that the IPsec SAs with the given SPIs (and none other) are currently
+ * installed by the given IKE_SA.
+ *
+ * @param sa IKE_SA
+ * @param ... list of SPIs
+ */
+#define assert_ipsec_sas_installed(sa, ...) ({ \
+ uint32_t _spis[] = { __VA_ARGS__ }; \
+ ipsec_sas_assert_t _sas_assert = { \
+ .file = __FILE__, \
+ .line = __LINE__, \
+ .ike_sa = sa, \
+ .spis = _spis, \
+ .count = countof(_spis), \
+ }; \
+ exchange_test_asserts_ipsec_sas(&_sas_assert); \
+})
+
#endif /** EXCHANGE_TEST_ASSERTS_H_ @}*/
diff --git a/src/libcharon/tests/utils/mock_ipsec.c b/src/libcharon/tests/utils/mock_ipsec.c
index d57a26a87..d6172f5bd 100644
--- a/src/libcharon/tests/utils/mock_ipsec.c
+++ b/src/libcharon/tests/utils/mock_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,12 @@
#include "mock_ipsec.h"
+#include <daemon.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+
+#include <assert.h>
+
typedef struct private_kernel_ipsec_t private_kernel_ipsec_t;
/**
@@ -29,16 +35,80 @@ struct private_kernel_ipsec_t {
kernel_ipsec_t public;
/**
+ * Rekey listener
+ */
+ listener_t listener;
+
+ /**
* Allocated SPI
*/
refcount_t spi;
+
+ /**
+ * Installed SAs
+ */
+ hashtable_t *sas;
};
+/**
+ * Global instance
+ */
+static private_kernel_ipsec_t *instance;
+
+/**
+ * Data about installed IPsec SAs
+ */
+typedef struct {
+ /**
+ * SPI of the SA
+ */
+ uint32_t spi;
+
+ /**
+ * Associated IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if this was an allocated SPI
+ */
+ bool alloc;
+
+} entry_t;
+
+/**
+ * Hash an IPsec SA entry
+ */
+static u_int entry_hash(const void *key)
+{
+ entry_t *entry = (entry_t*)key;
+ return chunk_hash_inc(chunk_from_thing(entry->spi),
+ chunk_hash(chunk_from_thing(entry->ike_sa)));
+}
+
+/**
+ * Compare an IPsec SA entry
+ */
+static bool entry_equals(const void *key, const void *other_key)
+{
+ entry_t *a = (entry_t*)key, *b = (entry_t*)other_key;
+ return a->spi == b->spi && a->ike_sa == b->ike_sa;
+}
+
METHOD(kernel_ipsec_t, get_spi, status_t,
private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol,
uint32_t *spi)
{
+ entry_t *entry;
+
*spi = (uint32_t)ref_get(&this->spi);
+ INIT(entry,
+ .spi = *spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ .alloc = TRUE,
+ );
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
return SUCCESS;
}
@@ -52,6 +122,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_add_sa_t *data)
{
+ entry_t *entry;
+
+ INIT(entry,
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ );
+ if (data->inbound)
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(entry && entry->alloc);
+ free(entry);
+ }
+ else
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
+ }
return SUCCESS;
}
@@ -74,9 +161,47 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_del_sa_t *data)
{
+ entry_t *entry, lookup = {
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ };
+
+ entry = this->sas->remove(this->sas, &lookup);
+ assert(entry);
+ free(entry);
return SUCCESS;
}
+METHOD(listener_t, ike_rekey, bool,
+ listener_t *listener, ike_sa_t *old, ike_sa_t *new)
+{
+ enumerator_t *enumerator;
+ array_t *sas = NULL;
+ entry_t *entry;
+
+ enumerator = instance->sas->create_enumerator(instance->sas);
+ while (enumerator->enumerate(enumerator, &entry, NULL))
+ {
+ if (entry->ike_sa == old)
+ {
+ instance->sas->remove_at(instance->sas, enumerator);
+ array_insert_create(&sas, ARRAY_TAIL, entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ enumerator = array_create_enumerator(sas);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ array_remove_at(sas, enumerator);
+ entry->ike_sa = new;
+ entry = instance->sas->put(instance->sas, entry, entry);
+ assert(!entry);
+ }
+ enumerator->destroy(enumerator);
+ array_destroy(sas);
+ return TRUE;
+}
+
METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
kernel_ipsec_manage_policy_t *data)
@@ -99,6 +224,14 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_ipsec_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener);
+ this->sas->destroy(this->sas);
+ free(this);
+}
+
/*
* Described in header
*/
@@ -121,8 +254,50 @@ kernel_ipsec_t *mock_ipsec_create()
.flush_policies = (void*)return_failed,
.bypass_socket = (void*)return_true,
.enable_udp_decap = (void*)return_true,
- .destroy = (void*)free,
+ .destroy = _destroy,
+ },
+ .listener = {
+ .ike_rekey = _ike_rekey,
},
+ .sas = hashtable_create(entry_hash, entry_equals, 8),
);
+
+ instance = this;
+
+ charon->bus->add_listener(charon->bus, &this->listener);
+
return &this->public;
}
+
+
+CALLBACK(filter_sas, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ entry_t *entry;
+ ike_sa_t **ike_sa;
+ uint32_t *spi;
+
+ VA_ARGS_VGET(args, ike_sa, spi);
+
+ while (orig->enumerate(orig, &entry, NULL))
+ {
+ if (entry->alloc)
+ {
+ continue;
+ }
+ *ike_sa = entry->ike_sa;
+ *spi = entry->spi;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Described in header
+ */
+enumerator_t *mock_ipsec_create_sa_enumerator()
+{
+ return enumerator_create_filter(
+ instance->sas->create_enumerator(instance->sas),
+ filter_sas, NULL, NULL);
+}
diff --git a/src/libcharon/tests/utils/mock_ipsec.h b/src/libcharon/tests/utils/mock_ipsec.h
index cbf21524a..95038a561 100644
--- a/src/libcharon/tests/utils/mock_ipsec.h
+++ b/src/libcharon/tests/utils/mock_ipsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,7 +15,7 @@
/**
* kernel_ipsec_t implementation used for exchange unit tests. Currently
- * returns sequential SPIs, all other methods are noops.
+ * returns sequential SPIs, and keeps track of installed SAs.
*
* @defgroup mock_ipsec mock_ipsec
* @{ @ingroup test_utils_c
@@ -33,4 +33,11 @@
*/
kernel_ipsec_t *mock_ipsec_create();
+/**
+ * Enumerate the installed SAs
+ *
+ * @return enumerator over (ike_sa_t*, uint32_t)
+ */
+enumerator_t *mock_ipsec_create_sa_enumerator();
+
#endif /** MOCK_IPSEC_H_ @}*/
diff --git a/src/libcharon/tests/utils/sa_asserts.h b/src/libcharon/tests/utils/sa_asserts.h
index 7afa3b55b..d23f724f1 100644
--- a/src/libcharon/tests/utils/sa_asserts.h
+++ b/src/libcharon/tests/utils/sa_asserts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -82,13 +82,38 @@
})
/**
+ * Check if the CHILD_SA with the given SPI is in the expected state, optionally
+ * check the state of the outbound SA.
+ */
+#define assert_child_sa_state(...) VA_ARGS_DISPATCH(assert_child_sa_state, __VA_ARGS__)(__VA_ARGS__)
+
+/**
* Check if the CHILD_SA with the given SPI is in the expected state.
*/
-#define assert_child_sa_state(ike_sa, spi, state) \
+#define assert_child_sa_state3(ike_sa, spi, state) \
+({ \
+ typeof(ike_sa) _sa = ike_sa; \
+ typeof(spi) _spi = spi; \
+ typeof(state) _state = state; \
+ child_sa_t *_child = _sa->get_child_sa(_sa, PROTO_ESP, _spi, TRUE) ?: \
+ _sa->get_child_sa(_sa, PROTO_ESP, _spi, FALSE); \
+ test_assert_msg(_child, "CHILD_SA with SPI %.8x does not exist", \
+ ntohl(_spi)); \
+ test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
+ child_sa_state_names, _state, \
+ child_sa_state_names, _child->get_state(_child)); \
+})
+
+/**
+ * Check if the outbound SA of a CHILD_SA with the given SPI is in the
+ * expected state.
+ */
+#define assert_child_sa_state4(ike_sa, spi, state, outbound) \
({ \
typeof(ike_sa) _sa = ike_sa; \
typeof(spi) _spi = spi; \
typeof(state) _state = state; \
+ typeof(outbound) _outbound = outbound; \
child_sa_t *_child = _sa->get_child_sa(_sa, PROTO_ESP, _spi, TRUE) ?: \
_sa->get_child_sa(_sa, PROTO_ESP, _spi, FALSE); \
test_assert_msg(_child, "CHILD_SA with SPI %.8x does not exist", \
@@ -96,6 +121,9 @@
test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
child_sa_state_names, _state, \
child_sa_state_names, _child->get_state(_child)); \
+ test_assert_msg(_outbound == _child->get_outbound_state(_child), "%N != %N", \
+ child_sa_outbound_state_names, _outbound, \
+ child_sa_outbound_state_names, _child->get_outbound_state(_child)); \
})
/**