diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-09 21:02:41 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-09 21:02:41 +0000 |
commit | db67c87db3c9089ea8d2e14f617bf3d9e2af261f (patch) | |
tree | 665c0caea83d34c11c1517c4c57137bb58cba6fb /src/charon/config | |
parent | 1c088a8b6237ec67f63c23f97a0f2dc4e99af869 (diff) | |
download | vyos-strongswan-db67c87db3c9089ea8d2e14f617bf3d9e2af261f.tar.gz vyos-strongswan-db67c87db3c9089ea8d2e14f617bf3d9e2af261f.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.2.4)
Diffstat (limited to 'src/charon/config')
24 files changed, 1820 insertions, 3569 deletions
diff --git a/src/charon/config/attributes/attribute_manager.c b/src/charon/config/attributes/attribute_manager.c new file mode 100644 index 000000000..0ec84c7be --- /dev/null +++ b/src/charon/config/attributes/attribute_manager.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 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 "attribute_manager.h" + +#include <utils/linked_list.h> +#include <utils/mutex.h> + +typedef struct private_attribute_manager_t private_attribute_manager_t; + +/** + * private data of attribute_manager + */ +struct private_attribute_manager_t { + + /** + * public functions + */ + attribute_manager_t public; + + /** + * list of registered providers + */ + linked_list_t *providers; + + /** + * mutex to lock provider list + */ + mutex_t *mutex; +}; + +/** + * Implementation of attribute_manager_t.acquire_address. + */ +static host_t* acquire_address(private_attribute_manager_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + host_t *host = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + host = current->acquire_address(current, pool, id, auth, requested); + if (host) + { + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + return host; +} + +/** + * Implementation of attribute_manager_t.release_address. + */ +static void release_address(private_attribute_manager_t *this, + char *pool, host_t *address) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + + this->mutex->lock(this->mutex); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->release_address(current, pool, address)) + { + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.add_provider. + */ +static void add_provider(private_attribute_manager_t *this, + attribute_provider_t *provider) +{ + this->mutex->lock(this->mutex); + this->providers->insert_last(this->providers, provider); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.remove_provider. + */ +static void remove_provider(private_attribute_manager_t *this, + attribute_provider_t *provider) +{ + this->mutex->lock(this->mutex); + this->providers->remove(this->providers, provider, NULL); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.destroy + */ +static void destroy(private_attribute_manager_t *this) +{ + this->providers->destroy(this->providers); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +attribute_manager_t *attribute_manager_create() +{ + private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t); + + this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,auth_info_t*,host_t*))acquire_address; + this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*))release_address; + this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider; + this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider; + this->public.destroy = (void(*)(attribute_manager_t*))destroy; + + this->providers = linked_list_create(); + this->mutex = mutex_create(MUTEX_DEFAULT); + + return &this->public; +} + diff --git a/src/charon/config/attributes/attribute_manager.h b/src/charon/config/attributes/attribute_manager.h new file mode 100644 index 000000000..540e054fd --- /dev/null +++ b/src/charon/config/attributes/attribute_manager.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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$ + */ + +/** + * @defgroup attribute_manager attribute_manager + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_MANAGER_H_ +#define ATTRIBUTE_MANAGER_H_ + +#include <config/attributes/attribute_provider.h> + +typedef struct attribute_manager_t attribute_manager_t; + +/** + * Provide configuration attributes to include in CFG Payloads. + */ +struct attribute_manager_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pool pool name to acquire address from + * @param id peer identity to get address for + * @param auth authorization infos of peer + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_manager_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested); + + /** + * Release a previously acquired address. + * + * @param pool pool name from which the address was acquired + * @param address address to release + */ + void (*release_address)(attribute_manager_t *this, + char *pool, host_t *address); + + /** + * Register an attribute provider to the manager. + * + * @param provider attribute provider to register + */ + void (*add_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + /** + * Unregister an attribute provider from the manager. + * + * @param provider attribute provider to unregister + */ + void (*remove_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + /** + * Destroy a attribute_manager instance. + */ + void (*destroy)(attribute_manager_t *this); +}; + +/** + * Create a attribute_manager instance. + */ +attribute_manager_t *attribute_manager_create(); + +#endif /* ATTRIBUTE_MANAGER_H_ @}*/ diff --git a/src/charon/config/attributes/attribute_provider.h b/src/charon/config/attributes/attribute_provider.h new file mode 100644 index 000000000..1712bd188 --- /dev/null +++ b/src/charon/config/attributes/attribute_provider.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 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$ + */ + +/** + * @defgroup attribute_provider attribute_provider + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_PROVIDER_H_ +#define ATTRIBUTE_PROVIDER_H_ + +#include <library.h> +#include <utils/host.h> +#include <credentials/auth_info.h> + +typedef struct attribute_provider_t attribute_provider_t; + +/** + * Interface to provide attributes to peers through attribute manager. + */ +struct attribute_provider_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pool name of the pool to acquire address from + * @param id peer ID + * @param auth authorization infos + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_provider_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested); + /** + * Release a previously acquired address. + * + * @param pool name of the pool this address was acquired from + * @param address address to release + * @return TRUE if the address has been released by the provider + */ + bool (*release_address)(attribute_provider_t *this, + char *pool, host_t *address); +}; + +#endif /* ATTRIBUTE_PROVIDER_H_ @}*/ diff --git a/src/charon/config/backend.h b/src/charon/config/backend.h new file mode 100644 index 000000000..ec2c481bd --- /dev/null +++ b/src/charon/config/backend.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007-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: backend.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup backend backend + * @{ @ingroup config + */ + +#ifndef BACKEND_H_ +#define BACKEND_H_ + +typedef struct backend_t backend_t; + +#include <library.h> +#include <config/ike_cfg.h> +#include <config/peer_cfg.h> +#include <credentials/auth_info.h> +#include <utils/linked_list.h> + +/** + * The interface for a configuration backend. + * + * A configuration backend is loaded into the backend_manager. It does the actual + * configuration lookup for the method it implements. See backend_manager_t for + * more information. + */ +struct backend_t { + + /** + * Create an enumerator over all IKE configs matching two hosts. + * + * Hosts may be NULL to get all. + * + * @param me address of local host + * @param other address of remote host + * @return enumerator over ike_cfg_t's + */ + enumerator_t* (*create_ike_cfg_enumerator)(backend_t *this, + host_t *me, host_t *other); + /** + * Create an enumerator over all Peer configs matching two IDs. + * + * IDs may be NULL to get all. + * + * @param me identity of ourself + * @param other identity of remote host + * @return enumerator over peer_cfg_t + */ + enumerator_t* (*create_peer_cfg_enumerator)(backend_t *this, + identification_t *me, + identification_t *other); + /** + * Get a peer_cfg identified by it's name, or a name of its child. + * + * @param name name of peer/child cfg + * @return matching peer_config, or NULL if none found + */ + peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name); +}; + +#endif /* BACKEND_H_ @} */ diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c index b2104acea..d77c05fd7 100644 --- a/src/charon/config/backend_manager.c +++ b/src/charon/config/backend_manager.c @@ -1,10 +1,3 @@ -/** - * @file backend_manager.c - * - * @brief Implementation of backend_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,18 +11,18 @@ * 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: backend_manager.c 4044 2008-06-06 15:05:54Z martin $ */ #include "backend_manager.h" #include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <dlfcn.h> +#include <pthread.h> #include <daemon.h> #include <utils/linked_list.h> -#include <config/backends/writeable_backend.h> +#include <utils/mutex.h> typedef struct private_backend_manager_t private_backend_manager_t; @@ -50,164 +43,268 @@ struct private_backend_manager_t { linked_list_t *backends; /** - * Additional list of writable backends. + * locking mutex */ - linked_list_t *writeable; - - /** - * List of dlopen() handles we used to open backends - */ - linked_list_t *handles; + mutex_t *mutex; }; /** - * implements backend_manager_t.get_ike_cfg. + * data to pass nested IKE enumerator */ -static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, - host_t *my_host, host_t *other_host) +typedef struct { + private_backend_manager_t *this; + host_t *me; + host_t *other; +} ike_data_t; + +/** + * data to pass nested peer enumerator + */ +typedef struct { + private_backend_manager_t *this; + identification_t *me; + identification_t *other; +} peer_data_t; + +/** + * destroy IKE enumerator data and unlock list + */ +static void ike_enum_destroy(ike_data_t *data) { - backend_t *backend; - ike_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_ike_cfg(backend, my_host, other_host); - } - iterator->destroy(iterator); - return config; + data->this->mutex->unlock(data->this->mutex); + free(data); } /** - * implements backend_manager_t.get_peer_cfg. - */ -static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info) + * destroy PEER enumerator data and unlock list + */ +static void peer_enum_destroy(peer_data_t *data) { - backend_t *backend; - peer_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_peer_cfg(backend, my_id, other_id, other_ca_info); - } - iterator->destroy(iterator); - return config; + data->this->mutex->unlock(data->this->mutex); + free(data); } /** - * implements backend_manager_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name) + * inner enumerator constructor for IKE cfgs + */ +static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data) { - backend_t *backend; - peer_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_peer_cfg_by_name(backend, name); - } - iterator->destroy(iterator); - return config; + return backend->create_ike_cfg_enumerator(backend, data->me, data->other); } /** - * implements backend_manager_t.add_peer_cfg. - */ -static void add_peer_cfg(private_backend_manager_t *this, peer_cfg_t *config) + * inner enumerator constructor for Peer cfgs + */ +static enumerator_t *peer_enum_create(backend_t *backend, peer_data_t *data) { - writeable_backend_t *backend; - - if (this->writeable->get_first(this->writeable, (void**)&backend) == SUCCESS) - { - backend->add_cfg(backend, config); - } + return backend->create_peer_cfg_enumerator(backend, data->me, data->other); } - /** - * implements backend_manager_t.create_iterator. - */ -static iterator_t* create_iterator(private_backend_manager_t *this) + * inner enumerator constructor for all Peer cfgs + */ +static enumerator_t *peer_enum_create_all(backend_t *backend) { - writeable_backend_t *backend; - - if (this->writeable->get_first(this->writeable, (void**)&backend) == SUCCESS) - { - return backend->create_iterator(backend); - } - /* give out an empty iterator if we have no writable backend*/ - return this->writeable->create_iterator(this->writeable, TRUE); + return backend->create_peer_cfg_enumerator(backend, NULL, NULL); } /** - * load the configuration backend modules + * implements backend_manager_t.get_ike_cfg. */ -static void load_backends(private_backend_manager_t *this) +static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, + host_t *me, host_t *other) { - struct dirent* entry; - DIR* dir; - - dir = opendir(IPSEC_BACKENDDIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening backend modules directory "IPSEC_BACKENDDIR); - return; - } + ike_cfg_t *current, *found = NULL; + enumerator_t *enumerator; + host_t *my_candidate, *other_candidate; + ike_data_t *data; + enum { + MATCH_NONE = 0x00, + MATCH_ANY = 0x01, + MATCH_ME = 0x04, + MATCH_OTHER = 0x08, + } prio, best = MATCH_ANY; - DBG1(DBG_CFG, "loading backend modules from '"IPSEC_BACKENDDIR"'"); - - while ((entry = readdir(dir)) != NULL) + data = malloc_thing(ike_data_t); + data->this = this; + data->me = me; + data->other = other; + + DBG2(DBG_CFG, "looking for a config for %H...%H", me, other); + + this->mutex->lock(this->mutex); + enumerator = enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)ike_enum_create, data, (void*)ike_enum_destroy); + while (enumerator->enumerate(enumerator, (void**)¤t)) { - char file[256]; - backend_t *backend; - backend_constructor_t constructor; - void *handle; - char *ending; - - snprintf(file, sizeof(file), IPSEC_BACKENDDIR"/%s", entry->d_name); + prio = MATCH_NONE; - ending = entry->d_name + strlen(entry->d_name) - 3; - if (ending <= entry->d_name || !streq(ending, ".so")) + my_candidate = host_create_from_dns(current->get_my_addr(current), + me->get_family(me), 0); + if (!my_candidate) { - /* skip anything which does not look like a library */ - DBG2(DBG_CFG, " skipping %s, doesn't look like a library", - entry->d_name); continue; } - /* try to load the library */ - handle = dlopen(file, RTLD_LAZY); - if (handle == NULL) + if (my_candidate->ip_equals(my_candidate, me)) { - DBG1(DBG_CFG, " opening backend module %s failed: %s", - entry->d_name, dlerror()); - continue; + prio += MATCH_ME; } - constructor = dlsym(handle, "backend_create"); - if (constructor == NULL) + else if (my_candidate->is_anyaddr(my_candidate)) { - DBG1(DBG_CFG, " backend module %s has no backend_create() " - "function, skipped", entry->d_name); - dlclose(handle); - continue; + prio += MATCH_ANY; } + my_candidate->destroy(my_candidate); - backend = constructor(); - if (backend == NULL) + other_candidate = host_create_from_dns(current->get_other_addr(current), + other->get_family(other), 0); + if (!other_candidate) { - DBG1(DBG_CFG, " unable to create instance of backend " - "module %s, skipped", entry->d_name); - dlclose(handle); continue; } - DBG1(DBG_CFG, " loaded backend module successfully from %s", entry->d_name); - this->backends->insert_last(this->backends, backend); - if (backend->is_writeable(backend)) + if (other_candidate->ip_equals(other_candidate, other)) + { + prio += MATCH_OTHER; + } + else if (other_candidate->is_anyaddr(other_candidate)) + { + prio += MATCH_ANY; + } + other_candidate->destroy(other_candidate); + + DBG2(DBG_CFG, " candidate: %s...%s, prio %d", + current->get_my_addr(current), current->get_other_addr(current), + prio); + + /* we require at least two MATCH_ANY */ + if (prio > best) { - this->writeable->insert_last(this->writeable, backend); + best = prio; + DESTROY_IF(found); + found = current; + found->get_ref(found); } - this->handles->insert_last(this->handles, handle); } - closedir(dir); + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return found; +} + + +static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this) +{ + this->mutex->lock(this->mutex); + return enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)peer_enum_create_all, this->mutex, + (void*)this->mutex->unlock); +} + +/** + * implements backend_manager_t.get_peer_cfg. + */ +static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, + identification_t *me, identification_t *other, + auth_info_t *auth) +{ + peer_cfg_t *current, *found = NULL; + enumerator_t *enumerator; + identification_t *my_candidate, *other_candidate; + id_match_t best = ID_MATCH_NONE; + peer_data_t *data; + + DBG2(DBG_CFG, "looking for a config for %D...%D", me, other); + + data = malloc_thing(peer_data_t); + data->this = this; + data->me = me; + data->other = other; + + this->mutex->lock(this->mutex); + enumerator = enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)peer_enum_create, data, (void*)peer_enum_destroy); + while (enumerator->enumerate(enumerator, ¤t)) + { + id_match_t m1, m2, sum; + + my_candidate = current->get_my_id(current); + other_candidate = current->get_other_id(current); + + /* own ID may have wildcards in both, config and request (missing IDr) */ + m1 = my_candidate->matches(my_candidate, me); + if (!m1) + { + m1 = me->matches(me, my_candidate); + } + m2 = other->matches(other, other_candidate); + sum = m1 + m2; + + if (m1 && m2) + { + if (auth->complies(auth, current->get_auth(current))) + { + DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d", + current->get_name(current), my_candidate, + other_candidate, sum); + if (sum > best) + { + DESTROY_IF(found); + found = current; + found->get_ref(found); + best = sum; + } + } + } + } + if (found) + { + DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d", + found->get_name(found), found->get_my_id(found), + found->get_other_id(found), best); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return found; +} + +/** + * implements backend_manager_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name) +{ + backend_t *backend; + peer_cfg_t *config = NULL; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->backends->create_enumerator(this->backends); + while (config == NULL && enumerator->enumerate(enumerator, (void**)&backend)) + { + config = backend->get_peer_cfg_by_name(backend, name); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return config; +} + +/** + * Implementation of backend_manager_t.remove_backend. + */ +static void remove_backend(private_backend_manager_t *this, backend_t *backend) +{ + this->mutex->lock(this->mutex); + this->backends->remove(this->backends, backend, NULL); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of backend_manager_t.add_backend. + */ +static void add_backend(private_backend_manager_t *this, backend_t *backend) +{ + this->mutex->lock(this->mutex); + this->backends->insert_last(this->backends, backend); + this->mutex->unlock(this->mutex); } /** @@ -215,9 +312,8 @@ static void load_backends(private_backend_manager_t *this) */ static void destroy(private_backend_manager_t *this) { - this->backends->destroy_offset(this->backends, offsetof(backend_t, destroy)); - this->writeable->destroy(this->writeable); - this->handles->destroy_function(this->handles, (void*)dlclose); + this->backends->destroy(this->backends); + this->mutex->destroy(this->mutex); free(this); } @@ -229,17 +325,15 @@ backend_manager_t *backend_manager_create() private_backend_manager_t *this = malloc_thing(private_backend_manager_t); this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg; - this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; + this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg; this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name; - this->public.add_peer_cfg = (void (*)(backend_manager_t*,peer_cfg_t*))add_peer_cfg; - this->public.create_iterator = (iterator_t* (*)(backend_manager_t*))create_iterator; + this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*))create_peer_cfg_enumerator; + this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend; + this->public.remove_backend = (void(*)(backend_manager_t*, backend_t *backend))remove_backend; this->public.destroy = (void (*)(backend_manager_t*))destroy; this->backends = linked_list_create(); - this->writeable = linked_list_create(); - this->handles = linked_list_create(); - - load_backends(this); + this->mutex = mutex_create(MUTEX_RECURSIVE); return &this->public; } diff --git a/src/charon/config/backend_manager.h b/src/charon/config/backend_manager.h index 7ca6d660e..6400bd7fd 100644 --- a/src/charon/config/backend_manager.h +++ b/src/charon/config/backend_manager.h @@ -1,10 +1,3 @@ -/** - * @file backend_manager.h - * - * @brief Interface backend_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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: backend_manager.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup backend_manager backend_manager + * @{ @ingroup config */ #ifndef BACKEND_MANAGER_H_ @@ -30,20 +30,15 @@ typedef struct backend_manager_t backend_manager_t; #include <utils/identification.h> #include <config/ike_cfg.h> #include <config/peer_cfg.h> -#include <config/backends/backend.h> +#include <config/backend.h> /** - * @brief A loader and multiplexer to use multiple backends. + * A loader and multiplexer to use multiple backends. * * Charon allows the use of multiple configuration backends simultaneously. To * access all this backends by a single call, this class wraps multiple - * backends behind a single object. It is also responsible for loading - * the backend modules and cleaning them up. - * A backend may be writeable or not. All backends implement the backend_t - * interface, those who are writeable additionally implement the - * writeable_backend_t interface. Adding configs to the backend_manager will - * be redirected to the first writeable backend. + * backends behind a single object. * @verbatim +---------+ +-----------+ +--------------+ | @@ -55,18 +50,12 @@ typedef struct backend_manager_t backend_manager_t; +---------+ +-----------+ | @endverbatim - * - * @b Constructors: - * - backend_manager_create() - * - * @ingroup config */ struct backend_manager_t { /** - * @brief Get an ike_config identified by two hosts. + * Get an ike_config identified by two hosts. * - * @param this calling object * @param my_host address of own host * @param other_host address of remote host * @return matching ike_config, or NULL if none found @@ -75,59 +64,57 @@ struct backend_manager_t { host_t *my_host, host_t *other_host); /** - * @brief Get a peer_config identified by two IDs and the peer's certificate issuer + * Get a peer_config identified by two IDs and authorization info. * - * @param this calling object * @param my_id own ID * @param other_id peer ID - * @param other_ca_info info record on issuer of peer certificate + * @param auth_info authorization info * @return matching peer_config, or NULL if none found */ - peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info); + peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, identification_t *my_id, + identification_t *other_id, auth_info_t *auth); /** - * @brief Get a peer_config identified by it's name. + * Get a peer_config identified by it's name. * - * @param this calling object * @param name name of the peer_config * @return matching peer_config, or NULL if none found */ peer_cfg_t* (*get_peer_cfg_by_name)(backend_manager_t *this, char *name); /** - * @brief Add a peer_config to the first found writable backend. + * Create an enumerator over all peer configs. * - * @param this calling object - * @param config peer_config to add to the backend + * @return enumerator over peer configs */ - void (*add_peer_cfg)(backend_manager_t *this, peer_cfg_t *config); + enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this); /** - * @brief Create an iterator over all peer configs of the writable backend. + * Register a backend on the manager. * - * @param this calling object - * @return iterator over peer configs + * @param backend backend to register */ - iterator_t* (*create_iterator)(backend_manager_t *this); + void (*add_backend)(backend_manager_t *this, backend_t *backend); /** - * @brief Destroys a backend_manager_t object. + * Unregister a backend. * - * @param this calling object + * @param backend backend to unregister + */ + void (*remove_backend)(backend_manager_t *this, backend_t *backend); + + /** + * Destroys a backend_manager_t object. */ void (*destroy) (backend_manager_t *this); }; /** - * @brief Creates a new instance of the manager and loads all backends. + * Create an instance of the backend manager * * @return backend_manager instance - * - * @ingroup config */ backend_manager_t* backend_manager_create(void); -#endif /*BACKEND_MANAGER_H_*/ +#endif /*BACKEND_MANAGER_H_ @} */ diff --git a/src/charon/config/backends/backend.h b/src/charon/config/backends/backend.h deleted file mode 100644 index 592d1dd4c..000000000 --- a/src/charon/config/backends/backend.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file backend.h - * - * @brief Interface 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 BACKEND_H_ -#define BACKEND_H_ - -typedef struct backend_t backend_t; - -#include <library.h> -#include <config/ike_cfg.h> -#include <config/peer_cfg.h> -#include <utils/linked_list.h> - -/** - * @brief The interface for a configuration backend. - * - * A configuration backend is loaded by the backend_manager. It does the actual - * configuration lookup for the method it implements. See backend_manager_t for - * more information. - * - * @b Constructors: - * - implementations constructors - * - * @ingroup backends - */ -struct backend_t { - - /** - * @brief Get an ike_cfg identified by two hosts. - * - * @param this calling object - * @param my_host address of own host - * @param other_host address of remote host - * @return matching ike_config, or NULL if none found - */ - ike_cfg_t *(*get_ike_cfg)(backend_t *this, - host_t *my_host, host_t *other_host); - - /** - * @brief Get a peer_cfg identified by two IDs. - * - * Select a config based on the two IDs and the other's certificate issuer - * - * @param this calling object - * @param my_id own ID - * @param other_id peer ID - * @param other_ca_info info record on issuer of peer certificate - * @return matching peer_config, or NULL if none found - */ - peer_cfg_t *(*get_peer_cfg)(backend_t *this, - identification_t *my_id, identification_t *other_id, - 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 - * @return TRUE if backend implements writable_backend_t. - */ - bool (*is_writeable)(backend_t *this); - - /** - * @brief Destroy a backend. - * - * @param this calling object - */ - void (*destroy)(backend_t *this); -}; - - -/** - * Construction to create a backend. - */ -typedef backend_t*(*backend_constructor_t)(void); - -#endif /* BACKEND_H_ */ - diff --git a/src/charon/config/backends/local_backend.c b/src/charon/config/backends/local_backend.c deleted file mode 100644 index e04c72ac1..000000000 --- a/src/charon/config/backends/local_backend.c +++ /dev/null @@ -1,322 +0,0 @@ -/** - * @file local_backend.c - * - * @brief Implementation of local_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 "local_backend.h" - -#include <daemon.h> -#include <utils/linked_list.h> -#include <crypto/ca.h> - - -typedef struct private_local_backend_t private_local_backend_t; - -/** - * Private data of an local_backend_t object - */ -struct private_local_backend_t { - - /** - * Public part - */ - local_backend_t public; - - /** - * list of configs - */ - linked_list_t *cfgs; - - /** - * Mutex to exclusivly access list - */ - pthread_mutex_t mutex; -}; - -/** - * implements backen_t.get_ike_cfg. - */ -static ike_cfg_t *get_ike_cfg(private_local_backend_t *this, - host_t *my_host, host_t *other_host) -{ - peer_cfg_t *peer; - ike_cfg_t *current, *found = NULL; - iterator_t *iterator; - host_t *my_candidate, *other_candidate; - enum { - MATCH_NONE = 0x00, - MATCH_ANY = 0x01, - MATCH_ME = 0x04, - MATCH_OTHER = 0x08, - } prio, best = MATCH_ANY; - - DBG2(DBG_CFG, "looking for a config for %H...%H", - my_host, other_host); - - iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); - while (iterator->iterate(iterator, (void**)&peer)) - { - prio = MATCH_NONE; - current = peer->get_ike_cfg(peer); - my_candidate = current->get_my_host(current); - other_candidate = current->get_other_host(current); - - if (my_candidate->ip_equals(my_candidate, my_host)) - { - prio += MATCH_ME; - } - else if (my_candidate->is_anyaddr(my_candidate)) - { - prio += MATCH_ANY; - } - - if (other_candidate->ip_equals(other_candidate, other_host)) - { - prio += MATCH_OTHER; - } - else if (other_candidate->is_anyaddr(other_candidate)) - { - prio += MATCH_ANY; - } - - DBG2(DBG_CFG, " candidate '%s': %H...%H, prio %d", - peer->get_name(peer), my_candidate, other_candidate, prio); - - /* we require at least two MATCH_ANY */ - if (prio > best) - { - best = prio; - found = current; - } - } - if (found) - { - found->get_ref(found); - } - iterator->destroy(iterator); - return found; -} - -#define PRIO_NO_MATCH_FOUND 256 - -/** - * implements backend_t.get_peer. - */ -static peer_cfg_t *get_peer_cfg(private_local_backend_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info) -{ - peer_cfg_t *current, *found = NULL; - iterator_t *iterator; - identification_t *my_candidate, *other_candidate; - int best = PRIO_NO_MATCH_FOUND; - - DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id); - - iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); - while (iterator->iterate(iterator, (void**)¤t)) - { - int wc1, wc2; - - my_candidate = current->get_my_id(current); - other_candidate = current->get_other_id(current); - - if (my_candidate->matches(my_candidate, my_id, &wc1) - && other_id->matches(other_id, other_candidate, &wc2)) - { - 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) - { - ca_info_t *ca_info = other_ca_info; - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - if (ca_info == NULL) - { - prio = PRIO_NO_MATCH_FOUND; - break; - } - else - { - x509_t *cacert = ca_info->get_certificate(ca_info); - identification_t *other_ca = cacert->get_subject(cacert); - - if (other_candidate_ca->equals(other_candidate_ca, other_ca)) - { - /* found a ca match */ - break; - } - if (cacert->is_self_signed(cacert)) - { - /* reached the root ca without a match */ - prio = PRIO_NO_MATCH_FOUND; - break; - } - /* move a level upward in the trust path hierarchy */ - ca_info = charon->credentials->get_issuer(charon->credentials, cacert); - } - } - if (pathlen == MAX_CA_PATH_LEN) - { - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - prio = PRIO_NO_MATCH_FOUND; - } - } - if (prio == PRIO_NO_MATCH_FOUND) - { - DBG2(DBG_CFG, " candidate '%s': %D...%D, no ca match", - current->get_name(current), my_candidate, other_candidate); - } - else - { - prio += pathlen; - DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d", - current->get_name(current), my_candidate, other_candidate, prio); - - if (prio < best) - { - found = current; - best = prio; - } - } - } - } - if (found) - { - DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d", - found->get_name(found), - found->get_my_id(found), - found->get_other_id(found), - best); - found->get_ref(found); - } - iterator->destroy(iterator); - return found; -} - -/** - * 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) -{ - return TRUE; -} - -/** - * Implementation of writable_backend_t.create_iterator. - */ -static iterator_t* create_iterator(private_local_backend_t *this) -{ - return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); -} - -/** - * Implementation of writable_backend_t.add_peer_cfg. - */ -static void add_cfg(private_local_backend_t *this, peer_cfg_t *config) -{ - pthread_mutex_lock(&this->mutex); - this->cfgs->insert_last(this->cfgs, config); - pthread_mutex_unlock(&this->mutex); -} - -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_local_backend_t *this) -{ - this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy)); - free(this); -} - -/** - * Described in header. - */ -backend_t *backend_create(void) -{ - private_local_backend_t *this = malloc_thing(private_local_backend_t); - - 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; - this->public.backend.add_cfg = (void (*)(writeable_backend_t*,peer_cfg_t*))add_cfg; - - /* private variables */ - this->cfgs = linked_list_create(); - pthread_mutex_init(&this->mutex, NULL); - - return &this->public.backend.backend; -} diff --git a/src/charon/config/backends/local_backend.h b/src/charon/config/backends/local_backend.h deleted file mode 100644 index b33c6443b..000000000 --- a/src/charon/config/backends/local_backend.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file local_backend.h - * - * @brief Interface of local_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 LOCAL_BACKEND_H_ -#define LOCAL_BACKEND_H_ - -typedef struct local_backend_t local_backend_t; - -#include <library.h> -#include <config/backends/writeable_backend.h> - -/** - * @brief An in-memory backend to store configurations. - * - * The local_backend_t stores the configuration in a simple list. It - * implements both, backend_t and writeable_backend_t. - * - * @b Constructors: - * - local_backend_create() - * - * @ingroup backends - */ -struct local_backend_t { - - /** - * Implements writable_backend_t interface - */ - writeable_backend_t backend; -}; - -/** - * @brief Create a backend_t instance implemented as local backend. - * - * @return backend instance - * - * @ingroup backends - */ -backend_t *backend_create(void); - -#endif /* LOCAL_BACKEND_H_ */ - diff --git a/src/charon/config/backends/sqlite_backend.c b/src/charon/config/backends/sqlite_backend.c deleted file mode 100644 index e1c96c870..000000000 --- a/src/charon/config/backends/sqlite_backend.c +++ /dev/null @@ -1,309 +0,0 @@ -/** - * @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), 0 /* eap_type, vendor */ - sqlite3_column_int(stmt, 7), /* keyingtries */ - sqlite3_column_int(stmt, 8), /* rekey_time */ - sqlite3_column_int(stmt, 9), /* reauth_time */ - sqlite3_column_int(stmt, 10), /* jitter_time */ - sqlite3_column_int(stmt, 11), /* over_time */ - sqlite3_column_int(stmt, 14), /* mobike */ - sqlite3_column_int(stmt, 12), /* dpd_delay */ - sqlite3_column_int(stmt, 13), /* 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, " - "rekey_time, reauth_time, jitter_time, over_time, " - "dpd_delay, dpd_action, 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 deleted file mode 100644 index 4bc146583..000000000 --- a/src/charon/config/backends/sqlite_backend.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @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_ */ - diff --git a/src/charon/config/backends/writeable_backend.h b/src/charon/config/backends/writeable_backend.h deleted file mode 100644 index ea62f62c9..000000000 --- a/src/charon/config/backends/writeable_backend.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file writeable_backend.h - * - * @brief Interface of writeable_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 WRITEABLE_BACKEND_H_ -#define WRITEABLE_BACKEND_H_ - -typedef struct writeable_backend_t writeable_backend_t; - -#include <library.h> -#include <config/backends/backend.h> - -/** - * @brief A writeable backend extends backend_t by modification functions. - * - * @b Constructors: - * - writeable_backend_create() - * - * @ingroup backends - */ -struct writeable_backend_t { - - /** - * Implements backend_t interface - */ - backend_t backend; - - /** - * @brief Add a peer_config to the backend. - * - * @param this calling object - * @param config peer_config to add to the backend - */ - void (*add_cfg)(writeable_backend_t *this, peer_cfg_t *config); - - /** - * @brief Create an iterator over all peer configs. - * - * @param this calling object - * @return iterator over peer configs - */ - iterator_t* (*create_iterator)(writeable_backend_t *this); -}; - -#endif /* WRITEABLE_BACKEND_H_ */ - diff --git a/src/charon/config/child_cfg.c b/src/charon/config/child_cfg.c index 5827b4f61..f929927ef 100644 --- a/src/charon/config/child_cfg.c +++ b/src/charon/config/child_cfg.c @@ -1,11 +1,5 @@ -/** - * @file child_cfg.c - * - * @brief Implementation of child_cfg_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,9 +13,10 @@ * 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: child_cfg.c 4062 2008-06-12 11:42:19Z martin $ */ - #include "child_cfg.h" #include <daemon.h> @@ -34,6 +29,21 @@ ENUM(mode_names, MODE_TRANSPORT, MODE_BEET, "BEET", ); +ENUM(action_names, ACTION_NONE, ACTION_RESTART, + "ACTION_NONE", + "ACTION_ROUTE", + "ACTION_RESTART", +); + +ENUM_BEGIN(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_NONE, + "IPCOMP_NONE"); +ENUM_NEXT(ipcomp_transform_names, IPCOMP_OUI, IPCOMP_LZJH, IPCOMP_NONE, + "IPCOMP_OUI", + "IPCOMP_DEFLATE", + "IPCOMP_LZS", + "IPCOMP_LZJH"); +ENUM_END(ipcomp_transform_names, IPCOMP_LZJH); + typedef struct private_child_cfg_t private_child_cfg_t; /** @@ -87,6 +97,16 @@ struct private_child_cfg_t { mode_t mode; /** + * action to take on DPD + */ + action_t dpd_action; + + /** + * action to take on CHILD_SA close + */ + action_t close_action; + + /** * Time before an SA gets invalid */ u_int32_t lifetime; @@ -101,6 +121,11 @@ struct private_child_cfg_t { * substracted from rekeytime. */ u_int32_t jitter; + + /** + * enable IPComp + */ + bool use_ipcomp; }; /** @@ -120,42 +145,25 @@ static void add_proposal(private_child_cfg_t *this, proposal_t *proposal) } /** - * strip out DH groups from a proposal - */ -static void strip_dh_from_proposal(proposal_t *proposal) -{ - iterator_t *iterator; - algorithm_t *algo; - - iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); - while (iterator->iterate(iterator, (void**)&algo)) - { - iterator->remove(iterator); - free(algo); - } - iterator->destroy(iterator); -} - -/** * Implementation of child_cfg_t.get_proposals */ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *current; linked_list_t *proposals = linked_list_create(); - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, ¤t)) { current = current->clone(current); if (strip_dh) { - strip_dh_from_proposal(current); + current->strip_dh(current); } proposals->insert_last(proposals, current); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return proposals; } @@ -166,26 +174,28 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh) { - iterator_t *stored_iter, *supplied_iter; + enumerator_t *stored_enum, *supplied_enum; proposal_t *stored, *supplied, *selected = NULL; - stored_iter = this->proposals->create_iterator(this->proposals, TRUE); - supplied_iter = proposals->create_iterator(proposals, TRUE); + stored_enum = this->proposals->create_enumerator(this->proposals); + supplied_enum = proposals->create_enumerator(proposals); /* compare all stored proposals with all supplied. Stored ones are preferred. */ - while (stored_iter->iterate(stored_iter, (void**)&stored)) + while (stored_enum->enumerate(stored_enum, &stored)) { stored = stored->clone(stored); - supplied_iter->reset(supplied_iter); - while (supplied_iter->iterate(supplied_iter, (void**)&supplied)) + while (supplied_enum->enumerate(supplied_enum, &supplied)) { if (strip_dh) { - strip_dh_from_proposal(stored); + stored->strip_dh(stored); } selected = stored->select(stored, supplied); if (selected) { + DBG2(DBG_CFG, "received proposals: %#P", proposals); + DBG2(DBG_CFG, "configured proposals: %#P", this->proposals); + DBG2(DBG_CFG, "selected proposal: %P", selected); break; } } @@ -194,9 +204,16 @@ static proposal_t* select_proposal(private_child_cfg_t*this, { break; } + supplied_enum->destroy(supplied_enum); + supplied_enum = proposals->create_enumerator(proposals); + } + stored_enum->destroy(stored_enum); + supplied_enum->destroy(supplied_enum); + if (selected == NULL) + { + DBG1(DBG_CFG, "received proposals: %#P", proposals); + DBG1(DBG_CFG, "configured proposals: %#P", this->proposals); } - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); return selected; } @@ -223,17 +240,17 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca linked_list_t *supplied, host_t *host) { - iterator_t *i1, *i2; + enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; linked_list_t *result = linked_list_create(); if (local) { - i1 = this->my_ts->create_iterator(this->my_ts, TRUE); + e1 = this->my_ts->create_enumerator(this->my_ts); } else { - i1 = this->other_ts->create_iterator(this->other_ts, FALSE); + e1 = this->other_ts->create_enumerator(this->other_ts); } /* no list supplied, just fetch the stored traffic selectors */ @@ -241,7 +258,7 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca { DBG2(DBG_CFG, "proposing traffic selectors for %s:", local ? "us" : "other"); - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, this allows us to update dynamic TS' */ selected = ts1->clone(ts1); @@ -252,15 +269,15 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1); result->insert_last(result, selected); } - i1->destroy(i1); + e1->destroy(e1); } else { DBG2(DBG_CFG, "selecting traffic selectors for %s:", local ? "us" : "other"); - i2 = supplied->create_iterator(supplied, TRUE); + e2 = supplied->create_enumerator(supplied); /* iterate over all stored selectors */ - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, as we have to update dynamic TS' */ ts1 = ts1->clone(ts1); @@ -269,9 +286,8 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1->set_address(ts1, host); } - i2->reset(i2); /* iterate over all supplied traffic selectors */ - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { selected = ts1->get_subset(ts1, ts2); if (selected) @@ -286,40 +302,44 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1, ts2, selected); } } + e2->destroy(e2); + e2 = supplied->create_enumerator(supplied); ts1->destroy(ts1); } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); } /* remove any redundant traffic selectors in the list */ - i1 = result->create_iterator(result, TRUE); - i2 = result->create_iterator(result, TRUE); - while (i1->iterate(i1, (void**)&ts1)) + e1 = result->create_enumerator(result); + e2 = result->create_enumerator(result); + while (e1->enumerate(e1, &ts1)) { - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { if (ts1 != ts2) { if (ts2->is_contained_in(ts2, ts1)) { - i2->remove(i2); + result->remove_at(result, e2); ts2->destroy(ts2); - i1->reset(i1); + e1->destroy(e1); + e1 = result->create_enumerator(result); break; } if (ts1->is_contained_in(ts1, ts2)) { - i1->remove(i1); + result->remove_at(result, e1); ts1->destroy(ts1); - i2->reset(i2); + e2->destroy(e2); + e2 = result->create_enumerator(result); break; } } } } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); return result; } @@ -357,7 +377,7 @@ static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey) } /** - * Implementation of child_cfg_t.get_name + * Implementation of child_cfg_t.get_mode */ static mode_t get_mode(private_child_cfg_t *this) { @@ -365,34 +385,57 @@ static mode_t get_mode(private_child_cfg_t *this) } /** + * Implementation of child_cfg_t.get_dpd_action + */ +static action_t get_dpd_action(private_child_cfg_t *this) +{ + return this->dpd_action; +} + +/** + * Implementation of child_cfg_t.get_close_action + */ +static action_t get_close_action(private_child_cfg_t *this) +{ + return this->close_action; +} + +/** * Implementation of child_cfg_t.get_dh_group. */ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } /** + * Implementation of child_cfg_t.use_ipcomp. + */ +static bool use_ipcomp(private_child_cfg_t *this) +{ + return this->use_ipcomp; +} + +/** * Implementation of child_cfg_t.get_name */ -static void get_ref(private_child_cfg_t *this) +static child_cfg_t* get_ref(private_child_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -419,11 +462,11 @@ static void destroy(private_child_cfg_t *this) */ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, u_int32_t rekeytime, u_int32_t jitter, - char *updown, bool hostaccess, mode_t mode) + char *updown, bool hostaccess, mode_t mode, + action_t dpd_action, action_t close_action, bool ipcomp) { private_child_cfg_t *this = malloc_thing(private_child_cfg_t); - /* public functions */ this->public.get_name = (char* (*) (child_cfg_t*))get_name; this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector; this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors; @@ -433,12 +476,14 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, this->public.get_updown = (char* (*) (child_cfg_t*))get_updown; this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess; this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode; + this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action; + this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action; this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime; this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group; - this->public.get_ref = (void (*) (child_cfg_t*))get_ref; + this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp; + this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref; this->public.destroy = (void (*) (child_cfg_t*))destroy; - /* apply init values */ this->name = strdup(name); this->lifetime = lifetime; this->rekeytime = rekeytime; @@ -446,8 +491,9 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, this->updown = updown ? strdup(updown) : NULL; this->hostaccess = hostaccess; this->mode = mode; - - /* initialize private members*/ + this->dpd_action = dpd_action; + this->close_action = close_action; + this->use_ipcomp = ipcomp; this->refcount = 1; this->proposals = linked_list_create(); this->my_ts = linked_list_create(); @@ -455,3 +501,4 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, return &this->public; } + diff --git a/src/charon/config/child_cfg.h b/src/charon/config/child_cfg.h index e1a6553b4..6d262c217 100644 --- a/src/charon/config/child_cfg.h +++ b/src/charon/config/child_cfg.h @@ -1,11 +1,5 @@ -/** - * @file child_cfg.h - * - * @brief Interface of child_cfg_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,12 +13,21 @@ * 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: child_cfg.h 3920 2008-05-08 16:19:11Z tobias $ + */ + +/** + * @defgroup child_cfg child_cfg + * @{ @ingroup config */ #ifndef CHILD_CFG_H_ #define CHILD_CFG_H_ typedef enum mode_t mode_t; +typedef enum action_t action_t; +typedef enum ipcomp_transform_t ipcomp_transform_t; typedef struct child_cfg_t child_cfg_t; #include <library.h> @@ -32,11 +35,9 @@ typedef struct child_cfg_t child_cfg_t; #include <config/traffic_selector.h> /** - * @brief Mode of an CHILD_SA. + * Mode of an CHILD_SA. * * These are equal to those defined in XFRM, so don't change. - * - * @ingroup config */ enum mode_t { /** transport mode, no inner address */ @@ -53,7 +54,40 @@ enum mode_t { extern enum_name_t *mode_names; /** - * @brief A child_cfg_t defines the config template for a CHILD_SA. + * Action to take when DPD detected/connection gets closed by peer. + */ +enum action_t { + /** No action */ + ACTION_NONE, + /** Route config to reestablish on demand */ + ACTION_ROUTE, + /** Restart config immediately */ + ACTION_RESTART, +}; + +/** + * enum names for action_t. + */ +extern enum_name_t *action_names; + +/** + * IPComp transform IDs, as in RFC 4306 + */ +enum ipcomp_transform_t { + IPCOMP_NONE = 241, + IPCOMP_OUI = 1, + IPCOMP_DEFLATE = 2, + IPCOMP_LZS = 3, + IPCOMP_LZJH = 4, +}; + +/** + * enum strings for ipcomp_transform_t. + */ +extern enum_name_t *ipcomp_transform_names; + +/** + * A child_cfg_t defines the config template for a CHILD_SA. * * After creation, proposals and traffic selectors may be added to the config. * A child_cfg object is referenced multiple times, and is not thread save. @@ -62,51 +96,42 @@ extern enum_name_t *mode_names; * A reference counter handles the number of references hold to this config. * * @see peer_cfg_t to get an overview over the configurations. - * - * @b Constructors: - * - child_cfg_create() - * - * @ingroup config */ struct child_cfg_t { /** - * @brief Get the name of the child_cfg. + * Get the name of the child_cfg. * - * @param this calling object * @return child_cfg's name */ char *(*get_name) (child_cfg_t *this); /** - * @brief Add a proposal to the list. + * Add a proposal to the list. * * The proposals are stored by priority, first added * is the most prefered. * After add, proposal is owned by child_cfg. * - * @param this calling object * @param proposal proposal to add */ void (*add_proposal) (child_cfg_t *this, proposal_t *proposal); /** - * @brief Get the list of proposals for the CHILD_SA. + * Get the list of proposals for the CHILD_SA. * * Resulting list and all of its proposals must be freed after use. * - * @param this calling object * @param strip_dh TRUE strip out diffie hellman groups * @return list of proposals */ linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_dh); /** - * @brief Select a proposal from a supplied list. + * Select a proposal from a supplied list. * * Returned propsal is newly created and must be destroyed after usage. * - * @param this calling object * @param proposals list from from wich proposals are selected * @param strip_dh TRUE strip out diffie hellman groups * @return selected proposal, or NULL if nothing matches @@ -115,12 +140,11 @@ struct child_cfg_t { bool strip_dh); /** - * @brief Add a traffic selector to the config. + * Add a traffic selector to the config. * * Use the "local" parameter to add it for the local or the remote side. * After add, traffic selector is owned by child_cfg. * - * @param this calling object * @param local TRUE for local side, FALSE for remote * @param ts traffic_selector to add */ @@ -128,7 +152,7 @@ struct child_cfg_t { traffic_selector_t *ts); /** - * @brief Get a list of traffic selectors to use for the CHILD_SA. + * Get a list of traffic selectors to use for the CHILD_SA. * * The config contains two set of traffic selectors, one for the local * side, one for the remote side. @@ -139,7 +163,6 @@ struct child_cfg_t { * the "host" parameter to narrow such traffic selectors to that address. * Resulted list and its traffic selectors must be destroyed after use. * - * @param this calling object * @param local TRUE for TS on local side, FALSE for remote * @param supplied list with TS to select from, or NULL * @param host address to use for narrowing "dynamic" TS', or NULL @@ -150,23 +173,21 @@ struct child_cfg_t { host_t *host); /** - * @brief Get the updown script to run for the CHILD_SA. + * Get the updown script to run for the CHILD_SA. * - * @param this calling object * @return path to updown script */ char* (*get_updown)(child_cfg_t *this); /** - * @brief Should we allow access to the local host (gateway)? + * Should we allow access to the local host (gateway)? * - * @param this calling object * @return value of hostaccess flag */ bool (*get_hostaccess) (child_cfg_t *this); /** - * @brief Get the lifetime of a CHILD_SA. + * Get the lifetime of a CHILD_SA. * * If "rekey" is set to TRUE, a lifetime is returned before the first * rekeying should be started. If it is FALSE, the actual lifetime is @@ -174,57 +195,68 @@ struct child_cfg_t { * The rekey time automatically contains a jitter to avoid simlutaneous * rekeying. * - * @param this child_cfg * @param rekey TRUE to get rekey time * @return lifetime in seconds */ u_int32_t (*get_lifetime) (child_cfg_t *this, bool rekey); /** - * @brief Get the mode to use for the CHILD_SA. + * Get the mode to use for the CHILD_SA. * * The mode is either tunnel, transport or BEET. The peer must agree * on the method, fallback is tunnel mode. * - * @param this child_cfg - * @return lifetime in seconds + * @return ipsec mode */ mode_t (*get_mode) (child_cfg_t *this); /** - * @brief Get the DH group to use for CHILD_SA setup. + * Action to take on DPD. + * + * @return DPD action + */ + action_t (*get_dpd_action) (child_cfg_t *this); + + /** + * Action to take if CHILD_SA gets closed. + * + * @return close action + */ + action_t (*get_close_action) (child_cfg_t *this); + + /** + * Get the DH group to use for CHILD_SA setup. * - * @param this calling object - * @return dh group to use + * @return dh group to use */ diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this); /** - * @brief Get a new reference. - * - * Get a new reference to this child_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), + * Check whether IPComp should be used, if the other peer supports it. * - * @param this calling object + * @return TRUE, if IPComp should be used + * FALSE, otherwise */ - void (*get_ref) (child_cfg_t *this); + bool (*use_ipcomp)(child_cfg_t *this); /** - * @brief Destroys the child_cfg object. + * Increase the reference count. + * + * @return reference to this + */ + child_cfg_t* (*get_ref) (child_cfg_t *this); + + /** + * Destroys the child_cfg object. * * Decrements the internal reference counter and * destroys the child_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (child_cfg_t *this); }; /** - * @brief Create a configuration template for CHILD_SA setup. + * Create a configuration template for CHILD_SA setup. * * The "name" string gets cloned. * Lifetimes are in seconds. To prevent to peers to start rekeying at the @@ -240,12 +272,15 @@ struct child_cfg_t { * @param updown updown script to execute on up/down event * @param hostaccess TRUE to allow access to the local host * @param mode mode to propose for CHILD_SA, transport, tunnel or BEET + * @param dpd_action DPD action + * @param close_action close action + * @param ipcomp use IPComp, if peer supports it * @return child_cfg_t object - * - * @ingroup config */ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, u_int32_t rekeytime, u_int32_t jitter, - char *updown, bool hostaccess, mode_t mode); + char *updown, bool hostaccess, mode_t mode, + action_t dpd_action, action_t close_action, + bool ipcomp); -#endif /* CHILD_CFG_H_ */ +#endif /* CHILD_CFG_H_ @} */ diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c deleted file mode 100644 index b838f032d..000000000 --- a/src/charon/config/credentials/local_credential_store.c +++ /dev/null @@ -1,1620 +0,0 @@ -/** - * @file local_credential_store.c - * - * @brief Implementation of local_credential_store_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. - * - * RCSID $Id: local_credential_store.c 3346 2007-11-16 20:23:29Z andreas $ - */ - -#include <sys/stat.h> -#include <dirent.h> -#include <string.h> -#include <pthread.h> -#include <errno.h> - -#include <library.h> -#include <utils/lexparser.h> -#include <utils/linked_list.h> -#include <crypto/rsa/rsa_public_key.h> -#include <crypto/certinfo.h> -#include <crypto/x509.h> -#include <crypto/ca.h> -#include <crypto/ac.h> -#include <crypto/crl.h> -#include <asn1/ttodata.h> - -#include "local_credential_store.h" - -#define PATH_BUF 256 - -typedef struct shared_key_t shared_key_t; - -/** - * Private date of a shared_key_t object - */ -struct shared_key_t { - - /** - * shared secret - */ - chunk_t secret; - - /** - * list of peer IDs - */ - linked_list_t *peers; -}; - - -/** - * Implementation of shared_key_t.destroy. - */ -static void shared_key_destroy(shared_key_t *this) -{ - this->peers->destroy_offset(this->peers, offsetof(identification_t, destroy)); - chunk_free_randomized(&this->secret); - free(this); -} - -/** - * @brief Creates a shared_key_t object. - * - * @param shared_key shared key value - * @return shared_key_t object - * - * @ingroup config - */ -static shared_key_t *shared_key_create(chunk_t secret) -{ - shared_key_t *this = malloc_thing(shared_key_t); - - /* private data */ - this->secret = secret; - this->peers = linked_list_create(); - - return (this); -} - -/* ------------------------------------------------------------------------ * - * the ca_info_t object as a central control element - -+--------------------------------------------------------+ -| local_credential_store_t | -+--------------------------------------------------------+ - | | -+---------------------------+ +-------------------------+ -| linked_list_t *auth_certs | | linked_list_t *ca_infos | -+---------------------------+ +-------------------------+ - | | - | +------------------------- + - | | ca_info_t | - | +--------------------------+ -+---------------+ | char *name | -| x509_t |<--| x509_t *cacert | -+---------------+ | linked_list_t *attrcerts | +----------------------+ -| chunk_t keyid | | linked_list_t *certinfos |-->| certinfo_t | -+---------------+ | linked_list_t *ocspuris | +----------------------+ - | | crl_t *crl | | chunk_t serialNumber | - | | linked_list_t *crluris | | cert_status_t status | -+---------------+ | pthread_mutex_t mutex | | time_t thisUpdate | -| x509_t | +--------------------------+ | time_t nextUpdate | -+---------------+ | | bool once | -| chunk_t keyid | | +----------------------+ -+---------------+ +------------------------- + | - | | ca_info_t | +----------------------+ - | +--------------------------+ | certinfo_t | -+---------------+ | char *name | +----------------------+ -| x509_t |<--| x509_t *cacert | | chunk_t serialNumber | -+---------------+ | linked_list_t *attrcerts | | cert_status_t status | -| chunk_t keyid | | linked_list_t *certinfos | | time_t thisUpdate | -+---------------+ | linked_list_t *ocspuris | | time_t nextUpdate | - | | crl_t *crl | | bool once | - | | linked_list_t *crluris | +----------------------+ - | | pthread_mutex_t mutex; | | - | +--------------------------+ - | | - - * ------------------------------------------------------------------------ */ - -typedef struct private_local_credential_store_t private_local_credential_store_t; - -/** - * Private data of an local_credential_store_t object - */ -struct private_local_credential_store_t { - - /** - * Public part - */ - local_credential_store_t public; - - /** - * list of shared keys - */ - linked_list_t *shared_keys; - - /** - * list of EAP keys - */ - linked_list_t *eap_keys; - - /** - * list of key_entry_t's with private keys - */ - linked_list_t *private_keys; - - /** - * mutex controls access to the linked lists of secret keys - */ - pthread_mutex_t keys_mutex; - - /** - * list of X.509 certificates with public keys - */ - linked_list_t *certs; - - /** - * list of X.509 authority certificates with public keys - */ - linked_list_t *auth_certs; - - /** - * list of X.509 CA information records - */ - linked_list_t *ca_infos; - - /** - * list of X.509 attribute certificates - */ - linked_list_t *acerts; - - /** - * mutex controls access to the linked list of attribute certificates - */ - pthread_mutex_t acerts_mutex; -}; - - -/** - * Get a key from a list with shared_key_t's - */ -static status_t get_key(linked_list_t *keys, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - typedef enum { - PRIO_UNDEFINED= 0x00, - PRIO_ANY_MATCH= 0x01, - PRIO_MY_MATCH= 0x02, - PRIO_OTHER_MATCH= 0x04, - } prio_t; - - prio_t best_prio = PRIO_UNDEFINED; - chunk_t found = chunk_empty; - shared_key_t *shared_key; - iterator_t *iterator; - - iterator = keys->create_iterator(keys, TRUE); - - while (iterator->iterate(iterator, (void**)&shared_key)) - { - iterator_t *peer_iterator; - identification_t *peer_id; - prio_t prio = PRIO_UNDEFINED; - - peer_iterator = shared_key->peers->create_iterator(shared_key->peers, TRUE); - - if (peer_iterator->get_count(peer_iterator) == 0) - { - /* this is a wildcard shared key */ - prio = PRIO_ANY_MATCH; - } - else - { - while (peer_iterator->iterate(peer_iterator, (void**)&peer_id)) - { - if (my_id->equals(my_id, peer_id)) - { - prio |= PRIO_MY_MATCH; - } - if (other_id->equals(other_id, peer_id)) - { - prio |= PRIO_OTHER_MATCH; - } - } - } - peer_iterator->destroy(peer_iterator); - - if (prio > best_prio) - { - best_prio = prio; - found = shared_key->secret; - } - } - iterator->destroy(iterator); - - if (best_prio == PRIO_UNDEFINED) - { - return NOT_FOUND; - } - else - { - *secret = chunk_clone(found); - return SUCCESS; - } -} - -/** - * Implementation of local_credential_store_t.get_shared_key. - */ -static status_t get_shared_key(private_local_credential_store_t *this, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - status_t status; - - pthread_mutex_lock(&(this->keys_mutex)); - status = get_key(this->shared_keys, my_id, other_id, secret); - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of local_credential_store_t.get_eap_key. - */ -static status_t get_eap_key(private_local_credential_store_t *this, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - status_t status; - - pthread_mutex_lock(&(this->keys_mutex)); - status = get_key(this->eap_keys, my_id, other_id, secret); - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of credential_store_t.get_certificate. - */ -static x509_t* get_certificate(private_local_credential_store_t *this, - identification_t *id) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (id->equals(id, current_cert->get_subject(current_cert)) || - current_cert->equals_subjectAltName(current_cert, id)) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implementation of local_credential_store_t.get_rsa_public_key. - */ -static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this, - identification_t *id) -{ - x509_t *cert = get_certificate(this, id); - - return (cert == NULL)? NULL:cert->get_public_key(cert); -} - -/** - * Implementation of credential_store_t.get_issuer. - */ -static ca_info_t* get_issuer(private_local_credential_store_t *this, x509_t *cert) -{ - ca_info_t *found = cert->get_ca_info(cert); - - if (found == NULL) - { - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_cert_issuer(ca_info, cert)) - { - found = ca_info; - cert->set_ca_info(cert, found); - break; - } - } - iterator->destroy(iterator); - } - return found; -} - -/** - * Implementation of local_credential_store_t.has_rsa_private_key. - */ -static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey) -{ - bool found = FALSE; - rsa_private_key_t *current; - iterator_t *iterator; - - pthread_mutex_lock(&(this->keys_mutex)); - iterator = this->private_keys->create_iterator(this->private_keys, TRUE); - - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->belongs_to(current, pubkey)) - { - found = TRUE; - break; - } - } - iterator->destroy(iterator); - pthread_mutex_unlock(&(this->keys_mutex)); - return found; -} - -/** - * Implementation of credential_store_t.get_auth_certificate. - */ -static x509_t* get_auth_certificate(private_local_credential_store_t *this, - u_int auth_flags, - identification_t *id) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (current_cert->has_authority_flag(current_cert, auth_flags) - && id->equals(id, current_cert->get_subject(current_cert))) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Implementation of credential_store_t.get_ca_certificate_by_keyid. - */ -static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *this, - chunk_t keyid) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - rsa_public_key_t *pubkey = current_cert->get_public_key(current_cert); - - if (current_cert->has_authority_flag(current_cert, AUTH_CA) - && chunk_equals(keyid, pubkey->get_keyid(pubkey))) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Find an exact copy of a certificate in a linked list - */ -static x509_t* find_certificate(linked_list_t *certs, x509_t *cert) -{ - x509_t *found_cert = NULL, *current_cert; - - iterator_t *iterator = certs->create_iterator(certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (cert->equals(cert, current_cert)) - { - found_cert = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found_cert; -} - -/** - * Adds crl and ocsp uris to the corresponding issuer info record - */ -static void add_uris(ca_info_t *issuer, x509_t *cert) -{ - iterator_t *iterator; - identification_t *uri; - - /* add any crl distribution points to the issuer ca info record */ - iterator = cert->create_crluri_iterator(cert); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - issuer->add_crluri(issuer, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); - - /* add any ocsp access points to the issuer ca info record */ - iterator = cert->create_ocspuri_iterator(cert); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - issuer->add_ocspuri(issuer, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); -} - -/** - * Implementation of credential_store_t.is_trusted - */ -static bool is_trusted(private_local_credential_store_t *this, const char *label, x509_t *cert) -{ - int pathlen; - time_t until = UNDEFINED_TIME; - x509_t *cert_to_be_trusted = cert; - - DBG1(DBG_CFG, "establishing trust in %s certificate:", label); - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - err_t ugh = NULL; - ca_info_t *issuer; - x509_t *issuer_cert; - rsa_public_key_t *issuer_public_key; - bool valid_signature; - - DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - - ugh = cert->is_valid(cert, &until); - if (ugh != NULL) - { - DBG1(DBG_CFG, "certificate %s", ugh); - return FALSE; - } - DBG2(DBG_CFG, "certificate is valid"); - - issuer = get_issuer(this, cert); - if (issuer == NULL) - { - DBG1(DBG_CFG, "issuer not found"); - return FALSE; - } - DBG2(DBG_CFG, "issuer found"); - - issuer_cert = issuer->get_certificate(issuer); - issuer_public_key = issuer_cert->get_public_key(issuer_cert); - valid_signature = cert->verify(cert, issuer_public_key); - - if (!valid_signature) - { - DBG1(DBG_CFG, "certificate signature is invalid"); - return FALSE; - } - DBG2(DBG_CFG, "certificate signature is valid"); - - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && cert->is_self_signed(cert)) - { - DBG1(DBG_CFG, "reached self-signed root ca"); - cert_to_be_trusted->set_until(cert_to_be_trusted, until); - cert_to_be_trusted->set_status(cert_to_be_trusted, CERT_GOOD); - return TRUE; - } - else - { - DBG1(DBG_CFG, "going up one step in the certificate trust chain (%d)", - pathlen + 1); - cert = issuer_cert; - } - } - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - return FALSE; -} - -/** - * Implementation of credential_store_t.verify. - */ -static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found) -{ - int pathlen; - time_t until = UNDEFINED_TIME; - - x509_t *end_cert = cert; - x509_t *cert_copy = find_certificate(this->certs, end_cert); - - DBG1(DBG_CFG, "verifying end entity certificate up to trust anchor:"); - - *found = (cert_copy != NULL); - if (*found) - { - DBG2(DBG_CFG, - "end entitity certificate is already in credential store"); - } - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - bool valid_signature; - err_t ugh = NULL; - ca_info_t *issuer; - x509_t *issuer_cert; - rsa_public_key_t *issuer_public_key; - chunk_t keyid = cert->get_keyid(cert); - - DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - DBG1(DBG_CFG, "keyid: %#B", &keyid); - - ugh = cert->is_valid(cert, &until); - if (ugh != NULL) - { - DBG1(DBG_CFG, "certificate %s", ugh); - return FALSE; - } - DBG2(DBG_CFG, "certificate is valid"); - - issuer = get_issuer(this, cert); - if (issuer == NULL) - { - DBG1(DBG_CFG, "issuer not found"); - return FALSE; - } - DBG2(DBG_CFG, "issuer found"); - - issuer_cert = issuer->get_certificate(issuer); - issuer_public_key = issuer_cert->get_public_key(issuer_cert); - valid_signature = cert->verify(cert, issuer_public_key); - - if (!valid_signature) - { - DBG1(DBG_CFG, "certificate signature is invalid"); - return FALSE; - } - DBG2(DBG_CFG, "certificate signature is valid"); - - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && cert->is_self_signed(cert)) - { - DBG1(DBG_CFG, "reached self-signed root ca"); - - /* set the definite status and trust interval of the end entity certificate */ - end_cert->set_until(end_cert, until); - if (cert_copy) - { - cert_copy->set_status(cert_copy, end_cert->get_status(end_cert)); - cert_copy->set_until(cert_copy, until); - } - return TRUE; - } - else - { - bool strict; - time_t nextUpdate; - cert_status_t status; - certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert)); - - if (pathlen == 0) - { - /* add any crl and ocsp uris contained in the certificate under test */ - add_uris(issuer, cert); - } - - strict = issuer->is_strict(issuer); - DBG1(DBG_CFG, "issuer %s a strict crl policy", - strict ? "enforces":"does not enforce"); - - /* first check certificate revocation using ocsp */ - status = issuer->verify_by_ocsp(issuer, certinfo, &this->public.credential_store); - - /* if ocsp service is not available then fall back to crl */ - if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && strict)) - { - - certinfo->set_status(certinfo, CERT_UNKNOWN); - status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR); - } - - nextUpdate = certinfo->get_nextUpdate(certinfo); - cert->set_status(cert, status); - - switch (status) - { - case CERT_GOOD: - /* with strict crl policy the public key must have the same - * lifetime as the validity of the ocsp status or crl lifetime - */ - if (strict) - { - cert->set_until(cert, nextUpdate); - until = (nextUpdate < until)? nextUpdate : until; - } - - /* if status information is stale */ - if (strict && nextUpdate < time(NULL)) - { - DBG2(DBG_CFG, "certificate is good but status is stale"); - certinfo->destroy(certinfo); - return FALSE; - } - DBG1(DBG_CFG, "certificate is good"); - break; - case CERT_REVOKED: - { - time_t revocationTime = certinfo->get_revocationTime(certinfo); - DBG1(DBG_CFG, - "certificate was revoked on %T, reason: %N", - &revocationTime, crl_reason_names, - certinfo->get_revocationReason(certinfo)); - - /* set revocationTime */ - cert->set_until(cert, revocationTime); - - /* update status of end certificate in the credential store */ - if (cert_copy) - { - if (pathlen > 0) - { - cert_copy->set_status(cert_copy, CERT_UNTRUSTED); - } - else - { - cert_copy->set_status(cert_copy, CERT_REVOKED); - cert_copy->set_until(cert_copy, - certinfo->get_revocationTime(certinfo)); - } - } - certinfo->destroy(certinfo); - return FALSE; - } - case CERT_UNKNOWN: - case CERT_UNDEFINED: - default: - DBG1(DBG_CFG, "certificate status unknown"); - if (strict) - { - /* update status of end certificate in the credential store */ - if (cert_copy) - { - cert_copy->set_status(cert_copy, CERT_UNTRUSTED); - } - certinfo->destroy(certinfo); - return FALSE; - } - break; - } - certinfo->destroy(certinfo); - } - DBG1(DBG_CFG, "going up one step in the certificate trust chain (%d)", - pathlen + 1); - cert = issuer_cert; - } - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - return FALSE; -} - -/** - * Implementation of local_credential_store_t.rsa_signature. - */ -static status_t rsa_signature(private_local_credential_store_t *this, - rsa_public_key_t *pubkey, - hash_algorithm_t hash_algorithm, - chunk_t data, chunk_t *signature) -{ - rsa_private_key_t *current, *key = NULL; - iterator_t *iterator; - status_t status; - chunk_t keyid = pubkey->get_keyid(pubkey); - - DBG2(DBG_IKE, "looking for RSA private key with keyid %#B...", &keyid); - pthread_mutex_lock(&(this->keys_mutex)); - - iterator = this->private_keys->create_iterator(this->private_keys, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->belongs_to(current, pubkey)) - { - key = current; - break; - } - } - iterator->destroy(iterator); - - if (key) - { - DBG2(DBG_IKE, " matching RSA private key found"); - status = key->build_emsa_pkcs1_signature(key, hash_algorithm, data, signature); - } - else - { - DBG1(DBG_IKE, "no RSA private key found with keyid %#B", &keyid); - status = NOT_FOUND; - } - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of local_credential_store_t.verify_signature. - */ -static status_t verify_signature(private_local_credential_store_t *this, - chunk_t hash, chunk_t signature, - identification_t *id, ca_info_t **issuer_p) -{ - iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); - status_t sig_status; - x509_t *cert; - - /* default return values in case of failure */ - sig_status = NOT_FOUND; - *issuer_p = NULL; - - while (iterator->iterate(iterator, (void**)&cert)) - { - if (id->equals(id, cert->get_subject(cert)) - || cert->equals_subjectAltName(cert, id)) - { - rsa_public_key_t *public_key = cert->get_public_key(cert); - cert_status_t cert_status = cert->get_status(cert); - - DBG2(DBG_CFG, "found candidate peer certificate"); - - if (cert_status == CERT_UNDEFINED || cert->get_until(cert) < time(NULL)) - { - bool found; - - if (!verify(this, cert, &found)) - { - sig_status = VERIFY_ERROR; - DBG1(DBG_CFG, "candidate peer certificate was not successfully verified"); - continue; - } - *issuer_p = get_issuer(this, cert); - } - else - { - ca_info_t *issuer = get_issuer(this, cert); - chunk_t keyid = public_key->get_keyid(public_key); - - DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - DBG2(DBG_CFG, "keyid: %#B", &keyid); - - if (issuer == NULL) - { - DBG1(DBG_CFG, "candidate peer certificate has no retrievable issuer"); - sig_status = NOT_FOUND; - continue; - } - if (cert_status == CERT_REVOKED || cert_status == CERT_UNTRUSTED - || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD)) - { - DBG1(DBG_CFG, "candidate peer certificate has an inacceptable status: %N", cert_status_names, cert_status); - sig_status = VERIFY_ERROR; - continue; - } - *issuer_p = issuer; - } - sig_status = public_key->verify_emsa_pkcs1_signature(public_key, HASH_UNKNOWN, hash, signature); - if (sig_status == SUCCESS) - { - DBG2(DBG_CFG, "candidate peer certificate has a matching RSA public key"); - break; - } - else - { - DBG1(DBG_CFG, "candidate peer certificate has a non-matching RSA public key"); - *issuer_p = NULL; - } - } - } - iterator->destroy(iterator); - if (sig_status == NOT_FOUND) - { - DBG1(DBG_CFG, "no candidate peer certificate found"); - } - return sig_status; -} - -/** - * Add a unique certificate to a linked list - */ -static x509_t* add_certificate(linked_list_t *certs, x509_t *cert) -{ - x509_t *found_cert = find_certificate(certs, cert); - - if (found_cert) - { - /* add the authority flags */ - found_cert->add_authority_flags(found_cert, cert->get_authority_flags(cert)); - - cert->destroy(cert); - return found_cert; - } - else - { - certs->insert_last(certs, (void*)cert); - return cert; - } -} - -/** - * Add a unique ca info record to a linked list - */ -static ca_info_t* add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info) -{ - ca_info_t *current_ca_info; - ca_info_t *found_ca_info = NULL; - - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_ca_info)) - { - if (current_ca_info->equals(current_ca_info, ca_info)) - { - found_ca_info = current_ca_info; - break; - } - } - iterator->destroy(iterator); - - if (found_ca_info) - { - current_ca_info->add_info(current_ca_info, ca_info); - ca_info->destroy(ca_info); - ca_info = found_ca_info; - } - else - { - this->ca_infos->insert_last(this->ca_infos, (void*)ca_info); - } - return ca_info; -} - -/** - * Release ca info record of a given name - */ -static status_t release_ca_info(private_local_credential_store_t *this, const char *name) -{ - status_t status = NOT_FOUND; - ca_info_t *ca_info; - - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->equals_name_release_info(ca_info, name)) - { - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; -} - -/** - * Implements local_credential_store_t.add_end_certificate - */ -static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_t *cert) -{ - x509_t *ret_cert = add_certificate(this->certs, cert); - - /* add crl and ocsp uris the first time the certificate is added */ - if (ret_cert == cert) - { - ca_info_t *issuer = get_issuer(this, cert); - - if (issuer) - { - add_uris(issuer, cert); - } - } - return ret_cert; -} - -/** - * Implements local_credential_store_t.add_auth_certificate - */ -static x509_t* add_auth_certificate(private_local_credential_store_t *this, x509_t *cert, u_int auth_flags) -{ - cert->add_authority_flags(cert, auth_flags); - return add_certificate(this->auth_certs, cert); -} - -/** - * Implements local_credential_store_t.create_cert_iterator - */ -static iterator_t* create_cert_iterator(private_local_credential_store_t *this) -{ - return this->certs->create_iterator(this->certs, TRUE); -} - -/** - * Implements local_credential_store_t.create_cacert_iterator - */ -static iterator_t* create_auth_cert_iterator(private_local_credential_store_t *this) -{ - return this->auth_certs->create_iterator(this->auth_certs, TRUE); -} - -/** - * Implements local_credential_store_t.create_cainfo_iterator - */ -static iterator_t* create_cainfo_iterator(private_local_credential_store_t *this) -{ - return this->ca_infos->create_iterator(this->ca_infos, TRUE); -} - -/** - * Implements local_credential_store_t.create_acert_iterator - */ -static iterator_t* create_acert_iterator(private_local_credential_store_t *this) -{ - return this->acerts->create_iterator_locked(this->acerts, &this->acerts_mutex); -} - -/** - * Implements local_credential_store_t.load_auth_certificates - */ -static void load_auth_certificates(private_local_credential_store_t *this, - u_int auth_flag, - const char* label, - const char* path) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - - DBG1(DBG_CFG, "loading %s certificates from '%s'", label, path); - - dir = opendir(path); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening %s certs directory '%s'", label, path); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - x509_t *cert = x509_create_from_file(file, label); - - if (cert) - { - err_t ugh = cert->is_valid(cert, NULL); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "warning: %s certificate %s", label, ugh); - } - - if (auth_flag == AUTH_CA && !cert->is_ca(cert)) - { - DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded"); - cert->destroy(cert); - } - else - { - x509_t *ret_cert; - - cert->add_authority_flags(cert, auth_flag); - - ret_cert = add_certificate(this->auth_certs, cert); - - if (auth_flag == AUTH_CA && ret_cert == cert) - { - ca_info_t *ca_info = ca_info_create(NULL, cert); - - add_ca_info(this, ca_info); - } - } - } - } - } - closedir(dir); -} - -/** - * Implements local_credential_store_t.load_ca_certificates - */ -static void load_ca_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_CA, "ca", CA_CERTIFICATE_DIR); - - /* add any crl and ocsp uris found in the ca certificates to the - * corresponding issuer info record. We can do this only after all - * ca certificates have been loaded and the ca hierarchy is known. - */ - { - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - - while (iterator->iterate(iterator, (void **)&ca_info)) - { - if (ca_info->is_ca(ca_info)) - { - x509_t *cacert = ca_info->get_certificate(ca_info); - ca_info_t *issuer = get_issuer(this, cacert); - - if (issuer) - { - add_uris(issuer, cacert); - } - } - } - iterator->destroy(iterator); - } -} - -/** - * Implements local_credential_store_t.load_aa_certificates - */ -static void load_aa_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_AA, "aa", AA_CERTIFICATE_DIR); -} - -/** - * Add a unique attribute certificate to a linked list - */ -static void add_attr_certificate(private_local_credential_store_t *this, x509ac_t *cert) -{ - iterator_t *iterator; - x509ac_t *current_cert; - bool found = FALSE; - - pthread_mutex_lock(&(this->acerts_mutex)); - iterator = this->acerts->create_iterator(this->acerts, TRUE); - - while (iterator->iterate(iterator, (void **)¤t_cert)) - { - if (cert->equals_holder(cert, current_cert)) - { - if (cert->is_newer(cert, current_cert)) - { - iterator->replace(iterator, NULL, (void *)cert); - current_cert->destroy(current_cert); - DBG1(DBG_CFG, " this attr cert is newer - existing attr cert replaced"); - } - else - { - cert->destroy(cert); - DBG1(DBG_CFG, " this attr cert is not newer - existing attr cert retained"); - } - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (!found) - { - this->acerts->insert_last(this->acerts, (void *)cert); - } - pthread_mutex_unlock(&(this->acerts_mutex)); -} - -/** - * Implements local_credential_store_t.load_attr_certificates - */ -static void load_attr_certificates(private_local_credential_store_t *this) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - - const char *path = ATTR_CERTIFICATE_DIR; - - DBG1(DBG_CFG, "loading attribute certificates from '%s'", path); - - dir = opendir(ATTR_CERTIFICATE_DIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening attribute certs directory '%s'", path); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - x509ac_t *cert = x509ac_create_from_file(file); - - if (cert) - { - err_t ugh = cert->is_valid(cert, NULL); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "warning: attribute certificate %s", ugh); - } - add_attr_certificate(this, cert); - } - } - } - closedir(dir); - - -} - -/** - * Implements local_credential_store_t.load_ocsp_certificates - */ -static void load_ocsp_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_OCSP, "ocsp", OCSP_CERTIFICATE_DIR); -} - -/** - * Add the latest crl to the issuing ca - */ -static void add_crl(private_local_credential_store_t *this, crl_t *crl, const char *path) -{ - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - bool found = FALSE; - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_ca(ca_info) && ca_info->is_crl_issuer(ca_info, crl)) - { - char buffer[BUF_LEN]; - chunk_t uri = { buffer, 7 + strlen(path) }; - - ca_info->add_crl(ca_info, crl); - if (uri.len < BUF_LEN) - { - snprintf(buffer, BUF_LEN, "file://%s", path); - ca_info->add_crluri(ca_info, uri); - } - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (!found) - { - crl->destroy(crl); - DBG2(DBG_CFG, " no issuing ca found for this crl - discarded"); - } -} - -/** - * Implements local_credential_store_t.load_crls - */ -static void load_crls(private_local_credential_store_t *this) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - crl_t *crl; - - DBG1(DBG_CFG, "loading crls from '%s'", CRL_DIR); - - dir = opendir(CRL_DIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening crl directory '%s'", CRL_DIR); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", CRL_DIR, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - crl = crl_create_from_file(file); - if (crl) - { - DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale"); - add_crl(this, crl, file); - } - } - } - closedir(dir); -} - -/** - * Convert a string of characters into a binary secret - * A string between single or double quotes is treated as ASCII characters - * A string prepended by 0x is treated as HEX and prepended by 0s as Base64 - */ -static err_t extract_secret(chunk_t *secret, chunk_t *line) -{ - chunk_t raw_secret; - char delimiter = ' '; - bool quotes = FALSE; - - if (!eat_whitespace(line)) - { - return "missing secret"; - } - - if (*line->ptr == '\'' || *line->ptr == '"') - { - quotes = TRUE; - delimiter = *line->ptr; - line->ptr++; line->len--; - } - - if (!extract_token(&raw_secret, delimiter, line)) - { - if (delimiter == ' ') - { - raw_secret = *line; - } - else - { - return "missing second delimiter"; - } - } - - if (quotes) - { - /* treat as an ASCII string */ - *secret = chunk_clone(raw_secret); - } - else - { - size_t len; - err_t ugh; - - /* secret converted to binary form doesn't use more space than the raw_secret */ - *secret = chunk_alloc(raw_secret.len); - - /* convert from HEX or Base64 to binary */ - ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len); - - if (ugh != NULL) - { - chunk_free_randomized(secret); - return ugh; - } - secret->len = len; - } - return NULL; -} - -/** - * Implements local_credential_store_t.load_secrets - */ -static void load_secrets(private_local_credential_store_t *this, bool reload) -{ - FILE *fd = fopen(SECRETS_FILE, "r"); - - if (fd) - { - size_t bytes; - int line_nr = 0; - chunk_t chunk, src, line; - - DBG1(DBG_CFG, "%sloading secrets from \"%s\"", - reload? "re":"", SECRETS_FILE); - - fseek(fd, 0, SEEK_END); - chunk.len = ftell(fd); - rewind(fd); - chunk.ptr = malloc(chunk.len); - bytes = fread(chunk.ptr, 1, chunk.len, fd); - fclose(fd); - src = chunk; - - pthread_mutex_lock(&(this->keys_mutex)); - if (reload) - { - DBG1(DBG_CFG, " forgetting old secrets"); - this->private_keys->destroy_offset(this->private_keys, - offsetof(rsa_private_key_t, destroy)); - this->private_keys = linked_list_create(); - - this->shared_keys->destroy_function(this->shared_keys, - (void*)shared_key_destroy); - this->shared_keys = linked_list_create(); - - this->eap_keys->destroy_function(this->eap_keys, - (void*)shared_key_destroy); - this->eap_keys = linked_list_create(); - } - - while (fetchline(&src, &line)) - { - chunk_t ids, token; - bool is_eap = FALSE; - - line_nr++; - - if (!eat_whitespace(&line)) - { - continue; - } - if (!extract_last_token(&ids, ':', &line)) - { - DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr); - goto error; - } - /* NULL terminate the ids string by replacing the : separator */ - *(ids.ptr + ids.len) = '\0'; - - if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) - { - DBG1(DBG_CFG, "line %d: missing token", line_nr); - goto error; - } - if (match("RSA", &token)) - { - char path[PATH_BUF]; - chunk_t filename; - chunk_t secret = chunk_empty; - chunk_t *passphrase = NULL; - - rsa_private_key_t *key; - - err_t ugh = extract_value(&filename, &line); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); - goto error; - } - if (filename.len == 0) - { - DBG1(DBG_CFG, "line %d: empty filename", line_nr); - goto error; - } - if (*filename.ptr == '/') - { - /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); - } - else - { - /* relative path name */ - snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, - filename.len, filename.ptr); - } - - /* check for optional passphrase */ - if (eat_whitespace(&line)) - { - ugh = extract_secret(&secret, &line); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); - goto error; - } - if (secret.len > 0) - passphrase = &secret; - } - key = rsa_private_key_create_from_file(path, passphrase); - if (key) - { - this->private_keys->insert_last(this->private_keys, (void*)key); - } - chunk_free_randomized(&secret); - } - else if ( match("PSK", &token) || - ((match("EAP", &token) || match("XAUTH", &token)) && (is_eap = TRUE))) - { - shared_key_t *shared_key; - chunk_t secret = chunk_empty; - - err_t ugh = extract_secret(&secret, &line); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh); - goto error; - } - - DBG1(DBG_CFG, " loading %s key for %s", - is_eap ? "EAP" : "shared", - ids.len > 0 ? (char*)ids.ptr : "%any"); - - DBG4(DBG_CFG, " secret:", secret); - - shared_key = shared_key_create(secret); - if (is_eap) - { - this->eap_keys->insert_last(this->eap_keys, (void*)shared_key); - } - else - { - this->shared_keys->insert_last(this->shared_keys, (void*)shared_key); - } - while (ids.len > 0) - { - chunk_t id; - identification_t *peer_id; - - ugh = extract_value(&id, &ids); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); - goto error; - } - if (id.len == 0) - { - continue; - } - - /* NULL terminate the ID string */ - *(id.ptr + id.len) = '\0'; - - peer_id = identification_create_from_string(id.ptr); - if (peer_id == NULL) - { - DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr); - goto error; - } - - if (peer_id->get_type(peer_id) == ID_ANY) - { - peer_id->destroy(peer_id); - continue; - } - shared_key->peers->insert_last(shared_key->peers, (void*)peer_id); - } - } - else if (match("PIN", &token)) - { - - } - else - { - DBG1(DBG_CFG, "line %d: token must be either " - "RSA, PSK, EAP, or PIN", line_nr, token.len); - goto error; - } - } -error: - chunk_free_randomized(&chunk); - pthread_mutex_unlock(&(this->keys_mutex)); - } - else - { - DBG1(DBG_CFG, "could not open file '%s': %s", SECRETS_FILE, - strerror(errno)); - } -} - -/** - * Implementation of local_credential_store_t.destroy. - */ -static void destroy(private_local_credential_store_t *this) -{ - this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy)); - this->auth_certs->destroy_offset(this->auth_certs, offsetof(x509_t, destroy)); - this->ca_infos->destroy_offset(this->ca_infos, offsetof(ca_info_t, destroy)); - - pthread_mutex_lock(&(this->acerts_mutex)); - this->acerts->destroy_offset(this->acerts, offsetof(x509ac_t, destroy)); - pthread_mutex_unlock(&(this->acerts_mutex)); - - pthread_mutex_lock(&(this->keys_mutex)); - this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy)); - this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy); - this->eap_keys->destroy_function(this->eap_keys, (void*)shared_key_destroy); - pthread_mutex_unlock(&(this->keys_mutex)); - - free(this); -} - -/** - * Described in header. - */ -local_credential_store_t * local_credential_store_create(void) -{ - private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t); - - /* public functions */ - this->public.credential_store.get_shared_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_shared_key; - this->public.credential_store.get_eap_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_eap_key; - this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; - this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key; - this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate; - this->public.credential_store.get_auth_certificate = (x509_t* (*) (credential_store_t*,u_int,identification_t*))get_auth_certificate; - this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid; - this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,x509_t*))get_issuer; - this->public.credential_store.is_trusted = (bool (*) (credential_store_t*,const char*,x509_t*))is_trusted; - this->public.credential_store.rsa_signature = (status_t (*) (credential_store_t*,rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t*))rsa_signature; - this->public.credential_store.verify_signature = (status_t (*) (credential_store_t*,chunk_t,chunk_t,identification_t*,ca_info_t**))verify_signature; - this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify; - this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate; - this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate; - this->public.credential_store.add_ca_info = (ca_info_t* (*) (credential_store_t*,ca_info_t*))add_ca_info; - this->public.credential_store.release_ca_info = (status_t (*) (credential_store_t*,const char*))release_ca_info; - this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator; - this->public.credential_store.create_auth_cert_iterator = (iterator_t* (*) (credential_store_t*))create_auth_cert_iterator; - this->public.credential_store.create_cainfo_iterator = (iterator_t* (*) (credential_store_t*))create_cainfo_iterator; - this->public.credential_store.create_acert_iterator = (iterator_t* (*) (credential_store_t*))create_acert_iterator; - this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates; - this->public.credential_store.load_aa_certificates = (void (*) (credential_store_t*))load_aa_certificates; - this->public.credential_store.load_attr_certificates = (void (*) (credential_store_t*))load_attr_certificates; - this->public.credential_store.load_ocsp_certificates = (void (*) (credential_store_t*))load_ocsp_certificates; - this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls; - this->public.credential_store.load_secrets = (void (*) (credential_store_t*,bool))load_secrets; - this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy; - - /* initialize the mutexes */ - pthread_mutex_init(&(this->keys_mutex), NULL); - pthread_mutex_init(&(this->acerts_mutex), NULL); - - /* private variables */ - this->shared_keys = linked_list_create(); - this->eap_keys = linked_list_create(); - this->private_keys = linked_list_create(); - this->certs = linked_list_create(); - this->auth_certs = linked_list_create(); - this->ca_infos = linked_list_create(); - this->acerts = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/config/credentials/local_credential_store.h b/src/charon/config/credentials/local_credential_store.h deleted file mode 100644 index 87a12663a..000000000 --- a/src/charon/config/credentials/local_credential_store.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file local_credential_store.h - * - * @brief Interface of local_credential_store_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. - */ - -#ifndef LOCAL_CREDENTIAL_H_ -#define LOCAL_CREDENTIAL_H_ - -typedef struct local_credential_store_t local_credential_store_t; - -#include <library.h> -#include <credential_store.h> -#include <daemon.h> - - -/** - * @brief A credential_store_t implementation using simple credentail lists. - * - * The local_credential_store_t class implements the credential_store_t interface - * as simple as possible. The credentials are stored in lists, and are loaded from - * files on the disk. - * Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND. - * - * @b Constructors: - * - local_credential_store_create(bool strict) - * - * @ingroup config - */ -struct local_credential_store_t { - - /** - * Implements credential_store_t interface - */ - credential_store_t credential_store; -}; - -/** - * @brief Creates a local_credential_store_t instance. - * - * @return credential store instance. - * - * @ingroup config - */ -local_credential_store_t *local_credential_store_create(void); - -#endif /* LOCAL_CREDENTIAL_H_ */ diff --git a/src/charon/config/ike_cfg.c b/src/charon/config/ike_cfg.c index abb300aab..8beccdc29 100644 --- a/src/charon/config/ike_cfg.c +++ b/src/charon/config/ike_cfg.c @@ -1,10 +1,3 @@ -/** - * @file ike_cfg.c - * - * @brief Implementation of ike_cfg_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,12 +12,16 @@ * 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: ike_cfg.c 4062 2008-06-12 11:42:19Z martin $ */ #include "ike_cfg.h" #include <string.h> +#include <daemon.h> + typedef struct private_ike_cfg_t private_ike_cfg_t; @@ -46,12 +43,12 @@ struct private_ike_cfg_t { /** * Address of local host */ - host_t *my_host; + char *me; /** * Address of remote host */ - host_t *other_host; + char *other; /** * should we send a certificate request? @@ -86,19 +83,19 @@ static bool force_encap_meth(private_ike_cfg_t *this) } /** - * Implementation of ike_cfg_t.get_my_host. + * Implementation of ike_cfg_t.get_my_addr. */ -static host_t *get_my_host (private_ike_cfg_t *this) +static char *get_my_addr(private_ike_cfg_t *this) { - return this->my_host; + return this->me; } /** - * Implementation of ike_cfg_t.get_other_host. + * Implementation of ike_cfg_t.get_other_addr. */ -static host_t *get_other_host (private_ike_cfg_t *this) +static char *get_other_addr(private_ike_cfg_t *this) { - return this->other_host; + return this->other; } /** @@ -141,6 +138,7 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, stored_iter = this->proposals->create_iterator(this->proposals, TRUE); supplied_iter = proposals->create_iterator(proposals, TRUE); + /* compare all stored proposals with all supplied. Stored ones are preferred.*/ while (stored_iter->iterate(stored_iter, (void**)&stored)) { @@ -154,6 +152,9 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, /* they match, return */ stored_iter->destroy(stored_iter); supplied_iter->destroy(supplied_iter); + DBG2(DBG_CFG, "received proposals: %#P", proposals); + DBG2(DBG_CFG, "configured proposals: %#P", this->proposals); + DBG2(DBG_CFG, "selected proposal: %P", selected); return selected; } } @@ -161,6 +162,8 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ stored_iter->destroy(stored_iter); supplied_iter->destroy(supplied_iter); + DBG1(DBG_CFG, "received proposals: %#P", proposals); + DBG1(DBG_CFG, "configured proposals: %#P", this->proposals); return NULL; } @@ -170,30 +173,71 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, */ static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } /** + * Implementation of ike_cfg_t.equals. + */ +static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other) +{ + enumerator_t *e1, *e2; + proposal_t *p1, *p2; + bool eq = TRUE; + + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + if (this->proposals->get_count(this->proposals) != + other->proposals->get_count(other->proposals)) + { + return FALSE; + } + e1 = this->proposals->create_enumerator(this->proposals); + e2 = this->proposals->create_enumerator(this->proposals); + while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2)) + { + if (!p1->equals(p1, p2)) + { + eq = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + + return (eq && + this->certreq == other->certreq && + this->force_encap == other->force_encap && + streq(this->me, other->me) && + streq(this->other, other->other)); +} + +/** * Implementation of ike_cfg_t.get_ref. */ -static void get_ref(private_ike_cfg_t *this) +static ike_cfg_t* get_ref(private_ike_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -205,8 +249,8 @@ static void destroy(private_ike_cfg_t *this) { this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - this->my_host->destroy(this->my_host); - this->other_host->destroy(this->other_host); + free(this->me); + free(this->other); free(this); } } @@ -215,29 +259,29 @@ static void destroy(private_ike_cfg_t *this) * Described in header. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host) + char *me, char *other) { private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t); /* public functions */ this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq; this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth; - this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host; - this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host; + this->public.get_my_addr = (char*(*)(ike_cfg_t*))get_my_addr; + this->public.get_other_addr = (char*(*)(ike_cfg_t*))get_other_addr; this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal; this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals; this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal; this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group; - this->public.get_ref = (void(*)(ike_cfg_t*))get_ref; + this->public.equals = (bool(*)(ike_cfg_t*,ike_cfg_t*)) equals; + this->public.get_ref = (ike_cfg_t*(*)(ike_cfg_t*))get_ref; this->public.destroy = (void(*)(ike_cfg_t*))destroy; /* private variables */ this->refcount = 1; this->certreq = certreq; this->force_encap = force_encap; - this->my_host = my_host; - this->other_host = other_host; - + this->me = strdup(me); + this->other = strdup(other); this->proposals = linked_list_create(); return &this->public; diff --git a/src/charon/config/ike_cfg.h b/src/charon/config/ike_cfg.h index 5165d12a6..6169af96b 100644 --- a/src/charon/config/ike_cfg.h +++ b/src/charon/config/ike_cfg.h @@ -1,10 +1,3 @@ -/** - * @file ike_cfg.h - * - * @brief Interface of ike_cfg_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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: ike_cfg.h 4044 2008-06-06 15:05:54Z martin $ + */ + +/** + * @defgroup ike_cfg ike_cfg + * @{ @ingroup config */ #ifndef IKE_CFG_H_ @@ -34,128 +34,113 @@ typedef struct ike_cfg_t ike_cfg_t; #include <crypto/diffie_hellman.h> /** - * @brief An ike_cfg_t defines the rules to set up an IKE_SA. + * An ike_cfg_t defines the rules to set up an IKE_SA. * * @see peer_cfg_t to get an overview over the configurations. - * - * @b Constructors: - * - ike_cfg_create() - * - * @ingroup config */ struct ike_cfg_t { /** - * @brief Get own address. + * Get own address. * - * @param this calling object - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_my_host) (ike_cfg_t *this); + char* (*get_my_addr) (ike_cfg_t *this); /** - * @brief Get peers address. + * Get peers address. * - * @param this calling object - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_other_host) (ike_cfg_t *this); + char* (*get_other_addr) (ike_cfg_t *this); /** - * @brief Adds a proposal to the list. + * Adds a proposal to the list. * * The first added proposal has the highest priority, the last * added the lowest. * - * @param this calling object * @param proposal proposal to add */ void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal); /** - * @brief Returns a list of all supported proposals. + * Returns a list of all supported proposals. * * Returned list and its proposals must be destroyed after use. * - * @param this calling object * @return list containing all the proposals */ linked_list_t* (*get_proposals) (ike_cfg_t *this); /** - * @brief Select a proposed from suggested proposals. + * Select a proposed from suggested proposals. * * Returned proposal must be destroyed after use. * - * @param this calling object * @param proposals list of proposals to select from * @return selected proposal, or NULL if none matches. */ proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals); /** - * @brief Should we send a certificate request in IKE_SA_INIT? + * Should we send a certificate request in IKE_SA_INIT? * - * @param this calling object * @return certificate request sending policy */ bool (*send_certreq) (ike_cfg_t *this); /** - * @brief Enforce UDP encapsulation by faking NATD notifies? + * Enforce UDP encapsulation by faking NATD notifies? * - * @param this calling object * @return TRUE to enfoce UDP encapsulation */ bool (*force_encap) (ike_cfg_t *this); /** - * @brief Get the DH group to use for IKE_SA setup. + * Get the DH group to use for IKE_SA setup. * - * @param this calling object * @return dh group to use for initialization */ diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this); /** - * @brief Get a new reference to this ike_cfg. + * Check if two IKE configs are equal. * - * Get a new reference to this ike_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), + * @param other other to check for equality + * @return TRUE if other equal to this + */ + bool (*equals)(ike_cfg_t *this, ike_cfg_t *other); + + /** + * Increase reference count. * - * @param this calling object + * @return reference to this */ - void (*get_ref) (ike_cfg_t *this); + ike_cfg_t* (*get_ref) (ike_cfg_t *this); /** - * @brief Destroys a ike_cfg_t object. + * Destroys a ike_cfg_t object. * * Decrements the internal reference counter and * destroys the ike_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (ike_cfg_t *this); }; /** - * @brief Creates a ike_cfg_t object. + * Creates a ike_cfg_t object. * * Supplied hosts become owned by ike_cfg, the name gets cloned. * * @param name ike_cfg identifier * @param certreq TRUE to send a certificate request * @param force_encap enforce UDP encapsulation by faking NATD notify - * @param my_host host_t representing local address - * @param other_host host_t representing remote address + * @param me address/DNS name of local peer + * @param other address/DNS name of remote peer * @return ike_cfg_t object. - * - * @ingroup config */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host); + char *me, char *other); -#endif /* IKE_CFG_H_ */ +#endif /* IKE_CFG_H_ @} */ diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index 0b5d391c4..0e56759c2 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -1,12 +1,5 @@ -/** - * @file peer_cfg.c - * - * @brief Implementation of peer_cfg_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +13,8 @@ * 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: peer_cfg.c 4051 2008-06-10 09:08:27Z tobias $ */ #include <string.h> @@ -29,19 +24,23 @@ #include <utils/linked_list.h> #include <utils/identification.h> -#include <crypto/ietf_attr_list.h> ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND, "CERT_ALWAYS_SEND", "CERT_SEND_IF_ASKED", - "CERT_NEVER_SEND" + "CERT_NEVER_SEND", ); -ENUM(dpd_action_names, DPD_NONE, DPD_RESTART, - "DPD_NONE", - "DPD_CLEAR", - "DPD_ROUTE", - "DPD_RESTART" +ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP, + "UNIQUE_NO", + "UNIQUE_REPLACE", + "UNIQUE_KEEP", +); + +ENUM(config_auth_method_names, CONF_AUTH_PUBKEY, CONF_AUTH_EAP, + "CONF_AUTH_PUBKEY", + "CONF_AUTH_PSK", + "CONF_AUTH_EAP", ); typedef struct private_peer_cfg_t private_peer_cfg_t; @@ -97,29 +96,19 @@ struct private_peer_cfg_t { identification_t *other_id; /** - * we have a cert issued by this CA - */ - identification_t *my_ca; - - /** - * we require the other end to have a cert issued by this CA - */ - identification_t *other_ca; - - /** - * we require the other end to belong to at least one group + * should we send a certificate */ - linked_list_t *groups; + cert_policy_t cert_policy; /** - * should we send a certificate + * uniqueness of an IKE_SA */ - cert_policy_t cert_policy; + unique_policy_t unique; /** * Method to use for own authentication data */ - auth_method_t auth_method; + config_auth_method_t auth_method; /** * EAP type to use for peer authentication @@ -162,42 +151,42 @@ struct private_peer_cfg_t { u_int32_t over_time; /** - * What to do with an SA when other peer seams to be dead? + * DPD check intervall */ - bool dpd_delay; + u_int32_t dpd; /** - * What to do with CHILDren when other peer seams to be dead? + * virtual IP to use locally */ - bool dpd_action; + host_t *virtual_ip; /** - * virtual IP to use locally + * pool to acquire configuration attributes from */ - host_t *my_virtual_ip; + char *pool; /** - * virtual IP to use remotly + * required authorization constraints */ - host_t *other_virtual_ip; + auth_info_t *auth; -#ifdef P2P +#ifdef ME /** * Is this a mediation connection? */ - bool p2p_mediation; + bool mediation; /** * Name of the mediation connection to mediate through */ - peer_cfg_t *p2p_mediated_by; + peer_cfg_t *mediated_by; /** * ID of our peer at the mediation server (= leftid of the peer's conn with * the mediation server) */ identification_t *peer_id; -#endif /* P2P */ +#endif /* ME */ }; /** @@ -235,12 +224,26 @@ static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg) } /** - * Implementation of peer_cfg_t.create_child_cfg_iterator. + * Implementation of peer_cfg_t.remove_child_cfg. + */ +static void remove_child_cfg(private_peer_cfg_t *this, enumerator_t *enumerator) +{ + pthread_mutex_lock(&this->mutex); + this->child_cfgs->remove_at(this->child_cfgs, enumerator); + pthread_mutex_unlock(&this->mutex); +} + +/** + * Implementation of peer_cfg_t.create_child_cfg_enumerator. */ -static iterator_t* create_child_cfg_iterator(private_peer_cfg_t *this) +static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this) { - return this->child_cfgs->create_iterator_locked(this->child_cfgs, - &this->mutex); + enumerator_t *enumerator; + + pthread_mutex_lock(&this->mutex); + enumerator = this->child_cfgs->create_enumerator(this->child_cfgs); + return enumerator_create_cleaner(enumerator, + (void*)pthread_mutex_unlock, &this->mutex); } /** @@ -267,20 +270,19 @@ static child_cfg_t* select_child_cfg(private_peer_cfg_t *this, host_t *my_host, host_t *other_host) { child_cfg_t *current, *found = NULL; - iterator_t *iterator; + enumerator_t *enumerator; - iterator = create_child_cfg_iterator(this); - while (iterator->iterate(iterator, (void**)¤t)) + enumerator = create_child_cfg_enumerator(this); + while (enumerator->enumerate(enumerator, ¤t)) { if (contains_ts(current, TRUE, my_ts, my_host) && contains_ts(current, FALSE, other_ts, other_host)) { - found = current; - found->get_ref(found); + found = current->get_ref(current); break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return found; } @@ -301,47 +303,31 @@ static identification_t *get_other_id(private_peer_cfg_t *this) } /** - * Implementation of peer_cfg_t.get_my_ca - */ -static identification_t *get_my_ca(private_peer_cfg_t *this) -{ - return this->my_ca; -} - -/** - * Implementation of peer_cfg_t.get_other_ca - */ -static identification_t *get_other_ca(private_peer_cfg_t *this) -{ - return this->other_ca; -} - -/** - * Implementation of peer_cfg_t.get_groups + * Implementation of peer_cfg_t.get_cert_policy. */ -static linked_list_t *get_groups(private_peer_cfg_t *this) +static cert_policy_t get_cert_policy(private_peer_cfg_t *this) { - return this->groups; + return this->cert_policy; } /** - * Implementation of peer_cfg_t.get_cert_policy. + * Implementation of peer_cfg_t.get_unique_policy. */ -static cert_policy_t get_cert_policy(private_peer_cfg_t *this) +static unique_policy_t get_unique_policy(private_peer_cfg_t *this) { - return this->cert_policy; + return this->unique; } /** - * Implementation of connection_t.auth_method_t. + * Implementation of peer_cfg_t.get_auth_method. */ -static auth_method_t get_auth_method(private_peer_cfg_t *this) +static config_auth_method_t get_auth_method(private_peer_cfg_t *this) { return this->auth_method; } /** - * Implementation of connection_t.get_eap_type. + * Implementation of peer_cfg_t.get_eap_type. */ static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor) { @@ -350,7 +336,7 @@ static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor) } /** - * Implementation of connection_t.get_keyingtries. + * Implementation of peer_cfg_t.get_keyingtries. */ static u_int32_t get_keyingtries(private_peer_cfg_t *this) { @@ -406,60 +392,44 @@ static bool use_mobike(private_peer_cfg_t *this) } /** - * Implements peer_cfg_t.get_dpd_delay + * Implements peer_cfg_t.get_dpd */ -static u_int32_t get_dpd_delay(private_peer_cfg_t *this) +static u_int32_t get_dpd(private_peer_cfg_t *this) { - return this->dpd_delay; + return this->dpd; } /** - * Implements peer_cfg_t.get_dpd_action + * Implementation of peer_cfg_t.get_virtual_ip. */ -static dpd_action_t get_dpd_action(private_peer_cfg_t *this) +static host_t* get_virtual_ip(private_peer_cfg_t *this) { - return this->dpd_action; + return this->virtual_ip; } - + /** - * Implementation of peer_cfg_t.get_my_virtual_ip. + * Implementation of peer_cfg_t.get_pool. */ -static host_t* get_my_virtual_ip(private_peer_cfg_t *this) +static char* get_pool(private_peer_cfg_t *this) { - if (this->my_virtual_ip == NULL) - { - return NULL; - } - return this->my_virtual_ip->clone(this->my_virtual_ip); + return this->pool; } - + /** - * Implementation of peer_cfg_t.get_other_virtual_ip. + * Implementation of peer_cfg_t.get_auth. */ -static host_t* get_other_virtual_ip(private_peer_cfg_t *this, host_t *suggestion) +static auth_info_t* get_auth(private_peer_cfg_t *this) { - if (this->other_virtual_ip == NULL) - { /* disallow */ - return NULL; - } - if (!this->other_virtual_ip->is_anyaddr(this->other_virtual_ip)) - { /* force own configuration */ - return this->other_virtual_ip->clone(this->other_virtual_ip); - } - if (suggestion == NULL || suggestion->is_anyaddr(suggestion)) - { - return NULL; - } - return suggestion->clone(suggestion); + return this->auth; } -#ifdef P2P +#ifdef ME /** * Implementation of peer_cfg_t.is_mediation. */ static bool is_mediation(private_peer_cfg_t *this) { - return this->p2p_mediation; + return this->mediation; } /** @@ -467,11 +437,7 @@ static bool is_mediation(private_peer_cfg_t *this) */ static peer_cfg_t* get_mediated_by(private_peer_cfg_t *this) { - if (this->p2p_mediated_by) { - this->p2p_mediated_by->get_ref(this->p2p_mediated_by); - return this->p2p_mediated_by; - } - return NULL; + return this->mediated_by; } /** @@ -481,14 +447,61 @@ static identification_t* get_peer_id(private_peer_cfg_t *this) { return this->peer_id; } -#endif /* P2P */ +#endif /* ME */ + +/** + * Implementation of peer_cfg_t.equals. + */ +static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + + return ( + this->ike_version == other->ike_version && + this->my_id->equals(this->my_id, other->my_id) && + this->other_id->equals(this->other_id, other->other_id) && + this->cert_policy == other->cert_policy && + this->unique == other->unique && + this->auth_method == other->auth_method && + this->eap_type == other->eap_type && + this->eap_vendor == other->eap_vendor && + this->keyingtries == other->keyingtries && + this->use_mobike == other->use_mobike && + this->rekey_time == other->rekey_time && + this->reauth_time == other->reauth_time && + this->jitter_time == other->jitter_time && + this->over_time == other->over_time && + this->dpd == other->dpd && + (this->virtual_ip == other->virtual_ip || + (this->virtual_ip && other->virtual_ip && + this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) && + (this->pool == other->pool || + (this->pool && other->pool && streq(this->pool, other->pool))) && + this->auth->equals(this->auth, other->auth) +#ifdef ME + && this->mediation == other->mediation && + this->mediated_by == other->mediated_by && + (this->peer_id == other->peer_id || + (this->peer_id && other->peer_id && + this->peer_id->equals(this->peer_id, other->peer_id))) +#endif /* ME */ + ); +} /** * Implements peer_cfg_t.get_ref. */ -static void get_ref(private_peer_cfg_t *this) +static peer_cfg_t* get_ref(private_peer_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -502,16 +515,14 @@ static void destroy(private_peer_cfg_t *this) this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy)); this->my_id->destroy(this->my_id); this->other_id->destroy(this->other_id); - DESTROY_IF(this->my_ca); - DESTROY_IF(this->other_ca); - DESTROY_IF(this->my_virtual_ip); - DESTROY_IF(this->other_virtual_ip); -#ifdef P2P - DESTROY_IF(this->p2p_mediated_by); + DESTROY_IF(this->virtual_ip); + this->auth->destroy(this->auth); +#ifdef ME + DESTROY_IF(this->mediated_by); DESTROY_IF(this->peer_id); -#endif /* P2P */ - ietfAttr_list_destroy(this->groups); +#endif /* ME */ free(this->name); + free(this->pool); free(this); } } @@ -521,16 +532,14 @@ static void destroy(private_peer_cfg_t *this) */ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, identification_t *my_id, identification_t *other_id, - identification_t *my_ca, identification_t *other_ca, - linked_list_t *groups, cert_policy_t cert_policy, - auth_method_t auth_method, eap_type_t eap_type, + cert_policy_t cert_policy, unique_policy_t unique, + config_auth_method_t auth_method, eap_type_t eap_type, u_int32_t eap_vendor, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, - u_int32_t dpd_delay, dpd_action_t dpd_action, - host_t *my_virtual_ip, host_t *other_virtual_ip, - bool p2p_mediation, peer_cfg_t *p2p_mediated_by, + u_int32_t over_time, bool mobike, u_int32_t dpd, + host_t *virtual_ip, char *pool, + bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id) { private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t); @@ -540,32 +549,32 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version; this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg; this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg; - this->public.create_child_cfg_iterator = (iterator_t* (*) (peer_cfg_t *))create_child_cfg_iterator; + this->public.remove_child_cfg = (void(*)(peer_cfg_t*, enumerator_t*))remove_child_cfg; + this->public.create_child_cfg_enumerator = (enumerator_t* (*) (peer_cfg_t *))create_child_cfg_enumerator; this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg; this->public.get_my_id = (identification_t* (*)(peer_cfg_t*))get_my_id; this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id; - this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca; - this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca; - this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups; this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy; - this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method; + this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy; + this->public.get_auth_method = (config_auth_method_t (*) (peer_cfg_t *))get_auth_method; this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *,u_int32_t*))get_eap_type; this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries; this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time; this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time; this->public.get_over_time = (u_int32_t(*)(peer_cfg_t*))get_over_time; this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike; - this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay; - this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action; - this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip; - this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip; - this->public.get_ref = (void(*)(peer_cfg_t *))get_ref; + this->public.get_dpd = (u_int32_t (*) (peer_cfg_t *))get_dpd; + this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *))get_virtual_ip; + this->public.get_pool = (char*(*)(peer_cfg_t*))get_pool; + this->public.get_auth = (auth_info_t*(*)(peer_cfg_t*))get_auth; + this->public.equals = (bool(*)(peer_cfg_t*, peer_cfg_t *other))equals; + this->public.get_ref = (peer_cfg_t*(*)(peer_cfg_t *))get_ref; this->public.destroy = (void(*)(peer_cfg_t *))destroy; -#ifdef P2P +#ifdef ME this->public.is_mediation = (bool (*) (peer_cfg_t *))is_mediation; this->public.get_mediated_by = (peer_cfg_t* (*) (peer_cfg_t *))get_mediated_by; this->public.get_peer_id = (identification_t* (*) (peer_cfg_t *))get_peer_id; -#endif /* P2P */ +#endif /* ME */ /* apply init values */ this->name = strdup(name); @@ -575,10 +584,8 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, pthread_mutex_init(&this->mutex, NULL); this->my_id = my_id; this->other_id = other_id; - this->my_ca = my_ca; - this->other_ca = other_ca; - this->groups = groups; this->cert_policy = cert_policy; + this->unique = unique; this->auth_method = auth_method; this->eap_type = eap_type; this->eap_vendor = eap_vendor; @@ -596,16 +603,19 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->jitter_time = jitter_time; this->over_time = over_time; this->use_mobike = mobike; - this->dpd_delay = dpd_delay; - this->dpd_action = dpd_action; - this->my_virtual_ip = my_virtual_ip; - this->other_virtual_ip = other_virtual_ip; + this->dpd = dpd; + this->virtual_ip = virtual_ip; + this->pool = pool ? strdup(pool) : NULL; + this->auth = auth_info_create(); this->refcount = 1; -#ifdef P2P - this->p2p_mediation = p2p_mediation; - this->p2p_mediated_by = p2p_mediated_by; +#ifdef ME + this->mediation = mediation; + this->mediated_by = mediated_by; this->peer_id = peer_id; -#endif /* P2P */ +#else /* ME */ + DESTROY_IF(mediated_by); + DESTROY_IF(peer_id); +#endif /* ME */ return &this->public; } diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 7f1dbcab6..5662b48df 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -1,12 +1,5 @@ -/** - * @file peer_cfg.h - * - * @brief Interface of peer_cfg_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,32 +13,39 @@ * 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: peer_cfg.h 4054 2008-06-10 20:31:53Z andreas $ + */ + +/** + * @defgroup peer_cfg peer_cfg + * @{ @ingroup config */ #ifndef PEER_CFG_H_ #define PEER_CFG_H_ -typedef enum dpd_action_t dpd_action_t; typedef enum cert_policy_t cert_policy_t; +typedef enum unique_policy_t unique_policy_t; +typedef enum config_auth_method_t config_auth_method_t; typedef struct peer_cfg_t peer_cfg_t; #include <library.h> #include <utils/identification.h> -#include <utils/linked_list.h> +#include <utils/enumerator.h> #include <config/traffic_selector.h> #include <config/proposal.h> #include <config/ike_cfg.h> #include <config/child_cfg.h> #include <sa/authenticators/authenticator.h> #include <sa/authenticators/eap/eap_method.h> +#include <credentials/auth_info.h> /** * Certificate sending policy. This is also used for certificate * requests when using this definition for the other peer. If * it is CERT_NEVER_SEND, a certreq is omitted, otherwise its * included. - * - * @ingroup config * * @warning These definitions must be the same as in pluto/starter, * as they are sent over the stroke socket. @@ -61,36 +61,45 @@ enum cert_policy_t { /** * enum strings for cert_policy_t - * - * @ingroup config */ extern enum_name_t *cert_policy_names; /** - * @brief Actions to take when a peer does not respond (dead peer detected). - * - * These values are the same as in pluto/starter, so do not modify them! - * - * @ingroup config + * Uniqueness of an IKE_SA, used to drop multiple connections with one peer. */ -enum dpd_action_t { - /** DPD disabled */ - DPD_NONE, - /** remove CHILD_SAs without replacement */ - DPD_CLEAR, - /** route the CHILD_SAs to resetup when needed */ - DPD_ROUTE, - /** restart CHILD_SAs in a new IKE_SA, immediately */ - DPD_RESTART, +enum unique_policy_t { + /** do not check for client uniqueness */ + UNIQUE_NO, + /** replace unique IKE_SAs if new ones get established */ + UNIQUE_REPLACE, + /** keep existing IKE_SAs, close the new ones on connection attept */ + UNIQUE_KEEP, }; /** - * enum names for dpd_action_t. + * enum strings for unique_policy_t */ -extern enum_name_t *dpd_action_names; +extern enum_name_t *unique_policy_names; /** - * @brief Configuration of a peer, specified by IDs. + * Authentication method for this IKE_SA. + */ +enum config_auth_method_t { + /** authentication using public keys (RSA, ECDSA) */ + CONF_AUTH_PUBKEY = 1, + /** authentication using a pre-shared secret */ + CONF_AUTH_PSK = 2, + /** authentication using EAP */ + CONF_AUTH_EAP = 3, +}; + +/** + * enum strings for config_auth_method_t + */ +extern enum_name_t *config_auth_method_names; + +/** + * Configuration of a peer, specified by IDs. * * The peer config defines a connection between two given IDs. It contains * exactly one ike_cfg_t, which is use for initiation. Additionally, it contains @@ -106,61 +115,67 @@ extern enum_name_t *dpd_action_names; | - ... | | - dpd config | | - ... |-+ +---------------+ | - ... | +---------------+ +-------------------+ + ^ + | + +-------------------+ + | auth_info | + +-------------------+ + | auth_items | + +-------------------+ @endverbatim - * - * @b Constructors: - * - peer_cfg_create() - * - * @ingroup config + * The auth_info_t object associated to the peer_cfg holds additional + * authorization constraints. A peer who wants to use a config needs to fullfil + * the requirements defined in auth_info. */ struct peer_cfg_t { /** - * @brief Get the name of the peer_cfg. + * Get the name of the peer_cfg. * * Returned object is not getting cloned. * - * @param this calling object * @return peer_cfg's name */ char* (*get_name) (peer_cfg_t *this); /** - * @brief Get the IKE version to use for initiating. + * Get the IKE version to use for initiating. * - * @param this calling object * @return IKE major version */ u_int (*get_ike_version)(peer_cfg_t *this); /** - * @brief Get the IKE config to use for initiaton. + * Get the IKE config to use for initiaton. * - * @param this calling object * @return the IKE config to use */ ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this); /** - * @brief Attach a CHILD config. + * Attach a CHILD config. * - * @param this calling object * @param child_cfg CHILD config to add */ void (*add_child_cfg) (peer_cfg_t *this, child_cfg_t *child_cfg); /** - * @brief Create an iterator for all attached CHILD configs. + * Detach a CHILD config, pointed to by an enumerator. + * + * @param enumerator enumerator indicating element position + */ + void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator); + + /** + * Create an enumerator for all attached CHILD configs. * - * @param this calling object - * @return an iterator over all CHILD configs. + * @return an enumerator over all CHILD configs. */ - iterator_t* (*create_child_cfg_iterator) (peer_cfg_t *this); + enumerator_t* (*create_child_cfg_enumerator) (peer_cfg_t *this); /** - * @brief Select a CHILD config from traffic selectors. + * Select a CHILD config from traffic selectors. * - * @param this calling object * @param my_ts TS for local side * @param other_ts TS for remote side * @param my_host host to narrow down dynamic TS for local side @@ -172,213 +187,176 @@ struct peer_cfg_t { host_t *other_host); /** - * @brief Get own ID. + * Get the authentication constraint items. + * + * @return auth_info object to manipulate requirements + */ + auth_info_t* (*get_auth)(peer_cfg_t *this); + + /** + * Get own ID. * - * @param this calling object * @return own id */ identification_t* (*get_my_id)(peer_cfg_t *this); /** - * @brief Get peers ID. + * Get peers ID. * - * @param this calling object * @return other id */ identification_t* (*get_other_id)(peer_cfg_t *this); - - /** - * @brief Get own CA. - * - * @param this calling object - * @return own ca - */ - identification_t* (*get_my_ca)(peer_cfg_t *this); /** - * @brief Get peer CA. - * - * @param this calling object - * @return other ca - */ - identification_t* (*get_other_ca)(peer_cfg_t *this); - - /** - * @brief Get list of group attributes. - * - * @param this calling object - * @return linked list of group attributes + * Should be sent a certificate for this connection? + * + * @return certificate sending policy */ - linked_list_t* (*get_groups)(peer_cfg_t *this); + cert_policy_t (*get_cert_policy) (peer_cfg_t *this); /** - * @brief Should be sent a certificate for this connection? + * How to handle uniqueness of IKE_SAs? * - * @param this calling object - * @return certificate sending policy + * @return unique policy */ - cert_policy_t (*get_cert_policy) (peer_cfg_t *this); + unique_policy_t (*get_unique_policy) (peer_cfg_t *this); /** - * @brief Get the authentication method to use to authenticate us. + * Get the authentication method to use to authenticate us. * - * @param this calling object * @return authentication method */ - auth_method_t (*get_auth_method) (peer_cfg_t *this); + config_auth_method_t (*get_auth_method) (peer_cfg_t *this); /** - * @brief Get the EAP type to use for peer authentication. + * Get the EAP type to use for peer authentication. * * If vendor specific types are used, a vendor ID != 0 is returned to * to vendor argument. Then the returned type is specific for that * vendor ID. * - * @param this calling object * @param vendor receives vendor specifier, 0 for predefined EAP types * @return authentication method */ eap_type_t (*get_eap_type) (peer_cfg_t *this, u_int32_t *vendor); /** - * @brief Get the max number of retries after timeout. + * Get the max number of retries after timeout. * - * @param this calling object * @return max number retries */ u_int32_t (*get_keyingtries) (peer_cfg_t *this); /** - * @brief Get a time to start rekeying (is randomized with jitter). + * Get a time to start rekeying (is randomized with jitter). * - * @param this calling object * @return time in s when to start rekeying, 0 disables rekeying */ u_int32_t (*get_rekey_time)(peer_cfg_t *this); /** - * @brief Get a time to start reauthentication (is randomized with jitter). + * Get a time to start reauthentication (is randomized with jitter). * - * @param this calling object * @return time in s when to start reauthentication, 0 disables it */ u_int32_t (*get_reauth_time)(peer_cfg_t *this); /** - * @brief Get the timeout of a rekeying/reauthenticating SA. + * Get the timeout of a rekeying/reauthenticating SA. * - * @param thsi calling object * @return timeout in s */ u_int32_t (*get_over_time)(peer_cfg_t *this); /** - * @brief Use MOBIKE (RFC4555) if peer supports it? + * Use MOBIKE (RFC4555) if peer supports it? * - * @param this calling object * @return TRUE to enable MOBIKE support */ bool (*use_mobike) (peer_cfg_t *this); /** - * @brief Get the DPD check interval. + * Get the DPD check interval. * - * @param this calling object * @return dpd_delay in seconds */ - u_int32_t (*get_dpd_delay) (peer_cfg_t *this); + u_int32_t (*get_dpd) (peer_cfg_t *this); /** - * @brief What should be done with a CHILD_SA, when other peer does not respond. - * - * @param this calling object - * @return dpd action - */ - dpd_action_t (*get_dpd_action) (peer_cfg_t *this); - - /** - * @brief Get a virtual IP for the local peer. + * Get a virtual IP for the local peer. * * If no virtual IP should be used, NULL is returned. %any means to request * a virtual IP using configuration payloads. A specific address is also * used for a request and may be changed by the server. * - * @param this peer_cfg * @param suggestion NULL, %any or specific - * @return clone of an IP, %any or NULL + * @return virtual IP, %any or NULL */ - host_t* (*get_my_virtual_ip) (peer_cfg_t *this); + host_t* (*get_virtual_ip) (peer_cfg_t *this); /** - * @brief Get a virtual IP for the remote peer. - * - * An IP may be supplied, if one was requested by the initiator. However, - * the suggestion is not more as it says, any address may be returned, even - * NULL to not use virtual IPs. + * Get the name of the pool to acquire configuration attributes from. * - * @param this peer_cfg - * @param suggestion NULL, %any or specific - * @return clone of an IP to use + * @return pool name, NULL if none defined */ - host_t* (*get_other_virtual_ip) (peer_cfg_t *this, host_t *suggestion); - -#ifdef P2P + char* (*get_pool)(peer_cfg_t *this); + +#ifdef ME /** - * @brief Is this a mediation connection? + * Is this a mediation connection? * - * @param this peer_cfg * @return TRUE, if this is a mediation connection */ bool (*is_mediation) (peer_cfg_t *this); /** - * @brief Get peer_cfg of the connection this one is mediated through. + * Get peer_cfg of the connection this one is mediated through. * - * @param this peer_cfg - * @return reference to peer_cfg of the mediation connection + * @return the peer_cfg of the mediation connection */ peer_cfg_t* (*get_mediated_by) (peer_cfg_t *this); /** - * @brief Get the id of the other peer at the mediation server. + * Get the id of the other peer at the mediation server. * * This is the leftid of the peer's connection with the mediation server. * * If it is not configured, it is assumed to be the same as the right id * of this connection. * - * @param this peer_cfg * @return the id of the other peer */ identification_t* (*get_peer_id) (peer_cfg_t *this); -#endif /* P2P */ +#endif /* ME */ + + /** + * Check if two peer configurations are equal. + * + * This method does not compare associated ike/child_cfg. + * + * @param other candidate to check for equality against this + * @return TRUE if peer_cfg and ike_cfg are equal + */ + bool (*equals)(peer_cfg_t *this, peer_cfg_t *other); /** - * @brief Get a new reference. + * Increase reference count. * - * Get a new reference to this peer_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), - * - * @param this calling object + * @return reference to this */ - void (*get_ref) (peer_cfg_t *this); + peer_cfg_t* (*get_ref) (peer_cfg_t *this); /** - * @brief Destroys the peer_cfg object. + * Destroys the peer_cfg object. * * Decrements the internal reference counter and * destroys the peer_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (peer_cfg_t *this); }; /** - * @brief Create a configuration object for IKE_AUTH and later. + * Create a configuration object for IKE_AUTH and later. * * name-string gets cloned, ID's not. * Virtual IPs are used if they are != NULL. A %any host means the virtual @@ -392,10 +370,8 @@ struct peer_cfg_t { * @param ike_cfg IKE config to use when acting as initiator * @param my_id identification_t for ourselves * @param other_id identification_t for the remote guy - * @param my_ca CA to use for us - * @param other_ca CA to use for other - * @param groups list of group memberships * @param cert_policy should we send a certificate payload? + * @param unique uniqueness of an IKE_SA * @param auth_method auth method to use to authenticate us * @param eap_type EAP type to use for peer authentication * @param eap_vendor EAP vendor identifier, if vendor specific type is used @@ -406,29 +382,24 @@ struct peer_cfg_t { * @param over_time maximum overtime before closing a rekeying/reauth SA * @param reauth sould be done reauthentication instead of rekeying? * @param mobike use MOBIKE (RFC4555) if peer supports it - * @param dpd_delay after how many seconds of inactivity to check DPD - * @param dpd_action what to do with CHILD_SAs when detected a dead peer - * @param my_virtual_ip virtual IP for local host, or NULL - * @param other_virtual_ip virtual IP for remote host, or NULL - * @param p2p_mediation TRUE if this is a mediation connection - * @param p2p_mediated_by name of the mediation connection to mediate through + * @param dpd DPD check interval, 0 to disable + * @param virtual_ip virtual IP for local host, or NULL + * @param pool pool name to get configuration attributes from, or NULL + * @param mediation TRUE if this is a mediation connection + * @param mediated_by peer_cfg_t of the mediation connection to mediate through * @param peer_id ID that identifies our peer at the mediation server * @return peer_cfg_t object - * - * @ingroup config */ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg, identification_t *my_id, identification_t *other_id, - identification_t *my_ca, identification_t *other_ca, - linked_list_t *groups, cert_policy_t cert_policy, - auth_method_t auth_method, eap_type_t eap_type, + cert_policy_t cert_policy, unique_policy_t unique, + config_auth_method_t auth_method, eap_type_t eap_type, u_int32_t eap_vendor, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, - u_int32_t dpd_delay, dpd_action_t dpd_action, - host_t *my_virtual_ip, host_t *other_virtual_ip, - bool p2p_mediation, peer_cfg_t *p2p_mediated_by, + u_int32_t over_time, bool mobike, u_int32_t dpd, + host_t *virtual_ip, char *pool, + bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id); -#endif /* PEER_CFG_H_ */ +#endif /* PEER_CFG_H_ @} */ diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c index cff9859c1..803cf8ae4 100644 --- a/src/charon/config/proposal.c +++ b/src/charon/config/proposal.c @@ -1,11 +1,5 @@ -/** - * @file proposal.c - * - * @brief Implementation of proposal_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -18,6 +12,8 @@ * 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: proposal.c 4062 2008-06-12 11:42:19Z martin $ */ #include <string.h> @@ -51,11 +47,12 @@ ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, ENUM_END(transform_type_names, EXTENDED_SEQUENCE_NUMBERS); ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, - "NO_EXT_SEQ_NUMBERS", - "EXT_SEQ_NUMBERS", + "NO_EXT_SEQ", + "EXT_SEQ", ); typedef struct private_proposal_t private_proposal_t; +typedef struct algorithm_t algorithm_t; /** * Private data of an proposal_t object @@ -104,9 +101,24 @@ struct private_proposal_t { }; /** + * Struct used to store different kinds of algorithms. + */ +struct algorithm_t { + /** + * Value from an encryption_algorithm_t/integrity_algorithm_t/... + */ + u_int16_t algorithm; + + /** + * the associated key size in bits, or zero if not needed + */ + u_int16_t key_size; +}; + +/** * Add algorithm/keysize to a algorithm list */ -static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) +static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size) { algorithm_t *algo_key; @@ -119,7 +131,8 @@ static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) /** * Implements proposal_t.add_algorithm */ -static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int16_t algo, size_t key_size) +static void add_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t algo, u_int16_t key_size) { switch (type) { @@ -144,41 +157,68 @@ static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int } /** - * Implements proposal_t.create_algorithm_iterator. + * filter function for peer configs + */ +static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg, + void **unused, u_int16_t *key_size) +{ + algorithm_t *algo = *in; + *alg = algo->algorithm; + if (key_size) + { + *key_size = algo->key_size; + } + return TRUE; +} + +/** + * Implements proposal_t.create_enumerator. */ -static iterator_t *create_algorithm_iterator(private_proposal_t *this, transform_type_t type) +static enumerator_t *create_enumerator(private_proposal_t *this, + transform_type_t type) { + linked_list_t *list; + switch (type) { case ENCRYPTION_ALGORITHM: - return this->encryption_algos->create_iterator(this->encryption_algos, TRUE); + list = this->encryption_algos; + break; case INTEGRITY_ALGORITHM: - return this->integrity_algos->create_iterator(this->integrity_algos, TRUE); + list = this->integrity_algos; + break; case PSEUDO_RANDOM_FUNCTION: - return this->prf_algos->create_iterator(this->prf_algos, TRUE); + list = this->prf_algos; + break; case DIFFIE_HELLMAN_GROUP: - return this->dh_groups->create_iterator(this->dh_groups, TRUE); + list = this->dh_groups; + break; case EXTENDED_SEQUENCE_NUMBERS: - return this->esns->create_iterator(this->esns, TRUE); - default: + list = this->esns; break; + default: + return NULL; } - return NULL; + return enumerator_create_filter(list->create_enumerator(list), + (void*)alg_filter, NULL, NULL); } /** * Implements proposal_t.get_algorithm. */ -static bool get_algorithm(private_proposal_t *this, transform_type_t type, algorithm_t** algo) +static bool get_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size) { - iterator_t *iterator = create_algorithm_iterator(this, type); - if (iterator->iterate(iterator, (void**)algo)) + enumerator_t *enumerator; + bool found = FALSE; + + enumerator = create_enumerator(this, type); + if (enumerator->enumerate(enumerator, alg, key_size)) { - iterator->destroy(iterator); - return TRUE; + found = TRUE; } - iterator->destroy(iterator); - return FALSE; + enumerator->destroy(enumerator); + return found; } /** @@ -186,14 +226,15 @@ static bool get_algorithm(private_proposal_t *this, transform_type_t type, algor */ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) { - algorithm_t *current; - iterator_t *iterator; bool result = FALSE; - iterator = this->dh_groups->create_iterator(this->dh_groups, TRUE); - if (iterator->get_count(iterator)) + if (this->dh_groups->get_count(this->dh_groups)) { - while (iterator->iterate(iterator, (void**)¤t)) + algorithm_t *current; + enumerator_t *enumerator; + + enumerator = this->dh_groups->create_enumerator(this->dh_groups); + while (enumerator->enumerate(enumerator, (void**)¤t)) { if (current->algorithm == group) { @@ -201,22 +242,54 @@ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) break; } } + enumerator->destroy(enumerator); } else if (group == MODP_NONE) { result = TRUE; } - iterator->destroy(iterator); return result; } /** + * Implementation of proposal_t.strip_dh. + */ +static void strip_dh(private_proposal_t *this) +{ + algorithm_t *alg; + + while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS) + { + free(alg); + } +} + +/** + * Returns true if the given alg is an authenticated encryption algorithm + */ +static bool is_authenticated_encryption(u_int16_t alg) +{ + switch(alg) + { + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + return TRUE; + } + return FALSE; +} + +/** * Find a matching alg/keysize in two linked lists */ -static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size) +static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, + u_int16_t *alg, size_t *key_size) { - iterator_t *first_iter, *second_iter; - algorithm_t *first_alg, *second_alg; + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; /* if in both are zero algorithms specified, we HAVE a match */ if (first->get_count(first) == 0 && second->get_count(second) == 0) @@ -225,30 +298,31 @@ static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, return TRUE; } - first_iter = first->create_iterator(first, TRUE); - second_iter = second->create_iterator(second, TRUE); + e1 = first->create_enumerator(first); + e2 = second->create_enumerator(second); /* compare algs, order of algs in "first" is preferred */ - while (first_iter->iterate(first_iter, (void**)&first_alg)) + while (e1->enumerate(e1, &alg1)) { - second_iter->reset(second_iter); - while (second_iter->iterate(second_iter, (void**)&second_alg)) + e2->destroy(e2); + e2 = second->create_enumerator(second); + while (e2->enumerate(e2, &alg2)) { - if (first_alg->algorithm == second_alg->algorithm && - first_alg->key_size == second_alg->key_size) + if (alg1->algorithm == alg2->algorithm && + alg1->key_size == alg2->key_size) { /* ok, we have an algorithm */ - *alg = first_alg->algorithm; - *key_size = first_alg->key_size; + *alg = alg1->algorithm; + *key_size = alg1->key_size; *add = TRUE; - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return TRUE; } } } /* no match in all comparisons */ - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return FALSE; } @@ -274,45 +348,57 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t selected = proposal_create(this->protocol); /* select encryption algorithm */ - if (select_algo(this->encryption_algos, other->encryption_algos, &add, &algo, &key_size)) + if (select_algo(this->encryption_algos, other->encryption_algos, + &add, &algo, &key_size)) { if (add) { - selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, algo, key_size); + selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, + algo, key_size); } } else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable ENCRYPTION_ALGORITHM found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, ENCRYPTION_ALGORITHM); return NULL; } /* select integrity algorithm */ - if (select_algo(this->integrity_algos, other->integrity_algos, &add, &algo, &key_size)) + if (!is_authenticated_encryption(algo)) { - if (add) + if (select_algo(this->integrity_algos, other->integrity_algos, + &add, &algo, &key_size)) { - selected->add_algorithm(selected, INTEGRITY_ALGORITHM, algo, key_size); + if (add) + { + selected->add_algorithm(selected, INTEGRITY_ALGORITHM, + algo, key_size); + } + } + else + { + selected->destroy(selected); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, INTEGRITY_ALGORITHM); + return NULL; } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable INTEGRITY_ALGORITHM found, skipping"); - return NULL; } /* select prf algorithm */ - if (select_algo(this->prf_algos, other->prf_algos, &add, &algo, &key_size)) + if (select_algo(this->prf_algos, other->prf_algos, + &add, &algo, &key_size)) { if (add) { - selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, algo, key_size); + selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, + algo, key_size); } } else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable PSEUDO_RANDOM_FUNCTION found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, PSEUDO_RANDOM_FUNCTION); return NULL; } /* select a DH-group */ @@ -326,7 +412,8 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable DIFFIE_HELLMAN_GROUP found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, DIFFIE_HELLMAN_GROUP); return NULL; } /* select if we use ESNs */ @@ -340,7 +427,8 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable EXTENDED_SEQUENCE_NUMBERS found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, EXTENDED_SEQUENCE_NUMBERS); return NULL; } DBG2(DBG_CFG, " proposal matches"); @@ -382,14 +470,67 @@ static u_int64_t get_spi(private_proposal_t *this) static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) { algorithm_t *algo, *clone_algo; - iterator_t *iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator_t *enumerator; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &algo)) { clone_algo = malloc_thing(algorithm_t); memcpy(clone_algo, algo, sizeof(algorithm_t)); clone_list->insert_last(clone_list, (void*)clone_algo); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); +} + +/** + * check if an algorithm list equals + */ +static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2) +{ + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; + bool equals = TRUE; + + if (l1->get_count(l1) != l2->get_count(l2)) + { + return FALSE; + } + + e1 = l1->create_enumerator(l1); + e2 = l2->create_enumerator(l2); + while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2)) + { + if (alg1->algorithm != alg2->algorithm || + alg1->key_size != alg2->key_size) + { + equals = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + return equals; +} + +/** + * Implementation of proposal_t.equals. + */ +static bool equals(private_proposal_t *this, private_proposal_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + return ( + algo_list_equals(this->encryption_algos, other->encryption_algos) && + algo_list_equals(this->integrity_algos, other->integrity_algos) && + algo_list_equals(this->prf_algos, other->prf_algos) && + algo_list_equals(this->dh_groups, other->dh_groups) && + algo_list_equals(this->esns, other->esns)); } /** @@ -411,6 +552,38 @@ static proposal_t *clone_(private_proposal_t *this) } /** + * Checks the proposal read from a string. + */ +static void check_proposal(private_proposal_t *this) +{ + enumerator_t *e; + algorithm_t *alg; + bool all_aead = TRUE; + + e = this->encryption_algos->create_enumerator(this->encryption_algos); + while (e->enumerate(e, &alg)) + { + if (!is_authenticated_encryption(alg->algorithm)) + { + all_aead = FALSE; + break; + } + } + e->destroy(e); + + if (all_aead) + { + /* if all encryption algorithms in the proposal are authenticated encryption + * algorithms we MUST NOT propose any integrity algorithms */ + while (this->integrity_algos->remove_last(this->integrity_algos, + (void**)&alg) == SUCCESS) + { + free(alg); + } + } +} + +/** * add a algorithm identified by a string to the proposal. * TODO: we could use gperf here. */ @@ -432,6 +605,70 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) { add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); } + else if (strstr(alg.ptr, "ccm")) + { + u_int16_t key_size, icv_size; + + if (sscanf(alg.ptr, "aes%huccm%hu", &key_size, &icv_size) == 2) + { + if (key_size == 128 || key_size == 192 || key_size == 256) + { + switch (icv_size) + { + case 8: /* octets */ + case 64: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV8, key_size); + break; + case 12: /* octets */ + case 96: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV12, key_size); + break; + case 16: /* octets */ + case 128: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV16, key_size); + break; + default: + /* invalid ICV size */ + break; + } + } + } + } + else if (strstr(alg.ptr, "gcm")) + { + u_int16_t key_size, icv_size; + + if (sscanf(alg.ptr, "aes%hugcm%hu", &key_size, &icv_size) == 2) + { + if (key_size == 128 || key_size == 192 || key_size == 256) + { + switch (icv_size) + { + case 8: /* octets */ + case 64: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV8, key_size); + break; + case 12: /* octets */ + case 96: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV12, key_size); + break; + case 16: /* octets */ + case 128: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV16, key_size); + break; + default: + /* invalid ICV size */ + break; + } + } + } + } else if (strncmp(alg.ptr, "3des", alg.len) == 0) { add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); @@ -499,7 +736,7 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); if (this->protocol == PROTO_IKE) { - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, AUTH_AES_XCBC_96, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0); } } else if (strncmp(alg.ptr, "modp768", alg.len) == 0) @@ -526,6 +763,26 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) { add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); } + else if (strncmp(alg.ptr, "ecp192", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp224", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp256", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp384", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp521", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0); + } else { return FAILED; @@ -534,6 +791,109 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) } /** + * print all algorithms of a kind to stream + */ +static int print_alg(private_proposal_t *this, FILE *stream, u_int kind, + void *names, bool *first) +{ + enumerator_t *enumerator; + size_t written = 0; + u_int16_t alg, size; + + enumerator = create_enumerator(this, kind); + while (enumerator->enumerate(enumerator, &alg, &size)) + { + if (*first) + { + written += fprintf(stream, "%N", names, alg); + *first = FALSE; + } + else + { + written += fprintf(stream, "/%N", names, alg); + } + if (size) + { + written += fprintf(stream, "-%d", size); + } + } + enumerator->destroy(enumerator); + return written; +} + +/** + * output handler in printf() + */ +static int print(FILE *stream, const struct printf_info *info, + const void *const *args) +{ + private_proposal_t *this = *((private_proposal_t**)(args[0])); + linked_list_t *list = *((linked_list_t**)(args[0])); + enumerator_t *enumerator; + size_t written = 0; + bool first = TRUE; + + if (this == NULL) + { + return fprintf(stream, "(null)"); + } + + if (info->alt) + { + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &this)) + { /* call recursivly */ + if (first) + { + written += fprintf(stream, "%P", this); + first = FALSE; + } + else + { + written += fprintf(stream, ", %P", this); + } + } + enumerator->destroy(enumerator); + return written; + } + + written = fprintf(stream, "%N:", protocol_id_names, this->protocol); + written += print_alg(this, stream, ENCRYPTION_ALGORITHM, + encryption_algorithm_names, &first); + written += print_alg(this, stream, INTEGRITY_ALGORITHM, + integrity_algorithm_names, &first); + written += print_alg(this, stream, PSEUDO_RANDOM_FUNCTION, + pseudo_random_function_names, &first); + written += print_alg(this, stream, DIFFIE_HELLMAN_GROUP, + diffie_hellman_group_names, &first); + written += print_alg(this, stream, EXTENDED_SEQUENCE_NUMBERS, + extended_sequence_numbers_names, &first); + return written; +} + +/** + * arginfo handler for printf() proposal + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * return printf hook functions for a proposal + */ +printf_hook_functions_t proposal_get_printf_hooks() +{ + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; +} + +/** * Implements proposal_t.destroy. */ static void destroy(private_proposal_t *this) @@ -553,14 +913,16 @@ proposal_t *proposal_create(protocol_id_t protocol) { private_proposal_t *this = malloc_thing(private_proposal_t); - this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,size_t))add_algorithm; - this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,transform_type_t))create_algorithm_iterator; - this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,algorithm_t**))get_algorithm; + this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm; + this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator; + this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm; this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group; + this->public.strip_dh = (void(*)(proposal_t*))strip_dh; this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol; this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi; this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi; + this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals; this->public.clone = (proposal_t*(*)(proposal_t*))clone_; this->public.destroy = (void(*)(proposal_t*))destroy; @@ -590,17 +952,19 @@ proposal_t *proposal_create_default(protocol_id_t protocol) add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0); - add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); @@ -662,6 +1026,8 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs return NULL; } + check_proposal(this); + if (protocol == PROTO_AH || protocol == PROTO_ESP) { add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h index 379550f44..fb7dc9dfa 100644 --- a/src/charon/config/proposal.h +++ b/src/charon/config/proposal.h @@ -1,10 +1,3 @@ -/** - * @file proposal.h - * - * @brief Interface of proposal_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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: proposal.h 4062 2008-06-12 11:42:19Z martin $ + */ + +/** + * @defgroup proposal proposal + * @{ @ingroup config */ #ifndef PROPOSAL_H_ @@ -26,7 +26,6 @@ typedef enum protocol_id_t protocol_id_t; typedef enum transform_type_t transform_type_t; typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; -typedef struct algorithm_t algorithm_t; typedef struct proposal_t proposal_t; #include <library.h> @@ -40,8 +39,6 @@ typedef struct proposal_t proposal_t; /** * Protocol ID of a proposal. - * - * @ingroup config */ enum protocol_id_t { PROTO_NONE = 0, @@ -52,16 +49,12 @@ enum protocol_id_t { /** * enum names for protocol_id_t - * - * @ingroup config */ extern enum_name_t *protocol_id_names; /** * Type of a transform, as in IKEv2 RFC 3.3.2. - * - * @ingroup config */ enum transform_type_t { UNDEFINED_TRANSFORM_TYPE = 241, @@ -74,16 +67,12 @@ enum transform_type_t { /** * enum names for transform_type_t. - * - * @ingroup config */ extern enum_name_t *transform_type_names; /** * Extended sequence numbers, as in IKEv2 RFC 3.3.2. - * - * @ingroup config */ enum extended_sequence_numbers_t { NO_EXT_SEQ_NUMBERS = 0, @@ -92,48 +81,21 @@ enum extended_sequence_numbers_t { /** * enum strings for extended_sequence_numbers_t. - * - * @ingroup config */ extern enum_name_t *extended_sequence_numbers_names; - - -/** - * Struct used to store different kinds of algorithms. The internal - * lists of algorithms contain such structures. - * - * @ingroup config - */ -struct algorithm_t { - /** - * Value from an encryption_algorithm_t/integrity_algorithm_t/... - */ - u_int16_t algorithm; - - /** - * the associated key size in bits, or zero if not needed - */ - u_int16_t key_size; -}; - /** - * @brief Stores a set of algorithms used for an SA. + * Stores a set of algorithms used for an SA. * * A proposal stores algorithms for a specific * protocol. It can store algorithms for one protocol. * Proposals with multiple protocols are not supported, * as it's not specified in RFC4301 anymore. - * - * @b Constructors: - * - proposal_create() - * - * @ingroup config */ struct proposal_t { /** - * @brief Add an algorithm to the proposal. + * Add an algorithm to the proposal. * * The algorithms are stored by priority, first added * is the most preferred. @@ -144,120 +106,119 @@ struct proposal_t { * integrity_algorithm_t, dh_group_number_t and * extended_sequence_numbers_t. * - * @param this calling object - * @param type kind of algorithm - * @param alg identifier for algorithm - * @param key_size key size to use + * @param type kind of algorithm + * @param alg identifier for algorithm + * @param key_size key size to use */ - void (*add_algorithm) (proposal_t *this, transform_type_t type, u_int16_t alg, size_t key_size); + void (*add_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t alg, u_int16_t key_size); /** - * @brief Get an iterator over algorithms for a specifc algo type. + * Get an enumerator over algorithms for a specifc algo type. * - * @param this calling object - * @param type kind of algorithm - * @return iterator over algorithm_t's + * @param type kind of algorithm + * @return enumerator over u_int16_t alg, u_int16_t key_size */ - iterator_t *(*create_algorithm_iterator) (proposal_t *this, transform_type_t type); + enumerator_t *(*create_enumerator) (proposal_t *this, transform_type_t type); /** - * @brief Get the algorithm for a type to use. + * Get the algorithm for a type to use. * * If there are multiple algorithms, only the first is returned. * - * @param this calling object - * @param type kind of algorithm - * @param[out] algo pointer which receives algorithm and key size - * @return TRUE if algorithm of this kind available + * @param type kind of algorithm + * @param alg pointer which receives algorithm + * @param key_size pointer which receives the key size + * @return TRUE if algorithm of this kind available */ - bool (*get_algorithm) (proposal_t *this, transform_type_t type, algorithm_t** algo); + bool (*get_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size); /** - * @brief Check if the proposal has a specific DH group. + * Check if the proposal has a specific DH group. * - * @param this calling object - * @param group group to check for - * @return TRUE if algorithm included + * @param group group to check for + * @return TRUE if algorithm included */ bool (*has_dh_group) (proposal_t *this, diffie_hellman_group_t group); + + /** + * Strip DH groups from proposal to use it without PFS. + */ + void (*strip_dh)(proposal_t *this); /** - * @brief Compare two proposal, and select a matching subset. + * Compare two proposal, and select a matching subset. * * If the proposals are for the same protocols (AH/ESP), they are * compared. If they have at least one algorithm of each type * in common, a resulting proposal of this kind is created. * - * @param this calling object - * @param other proposal to compair agains - * @return - * - selected proposal, if possible - * - NULL, if proposals don't match + * @param other proposal to compair agains + * @return selected proposal, NULL if proposals don't match */ proposal_t *(*select) (proposal_t *this, proposal_t *other); /** - * @brief Get the protocol ID of the proposal. + * Get the protocol ID of the proposal. * - * @param this calling object - * @return protocol of the proposal + * @return protocol of the proposal */ protocol_id_t (*get_protocol) (proposal_t *this); /** - * @brief Get the SPI of the proposal. + * Get the SPI of the proposal. * - * @param this calling object - * @return spi for proto + * @return spi for proto */ u_int64_t (*get_spi) (proposal_t *this); /** - * @brief Set the SPI of the proposal. + * Set the SPI of the proposal. * - * @param this calling object - * @param spi spi to set for proto + * @param spi spi to set for proto */ void (*set_spi) (proposal_t *this, u_int64_t spi); /** - * @brief Clone a proposal. + * Check for the eqality of two proposals. + * + * @param other other proposal to check for equality + * @return TRUE if other equal to this + */ + bool (*equals)(proposal_t *this, proposal_t *other); + + /** + * Clone a proposal. * - * @param this proposal to clone - * @return clone of it + * @return clone of proposal */ proposal_t *(*clone) (proposal_t *this); /** - * @brief Destroys the proposal object. - * - * @param this calling object + * Destroys the proposal object. */ void (*destroy) (proposal_t *this); }; /** - * @brief Create a child proposal for AH, ESP or IKE. + * Create a child proposal for AH, ESP or IKE. * * @param protocol protocol, such as PROTO_ESP * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create(protocol_id_t protocol); /** - * @brief Create a default proposal if nothing further specified. + * Create a default proposal if nothing further specified. * * @param protocol protocol, such as PROTO_ESP * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create_default(protocol_id_t protocol); /** - * @brief Create a proposal from a string identifying the algorithms. + * Create a proposal from a string identifying the algorithms. * * The string is in the same form as a in the ipsec.conf file. * E.g.: aes128-sha2_256-modp2048 @@ -268,9 +229,17 @@ proposal_t *proposal_create_default(protocol_id_t protocol); * @param protocol protocol, such as PROTO_ESP * @param algs algorithms as string * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs); -#endif /* PROPOSAL_H_ */ +/** + * Get printf hooks for a proposal. + * + * Arguments are: + * proposal_t *proposal + * With the #-specifier, arguments are: + * linked_list_t *list containing proposal_t* + */ +printf_hook_functions_t proposal_get_printf_hooks(); + +#endif /* PROPOSAL_H_ @} */ diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c index da39c434d..f41c39d30 100644 --- a/src/charon/config/traffic_selector.c +++ b/src/charon/config/traffic_selector.c @@ -1,10 +1,3 @@ -/** - * @file traffic_selector.c - * - * @brief Implementation of traffic_selector_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi @@ -20,6 +13,8 @@ * 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: traffic_selector.c 3658 2008-03-26 10:06:45Z martin $ */ #include <arpa/inet.h> @@ -276,11 +271,25 @@ static int print(FILE *stream, const struct printf_info *info, } /** - * register printf() handlers + * arginfo handler for printf() traffic selector + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * return printf hook functions for a chunk */ -static void __attribute__ ((constructor))print_register() +printf_hook_functions_t traffic_selector_get_printf_hooks() { - register_printf_function(PRINTF_TRAFFIC_SELECTOR, print, arginfo_ptr); + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; } /** @@ -709,6 +718,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, } default: { + net->destroy(net); free(this); return NULL; } @@ -718,6 +728,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, this->from_port = port; this->to_port = port; } + net->destroy(net); return (&this->public); } @@ -770,12 +781,11 @@ traffic_selector_t *traffic_selector_create_from_string( /* * see header */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port) { - private_traffic_selector_t *this = traffic_selector_create(protocol, type, - from_port, to_port); + private_traffic_selector_t *this = traffic_selector_create( + protocol, TS_IPV4_ADDR_RANGE, from_port, to_port); memset(this->from6, 0, sizeof(this->from6)); memset(this->to6, 0xFF, sizeof(this->to6)); @@ -818,4 +828,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, return this; } -/* vim: set ts=4 sw=4 noet: */ diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h index 0e798fc6a..4b079a8e0 100644 --- a/src/charon/config/traffic_selector.h +++ b/src/charon/config/traffic_selector.h @@ -1,10 +1,3 @@ -/** - * @file traffic_selector.h - * - * @brief Interface of traffic_selector_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,13 @@ * 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: traffic_selector.h 3658 2008-03-26 10:06:45Z martin $ + */ + +/** + * @defgroup traffic_selector traffic_selector + * @{ @ingroup config */ #ifndef TRAFFIC_SELECTOR_H_ @@ -33,8 +33,6 @@ typedef struct traffic_selector_t traffic_selector_t; /** * Traffic selector types. - * - * @ingroup config */ enum ts_type_t { @@ -63,29 +61,20 @@ enum ts_type_t { extern enum_name_t *ts_type_name; /** - * @brief Object representing a traffic selector entry. + * Object representing a traffic selector entry. * * A traffic selector defines an range of addresses * and a range of ports. IPv6 is not fully supported yet. - * - * @b Constructors: - * - traffic_selector_create_from_bytes() - * - traffic_selector_create_from_string() - * - * @todo Add IPv6 support - * - * @ingroup config */ struct traffic_selector_t { /** - * @brief Compare two traffic selectors, and create a new one + * Compare two traffic selectors, and create a new one * which is the largest subset of both (subnet & port). * * Resulting traffic_selector is newly created and must be destroyed. * - * @param this first to compare - * @param other second to compare + * @param other traffic selector to compare * @return * - created subset of them * - or NULL if no match between this and other @@ -94,73 +83,66 @@ struct traffic_selector_t { traffic_selector_t *other); /** - * @brief Clone a traffic selector. + * Clone a traffic selector. * - * @param this traffic selector to clone * @return clone of it */ traffic_selector_t *(*clone) (traffic_selector_t *this); /** - * @brief Get starting address of this ts as a chunk. + * Get starting address of this ts as a chunk. * * Chunk is in network order gets allocated. * - * @param this called object * @return chunk containing the address */ chunk_t (*get_from_address) (traffic_selector_t *this); /** - * @brief Get ending address of this ts as a chunk. + * Get ending address of this ts as a chunk. * * Chunk is in network order gets allocated. * - * @param this called object * @return chunk containing the address */ chunk_t (*get_to_address) (traffic_selector_t *this); /** - * @brief Get starting port of this ts. + * Get starting port of this ts. * * Port is in host order, since the parser converts it. * Size depends on protocol. * - * @param this called object * @return port */ u_int16_t (*get_from_port) (traffic_selector_t *this); /** - * @brief Get ending port of this ts. + * Get ending port of this ts. * * Port is in host order, since the parser converts it. * Size depends on protocol. * - * @param this called object * @return port */ u_int16_t (*get_to_port) (traffic_selector_t *this); /** - * @brief Get the type of the traffic selector. + * Get the type of the traffic selector. * - * @param this called object * @return ts_type_t specifying the type */ ts_type_t (*get_type) (traffic_selector_t *this); /** - * @brief Get the protocol id of this ts. + * Get the protocol id of this ts. * - * @param this called object * @return protocol id */ u_int8_t (*get_protocol) (traffic_selector_t *this); /** - * @brief Check if the traffic selector is for a single host. + * Check if the traffic selector is for a single host. * * Traffic selector may describe the end of *-to-host tunnel. In this * case, the address range is a single address equal to the hosts @@ -168,61 +150,54 @@ struct traffic_selector_t { * If host is NULL, the traffic selector is checked if it is a single host, * but not a specific one. * - * @param this called object * @param host host_t specifying the address range */ bool (*is_host) (traffic_selector_t *this, host_t* host); /** - * @brief Update the address of a traffic selector. + * Update the address of a traffic selector. * * Update the address range of a traffic selector, if it is * constructed with the traffic_selector_create_dynamic(). * - * @param this called object * @param host host_t specifying the address */ void (*set_address) (traffic_selector_t *this, host_t* host); /** - * @brief Compare two traffic selectors for equality. + * Compare two traffic selectors for equality. * - * @param this first to compare - * @param other second to compare with first + * @param other ts to compare with this * @return pointer to a string. */ bool (*equals) (traffic_selector_t *this, traffic_selector_t *other); /** - * @brief Check if a traffic selector is contained completly in another. + * Check if a traffic selector is contained completly in another. * * contains() allows to check if multiple traffic selectors are redundant. * - * @param this ts that is contained in another * @param other ts that contains this * @return TRUE if other contains this completly, FALSE otherwise */ bool (*is_contained_in) (traffic_selector_t *this, traffic_selector_t *other); /** - * @brief Check if a specific host is included in the address range of + * Check if a specific host is included in the address range of * this traffic selector. * - * @param this called object * @param host the host to check */ bool (*includes) (traffic_selector_t *this, host_t *host); /** - * @brief Destroys the ts object - * - * @param this called object + * Destroys the ts object */ void (*destroy) (traffic_selector_t *this); }; /** - * @brief Create a new traffic selector using human readable params. + * Create a new traffic selector using human readable params. * * @param protocol protocol for this ts, such as TCP or UDP * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE @@ -233,8 +208,6 @@ struct traffic_selector_t { * @return * - traffic_selector_t object * - NULL if invalid address strings/protocol - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_string( u_int8_t protocol, ts_type_t type, @@ -242,7 +215,7 @@ traffic_selector_t *traffic_selector_create_from_string( char *to_addr, u_int16_t to_port); /** - * @brief Create a new traffic selector using data read from the net. + * Create a new traffic selector using data read from the net. * * There exists a mix of network and host order in the params. * But the parser gives us this data in this format, so we @@ -255,8 +228,6 @@ traffic_selector_t *traffic_selector_create_from_string( * @param to_address end of address range as string, network * @param to_port port number, host order * @return traffic_selector_t object - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_bytes( u_int8_t protocol, ts_type_t type, @@ -264,7 +235,7 @@ traffic_selector_t *traffic_selector_create_from_bytes( chunk_t to_address, u_int16_t to_port); /** - * @brief Create a new traffic selector defining a whole subnet. + * Create a new traffic selector defining a whole subnet. * * In most cases, definition of a traffic selector for full subnets * is sufficient. This constructor creates a traffic selector for @@ -278,15 +249,13 @@ traffic_selector_t *traffic_selector_create_from_bytes( * @return * - traffic_selector_t object * - NULL if address family of net not supported - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_subnet( host_t *net, u_int8_t netbits, u_int8_t protocol, u_int16_t port); /** - * @brief Create a traffic selector for host-to-host cases. + * Create a traffic selector for host-to-host cases. * * For host2host or virtual IP setups, the traffic selectors gets * created at runtime using the external/virtual IP. Using this constructor, @@ -294,19 +263,23 @@ traffic_selector_t *traffic_selector_create_from_subnet( * * * @param protocol upper layer protocl to allow - * @param type family type * @param from_port start of allowed port range * @param to_port end of range * @return * - traffic_selector_t object * - NULL if type not supported - * - * @ingroup config */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port); -#endif /* TRAFFIC_SELECTOR_H_ */ +/** + * Get printf hooks for a traffic selector. + * + * Arguments are: + * traffic_selector_t *ts + * With the #-specifier, arguments are: + * linked_list_t *list containing traffic_selector_t* + */ +printf_hook_functions_t traffic_selector_get_printf_hooks(); -/* vim: set ts=4 sw=4 noet: */ +#endif /* TRAFFIC_SELECTOR_H_ @} */ |