Annotation of embedaddon/strongswan/src/libcharon/tests/utils/exchange_test_helper.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2016-2018 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 "exchange_test_helper.h"
        !            17: #include "mock_dh.h"
        !            18: #include "mock_ipsec.h"
        !            19: #include "mock_net.h"
        !            20: #include "mock_nonce_gen.h"
        !            21: 
        !            22: #include <collections/array.h>
        !            23: #include <credentials/sets/mem_cred.h>
        !            24: 
        !            25: typedef struct private_exchange_test_helper_t private_exchange_test_helper_t;
        !            26: typedef struct private_backend_t private_backend_t;
        !            27: 
        !            28: /**
        !            29:  * Private data
        !            30:  */
        !            31: struct private_exchange_test_helper_t {
        !            32: 
        !            33:        /**
        !            34:         * Public interface
        !            35:         */
        !            36:        exchange_test_helper_t public;
        !            37: 
        !            38:        /**
        !            39:         * Credentials
        !            40:         */
        !            41:        mem_cred_t *creds;
        !            42: 
        !            43:        /**
        !            44:         * IKE_SA SPI counter
        !            45:         */
        !            46:        refcount_t ike_spi;
        !            47: 
        !            48:        /**
        !            49:         * List of registered listeners
        !            50:         */
        !            51:        array_t *listeners;
        !            52: 
        !            53:        /**
        !            54:         * Config backend
        !            55:         */
        !            56:        private_backend_t *backend;
        !            57: };
        !            58: 
        !            59: /**
        !            60:  * Custom backend_t implementation
        !            61:  */
        !            62: struct private_backend_t {
        !            63: 
        !            64:        /**
        !            65:         * Public interface
        !            66:         */
        !            67:        backend_t public;
        !            68: 
        !            69:        /**
        !            70:         * Responder ike_cfg
        !            71:         */
        !            72:        ike_cfg_t *ike_cfg;
        !            73: 
        !            74:        /**
        !            75:         * Responder peer_cfg/child_cfg
        !            76:         */
        !            77:        peer_cfg_t *peer_cfg;
        !            78: };
        !            79: 
        !            80: CALLBACK(get_ike_spi, uint64_t,
        !            81:        private_exchange_test_helper_t *this)
        !            82: {
        !            83:        return (uint64_t)ref_get(&this->ike_spi);
        !            84: }
        !            85: 
        !            86: /*
        !            87:  * Described in header
        !            88:  */
        !            89: exchange_test_helper_t *exchange_test_helper;
        !            90: 
        !            91: static ike_cfg_t *create_ike_cfg(bool initiator, exchange_test_sa_conf_t *conf)
        !            92: {
        !            93:        ike_cfg_create_t ike = {
        !            94:                .version = IKEV2,
        !            95:                .local = "127.0.0.1",
        !            96:                .local_port = IKEV2_UDP_PORT,
        !            97:                .remote = "127.0.0.1",
        !            98:                .remote_port = IKEV2_UDP_PORT,
        !            99:        };
        !           100:        ike_cfg_t *ike_cfg;
        !           101:        char *proposal = NULL;
        !           102: 
        !           103:        if (conf)
        !           104:        {
        !           105:                ike.childless = initiator ? conf->initiator.childless
        !           106:                                                                  : conf->responder.childless;
        !           107:                proposal = initiator ? conf->initiator.ike : conf->responder.ike;
        !           108:        }
        !           109: 
        !           110:        ike_cfg = ike_cfg_create(&ike);
        !           111:        if (proposal)
        !           112:        {
        !           113:                ike_cfg->add_proposal(ike_cfg,
        !           114:                                                        proposal_create_from_string(PROTO_IKE, proposal));
        !           115:        }
        !           116:        else
        !           117:        {
        !           118:                ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        !           119:        }
        !           120:        return ike_cfg;
        !           121: }
        !           122: 
        !           123: static child_cfg_t *create_child_cfg(bool initiator,
        !           124:                                                                         exchange_test_sa_conf_t *conf)
        !           125: {
        !           126:        child_cfg_t *child_cfg;
        !           127:        child_cfg_create_t child = {
        !           128:                .mode = MODE_TUNNEL,
        !           129:        };
        !           130:        char *proposal = NULL;
        !           131: 
        !           132:        child_cfg = child_cfg_create(initiator ? "init" : "resp", &child);
        !           133:        if (conf)
        !           134:        {
        !           135:                proposal = initiator ? conf->initiator.esp : conf->responder.esp;
        !           136:        }
        !           137:        if (proposal)
        !           138:        {
        !           139:                child_cfg->add_proposal(child_cfg,
        !           140:                                                        proposal_create_from_string(PROTO_ESP, proposal));
        !           141:        }
        !           142:        else
        !           143:        {
        !           144:                child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        !           145:        }
        !           146:        child_cfg->add_traffic_selector(child_cfg, TRUE,
        !           147:                                                                traffic_selector_create_dynamic(0, 0, 65535));
        !           148:        child_cfg->add_traffic_selector(child_cfg, FALSE,
        !           149:                                                                traffic_selector_create_dynamic(0, 0, 65535));
        !           150:        return child_cfg;
        !           151: }
        !           152: 
        !           153: static void add_auth_cfg(peer_cfg_t *peer_cfg, bool initiator, bool local)
        !           154: {
        !           155:        auth_cfg_t *auth;
        !           156:        char *id = "init";
        !           157: 
        !           158:        auth = auth_cfg_create();
        !           159:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
        !           160:        if (initiator ^ local)
        !           161:        {
        !           162:                id = "resp";
        !           163:        }
        !           164:        auth->add(auth, AUTH_RULE_IDENTITY, identification_create_from_string(id));
        !           165:        peer_cfg->add_auth_cfg(peer_cfg, auth, local);
        !           166: }
        !           167: 
        !           168: static peer_cfg_t *create_peer_cfg(bool initiator,
        !           169:                                                                   exchange_test_sa_conf_t *conf)
        !           170: {
        !           171:        peer_cfg_t *peer_cfg;
        !           172:        peer_cfg_create_t peer = {
        !           173:                .cert_policy = CERT_SEND_IF_ASKED,
        !           174:                .unique = UNIQUE_REPLACE,
        !           175:                .keyingtries = 1,
        !           176:        };
        !           177: 
        !           178:        peer_cfg = peer_cfg_create(initiator ? "init" : "resp",
        !           179:                                                           create_ike_cfg(initiator, conf), &peer);
        !           180:        add_auth_cfg(peer_cfg, initiator, TRUE);
        !           181:        add_auth_cfg(peer_cfg, initiator, FALSE);
        !           182:        return peer_cfg;
        !           183: }
        !           184: 
        !           185: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
        !           186:        private_backend_t *this, host_t *me, host_t *other)
        !           187: {
        !           188:        return enumerator_create_single(this->ike_cfg, NULL);
        !           189: }
        !           190: 
        !           191: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
        !           192:        private_backend_t *this, identification_t *me, identification_t *other)
        !           193: {
        !           194:        return enumerator_create_single(this->peer_cfg, NULL);
        !           195: }
        !           196: 
        !           197: /**
        !           198:  * Sets the config objects provided by the backend
        !           199:  */
        !           200: static void set_config(private_backend_t *this, ike_cfg_t *ike,
        !           201:                                           peer_cfg_t *peer)
        !           202: {
        !           203:        DESTROY_IF(this->ike_cfg);
        !           204:        this->ike_cfg = ike;
        !           205:        DESTROY_IF(this->peer_cfg);
        !           206:        this->peer_cfg = peer;
        !           207: }
        !           208: 
        !           209: METHOD(exchange_test_helper_t, process_message, status_t,
        !           210:        private_exchange_test_helper_t *this, ike_sa_t *ike_sa, message_t *message)
        !           211: {
        !           212:        status_t status = FAILED;
        !           213:        ike_sa_id_t *id;
        !           214: 
        !           215:        if (!message)
        !           216:        {
        !           217:                message = this->public.sender->dequeue(this->public.sender);
        !           218:        }
        !           219:        id = message->get_ike_sa_id(message);
        !           220:        id = id->clone(id);
        !           221:        id->switch_initiator(id);
        !           222:        if (!id->get_responder_spi(id) || id->equals(id, ike_sa->get_id(ike_sa)))
        !           223:        {
        !           224:                charon->bus->set_sa(charon->bus, ike_sa);
        !           225:                status = ike_sa->process_message(ike_sa, message);
        !           226:                charon->bus->set_sa(charon->bus, NULL);
        !           227:        }
        !           228:        message->destroy(message);
        !           229:        id->destroy(id);
        !           230:        return status;
        !           231: }
        !           232: 
        !           233: METHOD(exchange_test_helper_t, create_sa, child_cfg_t*,
        !           234:        private_exchange_test_helper_t *this, ike_sa_t **init, ike_sa_t **resp,
        !           235:        exchange_test_sa_conf_t *conf)
        !           236: {
        !           237:        peer_cfg_t *peer_cfg;
        !           238:        child_cfg_t *child_cfg;
        !           239: 
        !           240:        *init = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
        !           241:                                                                                                 IKEV2, TRUE);
        !           242: 
        !           243:        *resp = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
        !           244:                                                                                                 IKEV2, FALSE);
        !           245: 
        !           246:        peer_cfg = create_peer_cfg(FALSE, conf);
        !           247:        child_cfg = create_child_cfg(FALSE, conf);
        !           248:        peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg));
        !           249:        child_cfg->destroy(child_cfg);
        !           250:        set_config(this->backend,  create_ike_cfg(FALSE, conf), peer_cfg);
        !           251: 
        !           252:        peer_cfg = create_peer_cfg(TRUE, conf);
        !           253:        child_cfg = create_child_cfg(TRUE, conf);
        !           254:        peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg));
        !           255:        (*init)->set_peer_cfg(*init, peer_cfg);
        !           256:        peer_cfg->destroy(peer_cfg);
        !           257:        return child_cfg;
        !           258: }
        !           259: 
        !           260: METHOD(exchange_test_helper_t, establish_sa, void,
        !           261:        private_exchange_test_helper_t *this, ike_sa_t **init, ike_sa_t **resp,
        !           262:        exchange_test_sa_conf_t *conf)
        !           263: {
        !           264:        ike_sa_id_t *id_i, *id_r;
        !           265:        ike_sa_t *sa_i, *sa_r;
        !           266:        child_cfg_t *child_i;
        !           267: 
        !           268:        child_i = create_sa(this, init, resp, conf);
        !           269: 
        !           270:        sa_i = *init;
        !           271:        sa_r = *resp;
        !           272: 
        !           273:        id_i = sa_i->get_id(sa_i);
        !           274:        id_r = sa_r->get_id(sa_r);
        !           275: 
        !           276:        call_ikesa(sa_i, initiate, child_i, 0, NULL, NULL);
        !           277: 
        !           278:        /* IKE_SA_INIT --> */
        !           279:        id_r->set_initiator_spi(id_r, id_i->get_initiator_spi(id_i));
        !           280:        process_message(this, sa_r, NULL);
        !           281:        /* <-- IKE_SA_INIT */
        !           282:        id_i->set_responder_spi(id_i, id_r->get_responder_spi(id_r));
        !           283:        process_message(this, sa_i, NULL);
        !           284:        /* IKE_AUTH --> */
        !           285:        process_message(this, sa_r, NULL);
        !           286:        /* <-- IKE_AUTH */
        !           287:        process_message(this, sa_i, NULL);
        !           288: }
        !           289: 
        !           290: METHOD(exchange_test_helper_t, add_listener, void,
        !           291:        private_exchange_test_helper_t *this, listener_t *listener)
        !           292: {
        !           293:        array_insert_create(&this->listeners, ARRAY_TAIL, listener);
        !           294:        charon->bus->add_listener(charon->bus, listener);
        !           295: }
        !           296: 
        !           297: /**
        !           298:  * Enable logging in charon as requested
        !           299:  */
        !           300: static void initialize_logging()
        !           301: {
        !           302:        int level = LEVEL_SILENT;
        !           303:        char *verbosity;
        !           304: 
        !           305:        verbosity = getenv("TESTS_VERBOSITY");
        !           306:        if (verbosity)
        !           307:        {
        !           308:                level = atoi(verbosity);
        !           309:        }
        !           310:        lib->settings->set_int(lib->settings, "%s.filelog.stderr.default",
        !           311:                        lib->settings->get_int(lib->settings, "%s.filelog.stderr.default",
        !           312:                                                                   level, lib->ns), lib->ns);
        !           313:        lib->settings->set_bool(lib->settings, "%s.filelog.stderr.ike_name", TRUE,
        !           314:                                                        lib->ns);
        !           315:        charon->load_loggers(charon);
        !           316: }
        !           317: 
        !           318: /**
        !           319:  * Create a nonce generator with the first byte
        !           320:  */
        !           321: static nonce_gen_t *create_nonce_gen()
        !           322: {
        !           323:        return mock_nonce_gen_create(exchange_test_helper->nonce_first_byte);
        !           324: }
        !           325: 
        !           326: /*
        !           327:  * Described in header
        !           328:  */
        !           329: void exchange_test_helper_init(char *plugins)
        !           330: {
        !           331:        private_exchange_test_helper_t *this;
        !           332:        private_backend_t *backend;
        !           333:        plugin_feature_t features[] = {
        !           334:                PLUGIN_REGISTER(DH, mock_dh_create),
        !           335:                        /* we only need to support a limited number of DH groups */
        !           336:                        PLUGIN_PROVIDE(DH, MODP_2048_BIT),
        !           337:                        PLUGIN_PROVIDE(DH, MODP_3072_BIT),
        !           338:                        PLUGIN_PROVIDE(DH, ECP_256_BIT),
        !           339:                PLUGIN_REGISTER(NONCE_GEN, create_nonce_gen),
        !           340:                        PLUGIN_PROVIDE(NONCE_GEN),
        !           341:                                PLUGIN_DEPENDS(RNG, RNG_WEAK),
        !           342:        };
        !           343: 
        !           344:        INIT(backend,
        !           345:                .public = {
        !           346:                        .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
        !           347:                        .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
        !           348:                        .get_peer_cfg_by_name = (void*)return_null,
        !           349:                },
        !           350:        );
        !           351: 
        !           352:        INIT(this,
        !           353:                .public = {
        !           354:                        .sender = mock_sender_create(),
        !           355:                        .establish_sa = _establish_sa,
        !           356:                        .create_sa = _create_sa,
        !           357:                        .process_message = _process_message,
        !           358:                        .add_listener = _add_listener,
        !           359:                },
        !           360:                .creds = mem_cred_create(),
        !           361:                .backend = backend,
        !           362:        );
        !           363: 
        !           364:        initialize_logging();
        !           365:        lib->plugins->add_static_features(lib->plugins, "exchange-test-helper",
        !           366:                                                                features, countof(features), TRUE, NULL, NULL);
        !           367:        /* the libcharon unit tests only load the libstrongswan plugins, unless
        !           368:         * TESTS_PLUGINS is defined */
        !           369:        charon->initialize(charon, plugins);
        !           370:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
        !           371: 
        !           372:        /* the original sender is not initialized because there is no socket */
        !           373:        charon->sender = (sender_t*)this->public.sender;
        !           374:        /* and there is no kernel plugin loaded
        !           375:         * TODO: we'd have more control if we'd implement kernel_interface_t */
        !           376:        charon->kernel->add_ipsec_interface(charon->kernel, mock_ipsec_create);
        !           377:        charon->kernel->add_net_interface(charon->kernel, mock_net_create);
        !           378:        /* like SPIs for IPsec SAs, make IKE SPIs predictable */
        !           379:        charon->ike_sa_manager->set_spi_cb(charon->ike_sa_manager, get_ike_spi,
        !           380:                                                                           this);
        !           381: 
        !           382:        charon->backends->add_backend(charon->backends, &backend->public);
        !           383: 
        !           384:        lib->credmgr->add_set(lib->credmgr, &this->creds->set);
        !           385: 
        !           386:        this->creds->add_shared(this->creds,
        !           387:                        shared_key_create(SHARED_IKE, chunk_clone(chunk_from_str("test"))),
        !           388:                        identification_create_from_string("%any"), NULL);
        !           389: 
        !           390:        exchange_test_helper = &this->public;
        !           391: }
        !           392: 
        !           393: /*
        !           394:  * Described in header
        !           395:  */
        !           396: void exchange_test_helper_deinit()
        !           397: {
        !           398:        private_exchange_test_helper_t *this;
        !           399:        listener_t *listener;
        !           400: 
        !           401:        this = (private_exchange_test_helper_t*)exchange_test_helper;
        !           402: 
        !           403:        while (array_remove(this->listeners, ARRAY_HEAD, &listener))
        !           404:        {
        !           405:                charon->bus->remove_listener(charon->bus, listener);
        !           406:        }
        !           407:        charon->backends->remove_backend(charon->backends, &this->backend->public);
        !           408:        set_config(this->backend, NULL, NULL);
        !           409:        free(this->backend);
        !           410:        lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
        !           411:        this->creds->destroy(this->creds);
        !           412:        /* flush SAs before destroying the sender (in case of test failures) */
        !           413:        charon->ike_sa_manager->flush(charon->ike_sa_manager);
        !           414:        /* charon won't destroy this as it didn't initialize the original sender */
        !           415:        charon->sender->destroy(charon->sender);
        !           416:        charon->sender = NULL;
        !           417:        array_destroy(this->listeners);
        !           418:        free(this);
        !           419: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>