2 * Copyright (C) 2006-2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
20 #include "sql_config.h"
24 typedef struct private_sql_config_t private_sql_config_t
;
27 * Private data of an sql_config_t object
29 struct private_sql_config_t
{
45 static peer_cfg_t
*build_peer_cfg(private_sql_config_t
*this, enumerator_t
*e
,
46 identification_t
*me
, identification_t
*other
);
49 * build a traffic selector from a SQL query
51 static traffic_selector_t
*build_traffic_selector(private_sql_config_t
*this,
52 enumerator_t
*e
, bool *local
)
54 int type
, protocol
, start_port
, end_port
;
55 chunk_t start_addr
, end_addr
;
56 traffic_selector_t
*ts
;
61 TS_REMOTE_DYNAMIC
= 3,
64 while (e
->enumerate(e
, &kind
, &type
, &protocol
,
65 &start_addr
, &end_addr
, &start_port
, &end_port
))
74 ts
= traffic_selector_create_from_bytes(protocol
, type
,
75 start_addr
, start_port
, end_addr
, end_port
);
77 case TS_LOCAL_DYNAMIC
:
80 case TS_REMOTE_DYNAMIC
:
81 ts
= traffic_selector_create_dynamic(protocol
,
82 start_port
, end_port
);
96 * Add traffic selectors to a child config
98 static void add_traffic_selectors(private_sql_config_t
*this,
99 child_cfg_t
*child
, int id
)
102 traffic_selector_t
*ts
;
105 e
= this->db
->query(this->db
,
106 "SELECT kind, type, protocol, "
107 "start_addr, end_addr, start_port, end_port "
108 "FROM traffic_selectors JOIN child_config_traffic_selector "
109 "ON id = traffic_selector WHERE child_cfg = ?",
111 DB_INT
, DB_INT
, DB_INT
,
112 DB_BLOB
, DB_BLOB
, DB_INT
, DB_INT
);
115 while ((ts
= build_traffic_selector(this, e
, &local
)))
117 child
->add_traffic_selector(child
, local
, ts
);
124 * build a Child configuration from a SQL query
126 static child_cfg_t
*build_child_cfg(private_sql_config_t
*this, enumerator_t
*e
)
128 int id
, lifetime
, rekeytime
, jitter
, hostaccess
, mode
, dpd
, close
, ipcomp
;
130 child_cfg_t
*child_cfg
;
132 if (e
->enumerate(e
, &id
, &name
, &lifetime
, &rekeytime
, &jitter
,
133 &updown
, &hostaccess
, &mode
, &dpd
, &close
, &ipcomp
))
135 child_cfg
= child_cfg_create(name
, lifetime
, rekeytime
, jitter
,
136 updown
, hostaccess
, mode
, dpd
, close
, ipcomp
);
137 /* TODO: read proposal from db */
138 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
139 add_traffic_selectors(this, child_cfg
, id
);
146 * Add child configs to peer config
148 static void add_child_cfgs(private_sql_config_t
*this, peer_cfg_t
*peer
, int id
)
151 child_cfg_t
*child_cfg
;
153 e
= this->db
->query(this->db
,
154 "SELECT id, name, lifetime, rekeytime, jitter, "
155 "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
156 "FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
157 "WHERE peer_cfg = ?",
159 DB_INT
, DB_TEXT
, DB_INT
, DB_INT
, DB_INT
,
160 DB_TEXT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
);
163 while ((child_cfg
= build_child_cfg(this, e
)))
165 peer
->add_child_cfg(peer
, child_cfg
);
172 * build a ike configuration from a SQL query
174 static ike_cfg_t
*build_ike_cfg(private_sql_config_t
*this, enumerator_t
*e
,
175 host_t
*my_host
, host_t
*other_host
)
177 int certreq
, force_encap
;
178 char *local
, *remote
;
180 while (e
->enumerate(e
, &certreq
, &force_encap
, &local
, &remote
))
185 me
= host_create_from_string(local
, 500);
190 if (my_host
&& !me
->is_anyaddr(me
) &&
191 !me
->ip_equals(me
, my_host
))
196 other
= host_create_from_string(remote
, 500);
202 if (other_host
&& !other
->is_anyaddr(other
) &&
203 !other
->ip_equals(other
, other_host
))
206 other
->destroy(other
);
209 ike_cfg
= ike_cfg_create(certreq
, force_encap
, me
, other
);
210 /* TODO: read proposal from db */
211 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
218 * Query a IKE config by its id
220 static ike_cfg_t
* get_ike_cfg_by_id(private_sql_config_t
*this, int id
)
223 ike_cfg_t
*ike_cfg
= NULL
;
225 e
= this->db
->query(this->db
,
226 "SELECT certreq, force_encap, local, remote "
227 "FROM ike_configs WHERE id = ?",
229 DB_INT
, DB_INT
, DB_TEXT
, DB_TEXT
);
232 ike_cfg
= build_ike_cfg(this, e
, NULL
, NULL
);
239 * Query a peer config by its id
241 static peer_cfg_t
*get_peer_cfg_by_id(private_sql_config_t
*this, int id
)
244 peer_cfg_t
*peer_cfg
= NULL
;
246 e
= this->db
->query(this->db
,
247 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
248 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
249 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
250 "dpd_delay, virtual, pool, "
251 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
252 "FROM peer_configs AS c "
253 "JOIN identities AS l ON local_id = l.id "
254 "JOIN identities AS r ON remote_id = r.id "
255 "LEFT JOIN identities AS p ON peer_id = p.id "
258 DB_INT
, DB_TEXT
, DB_INT
, DB_INT
, DB_BLOB
, DB_INT
, DB_BLOB
,
259 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
260 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
261 DB_INT
, DB_TEXT
, DB_TEXT
,
262 DB_INT
, DB_INT
, DB_INT
, DB_BLOB
);
265 peer_cfg
= build_peer_cfg(this, e
, NULL
, NULL
);
272 * build a peer configuration from a SQL query
274 static peer_cfg_t
*build_peer_cfg(private_sql_config_t
*this, enumerator_t
*e
,
275 identification_t
*me
, identification_t
*other
)
277 int id
, ike_cfg
, l_type
, r_type
,
278 cert_policy
, uniqueid
, auth_method
, eap_type
, eap_vendor
, keyingtries
,
279 rekeytime
, reauthtime
, jitter
, overtime
, mobike
, dpd_delay
,
280 mediation
, mediated_by
, p_type
;
281 chunk_t l_data
, r_data
, p_data
;
282 char *name
, *virtual, *pool
;
284 while (e
->enumerate(e
,
285 &id
, &name
, &ike_cfg
, &l_type
, &l_data
, &r_type
, &r_data
,
286 &cert_policy
, &uniqueid
, &auth_method
, &eap_type
, &eap_vendor
,
287 &keyingtries
, &rekeytime
, &reauthtime
, &jitter
, &overtime
, &mobike
,
288 &dpd_delay
, &virtual, &pool
,
289 &mediation
, &mediated_by
, &p_type
, &p_data
))
291 identification_t
*local_id
, *remote_id
, *peer_id
= NULL
;
292 peer_cfg_t
*peer_cfg
, *mediated_cfg
;
296 local_id
= identification_create_from_encoding(l_type
, l_data
);
297 remote_id
= identification_create_from_encoding(r_type
, r_data
);
298 if ((me
&& !me
->matches(me
, local_id
)) ||
299 (other
&& !other
->matches(other
, remote_id
)))
301 local_id
->destroy(local_id
);
302 remote_id
->destroy(remote_id
);
305 ike
= get_ike_cfg_by_id(this, ike_cfg
);
306 mediated_cfg
= mediated_by ?
get_peer_cfg_by_id(this, mediated_by
) : NULL
;
309 peer_id
= identification_create_from_encoding(p_type
, p_data
);
313 vip
= host_create_from_string(virtual, 0);
317 peer_cfg
= peer_cfg_create(
318 name
, 2, ike
, local_id
, remote_id
, cert_policy
, uniqueid
,
319 auth_method
, eap_type
, eap_vendor
, keyingtries
,
320 rekeytime
, reauthtime
, jitter
, overtime
, mobike
,
321 dpd_delay
, vip
, pool
,
322 mediation
, mediated_cfg
, peer_id
);
323 add_child_cfgs(this, peer_cfg
, id
);
327 DESTROY_IF(mediated_cfg
);
329 DESTROY_IF(local_id
);
330 DESTROY_IF(remote_id
);
336 * implements backend_t.get_peer_cfg_by_name.
338 static peer_cfg_t
*get_peer_cfg_by_name(private_sql_config_t
*this, char *name
)
341 peer_cfg_t
*peer_cfg
= NULL
;
343 e
= this->db
->query(this->db
,
344 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
345 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
346 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
347 "dpd_delay, virtual, pool, "
348 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
349 "FROM peer_configs AS c "
350 "JOIN identities AS l ON local_id = l.id "
351 "JOIN identities AS r ON remote_id = r.id "
352 "LEFT JOIN identities AS p ON peer_id = p.id "
353 "WHERE ike_version = ? AND name = ?",
354 DB_INT
, 2, DB_TEXT
, name
,
355 DB_INT
, DB_TEXT
, DB_INT
, DB_INT
, DB_BLOB
, DB_INT
, DB_BLOB
,
356 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
357 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
358 DB_INT
, DB_TEXT
, DB_TEXT
,
359 DB_INT
, DB_INT
, DB_INT
, DB_BLOB
);
362 peer_cfg
= build_peer_cfg(this, e
, NULL
, NULL
);
369 /** implements enumerator */
371 /** reference to context */
372 private_sql_config_t
*this;
373 /** filtering own host */
375 /** filtering remote host */
377 /** inner SQL enumerator */
379 /** currently enumerated peer config */
384 * Implementation of ike_enumerator_t.public.enumerate
386 static bool ike_enumerator_enumerate(ike_enumerator_t
*this, ike_cfg_t
**cfg
)
388 DESTROY_IF(this->current
);
389 this->current
= build_ike_cfg(this->this, this->inner
, this->me
, this->other
);
392 *cfg
= this->current
;
399 * Implementation of ike_enumerator_t.public.destroy
401 static void ike_enumerator_destroy(ike_enumerator_t
*this)
403 DESTROY_IF(this->current
);
404 this->inner
->destroy(this->inner
);
409 * Implementation of backend_t.create_ike_cfg_enumerator.
411 static enumerator_t
* create_ike_cfg_enumerator(private_sql_config_t
*this,
412 host_t
*me
, host_t
*other
)
414 ike_enumerator_t
*e
= malloc_thing(ike_enumerator_t
);
420 e
->public.enumerate
= (void*)ike_enumerator_enumerate
;
421 e
->public.destroy
= (void*)ike_enumerator_destroy
;
423 e
->inner
= this->db
->query(this->db
,
424 "SELECT certreq, force_encap, local, remote "
426 DB_INT
, DB_INT
, DB_TEXT
, DB_TEXT
);
437 /** implements enumerator */
439 /** reference to context */
440 private_sql_config_t
*this;
441 /** filtering own identity */
442 identification_t
*me
;
443 /** filtering remote identity */
444 identification_t
*other
;
445 /** inner SQL enumerator */
447 /** currently enumerated peer config */
452 * Implementation of peer_enumerator_t.public.enumerate
454 static bool peer_enumerator_enumerate(peer_enumerator_t
*this, peer_cfg_t
**cfg
)
456 DESTROY_IF(this->current
);
457 this->current
= build_peer_cfg(this->this, this->inner
, this->me
, this->other
);
460 *cfg
= this->current
;
467 * Implementation of peer_enumerator_t.public.destroy
469 static void peer_enumerator_destroy(peer_enumerator_t
*this)
471 DESTROY_IF(this->current
);
472 this->inner
->destroy(this->inner
);
477 * Implementation of backend_t.create_peer_cfg_enumerator.
479 static enumerator_t
* create_peer_cfg_enumerator(private_sql_config_t
*this,
480 identification_t
*me
,
481 identification_t
*other
)
483 peer_enumerator_t
*e
= malloc_thing(peer_enumerator_t
);
489 e
->public.enumerate
= (void*)peer_enumerator_enumerate
;
490 e
->public.destroy
= (void*)peer_enumerator_destroy
;
492 /* TODO: only get configs whose IDs match exactly or contain wildcards */
493 e
->inner
= this->db
->query(this->db
,
494 "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, "
495 "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, "
496 "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, "
497 "dpd_delay, virtual, pool, "
498 "mediation, mediated_by, COALESCE(p.type, 0), p.data "
499 "FROM peer_configs AS c "
500 "JOIN identities AS l ON local_id = l.id "
501 "JOIN identities AS r ON remote_id = r.id "
502 "LEFT JOIN identities AS p ON peer_id = p.id "
503 "WHERE ike_version = ?",
505 DB_INT
, DB_TEXT
, DB_INT
, DB_INT
, DB_BLOB
, DB_INT
, DB_BLOB
,
506 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
507 DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
, DB_INT
,
508 DB_INT
, DB_TEXT
, DB_TEXT
,
509 DB_INT
, DB_INT
, DB_INT
, DB_BLOB
);
519 * Implementation of sql_config_t.destroy.
521 static void destroy(private_sql_config_t
*this)
527 * Described in header.
529 sql_config_t
*sql_config_create(database_t
*db
)
531 private_sql_config_t
*this = malloc_thing(private_sql_config_t
);
533 this->public.backend
.create_peer_cfg_enumerator
= (enumerator_t
*(*)(backend_t
*, identification_t
*me
, identification_t
*other
))create_peer_cfg_enumerator
;
534 this->public.backend
.create_ike_cfg_enumerator
= (enumerator_t
*(*)(backend_t
*, host_t
*me
, host_t
*other
))create_ike_cfg_enumerator
;
535 this->public.backend
.get_peer_cfg_by_name
= (peer_cfg_t
* (*)(backend_t
*,char*))get_peer_cfg_by_name
;
536 this->public.destroy
= (void(*)(sql_config_t
*))destroy
;
540 return &this->public;