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