diff options
Diffstat (limited to 'src/charon/plugins/sql/sql_config.c')
-rw-r--r-- | src/charon/plugins/sql/sql_config.c | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c new file mode 100644 index 000000000..eaa9da5ef --- /dev/null +++ b/src/charon/plugins/sql/sql_config.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2006-2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include <string.h> + +#include "sql_config.h" + +#include <daemon.h> + +typedef struct private_sql_config_t private_sql_config_t; + +/** + * Private data of an sql_config_t object + */ +struct private_sql_config_t { + + /** + * Public part + */ + sql_config_t public; + + /** + * database connection + */ + database_t *db; +}; + +/** + * forward declaration + */ +static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, + identification_t *me, identification_t *other); + +/** + * build a traffic selector from a SQL query + */ +static traffic_selector_t *build_traffic_selector(private_sql_config_t *this, + enumerator_t *e, bool *local) +{ + int type, protocol, start_port, end_port; + char *start_addr, *end_addr; + traffic_selector_t *ts; + enum { + TS_LOCAL = 0, + TS_REMOTE = 1, + TS_LOCAL_DYNAMIC = 2, + TS_REMOTE_DYNAMIC = 3, + } kind; + + while (e->enumerate(e, &kind, &type, &protocol, + &start_addr, &end_addr, &start_port, &end_port)) + { + *local = FALSE; + switch (kind) + { + case TS_LOCAL: + *local = TRUE; + /* FALL */ + case TS_REMOTE: + ts = traffic_selector_create_from_string(protocol, type, + start_addr, start_port, end_addr, end_port); + break; + case TS_LOCAL_DYNAMIC: + *local = TRUE; + /* FALL */ + case TS_REMOTE_DYNAMIC: + ts = traffic_selector_create_dynamic(protocol, type, + start_port, end_port); + break; + default: + continue; + } + if (ts) + { + return ts; + } + } + return NULL; +} + +/** + * Add traffic selectors to a child config + */ +static void add_traffic_selectors(private_sql_config_t *this, + child_cfg_t *child, int id) +{ + enumerator_t *e; + traffic_selector_t *ts; + bool local; + + e = this->db->query(this->db, + "SELECT kind, type, protocol, " + "start_addr, end_addr, start_port, end_port " + "FROM traffic_selectors JOIN child_config_traffic_selector " + "ON id = traffic_selector WHERE child_cfg = ?", + DB_INT, id, + DB_INT, DB_INT, DB_INT, + DB_TEXT, DB_TEXT, DB_INT, DB_INT); + if (e) + { + while ((ts = build_traffic_selector(this, e, &local))) + { + child->add_traffic_selector(child, local, ts); + } + e->destroy(e); + } +} + +/** + * build a Child configuration from a SQL query + */ +static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e) +{ + int id, lifetime, rekeytime, jitter, hostaccess, mode; + char *name, *updown; + child_cfg_t *child_cfg; + + if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, + &updown, &hostaccess, &mode)) + { + child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter, + updown, hostaccess, mode); + /* TODO: read proposal from db */ + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + add_traffic_selectors(this, child_cfg, id); + return child_cfg; + } + return NULL; +} + +/** + * Add child configs to peer config + */ +static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id) +{ + enumerator_t *e; + child_cfg_t *child_cfg; + + e = this->db->query(this->db, + "SELECT id, name, lifetime, rekeytime, jitter, " + "updown, hostaccess, mode " + "FROM child_configs JOIN peer_config_child_config ON id = child_cfg " + "WHERE peer_cfg = ?", + DB_INT, id, + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, + DB_TEXT, DB_INT, DB_INT); + if (e) + { + while ((child_cfg = build_child_cfg(this, e))) + { + peer->add_child_cfg(peer, child_cfg); + } + e->destroy(e); + } +} + +/** + * build a ike configuration from a SQL query + */ +static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, + host_t *my_host, host_t *other_host) +{ + int certreq, force_encap; + char *local, *remote; + + while (e->enumerate(e, &certreq, &force_encap, &local, &remote)) + { + host_t *me, *other; + ike_cfg_t *ike_cfg; + + me = host_create_from_string(local, 500); + if (!me) + { + continue; + } + if (my_host && !me->is_anyaddr(me) && + !me->ip_equals(me, my_host)) + { + me->destroy(me); + continue; + } + other = host_create_from_string(remote, 500); + if (!other) + { + me->destroy(me); + continue; + } + if (other_host && !other->is_anyaddr(other) && + !other->ip_equals(other, other_host)) + { + me->destroy(me); + other->destroy(other); + continue; + } + ike_cfg = ike_cfg_create(certreq, force_encap, me, other); + /* TODO: read proposal from db */ + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + return ike_cfg; + } + return NULL; +} + +/** + * Query a IKE config by its id + */ +static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id) +{ + enumerator_t *e; + ike_cfg_t *ike_cfg = NULL; + + e = this->db->query(this->db, + "SELECT certreq, force_encap, local, remote " + "FROM ike_configs WHERE id = ?", + DB_INT, id, + DB_INT, DB_INT, DB_TEXT, DB_TEXT); + if (e) + { + ike_cfg = build_ike_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return ike_cfg; +} + +/** + * Query a peer config by its id + */ +static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id) +{ + enumerator_t *e; + peer_cfg_t *peer_cfg = NULL; + + e = this->db->query(this->db, + "SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, " + "auth_method, eap_type, eap_vendor, keyingtries, " + "rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, dpd_action, local_vip, remote_vip, " + "mediation, mediated_by, peer_id " + "FROM peer_configs WHERE id = ?", + DB_INT, id, + DB_INT, DB_INT, DB_TEXT, DB_TEXT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_TEXT); + if (e) + { + peer_cfg = build_peer_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return peer_cfg; +} + +/** + * build a peer configuration from a SQL query + */ +static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, + identification_t *me, identification_t *other) +{ + int id, ike_cfg, cert_policy, auth_method, eap_type, eap_vendor, + keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, + dpd_delay, dpd_action, mediation, mediated_by; + char *local_id, *remote_id, *local_vip, *remote_vip, *peer_id, *name; + + while (e->enumerate(e, &id, &name, &ike_cfg, &local_id, &remote_id, &cert_policy, + &auth_method, &eap_type, &eap_vendor, &keyingtries, + &rekeytime, &reauthtime, &jitter, &overtime, &mobike, + &dpd_delay, &dpd_action, &local_vip, &remote_vip, + &mediation, &mediated_by, &peer_id)) + { + ike_cfg_t *ike; + peer_cfg_t *peer_cfg, *mediated_cfg; + identification_t *my_id, *other_id, *peer; + host_t *my_vip, *other_vip; + + my_id = identification_create_from_string(local_id); + if (!my_id) + { + continue; + } + if (me && !me->matches(me, my_id)) + { + my_id->destroy(my_id); + continue; + } + other_id = identification_create_from_string(remote_id); + if (!other_id) + { + my_id->destroy(my_id); + continue; + } + if (other && !other->matches(other, other_id)) + { + other_id->destroy(other_id); + my_id->destroy(my_id); + continue; + } + ike = get_ike_cfg_by_id(this, ike_cfg); + mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL; + peer = peer_id ? identification_create_from_string(peer_id) : NULL; + my_vip = local_vip ? host_create_from_string(local_vip, 0) : NULL; + other_vip = remote_vip ? host_create_from_string(remote_vip, 0) : NULL; + + if (ike) + { + peer_cfg = peer_cfg_create( + name, 2, ike, my_id, other_id, cert_policy, + auth_method, eap_type, eap_vendor, keyingtries, + rekeytime, reauthtime, jitter, overtime, mobike, + dpd_delay, dpd_action, my_vip, other_vip, + mediation, mediated_cfg, peer); + add_child_cfgs(this, peer_cfg, id); + return peer_cfg; + } + DESTROY_IF(ike); + DESTROY_IF(mediated_cfg); + DESTROY_IF(peer); + DESTROY_IF(my_vip); + DESTROY_IF(other_vip); + DESTROY_IF(my_id); + DESTROY_IF(other_id); + } + return NULL; +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name) +{ + enumerator_t *e; + peer_cfg_t *peer_cfg = NULL; + + e = this->db->query(this->db, + "SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, " + "auth_method, eap_type, eap_vendor, keyingtries, " + "rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, dpd_action, local_vip, remote_vip, " + "mediation, mediated_by, peer_id " + "FROM peer_configs WHERE ike_version = ? AND name = ?", + DB_INT, 2, DB_TEXT, name, + DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_TEXT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_TEXT); + if (e) + { + peer_cfg = build_peer_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return peer_cfg; +} + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** reference to context */ + private_sql_config_t *this; + /** filtering own host */ + host_t *me; + /** filtering remote host */ + host_t *other; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated peer config */ + ike_cfg_t *current; +} ike_enumerator_t; + +/** + * Implementation of ike_enumerator_t.public.enumerate + */ +static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg) +{ + DESTROY_IF(this->current); + this->current = build_ike_cfg(this->this, this->inner, this->me, this->other); + if (this->current) + { + *cfg = this->current; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of ike_enumerator_t.public.destroy + */ +static void ike_enumerator_destroy(ike_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this, + host_t *me, host_t *other) +{ + ike_enumerator_t *e = malloc_thing(ike_enumerator_t); + + e->this = this; + e->me = me; + e->other = other; + e->current = NULL; + e->public.enumerate = (void*)ike_enumerator_enumerate; + e->public.destroy = (void*)ike_enumerator_destroy; + + e->inner = this->db->query(this->db, + "SELECT certreq, force_encap, local, remote " + "FROM ike_configs", + DB_INT, DB_INT, DB_TEXT, DB_TEXT); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** reference to context */ + private_sql_config_t *this; + /** filtering own identity */ + identification_t *me; + /** filtering remote identity */ + identification_t *other; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated peer config */ + peer_cfg_t *current; +} peer_enumerator_t; + +/** + * Implementation of peer_enumerator_t.public.enumerate + */ +static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +{ + DESTROY_IF(this->current); + this->current = build_peer_cfg(this->this, this->inner, this->me, this->other); + if (this->current) + { + *cfg = this->current; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of peer_enumerator_t.public.destroy + */ +static void peer_enumerator_destroy(peer_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this, + identification_t *me, + identification_t *other) +{ + peer_enumerator_t *e = malloc_thing(peer_enumerator_t); + + e->this = this; + e->me = me; + e->other = other; + e->current = NULL; + e->public.enumerate = (void*)peer_enumerator_enumerate; + e->public.destroy = (void*)peer_enumerator_destroy; + + /* TODO: only get configs whose IDs match exactly or contain wildcards */ + e->inner = this->db->query(this->db, + "SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, " + "auth_method, eap_type, eap_vendor, keyingtries, " + "rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, dpd_action, local_vip, remote_vip, " + "mediation, mediated_by, peer_id " + "FROM peer_configs WHERE ike_version = ? ", + DB_INT, 2, + DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_TEXT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_TEXT); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of sql_config_t.destroy. + */ +static void destroy(private_sql_config_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +sql_config_t *sql_config_create(database_t *db) +{ + private_sql_config_t *this = malloc_thing(private_sql_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.destroy = (void(*)(sql_config_t*))destroy; + + this->db = db; + + return &this->public; +} + |