diff options
Diffstat (limited to 'src/charon/config/backends')
-rw-r--r-- | src/charon/config/backends/backend.h | 9 | ||||
-rw-r--r-- | src/charon/config/backends/local_backend.c | 48 | ||||
-rw-r--r-- | src/charon/config/backends/sqlite_backend.c | 308 | ||||
-rw-r--r-- | src/charon/config/backends/sqlite_backend.h | 58 |
4 files changed, 423 insertions, 0 deletions
diff --git a/src/charon/config/backends/backend.h b/src/charon/config/backends/backend.h index acab660b6..592d1dd4c 100644 --- a/src/charon/config/backends/backend.h +++ b/src/charon/config/backends/backend.h @@ -71,6 +71,15 @@ struct backend_t { ca_info_t *other_ca_info); /** + * @brief Get a peer_cfg identified by it's name, or a name of its child. + * + * @param this calling object + * @param name + * @return matching peer_config, or NULL if none found + */ + peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name); + + /** * @brief Check if a backend is writable and implements writable_backend_t. * * @param this calling object diff --git a/src/charon/config/backends/local_backend.c b/src/charon/config/backends/local_backend.c index 2e80cc870..e04c72ac1 100644 --- a/src/charon/config/backends/local_backend.c +++ b/src/charon/config/backends/local_backend.c @@ -146,6 +146,13 @@ static peer_cfg_t *get_peer_cfg(private_local_backend_t *this, int prio = (wc1 + wc2) * (MAX_CA_PATH_LEN + 1); int pathlen = 0; identification_t *other_candidate_ca = current->get_other_ca(current); + linked_list_t *groups = current->get_groups(current); + + /* is a group membership required? */ + if (groups->get_count(groups) > 0) + { + DBG1(DBG_CFG, " group membership required"); + } /* are there any ca constraints? */ if (other_candidate_ca->get_type(other_candidate_ca) != ID_ANY) @@ -218,6 +225,46 @@ static peer_cfg_t *get_peer_cfg(private_local_backend_t *this, } /** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_local_backend_t *this, char *name) +{ + iterator_t *i1, *i2; + peer_cfg_t *current, *found = NULL; + child_cfg_t *child; + + i1 = this->cfgs->create_iterator(this->cfgs, TRUE); + while (i1->iterate(i1, (void**)¤t)) + { + /* compare peer_cfgs name first */ + if (streq(current->get_name(current), name)) + { + found = current; + found->get_ref(found); + break; + } + /* compare all child_cfg names otherwise */ + i2 = current->create_child_cfg_iterator(current); + while (i2->iterate(i2, (void**)&child)) + { + if (streq(child->get_name(child), name)) + { + found = current; + found->get_ref(found); + break; + } + } + i2->destroy(i2); + if (found) + { + break; + } + } + i1->destroy(i1); + return found; +} + +/** * Implementation of backend_t.is_writable. */ static bool is_writeable(private_local_backend_t *this) @@ -261,6 +308,7 @@ backend_t *backend_create(void) this->public.backend.backend.get_ike_cfg = (ike_cfg_t* (*)(backend_t*, host_t*, host_t*))get_ike_cfg; this->public.backend.backend.get_peer_cfg = (peer_cfg_t* (*)(backend_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; + this->public.backend.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; this->public.backend.backend.is_writeable = (bool(*) (backend_t*))is_writeable; this->public.backend.backend.destroy = (void (*)(backend_t*))destroy; this->public.backend.create_iterator = (iterator_t* (*)(writeable_backend_t*))create_iterator; diff --git a/src/charon/config/backends/sqlite_backend.c b/src/charon/config/backends/sqlite_backend.c new file mode 100644 index 000000000..33093a735 --- /dev/null +++ b/src/charon/config/backends/sqlite_backend.c @@ -0,0 +1,308 @@ +/** + * @file sqlite_backend.c + * + * @brief Implementation of sqlite_backend_t. + * + */ + +/* + * Copyright (C) 2006 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. + */ + +#include <string.h> +#include <sqlite3.h> + +#include "sqlite_backend.h" + +#include <daemon.h> + + +typedef struct private_sqlite_backend_t private_sqlite_backend_t; + +/** + * Private data of an sqlite_backend_t object + */ +struct private_sqlite_backend_t { + + /** + * Public part + */ + sqlite_backend_t public; + + /** + * SQLite database handle + */ + sqlite3 *db; +}; + +/** + * implements backen_t.get_ike_cfg. + */ +static ike_cfg_t *get_ike_cfg(private_sqlite_backend_t *this, + host_t *my_host, host_t *other_host) +{ + return NULL; +} + +/** + * add TS with child "id" to "child_cfg" + */ +static void add_ts(private_sqlite_backend_t *this, child_cfg_t *child_cfg, int id) +{ + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(this->db, + "SELECT type, protocol, start_addr, end_addr, start_port, end_port, kind " + "FROM traffic_selectors, child_config_traffic_selector " + "ON traffic_selectors.oid = child_config_traffic_selector.traffic_selector " + "WHERE child_config_traffic_selector.child_cfg = ?;", + -1, &stmt, NULL) == SQLITE_OK && + sqlite3_bind_int(stmt, 1, id) == SQLITE_OK) + { + while (sqlite3_step(stmt) == SQLITE_ROW) + { + traffic_selector_t *ts; + bool local = FALSE; + enum { + TS_LOCAL = 0, + TS_REMOTE = 1, + TS_LOCAL_DYNAMIC = 2, + TS_REMOTE_DYNAMIC = 3, + } kind; + + kind = sqlite3_column_int(stmt, 6); + switch (kind) + { + case TS_LOCAL: + local = TRUE; + /* FALL */ + case TS_REMOTE: + ts = traffic_selector_create_from_string( + sqlite3_column_int(stmt, 1), /* protocol */ + sqlite3_column_int(stmt, 0), /* type */ + (char*)sqlite3_column_text(stmt, 2), /* from addr */ + sqlite3_column_int(stmt, 4), /* from port */ + (char*)sqlite3_column_text(stmt, 3), /* to addr */ + sqlite3_column_int(stmt, 5)); /* to port */ + break; + case TS_LOCAL_DYNAMIC: + local = TRUE; + /* FALL */ + case TS_REMOTE_DYNAMIC: + ts = traffic_selector_create_dynamic( + sqlite3_column_int(stmt, 1), /* protocol */ + sqlite3_column_int(stmt, 0), /* type */ + sqlite3_column_int(stmt, 4), /* from port */ + sqlite3_column_int(stmt, 5)); /* to port */ + break; + default: + continue; + } + if (ts) + { + child_cfg->add_traffic_selector(child_cfg, local, ts); + } + } + } + sqlite3_finalize(stmt); +} + +/** + * add childrens belonging to config with "id" to "peer_cfg" + */ +static void add_children(private_sqlite_backend_t *this, peer_cfg_t *peer_cfg, int id) +{ + sqlite3_stmt *stmt; + child_cfg_t *child_cfg; + + if (sqlite3_prepare_v2(this->db, + "SELECT child_configs.oid, name, updown, hostaccess, mode, " + "lifetime, rekeytime, jitter " + "FROM child_configs, peer_config_child_config " + "ON child_configs.oid = peer_config_child_config.child_cfg " + "WHERE peer_config_child_config.peer_cfg = ?;", + -1, &stmt, NULL) == SQLITE_OK && + sqlite3_bind_int(stmt, 1, id) == SQLITE_OK) + { + while (sqlite3_step(stmt) == SQLITE_ROW) + { + child_cfg = child_cfg_create( + (char*)sqlite3_column_text(stmt, 1), /* name */ + sqlite3_column_int(stmt, 5), /* lifetime */ + sqlite3_column_int(stmt, 6), /* rekeytime */ + sqlite3_column_int(stmt, 7), /* jitter */ + (char*)sqlite3_column_text(stmt, 2), /* updown */ + sqlite3_column_int(stmt, 3), /* hostaccess */ + sqlite3_column_int(stmt, 4)); /* mode */ + add_ts(this, child_cfg, sqlite3_column_int(stmt, 0)); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + } + } + sqlite3_finalize(stmt); +} + +/** + * processing function for get_peer_cfg and get_peer_cfg_by_name + */ +static peer_cfg_t *process_peer_cfg_row(private_sqlite_backend_t *this, + sqlite3_stmt *stmt) +{ + host_t *local_host, *remote_host, *local_vip = NULL, *remote_vip = NULL; + identification_t *local_id, *remote_id; + peer_cfg_t *peer_cfg; + ike_cfg_t *ike_cfg; + + local_host = host_create_from_string((char*)sqlite3_column_text(stmt, 17), IKEV2_UDP_PORT); + remote_host = host_create_from_string((char*)sqlite3_column_text(stmt, 18), IKEV2_UDP_PORT); + if (sqlite3_column_text(stmt, 15)) + { + local_vip = host_create_from_string((char*)sqlite3_column_text(stmt, 15), 0); + } + if (sqlite3_column_text(stmt, 16)) + { + remote_vip = host_create_from_string((char*)sqlite3_column_text(stmt, 16), 0); + } + local_id = identification_create_from_string((char*)sqlite3_column_text(stmt, 2)); + remote_id = identification_create_from_string((char*)sqlite3_column_text(stmt, 3)); + if (local_host && remote_host && local_id && remote_id) + { + ike_cfg = ike_cfg_create(sqlite3_column_int(stmt, 19), FALSE, + local_host, remote_host); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + peer_cfg = peer_cfg_create( + (char*)sqlite3_column_text(stmt, 1), /* name */ + 2, ike_cfg, local_id, remote_id, NULL, NULL, linked_list_create(), + sqlite3_column_int(stmt, 4), /* cert_policy */ + sqlite3_column_int(stmt, 5), /* auth_method */ + sqlite3_column_int(stmt, 6), /* eap_type */ + sqlite3_column_int(stmt, 7), /* keyingtries */ + sqlite3_column_int(stmt, 8), /* lifetime */ + sqlite3_column_int(stmt, 9), /* rekeytime */ + sqlite3_column_int(stmt, 10), /* jitter */ + sqlite3_column_int(stmt, 13), /* reauth */ + sqlite3_column_int(stmt, 14), /* mobike */ + sqlite3_column_int(stmt, 11), /* dpd_delay */ + sqlite3_column_int(stmt, 12), /* dpd_action */ + local_vip, remote_vip, FALSE, NULL, NULL); + add_children(this, peer_cfg, sqlite3_column_int(stmt, 0)); + return peer_cfg; + } + + DESTROY_IF(local_host); + DESTROY_IF(remote_host); + DESTROY_IF(local_id); + DESTROY_IF(remote_id); + DESTROY_IF(local_vip); + DESTROY_IF(remote_vip); + return NULL; +} + +/** + * implements backend_t.get_peer_cfg. + */ +static peer_cfg_t *get_peer_cfg(private_sqlite_backend_t *this, + identification_t *my_id, identification_t *other_id, + ca_info_t *other_ca_info) +{ + sqlite3_stmt *stmt; + char local[256], remote[256]; + peer_cfg_t *peer_cfg = NULL; + + snprintf(local, sizeof(local), "%D", my_id); + snprintf(remote, sizeof(remote), "%D", other_id); + + if (sqlite3_prepare_v2(this->db, + "SELECT peer_configs.oid, name, local_id, remote_id, cert_policy, " + "auth_method, eap_type, keyingtries, lifetime, rekeytime, jitter, " + "dpd_delay, dpd_action, reauth, mobike, local_vip, remote_vip, " + "local, remote, certreq " + "FROM peer_configs, ike_configs " + "ON peer_configs.ike_cfg = ike_configs.oid " + "WHERE local_id = ? and remote_id = ?;", -1, &stmt, NULL) == SQLITE_OK && + sqlite3_bind_text(stmt, 1, local, -1, SQLITE_STATIC) == SQLITE_OK && + sqlite3_bind_text(stmt, 2, remote, -1, SQLITE_STATIC) == SQLITE_OK && + sqlite3_step(stmt) == SQLITE_ROW) + { + peer_cfg = process_peer_cfg_row(this, stmt); + } + sqlite3_finalize(stmt); + return peer_cfg; +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_sqlite_backend_t *this, char *name) +{ + sqlite3_stmt *stmt; + peer_cfg_t *peer_cfg = NULL; + + if (sqlite3_prepare_v2(this->db, + "SELECT peer_configs.oid, name, local_id, remote_id, cert_policy, " + "auth_method, eap_type, keyingtries, lifetime, rekeytime, jitter, " + "dpd_delay, dpd_action, reauth, mobike, local_vip, remote_vip, " + "local, remote, certreq " + "FROM peer_configs, ike_configs " + "ON peer_configs.ike_cfg = ike_configs.oid " + "WHERE name = ? ;", -1, &stmt, NULL) == SQLITE_OK && + sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC) == SQLITE_OK && + sqlite3_step(stmt) == SQLITE_ROW) + { + peer_cfg = process_peer_cfg_row(this, stmt); + } + sqlite3_finalize(stmt); + return peer_cfg; +} + +/** + * Implementation of backend_t.is_writable. + */ +static bool is_writeable(private_sqlite_backend_t *this) +{ + return FALSE; +} + +/** + * Implementation of backend_t.destroy. + */ +static void destroy(private_sqlite_backend_t *this) +{ + sqlite3_close(this->db); + free(this); +} + +/** + * Described in header. + */ +backend_t *backend_create(void) +{ + private_sqlite_backend_t *this = malloc_thing(private_sqlite_backend_t); + + this->public.backend.get_ike_cfg = (ike_cfg_t* (*)(backend_t*, host_t*, host_t*))get_ike_cfg; + this->public.backend.get_peer_cfg = (peer_cfg_t* (*)(backend_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.backend.is_writeable = (bool(*) (backend_t*))is_writeable; + this->public.backend.destroy = (void (*)(backend_t*))destroy; + + if (sqlite3_open(IPSEC_DIR "/manager.db", &this->db) != SQLITE_OK) + { + DBG1(DBG_CFG, "opening SQLite database '" IPSEC_DIR "/manager.db' failed."); + destroy(this); + return NULL; + } + + return &this->public.backend; +} + diff --git a/src/charon/config/backends/sqlite_backend.h b/src/charon/config/backends/sqlite_backend.h new file mode 100644 index 000000000..4bc146583 --- /dev/null +++ b/src/charon/config/backends/sqlite_backend.h @@ -0,0 +1,58 @@ +/** + * @file sqlite_backend.h + * + * @brief Interface of sqlite_backend_t. + * + */ + +/* + * Copyright (C) 2007 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. + */ + +#ifndef SQLITE_BACKEND_H_ +#define SQLITE_BACKEND_H_ + +typedef struct sqlite_backend_t sqlite_backend_t; + +#include <library.h> + +#include "backend.h" + +/** + * @brief An SQLite based configuration backend. + * + * @b Constructors: + * - sqlite_backend_create() + * + * @ingroup backends + */ +struct sqlite_backend_t { + + /** + * Implements backend_t interface + */ + backend_t backend; +}; + +/** + * @brief Create a backend_t instance implemented as sqlite backend. + * + * @return backend instance + * + * @ingroup backends + */ +backend_t *backend_create(void); + +#endif /* SQLITE_BACKEND_H_ */ + |