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

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: 
1.1.1.2 ! misho     240:        *init = charon->ike_sa_manager->create_new(charon->ike_sa_manager,
        !           241:                                                                                           IKEV2, TRUE);
1.1       misho     242: 
1.1.1.2 ! misho     243:        *resp = charon->ike_sa_manager->create_new(charon->ike_sa_manager,
        !           244:                                                                                           IKEV2, FALSE);
1.1       misho     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>