018804e6c85dd35344dc923816394d46aabc2928
[strongswan.git] / src / libcharon / tests / utils / exchange_test_helper.c
1 /*
2 * Copyright (C) 2016 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_nonce_gen.h"
20
21 #include <credentials/sets/mem_cred.h>
22
23 typedef struct private_exchange_test_helper_t private_exchange_test_helper_t;
24
25 /**
26 * Private data
27 */
28 struct private_exchange_test_helper_t {
29
30 /**
31 * Public interface
32 */
33 exchange_test_helper_t public;
34
35 /**
36 * Config backend
37 */
38 backend_t backend;
39
40 /**
41 * Credentials
42 */
43 mem_cred_t *creds;
44
45 /**
46 * IKE_SA SPI counter
47 */
48 refcount_t ike_spi;
49 };
50
51 CALLBACK(get_ike_spi, uint64_t,
52 private_exchange_test_helper_t *this)
53 {
54 return (uint64_t)ref_get(&this->ike_spi);
55 }
56
57 /*
58 * Described in header
59 */
60 exchange_test_helper_t *exchange_test_helper;
61
62 static ike_cfg_t *create_ike_cfg()
63 {
64 ike_cfg_t *ike_cfg;
65
66 ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "127.0.0.1", IKEV2_UDP_PORT,
67 "127.0.0.1", IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
68 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
69 return ike_cfg;
70 }
71
72 static child_cfg_t *create_child_cfg(bool initiator)
73 {
74 child_cfg_t *child_cfg;
75 child_cfg_create_t child = {
76 .mode = MODE_TUNNEL,
77 };
78
79 child_cfg = child_cfg_create(initiator ? "init" : "resp", &child);
80 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
81 child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
82 child_cfg->add_traffic_selector(child_cfg, TRUE,
83 traffic_selector_create_dynamic(0, 0, 65535));
84 child_cfg->add_traffic_selector(child_cfg, FALSE,
85 traffic_selector_create_dynamic(0, 0, 65535));
86 return child_cfg;
87 }
88
89 static void add_auth_cfg(peer_cfg_t *peer_cfg, bool initiator, bool local)
90 {
91 auth_cfg_t *auth;
92 char *id = "init";
93
94 auth = auth_cfg_create();
95 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
96 if (initiator ^ local)
97 {
98 id = "resp";
99 }
100 auth->add(auth, AUTH_RULE_IDENTITY, identification_create_from_string(id));
101 peer_cfg->add_auth_cfg(peer_cfg, auth, local);
102 }
103
104 static peer_cfg_t *create_peer_cfg(bool initiator)
105 {
106 peer_cfg_t *peer_cfg;
107 peer_cfg_create_t peer = {
108 .cert_policy = CERT_SEND_IF_ASKED,
109 .unique = UNIQUE_REPLACE,
110 .keyingtries = 1,
111 };
112
113 peer_cfg = peer_cfg_create(initiator ? "init" : "resp", create_ike_cfg(),
114 &peer);
115 add_auth_cfg(peer_cfg, initiator, TRUE);
116 add_auth_cfg(peer_cfg, initiator, FALSE);
117 peer_cfg->add_child_cfg(peer_cfg, create_child_cfg(initiator));
118 return peer_cfg;
119 }
120
121 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
122 backend_t *this, host_t *me, host_t *other)
123 {
124 ike_cfg_t *ike_cfg = create_ike_cfg();
125 return enumerator_create_single(ike_cfg, (void*)ike_cfg->destroy);
126 }
127
128 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
129 backend_t *this, identification_t *me, identification_t *other)
130 {
131 peer_cfg_t *peer_cfg = create_peer_cfg(FALSE);
132 return enumerator_create_single(peer_cfg, (void*)peer_cfg->destroy);
133 }
134
135 METHOD(exchange_test_helper_t, process_message, void,
136 private_exchange_test_helper_t *this, ike_sa_t *ike_sa, message_t *message)
137 {
138 if (!message)
139 {
140 message = this->public.sender->dequeue(this->public.sender);
141 }
142 charon->bus->set_sa(charon->bus, ike_sa);
143 ike_sa->process_message(ike_sa, message);
144 charon->bus->set_sa(charon->bus, NULL);
145 message->destroy(message);
146 }
147
148 METHOD(exchange_test_helper_t, establish_sa, void,
149 private_exchange_test_helper_t *this, ike_sa_t **init, ike_sa_t **resp)
150 {
151 ike_sa_id_t *id_i, *id_r;
152 ike_sa_t *sa_i, *sa_r;
153 peer_cfg_t *peer_cfg;
154
155 sa_i = *init = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
156 IKEV2, TRUE);
157 id_i = sa_i->get_id(sa_i);
158
159 sa_r = *resp = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
160 IKEV2, FALSE);
161 id_r = sa_r->get_id(sa_r);
162
163 peer_cfg = create_peer_cfg(TRUE);
164 sa_i->set_peer_cfg(sa_i, peer_cfg);
165 peer_cfg->destroy(peer_cfg);
166 call_ikesa(sa_i, initiate, create_child_cfg(TRUE), 0, NULL, NULL);
167 /* IKE_SA_INIT --> */
168 id_r->set_initiator_spi(id_r, id_i->get_initiator_spi(id_i));
169 process_message(this, sa_r, NULL);
170 /* <-- IKE_SA_INIT */
171 id_i->set_responder_spi(id_i, id_r->get_responder_spi(id_r));
172 process_message(this, sa_i, NULL);
173 /* IKE_AUTH --> */
174 process_message(this, sa_r, NULL);
175 /* <-- IKE_AUTH */
176 process_message(this, sa_i, NULL);
177 }
178
179 /**
180 * Enable logging in charon as requested
181 */
182 static void initialize_logging()
183 {
184 int level = LEVEL_SILENT;
185 char *verbosity;
186
187 verbosity = getenv("TESTS_VERBOSITY");
188 if (verbosity)
189 {
190 level = atoi(verbosity);
191 }
192 lib->settings->set_int(lib->settings, "%s.filelog.stderr.default",
193 lib->settings->get_int(lib->settings, "%s.filelog.stderr.default",
194 level, lib->ns), lib->ns);
195 lib->settings->set_bool(lib->settings, "%s.filelog.stderr.ike_name", TRUE,
196 lib->ns);
197 charon->load_loggers(charon, NULL, TRUE);
198 }
199
200 /**
201 * Create a nonce generator with the first byte
202 */
203 static nonce_gen_t *create_nonce_gen()
204 {
205 return mock_nonce_gen_create(exchange_test_helper->nonce_first_byte);
206 }
207
208 /*
209 * Described in header
210 */
211 void exchange_test_helper_init(char *plugins)
212 {
213 private_exchange_test_helper_t *this;
214 plugin_feature_t features[] = {
215 PLUGIN_REGISTER(DH, mock_dh_create),
216 /* we only need to support a limited number of DH groups */
217 PLUGIN_PROVIDE(DH, MODP_2048_BIT),
218 PLUGIN_PROVIDE(DH, MODP_3072_BIT),
219 PLUGIN_PROVIDE(DH, ECP_256_BIT),
220 PLUGIN_REGISTER(NONCE_GEN, create_nonce_gen),
221 PLUGIN_PROVIDE(NONCE_GEN),
222 PLUGIN_DEPENDS(RNG, RNG_WEAK),
223 };
224
225 INIT(this,
226 .public = {
227 .sender = mock_sender_create(),
228 .establish_sa = _establish_sa,
229 .process_message = _process_message,
230 },
231 .backend = {
232 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
233 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
234 .get_peer_cfg_by_name = (void*)return_null,
235 },
236 .creds = mem_cred_create(),
237 );
238
239 initialize_logging();
240 lib->plugins->add_static_features(lib->plugins, "exchange-test-helper",
241 features, countof(features), TRUE, NULL, NULL);
242 /* the libcharon unit tests only load the libstrongswan plugins, unless
243 * TESTS_PLUGINS is defined */
244 charon->initialize(charon, plugins);
245 lib->plugins->status(lib->plugins, LEVEL_CTRL);
246
247 /* the original sender is not initialized because there is no socket */
248 charon->sender = (sender_t*)this->public.sender;
249 /* and there is no kernel plugin loaded
250 * TODO: we'd have more control if we'd implement kernel_interface_t */
251 charon->kernel->add_ipsec_interface(charon->kernel, mock_ipsec_create);
252 /* like SPIs for IPsec SAs, make IKE SPIs predictable */
253 charon->ike_sa_manager->set_spi_cb(charon->ike_sa_manager, get_ike_spi,
254 this);
255
256 charon->backends->add_backend(charon->backends, &this->backend);
257 lib->credmgr->add_set(lib->credmgr, &this->creds->set);
258
259 this->creds->add_shared(this->creds,
260 shared_key_create(SHARED_IKE, chunk_clone(chunk_from_str("test"))),
261 identification_create_from_string("%any"), NULL);
262
263 exchange_test_helper = &this->public;
264 }
265
266 /*
267 * Described in header
268 */
269 void exchange_test_helper_deinit()
270 {
271 private_exchange_test_helper_t *this;
272
273 this = (private_exchange_test_helper_t*)exchange_test_helper;
274
275 charon->backends->remove_backend(charon->backends, &this->backend);
276 lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
277 this->creds->destroy(this->creds);
278 /* can't let charon do it as it happens too late */
279 charon->sender->destroy(charon->sender);
280 charon->sender = NULL;
281 free(this);
282 }