kernel-netlink: Support extended table IDs for custom routes
[strongswan.git] / src / libcharon / tests / suites / test_child_delete.c
1 /*
2 * Copyright (C) 2016 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <daemon.h>
19 #include <tests/utils/exchange_test_helper.h>
20 #include <tests/utils/exchange_test_asserts.h>
21 #include <tests/utils/job_asserts.h>
22 #include <tests/utils/sa_asserts.h>
23
24 /**
25 * Regular CHILD_SA deletion either initiated by the original initiator or
26 * responder of the IKE_SA.
27 */
28 START_TEST(test_regular)
29 {
30 ike_sa_t *a, *b;
31
32 if (_i)
33 { /* responder deletes the CHILD_SA (SPI 2) */
34 exchange_test_helper->establish_sa(exchange_test_helper,
35 &b, &a, NULL);
36 }
37 else
38 { /* initiator deletes the CHILD_SA (SPI 1) */
39 exchange_test_helper->establish_sa(exchange_test_helper,
40 &a, &b, NULL);
41 }
42 assert_hook_not_called(child_updown);
43 call_ikesa(a, delete_child_sa, PROTO_ESP, _i+1, FALSE);
44 assert_child_sa_state(a, _i+1, CHILD_DELETING);
45 assert_hook();
46
47 /* INFORMATIONAL { D } --> */
48 assert_hook_updown(child_updown, FALSE);
49 assert_single_payload(IN, PLV2_DELETE);
50 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
51 assert_child_sa_count(b, 0);
52 assert_hook();
53
54 /* <-- INFORMATIONAL { D } */
55 assert_hook_updown(child_updown, FALSE);
56 assert_single_payload(IN, PLV2_DELETE);
57 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
58 assert_child_sa_count(a, 0);
59 assert_hook();
60
61 call_ikesa(a, destroy);
62 call_ikesa(b, destroy);
63 }
64 END_TEST
65
66 /**
67 * Both peers initiate the CHILD_SA deletion concurrently and should handle
68 * the collision properly.
69 */
70 START_TEST(test_collision)
71 {
72 ike_sa_t *a, *b;
73
74 exchange_test_helper->establish_sa(exchange_test_helper,
75 &a, &b, NULL);
76 /* both peers delete the CHILD_SA concurrently */
77 assert_hook_not_called(child_updown);
78 call_ikesa(a, delete_child_sa, PROTO_ESP, 1, FALSE);
79 assert_child_sa_state(a, 1, CHILD_DELETING);
80 call_ikesa(b, delete_child_sa, PROTO_ESP, 2, FALSE);
81 assert_child_sa_state(b, 2, CHILD_DELETING);
82 assert_hook();
83
84 /* RFC 7296 says:
85 *
86 * Normally, the response in the INFORMATIONAL exchange will contain
87 * Delete payloads for the paired SAs going in the other direction.
88 * There is one exception. If, by chance, both ends of a set of SAs
89 * independently decide to close them, each may send a Delete payload
90 * and the two requests may cross in the network. If a node receives a
91 * delete request for SAs for which it has already issued a delete
92 * request, it MUST delete the outgoing SAs while processing the request
93 * and the incoming SAs while processing the response. In that case,
94 * the responses MUST NOT include Delete payloads for the deleted SAs,
95 * since that would result in duplicate deletion and could in theory
96 * delete the wrong SA.
97 *
98 * We don't handle SAs separately so we expect both are still installed,
99 * but the INFORMATIONAL response should not contain a DELETE payload.
100 */
101
102 /* INFORMATIONAL { D } --> */
103 assert_hook_not_called(child_updown);
104 assert_single_payload(IN, PLV2_DELETE);
105 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
106 assert_child_sa_state(b, 2, CHILD_DELETING);
107 /* <-- INFORMATIONAL { D } */
108 assert_single_payload(IN, PLV2_DELETE);
109 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
110 assert_child_sa_state(a, 1, CHILD_DELETING);
111 assert_hook();
112
113 /* <-- INFORMATIONAL { } */
114 assert_hook_updown(child_updown, FALSE);
115 assert_message_empty(IN);
116 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
117 assert_child_sa_count(a, 0);
118 assert_hook();
119 /* INFORMATIONAL { } --> */
120 assert_hook_updown(child_updown, FALSE);
121 assert_message_empty(IN);
122 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
123 assert_child_sa_count(b, 0);
124 assert_hook();
125
126 call_ikesa(a, destroy);
127 call_ikesa(b, destroy);
128 }
129 END_TEST
130
131 /**
132 * This is like the collision above but one of the DELETEs is dropped or delayed
133 * so the other peer is not aware that there is a collision.
134 */
135 START_TEST(test_collision_drop)
136 {
137 ike_sa_t *a, *b;
138 message_t *msg;
139
140 exchange_test_helper->establish_sa(exchange_test_helper,
141 &a, &b, NULL);
142 /* both peers delete the CHILD_SA concurrently */
143 assert_hook_not_called(child_updown);
144 call_ikesa(a, delete_child_sa, PROTO_ESP, 1, FALSE);
145 assert_child_sa_state(a, 1, CHILD_DELETING);
146 call_ikesa(b, delete_child_sa, PROTO_ESP, 2, FALSE);
147 assert_child_sa_state(b, 2, CHILD_DELETING);
148 assert_hook();
149
150 /* INFORMATIONAL { D } --> */
151 assert_hook_not_called(child_updown);
152 assert_single_payload(IN, PLV2_DELETE);
153 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
154 assert_child_sa_state(b, 2, CHILD_DELETING);
155 assert_hook();
156
157 /* drop/delay the responder's message */
158 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
159
160 /* <-- INFORMATIONAL { } */
161 assert_hook_updown(child_updown, FALSE);
162 assert_message_empty(IN);
163 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
164 assert_child_sa_count(a, 0);
165 assert_hook();
166
167 /* <-- INFORMATIONAL { D } (delayed/retransmitted) */
168 assert_hook_not_called(child_updown);
169 assert_single_payload(IN, PLV2_DELETE);
170 exchange_test_helper->process_message(exchange_test_helper, a, msg);
171 assert_hook();
172
173 /* INFORMATIONAL { } --> */
174 assert_hook_updown(child_updown, FALSE);
175 assert_message_empty(IN);
176 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
177 assert_child_sa_count(b, 0);
178 assert_hook();
179
180 call_ikesa(a, destroy);
181 call_ikesa(b, destroy);
182 }
183 END_TEST
184
185 /**
186 * One of the hosts initiates a rekey of the IKE_SA of the CHILD_SA the other
187 * peer is concurrently trying to delete.
188 *
189 * delete ----\ /---- rekey IKE
190 * \-----/----> detect collision
191 * detect collision <---------/ /---- delete
192 * TEMP_FAIL ----\ /
193 * \----/----->
194 * <--------/
195 */
196 START_TEST(test_collision_ike_rekey)
197 {
198 ike_sa_t *a, *b;
199 uint32_t spi_a = _i+1;
200
201 if (_i)
202 { /* responder deletes the CHILD_SA (SPI 2) */
203 exchange_test_helper->establish_sa(exchange_test_helper,
204 &b, &a, NULL);
205 }
206 else
207 { /* initiator deletes the CHILD_SA (SPI 1) */
208 exchange_test_helper->establish_sa(exchange_test_helper,
209 &a, &b, NULL);
210 }
211 call_ikesa(a, delete_child_sa, PROTO_ESP, spi_a, FALSE);
212 assert_child_sa_state(a, spi_a, CHILD_DELETING);
213 call_ikesa(b, rekey);
214 assert_ike_sa_state(b, IKE_REKEYING);
215
216 /* this should never get called as there is no successful rekeying */
217 assert_hook_not_called(ike_rekey);
218
219 /* RFC 7296, 2.25.2: If a peer receives a request to delete a Child SA when
220 * it is currently rekeying the IKE SA, it SHOULD reply as usual, with a
221 * Delete payload.
222 */
223
224 /* INFORMATIONAL { D } --> */
225 assert_hook_updown(child_updown, FALSE);
226 assert_single_payload(OUT, PLV2_DELETE);
227 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
228 assert_ike_sa_state(b, IKE_REKEYING);
229 assert_child_sa_count(b, 0);
230 assert_hook();
231
232 /* RFC 7296, 2.25.1: If a peer receives a request to rekey the IKE SA, and
233 * it is currently, rekeying, or closing a Child SA of that IKE SA, it
234 * SHOULD reply with TEMPORARY_FAILURE.
235 */
236
237 /* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
238 assert_single_notify(OUT, TEMPORARY_FAILURE);
239 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
240 assert_child_sa_state(a, spi_a, CHILD_DELETING);
241
242 /* <-- INFORMATIONAL { D } */
243 assert_hook_updown(child_updown, FALSE);
244 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
245 assert_child_sa_count(a, 0);
246 assert_hook();
247
248 /* CREATE_CHILD_SA { N(TEMP_FAIL) } --> */
249 /* we expect a job to retry the rekeying is scheduled */
250 assert_jobs_scheduled(1);
251 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
252 assert_ike_sa_state(b, IKE_ESTABLISHED);
253 assert_scheduler();
254
255 /* ike_rekey */
256 assert_hook();
257
258 call_ikesa(a, destroy);
259 call_ikesa(b, destroy);
260 }
261 END_TEST
262
263 /**
264 * One of the hosts initiates a delete of the IKE_SA of the CHILD_SA the other
265 * peer is concurrently trying to delete.
266 *
267 * delete ----\ /---- delete IKE
268 * \-----/----> detect collision
269 * <---------/ /---- delete
270 * delete ----\ /
271 * \----/----->
272 * sa already gone <--------/
273 */
274 START_TEST(test_collision_ike_delete)
275 {
276 ike_sa_t *a, *b;
277 uint32_t spi_a = _i+1;
278 message_t *msg;
279 status_t s;
280
281 if (_i)
282 { /* responder rekeys the CHILD_SA (SPI 2) */
283 exchange_test_helper->establish_sa(exchange_test_helper,
284 &b, &a, NULL);
285 }
286 else
287 { /* initiator rekeys the CHILD_SA (SPI 1) */
288 exchange_test_helper->establish_sa(exchange_test_helper,
289 &a, &b, NULL);
290 }
291 call_ikesa(a, delete_child_sa, PROTO_ESP, spi_a, FALSE);
292 assert_child_sa_state(a, spi_a, CHILD_DELETING);
293 call_ikesa(b, delete, FALSE);
294 assert_ike_sa_state(b, IKE_DELETING);
295
296 /* RFC 7296, 2.25.2 does not explicitly state what the behavior SHOULD be if
297 * a peer receives a request to delete a CHILD_SA when it is currently
298 * closing the IKE SA. We expect a regular response.
299 */
300
301 /* INFORMATIONAL { D } --> */
302 assert_hook_updown(child_updown, FALSE);
303 assert_single_payload(OUT, PLV2_DELETE);
304 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
305 assert_ike_sa_state(b, IKE_DELETING);
306 assert_child_sa_count(b, 0);
307 assert_hook();
308
309 /* RFC 7296, 2.25.1 does not explicitly state what the behavior SHOULD be if
310 * a peer receives a request to close the IKE SA if it is currently deleting
311 * a Child SA of that IKE SA. Let's just close the IKE_SA and forget the
312 * delete.
313 */
314
315 /* <-- INFORMATIONAL { D } */
316 assert_hook_updown(ike_updown, FALSE);
317 assert_hook_updown(child_updown, FALSE);
318 assert_message_empty(OUT);
319 s = exchange_test_helper->process_message(exchange_test_helper, a, NULL);
320 ck_assert_int_eq(DESTROY_ME, s);
321 call_ikesa(a, destroy);
322 assert_hook();
323 assert_hook();
324
325 /* <-- INFORMATIONAL { D } */
326 /* the SA is already gone */
327 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
328 msg->destroy(msg);
329
330 /* INFORMATIONAL { } --> */
331 assert_hook_updown(ike_updown, FALSE);
332 assert_hook_not_called(child_updown);
333 s = exchange_test_helper->process_message(exchange_test_helper, b, NULL);
334 ck_assert_int_eq(DESTROY_ME, s);
335 call_ikesa(b, destroy);
336 assert_hook();
337 assert_hook();
338 }
339 END_TEST
340
341 Suite *child_delete_suite_create()
342 {
343 Suite *s;
344 TCase *tc;
345
346 s = suite_create("child delete");
347
348 tc = tcase_create("regular");
349 tcase_add_loop_test(tc, test_regular, 0, 2);
350 suite_add_tcase(s, tc);
351
352 tc = tcase_create("collisions");
353 tcase_add_test(tc, test_collision);
354 tcase_add_test(tc, test_collision_drop);
355 suite_add_tcase(s, tc);
356
357 tc = tcase_create("collisions ike rekey");
358 tcase_add_loop_test(tc, test_collision_ike_rekey, 0, 2);
359 suite_add_tcase(s, tc);
360
361 tc = tcase_create("collisions ike delete");
362 tcase_add_loop_test(tc, test_collision_ike_delete, 0, 2);
363 suite_add_tcase(s, tc);
364
365 return s;
366 }