summaryrefslogtreecommitdiff
path: root/src/charon/config/policies
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2007-04-12 20:30:08 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2007-04-12 20:30:08 +0000
commitb0d8ed94fe9e74afb49fdf5f11e4add29879c65c (patch)
treeb20167235628771046e940a82a906a6d0991ee4a /src/charon/config/policies
parentea939d07c84d2a8e51215458063fc05e9c399290 (diff)
downloadvyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.tar.gz
vyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.1.1)
Diffstat (limited to 'src/charon/config/policies')
-rw-r--r--src/charon/config/policies/local_policy_store.c282
-rw-r--r--src/charon/config/policies/local_policy_store.h60
-rw-r--r--src/charon/config/policies/policy.c635
-rw-r--r--src/charon/config/policies/policy.h413
-rwxr-xr-xsrc/charon/config/policies/policy_store.h119
5 files changed, 1509 insertions, 0 deletions
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..dd22b43a0
--- /dev/null
+++ b/src/charon/config/policies/local_policy_store.c
@@ -0,0 +1,282 @@
+/**
+ * @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 <string.h>
+
+#include "local_policy_store.h"
+
+#include <daemon.h>
+#include <utils/linked_list.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;
+
+ /**
+ * Mutex to exclusivly access list
+ */
+ pthread_mutex_t mutex;
+};
+
+/**
+ * Implementation of policy_store_t.add_policy.
+ */
+static void add_policy(private_local_policy_store_t *this, policy_t *policy)
+{
+ pthread_mutex_lock(&(this->mutex));
+ this->policies->insert_last(this->policies, (void*)policy);
+ pthread_mutex_unlock(&(this->mutex));
+}
+
+/**
+ * Check if a policy contains traffic selectors
+ */
+static bool contains_traffic_selectors(policy_t *policy, bool mine,
+ linked_list_t *ts, host_t *host)
+{
+ linked_list_t *selected;
+ bool contains = FALSE;
+
+ if (mine)
+ {
+ selected = policy->select_my_traffic_selectors(policy, ts, host);
+ }
+ else
+ {
+ selected = policy->select_other_traffic_selectors(policy, ts, host);
+ }
+ if (selected->get_count(selected))
+ {
+ contains = TRUE;
+ }
+ selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
+ return contains;
+}
+
+/**
+ * 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,
+ linked_list_t *my_ts, linked_list_t *other_ts,
+ host_t *my_host, host_t *other_host)
+{
+ typedef enum {
+ PRIO_UNDEFINED = 0x00,
+ PRIO_TS_MISMATCH = 0x01,
+ PRIO_ID_ANY = 0x02,
+ PRIO_ID_MATCH = PRIO_ID_ANY + MAX_WILDCARDS,
+ } prio_t;
+
+ prio_t best_prio = PRIO_UNDEFINED;
+
+ iterator_t *iterator;
+ policy_t *candidate;
+ policy_t *found = NULL;
+ traffic_selector_t *ts;
+
+ DBG1(DBG_CFG, "searching policy for '%D'...'%D'", my_id, other_id);
+ iterator = my_ts->create_iterator(my_ts, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts))
+ {
+ DBG1(DBG_CFG, " local TS: %R", ts);
+ }
+ iterator->destroy(iterator);
+ iterator = other_ts->create_iterator(other_ts, TRUE);
+ while (iterator->iterate(iterator, (void**)&ts))
+ {
+ DBG1(DBG_CFG, " remote TS: %R", ts);
+ }
+ iterator->destroy(iterator);
+
+ pthread_mutex_lock(&(this->mutex));
+ iterator = this->policies->create_iterator(this->policies, TRUE);
+
+ /* determine closest matching policy */
+ while (iterator->iterate(iterator, (void**)&candidate))
+ {
+ identification_t *candidate_my_id;
+ identification_t *candidate_other_id;
+ int wildcards;
+
+ candidate_my_id = candidate->get_my_id(candidate);
+ candidate_other_id = candidate->get_other_id(candidate);
+
+ /* my_id is either %any or if set must match exactly */
+ if (candidate_my_id->matches(candidate_my_id, my_id, &wildcards))
+ {
+ prio_t prio = PRIO_UNDEFINED;
+
+ /* wildcard match for other_id */
+ if (!other_id->matches(other_id, candidate_other_id, &wildcards))
+ {
+ continue;
+ }
+ prio = PRIO_ID_MATCH - wildcards;
+
+ /* only accept if traffic selectors match */
+ if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) ||
+ !contains_traffic_selectors(candidate, FALSE, other_ts, other_host))
+ {
+ DBG2(DBG_CFG, "candidate '%s' inacceptable due traffic "
+ "selector mismatch", candidate->get_name(candidate));
+ prio = PRIO_TS_MISMATCH;
+ }
+
+ DBG2(DBG_CFG, "candidate policy '%s': '%D'...'%D' (prio=%d)",
+ candidate->get_name(candidate),
+ candidate_my_id, candidate_other_id, prio);
+
+ if (prio > best_prio)
+ {
+ found = candidate;
+ best_prio = prio;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (found)
+ {
+ DBG1(DBG_CFG, "found matching policy '%s': '%D'...'%D' (prio=%d)",
+ found->get_name(found), found->get_my_id(found),
+ found->get_other_id(found), best_prio);
+ /* give out a new reference to it */
+ found->get_ref(found);
+ }
+ pthread_mutex_unlock(&(this->mutex));
+ return found;
+}
+
+/**
+ * Implementation of policy_store_t.get_policy_by_name.
+ */
+static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name)
+{
+ iterator_t *iterator;
+ policy_t *current, *found = NULL;
+
+ DBG2(DBG_CFG, "looking for policy '%s'", name);
+
+ pthread_mutex_lock(&(this->mutex));
+ iterator = this->policies->create_iterator(this->policies, TRUE);
+ while (iterator->iterate(iterator, (void **)&current))
+ {
+ if (strcmp(current->get_name(current), name) == 0)
+ {
+ found = current;
+ }
+ }
+ iterator->destroy(iterator);
+ pthread_mutex_unlock(&(this->mutex));
+
+ /* give out a new reference */
+ found->get_ref(found);
+ return found;
+}
+
+/**
+ * Implementation of policy_store_t.delete_policy.
+ */
+static status_t delete_policy(private_local_policy_store_t *this, char *name)
+{
+ iterator_t *iterator;
+ policy_t *current;
+ bool found = FALSE;
+
+ pthread_mutex_lock(&(this->mutex));
+ iterator = this->policies->create_iterator(this->policies, TRUE);
+ while (iterator->iterate(iterator, (void **)&current))
+ {
+ if (strcmp(current->get_name(current), name) == 0)
+ {
+ /* remove policy from list, and destroy it */
+ iterator->remove(iterator);
+ current->destroy(current);
+ found = TRUE;
+ /* we do not break here, as there may be multipe policies */
+ }
+ }
+ iterator->destroy(iterator);
+ pthread_mutex_unlock(&(this->mutex));
+ if (found)
+ {
+ return SUCCESS;
+ }
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of policy_store_t.create_iterator.
+ */
+static iterator_t* create_iterator(private_local_policy_store_t *this)
+{
+ return this->policies->create_iterator_locked(this->policies,
+ &this->mutex);
+}
+
+/**
+ * Implementation of policy_store_t.destroy.
+ */
+static void destroy(private_local_policy_store_t *this)
+{
+ pthread_mutex_lock(&(this->mutex));
+ this->policies->destroy_offset(this->policies, offsetof(policy_t, destroy));
+ pthread_mutex_unlock(&(this->mutex));
+ 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*,
+ linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy;
+ this->public.policy_store.get_policy_by_name = (policy_t* (*) (policy_store_t*,char*))get_policy_by_name;
+ this->public.policy_store.delete_policy = (status_t (*) (policy_store_t*,char*))delete_policy;
+ this->public.policy_store.create_iterator = (iterator_t* (*) (policy_store_t*))create_iterator;
+ this->public.policy_store.destroy = (void (*) (policy_store_t*))destroy;
+
+ /* private variables */
+ this->policies = linked_list_create();
+ pthread_mutex_init(&(this->mutex), NULL);
+
+ 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..01d5d2d60
--- /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_
+
+typedef struct local_policy_store_t local_policy_store_t;
+
+#include <library.h>
+#include <config/policies/policy_store.h>
+
+
+/**
+ * @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..363d1609f
--- /dev/null
+++ b/src/charon/config/policies/policy.c
@@ -0,0 +1,635 @@
+/**
+ * @file policy.c
+ *
+ * @brief Implementation of policy_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 <time.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "policy.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+
+ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
+ "DPD_NONE",
+ "DPD_CLEAR",
+ "DPD_ROUTE",
+ "DPD_RESTART"
+);
+
+ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
+ "TRANSPORT",
+ "TUNNEL",
+ "2",
+ "3",
+ "BEET"
+);
+
+typedef struct private_policy_t private_policy_t;
+
+/**
+ * Private data of an policy_t object
+ */
+struct private_policy_t {
+
+ /**
+ * Public part
+ */
+ policy_t public;
+
+ /**
+ * Number of references hold by others to this policy
+ */
+ refcount_t refcount;
+
+ /**
+ * Name of the policy, used to query it
+ */
+ char *name;
+
+ /**
+ * id to use to identify us
+ */
+ identification_t *my_id;
+
+ /**
+ * allowed id for other
+ */
+ identification_t *other_id;
+
+ /**
+ * virtual IP to use locally
+ */
+ host_t *my_virtual_ip;
+
+ /**
+ * virtual IP to use remotly
+ */
+ host_t *other_virtual_ip;
+
+ /**
+ * Method to use for own authentication data
+ */
+ auth_method_t auth_method;
+
+ /**
+ * EAP type to use for peer authentication
+ */
+ eap_type_t eap_type;
+
+ /**
+ * we have a cert issued by this CA
+ */
+ identification_t *my_ca;
+
+ /**
+ * we require the other end to have a cert issued by this CA
+ */
+ identification_t *other_ca;
+
+ /**
+ * updown script
+ */
+ char *updown;
+
+ /**
+ * allow host access
+ */
+ bool hostaccess;
+
+ /**
+ * 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;
+
+ /**
+ * Time before an SA gets invalid
+ */
+ u_int32_t soft_lifetime;
+
+ /**
+ * Time before an SA gets rekeyed
+ */
+ u_int32_t hard_lifetime;
+
+ /**
+ * Time, which specifies the range of a random value
+ * substracted from soft_lifetime.
+ */
+ u_int32_t jitter;
+
+ /**
+ * What to do with an SA when other peer seams to be dead?
+ */
+ bool dpd_action;
+
+ /**
+ * Mode to propose for a initiated CHILD: tunnel/transport
+ */
+ mode_t mode;
+};
+
+/**
+ * Implementation of policy_t.get_name
+ */
+static char *get_name(private_policy_t *this)
+{
+ return this->name;
+}
+
+/**
+ * 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.get_my_ca
+ */
+static identification_t *get_my_ca(private_policy_t *this)
+{
+ return this->my_ca;
+}
+
+/**
+ * Implementation of policy_t.get_other_ca
+ */
+static identification_t *get_other_ca(private_policy_t *this)
+{
+ return this->other_ca;
+}
+
+/**
+ * Implementation of connection_t.auth_method_t.
+ */
+static auth_method_t get_auth_method(private_policy_t *this)
+{
+ return this->auth_method;
+}
+
+/**
+ * Implementation of connection_t.get_eap_type.
+ */
+static eap_type_t get_eap_type(private_policy_t *this)
+{
+ return this->eap_type;
+}
+
+/**
+ * Get traffic selectors, with wildcard-address update
+ */
+static linked_list_t *get_traffic_selectors(private_policy_t *this,
+ linked_list_t *list, host_t *host)
+{
+ iterator_t *iterator;
+ traffic_selector_t *current;
+ linked_list_t *result = linked_list_create();
+
+ iterator = list->create_iterator(list, TRUE);
+
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ current = current->clone(current);
+ if (host)
+ {
+ current->set_address(current, host);
+ }
+
+ result->insert_last(result, (void*)current);
+ }
+ iterator->destroy(iterator);
+ return result;
+}
+
+/**
+ * Implementation of policy_t.get_my_traffic_selectors
+ */
+static linked_list_t *get_my_traffic_selectors(private_policy_t *this, host_t *me)
+{
+ return get_traffic_selectors(this, this->my_ts, me);
+}
+
+/**
+ * Implementation of policy_t.get_other_traffic_selectors
+ */
+static linked_list_t *get_other_traffic_selectors(private_policy_t *this, host_t *other)
+{
+ return get_traffic_selectors(this, this->other_ts, other);
+}
+
+/**
+ * Narrow traffic selectors, with wildcard-address update in "stored".
+ */
+static linked_list_t *select_traffic_selectors(private_policy_t *this,
+ linked_list_t *stored,
+ linked_list_t *supplied,
+ host_t *host)
+{
+ iterator_t *supplied_iter, *stored_iter, *i1, *i2;
+ traffic_selector_t *supplied_ts, *stored_ts, *selected_ts, *ts1, *ts2;
+ linked_list_t *selected = linked_list_create();
+
+ DBG2(DBG_CFG, "selecting traffic selectors");
+
+ stored_iter = stored->create_iterator(stored, TRUE);
+ supplied_iter = supplied->create_iterator(supplied, TRUE);
+
+ /* iterate over all stored selectors */
+ while (stored_iter->iterate(stored_iter, (void**)&stored_ts))
+ {
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ stored_ts = stored_ts->clone(stored_ts);
+ if (host)
+ {
+ stored_ts->set_address(stored_ts, host);
+ }
+
+ supplied_iter->reset(supplied_iter);
+ /* iterate over all supplied traffic selectors */
+ while (supplied_iter->iterate(supplied_iter, (void**)&supplied_ts))
+ {
+ DBG2(DBG_CFG, "stored %R <=> %R received",
+ stored_ts, 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);
+
+ DBG2(DBG_CFG, "found traffic selector for %s: %R",
+ stored == this->my_ts ? "us" : "other", selected_ts);
+ }
+ }
+ stored_ts->destroy(stored_ts);
+ }
+ stored_iter->destroy(stored_iter);
+ supplied_iter->destroy(supplied_iter);
+
+ /* remove any redundant traffic selectors in the list */
+ i1 = selected->create_iterator(selected, TRUE);
+ i2 = selected->create_iterator(selected, TRUE);
+ while (i1->iterate(i1, (void**)&ts1))
+ {
+ while (i2->iterate(i2, (void**)&ts2))
+ {
+ if (ts1 != ts2)
+ {
+ if (ts2->is_contained_in(ts2, ts1))
+ {
+ i2->remove(i2);
+ ts2->destroy(ts2);
+ i1->reset(i1);
+ break;
+ }
+ if (ts1->is_contained_in(ts1, ts2))
+ {
+ i1->remove(i1);
+ ts1->destroy(ts1);
+ i2->reset(i2);
+ break;
+ }
+ }
+ }
+ }
+ i1->destroy(i1);
+ i2->destroy(i2);
+
+ return selected;
+}
+
+/**
+ * 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,
+ host_t *me)
+{
+ return select_traffic_selectors(this, this->my_ts, supplied, me);
+}
+
+/**
+ * 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,
+ host_t* other)
+{
+ return select_traffic_selectors(this, this->other_ts, supplied, other);
+}
+
+/**
+ * Implementation of policy_t.get_proposal_iterator
+ */
+static linked_list_t *get_proposals(private_policy_t *this)
+{
+ iterator_t *iterator;
+ proposal_t *current;
+ linked_list_t *proposals = linked_list_create();
+
+ iterator = this->proposals->create_iterator(this->proposals, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ current = current->clone(current);
+ proposals->insert_last(proposals, (void*)current);
+ }
+ iterator->destroy(iterator);
+
+ return 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->iterate(stored_iter, (void**)&stored))
+ {
+ supplied_iter->reset(supplied_iter);
+ while (supplied_iter->iterate(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_authorities
+ */
+static void add_authorities(private_policy_t *this, identification_t *my_ca, identification_t *other_ca)
+{
+ this->my_ca = my_ca;
+ this->other_ca = other_ca;
+}
+
+/**
+ * Implementation of policy_t.get_updown
+ */
+static char* get_updown(private_policy_t *this)
+{
+ return this->updown;
+}
+
+/**
+ * Implementation of policy_t.get_hostaccess
+ */
+static bool get_hostaccess(private_policy_t *this)
+{
+ return this->hostaccess;
+}
+
+/**
+ * Implements policy_t.get_dpd_action
+ */
+static dpd_action_t get_dpd_action(private_policy_t *this)
+{
+ return this->dpd_action;
+}
+
+/**
+ * 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);
+}
+
+/**
+ * Implementation of policy_t.get_soft_lifetime
+ */
+static u_int32_t get_soft_lifetime(private_policy_t *this)
+{
+ if (this->jitter == 0)
+ {
+ return this->soft_lifetime ;
+ }
+ return this->soft_lifetime - (random() % this->jitter);
+}
+
+/**
+ * Implementation of policy_t.get_hard_lifetime
+ */
+static u_int32_t get_hard_lifetime(private_policy_t *this)
+{
+ return this->hard_lifetime;
+}
+
+/**
+ * Implementation of policy_t.get_mode.
+ */
+static mode_t get_mode(private_policy_t *this)
+{
+ return this->mode;
+}
+
+/**
+ * Implementation of policy_t.get_virtual_ip.
+ */
+static host_t* get_virtual_ip(private_policy_t *this, host_t *suggestion)
+{
+ if (suggestion == NULL)
+ {
+ if (this->my_virtual_ip)
+ {
+ return this->my_virtual_ip->clone(this->my_virtual_ip);
+ }
+ return NULL;
+ }
+ if (this->other_virtual_ip)
+ {
+ return this->other_virtual_ip->clone(this->other_virtual_ip);
+ }
+ if (suggestion->is_anyaddr(suggestion))
+ {
+ return NULL;
+ }
+ return suggestion->clone(suggestion);
+}
+
+/**
+ * Implements policy_t.get_ref.
+ */
+static void get_ref(private_policy_t *this)
+{
+ ref_get(&this->refcount);
+}
+
+/**
+ * Implements policy_t.destroy.
+ */
+static void destroy(private_policy_t *this)
+{
+ if (ref_put(&this->refcount))
+ {
+
+ this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
+ this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
+ this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
+
+ /* delete certification authorities */
+ DESTROY_IF(this->my_ca);
+ DESTROY_IF(this->other_ca);
+
+ /* delete updown script */
+ if (this->updown)
+ {
+ free(this->updown);
+ }
+
+ /* delete ids */
+ this->my_id->destroy(this->my_id);
+ this->other_id->destroy(this->other_id);
+ DESTROY_IF(this->my_virtual_ip);
+ DESTROY_IF(this->other_virtual_ip);
+
+ free(this->name);
+ free(this);
+ }
+}
+
+/*
+ * Described in header-file
+ */
+policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
+ host_t *my_virtual_ip, host_t *other_virtual_ip,
+ auth_method_t auth_method, eap_type_t eap_type,
+ u_int32_t hard_lifetime, u_int32_t soft_lifetime,
+ u_int32_t jitter, char *updown, bool hostaccess,
+ mode_t mode, dpd_action_t dpd_action)
+{
+ private_policy_t *this = malloc_thing(private_policy_t);
+
+ /* public functions */
+ this->public.get_name = (char* (*) (policy_t*))get_name;
+ 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.get_my_ca = (identification_t* (*) (policy_t*))get_my_ca;
+ this->public.get_other_ca = (identification_t* (*) (policy_t*))get_other_ca;
+ this->public.get_auth_method = (auth_method_t (*) (policy_t*)) get_auth_method;
+ this->public.get_eap_type = (eap_type_t (*) (policy_t*)) get_eap_type;
+ this->public.get_my_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_my_traffic_selectors;
+ this->public.get_other_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_other_traffic_selectors;
+ this->public.select_my_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_t*))select_my_traffic_selectors;
+ this->public.select_other_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_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.add_authorities = (void (*) (policy_t*,identification_t*,identification_t*))add_authorities;
+ this->public.get_updown = (char* (*) (policy_t*))get_updown;
+ this->public.get_hostaccess = (bool (*) (policy_t*))get_hostaccess;
+ this->public.get_dpd_action = (dpd_action_t (*) (policy_t*))get_dpd_action;
+ this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
+ this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
+ this->public.get_mode = (mode_t (*) (policy_t *))get_mode;
+ this->public.get_virtual_ip = (host_t* (*)(policy_t*,host_t*))get_virtual_ip;
+ this->public.get_ref = (void (*) (policy_t*))get_ref;
+ this->public.destroy = (void (*) (policy_t*))destroy;
+
+ /* apply init values */
+ this->name = strdup(name);
+ this->my_id = my_id;
+ this->other_id = other_id;
+ this->my_virtual_ip = my_virtual_ip;
+ this->other_virtual_ip = other_virtual_ip;
+ this->auth_method = auth_method;
+ this->eap_type = eap_type;
+ this->hard_lifetime = hard_lifetime;
+ this->soft_lifetime = soft_lifetime;
+ this->jitter = jitter;
+ this->updown = (updown == NULL) ? NULL : strdup(updown);
+ this->hostaccess = hostaccess;
+ this->dpd_action = dpd_action;
+ this->mode = mode;
+
+ /* initialize private members*/
+ this->refcount = 1;
+ this->my_ca = NULL;
+ this->other_ca = NULL;
+ 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..d8916b29e
--- /dev/null
+++ b/src/charon/config/policies/policy.h
@@ -0,0 +1,413 @@
+/**
+ * @file policy.h
+ *
+ * @brief Interface of policy_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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_
+
+typedef enum dpd_action_t dpd_action_t;
+typedef struct policy_t policy_t;
+
+#include <library.h>
+#include <utils/identification.h>
+#include <config/traffic_selector.h>
+#include <config/proposal.h>
+#include <sa/authenticators/authenticator.h>
+#include <sa/authenticators/eap/eap_method.h>
+
+
+/**
+ * @brief Actions to take when a peer does not respond (dead peer detected).
+ *
+ * These values are the same as in pluto/starter, so do not modify them!
+ *
+ * @ingroup config
+ */
+enum dpd_action_t {
+ /** DPD disabled */
+ DPD_NONE,
+ /** remove CHILD_SA without replacement */
+ DPD_CLEAR,
+ /** route the CHILD_SA to resetup when needed */
+ DPD_ROUTE,
+ /** restart CHILD_SA in a new IKE_SA, immediately */
+ DPD_RESTART,
+};
+
+/**
+ * enum names for dpd_action_t.
+ */
+extern enum_name_t *dpd_action_names;
+
+/**
+ * @brief Mode of an IPsec SA.
+ *
+ * These are equal to those defined in XFRM, so don't change.
+ *
+ * @ingroup config
+ */
+enum mode_t {
+ /** transport mode, no inner address */
+ MODE_TRANSPORT = 0,
+ /** tunnel mode, inner and outer addresses */
+ MODE_TUNNEL = 1,
+ /** BEET mode, tunnel mode but fixed, bound inner addresses */
+ MODE_BEET = 4,
+};
+
+/**
+ * enum names for mode_t.
+ */
+extern enum_name_t *mode_names;
+
+/**
+ * @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 the name of the policy.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @param this calling object
+ * @return policy's name
+ */
+ char *(*get_name) (policy_t *this);
+
+ /**
+ * @brief Get own id.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @param this calling object
+ * @return own id
+ */
+ identification_t *(*get_my_id) (policy_t *this);
+
+ /**
+ * @brief Get peer id.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @param this calling object
+ * @return other id
+ */
+ identification_t *(*get_other_id) (policy_t *this);
+
+ /**
+ * @brief Get own ca.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @param this calling object
+ * @return own ca
+ */
+ identification_t *(*get_my_ca) (policy_t *this);
+
+ /**
+ * @brief Get peer ca.
+ *
+ * Returned object is not getting cloned.
+ *
+ * @param this calling object
+ * @return other ca
+ */
+ identification_t *(*get_other_ca) (policy_t *this);
+
+ /**
+ * @brief Get the authentication method to use.
+ *
+ * @param this calling object
+ * @return authentication method
+ */
+ auth_method_t (*get_auth_method) (policy_t *this);
+
+ /**
+ * @brief Get the EAP type to use for peer authentication.
+ *
+ * @param this calling object
+ * @return authentication method
+ */
+ eap_type_t (*get_eap_type) (policy_t *this);
+
+ /**
+ * @brief Get configured traffic selectors for our site.
+ *
+ * Returns a list with all traffic selectors for the local
+ * site. List and items must be destroyed after usage.
+ *
+ * @param this calling object
+ * @return list with traffic selectors
+ */
+ linked_list_t *(*get_my_traffic_selectors) (policy_t *this, host_t *me);
+
+ /**
+ * @brief Get configured traffic selectors for others site.
+ *
+ * Returns a list with all traffic selectors for the remote
+ * site. List and items must be destroyed after usage.
+ *
+ * @param this calling object
+ * @return list with traffic selectors
+ */
+ linked_list_t *(*get_other_traffic_selectors) (policy_t *this, host_t* other);
+
+ /**
+ * @brief Select traffic selectors from a supplied list for local site.
+ *
+ * Resulted list and traffic selectors must be destroyed after usage.
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
+ *
+ * @param this calling object
+ * @param supplied linked list with traffic selectors
+ * @param me host address used by us
+ * @return list containing the selected traffic selectors
+ */
+ linked_list_t *(*select_my_traffic_selectors) (policy_t *this,
+ linked_list_t *supplied,
+ host_t *me);
+
+ /**
+ * @brief Select traffic selectors from a supplied list for remote site.
+ *
+ * Resulted list and traffic selectors must be destroyed after usage.
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
+ *
+ * @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,
+ host_t *other);
+
+ /**
+ * @brief Get the list of internally stored proposals.
+ *
+ * policy_t does store proposals for AH/ESP, IKE proposals are in
+ * the connection_t.
+ * Resulting list and all of its proposals must be freed after usage.
+ *
+ * @param this calling object
+ * @return lists with proposals
+ */
+ linked_list_t *(*get_proposals) (policy_t *this);
+
+ /**
+ * @brief Select a proposal from a supplied list.
+ *
+ * Returned propsal is newly created and must be destroyed after usage.
+ *
+ * @param this calling object
+ * @param proposals list from from wich proposals are selected
+ * @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, traffic selector is owned by policy.
+ *
+ * @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, traffic selector is owned by policy.
+ *
+ * @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.
+ * After add, proposal is owned by policy.
+ *
+ * @param this calling object
+ * @param proposal proposal to add
+ */
+ void (*add_proposal) (policy_t *this, proposal_t *proposal);
+
+ /**
+ * @brief Add certification authorities.
+ *
+ * @param this calling object
+ * @param my_ca issuer of my certificate
+ * @param other_ca required issuer of the peer's certificate
+ */
+ void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca);
+
+ /**
+ * @brief Get updown script
+ *
+ * @param this calling object
+ * @return path to updown script
+ */
+ char* (*get_updown) (policy_t *this);
+
+ /**
+ * @brief Get hostaccess flag
+ *
+ * @param this calling object
+ * @return value of hostaccess flag
+ */
+ bool (*get_hostaccess) (policy_t *this);
+
+ /**
+ * @brief What should be done with a CHILD_SA, when other peer does not respond.
+ *
+ * @param this calling object
+ * @return dpd action
+ */
+ dpd_action_t (*get_dpd_action) (policy_t *this);
+
+ /**
+ * @brief Get the lifetime of a policy, before rekeying starts.
+ *
+ * A call to this function automatically adds a jitter to
+ * avoid simultanous rekeying.
+ *
+ * @param this policy
+ * @return lifetime in seconds
+ */
+ u_int32_t (*get_soft_lifetime) (policy_t *this);
+
+ /**
+ * @brief Get the lifetime of a policy, before SA gets deleted.
+ *
+ * @param this policy
+ * @return lifetime in seconds
+ */
+ u_int32_t (*get_hard_lifetime) (policy_t *this);
+
+ /**
+ * @brief Get the mode to use for the CHILD_SA, tunnel, transport or BEET.
+ *
+ * @param this policy
+ * @return lifetime in seconds
+ */
+ mode_t (*get_mode) (policy_t *this);
+
+ /**
+ * @brief Get a virtual IP for the local or the remote host.
+ *
+ * By supplying NULL as IP, an IP for the local host is requested. It
+ * may be %any or specific.
+ * By supplying %any as host, an IP from the pool is selected to be
+ * served to the peer.
+ * If a specified host is supplied, it is checked if this address
+ * is acceptable to serve to the peer. If so, it is returned. Otherwise,
+ * an alternative IP is returned.
+ * In any mode, this call may return NULL indicating virtual IP should
+ * not be used.
+ *
+ * @param this policy
+ * @param suggestion NULL, %any or specific, see description
+ * @return clone of an IP to use, or NULL
+ */
+ host_t* (*get_virtual_ip) (policy_t *this, host_t *suggestion);
+
+ /**
+ * @brief Get a new reference.
+ *
+ * Get a new reference to this policy by increasing
+ * it's internal reference counter.
+ * Do not call get_ref or any other function until you
+ * already have a reference. Otherwise the object may get
+ * destroyed while calling get_ref(),
+ *
+ * @param this calling object
+ */
+ void (*get_ref) (policy_t *this);
+
+ /**
+ * @brief Destroys the policy object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the policy when it reaches zero.
+ *
+ * @param this calling object
+ */
+ void (*destroy) (policy_t *this);
+};
+
+/**
+ * @brief Create a configuration object for IKE_AUTH and later.
+ *
+ * name-string gets cloned, ID's not.
+ * Virtual IPs are used if they are != NULL. A %any host means the virtual
+ * IP should be obtained from the other peer.
+ * Lifetimes are in seconds. To prevent to peers to start rekeying at the
+ * same time, a jitter may be specified. Rekeying of an SA starts at
+ * (soft_lifetime - random(0, jitter)). After a successful rekeying,
+ * the hard_lifetime limit counter is reset. You should specify
+ * hard_lifetime > soft_lifetime > jitter.
+ * After a call to create, a reference is obtained (refcount = 1).
+ *
+ * @param name name of the policy
+ * @param my_id identification_t for ourselves
+ * @param other_id identification_t for the remote guy
+ * @param my_virtual_ip virtual IP for local host, or NULL
+ * @param other_virtual_ip virtual IP for remote host, or NULL
+ * @param auth_method Authentication method to use for our(!) auth data
+ * @param eap_type EAP type to use for peer authentication
+ * @param hard_lifetime lifetime before deleting an SA
+ * @param soft_lifetime lifetime before rekeying an SA
+ * @param jitter range of randomization time
+ * @param updown updown script to execute on up/down event
+ * @param hostaccess allow access to the host itself (used by the updown script)
+ * @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
+ * @param dpd_action what to to with a CHILD_SA when other peer does not respond
+ * @return policy_t object
+ *
+ * @ingroup config
+ */
+policy_t *policy_create(char *name,
+ identification_t *my_id, identification_t *other_id,
+ host_t *my_virtual_ip, host_t *other_virtual_ip,
+ auth_method_t auth_method, eap_type_t eap_type,
+ u_int32_t hard_lifetime, u_int32_t soft_lifetime,
+ u_int32_t jitter, char *updown, bool hostaccess,
+ mode_t mode, dpd_action_t dpd_action);
+
+#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..cd8870953
--- /dev/null
+++ b/src/charon/config/policies/policy_store.h
@@ -0,0 +1,119 @@
+/**
+ * @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_
+
+typedef struct policy_store_t policy_store_t;
+
+#include <library.h>
+#include <config/policies/policy.h>
+#include <utils/linked_list.h>
+
+
+/**
+ * @brief The interface for a store of policy_t's.
+ *
+ * The store uses reference counting to manage their lifetime. Call
+ * destroy() for a policy which is returned from the store after usage.
+ *
+ * @b Constructors:
+ * - stroke_create()
+ *
+ * @ingroup config
+ */
+struct policy_store_t {
+
+ /**
+ * @brief Returns a policy identified by two IDs and a set of traffic selectors.
+ *
+ * other_id must be fully qualified. my_id may be %any, as the
+ * other peer may not include an IDr Request.
+ *
+ * @param this calling object
+ * @param my_id own ID of the policy
+ * @param other_id others ID of the policy
+ * @param my_ts traffic selectors requested for local host
+ * @param other_ts traffic selectors requested for remote host
+ * @param my_host host to use for wilcards in TS compare
+ * @param other_host host to use for wildcards in TS compare
+ * @return
+ * - matching policy_t, if found
+ * - NULL otherwise
+ */
+ policy_t *(*get_policy) (policy_store_t *this,
+ identification_t *my_id, identification_t *other_id,
+ linked_list_t *my_ts, linked_list_t *other_ts,
+ host_t *my_host, host_t* other_host);
+
+ /**
+ * @brief Returns a policy identified by a connection name.
+ *
+ * @param this calling object
+ * @param name name of the policy
+ * @return
+ * - matching policy_t, if found
+ * - NULL otherwise
+ */
+ policy_t *(*get_policy_by_name) (policy_store_t *this, char *name);
+
+ /**
+ * @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 Delete a policy from the store.
+ *
+ * Remove a policy from the store identified by its name.
+ *
+ * @param this calling object
+ * @param policy policy to add
+ * @return
+ * - SUCCESS, or
+ * - NOT_FOUND
+ */
+ status_t (*delete_policy) (policy_store_t *this, char *name);
+
+ /**
+ * @brief Get an iterator for the stored policies.
+ *
+ * @param this calling object
+ * @return iterator over all stored policies
+ */
+ iterator_t* (*create_iterator) (policy_store_t *this);
+
+ /**
+ * @brief Destroys a policy_store_t object.
+ *
+ * @param this calling object
+ */
+ void (*destroy) (policy_store_t *this);
+};
+
+#endif /*POLICY_STORE_H_*/