Return to exchange_test_helper.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / tests / utils |
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: }