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>