aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/config')
-rw-r--r--src/charon/config/Makefile.config32
-rwxr-xr-xsrc/charon/config/configuration.c112
-rwxr-xr-xsrc/charon/config/configuration.h89
-rw-r--r--src/charon/config/connections/Makefile.connections24
-rw-r--r--src/charon/config/connections/connection.c367
-rw-r--r--src/charon/config/connections/connection.h283
-rwxr-xr-xsrc/charon/config/connections/connection_store.h112
-rw-r--r--src/charon/config/connections/local_connection_store.c228
-rw-r--r--src/charon/config/connections/local_connection_store.h63
-rw-r--r--src/charon/config/credentials/Makefile.credentials20
-rwxr-xr-xsrc/charon/config/credentials/credential_store.h91
-rw-r--r--src/charon/config/credentials/local_credential_store.c381
-rw-r--r--src/charon/config/credentials/local_credential_store.h85
-rw-r--r--src/charon/config/policies/Makefile.policies24
-rw-r--r--src/charon/config/policies/local_policy_store.c136
-rw-r--r--src/charon/config/policies/local_policy_store.h60
-rw-r--r--src/charon/config/policies/policy.c397
-rw-r--r--src/charon/config/policies/policy.h249
-rwxr-xr-xsrc/charon/config/policies/policy_store.h76
-rw-r--r--src/charon/config/proposal.c642
-rw-r--r--src/charon/config/proposal.h269
-rw-r--r--src/charon/config/traffic_selector.c425
-rw-r--r--src/charon/config/traffic_selector.h258
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**)&current);
+
+ 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**)&current);
+
+ 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**)&current);
+ 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**)&current);
+ 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**)&current);
+ 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 **)&current);
+ 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**)&current_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_ */