diff options
Diffstat (limited to 'src/charon/config')
23 files changed, 4423 insertions, 0 deletions
diff --git a/src/charon/config/Makefile.config b/src/charon/config/Makefile.config new file mode 100644 index 000000000..d4638b318 --- /dev/null +++ b/src/charon/config/Makefile.config @@ -0,0 +1,32 @@ +# Copyright (C) 2005 Jan Hutter, 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. +# + +CONFIG_DIR= $(CHARON_DIR)config/ + + +CHARON_OBJS+= $(BUILD_DIR)traffic_selector.o +$(BUILD_DIR)traffic_selector.o : $(CONFIG_DIR)traffic_selector.c $(CONFIG_DIR)traffic_selector.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)proposal.o +$(BUILD_DIR)proposal.o : $(CONFIG_DIR)proposal.c $(CONFIG_DIR)proposal.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)configuration.o +$(BUILD_DIR)configuration.o : $(CONFIG_DIR)configuration.c $(CONFIG_DIR)configuration.h + $(CC) $(CFLAGS) -c -o $@ $< + +include $(CONFIG_DIR)connections/Makefile.connections +include $(CONFIG_DIR)credentials/Makefile.credentials +include $(CONFIG_DIR)policies/Makefile.policies
\ No newline at end of file diff --git a/src/charon/config/configuration.c b/src/charon/config/configuration.c new file mode 100755 index 000000000..eac1bd43a --- /dev/null +++ b/src/charon/config/configuration.c @@ -0,0 +1,112 @@ +/** + * @file configuration.c + * + * @brief Implementation of configuration_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 <stdlib.h> + +#include "configuration.h" + +#include <types.h> + +/** + * First retransmit timeout in milliseconds. + * Timeout value is increasing in each retransmit round. + */ +#define RETRANSMIT_TIMEOUT 3000 + +/** + * Timeout in milliseconds after that a half open IKE_SA gets deleted. + */ +#define HALF_OPEN_IKE_SA_TIMEOUT 30000 + +/** + * Max retransmit count. + * 0 for infinite. The max time a half open IKE_SA is alive is set by + * RETRANSMIT_TIMEOUT. + */ +#define MAX_RETRANSMIT_COUNT 0 + + +typedef struct private_configuration_t private_configuration_t; + +/** + * Private data of an configuration_t object. + */ +struct private_configuration_t { + + /** + * Public part of configuration_t object. + */ + configuration_t public; + +}; + +/** + * Implementation of configuration_t.get_retransmit_timeout. + */ +static status_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout) +{ + int new_timeout = RETRANSMIT_TIMEOUT, i; + if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0) + { + return FAILED; + } + + for (i = 0; i < retransmit_count; i++) + { + new_timeout *= 2; + } + + *timeout = new_timeout; + + return SUCCESS; +} + +/** + * Implementation of configuration_t.get_half_open_ike_sa_timeout. + */ +static u_int32_t get_half_open_ike_sa_timeout (private_configuration_t *this) +{ + return HALF_OPEN_IKE_SA_TIMEOUT; +} + +/** + * Implementation of configuration_t.destroy. + */ +static void destroy(private_configuration_t *this) +{ + free(this); +} + +/* + * Described in header-file + */ +configuration_t *configuration_create() +{ + private_configuration_t *this = malloc_thing(private_configuration_t); + + /* public functions */ + this->public.destroy = (void(*)(configuration_t*))destroy; + this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout; + this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout; + + return (&this->public); +} diff --git a/src/charon/config/configuration.h b/src/charon/config/configuration.h new file mode 100755 index 000000000..3696215f0 --- /dev/null +++ b/src/charon/config/configuration.h @@ -0,0 +1,89 @@ +/** + * @file configuration.h + * + * @brief Interface configuration_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 CONFIGURATION_H_ +#define CONFIGURATION_H_ + +#include <types.h> + + +typedef struct configuration_t configuration_t; + +/** + * @brief The interface for various daemon related configs. + * + * @b Constructors: + * - configuration_create() + * + * @ingroup config + */ +struct configuration_t { + + /** + * @brief Returns the retransmit timeout. + * + * The timeout values are managed by the configuration, so + * another backoff algorithm may be implemented here. + * + * @param this calling object + * @param retransmit_count number of times a message was retransmitted so far + * @param[out] timeout the new retransmit timeout in milliseconds + * + * @return + * - FAILED, if the message should not be retransmitted + * - SUCCESS + */ + status_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout); + + /** + * @brief Returns the timeout for an half open IKE_SA in ms. + * + * Half open means that the IKE_SA is still in one of the following states: + * - INITIATOR_INIT + * - RESPONDER_INIT + * - IKE_SA_INIT_REQUESTED + * - IKE_SA_INIT_RESPONDED + * - IKE_AUTH_REQUESTED + * + * @param this calling object + * @return timeout in milliseconds (ms) + */ + u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this); + + /** + * @brief Destroys a configuration_t object. + * + * @param this calling object + */ + void (*destroy) (configuration_t *this); +}; + +/** + * @brief Creates a configuration backend. + * + * @return static_configuration_t object + * + * @ingroup config + */ +configuration_t *configuration_create(void); + +#endif /*CONFIGURATION_H_*/ diff --git a/src/charon/config/connections/Makefile.connections b/src/charon/config/connections/Makefile.connections new file mode 100644 index 000000000..8fbc983f6 --- /dev/null +++ b/src/charon/config/connections/Makefile.connections @@ -0,0 +1,24 @@ +# 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. +# + +CONNECTIONS_DIR= $(CONFIG_DIR)connections/ + + +CHARON_OBJS+= $(BUILD_DIR)connection.o +$(BUILD_DIR)connection.o : $(CONNECTIONS_DIR)connection.c $(CONNECTIONS_DIR)connection.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)local_connection_store.o +$(BUILD_DIR)local_connection_store.o : $(CONNECTIONS_DIR)local_connection_store.c $(CONNECTIONS_DIR)local_connection_store.h + $(CC) $(CFLAGS) -c -o $@ $<
\ No newline at end of file diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c new file mode 100644 index 000000000..74e6762b4 --- /dev/null +++ b/src/charon/config/connections/connection.c @@ -0,0 +1,367 @@ +/** + * @file connection.c + * + * @brief Implementation of connection_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 "connection.h" + +#include <utils/linked_list.h> +#include <utils/logger.h> + +/** + * String mappings for auth_method_t. + */ +mapping_t auth_method_m[] = { + {RSA_DIGITAL_SIGNATURE, "RSA"}, + {SHARED_KEY_MESSAGE_INTEGRITY_CODE, "SHARED_KEY"}, + {DSS_DIGITAL_SIGNATURE, "DSS"}, + {MAPPING_END, NULL} +}; + + +typedef struct private_connection_t private_connection_t; + +/** + * Private data of an connection_t object + */ +struct private_connection_t { + + /** + * Public part + */ + connection_t public; + + /** + * Name of the connection + */ + char *name; + + /** + * ID of us + */ + identification_t *my_id; + + /** + * ID of remote peer + */ + identification_t *other_id; + + /** + * Host information of my host. + */ + host_t *my_host; + + /** + * Host information of other host. + */ + host_t *other_host; + + /** + * Method to use for own authentication data + */ + auth_method_t auth_method; + + /** + * Supported proposals + */ + linked_list_t *proposals; +}; + +/** + * Implementation of connection_t.get_name. + */ +static char *get_name (private_connection_t *this) +{ + return this->name; +} + +/** + * Implementation of connection_t.get_my_id. + */ +static identification_t *get_my_id (private_connection_t *this) +{ + return this->my_id; +} + +/** + * Implementation of connection_t.get_other_id. + */ +static identification_t *get_other_id(private_connection_t *this) +{ + return this->other_id; +} + +/** + * Implementation of connection_t.update_my_id + */ +static void update_my_id(private_connection_t *this, identification_t *my_id) +{ + this->my_id->destroy(this->my_id); + this->my_id = my_id; +} + +/** + * Implementation of connection_t.update_other_id + */ +static void update_other_id(private_connection_t *this, identification_t *other_id) +{ + this->other_id->destroy(this->other_id); + this->other_id = other_id; +} + +/** + * Implementation of connection_t.get_my_host. + */ +static host_t * get_my_host (private_connection_t *this) +{ + return this->my_host; +} + +/** + * Implementation of connection_t.update_my_host. + */ +static void update_my_host(private_connection_t *this, host_t *my_host) +{ + this->my_host->destroy(this->my_host); + this->my_host = my_host; +} + +/** + * Implementation of connection_t.update_other_host. + */ +static void update_other_host(private_connection_t *this, host_t *other_host) +{ + this->other_host->destroy(this->other_host); + this->other_host = other_host; +} + +/** + * Implementation of connection_t.get_other_host. + */ +static host_t * get_other_host (private_connection_t *this) +{ + return this->other_host; +} + +/** + * Implementation of connection_t.get_proposals. + */ +static linked_list_t* get_proposals (private_connection_t *this) +{ + return this->proposals; +} + +/** + * Implementation of connection_t.select_proposal. + */ +static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals) +{ + iterator_t *stored_iter, *supplied_iter; + proposal_t *stored, *supplied, *selected; + + 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->has_next(stored_iter)) + { + supplied_iter->reset(supplied_iter); + stored_iter->current(stored_iter, (void**)&stored); + + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied); + selected = stored->select(stored, supplied); + if (selected) + { + /* they match, return */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + return selected; + } + } + } + + /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return NULL; +} + +/** + * Implementation of connection_t.add_proposal. + */ +static void add_proposal (private_connection_t *this, proposal_t *proposal) +{ + this->proposals->insert_last(this->proposals, proposal); +} + +/** + * Implementation of connection_t.auth_method_t. + */ +static auth_method_t get_auth_method(private_connection_t *this) +{ + return this->auth_method; +} + +/** + * Implementation of connection_t.get_dh_group. + */ +static diffie_hellman_group_t get_dh_group(private_connection_t *this) +{ + iterator_t *iterator; + proposal_t *proposal; + algorithm_t *algo; + + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo); + if (algo) + { + iterator->destroy(iterator); + return algo->algorithm; + } + } + iterator->destroy(iterator); + return MODP_UNDEFINED; +} + +/** + * Implementation of connection_t.check_dh_group. + */ +static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group) +{ + iterator_t *prop_iter, *alg_iter; + proposal_t *proposal; + algorithm_t *algo; + + prop_iter = this->proposals->create_iterator(this->proposals, TRUE); + while (prop_iter->has_next(prop_iter)) + { + prop_iter->current(prop_iter, (void**)&proposal); + alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP); + while (alg_iter->has_next(alg_iter)) + { + alg_iter->current(alg_iter, (void**)&algo); + if (algo->algorithm == dh_group) + { + prop_iter->destroy(prop_iter); + alg_iter->destroy(alg_iter); + return TRUE; + } + } + } + prop_iter->destroy(prop_iter); + alg_iter->destroy(alg_iter); + return FALSE; +} + +/** + * Implementation of connection_t.clone. + */ +static connection_t *clone(private_connection_t *this) +{ + iterator_t *iterator; + proposal_t *proposal; + private_connection_t *clone = (private_connection_t*)connection_create( + this->name, + this->my_host->clone(this->my_host), + this->other_host->clone(this->other_host), + this->my_id->clone(this->my_id), + this->other_id->clone(this->other_id), + this->auth_method); + + /* clone all proposals */ + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal = proposal->clone(proposal); + clone->proposals->insert_last(clone->proposals, (void*)proposal); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/** + * Implementation of connection_t.destroy. + */ +static void destroy (private_connection_t *this) +{ + proposal_t *proposal; + + while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + this->proposals->destroy(this->proposals); + + this->my_host->destroy(this->my_host); + this->other_host->destroy(this->other_host); + this->my_id->destroy(this->my_id); + this->other_id->destroy(this->other_id); + free(this->name); + free(this); +} + +/** + * Described in header. + */ +connection_t * connection_create(char *name, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method) +{ + private_connection_t *this = malloc_thing(private_connection_t); + + /* public functions */ + this->public.get_name = (char*(*)(connection_t*))get_name; + this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id; + this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id; + this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host; + this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host; + this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host; + this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id; + this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id; + this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host; + this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals; + this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal; + this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal; + this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method; + this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group; + this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group; + this->public.clone = (connection_t*(*)(connection_t*))clone; + this->public.destroy = (void(*)(connection_t*))destroy; + + /* private variables */ + this->name = strdup(name); + this->my_host = my_host; + this->other_host = other_host; + this->my_id = my_id; + this->other_id = other_id; + this->auth_method = auth_method; + + this->proposals = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h new file mode 100644 index 000000000..2cb3c20b8 --- /dev/null +++ b/src/charon/config/connections/connection.h @@ -0,0 +1,283 @@ +/** + * @file connection.h + * + * @brief Interface of connection_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 CONNECTION_H_ +#define CONNECTION_H_ + +#include <types.h> +#include <utils/host.h> +#include <utils/linked_list.h> +#include <utils/identification.h> +#include <config/proposal.h> +#include <crypto/diffie_hellman.h> + + +typedef enum auth_method_t auth_method_t; + +/** + * AUTH Method to use. + * + * @ingroup config + */ +enum auth_method_t { + /** + * Computed as specified in section 2.15 of RFC using + * an RSA private key over a PKCS#1 padded hash. + */ + RSA_DIGITAL_SIGNATURE = 1, + + /** + * Computed as specified in section 2.15 of RFC using the + * shared key associated with the identity in the ID payload + * and the negotiated prf function + */ + SHARED_KEY_MESSAGE_INTEGRITY_CODE = 2, + + /** + * Computed as specified in section 2.15 of RFC using a + * DSS private key over a SHA-1 hash. + */ + DSS_DIGITAL_SIGNATURE = 3, +}; + +/** + * string mappings for auth method. + * + * @ingroup config + */ +extern mapping_t auth_method_m[]; + + +typedef struct connection_t connection_t; + +/** + * @brief A connection_t defines the rules to set up an IKE_SA. + * + * + * @b Constructors: + * - connection_create() + * + * @ingroup config + */ +struct connection_t { + + /** + * @brief Get my ID for this connection. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as identification_t object + */ + identification_t *(*get_my_id) (connection_t *this); + + /** + * @brief Get others ID for this connection. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as identification_t object + */ + identification_t *(*get_other_id) (connection_t *this); + + /** + * @brief Get my address as host_t object. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as host_t object + */ + host_t *(*get_my_host) (connection_t *this); + + /** + * @brief Get others address as host_t object. + * + * Object is NOT getting cloned. + * + * @param this calling object + * @return host information as host_t object + */ + host_t *(*get_other_host) (connection_t *this); + + /** + * @brief Update address of my host. + * + * It may be necessary to uptdate own address, as it + * is set to the default route (0.0.0.0) in some cases. + * Old host is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_host new host to set as my_host + */ + void (*update_my_host) (connection_t *this, host_t *my_host); + + /** + * @brief Update address of remote host. + * + * It may be necessary to uptdate remote address, as a + * connection may define %any (0.0.0.0) or a subnet. + * Old host is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_host new host to set as other_host + */ + void (*update_other_host) (connection_t *this, host_t *other_host); + + /** + * @brief Update own ID. + * + * It may be necessary to uptdate own ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_id new ID to set as my_id + */ + void (*update_my_id) (connection_t *this, identification_t *my_id); + + /** + * @brief Update others ID. + * + * It may be necessary to uptdate others ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param other_id new ID to set as other_id + */ + void (*update_other_id) (connection_t *this, identification_t *other_id); + + /** + * @brief Returns a list of all supported proposals. + * + * Returned list is still owned by connection and MUST NOT + * modified or destroyed. + * + * @param this calling object + * @return list containing all the proposals + */ + linked_list_t *(*get_proposals) (connection_t *this); + + /** + * @brief 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) (connection_t *this, proposal_t *proposal); + + /** + * @brief Select a proposed from suggested proposals. + * + * Returned proposal must be destroyed after usage. + * + * @param this calling object + * @param proposals list of proposals to select from + * @return selected proposal, or NULL if none matches. + */ + proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals); + + /** + * @brief Get the authentication method to use + * + * @param this calling object + * @return authentication method + */ + auth_method_t (*get_auth_method) (connection_t *this); + + /** + * @brief Get the connection name. + * + * Name must not be freed, since it points to + * internal data. + * + * @param this calling object + * @return name of the connection + */ + char* (*get_name) (connection_t *this); + + /** + * @brief Get the DH group to use for connection initialization. + * + * @param this calling object + * @return dh group to use for initialization + */ + diffie_hellman_group_t (*get_dh_group) (connection_t *this); + + /** + * @brief Check if a suggested dh group is acceptable. + * + * If we guess a wrong DH group for IKE_SA_INIT, the other + * peer will send us a offer. But is this acceptable for us? + * + * @param this calling object + * @return TRUE if group acceptable + */ + bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group); + + /** + * @brief Clone a connection_t object. + * + * @param this connection to clone + * @return clone of it + */ + connection_t *(*clone) (connection_t *this); + + /** + * @brief Destroys a connection_t object. + * + * @param this calling object + */ + void (*destroy) (connection_t *this); +}; + +/** + * @brief Creates a connection_t object. + * + * Supplied hosts/IDs become owned by connection, so + * do not modify or destroy them after a call to + * connection_create(). Name gets cloned internally. + * + * @param name connection identifier + * @param my_host host_t representing local address + * @param other_host host_t representing remote address + * @param my_id identification_t for me + * @param other_id identification_t for other + * @param auth_method Authentication method to use for our(!) auth data + * @return connection_t object. + * + * @ingroup config + */ +connection_t * connection_create(char *name, + host_t *my_host, host_t *other_host, + identification_t *my_id, + identification_t *other_id, + auth_method_t auth_method); + +#endif /* CONNECTION_H_ */ diff --git a/src/charon/config/connections/connection_store.h b/src/charon/config/connections/connection_store.h new file mode 100755 index 000000000..41fd58e42 --- /dev/null +++ b/src/charon/config/connections/connection_store.h @@ -0,0 +1,112 @@ +/** + * @file connection_store.h + * + * @brief Interface connection_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 CONNECTION_STORE_H_ +#define CONNECTION_STORE_H_ + +#include <types.h> +#include <config/connections/connection.h> + + +typedef struct connection_store_t connection_store_t; + +/** + * @brief The interface for a store of connection_t's. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct connection_store_t { + + /** + * @brief Returns a connection definition identified by two IDs. + * + * This call is useful to get a connection which is identified by IDs + * rather than addresses, e.g. for connection setup on user request. + * The returned connection gets created/cloned and therefore must + * be destroyed after usage. + * + * @param this calling object + * @param my_id own ID of connection + * @param other_id others ID of connection + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_ids) (connection_store_t *this, identification_t *my_id, identification_t *other_id); + + /** + * @brief Returns a connection definition identified by two hosts. + * + * This call is usefull to get a connection identified by addresses. + * It may be used after kernel request for traffic protection. + * The returned connection gets created/cloned and therefore must + * be destroyed after usage. + * + * @param this calling object + * @param my_id own address of connection + * @param other_id others address of connection + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_hosts) (connection_store_t *this, host_t *my_host, host_t *other_host); + + /** + * @brief Returns a connection identified by its name. + * + * This call is usefull to get a connection identified its + * name, as on an connection setup. + * + * @param this calling object + * @param name name of the connection to get + * @return + * - connection_t, if found + * - NULL otherwise + */ + connection_t *(*get_connection_by_name) (connection_store_t *this, char *name); + + /** + * @brief Add a connection to the store. + * + * After a successful call, the connection is owned by the store and may + * not be manipulated nor destroyed. + * + * @param this calling object + * @param connection connection to add + * @return + * - SUCCESS, or + * - FAILED + */ + status_t (*add_connection) (connection_store_t *this, connection_t *connection); + + /** + * @brief Destroys a connection_store_t object. + * + * @param this calling object + */ + void (*destroy) (connection_store_t *this); +}; + +#endif /* CONNECTION_STORE_H_ */ diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c new file mode 100644 index 000000000..0ae18e0a7 --- /dev/null +++ b/src/charon/config/connections/local_connection_store.c @@ -0,0 +1,228 @@ +/** + * @file local_connection_store.c + * + * @brief Implementation of local_connection_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. + */ + +#include <string.h> + +#include "local_connection_store.h" + +#include <utils/linked_list.h> +#include <utils/logger_manager.h> + + +typedef struct private_local_connection_store_t private_local_connection_store_t; + +/** + * Private data of an local_connection_store_t object + */ +struct private_local_connection_store_t { + + /** + * Public part + */ + local_connection_store_t public; + + /** + * stored connection + */ + linked_list_t *connections; + + /** + * Assigned logger + */ + logger_t *logger; +}; + + +/** + * Implementation of connection_store_t.get_connection_by_hosts. + */ +static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", + my_host->get_address(my_host), other_host->get_address(other_host)); + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + host_t *config_my_host, *config_other_host; + + iterator->current(iterator, (void**)¤t); + + config_my_host = current->get_my_host(current); + config_other_host = current->get_other_host(current); + + /* first check if ip is equal */ + if(config_other_host->ip_equals(config_other_host, other_host)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", + config_other_host->get_address(config_other_host)); + /* could be right one, check my_host for default route*/ + if (config_my_host->is_default_route(config_my_host)) + { + found = current->clone(current); + break; + } + /* check now if host informations are the same */ + else if (config_my_host->ip_equals(config_my_host,my_host)) + { + found = current->clone(current); + break; + } + + } + /* Then check for wildcard hosts! + * TODO + * actually its only checked if other host with default route can be found! */ + else if (config_other_host->is_default_route(config_other_host)) + { + /* could be right one, check my_host for default route*/ + if (config_my_host->is_default_route(config_my_host)) + { + found = current->clone(current); + break; + } + /* check now if host informations are the same */ + else if (config_my_host->ip_equals(config_my_host,my_host)) + { + found = current->clone(current); + break; + } + } + } + iterator->destroy(iterator); + + /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */ + if (found) + { + found->update_my_host(found, my_host->clone(my_host)); + found->update_other_host(found, other_host->clone(other_host)); + } + + return found; +} + +/** + * Implementation of connection_store_t.get_connection_by_ids. + */ +static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", + my_id->get_string(my_id), other_id->get_string(other_id)); + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + identification_t *config_my_id, *config_other_id; + + iterator->current(iterator, (void**)¤t); + + config_my_id = current->get_my_id(current); + config_other_id = current->get_other_id(current); + + /* first check if ids are equal + * TODO: Add wildcard checks */ + if (config_other_id->equals(config_other_id, other_id) && + config_my_id->equals(config_my_id, my_id)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", + config_other_id->get_string(config_other_id)); + found = current->clone(current); + break; + } + } + iterator->destroy(iterator); + + return found; +} + +/** + * Implementation of connection_store_t.get_connection_by_name. + */ +static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name) +{ + iterator_t *iterator; + connection_t *current, *found = NULL; + + iterator = this->connections->create_iterator(this->connections, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + if (strcmp(name, current->get_name(current)) == 0) + { + found = current->clone(current); + break; + } + } + iterator->destroy(iterator); + + return found; +} + +/** + * Implementation of connection_store_t.add_connection. + */ +static status_t add_connection(private_local_connection_store_t *this, connection_t *connection) +{ + this->connections->insert_last(this->connections, connection); + return SUCCESS; +} + +/** + * Implementation of connection_store_t.destroy. + */ +static void destroy (private_local_connection_store_t *this) +{ + connection_t *connection; + + while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS) + { + connection->destroy(connection); + } + this->connections->destroy(this->connections); + free(this); +} + +/** + * Described in header. + */ +local_connection_store_t * local_connection_store_create(void) +{ + private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t); + + this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts; + this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids; + this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name; + this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection; + this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy; + + /* private variables */ + this->connections = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/connections/local_connection_store.h b/src/charon/config/connections/local_connection_store.h new file mode 100644 index 000000000..6e73ef945 --- /dev/null +++ b/src/charon/config/connections/local_connection_store.h @@ -0,0 +1,63 @@ +/** + * @file local_connection_store.h + * + * @brief Interface of local_connection_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_CONNECTION_H_ +#define LOCAL_CONNECTION_H_ + +#include <types.h> +#include <config/connections/connection_store.h> + + +typedef struct local_connection_store_t local_connection_store_t; + +/** + * @brief A connection_store_t implementation using a simple connection list. + * + * The local_connection_store_t class implements the connection_store_t interface + * as simple as possible. connection_t's are stored in an in-memory list. + * + * @b Constructors: + * - local_connection_store_create() + * + * @todo Make thread-save first + * @todo Add remove_connection method + * + * @ingroup config + */ +struct local_connection_store_t { + + /** + * Implements connection_store_t interface + */ + connection_store_t connection_store; +}; + +/** + * @brief Creates a local_connection_store_t instance. + * + * @return connection store instance. + * + * @ingroup config + */ +local_connection_store_t * local_connection_store_create(void); + +#endif /* LOCAL_CONNECTION_H_ */ diff --git a/src/charon/config/credentials/Makefile.credentials b/src/charon/config/credentials/Makefile.credentials new file mode 100644 index 000000000..720d56656 --- /dev/null +++ b/src/charon/config/credentials/Makefile.credentials @@ -0,0 +1,20 @@ +# 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. +# + +CREDENTIALS_DIR= $(CONFIG_DIR)credentials/ + + +CHARON_OBJS+= $(BUILD_DIR)local_credential_store.o +$(BUILD_DIR)local_credential_store.o : $(CREDENTIALS_DIR)local_credential_store.c $(CREDENTIALS_DIR)local_credential_store.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/charon/config/credentials/credential_store.h b/src/charon/config/credentials/credential_store.h new file mode 100755 index 000000000..2339469c0 --- /dev/null +++ b/src/charon/config/credentials/credential_store.h @@ -0,0 +1,91 @@ +/** + * @file credential_store.h + * + * @brief Interface credential_store_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 CREDENTIAL_STORE_H_ +#define CREDENTIAL_STORE_H_ + +#include <types.h> +#include <crypto/rsa/rsa_private_key.h> +#include <crypto/rsa/rsa_public_key.h> +#include <utils/identification.h> + + +typedef struct credential_store_t credential_store_t; + +/** + * @brief The interface for a credential_store backend. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct credential_store_t { + + /** + * @brief Returns the preshared secret of a specific ID. + * + * The returned chunk must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the secret. + * @param[out] preshared_secret the preshared secret will be written there. + * @return + * - NOT_FOUND if no preshared secrets for specific ID could be found + * - SUCCESS + * + * @todo We should use two IDs to query shared secrets, since we want to use different + * keys for different peers... + */ + status_t (*get_shared_secret) (credential_store_t *this, identification_t *identification, chunk_t *preshared_secret); + + /** + * @brief Returns the RSA public key of a specific ID. + * + * The returned rsa_public_key_t must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the key. + * @return public key, or NULL if not found + */ + rsa_public_key_t * (*get_rsa_public_key) (credential_store_t *this, identification_t *identification); + + /** + * @brief Returns the RSA private key of a specific ID. + * + * The returned rsa_private_key_t must be destroyed by the caller after usage. + * + * @param this calling object + * @param identification identification_t object identifiying the key + * @return private key, or NULL if not found + */ + rsa_private_key_t *(*get_rsa_private_key) (credential_store_t *this, identification_t *identification); + + /** + * @brief Destroys a credential_store_t object. + * + * @param this calling object + */ + void (*destroy) (credential_store_t *this); +}; + +#endif /*CREDENTIAL_STORE_H_*/ diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c new file mode 100644 index 000000000..2554eec4a --- /dev/null +++ b/src/charon/config/credentials/local_credential_store.c @@ -0,0 +1,381 @@ +/** + * @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. + */ + +#include <sys/stat.h> +#include <dirent.h> +#include <string.h> + +#include "local_credential_store.h" + +#include <utils/lexparser.h> +#include <utils/linked_list.h> +#include <utils/logger_manager.h> +#include <crypto/x509.h> + +#define PATH_BUF 256 + +typedef struct key_entry_t key_entry_t; + +/** + * Private key with an associated ID to find it + */ +struct key_entry_t { + + /** + * ID, as added + */ + identification_t *id; + + /** + * Associated rsa private key + */ + rsa_private_key_t *key; +}; + + +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 key_entry_t's with private keys + */ + linked_list_t *private_keys; + + /** + * list of x509 certificates with public keys + */ + linked_list_t *certificates; + + /** + * Assigned logger + */ + logger_t *logger; +}; + + +/** + * Implementation of credential_store_t.get_shared_secret. + */ +static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *identification, chunk_t *preshared_secret) +{ + return FAILED; +} + +/** + * Implementation of credential_store_t.get_rsa_public_key. + */ +static rsa_public_key_t * get_rsa_public_key(private_local_credential_store_t *this, identification_t *identification) +{ + x509_t *current; + rsa_public_key_t *found = NULL; + iterator_t *iterator; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s", + identification->get_string(identification)); + iterator = this->certificates->create_iterator(this->certificates, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + identification_t *stored = current->get_subject(current); + this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s", + stored->get_string(stored)); + if (identification->equals(identification, stored)) + { + found = current->get_public_key(current); + break; + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implementation of credential_store_t.get_rsa_private_key. + */ +static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, identification_t *identification) +{ + rsa_private_key_t *found = NULL; + key_entry_t *current; + iterator_t *iterator; + + iterator = this->private_keys->create_iterator(this->private_keys, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t); + if (identification->equals(identification, current->id)) + { + found = current->key->clone(current->key); + break; + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implements local_credential_store_t.load_certificates + */ +static void load_certificates(private_local_credential_store_t *this, const char *path) +{ + struct dirent* entry; + struct stat stb; + DIR* dir; + x509_t *cert; + + dir = opendir(path); + if (dir == NULL) { + this->logger->log(this->logger, ERROR, "error opening certificate 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) + { + cert = x509_create_from_file(file); + if (cert) + { + this->certificates->insert_last(this->certificates, (void*)cert); + } + else + { + this->logger->log(this->logger, ERROR, "certificate \"%s\" invalid, skipped", file); + } + } + } + closedir(dir); +} + +/** + * Query the ID for a private key, by doing a lookup in the certificates + */ +static identification_t *get_id_for_private_key(private_local_credential_store_t *this, rsa_private_key_t *private_key) +{ + iterator_t *iterator; + x509_t *cert; + identification_t *found = NULL; + rsa_public_key_t *public_key; + + this->logger->log(this->logger, CONTROL|LEVEL2, "Getting ID for a private key..."); + + iterator = this->certificates->create_iterator(this->certificates, TRUE); + while (!found && iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&cert); + public_key = cert->get_public_key(cert); + if (public_key) + { + if (private_key->belongs_to(private_key, public_key)) + { + this->logger->log(this->logger, CONTROL|LEVEL2, "found a match"); + found = cert->get_subject(cert); + found = found->clone(found); + } + else + { + this->logger->log(this->logger, CONTROL|LEVEL3, "this one did not match"); + } + public_key->destroy(public_key); + } + } + iterator->destroy(iterator); + return found; +} + +/** + * Implements local_credential_store_t.load_private_keys + */ +static void load_private_keys(private_local_credential_store_t *this, const char *secretsfile, const char *defaultpath) +{ + FILE *fd = fopen(secretsfile, "r"); + + if (fd) + { + int bytes; + int line_nr = 0; + chunk_t chunk, src, line; + + this->logger->log(this->logger, CONTROL, "loading secrets from \"%s\"", secretsfile); + + 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; + + while (fetchline(&src, &line)) + { + chunk_t ids, token; + + line_nr++; + + if (!eat_whitespace(&line)) + { + continue; + } + if (!extract_token(&ids, ':', &line)) + { + this->logger->log(this->logger, ERROR, "line %d: missing ':' separator", line_nr); + goto error; + } + if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) + { + this->logger->log(this->logger, ERROR, "line %d: missing token", line_nr); + goto error; + } + if (match("RSA", &token)) + { + char path[PATH_BUF]; + chunk_t filename; + + err_t ugh = extract_value(&filename, &line); + + if (ugh != NULL) + { + this->logger->log(this->logger, ERROR, "line %d: %s", line_nr, ugh); + goto error; + } + if (filename.len == 0) + { + this->logger->log(this->logger, ERROR, + "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", defaultpath, filename.len, filename.ptr); + } + + rsa_private_key_t *key = rsa_private_key_create_from_file(path, NULL); + if (key) + { + key_entry_t *entry; + identification_t *id = get_id_for_private_key(this, key); + + if (!id) + { + this->logger->log(this->logger, ERROR, + "no certificate found for private key \"%s\", skipped", path); + key->destroy(key); + continue; + } + entry = malloc_thing(key_entry_t); + entry->key = key; + entry->id = id; + this->private_keys->insert_last(this->private_keys, (void*)entry); + } + } + else if (match("PSK", &token)) + { + + } + else if (match("PIN", &token)) + { + + } + else + { + this->logger->log(this->logger, ERROR, + "line %d: token must be either RSA, PSK, or PIN", + line_nr, token.len); + goto error; + } + } +error: + free(chunk.ptr); + } + else + { + this->logger->log(this->logger, ERROR, "could not open file '%s'", secretsfile); + } +} + +/** + * Implementation of credential_store_t.destroy. + */ +static void destroy(private_local_credential_store_t *this) +{ + x509_t *certificate; + key_entry_t *key_entry; + + while (this->certificates->remove_last(this->certificates, (void**)&certificate) == SUCCESS) + { + certificate->destroy(certificate); + } + this->certificates->destroy(this->certificates); + while (this->private_keys->remove_last(this->private_keys, (void**)&key_entry) == SUCCESS) + { + key_entry->id->destroy(key_entry->id); + key_entry->key->destroy(key_entry->key); + free(key_entry); + } + this->private_keys->destroy(this->private_keys); + 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); + + this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret; + this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,identification_t*))get_rsa_private_key; + this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; + this->public.load_certificates = (void(*)(local_credential_store_t*,const char*))load_certificates; + this->public.load_private_keys = (void(*)(local_credential_store_t*,const char*, const char*))load_private_keys; + this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy; + + /* private variables */ + this->private_keys = linked_list_create(); + this->certificates = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/credentials/local_credential_store.h b/src/charon/config/credentials/local_credential_store.h new file mode 100644 index 000000000..81b7568d7 --- /dev/null +++ b/src/charon/config/credentials/local_credential_store.h @@ -0,0 +1,85 @@ +/** + * @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_ + +#include <types.h> +#include <config/credentials/credential_store.h> + + +typedef struct local_credential_store_t local_credential_store_t; + +/** + * @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 can be loaded + * from folders. + * Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND. + * + * @b Constructors: + * - local_credential_store_create() + * + * @ingroup config + */ +struct local_credential_store_t { + + /** + * Implements credential_store_t interface + */ + credential_store_t credential_store; + + /** + * @brief Loads trusted certificates from a folder. + * + * Currently, all keys must be in binary DER format. + * + * @param this calling object + * @param path directory to load certificates from + */ + void (*load_certificates) (local_credential_store_t *this, const char *path); + + /** + * @brief Loads RSA private keys from a folder. + * + * Currently, all keys must be unencrypted in binary DER format. Anything + * other gets ignored. Further, a certificate for the specific private + * key must already be loaded to get the ID from. + * + * @param this calling object + * @param secretsfile file where secrets are stored + * @param defaultpath default directory for private keys + */ + void (*load_private_keys) (local_credential_store_t *this, const char *secretsfile, const char *defaultpath); +}; + +/** + * @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/policies/Makefile.policies b/src/charon/config/policies/Makefile.policies new file mode 100644 index 000000000..e7ed8ab13 --- /dev/null +++ b/src/charon/config/policies/Makefile.policies @@ -0,0 +1,24 @@ +# 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. +# + +POLICIES_DIR= $(CONFIG_DIR)policies/ + + +CHARON_OBJS+= $(BUILD_DIR)policy.o +$(BUILD_DIR)policy.o : $(POLICIES_DIR)policy.c $(POLICIES_DIR)policy.h + $(CC) $(CFLAGS) -c -o $@ $< + +CHARON_OBJS+= $(BUILD_DIR)local_policy_store.o +$(BUILD_DIR)local_policy_store.o : $(POLICIES_DIR)local_policy_store.c $(POLICIES_DIR)local_policy_store.h + $(CC) $(CFLAGS) -c -o $@ $<
\ No newline at end of file diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c new file mode 100644 index 000000000..24d22f485 --- /dev/null +++ b/src/charon/config/policies/local_policy_store.c @@ -0,0 +1,136 @@ +/** + * @file local_policy_store.c + * + * @brief Implementation of local_policy_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. + */ + +#include "local_policy_store.h" + +#include <utils/linked_list.h> +#include <utils/logger_manager.h> + + +typedef struct private_local_policy_store_t private_local_policy_store_t; + +/** + * Private data of an local_policy_store_t object + */ +struct private_local_policy_store_t { + + /** + * Public part + */ + local_policy_store_t public; + + /** + * list of policy_t's + */ + linked_list_t *policies; + + /** + * Assigned logger + */ + logger_t *logger; +}; + +/** + * Implementation of policy_store_t.add_policy. + */ +static void add_policy(private_local_policy_store_t *this, policy_t *policy) +{ + this->policies->insert_last(this->policies, (void*)policy); +} + + +/** + * Implementation of policy_store_t.get_policy. + */ +static policy_t *get_policy(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id) +{ + iterator_t *iterator; + policy_t *current, *found = NULL; + + this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy for IDs %s - %s", + my_id ? my_id->get_string(my_id) : "%any", + other_id->get_string(other_id)); + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void **)¤t); + identification_t *config_my_id = current->get_my_id(current); + identification_t *config_other_id = current->get_other_id(current); + + this->logger->log(this->logger, CONTROL|LEVEL2, "Found one for %s - %s", + config_my_id->get_string(config_my_id), + config_other_id->get_string(config_other_id)); + + /* check other host first */ + if (other_id->belongs_to(other_id, config_other_id)) + { + /* get it if my_id not specified */ + if (my_id->belongs_to(my_id, config_my_id)) + { + found = current->clone(current); + break; + } + } + } + iterator->destroy(iterator); + + /* apply IDs as they are requsted, since they may be configured as %any or such */ + if (found) + { + found->update_my_id(found, my_id->clone(my_id)); + found->update_other_id(found, other_id->clone(other_id)); + } + return found; +} + +/** + * Implementation of policy_store_t.destroy. + */ +static void destroy(private_local_policy_store_t *this) +{ + policy_t *policy; + + while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) + { + policy->destroy(policy); + } + this->policies->destroy(this->policies); + free(this); +} + +/** + * Described in header. + */ +local_policy_store_t *local_policy_store_create(void) +{ + private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t); + + this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy; + this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy; + this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy; + + /* private variables */ + this->policies = linked_list_create(); + this->logger = logger_manager->get_logger(logger_manager, CONFIG); + + return (&this->public); +} diff --git a/src/charon/config/policies/local_policy_store.h b/src/charon/config/policies/local_policy_store.h new file mode 100644 index 000000000..ce9b33d71 --- /dev/null +++ b/src/charon/config/policies/local_policy_store.h @@ -0,0 +1,60 @@ +/** + * @file local_policy_store.h + * + * @brief Interface of local_policy_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_POLICY_STORE_H_ +#define LOCAL_POLICY_STORE_H_ + +#include <types.h> +#include <config/policies/policy_store.h> + + +typedef struct local_policy_store_t local_policy_store_t; + +/** + * @brief A policy_store_t implementation using a simple policy lists. + * + * The local_policy_store_t class implements the policy_store_t interface + * as simple as possible. The policies are stored in a in-memory list. + * + * @b Constructors: + * - local_policy_store_create() + * + * @ingroup config + */ +struct local_policy_store_t { + + /** + * Implements policy_store_t interface + */ + policy_store_t policy_store; +}; + +/** + * @brief Creates a local_policy_store_t instance. + * + * @return policy store instance. + * + * @ingroup config + */ +local_policy_store_t *local_policy_store_create(void); + +#endif /* LOCAL_POLICY_STORE_H_ */ diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c new file mode 100644 index 000000000..cff87fc6b --- /dev/null +++ b/src/charon/config/policies/policy.c @@ -0,0 +1,397 @@ +/** + * @file policy.c + * + * @brief Implementation of policy_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 "policy.h" + +#include <utils/linked_list.h> +#include <utils/identification.h> +#include <utils/logger.h> + +typedef struct private_policy_t private_policy_t; + +/** + * Private data of an policy_t object + */ +struct private_policy_t { + + /** + * Public part + */ + policy_t public; + + /** + * id to use to identify us + */ + identification_t *my_id; + + /** + * allowed id for other + */ + identification_t *other_id; + + /** + * list for all proposals + */ + linked_list_t *proposals; + + /** + * list for traffic selectors for my site + */ + linked_list_t *my_ts; + + /** + * list for traffic selectors for others site + */ + linked_list_t *other_ts; + + /** + * select_traffic_selectors for both + */ + linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*); +}; + +/** + * Implementation of policy_t.get_my_id + */ +static identification_t *get_my_id(private_policy_t *this) +{ + return this->my_id; +} + +/** + * Implementation of policy_t.get_other_id + */ +static identification_t *get_other_id(private_policy_t *this) +{ + return this->other_id; +} + +/** + * Implementation of policy_t.update_my_id + */ +static void update_my_id(private_policy_t *this, identification_t *my_id) +{ + this->my_id->destroy(this->my_id); + this->my_id = my_id; +} + +/** + * Implementation of policy_t.update_other_id + */ +static void update_other_id(private_policy_t *this, identification_t *other_id) +{ + this->other_id->destroy(this->other_id); + this->other_id = other_id; +} + +/** + * Helper function which does the work for policy_t.update_my_ts and update_other_ts + */ +static void update_ts(linked_list_t* list, host_t *new_host) +{ + traffic_selector_t *ts; + iterator_t *iterator; + + iterator = list->create_iterator(list, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts->update_address_range(ts, new_host); + } + iterator->destroy(iterator); +} + +/** + * Implementation of policy_t.update_my_id + */ +static void update_my_ts(private_policy_t *this, host_t *my_host) +{ + update_ts(this->my_ts, my_host); +} + +/** + * Implementation of policy_t.update_other_ts + */ +static void update_other_ts(private_policy_t *this, host_t *my_host) +{ + update_ts(this->other_ts, my_host); +} + +/** + * Implementation of policy_t.get_my_traffic_selectors + */ +static linked_list_t *get_my_traffic_selectors(private_policy_t *this) +{ + return this->my_ts; +} + +/** + * Implementation of policy_t.get_other_traffic_selectors + */ +static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[]) +{ + return this->other_ts; +} + +/** + * Implementation of private_policy_t.select_my_traffic_selectors + */ +static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied) +{ + return this->select_traffic_selectors(this, this->my_ts, supplied); +} + +/** + * Implementation of private_policy_t.select_other_traffic_selectors + */ +static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied) +{ + return this->select_traffic_selectors(this, this->other_ts, supplied); +} +/** + * Implementation of private_policy_t.select_traffic_selectors + */ +static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied) +{ + iterator_t *supplied_iter, *stored_iter; + traffic_selector_t *supplied_ts, *stored_ts, *selected_ts; + linked_list_t *selected = linked_list_create(); + + + stored_iter = stored->create_iterator(stored, TRUE); + supplied_iter = supplied->create_iterator(supplied, TRUE); + + /* iterate over all stored selectors */ + while (stored_iter->has_next(stored_iter)) + { + stored_iter->current(stored_iter, (void**)&stored_ts); + + supplied_iter->reset(supplied_iter); + /* iterate over all supplied traffic selectors */ + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied_ts); + + selected_ts = stored_ts->get_subset(stored_ts, supplied_ts); + if (selected_ts) + { + /* got a match, add to list */ + selected->insert_last(selected, (void*)selected_ts); + } + } + } + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return selected; +} + +/** + * Implementation of policy_t.get_proposal_iterator + */ +static linked_list_t *get_proposals(private_policy_t *this) +{ + return this->proposals; +} + +/** + * Implementation of policy_t.select_proposal + */ +static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals) +{ + iterator_t *stored_iter, *supplied_iter; + proposal_t *stored, *supplied, *selected; + + 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->has_next(stored_iter)) + { + supplied_iter->reset(supplied_iter); + stored_iter->current(stored_iter, (void**)&stored); + + while (supplied_iter->has_next(supplied_iter)) + { + supplied_iter->current(supplied_iter, (void**)&supplied); + selected = stored->select(stored, supplied); + if (selected) + { + /* they match, return */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + return selected; + } + } + } + + /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ + stored_iter->destroy(stored_iter); + supplied_iter->destroy(supplied_iter); + + return NULL; +} + +/** + * Implementation of policy_t.add_my_traffic_selector + */ +static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) +{ + this->my_ts->insert_last(this->my_ts, (void*)traffic_selector); +} + +/** + * Implementation of policy_t.add_other_traffic_selector + */ +static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) +{ + this->other_ts->insert_last(this->other_ts, (void*)traffic_selector); +} + +/** + * Implementation of policy_t.add_proposal + */ +static void add_proposal(private_policy_t *this, proposal_t *proposal) +{ + this->proposals->insert_last(this->proposals, (void*)proposal); +} + +/** + * Implements policy_t.destroy. + */ +static status_t destroy(private_policy_t *this) +{ + proposal_t *proposal; + traffic_selector_t *traffic_selector; + + + /* delete proposals */ + while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS) + { + proposal->destroy(proposal); + } + this->proposals->destroy(this->proposals); + + /* delete traffic selectors */ + while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS) + { + traffic_selector->destroy(traffic_selector); + } + this->my_ts->destroy(this->my_ts); + + /* delete traffic selectors */ + while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS) + { + traffic_selector->destroy(traffic_selector); + } + this->other_ts->destroy(this->other_ts); + + /* delete ids */ + this->my_id->destroy(this->my_id); + this->other_id->destroy(this->other_id); + + free(this); + return SUCCESS; +} + +/** + * Implements policy_t.clone. + */ +static policy_t *clone(private_policy_t *this) +{ + private_policy_t *clone = (private_policy_t*)policy_create(this->my_id->clone(this->my_id), + this->other_id->clone(this->other_id)); + iterator_t *iterator; + proposal_t *proposal; + traffic_selector_t *ts; + + /* clone all proposals */ + iterator = this->proposals->create_iterator(this->proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&proposal); + proposal = proposal->clone(proposal); + clone->proposals->insert_last(clone->proposals, (void*)proposal); + } + iterator->destroy(iterator); + + /* clone all local traffic selectors */ + iterator = this->my_ts->create_iterator(this->my_ts, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts = ts->clone(ts); + clone->my_ts->insert_last(clone->my_ts, (void*)ts); + } + iterator->destroy(iterator); + + /* clone all remote traffic selectors */ + iterator = this->other_ts->create_iterator(this->other_ts, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&ts); + ts = ts->clone(ts); + clone->other_ts->insert_last(clone->other_ts, (void*)ts); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/* + * Described in header-file + */ +policy_t *policy_create(identification_t *my_id, identification_t *other_id) +{ + private_policy_t *this = malloc_thing(private_policy_t); + + /* public functions */ + this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id; + this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id; + this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id; + this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id; + this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts; + this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts; + this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors; + this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors; + this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors; + this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors; + this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals; + this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal; + this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector; + this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector; + this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal; + this->public.clone = (policy_t*(*)(policy_t*))clone; + this->public.destroy = (void(*)(policy_t*))destroy; + + /* apply init values */ + this->my_id = my_id; + this->other_id = other_id; + + /* init private members*/ + this->select_traffic_selectors = select_traffic_selectors; + this->proposals = linked_list_create(); + this->my_ts = linked_list_create(); + this->other_ts = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h new file mode 100644 index 000000000..78cda1e8b --- /dev/null +++ b/src/charon/config/policies/policy.h @@ -0,0 +1,249 @@ +/** + * @file policy.h + * + * @brief Interface of policy_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 POLICY_H_ +#define POLICY_H_ + +#include <types.h> +#include <utils/identification.h> +#include <config/traffic_selector.h> +#include <config/proposal.h> +#include <encoding/payloads/auth_payload.h> + + +typedef struct policy_t policy_t; + +/** + * @brief A policy_t defines the policies to apply to CHILD_SAs. + * + * The given two IDs identify a policy. These rules define how + * child SAs may be set up and which traffic may be IPsec'ed. + * + * @b Constructors: + * - policy_create() + * + * @ingroup config + */ +struct policy_t { + + /** + * @brief Get own id to use for identification. + * + * Returned object is not getting cloned. + * + * @param this calling object + * @return own id + */ + identification_t *(*get_my_id) (policy_t *this); + + /** + * @brief Get id of communication partner. + * + * Returned object is not getting cloned. + * + * @param this calling object + * @return other id + */ + identification_t *(*get_other_id) (policy_t *this); + + /** + * @brief Update own ID. + * + * It may be necessary to uptdate own ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param my_id new ID to set as my_id + */ + void (*update_my_id) (policy_t *this, identification_t *my_id); + + /** + * @brief Update others ID. + * + * It may be necessary to uptdate others ID, as it + * is set to %any or to e.g. *@strongswan.org in + * some cases. + * Old ID is destroyed, new one NOT cloned. + * + * @param this calling object + * @param other_id new ID to set as other_id + */ + void (*update_other_id) (policy_t *this, identification_t *other_id); + + /** + * @brief Update own address in traffic selectors. + * + * Update own 0.0.0.0 address in traffic selectors + * with supplied one. The size of the subnet will be + * set to /32. + * + * @param this calling object + * @param my_host new address to set in traffic selectors + */ + void (*update_my_ts) (policy_t *this, host_t *my_host); + + /** + * @brief Update others address in traffic selectors. + * + * Update remote 0.0.0.0 address in traffic selectors + * with supplied one. The size of the subnet will be + * set to /32. + * + * @param this calling object + * @param other_host new address to set in traffic selectors + */ + void (*update_other_ts) (policy_t *this, host_t *other_host); + + /** + * @brief Get configured traffic selectors for our site. + * + * Returns a list with all traffic selectors for the local + * site. List and items MUST NOT be freed nor modified. + * + * @param this calling object + * @return list with traffic selectors + */ + linked_list_t *(*get_my_traffic_selectors) (policy_t *this); + + /** + * @brief Get configured traffic selectors for others site. + * + * Returns a list with all traffic selectors for the remote + * site. List and items MUST NOT be freed nor modified. + * + * @param this calling object + * @return list with traffic selectors + */ + linked_list_t *(*get_other_traffic_selectors) (policy_t *this); + + /** + * @brief Select traffic selectors from a supplied list for local site. + * + * Resulted list and traffic selectors must be destroyed after usage. + * + * @param this calling object + * @param supplied linked list with traffic selectors + * @return list containing the selected traffic selectors + */ + linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied); + + /** + * @brief Select traffic selectors from a supplied list for remote site. + * + * Resulted list and traffic selectors must be destroyed after usage. + * + * @param this calling object + * @param supplied linked list with traffic selectors + * @return list containing the selected traffic selectors + */ + linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied); + + /** + * @brief Get the list of internally stored proposals. + * + * Rembember: policy_t does store proposals for AH/ESP, + * IKE proposals are in the connection_t + * + * @warning List and Items are still owned by policy and MUST NOT + * be manipulated or freed! + * + * @param this calling object + * @return lists with proposals + */ + linked_list_t *(*get_proposals) (policy_t *this); + + /** + * @brief Select a proposal from a supplied list. + * + * @param this calling object + * @param proposals list from from wich proposals are selected + * @return selected proposal, or NULL if nothing matches + */ + proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals); + + /** + * @brief Add a traffic selector to the list for local site. + * + * After add, proposal is owned by policy. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param traffic_selector traffic_selector to add + */ + void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); + + /** + * @brief Add a traffic selector to the list for remote site. + * + * After add, proposal is owned by policy. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param traffic_selector traffic_selector to add + */ + void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector); + + /** + * @brief Add a proposal to the list. + * + * The proposals are stored by priority, first added + * is the most prefered. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param proposal proposal to add + */ + void (*add_proposal) (policy_t *this, proposal_t *proposal); + + /** + * @brief Clone a policy. + * + * @param this policy to clone + * @return clone of it + */ + policy_t *(*clone) (policy_t *this); + + /** + * @brief Destroys the policy object + * + * @param this calling object + */ + void (*destroy) (policy_t *this); +}; + +/** + * @brief Create a configuration object for IKE_AUTH and later. + * + * @param my_id identification_t for ourselves + * @param other_id identification_t for the remote guy + * @return policy_t object + * + * @ingroup config + */ +policy_t *policy_create(identification_t *my_id, identification_t *other_id); + +#endif /* POLICY_H_ */ diff --git a/src/charon/config/policies/policy_store.h b/src/charon/config/policies/policy_store.h new file mode 100755 index 000000000..651dea634 --- /dev/null +++ b/src/charon/config/policies/policy_store.h @@ -0,0 +1,76 @@ +/** + * @file policy_store.h + * + * @brief Interface policy_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 POLICY_STORE_H_ +#define POLICY_STORE_H_ + +#include <types.h> +#include <config/policies/policy.h> + + +typedef struct policy_store_t policy_store_t; + +/** + * @brief The interface for a store of policy_t's. + * + * @b Constructors: + * - stroke_create() + * + * @ingroup config + */ +struct policy_store_t { + + /** + * @brief Returns a policy identified by two IDs. + * + * The returned policy gets created/cloned and therefore must be + * destroyed by the caller. + * + * @param this calling object + * @param my_id own ID of the policy + * @param other_id others ID of the policy + * @return + * - matching policy_t, if found + * - NULL otherwise + */ + policy_t *(*get_policy) (policy_store_t *this, identification_t *my_id, identification_t *other_id); + + /** + * @brief Add a policy to the list. + * + * The policy is owned by the store after the call. Do + * not modify nor free. + * + * @param this calling object + * @param policy policy to add + */ + void (*add_policy) (policy_store_t *this, policy_t *policy); + + /** + * @brief Destroys a policy_store_t object. + * + * @param this calling object + */ + void (*destroy) (policy_store_t *this); +}; + +#endif /*POLICY_STORE_H_*/ diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c new file mode 100644 index 000000000..cb71a756a --- /dev/null +++ b/src/charon/config/proposal.c @@ -0,0 +1,642 @@ +/** + * @file proposal.c + * + * @brief Implementation of proposal_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 "proposal.h" + +#include <utils/linked_list.h> +#include <utils/identification.h> +#include <utils/logger.h> + + +/** + * String mappings for protocol_id_t. + */ +mapping_t protocol_id_m[] = { + {PROTO_NONE, "PROTO_NONE"}, + {PROTO_IKE, "PROTO_IKE"}, + {PROTO_AH, "PROTO_AH"}, + {PROTO_ESP, "PROTO_ESP"}, + {MAPPING_END, NULL} +}; + +/** + * String mappings for transform_type_t. + */ +mapping_t transform_type_m[] = { + {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"}, + {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"}, + {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"}, + {INTEGRITY_ALGORITHM, "INTEGRITY_ALGORITHM"}, + {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"}, + {EXTENDED_SEQUENCE_NUMBERS, "EXTENDED_SEQUENCE_NUMBERS"}, + {MAPPING_END, NULL} +}; + +/** + * String mappings for extended_sequence_numbers_t. + */ +mapping_t extended_sequence_numbers_m[] = { + {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"}, + {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"}, + {MAPPING_END, NULL} +}; + + +typedef struct protocol_proposal_t protocol_proposal_t; + +/** + * substructure which holds all data algos for a specific protocol + */ +struct protocol_proposal_t { + /** + * protocol (ESP or AH) + */ + protocol_id_t protocol; + + /** + * priority ordered list of encryption algorithms + */ + linked_list_t *encryption_algos; + + /** + * priority ordered list of integrity algorithms + */ + linked_list_t *integrity_algos; + + /** + * priority ordered list of pseudo random functions + */ + linked_list_t *prf_algos; + + /** + * priority ordered list of dh groups + */ + linked_list_t *dh_groups; + + /** + * priority ordered list of extended sequence number flags + */ + linked_list_t *esns; + + /** + * senders SPI + */ + chunk_t spi; +}; + + +typedef struct private_proposal_t private_proposal_t; + +/** + * Private data of an proposal_t object + */ +struct private_proposal_t { + + /** + * Public part + */ + proposal_t public; + + /** + * number of this proposal, as used in the payload + */ + u_int8_t number; + + /** + * list of protocol_proposal_t's + */ + linked_list_t *protocol_proposals; +}; + +/** + * Look up a protocol_proposal, or create one if necessary... + */ +static protocol_proposal_t *get_protocol_proposal(private_proposal_t *this, protocol_id_t proto, bool create) +{ + protocol_proposal_t *proto_proposal = NULL, *current_proto_proposal;; + iterator_t *iterator; + + /* find our protocol in the proposals */ + iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t_proto_proposal); + if (current_proto_proposal->protocol == proto) + { + proto_proposal = current_proto_proposal; + break; + } + } + iterator->destroy(iterator); + + if (!proto_proposal && create) + { + /* nope, create a new one */ + proto_proposal = malloc_thing(protocol_proposal_t); + proto_proposal->protocol = proto; + proto_proposal->encryption_algos = linked_list_create(); + proto_proposal->integrity_algos = linked_list_create(); + proto_proposal->prf_algos = linked_list_create(); + proto_proposal->dh_groups = linked_list_create(); + proto_proposal->esns = linked_list_create(); + if (proto == PROTO_IKE) + { + proto_proposal->spi.len = 8; + } + else + { + proto_proposal->spi.len = 4; + } + proto_proposal->spi.ptr = malloc(proto_proposal->spi.len); + /* add to the list */ + this->protocol_proposals->insert_last(this->protocol_proposals, (void*)proto_proposal); + } + return proto_proposal; +} + +/** + * Add algorithm/keysize to a algorithm list + */ +static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size) +{ + algorithm_t *algo_key = malloc_thing(algorithm_t); + + algo_key->algorithm = algo; + algo_key->key_size = key_size; + list->insert_last(list, (void*)algo_key); +} + +/** + * Implements proposal_t.add_algorithm + */ +static void add_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t algo, size_t key_size) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, TRUE); + + switch (type) + { + case ENCRYPTION_ALGORITHM: + add_algo(proto_proposal->encryption_algos, algo, key_size); + break; + case INTEGRITY_ALGORITHM: + add_algo(proto_proposal->integrity_algos, algo, key_size); + break; + case PSEUDO_RANDOM_FUNCTION: + add_algo(proto_proposal->prf_algos, algo, key_size); + break; + case DIFFIE_HELLMAN_GROUP: + add_algo(proto_proposal->dh_groups, algo, 0); + break; + case EXTENDED_SEQUENCE_NUMBERS: + add_algo(proto_proposal->esns, algo, 0); + break; + default: + break; + } +} + +/** + * Implements proposal_t.get_algorithm. + */ +static bool get_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo) +{ + linked_list_t * list; + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + + if (proto_proposal == NULL) + { + return FALSE; + } + switch (type) + { + case ENCRYPTION_ALGORITHM: + list = proto_proposal->encryption_algos; + break; + case INTEGRITY_ALGORITHM: + list = proto_proposal->integrity_algos; + break; + case PSEUDO_RANDOM_FUNCTION: + list = proto_proposal->prf_algos; + break; + case DIFFIE_HELLMAN_GROUP: + list = proto_proposal->dh_groups; + break; + case EXTENDED_SEQUENCE_NUMBERS: + list = proto_proposal->esns; + break; + default: + return FALSE; + } + if (list->get_first(list, (void**)algo) != SUCCESS) + { + return FALSE; + } + return TRUE; +} + +/** + * Implements proposal_t.create_algorithm_iterator. + */ +static iterator_t *create_algorithm_iterator(private_proposal_t *this, protocol_id_t proto, transform_type_t type) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal == NULL) + { + return NULL; + } + + switch (type) + { + case ENCRYPTION_ALGORITHM: + return proto_proposal->encryption_algos->create_iterator(proto_proposal->encryption_algos, TRUE); + case INTEGRITY_ALGORITHM: + return proto_proposal->integrity_algos->create_iterator(proto_proposal->integrity_algos, TRUE); + case PSEUDO_RANDOM_FUNCTION: + return proto_proposal->prf_algos->create_iterator(proto_proposal->prf_algos, TRUE); + case DIFFIE_HELLMAN_GROUP: + return proto_proposal->dh_groups->create_iterator(proto_proposal->dh_groups, TRUE); + case EXTENDED_SEQUENCE_NUMBERS: + return proto_proposal->esns->create_iterator(proto_proposal->esns, TRUE); + default: + break; + } + return NULL; +} + +/** + * 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) +{ + iterator_t *first_iter, *second_iter; + algorithm_t *first_alg, *second_alg; + + /* if in both are zero algorithms specified, we HAVE a match */ + if (first->get_count(first) == 0 && second->get_count(second) == 0) + { + *add = FALSE; + return TRUE; + } + + first_iter = first->create_iterator(first, TRUE); + second_iter = second->create_iterator(second, TRUE); + /* compare algs, order of algs in "first" is preferred */ + while (first_iter->has_next(first_iter)) + { + first_iter->current(first_iter, (void**)&first_alg); + second_iter->reset(second_iter); + while (second_iter->has_next(second_iter)) + { + second_iter->current(second_iter, (void**)&second_alg); + if (first_alg->algorithm == second_alg->algorithm && + first_alg->key_size == second_alg->key_size) + { + /* ok, we have an algorithm */ + *alg = first_alg->algorithm; + *key_size = first_alg->key_size; + *add = TRUE; + first_iter->destroy(first_iter); + second_iter->destroy(second_iter); + return TRUE; + } + } + } + /* no match in all comparisons */ + first_iter->destroy(first_iter); + second_iter->destroy(second_iter); + return FALSE; +} + +/** + * Implements proposal_t.select. + */ +static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other) +{ + proposal_t *selected; + u_int16_t algo; + size_t key_size; + iterator_t *iterator; + protocol_proposal_t *this_prop, *other_prop; + protocol_id_t proto; + bool add; + u_int64_t spi; + + /* empty proposal? no match */ + if (this->protocol_proposals->get_count(this->protocol_proposals) == 0 || + other->protocol_proposals->get_count(other->protocol_proposals) == 0) + { + return NULL; + } + /* they MUST have the same amount of protocols */ + if (this->protocol_proposals->get_count(this->protocol_proposals) != + other->protocol_proposals->get_count(other->protocol_proposals)) + { + return NULL; + } + + selected = proposal_create(this->number); + + /* iterate over supplied proposals */ + iterator = other->protocol_proposals->create_iterator(other->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&other_prop); + /* get the proposal with the same protocol */ + proto = other_prop->protocol; + this_prop = get_protocol_proposal(this, proto, FALSE); + + if (this_prop == NULL) + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + + /* select encryption algorithm */ + if (select_algo(this_prop->encryption_algos, other_prop->encryption_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, ENCRYPTION_ALGORITHM, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select integrity algorithm */ + if (select_algo(this_prop->integrity_algos, other_prop->integrity_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, INTEGRITY_ALGORITHM, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select prf algorithm */ + if (select_algo(this_prop->prf_algos, other_prop->prf_algos, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, PSEUDO_RANDOM_FUNCTION, algo, key_size); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select a DH-group */ + if (select_algo(this_prop->dh_groups, other_prop->dh_groups, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, DIFFIE_HELLMAN_GROUP, algo, 0); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + /* select if we use ESNs */ + if (select_algo(this_prop->esns, other_prop->esns, &add, &algo, &key_size)) + { + if (add) + { + selected->add_algorithm(selected, proto, EXTENDED_SEQUENCE_NUMBERS, algo, 0); + } + } + else + { + iterator->destroy(iterator); + selected->destroy(selected); + return NULL; + } + } + iterator->destroy(iterator); + + /* apply spis from "other" */ + spi = other->public.get_spi(&(other->public), PROTO_AH); + if (spi) + { + selected->set_spi(selected, PROTO_AH, spi); + } + spi = other->public.get_spi(&(other->public), PROTO_ESP); + if (spi) + { + selected->set_spi(selected, PROTO_ESP, spi); + } + + /* everything matched, return new proposal */ + return selected; +} + +/** + * Implements proposal_t.get_number. + */ +static u_int8_t get_number(private_proposal_t *this) +{ + return this->number; +} + +/** + * Implements proposal_t.get_protocols. + */ +static void get_protocols(private_proposal_t *this, protocol_id_t ids[2]) +{ + iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + u_int i = 0; + + ids[0] = PROTO_NONE; + ids[1] = PROTO_NONE; + while (iterator->has_next(iterator)) + { + protocol_proposal_t *proto_prop; + iterator->current(iterator, (void**)&proto_prop); + ids[i++] = proto_prop->protocol; + if (i>1) + { + /* should not happen, but who knows */ + break; + } + } + iterator->destroy(iterator); +} + +/** + * Implements proposal_t.set_spi. + */ +static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal) + { + if (proto == PROTO_AH || proto == PROTO_ESP) + { + *((u_int32_t*)proto_proposal->spi.ptr) = (u_int32_t)spi; + } + else + { + *((u_int64_t*)proto_proposal->spi.ptr) = spi; + } + } +} + +/** + * Implements proposal_t.get_spi. + */ +static u_int64_t get_spi(private_proposal_t *this, protocol_id_t proto) +{ + protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE); + if (proto_proposal) + { + if (proto == PROTO_AH || proto == PROTO_ESP) + { + return (u_int64_t)*((u_int32_t*)proto_proposal->spi.ptr); + } + else + { + return *((u_int64_t*)proto_proposal->spi.ptr); + } + } + return 0; +} + +/** + * Clone a algorithm list + */ +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->has_next(iterator)) + { + iterator->current(iterator, (void**)&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); +} + +/** + * Implements proposal_t.clone + */ +static proposal_t *clone(private_proposal_t *this) +{ + private_proposal_t *clone = (private_proposal_t*)proposal_create(this->number); + + iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE); + while (iterator->has_next(iterator)) + { + protocol_proposal_t *proto_prop, *clone_proto_prop; + iterator->current(iterator, (void**)&proto_prop); + + clone_proto_prop = get_protocol_proposal(clone, proto_prop->protocol, TRUE); + memcpy(clone_proto_prop->spi.ptr, proto_prop->spi.ptr, clone_proto_prop->spi.len); + + clone_algo_list(proto_prop->encryption_algos, clone_proto_prop->encryption_algos); + clone_algo_list(proto_prop->integrity_algos, clone_proto_prop->integrity_algos); + clone_algo_list(proto_prop->prf_algos, clone_proto_prop->prf_algos); + clone_algo_list(proto_prop->dh_groups, clone_proto_prop->dh_groups); + clone_algo_list(proto_prop->esns, clone_proto_prop->esns); + } + iterator->destroy(iterator); + + return &clone->public; +} + +/** + * Frees all list items and destroys the list + */ +static void free_algo_list(linked_list_t *list) +{ + algorithm_t *algo; + + while(list->get_count(list) > 0) + { + list->remove_last(list, (void**)&algo); + free(algo); + } + list->destroy(list); +} + +/** + * Implements proposal_t.destroy. + */ +static void destroy(private_proposal_t *this) +{ + while(this->protocol_proposals->get_count(this->protocol_proposals) > 0) + { + protocol_proposal_t *proto_prop; + this->protocol_proposals->remove_last(this->protocol_proposals, (void**)&proto_prop); + + free_algo_list(proto_prop->encryption_algos); + free_algo_list(proto_prop->integrity_algos); + free_algo_list(proto_prop->prf_algos); + free_algo_list(proto_prop->dh_groups); + free_algo_list(proto_prop->esns); + + free(proto_prop->spi.ptr); + free(proto_prop); + } + this->protocol_proposals->destroy(this->protocol_proposals); + + free(this); +} + +/* + * Describtion in header-file + */ +proposal_t *proposal_create(u_int8_t number) +{ + private_proposal_t *this = malloc_thing(private_proposal_t); + + this->public.add_algorithm = (void (*)(proposal_t*,protocol_id_t,transform_type_t,u_int16_t,size_t))add_algorithm; + this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,protocol_id_t,transform_type_t))create_algorithm_iterator; + this->public.get_algorithm = (bool (*)(proposal_t*,protocol_id_t,transform_type_t,algorithm_t**))get_algorithm; + this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; + this->public.get_number = (u_int8_t (*)(proposal_t*))get_number; + this->public.get_protocols = (void(*)(proposal_t *this, protocol_id_t ids[2]))get_protocols; + this->public.set_spi = (void(*)(proposal_t*,protocol_id_t,u_int64_t spi))set_spi; + this->public.get_spi = (u_int64_t(*)(proposal_t*,protocol_id_t))get_spi; + this->public.clone = (proposal_t*(*)(proposal_t*))clone; + this->public.destroy = (void(*)(proposal_t*))destroy; + + /* init private members*/ + this->number = number; + this->protocol_proposals = linked_list_create(); + + return (&this->public); +} diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h new file mode 100644 index 000000000..48e3ad8d5 --- /dev/null +++ b/src/charon/config/proposal.h @@ -0,0 +1,269 @@ +/** + * @file proposal.h + * + * @brief Interface of proposal_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 PROPOSAL_H_ +#define PROPOSAL_H_ + +#include <types.h> +#include <utils/identification.h> +#include <utils/linked_list.h> +#include <utils/host.h> +#include <crypto/crypters/crypter.h> +#include <crypto/signers/signer.h> +#include <crypto/diffie_hellman.h> +#include <config/traffic_selector.h> + + +typedef enum protocol_id_t protocol_id_t; + +/** + * Protocol ID of a proposal. + * + * @ingroup config + */ +enum protocol_id_t { + PROTO_NONE = 0, + PROTO_IKE = 1, + PROTO_AH = 2, + PROTO_ESP = 3, +}; + +/** + * String mappings for protocol_id_t. + * + * @ingroup config + */ +extern mapping_t protocol_id_m[]; + + +typedef enum transform_type_t transform_type_t; + +/** + * Type of a transform, as in IKEv2 RFC 3.3.2. + * + * @ingroup payloads + */ +enum transform_type_t { + UNDEFINED_TRANSFORM_TYPE = 241, + ENCRYPTION_ALGORITHM = 1, + PSEUDO_RANDOM_FUNCTION = 2, + INTEGRITY_ALGORITHM = 3, + DIFFIE_HELLMAN_GROUP = 4, + EXTENDED_SEQUENCE_NUMBERS = 5 +}; + +/** + * String mappings for transform_type_t. + * + * @ingroup payloads + */ +extern mapping_t transform_type_m[]; + + +typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; + +/** + * Extended sequence numbers, as in IKEv2 RFC 3.3.2. + * + * @ingroup payloads + */ +enum extended_sequence_numbers_t { + NO_EXT_SEQ_NUMBERS = 0, + EXT_SEQ_NUMBERS = 1 +}; + +/** + * String mappings for extended_sequence_numbers_t. + * + * @ingroup payloads + */ +extern mapping_t extended_sequence_numbers_m[]; + + +typedef struct algorithm_t algorithm_t; + +/** + * Struct used to store different kinds of algorithms. The internal + * lists of algorithms contain such structures. + */ +struct algorithm_t { + /** + * Value from an encryption_algorithm_t/integrity_algorithm_t/... + */ + u_int16_t algorithm; + + /** + * the associated key size, or zero if not needed + */ + u_int16_t key_size; +}; + +typedef struct proposal_t proposal_t; + +/** + * @brief Stores a set of algorithms used for an SA. + * + * A proposal stores algorithms for a specific + * protocol. It can store algorithms for more than + * one protocol (e.g. AH and ESP). Then the proposal + * means both protocols must be used. + * A proposal may contain more than one algorithm + * of the same kind. ONE of them can be selected. + * + * @warning This class is NOT thread-save! + * + * @b Constructors: + * - proposal_create() + * + * @ingroup config + */ +struct proposal_t { + + /** + * @brief Add an algorithm to the proposal. + * + * The algorithms are stored by priority, first added + * is the most preferred. + * Key size is only needed for encryption algorithms + * with variable key size (such as AES). Must be set + * to zero if key size is not specified. + * The alg parameter accepts encryption_algorithm_t, + * integrity_algorithm_t, dh_group_number_t and + * extended_sequence_numbers_t. + * + * @warning Do not add while other threads are reading. + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @param alg identifier for algorithm + * @param key_size key size to use + */ + void (*add_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t alg, size_t key_size); + + /** + * @brief Get an iterator over algorithms for a specifc protocol/algo type. + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @return iterator over algorithms + */ + iterator_t *(*create_algorithm_iterator) (proposal_t *this, protocol_id_t proto, transform_type_t type); + + /** + * @brief Get the algorithm for a type to use. + * + * If there are multiple algorithms, only the first is returned. + * Result is still owned by proposal, do not modify! + * + * @param this calling object + * @param proto desired protocol + * @param type kind of algorithm + * @param[out] algo pointer which receives algorithm and key size + * @return TRUE if algorithm of this kind available + */ + bool (*get_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo); + + /** + * @brief 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 + */ + proposal_t *(*select) (proposal_t *this, proposal_t *other); + + /** + * @brief Get the number set on construction. + * + * @param this calling object + * @return number + */ + u_int8_t (*get_number) (proposal_t *this); + + /** + * @brief Get the protocol ids in the proposals. + * + * With AH and ESP, there could be two protocols in one + * proposal. + * + * @param this calling object + * @param ids array of protocol ids, + */ + void (*get_protocols) (proposal_t *this, protocol_id_t ids[2]); + + /** + * @brief Get the spi for a specific protocol. + * + * @param this calling object + * @param proto AH/ESP + * @return spi for proto + */ + u_int64_t (*get_spi) (proposal_t *this, protocol_id_t proto); + + /** + * @brief Set the spi for a specific protocol. + * + * @param this calling object + * @param proto AH/ESP + * @param spi spi to set for proto + */ + void (*set_spi) (proposal_t *this, protocol_id_t proto, u_int64_t spi); + + /** + * @brief Clone a proposal. + * + * @param this proposal to clone + * @return clone of it + */ + proposal_t *(*clone) (proposal_t *this); + + /** + * @brief Destroys the proposal object. + * + * @param this calling object + */ + void (*destroy) (proposal_t *this); +}; + +/** + * @brief Create a child proposal for AH and/or ESP. + * + * Since the order of multiple proposals is important for + * key derivation, we must assign them numbers as they + * appear in the raw payload. Numbering starts at 1. + * + * @param number number of the proposal, as in the payload + * @return proposal_t object + * + * @ingroup config + */ +proposal_t *proposal_create(u_int8_t number); + +#endif /* PROPOSAL_H_ */ diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c new file mode 100644 index 000000000..81272659a --- /dev/null +++ b/src/charon/config/traffic_selector.c @@ -0,0 +1,425 @@ +/** + * @file traffic_selector.c + * + * @brief Implementation of traffic_selector_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 "traffic_selector.h" + +#include <utils/linked_list.h> +#include <utils/identification.h> +#include <arpa/inet.h> +#include <string.h> + +typedef struct private_traffic_selector_t private_traffic_selector_t; + +/** + * Private data of an traffic_selector_t object + */ +struct private_traffic_selector_t { + + /** + * Public part + */ + traffic_selector_t public; + + /** + * Type of address + */ + ts_type_t type; + + /** + * IP protocol (UDP, TCP, ICMP, ...) + */ + u_int8_t protocol; + + /** + * begin of address range, host order + */ + union { + u_int32_t from_addr_ipv4; + }; + + /** + * end of address range, host order + */ + union { + u_int32_t to_addr_ipv4; + }; + + /** + * begin of port range + */ + u_int16_t from_port; + + /** + * end of port range + */ + u_int16_t to_port; +}; + +/** + * internal generic constructor + */ +static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port); + +/** + * implements traffic_selector_t.get_subset + */ +static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other) +{ + if ((this->type == TS_IPV4_ADDR_RANGE) && + (other->type == TS_IPV4_ADDR_RANGE) && + (this->protocol == other->protocol)) + { + u_int32_t from_addr, to_addr; + u_int16_t from_port, to_port; + private_traffic_selector_t *new_ts; + + /* calculate the maximum address range allowed for both */ + from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4); + to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4); + if (from_addr > to_addr) + { + /* no match */ + return NULL; + } + + /* calculate the maximum port range allowed for both */ + from_port = max(this->from_port, other->from_port); + to_port = min(this->to_port, other->to_port); + if (from_port > to_port) + { + /* no match */ + return NULL; + } + + /* got a match, return it */ + new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port); + new_ts->from_addr_ipv4 = from_addr; + new_ts->to_addr_ipv4 = to_addr; + new_ts->type = TS_IPV4_ADDR_RANGE; + return &(new_ts->public); + } + return NULL; +} + +/** + * Implements traffic_selector_t.get_from_address. + */ +static chunk_t get_from_address(private_traffic_selector_t *this) +{ + chunk_t from_addr = CHUNK_INITIALIZER; + + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t network; + from_addr.len = sizeof(network); + from_addr.ptr = malloc(from_addr.len); + /* chunk must contain network order, convert! */ + network = htonl(this->from_addr_ipv4); + memcpy(from_addr.ptr, &network, from_addr.len); + break; + } + case TS_IPV6_ADDR_RANGE: + { + break; + } + } + return from_addr; +} + +/** + * Implements traffic_selector_t.get_to_address. + */ +static chunk_t get_to_address(private_traffic_selector_t *this) +{ + chunk_t to_addr = CHUNK_INITIALIZER; + + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t network; + to_addr.len = sizeof(network); + to_addr.ptr = malloc(to_addr.len); + /* chunk must contain network order, convert! */ + network = htonl(this->to_addr_ipv4); + memcpy(to_addr.ptr, &network, to_addr.len); + break; + } + case TS_IPV6_ADDR_RANGE: + { + break; + } + } + return to_addr; +} + +/** + * Implements traffic_selector_t.get_from_port. + */ +static u_int16_t get_from_port(private_traffic_selector_t *this) +{ + return this->from_port; +} + +/** + * Implements traffic_selector_t.get_to_port. + */ +static u_int16_t get_to_port(private_traffic_selector_t *this) +{ + return this->to_port; +} + +/** + * Implements traffic_selector_t.get_type. + */ +static ts_type_t get_type(private_traffic_selector_t *this) +{ + return this->type; +} + +/** + * Implements traffic_selector_t.get_protocol. + */ +static u_int8_t get_protocol(private_traffic_selector_t *this) +{ + return this->protocol; +} + +/** + * Implements traffic_selector_t.get_netmask. + */ +static u_int8_t get_netmask(private_traffic_selector_t *this) +{ + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + { + u_int32_t from, to, bit; + from = htonl(this->from_addr_ipv4); + to = htonl(this->to_addr_ipv4); + for (bit = 0; bit < 32; bit++) + { + if ((1<<bit & from) != (1<<bit & to)) + { + return bit; + } + } + return 32; + } + case TS_IPV6_ADDR_RANGE: + default: + { + return 0; + } + } +} + +/** + * Implements traffic_selector_t.update_address_range. + */ +static void update_address_range(private_traffic_selector_t *this, host_t *host) +{ + if (host->get_family(host) == AF_INET && + this->type == TS_IPV4_ADDR_RANGE) + { + if (this->from_addr_ipv4 == 0) + { + chunk_t from = host->get_address_as_chunk(host); + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); + this->to_addr_ipv4 = this->from_addr_ipv4; + chunk_free(&from); + } + } +} + +/** + * Implements traffic_selector_t.clone. + */ +static traffic_selector_t *clone(private_traffic_selector_t *this) +{ + private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port); + clone->type = this->type; + switch (clone->type) + { + case TS_IPV4_ADDR_RANGE: + { + clone->from_addr_ipv4 = this->from_addr_ipv4; + clone->to_addr_ipv4 = this->to_addr_ipv4; + return &(clone->public); + } + case TS_IPV6_ADDR_RANGE: + default: + { + free(this); + return NULL; + } + } +} + +/** + * Implements traffic_selector_t.destroy. + */ +static void destroy(private_traffic_selector_t *this) +{ + free(this); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port) +{ + private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); + + this->type = type; + switch (type) + { + case TS_IPV4_ADDR_RANGE: + { + if (from_addr.len != 4 || to_addr.len != 4) + { + free(this); + return NULL; + } + /* chunk contains network order, convert! */ + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr)); + this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr)); + break; + } + case TS_IPV6_ADDR_RANGE: + default: + { + free(this); + return NULL; + } + } + return (&this->public); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits) +{ + private_traffic_selector_t *this = traffic_selector_create(0, 0, 0, 65535); + + switch (net->get_family(net)) + { + case AF_INET: + { + chunk_t from; + + this->type = TS_IPV4_ADDR_RANGE; + from = net->get_address_as_chunk(net); + this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr)); + if (this->from_addr_ipv4 == 0) + { + /* use /32 for 0.0.0.0 */ + this->to_addr_ipv4 = 0xFFFFFF; + } + else + { + this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1); + } + chunk_free(&from); + break; + } + case AF_INET6: + default: + { + free(this); + return NULL; + } + } + return (&this->public); +} + +/* + * see header + */ +traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port) +{ + private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port); + + /* public functions */ + this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; + this->public.destroy = (void(*)(traffic_selector_t*))destroy; + + this->type = type; + switch (type) + { + case TS_IPV4_ADDR_RANGE: + { + if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0) + { + free(this); + return NULL; + } + if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0) + { + free(this); + return NULL; + } + /* convert to host order, inet_aton has network order */ + this->from_addr_ipv4 = ntohl(this->from_addr_ipv4); + this->to_addr_ipv4 = ntohl(this->to_addr_ipv4); + break; + } + case TS_IPV6_ADDR_RANGE: + { + free(this); + return NULL; + } + } + + return (&this->public); +} + +/* + * see declaration + */ +static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port) +{ + private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t); + + /* public functions */ + this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset; + this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address; + this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address; + this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port; + this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port; + this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type; + this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol; + this->public.get_netmask = (u_int8_t(*)(traffic_selector_t*))get_netmask; + this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range; + this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone; + this->public.destroy = (void(*)(traffic_selector_t*))destroy; + + this->from_port = from_port; + this->to_port = to_port; + this->protocol = protocol; + this->type = type; + + return this; +} diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h new file mode 100644 index 000000000..5ac5bdeb1 --- /dev/null +++ b/src/charon/config/traffic_selector.h @@ -0,0 +1,258 @@ +/** + * @file traffic_selector.h + * + * @brief Interface of traffic_selector_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, 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 TRAFFIC_SELECTOR_H_ +#define TRAFFIC_SELECTOR_H_ + +#include <types.h> +#include <utils/host.h> + +typedef enum ts_type_t ts_type_t; + +/** + * Traffic selector types. + * + * @ingroup config + */ +enum ts_type_t { + + /** + * A range of IPv4 addresses, represented by two four (4) octet + * values. The first value is the beginning IPv4 address + * (inclusive) and the second value is the ending IPv4 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV4_ADDR_RANGE = 7, + + /** + * A range of IPv6 addresses, represented by two sixteen (16) + * octet values. The first value is the beginning IPv6 address + * (inclusive) and the second value is the ending IPv6 address + * (inclusive). All addresses falling between the two specified + * addresses are considered to be within the list. + */ + TS_IPV6_ADDR_RANGE = 8 +}; + +/** + * string mappings for ts_type_t + */ +extern mapping_t ts_type_m[]; + + +typedef struct traffic_selector_t traffic_selector_t; + +/** + * @brief 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 + * 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 + * @return + * - created subset of them + * - or NULL if no match between this and other + */ + traffic_selector_t *(*get_subset) (traffic_selector_t *this, traffic_selector_t *other); + + /** + * @brief 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. + * + * Data is in network order and represents the address. + * Size depends on protocol. + * + * Resulting chunk data is allocated and must be freed! + * + * @param this calling 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. + * + * Data is in network order and represents the address. + * Size depends on protocol. + * + * Resulting chunk data is allocated and must be freed! + * + * @param this calling object + * @return chunk containing the address + */ + chunk_t (*get_to_address) (traffic_selector_t *this); + + /** + * @brief Get starting port of this ts. + * + * Port is in host order, since the parser converts it. + * Size depends on protocol. + * + * @param this calling object + * @return port + */ + u_int16_t (*get_from_port) (traffic_selector_t *this); + + /** + * @brief Get ending port of this ts. + * + * Port is in host order, since the parser converts it. + * Size depends on protocol. + * + * @param this calling object + * @return port + */ + u_int16_t (*get_to_port) (traffic_selector_t *this); + + /** + * @brief Get the type of the traffic selector. + * + * @param this calling obect + * @return ts_type_t specifying the type + */ + ts_type_t (*get_type) (traffic_selector_t *this); + + /** + * @brief Get the protocol id of this ts. + * + * @param this calling obect + * @return protocol id + */ + u_int8_t (*get_protocol) (traffic_selector_t *this); + + /** + * @brief Get the netmask of the address range. + * + * Returns the number of bits associated to the subnet. + * (As the "24" in "192.168.0.0/24"). This is approximated + * if the address range is not a complete subnet! Since Linux + * does not support full IP address ranges (yet), we can't do this + * (much) better. + * + * @param this calling obect + * @return netmask as "bits for subnet" + */ + u_int8_t (*get_netmask) (traffic_selector_t *this); + + /** + * @brief Update the address of a traffic selector. + * + * Update the address range of a traffic selector, + * if the current address is 0.0.0.0. The new address range + * starts from the supplied address and also ends there + * (which means it is a one-host-address-range ;-). + * + * @param this calling obect + * @param host host_t specifying the address range + */ + void (*update_address_range) (traffic_selector_t *this, host_t* host); + + /** + * @brief Destroys the ts object + * + * @param this calling object + */ + void (*destroy) (traffic_selector_t *this); +}; + +/** + * @brief 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 + * @param from_addr start of address range as string + * @param from_port port number in host order + * @param to_addr end of address range as string + * @param to_port port number in host order + * @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, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port); + +/** + * @brief 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 + * don't have to convert twice. + * + * @param protocol protocol for this ts, such as TCP or UDP + * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE + * @param from_address start of address range, network order + * @param from_port port number, host order + * @param to_address end of address range as string, network + * @param to_port port number, host order + * @return + * - traffic_selector_t object + * - NULL if invalid address input/protocol + * + * @ingroup config + */ +traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_address, int16_t from_port, chunk_t to_address, u_int16_t to_port); + +/** + * @brief 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 + * all protocols, all ports and the address range specified by the + * subnet. + * + * @param net subnet to use + * @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation + * @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); + +#endif /* TRAFFIC_SELECTOR_H_ */ |