Annotation of embedaddon/strongswan/src/libcharon/tests/suites/test_child_delete.c, revision 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>