proposal-substructure: Fix incorrect type for IKEv2 proposals
[strongswan.git] / src / conftest / config.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "config.h"
17
18 #include <daemon.h>
19 #include <conftest.h>
20
21 typedef struct private_config_t private_config_t;
22
23 /**
24 * Private data of an config_t object.
25 */
26 struct private_config_t {
27
28 /**
29 * Public config_t interface.
30 */
31 config_t public;
32
33 /**
34 * List of loaded peer configs
35 */
36 linked_list_t *configs;
37 };
38
39 CALLBACK(ike_filter, bool,
40 void *data, enumerator_t *orig, va_list args)
41 {
42 peer_cfg_t *cfg;
43 ike_cfg_t **out;
44
45 VA_ARGS_VGET(args, out);
46
47 if (orig->enumerate(orig, &cfg))
48 {
49 *out = cfg->get_ike_cfg(cfg);
50 return TRUE;
51 }
52 return FALSE;
53 }
54
55 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
56 private_config_t *this, host_t *me, host_t *other)
57 {
58
59 return enumerator_create_filter(
60 this->configs->create_enumerator(this->configs),
61 ike_filter, NULL, NULL);
62 }
63
64 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
65 private_config_t *this, identification_t *me, identification_t *other)
66 {
67 return this->configs->create_enumerator(this->configs);
68 }
69
70 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
71 private_config_t *this, char *name)
72 {
73 enumerator_t *e1, *e2;
74 peer_cfg_t *current, *found = NULL;
75 child_cfg_t *child;
76
77 e1 = this->configs->create_enumerator(this->configs);
78 while (e1->enumerate(e1, &current))
79 {
80 e2 = current->create_child_cfg_enumerator(current);
81 while (e2->enumerate(e2, &child))
82 {
83 if (streq(child->get_name(child), name))
84 {
85 found = current;
86 found->get_ref(found);
87 break;
88 }
89 }
90 e2->destroy(e2);
91 if (found)
92 {
93 break;
94 }
95 }
96 e1->destroy(e1);
97 return found;
98 }
99
100 /**
101 * Load IKE config for a given section name
102 */
103 static ike_cfg_t *load_ike_config(private_config_t *this,
104 settings_t *settings, char *config)
105 {
106 enumerator_t *enumerator;
107 ike_cfg_t *ike_cfg;
108 proposal_t *proposal;
109 char *token;
110
111 ike_cfg = ike_cfg_create(IKEV2, TRUE,
112 settings->get_bool(settings, "configs.%s.fake_nat", FALSE, config),
113 settings->get_str(settings, "configs.%s.lhost", "%any", config),
114 settings->get_int(settings, "configs.%s.lport", 500, config),
115 settings->get_str(settings, "configs.%s.rhost", "%any", config),
116 settings->get_int(settings, "configs.%s.rport", 500, config),
117 FRAGMENTATION_NO, 0);
118 token = settings->get_str(settings, "configs.%s.proposal", NULL, config);
119 if (token)
120 {
121 enumerator = enumerator_create_token(token, ",", " ");
122 while (enumerator->enumerate(enumerator, &token))
123 {
124 proposal = proposal_create_from_string(PROTO_IKE, token);
125 if (proposal)
126 {
127 ike_cfg->add_proposal(ike_cfg, proposal);
128 }
129 else
130 {
131 DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token);
132 }
133 }
134 enumerator->destroy(enumerator);
135 }
136 else
137 {
138 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
139 ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
140 }
141 return ike_cfg;
142 }
143 /**
144 * Load CHILD config for given section names
145 */
146 static child_cfg_t *load_child_config(private_config_t *this,
147 settings_t *settings, char *config, char *child)
148 {
149 child_cfg_create_t data = {
150 .mode = MODE_TUNNEL,
151 };
152 child_cfg_t *child_cfg;
153 enumerator_t *enumerator;
154 proposal_t *proposal;
155 traffic_selector_t *ts;
156 char *token;
157
158 if (settings->get_bool(settings, "configs.%s.%s.transport",
159 FALSE, config, child))
160 {
161 data.mode = MODE_TRANSPORT;
162 }
163 data.tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
164 0, config, child);
165 child_cfg = child_cfg_create(child, &data);
166
167 token = settings->get_str(settings, "configs.%s.%s.proposal",
168 NULL, config, child);
169 if (token)
170 {
171 enumerator = enumerator_create_token(token, ",", " ");
172 while (enumerator->enumerate(enumerator, &token))
173 {
174 proposal = proposal_create_from_string(PROTO_ESP, token);
175 if (proposal)
176 {
177 child_cfg->add_proposal(child_cfg, proposal);
178 }
179 else
180 {
181 DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token);
182 }
183 }
184 enumerator->destroy(enumerator);
185 }
186 else
187 {
188 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
189 child_cfg->add_proposal(child_cfg,
190 proposal_create_default_aead(PROTO_ESP));
191 }
192
193 token = settings->get_str(settings, "configs.%s.%s.lts", NULL, config, child);
194 if (token)
195 {
196 enumerator = enumerator_create_token(token, ",", " ");
197 while (enumerator->enumerate(enumerator, &token))
198 {
199 ts = traffic_selector_create_from_cidr(token, 0, 0, 65535);
200 if (ts)
201 {
202 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
203 }
204 else
205 {
206 DBG1(DBG_CFG, "invalid local ts: %s, skipped", token);
207 }
208 }
209 enumerator->destroy(enumerator);
210 }
211 else
212 {
213 ts = traffic_selector_create_dynamic(0, 0, 65535);
214 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
215 }
216
217 token = settings->get_str(settings, "configs.%s.%s.rts", NULL, config, child);
218 if (token)
219 {
220 enumerator = enumerator_create_token(token, ",", " ");
221 while (enumerator->enumerate(enumerator, &token))
222 {
223 ts = traffic_selector_create_from_cidr(token, 0, 0, 65535);
224 if (ts)
225 {
226 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
227 }
228 else
229 {
230 DBG1(DBG_CFG, "invalid remote ts: %s, skipped", token);
231 }
232 }
233 enumerator->destroy(enumerator);
234 }
235 else
236 {
237 ts = traffic_selector_create_dynamic(0, 0, 65535);
238 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
239 }
240 return child_cfg;
241 }
242
243 /**
244 * Load peer config for a given section name
245 */
246 static peer_cfg_t *load_peer_config(private_config_t *this,
247 settings_t *settings, char *config)
248 {
249 ike_cfg_t *ike_cfg;
250 peer_cfg_t *peer_cfg;
251 auth_cfg_t *auth;
252 child_cfg_t *child_cfg;
253 enumerator_t *enumerator;
254 identification_t *lid, *rid;
255 char *child, *policy, *pool;
256 uintptr_t strength;
257 peer_cfg_create_t peer = {
258 .cert_policy = CERT_ALWAYS_SEND,
259 .unique = UNIQUE_NO,
260 .keyingtries = 1,
261 .no_mobike = TRUE,
262 };
263
264 ike_cfg = load_ike_config(this, settings, config);
265 peer_cfg = peer_cfg_create(config, ike_cfg, &peer);
266
267 auth = auth_cfg_create();
268 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
269 lid = identification_create_from_string(
270 settings->get_str(settings, "configs.%s.lid", "%any", config));
271 auth->add(auth, AUTH_RULE_IDENTITY, lid);
272 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
273
274 auth = auth_cfg_create();
275 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
276 rid = identification_create_from_string(
277 settings->get_str(settings, "configs.%s.rid", "%any", config));
278 strength = settings->get_int(settings, "configs.%s.rsa_strength", 0, config);
279 if (strength)
280 {
281 auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength);
282 }
283 strength = settings->get_int(settings, "configs.%s.ecdsa_strength", 0, config);
284 if (strength)
285 {
286 auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength);
287 }
288 policy = settings->get_str(settings, "configs.%s.cert_policy", NULL, config);
289 if (policy)
290 {
291 auth->add(auth, AUTH_RULE_CERT_POLICY, strdup(policy));
292 }
293 auth->add(auth, AUTH_RULE_IDENTITY, rid);
294 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
295 pool = settings->get_str(settings, "configs.%s.named_pool", NULL, config);
296 if (pool)
297 {
298 peer_cfg->add_pool(peer_cfg, pool);
299 }
300
301 DBG1(DBG_CFG, "loaded config %s: %Y - %Y", config, lid, rid);
302
303 enumerator = settings->create_section_enumerator(settings,
304 "configs.%s", config);
305 while (enumerator->enumerate(enumerator, &child))
306 {
307 child_cfg = load_child_config(this, settings, config, child);
308 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
309 }
310 enumerator->destroy(enumerator);
311 return peer_cfg;
312 }
313
314 METHOD(config_t, load, void,
315 private_config_t *this, settings_t *settings)
316 {
317 enumerator_t *enumerator;
318 char *config;
319
320 enumerator = settings->create_section_enumerator(settings, "configs");
321 while (enumerator->enumerate(enumerator, &config))
322 {
323 this->configs->insert_last(this->configs,
324 load_peer_config(this, settings, config));
325 }
326 enumerator->destroy(enumerator);
327 }
328
329 METHOD(config_t, destroy, void,
330 private_config_t *this)
331 {
332 this->configs->destroy_offset(this->configs, offsetof(peer_cfg_t, destroy));
333 free(this);
334 }
335
336 /**
337 * See header
338 */
339 config_t *config_create()
340 {
341 private_config_t *this;
342
343 INIT(this,
344 .public = {
345 .backend = {
346 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
347 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
348 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
349 },
350 .load = _load,
351 .destroy = _destroy,
352 },
353 .configs = linked_list_create(),
354 );
355
356 return &this->public;
357 }