diff options
Diffstat (limited to 'src/charon/config/policies')
-rw-r--r-- | src/charon/config/policies/local_policy_store.c | 282 | ||||
-rw-r--r-- | src/charon/config/policies/local_policy_store.h | 60 | ||||
-rw-r--r-- | src/charon/config/policies/policy.c | 635 | ||||
-rw-r--r-- | src/charon/config/policies/policy.h | 413 | ||||
-rwxr-xr-x | src/charon/config/policies/policy_store.h | 119 |
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 **)¤t)) + { + 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 **)¤t)) + { + 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**)¤t)) + { + /* 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**)¤t)) + { + 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_*/ |