Annotation of embedaddon/strongswan/src/libcharon/tests/suites/test_ike_mid_sync.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 <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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>