removing svn keyword $Id$ from all files
[strongswan.git] / src / charon / plugins / sql / sql_config.c
1 /*
2 * Copyright (C) 2006-2008 Martin Willi
3 * 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 <string.h>
17
18 #include "sql_config.h"
19
20 #include <daemon.h>
21
22 typedef struct private_sql_config_t private_sql_config_t;
23
24 /**
25 * Private data of an sql_config_t object
26 */
27 struct private_sql_config_t {
28
29 /**
30 * Public part
31 */
32 sql_config_t public;
33
34 /**
35 * database connection
36 */
37 database_t *db;
38 };
39
40 /**
41 * forward declaration
42 */
43 static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
44 identification_t *me, identification_t *other);
45
46 /**
47 * build a traffic selector from a SQL query
48 */
49 static traffic_selector_t *build_traffic_selector(private_sql_config_t *this,
50 enumerator_t *e, bool *local)
51 {
52 int type, protocol, start_port, end_port;
53 chunk_t start_addr, end_addr;
54 traffic_selector_t *ts;
55 enum {
56 TS_LOCAL = 0,
57 TS_REMOTE = 1,
58 TS_LOCAL_DYNAMIC = 2,
59 TS_REMOTE_DYNAMIC = 3,
60 } kind;
61
62 while (e->enumerate(e, &kind, &type, &protocol,
63 &start_addr, &end_addr, &start_port, &end_port))
64 {
65 *local = FALSE;
66 switch (kind)
67 {
68 case TS_LOCAL:
69 *local = TRUE;
70 /* FALL */
71 case TS_REMOTE:
72 ts = traffic_selector_create_from_bytes(protocol, type,
73 start_addr, start_port, end_addr, end_port);
74 break;
75 case TS_LOCAL_DYNAMIC:
76 *local = TRUE;
77 /* FALL */
78 case TS_REMOTE_DYNAMIC:
79 ts = traffic_selector_create_dynamic(protocol,
80 start_port, end_port);
81 break;
82 default:
83 continue;
84 }
85 if (ts)
86 {
87 return ts;
88 }
89 }
90 return NULL;
91 }
92
93 /**
94 * Add traffic selectors to a child config
95 */
96 static void add_traffic_selectors(private_sql_config_t *this,
97 child_cfg_t *child, int id)
98 {
99 enumerator_t *e;
100 traffic_selector_t *ts;
101 bool local;
102
103 e = this->db->query(this->db,
104 "SELECT kind, type, protocol, "
105 "start_addr, end_addr, start_port, end_port "
106 "FROM traffic_selectors JOIN child_config_traffic_selector "
107 "ON id = traffic_selector WHERE child_cfg = ?",
108 DB_INT, id,
109 DB_INT, DB_INT, DB_INT,
110 DB_BLOB, DB_BLOB, DB_INT, DB_INT);
111 if (e)
112 {
113 while ((ts = build_traffic_selector(this, e, &local)))
114 {
115 child->add_traffic_selector(child, local, ts);
116 }
117 e->destroy(e);
118 }
119 }
120
121 /**
122 * build a Child configuration from a SQL query
123 */
124 static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
125 {
126 int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp;
127 char *name, *updown;
128 child_cfg_t *child_cfg;
129
130 if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
131 &updown, &hostaccess, &mode, &dpd, &close, &ipcomp))
132 {
133 child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter,
134 updown, hostaccess, mode, dpd, close, ipcomp);
135 /* TODO: read proposal from db */
136 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
137 add_traffic_selectors(this, child_cfg, id);
138 return child_cfg;
139 }
140 return NULL;
141 }
142
143 /**
144 * Add child configs to peer config
145 */
146 static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
147 {
148 enumerator_t *e;
149 child_cfg_t *child_cfg;
150
151 e = this->db->query(this->db,
152 "SELECT id, name, lifetime, rekeytime, jitter, "
153 "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
154 "FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
155 "WHERE peer_cfg = ?",
156 DB_INT, id,
157 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT,
158 DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
159 if (e)
160 {
161 while ((child_cfg = build_child_cfg(this, e)))
162 {
163 peer->add_child_cfg(peer, child_cfg);
164 }
165 e->destroy(e);
166 }
167 }
168
169 /**
170 * build a ike configuration from a SQL query
171 */
172 static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
173 host_t *my_host, host_t *other_host)
174 {
175 int certreq, force_encap;
176 char *local, *remote;
177
178 while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
179 {
180 ike_cfg_t *ike_cfg;
181
182 ike_cfg = ike_cfg_create(certreq, force_encap, local, remote);
183 /* TODO: read proposal from db */
184 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
185 return ike_cfg;
186 }
187 return NULL;
188 }
189
190 /**
191 * Query a IKE config by its id
192 */
193 static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
194 {
195 enumerator_t *e;
196 ike_cfg_t *ike_cfg = NULL;
197
198 e = this->db->query(this->db,
199 "SELECT certreq, force_encap, local, remote "
200 "FROM ike_configs WHERE id = ?",
201 DB_INT, id,
202 DB_INT, DB_INT, DB_TEXT, DB_TEXT);
203 if (e)
204 {
205 ike_cfg = build_ike_cfg(this, e, NULL, NULL);
206 e->destroy(e);
207 }
208 return ike_cfg;
209 }
210
211 /**
212 * Query a peer config by its id
213 */
214 static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
215 {
216 enumerator_t *e;
217 peer_cfg_t *peer_cfg = NULL;
218
219 e = this->db->query(this->db,
220 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
221 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
222 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
223 "dpd_delay, virtual, pool, "
224 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
225 "FROM peer_configs AS c "
226 "JOIN identities AS l ON local_id = l.id "
227 "JOIN identities AS r ON remote_id = r.id "
228 "LEFT JOIN identities AS p ON peer_id = p.id "
229 "WHERE id = ?",
230 DB_INT, id,
231 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
232 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
233 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
234 DB_INT, DB_TEXT, DB_TEXT,
235 DB_INT, DB_INT, DB_INT, DB_BLOB);
236 if (e)
237 {
238 peer_cfg = build_peer_cfg(this, e, NULL, NULL);
239 e->destroy(e);
240 }
241 return peer_cfg;
242 }
243
244 /**
245 * build a peer configuration from a SQL query
246 */
247 static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
248 identification_t *me, identification_t *other)
249 {
250 int id, ike_cfg, l_type, r_type,
251 cert_policy, uniqueid, auth_method, eap_type, eap_vendor, keyingtries,
252 rekeytime, reauthtime, jitter, overtime, mobike, dpd_delay,
253 mediation, mediated_by, p_type;
254 chunk_t l_data, r_data, p_data;
255 char *name, *virtual, *pool;
256
257 while (e->enumerate(e,
258 &id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data,
259 &cert_policy, &uniqueid, &auth_method, &eap_type, &eap_vendor,
260 &keyingtries, &rekeytime, &reauthtime, &jitter, &overtime, &mobike,
261 &dpd_delay, &virtual, &pool,
262 &mediation, &mediated_by, &p_type, &p_data))
263 {
264 identification_t *local_id, *remote_id, *peer_id = NULL;
265 peer_cfg_t *peer_cfg, *mediated_cfg;
266 ike_cfg_t *ike;
267 host_t *vip = NULL;
268 auth_cfg_t *auth;
269
270 local_id = identification_create_from_encoding(l_type, l_data);
271 remote_id = identification_create_from_encoding(r_type, r_data);
272 if ((me && !me->matches(me, local_id)) ||
273 (other && !other->matches(other, remote_id)))
274 {
275 local_id->destroy(local_id);
276 remote_id->destroy(remote_id);
277 continue;
278 }
279 ike = get_ike_cfg_by_id(this, ike_cfg);
280 mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
281 if (p_type)
282 {
283 peer_id = identification_create_from_encoding(p_type, p_data);
284 }
285 if (virtual)
286 {
287 vip = host_create_from_string(virtual, 0);
288 }
289 if (ike)
290 {
291 peer_cfg = peer_cfg_create(
292 name, 2, ike, cert_policy, uniqueid,
293 keyingtries, rekeytime, reauthtime, jitter, overtime,
294 mobike, dpd_delay, vip, pool,
295 mediation, mediated_cfg, peer_id);
296 auth = auth_cfg_create();
297 auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
298 auth->add(auth, AUTH_RULE_IDENTITY, local_id->clone(local_id));
299 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
300 auth = auth_cfg_create();
301 auth->add(auth, AUTH_RULE_IDENTITY, remote_id->clone(remote_id));
302 if (eap_type)
303 {
304 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
305 auth->add(auth, AUTH_RULE_EAP_TYPE, eap_type);
306 if (eap_vendor)
307 {
308 auth->add(auth, AUTH_RULE_EAP_VENDOR, eap_vendor);
309 }
310 }
311 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
312 add_child_cfgs(this, peer_cfg, id);
313 return peer_cfg;
314 }
315 DESTROY_IF(ike);
316 DESTROY_IF(mediated_cfg);
317 DESTROY_IF(peer_id);
318 DESTROY_IF(local_id);
319 DESTROY_IF(remote_id);
320 }
321 return NULL;
322 }
323
324 /**
325 * implements backend_t.get_peer_cfg_by_name.
326 */
327 static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name)
328 {
329 enumerator_t *e;
330 peer_cfg_t *peer_cfg = NULL;
331
332 e = this->db->query(this->db,
333 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
334 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
335 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
336 "dpd_delay, virtual, pool, "
337 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
338 "FROM peer_configs AS c "
339 "JOIN identities AS l ON local_id = l.id "
340 "JOIN identities AS r ON remote_id = r.id "
341 "LEFT JOIN identities AS p ON peer_id = p.id "
342 "WHERE ike_version = ? AND name = ?",
343 DB_INT, 2, DB_TEXT, name,
344 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
345 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
346 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
347 DB_INT, DB_TEXT, DB_TEXT,
348 DB_INT, DB_INT, DB_INT, DB_BLOB);
349 if (e)
350 {
351 peer_cfg = build_peer_cfg(this, e, NULL, NULL);
352 e->destroy(e);
353 }
354 return peer_cfg;
355 }
356
357 typedef struct {
358 /** implements enumerator */
359 enumerator_t public;
360 /** reference to context */
361 private_sql_config_t *this;
362 /** filtering own host */
363 host_t *me;
364 /** filtering remote host */
365 host_t *other;
366 /** inner SQL enumerator */
367 enumerator_t *inner;
368 /** currently enumerated peer config */
369 ike_cfg_t *current;
370 } ike_enumerator_t;
371
372 /**
373 * Implementation of ike_enumerator_t.public.enumerate
374 */
375 static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
376 {
377 DESTROY_IF(this->current);
378 this->current = build_ike_cfg(this->this, this->inner, this->me, this->other);
379 if (this->current)
380 {
381 *cfg = this->current;
382 return TRUE;
383 }
384 return FALSE;
385 }
386
387 /**
388 * Implementation of ike_enumerator_t.public.destroy
389 */
390 static void ike_enumerator_destroy(ike_enumerator_t *this)
391 {
392 DESTROY_IF(this->current);
393 this->inner->destroy(this->inner);
394 free(this);
395 }
396
397 /**
398 * Implementation of backend_t.create_ike_cfg_enumerator.
399 */
400 static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
401 host_t *me, host_t *other)
402 {
403 ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
404
405 e->this = this;
406 e->me = me;
407 e->other = other;
408 e->current = NULL;
409 e->public.enumerate = (void*)ike_enumerator_enumerate;
410 e->public.destroy = (void*)ike_enumerator_destroy;
411
412 e->inner = this->db->query(this->db,
413 "SELECT certreq, force_encap, local, remote "
414 "FROM ike_configs",
415 DB_INT, DB_INT, DB_TEXT, DB_TEXT);
416 if (!e->inner)
417 {
418 free(e);
419 return NULL;
420 }
421 return &e->public;
422 }
423
424
425 typedef struct {
426 /** implements enumerator */
427 enumerator_t public;
428 /** reference to context */
429 private_sql_config_t *this;
430 /** filtering own identity */
431 identification_t *me;
432 /** filtering remote identity */
433 identification_t *other;
434 /** inner SQL enumerator */
435 enumerator_t *inner;
436 /** currently enumerated peer config */
437 peer_cfg_t *current;
438 } peer_enumerator_t;
439
440 /**
441 * Implementation of peer_enumerator_t.public.enumerate
442 */
443 static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
444 {
445 DESTROY_IF(this->current);
446 this->current = build_peer_cfg(this->this, this->inner, this->me, this->other);
447 if (this->current)
448 {
449 *cfg = this->current;
450 return TRUE;
451 }
452 return FALSE;
453 }
454
455 /**
456 * Implementation of peer_enumerator_t.public.destroy
457 */
458 static void peer_enumerator_destroy(peer_enumerator_t *this)
459 {
460 DESTROY_IF(this->current);
461 this->inner->destroy(this->inner);
462 free(this);
463 }
464
465 /**
466 * Implementation of backend_t.create_peer_cfg_enumerator.
467 */
468 static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
469 identification_t *me,
470 identification_t *other)
471 {
472 peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
473
474 e->this = this;
475 e->me = me;
476 e->other = other;
477 e->current = NULL;
478 e->public.enumerate = (void*)peer_enumerator_enumerate;
479 e->public.destroy = (void*)peer_enumerator_destroy;
480
481 /* TODO: only get configs whose IDs match exactly or contain wildcards */
482 e->inner = this->db->query(this->db,
483 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
484 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
485 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
486 "dpd_delay, virtual, pool, "
487 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
488 "FROM peer_configs AS c "
489 "JOIN identities AS l ON local_id = l.id "
490 "JOIN identities AS r ON remote_id = r.id "
491 "LEFT JOIN identities AS p ON peer_id = p.id "
492 "WHERE ike_version = ?",
493 DB_INT, 2,
494 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB,
495 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
496 DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
497 DB_INT, DB_TEXT, DB_TEXT,
498 DB_INT, DB_INT, DB_INT, DB_BLOB);
499 if (!e->inner)
500 {
501 free(e);
502 return NULL;
503 }
504 return &e->public;
505 }
506
507 /**
508 * Implementation of sql_config_t.destroy.
509 */
510 static void destroy(private_sql_config_t *this)
511 {
512 free(this);
513 }
514
515 /**
516 * Described in header.
517 */
518 sql_config_t *sql_config_create(database_t *db)
519 {
520 private_sql_config_t *this = malloc_thing(private_sql_config_t);
521
522 this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
523 this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
524 this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
525 this->public.destroy = (void(*)(sql_config_t*))destroy;
526
527 this->db = db;
528
529 return &this->public;
530 }
531