Annotation of embedaddon/strongswan/src/libcharon/tests/suites/test_child_delete.c, revision 1.1.1.1
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>