6dae14e3dcc7222dead660b576a38c11dd0f1e49
[strongswan.git] / src / libcharon / 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
18 #define _GNU_SOURCE
19 #include <string.h>
20
21 #include "uci_config.h"
22 #include "uci_parser.h"
23
24 #include <daemon.h>
25
26 typedef struct private_uci_config_t private_uci_config_t;
27
28 /**
29 * Private data of an uci_config_t object
30 */
31 struct private_uci_config_t {
32
33 /**
34 * Public part
35 */
36 uci_config_t public;
37
38 /**
39 * UCI parser context
40 */
41 uci_parser_t *parser;
42 };
43
44 /**
45 * enumerator implementation for create_peer_cfg_enumerator
46 */
47 typedef struct {
48 /** implements enumerator */
49 enumerator_t public;
50 /** currently enumerated peer config */
51 peer_cfg_t *peer_cfg;
52 /** inner uci_parser section enumerator */
53 enumerator_t *inner;
54 } peer_enumerator_t;
55
56 /**
57 * create a proposal from a string, with fallback to default
58 */
59 static proposal_t *create_proposal(char *string, protocol_id_t proto)
60 {
61 proposal_t *proposal = NULL;
62
63 if (string)
64 {
65 proposal = proposal_create_from_string(proto, string);
66 }
67 if (!proposal)
68 { /* UCI default is aes/sha1 only */
69 if (proto == PROTO_IKE)
70 {
71 proposal = proposal_create_from_string(proto,
72 "aes128-aes192-aes256-sha1-modp1536-modp2048");
73 }
74 else
75 {
76 proposal = proposal_create_from_string(proto,
77 "aes128-aes192-aes256-sha1");
78 }
79 }
80 return proposal;
81 }
82
83 /**
84 * create an traffic selector, fallback to dynamic
85 */
86 static traffic_selector_t *create_ts(char *string)
87 {
88 if (string)
89 {
90 traffic_selector_t *ts;
91
92 ts = traffic_selector_create_from_cidr(string, 0, 0);
93 if (ts)
94 {
95 return ts;
96 }
97 }
98 return traffic_selector_create_dynamic(0, 0, 65535);
99 }
100
101 /**
102 * create a rekey time from a string with hours, with fallback
103 */
104 static u_int create_rekey(char *string)
105 {
106 u_int rekey = 0;
107
108 if (string)
109 {
110 rekey = atoi(string);
111 if (rekey)
112 {
113 return rekey * 3600;
114 }
115 }
116 /* every 12 hours */
117 return 12 * 3600;
118 }
119
120 METHOD(enumerator_t, peer_enumerator_enumerate, bool,
121 peer_enumerator_t *this, peer_cfg_t **cfg)
122 {
123 char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey;
124 char *local_id, *local_addr, *local_net;
125 char *remote_id, *remote_addr, *remote_net;
126 child_cfg_t *child_cfg;
127 ike_cfg_t *ike_cfg;
128 auth_cfg_t *auth;
129 lifetime_cfg_t lifetime = {
130 .time = {
131 .life = create_rekey(esp_rekey) + 300,
132 .rekey = create_rekey(esp_rekey),
133 .jitter = 300
134 }
135 };
136
137 /* defaults */
138 name = "unnamed";
139 local_id = NULL;
140 remote_id = NULL;
141 local_addr = "0.0.0.0";
142 remote_addr = "0.0.0.0";
143 local_net = NULL;
144 remote_net = NULL;
145 ike_proposal = NULL;
146 esp_proposal = NULL;
147 ike_rekey = NULL;
148 esp_rekey = NULL;
149
150 if (this->inner->enumerate(this->inner, &name, &local_id, &remote_id,
151 &local_addr, &remote_addr, &local_net, &remote_net,
152 &ike_proposal, &esp_proposal, &ike_rekey, &esp_rekey))
153 {
154 DESTROY_IF(this->peer_cfg);
155 ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
156 local_addr, FALSE,
157 charon->socket->get_port(charon->socket, FALSE),
158 remote_addr, FALSE, IKEV2_UDP_PORT, FALSE);
159 ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
160 this->peer_cfg = peer_cfg_create(
161 name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
162 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
163 1800, 900, /* jitter, overtime */
164 TRUE, FALSE, /* mobike, aggressive */
165 60, 0, /* DPD delay, timeout */
166 FALSE, NULL, NULL); /* mediation, med by, peer id */
167 auth = auth_cfg_create();
168 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
169 auth->add(auth, AUTH_RULE_IDENTITY,
170 identification_create_from_string(local_id));
171 this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, TRUE);
172
173 auth = auth_cfg_create();
174 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
175 if (remote_id)
176 {
177 auth->add(auth, AUTH_RULE_IDENTITY,
178 identification_create_from_string(remote_id));
179 }
180 this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
181
182 child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
183 ACTION_NONE, ACTION_NONE, ACTION_NONE,
184 FALSE, 0, 0, NULL, NULL, 0);
185 child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
186 child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
187 child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
188 this->peer_cfg->add_child_cfg(this->peer_cfg, child_cfg);
189 *cfg = this->peer_cfg;
190 return TRUE;
191 }
192 return FALSE;
193 }
194
195
196 METHOD(enumerator_t, peer_enumerator_destroy, void,
197 peer_enumerator_t *this)
198 {
199 DESTROY_IF(this->peer_cfg);
200 this->inner->destroy(this->inner);
201 free(this);
202 }
203
204 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
205 private_uci_config_t *this, identification_t *me, identification_t *other)
206 {
207 peer_enumerator_t *e;
208
209 INIT(e,
210 .public = {
211 .enumerate = (void*)_peer_enumerator_enumerate,
212 .destroy = _peer_enumerator_destroy,
213 },
214 .inner = this->parser->create_section_enumerator(this->parser,
215 "local_id", "remote_id", "local_addr", "remote_addr",
216 "local_net", "remote_net", "ike_proposal", "esp_proposal",
217 "ike_rekey", "esp_rekey", NULL),
218 );
219 if (!e->inner)
220 {
221 free(e);
222 return NULL;
223 }
224 return &e->public;
225 }
226
227 /**
228 * enumerator implementation for create_ike_cfg_enumerator
229 */
230 typedef struct {
231 /** implements enumerator */
232 enumerator_t public;
233 /** currently enumerated ike config */
234 ike_cfg_t *ike_cfg;
235 /** inner uci_parser section enumerator */
236 enumerator_t *inner;
237 } ike_enumerator_t;
238
239 METHOD(enumerator_t, ike_enumerator_enumerate, bool,
240 ike_enumerator_t *this, ike_cfg_t **cfg)
241 {
242 char *local_addr, *remote_addr, *ike_proposal;
243
244 /* defaults */
245 local_addr = "0.0.0.0";
246 remote_addr = "0.0.0.0";
247 ike_proposal = NULL;
248
249 if (this->inner->enumerate(this->inner, NULL,
250 &local_addr, &remote_addr, &ike_proposal))
251 {
252 DESTROY_IF(this->ike_cfg);
253 this->ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE,
254 local_addr, FALSE,
255 charon->socket->get_port(charon->socket, FALSE),
256 remote_addr, FALSE, IKEV2_UDP_PORT, FALSE);
257 this->ike_cfg->add_proposal(this->ike_cfg,
258 create_proposal(ike_proposal, PROTO_IKE));
259
260 *cfg = this->ike_cfg;
261 return TRUE;
262 }
263 return FALSE;
264 }
265
266 METHOD(enumerator_t, ike_enumerator_destroy, void,
267 ike_enumerator_t *this)
268 {
269 DESTROY_IF(this->ike_cfg);
270 this->inner->destroy(this->inner);
271 free(this);
272 }
273
274 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
275 private_uci_config_t *this, host_t *me, host_t *other)
276 {
277 ike_enumerator_t *e;
278
279 INIT(e,
280 .public = {
281 .enumerate = (void*)_ike_enumerator_enumerate,
282 .destroy = _ike_enumerator_destroy,
283 },
284 .inner = this->parser->create_section_enumerator(this->parser,
285 "local_addr", "remote_addr", "ike_proposal", NULL),
286 );
287 if (!e->inner)
288 {
289 free(e);
290 return NULL;
291 }
292 return &e->public;
293 }
294
295 METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
296 private_uci_config_t *this, char *name)
297 {
298 enumerator_t *enumerator;
299 peer_cfg_t *current, *found = NULL;
300
301 enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
302 if (enumerator)
303 {
304 while (enumerator->enumerate(enumerator, &current))
305 {
306 if (streq(name, current->get_name(current)))
307 {
308 found = current->get_ref(current);
309 break;
310 }
311 }
312 enumerator->destroy(enumerator);
313 }
314 return found;
315 }
316
317 METHOD(uci_config_t, destroy, void,
318 private_uci_config_t *this)
319 {
320 free(this);
321 }
322
323 /**
324 * Described in header.
325 */
326 uci_config_t *uci_config_create(uci_parser_t *parser)
327 {
328 private_uci_config_t *this;
329
330 INIT(this,
331 .public = {
332 .backend = {
333 .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
334 .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
335 .get_peer_cfg_by_name = _get_peer_cfg_by_name,
336 },
337 .destroy = _destroy,
338 },
339 .parser = parser,
340 );
341
342 return &this->public;
343 }
344