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>