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>