changed [4856] to dynamically choose traffic selector family
[strongswan.git] / src / charon / plugins / uci / uci_config.c
1 /*
2 * Copyright (C) 2008 Thomas Kallenberg
3 * Copyright (C) 2008 Tobias Brunner
4 * Copyright (C) 2008 Martin Willi
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
20 #define _GNU_SOURCE
21 #include <string.h>
22
23 #include "uci_config.h"
24 #include "uci_parser.h"
25
26 #include <daemon.h>
27
28 typedef struct private_uci_config_t private_uci_config_t;
29
30 /**
31 * Private data of an uci_config_t object
32 */
33 struct private_uci_config_t {
34
35 /**
36 * Public part
37 */
38 uci_config_t public;
39
40 /**
41 * UCI parser context
42 */
43 uci_parser_t *parser;
44 };
45
46 /**
47 * enumerator implementation for create_peer_cfg_enumerator
48 */
49 typedef struct {
50 /** implements enumerator */
51 enumerator_t public;
52 /** currently enumerated peer config */
53 peer_cfg_t *peer_cfg;
54 /** inner uci_parser section enumerator */
55 enumerator_t *inner;
56 } peer_enumerator_t;
57
58 /**
59 * create a proposal from a string, with fallback to default
60 */
61 static proposal_t *create_proposal(char *string, protocol_id_t proto)
62 {
63 proposal_t *proposal = NULL;
64
65 if (string)
66 {
67 proposal = proposal_create_from_string(proto, string);
68 }
69 if (!proposal)
70 { /* UCI default is aes/sha1 only */
71 if (proto == PROTO_IKE)
72 {
73 proposal = proposal_create_from_string(proto,
74 "aes128-aes192-aes256-sha1-modp1536-modp2048");
75 }
76 else
77 {
78 proposal = proposal_create_from_string(proto,
79 "aes128-aes192-aes256-sha1");
80 }
81 }
82 return proposal;
83 }
84
85 /**
86 * create an identity, with fallback to %any
87 */
88 static identification_t *create_id(char *string)
89 {
90 identification_t *id = NULL;
91
92 if (string)
93 {
94 id = identification_create_from_string(string);
95 }
96 if (!id)
97 {
98 id = identification_create_from_encoding(ID_ANY, chunk_empty);
99 }
100 return id;
101 }
102
103 /**
104 * create an traffic selector, fallback to dynamic
105 */
106 static traffic_selector_t *create_ts(char *string)
107 {
108 if (string)
109 {
110 int netbits = 32;
111 host_t *net;
112 char *pos;
113
114 string = strdupa(string);
115 pos = strchr(string, '/');
116 if (pos)
117 {
118 *pos++ = '\0';
119 netbits = atoi(pos);
120 }
121 else
122 {
123 if (strchr(string, ':'))
124 {
125 netbits = 128;
126 }
127 }
128 net = host_create_from_string(string, 0);
129 if (net)
130 {
131 return traffic_selector_create_from_subnet(net, netbits, 0, 0);
132 }
133 }
134 return traffic_selector_create_dynamic(0, 0, 65535);
135 }
136
137 /**
138 * create a rekey time from a string with hours, with fallback
139 */
140 static u_int create_rekey(char *string)
141 {
142 u_int rekey = 0;
143
144 if (string)
145 {
146 rekey = atoi(string);
147 if (rekey)
148 {
149 return rekey * 3600;
150 }
151 }
152 /* every 12 hours */
153 return 12 * 3600;
154 }
155
156 /**
157 * Implementation of peer_enumerator_t.public.enumerate
158 */
159 static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
160 {
161 char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey;
162 char *local_id, *local_addr, *local_net;
163 char *remote_id, *remote_addr, *remote_net;
164 child_cfg_t *child_cfg;
165 ike_cfg_t *ike_cfg;
166 auth_info_t *auth;
167 auth_class_t class;
168
169 /* defaults */
170 name = "unnamed";
171 local_id = NULL;
172 remote_id = NULL;
173 local_addr = "0.0.0.0";
174 remote_addr = "0.0.0.0";
175 local_net = NULL;
176 remote_net = NULL;
177 ike_proposal = NULL;
178 esp_proposal = NULL;
179 ike_rekey = NULL;
180 esp_rekey = NULL;
181
182 if (this->inner->enumerate(this->inner, &name, &local_id, &remote_id,
183 &local_addr, &remote_addr, &local_net, &remote_net,
184 &ike_proposal, &esp_proposal, &ike_rekey, &esp_rekey))
185 {
186 DESTROY_IF(this->peer_cfg);
187 ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, remote_addr);
188 ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
189 this->peer_cfg = peer_cfg_create(
190 name, 2, ike_cfg, create_id(local_id), create_id(remote_id),
191 CERT_SEND_IF_ASKED, UNIQUE_NO,
192 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
193 1800, 900, /* jitter, overtime */
194 TRUE, 60, /* mobike, dpddelay */
195 NULL, NULL, /* vip, pool */
196 FALSE, NULL, NULL); /* mediation, med by, peer id */
197 auth = this->peer_cfg->get_auth(this->peer_cfg);
198 class = AUTH_CLASS_PSK;
199 auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
200 child_cfg = child_cfg_create(name,
201 create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300,
202 NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
203 child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
204 child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
205 child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
206 this->peer_cfg->add_child_cfg(this->peer_cfg, child_cfg);
207 *cfg = this->peer_cfg;
208 return TRUE;
209 }
210 return FALSE;
211 }
212
213 /**
214 * Implementation of peer_enumerator_t.public.destroy
215 */
216 static void peer_enumerator_destroy(peer_enumerator_t *this)
217 {
218 DESTROY_IF(this->peer_cfg);
219 this->inner->destroy(this->inner);
220 free(this);
221 }
222
223 /**
224 * Implementation of backend_t.create_peer_cfg_enumerator.
225 */
226 static enumerator_t* create_peer_cfg_enumerator(private_uci_config_t *this,
227 identification_t *me,
228 identification_t *other)
229 {
230 peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
231
232 e->public.enumerate = (void*)peer_enumerator_enumerate;
233 e->public.destroy = (void*)peer_enumerator_destroy;
234 e->peer_cfg = NULL;
235 e->inner = this->parser->create_section_enumerator(this->parser,
236 "local_id", "remote_id", "local_addr", "remote_addr",
237 "local_net", "remote_net", "ike_proposal", "esp_proposal",
238 "ike_rekey", "esp_rekey", NULL);
239 if (!e->inner)
240 {
241 free(e);
242 return NULL;
243 }
244 return &e->public;
245 }
246
247 /**
248 * enumerator implementation for create_ike_cfg_enumerator
249 */
250 typedef struct {
251 /** implements enumerator */
252 enumerator_t public;
253 /** currently enumerated ike config */
254 ike_cfg_t *ike_cfg;
255 /** inner uci_parser section enumerator */
256 enumerator_t *inner;
257 } ike_enumerator_t;
258
259 /**
260 * Implementation of peer_enumerator_t.public.enumerate
261 */
262 static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
263 {
264 char *local_addr, *remote_addr, *ike_proposal;
265
266 /* defaults */
267 local_addr = "0.0.0.0";
268 remote_addr = "0.0.0.0";
269 ike_proposal = NULL;
270
271 if (this->inner->enumerate(this->inner, NULL,
272 &local_addr, &remote_addr, &ike_proposal))
273 {
274 DESTROY_IF(this->ike_cfg);
275 this->ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, remote_addr);
276 this->ike_cfg->add_proposal(this->ike_cfg,
277 create_proposal(ike_proposal, PROTO_IKE));
278
279 *cfg = this->ike_cfg;
280 return TRUE;
281 }
282 return FALSE;
283 }
284
285 /**
286 * Implementation of ike_enumerator_t.public.destroy
287 */
288 static void ike_enumerator_destroy(ike_enumerator_t *this)
289 {
290 DESTROY_IF(this->ike_cfg);
291 this->inner->destroy(this->inner);
292 free(this);
293 }
294
295 /**
296 * Implementation of backend_t.create_ike_cfg_enumerator.
297 */
298 static enumerator_t* create_ike_cfg_enumerator(private_uci_config_t *this,
299 host_t *me, host_t *other)
300 {
301 ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
302
303 e->public.enumerate = (void*)ike_enumerator_enumerate;
304 e->public.destroy = (void*)ike_enumerator_destroy;
305 e->ike_cfg = NULL;
306 e->inner = this->parser->create_section_enumerator(this->parser,
307 "local_addr", "remote_addr", "ike_proposal", NULL);
308 if (!e->inner)
309 {
310 free(e);
311 return NULL;
312 }
313 return &e->public;
314 }
315
316 /**
317 * implements backend_t.get_peer_cfg_by_name.
318 */
319 static peer_cfg_t *get_peer_cfg_by_name(private_uci_config_t *this, char *name)
320 {
321 enumerator_t *enumerator;
322 peer_cfg_t *current, *found = NULL;
323
324 enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
325 if (enumerator)
326 {
327 while (enumerator->enumerate(enumerator, &current))
328 {
329 if (streq(name, current->get_name(current)))
330 {
331 found = current->get_ref(current);
332 break;
333 }
334 }
335 enumerator->destroy(enumerator);
336 }
337 return found;
338 }
339
340 /**
341 * Implementation of uci_config_t.destroy.
342 */
343 static void destroy(private_uci_config_t *this)
344 {
345 free(this);
346 }
347
348 /**
349 * Described in header.
350 */
351 uci_config_t *uci_config_create(uci_parser_t *parser)
352 {
353 private_uci_config_t *this = malloc_thing(private_uci_config_t);
354
355 this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
356 this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
357 this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
358 this->public.destroy = (void(*)(uci_config_t*))destroy;
359 this->parser = parser;
360
361 return &this->public;
362 }
363