kernel-netlink: Support extended table IDs for custom routes
[strongswan.git] / src / libcharon / tests / suites / test_ike_mid_sync.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 <tests/utils/exchange_test_helper.h>
19 #include <tests/utils/exchange_test_asserts.h>
20 #include <tests/utils/sa_asserts.h>
21 #include <bio/bio_reader.h>
22 #include <bio/bio_writer.h>
23
24 /**
25 * FIXME: Since we don't have the server side yet, this is kind of a hack!!!
26 */
27
28 /**
29 * Add the IKEV2_MESSAGE_ID_SYNC_SUPPORTED notify to the IKE_AUTH response
30 */
31 static bool add_notify(listener_t *listener, ike_sa_t *ike_sa,
32 message_t *message, bool incoming, bool plain)
33 {
34 if (plain && !incoming && message->get_exchange_type(message) == IKE_AUTH &&
35 !message->get_request(message))
36 {
37 message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
38 chunk_empty);
39 return FALSE;
40 }
41 return TRUE;
42 }
43 #define add_notify_to_ike_auth() ({ \
44 listener_t _notify_listener = { \
45 .message = add_notify, \
46 }; \
47 exchange_test_helper->add_listener(exchange_test_helper, &_notify_listener); \
48 })
49
50 /**
51 * Handle IKEV2_MESSAGE_ID_SYNC notifies
52 */
53 typedef struct {
54 listener_t listener;
55 struct {
56 chunk_t nonce;
57 uint32_t send;
58 uint32_t recv;
59 } init, resp;
60 } mid_sync_listener_t;
61
62 static bool handle_mid(listener_t *listener,
63 ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
64 {
65 mid_sync_listener_t *this = (mid_sync_listener_t*)listener;
66
67 if (!plain || incoming)
68 {
69 return TRUE;
70 }
71
72 if (message->get_exchange_type(message) == INFORMATIONAL)
73 {
74 if (streq("resp", ike_sa->get_name(ike_sa)))
75 {
76 bio_writer_t *writer;
77 rng_t *rng;
78
79 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
80 ignore_result(rng->allocate_bytes(rng, 4, &this->init.nonce));
81 rng->destroy(rng);
82 writer = bio_writer_create(12);
83 writer->write_data(writer, this->init.nonce);
84 writer->write_uint32(writer, this->init.send);
85 writer->write_uint32(writer, this->init.recv);
86 message->set_message_id(message, 0);
87 message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC,
88 writer->get_buf(writer));
89 writer->destroy(writer);
90 }
91 else
92 {
93 notify_payload_t *notify;
94 bio_reader_t *reader;
95
96 notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC);
97 reader = bio_reader_create(notify->get_notification_data(notify));
98 chunk_clear(&this->resp.nonce);
99 reader->read_data(reader, 4, &this->resp.nonce);
100 this->resp.nonce = chunk_clone(this->resp.nonce);
101 reader->read_uint32(reader, &this->resp.send);
102 reader->read_uint32(reader, &this->resp.recv);
103 reader->destroy(reader);
104 }
105 }
106 return TRUE;
107 }
108
109 /**
110 * Send a MESSAGE_ID_SYNC notify in an INFORMATIONAL. We reset the state
111 * afterwards so this seems as if nothing happened.
112 */
113 static void send_mid_sync(ike_sa_t *sa, uint32_t send, uint32_t recv)
114 {
115 call_ikesa(sa, send_dpd);
116 sa->set_message_id(sa, TRUE, send);
117 sa->set_message_id(sa, FALSE, recv);
118 sa->flush_queue(sa, TASK_QUEUE_QUEUED);
119 }
120
121 /**
122 * Send a regular DPD from one IKE_SA to another
123 */
124 static void send_dpd(ike_sa_t *from, ike_sa_t *to)
125 {
126 uint32_t send, recv;
127
128 send = from->get_message_id(from, TRUE);
129 recv = to->get_message_id(to, FALSE);
130 call_ikesa(from, send_dpd);
131 exchange_test_helper->process_message(exchange_test_helper, to, NULL);
132 exchange_test_helper->process_message(exchange_test_helper, from, NULL);
133 ck_assert_int_eq(send + 1, from->get_message_id(from, TRUE));
134 ck_assert_int_eq(recv + 1, to->get_message_id(to, FALSE));
135 }
136
137 /**
138 * Send a number of DPDs from on IKE_SA to the other
139 */
140 static void send_dpds(ike_sa_t *from, ike_sa_t *to, int count)
141 {
142 while (count--)
143 {
144 send_dpd(from, to);
145 }
146 }
147
148 static struct {
149 int dpds_a, dpds_b;
150 uint32_t send, recv;
151 } data[] = {
152 { 0, 0, 0, 2 },
153 { 0, 0, 1, 3 },
154 { 1, 0, 0, 3 },
155 { 1, 0, 5, 8 },
156 { 0, 1, 1, 2 },
157 { 0, 1, 2, 2 },
158 { 1, 1, 1, 3 },
159 { 1, 1, 2, 4 },
160 { 1, 2, 2, 4 },
161 };
162
163 /**
164 * The responder syncs message IDs with the initiator
165 */
166 START_TEST(test_responder)
167 {
168 ike_sa_t *a, *b;
169 mid_sync_listener_t mid = {
170 .listener = { .message = (void*)handle_mid, },
171 .init = {
172 .send = data[_i].send,
173 .recv = data[_i].recv,
174 },
175 };
176
177 add_notify_to_ike_auth();
178 exchange_test_helper->establish_sa(exchange_test_helper,
179 &a, &b, NULL);
180
181 send_dpds(a, b, data[_i].dpds_a);
182 send_dpds(b, a, data[_i].dpds_b);
183
184 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
185 send_mid_sync(b, data[_i].send, data[_i].recv);
186 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
187 ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
188 ck_assert_int_eq(data[_i].recv, mid.resp.send);
189 ck_assert_int_eq(data[_i].send, mid.resp.recv);
190 ck_assert_int_eq(data[_i].recv, a->get_message_id(a, TRUE));
191 ck_assert_int_eq(data[_i].send, a->get_message_id(a, FALSE));
192 /* this currently won't be handled */
193 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
194 charon->bus->remove_listener(charon->bus, &mid.listener);
195
196 send_dpd(a, b);
197 send_dpd(b, a);
198
199 call_ikesa(a, destroy);
200 call_ikesa(b, destroy);
201 chunk_free(&mid.init.nonce);
202 chunk_free(&mid.resp.nonce);
203 }
204 END_TEST
205
206 /**
207 * Make sure a retransmit is handled properly.
208 */
209 START_TEST(test_retransmit)
210 {
211 ike_sa_t *a, *b;
212 mid_sync_listener_t mid = {
213 .listener = { .message = (void*)handle_mid, },
214 .init = {
215 .send = data[_i].send,
216 .recv = data[_i].recv,
217 },
218 };
219 message_t *msg, *retransmit;
220
221 add_notify_to_ike_auth();
222 exchange_test_helper->establish_sa(exchange_test_helper,
223 &a, &b, NULL);
224
225 send_dpds(a, b, data[_i].dpds_a);
226 send_dpds(b, a, data[_i].dpds_b);
227
228 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
229 send_mid_sync(b, data[_i].send, data[_i].recv);
230 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
231 retransmit = message_create_from_packet(msg->get_packet(msg));
232 retransmit->parse_header(retransmit);
233 exchange_test_helper->process_message(exchange_test_helper, a, msg);
234 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
235 msg->destroy(msg);
236 exchange_test_helper->process_message(exchange_test_helper, a, retransmit);
237 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
238 charon->bus->remove_listener(charon->bus, &mid.listener);
239
240 send_dpd(a, b);
241 send_dpd(b, a);
242
243 call_ikesa(a, destroy);
244 call_ikesa(b, destroy);
245 chunk_free(&mid.init.nonce);
246 chunk_free(&mid.resp.nonce);
247 }
248 END_TEST
249
250 /**
251 * Make sure a replayed or delayed notify is ignored.
252 */
253 START_TEST(test_replay)
254 {
255 ike_sa_t *a, *b;
256 mid_sync_listener_t mid = {
257 .listener = { .message = (void*)handle_mid, },
258 .init = {
259 .send = data[_i].send,
260 .recv = data[_i].recv,
261 },
262 };
263 message_t *msg, *replay;
264
265 add_notify_to_ike_auth();
266 exchange_test_helper->establish_sa(exchange_test_helper,
267 &a, &b, NULL);
268
269 send_dpds(a, b, data[_i].dpds_a);
270 send_dpds(b, a, data[_i].dpds_b);
271
272 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
273 send_mid_sync(b, data[_i].send, data[_i].recv);
274 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
275 replay = message_create_from_packet(msg->get_packet(msg));
276 replay->parse_header(replay);
277 exchange_test_helper->process_message(exchange_test_helper, a, msg);
278 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
279 charon->bus->remove_listener(charon->bus, &mid.listener);
280
281 send_dpd(a, b);
282 send_dpd(b, a);
283
284 exchange_test_helper->process_message(exchange_test_helper, a, replay);
285 ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
286
287 call_ikesa(a, destroy);
288 call_ikesa(b, destroy);
289 chunk_free(&mid.init.nonce);
290 chunk_free(&mid.resp.nonce);
291 }
292 END_TEST
293
294 /**
295 * Make sure the notify is ignored if the extension is not enabled.
296 */
297 START_TEST(test_disabled)
298 {
299 ike_sa_t *a, *b;
300 mid_sync_listener_t mid = {
301 .listener = { .message = (void*)handle_mid, },
302 .init = {
303 .send = data[_i].send,
304 .recv = data[_i].recv,
305 },
306 };
307
308 exchange_test_helper->establish_sa(exchange_test_helper,
309 &a, &b, NULL);
310
311 send_dpds(a, b, data[_i].dpds_a);
312 send_dpds(b, a, data[_i].dpds_b);
313
314 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
315 send_mid_sync(b, data[_i].dpds_b, UINT_MAX);
316 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
317 /* we don't expect a response and unchanged MIDs */
318 ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
319 ck_assert_int_eq(2 + data[_i].dpds_a, a->get_message_id(a, TRUE));
320 ck_assert_int_eq(data[_i].dpds_b, a->get_message_id(a, FALSE));
321 charon->bus->remove_listener(charon->bus, &mid.listener);
322
323 send_dpd(a, b);
324 send_dpd(b, a);
325
326 call_ikesa(a, destroy);
327 call_ikesa(b, destroy);
328 chunk_free(&mid.init.nonce);
329 chunk_free(&mid.resp.nonce);
330 }
331 END_TEST
332
333 static struct {
334 int dpds_a, dpds_b;
335 uint32_t send, recv;
336 } data_too_low[] = {
337 { 0, 1, 0, 2 },
338 { 1, 2, 0, 0 },
339 { 1, 2, 1, 3 },
340 };
341
342 /**
343 * The responder syncs message IDs with the initiator but uses too low sender
344 * MIDs so the initiator ignores the notify.
345 */
346 START_TEST(test_sender_too_low)
347 {
348 ike_sa_t *a, *b;
349 mid_sync_listener_t mid = {
350 .listener = { .message = (void*)handle_mid, },
351 .init = {
352 .send = data_too_low[_i].send,
353 .recv = data_too_low[_i].recv,
354 },
355 };
356
357 add_notify_to_ike_auth();
358 exchange_test_helper->establish_sa(exchange_test_helper,
359 &a, &b, NULL);
360
361 send_dpds(a, b, data_too_low[_i].dpds_a);
362 send_dpds(b, a, data_too_low[_i].dpds_b);
363
364 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
365 send_mid_sync(b, data_too_low[_i].dpds_b, UINT_MAX);
366 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
367 /* we don't expect a response and unchanged MIDs */
368 ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
369 ck_assert_int_eq(2 + data_too_low[_i].dpds_a, a->get_message_id(a, TRUE));
370 ck_assert_int_eq(data_too_low[_i].dpds_b, a->get_message_id(a, FALSE));
371 charon->bus->remove_listener(charon->bus, &mid.listener);
372
373 send_dpd(a, b);
374 send_dpd(b, a);
375
376 call_ikesa(a, destroy);
377 call_ikesa(b, destroy);
378 chunk_free(&mid.init.nonce);
379 }
380 END_TEST
381
382 static struct {
383 int dpds_a, dpds_b;
384 uint32_t send, recv;
385 /* reversed so the table below is clearer */
386 uint32_t recv_exp, send_exp;
387 } data_recv_update[] = {
388 { 0, 0, 0, 0, 0, 2 },
389 { 0, 0, 0, 1, 0, 2 },
390 { 0, 0, 1, 1, 1, 2 },
391 { 1, 0, 0, 1, 0, 3 },
392 { 1, 0, 5, 2, 5, 3 },
393 };
394
395 /**
396 * The responder syncs message IDs with the initiator but uses too low receiver
397 * MID, which is updated by the initiator in the response.
398 */
399 START_TEST(test_recv_update)
400 {
401 ike_sa_t *a, *b;
402 mid_sync_listener_t mid = {
403 .listener = { .message = (void*)handle_mid, },
404 .init = {
405 .send = data_recv_update[_i].send,
406 .recv = data_recv_update[_i].recv,
407 },
408 };
409
410 add_notify_to_ike_auth();
411 exchange_test_helper->establish_sa(exchange_test_helper,
412 &a, &b, NULL);
413
414 send_dpds(a, b, data_recv_update[_i].dpds_a);
415 send_dpds(b, a, data_recv_update[_i].dpds_b);
416
417 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
418 send_mid_sync(b, data_recv_update[_i].send, data_recv_update[_i].recv);
419 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
420 ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
421 ck_assert_int_eq(data_recv_update[_i].send_exp, mid.resp.send);
422 ck_assert_int_eq(data_recv_update[_i].recv_exp, mid.resp.recv);
423 ck_assert_int_eq(data_recv_update[_i].send_exp, a->get_message_id(a, TRUE));
424 ck_assert_int_eq(data_recv_update[_i].recv_exp, a->get_message_id(a, FALSE));
425 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
426 charon->bus->remove_listener(charon->bus, &mid.listener);
427 /* fake the receipt of the notify */
428 b->set_message_id(b, TRUE, data_recv_update[_i].recv_exp);
429 b->set_message_id(b, FALSE, data_recv_update[_i].send_exp);
430
431 send_dpd(a, b);
432 send_dpd(b, a);
433
434 call_ikesa(a, destroy);
435 call_ikesa(b, destroy);
436 chunk_free(&mid.init.nonce);
437 chunk_free(&mid.resp.nonce);
438 }
439 END_TEST
440
441 static struct {
442 int dpds_a, dpds_b;
443 uint32_t send, recv;
444 /* reversed so the table below is clearer */
445 uint32_t recv_exp, send_exp;
446 } data_active[] = {
447 { 0, 0, 0, 2, 0, 3 },
448 { 0, 0, 1, 3, 1, 3 },
449 { 1, 0, 0, 3, 0, 4 },
450 { 1, 0, 5, 8, 5, 8 },
451 { 0, 1, 1, 2, 1, 3 },
452 { 0, 1, 2, 2, 2, 2 },
453 { 1, 1, 1, 3, 1, 4 },
454 { 1, 1, 2, 4, 2, 4 },
455 };
456
457 /**
458 * The responder syncs message IDs with the initiator that waits for the
459 * response for an active task.
460 */
461 START_TEST(test_active)
462 {
463 ike_sa_t *a, *b;
464 mid_sync_listener_t mid = {
465 .listener = { .message = (void*)handle_mid, },
466 .init = {
467 .send = data_active[_i].send,
468 .recv = data_active[_i].recv,
469 },
470 };
471 message_t *msg;
472
473 add_notify_to_ike_auth();
474 exchange_test_helper->establish_sa(exchange_test_helper,
475 &a, &b, NULL);
476
477 send_dpds(a, b, data_active[_i].dpds_a);
478 send_dpds(b, a, data_active[_i].dpds_b);
479
480 call_ikesa(a, send_dpd);
481 msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
482 msg->destroy(msg);
483
484 exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
485 send_mid_sync(b, data_active[_i].recv_exp, data_active[_i].send_exp);
486 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
487 ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
488 ck_assert_int_eq(data_active[_i].send_exp, mid.resp.send);
489 ck_assert_int_eq(data_active[_i].recv_exp, mid.resp.recv);
490 ck_assert_int_eq(data_active[_i].send_exp, a->get_message_id(a, TRUE));
491 ck_assert_int_eq(data_active[_i].recv_exp, a->get_message_id(a, FALSE));
492 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
493 charon->bus->remove_listener(charon->bus, &mid.listener);
494
495 /* the active task was queued again */
496 call_ikesa(a, initiate, NULL, 0, NULL, NULL);
497 exchange_test_helper->process_message(exchange_test_helper, b, NULL);
498 exchange_test_helper->process_message(exchange_test_helper, a, NULL);
499 send_dpd(b, a);
500
501 call_ikesa(a, destroy);
502 call_ikesa(b, destroy);
503 chunk_free(&mid.init.nonce);
504 chunk_free(&mid.resp.nonce);
505 }
506 END_TEST
507
508 Suite *ike_mid_sync_suite_create()
509 {
510 Suite *s;
511 TCase *tc;
512
513 s = suite_create("ike MID sync");
514
515 tc = tcase_create("responder");
516 tcase_add_loop_test(tc, test_responder, 0, countof(data));
517 tcase_add_loop_test(tc, test_retransmit, 0, countof(data));
518 tcase_add_loop_test(tc, test_replay, 0, countof(data));
519 tcase_add_loop_test(tc, test_disabled, 0, countof(data));
520 suite_add_tcase(s, tc);
521
522 tc = tcase_create("sender MID too low");
523 tcase_add_loop_test(tc, test_sender_too_low, 0, countof(data_too_low));
524 suite_add_tcase(s, tc);
525
526 tc = tcase_create("receiver MID updated");
527 tcase_add_loop_test(tc, test_recv_update, 0, countof(data_recv_update));
528 suite_add_tcase(s, tc);
529
530 tc = tcase_create("active task");
531 tcase_add_loop_test(tc, test_active, 0, countof(data_active));
532 suite_add_tcase(s, tc);
533
534 return s;
535 }