restructured file layout

new configuration structure:
  peer_cfg: configuration related to a peer (authenitcation, ...=
  ike_cfg: config to use for IKE setup (proposals)
  child_Cfg: config for CHILD_SA (proposals, traffic selectors)
  a peer_cfg has one ike_cfg and multiple child_cfg's
stroke now uses fixed count of threads
This commit is contained in:
Martin Willi 2007-04-10 06:01:03 +00:00
parent 1628cd6bda
commit e0fe765152
104 changed files with 3466 additions and 3470 deletions

1
TODO
View File

@ -47,6 +47,7 @@ Build system
------------
- configure flag which allows to ommit vendor id in pluto
- reduce printf handlers count to 10, as uClibc does not support more
- remove %m printf handlers, as error may have changed until it reaches fprintf()
Certificate support
-------------------

View File

@ -1,4 +1,4 @@
#!/bin/bash
CFLAGS="-Wall -Wno-format -Wno-pointer-sign -Wno-strict-aliasing -g -O2" ./configure \
--sysconfdir=/etc --with-random-device=/dev/urandom --enable-ldap --enable-http \
--enable-leak-detective
--sysconfdir=/etc --with-random-device=/dev/urandom \
--enable-leak-detective --enable-eap-sim --with-sim-reader=/home/martin/strongswan/trunk/src/charon/sa/authenticators/eap/sim_reader/sim_api.so

View File

@ -17,65 +17,90 @@ ipsec_PROGRAMS = charon
charon_SOURCES = \
bus/bus.c bus/bus.h \
bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
bus/listeners/file_logger.c bus/listeners/file_logger.h \
config/connections/connection.c config/connections/connection.h \
config/connections/local_connection_store.c config/connections/local_connection_store.h config/connections/connection_store.h \
config/policies/policy.c config/policies/policy.h \
config/policies/local_policy_store.c config/policies/policy_store.h config/policies/local_policy_store.h \
bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
config/backends/backend.h \
config/backends/local_backend.c config/backends/local_backend.h \
config/cfg_store.c config/cfg_store.h \
config/child_cfg.c config/child_cfg.h \
config/configuration.c config/configuration.h \
config/credentials/local_credential_store.c config/credentials/local_credential_store.h \
config/ike_cfg.c config/ike_cfg.h \
config/peer_cfg.c config/peer_cfg.h \
config/proposal.c config/proposal.h \
config/traffic_selector.c config/traffic_selector.h \
config/proposal.c config/proposal.h config/configuration.c config/configuration.h \
sa/authenticators/eap_authenticator.h sa/authenticators/eap_authenticator.c \
sa/authenticators/eap/eap_method.h sa/authenticators/eap/eap_method.c \
sa/child_sa.c sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
sa/ike_sa_id.c sa/ike_sa_id.h sa/tasks/task.c sa/tasks/task.h \
sa/tasks/ike_init.c sa/tasks/ike_init.h \
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
sa/tasks/ike_config.c sa/tasks/ike_config.h \
sa/tasks/ike_cert.c sa/tasks/ike_cert.h \
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
control/controller.c control/controller.h \
control/stroke_interface.c control/stroke_interface.h \
daemon.c daemon.h \
encoding/generator.c encoding/generator.h \
encoding/message.c encoding/message.h \
encoding/parser.c encoding/parser.h \
encoding/payloads/auth_payload.c encoding/payloads/auth_payload.h \
encoding/payloads/cert_payload.c encoding/payloads/cert_payload.h \
encoding/payloads/certreq_payload.c encoding/payloads/certreq_payload.h \
encoding/payloads/configuration_attribute.c encoding/payloads/configuration_attribute.h \
encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
encoding/payloads/encodings.c encoding/payloads/encodings.h \
encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
encoding/payloads/nonce_payload.c encoding/payloads/nonce_payload.h \
encoding/payloads/notify_payload.c encoding/payloads/notify_payload.h \
encoding/payloads/payload.c encoding/payloads/payload.h \
encoding/payloads/proposal_substructure.c encoding/payloads/proposal_substructure.h \
encoding/payloads/sa_payload.c encoding/payloads/sa_payload.h \
encoding/payloads/traffic_selector_substructure.c encoding/payloads/traffic_selector_substructure.h \
encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
encoding/payloads/transform_substructure.c encoding/payloads/transform_substructure.h \
encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
kernel/kernel_interface.c kernel/kernel_interface.h \
network/packet.c network/packet.h \
network/receiver.c network/receiver.h \
network/sender.c network/sender.h \
network/socket.c network/socket.h \
processing/event_queue.c processing/event_queue.h \
processing/job_queue.c processing/job_queue.h \
processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
processing/jobs/initiate_job.c processing/jobs/initiate_job.h \
processing/jobs/job.c processing/jobs/job.h \
processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
processing/jobs/route_job.c processing/jobs/route_job.h \
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
processing/scheduler.c processing/scheduler.h \
processing/thread_pool.c processing/thread_pool.h \
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
sa/authenticators/rsa_authenticator.c sa/authenticators/rsa_authenticator.h \
sa/child_sa.c sa/child_sa.h \
sa/ike_sa.c sa/ike_sa.h \
sa/ike_sa_id.c sa/ike_sa_id.h \
sa/ike_sa_manager.c sa/ike_sa_manager.h \
sa/task_manager.c sa/task_manager.h \
sa/tasks/child_create.c sa/tasks/child_create.h \
sa/tasks/child_delete.c sa/tasks/child_delete.h \
sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
sa/authenticators/rsa_authenticator.c sa/authenticators/rsa_authenticator.h \
sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
sa/task_manager.c sa/task_manager.h encoding/payloads/encryption_payload.c \
encoding/payloads/cert_payload.c encoding/payloads/payload.h encoding/payloads/traffic_selector_substructure.c \
encoding/payloads/configuration_attribute.h encoding/payloads/proposal_substructure.h \
encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
encoding/payloads/configuration_attribute.c encoding/payloads/transform_substructure.c \
encoding/payloads/encryption_payload.h encoding/payloads/auth_payload.c encoding/payloads/ike_header.c \
encoding/payloads/transform_substructure.h encoding/payloads/nonce_payload.c encoding/payloads/cert_payload.h \
encoding/payloads/eap_payload.c encoding/payloads/ike_header.h encoding/payloads/auth_payload.h \
encoding/payloads/ts_payload.c encoding/payloads/traffic_selector_substructure.h encoding/payloads/nonce_payload.h \
encoding/payloads/notify_payload.c encoding/payloads/eap_payload.h encoding/payloads/notify_payload.h \
encoding/payloads/ts_payload.h encoding/payloads/id_payload.c encoding/payloads/ke_payload.c \
encoding/payloads/unknown_payload.c encoding/payloads/encodings.c encoding/payloads/id_payload.h \
encoding/payloads/cp_payload.c encoding/payloads/delete_payload.c encoding/payloads/sa_payload.c \
encoding/payloads/ke_payload.h encoding/payloads/unknown_payload.h encoding/payloads/encodings.h \
encoding/payloads/certreq_payload.c encoding/payloads/cp_payload.h encoding/payloads/delete_payload.h \
encoding/payloads/sa_payload.h encoding/payloads/vendor_id_payload.c encoding/payloads/certreq_payload.h \
encoding/payloads/vendor_id_payload.h encoding/payloads/proposal_substructure.c encoding/payloads/payload.c \
encoding/parser.h encoding/message.c encoding/generator.c encoding/message.h encoding/generator.h \
encoding/parser.c daemon.c daemon.h network/packet.c \
network/socket.c network/packet.h network/socket.h queues/jobs/job.h queues/jobs/job.c \
queues/jobs/retransmit_job.h queues/jobs/initiate_job.h \
queues/jobs/process_message_job.h queues/jobs/process_message_job.c \
queues/jobs/delete_ike_sa_job.c queues/jobs/delete_ike_sa_job.h \
queues/jobs/retransmit_job.c queues/jobs/initiate_job.c \
queues/jobs/send_keepalive_job.c queues/jobs/send_keepalive_job.h \
queues/jobs/rekey_child_sa_job.c queues/jobs/rekey_child_sa_job.h queues/jobs/delete_child_sa_job.c queues/jobs/delete_child_sa_job.h \
queues/jobs/send_dpd_job.c queues/jobs/send_dpd_job.h queues/jobs/route_job.c queues/jobs/route_job.h \
queues/jobs/acquire_job.c queues/jobs/acquire_job.h queues/jobs/rekey_ike_sa_job.c queues/jobs/rekey_ike_sa_job.h \
queues/job_queue.c queues/event_queue.c queues/job_queue.h queues/event_queue.h \
threads/kernel_interface.c threads/thread_pool.c threads/scheduler.c threads/sender.c \
threads/sender.h threads/kernel_interface.h threads/scheduler.h threads/receiver.c threads/stroke_interface.c \
threads/thread_pool.h threads/receiver.h threads/stroke_interface.h
sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
sa/tasks/ike_cert.c sa/tasks/ike_cert.h \
sa/tasks/ike_config.c sa/tasks/ike_config.h \
sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
sa/tasks/ike_init.c sa/tasks/ike_init.h \
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/task.c sa/tasks/task.h
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke
AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\"

View File

@ -0,0 +1,77 @@
/**
* @file backend.h
*
* @brief Interface backend_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef BACKEND_H_
#define BACKEND_H_
typedef struct backend_t backend_t;
#include <library.h>
#include <config/ike_cfg.h>
#include <config/peer_cfg.h>
#include <utils/linked_list.h>
/**
* @brief The interface for a configuration backend.
*
* @b Constructors:
* - implementations constructor, such as local_backend_create()
*
* @ingroup backends
*/
struct backend_t {
/**
* @brief Get an ike_cfg identified by two hosts.
*
* @param this calling object
* @param my_host address of own host
* @param other_host address of remote host
* @return matching ike_config, or NULL if none found
*/
ike_cfg_t *(*get_ike_cfg)(backend_t *this,
host_t *my_host, host_t *other_host);
/**
* @brief Get a peer_cfg identified by two IDs.
*
* @param this calling object
* @param my_id own ID
* @param other_id peers ID
* @return matching peer_config, or NULL if none found
*/
peer_cfg_t *(*get_peer_cfg)(backend_t *this,
identification_t *my_id,
identification_t *other_id);
/**
* @brief Get a peer_cfg identified by its name.
*
* @param this calling object
* @param name configs name
* @return matching peer_config, or NULL if none found
*/
peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name);
};
#endif /* BACKEND_H_ */

View File

@ -0,0 +1,231 @@
/**
* @file local_backend.c
*
* @brief Implementation of local_backend_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include "local_backend.h"
#include <daemon.h>
#include <utils/linked_list.h>
typedef struct private_local_backend_t private_local_backend_t;
/**
* Private data of an local_backend_t object
*/
struct private_local_backend_t {
/**
* Public part
*/
local_backend_t public;
/**
* list of configs
*/
linked_list_t *cfgs;
/**
* Mutex to exclusivly access list
*/
pthread_mutex_t mutex;
};
/**
* implements cfg_store_t.get_ike_cfg.
*/
static ike_cfg_t *get_ike_cfg(private_local_backend_t *this,
host_t *my_host, host_t *other_host)
{
peer_cfg_t *peer;
ike_cfg_t *current, *found = NULL;
iterator_t *iterator;
host_t *my_candidate, *other_candidate;
enum {
MATCH_NONE = 0x00,
MATCH_ANY = 0x01,
MATCH_ME = 0x04,
MATCH_OTHER = 0x08,
} prio, best = MATCH_ANY;
DBG2(DBG_CFG, "looking for a config for %H...%H",
my_host, other_host);
iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
while (iterator->iterate(iterator, (void**)&peer))
{
prio = MATCH_NONE;
current = peer->get_ike_cfg(peer);
my_candidate = current->get_my_host(current);
other_candidate = current->get_other_host(current);
if (my_candidate->ip_equals(my_candidate, my_host))
{
prio += MATCH_ME;
}
else if (my_candidate->is_anyaddr(my_candidate))
{
prio += MATCH_ANY;
}
if (other_candidate->ip_equals(other_candidate, other_host))
{
prio += MATCH_OTHER;
}
else if (other_candidate->is_anyaddr(other_candidate))
{
prio += MATCH_ANY;
}
DBG2(DBG_CFG, " candidate '%s': %H...%H, prio %d",
peer->get_name(peer), my_candidate, other_candidate, prio);
/* we require at least two MATCH_ANY */
if (prio > best)
{
best = prio;
found = current;
}
}
if (found)
{
found->get_ref(found);
}
iterator->destroy(iterator);
return found;
}
/**
* implements cfg_store_t.get_peer.
*/
static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
identification_t *my_id,
identification_t *other_id)
{
peer_cfg_t *current, *found = NULL;
iterator_t *iterator;
identification_t *my_candidate, *other_candidate;
int wc1, wc2, total, best = MAX_WILDCARDS;
DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
while (iterator->iterate(iterator, (void**)&current))
{
my_candidate = current->get_my_id(current);
other_candidate = current->get_other_id(current);
if (my_candidate->matches(my_candidate, my_id, &wc1) &&
other_id->matches(other_id, other_candidate, &wc2))
{
total = wc1 + wc2;
DBG2(DBG_CFG, " candidate '%s': %D...%D, wildcards %d",
current->get_name(current), my_candidate, other_candidate,
total);
if (total < best)
{
found = current;
best = total;
}
}
}
if (found)
{
found->get_ref(found);
}
iterator->destroy(iterator);
return found;
}
/**
* implements cfg_store_t.get_peer_by_name.
*/
static peer_cfg_t *get_peer_cfg_by_name(private_local_backend_t *this,
char *name)
{
iterator_t *iterator;
peer_cfg_t *current, *found = NULL;
iterator = this->cfgs->create_iterator(this->cfgs, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (streq(current->get_name(current), name))
{
found = current;
found->get_ref(found);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of local_backend_t.create_peer_cfg_iterator.
*/
static iterator_t* create_peer_cfg_iterator(private_local_backend_t *this)
{
return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
}
/**
* Implementation of local_backend_t.add_peer_cfg.
*/
static void add_peer_cfg(private_local_backend_t *this, peer_cfg_t *config)
{
pthread_mutex_lock(&this->mutex);
this->cfgs->insert_last(this->cfgs, config);
pthread_mutex_unlock(&this->mutex);
}
/**
* Implementation of local_backend_t.destroy.
*/
static void destroy(private_local_backend_t *this)
{
this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy));
free(this);
}
/**
* Described in header.
*/
local_backend_t *local_backend_create(void)
{
private_local_backend_t *this = malloc_thing(private_local_backend_t);
this->public.backend.get_ike_cfg = (ike_cfg_t*(*)(backend_t*, host_t *, host_t *))get_ike_cfg;
this->public.backend.get_peer_cfg = (peer_cfg_t*(*)(backend_t*, identification_t *, identification_t *))get_peer_cfg;
this->public.backend.get_peer_cfg_by_name = (peer_cfg_t*(*)(backend_t*, char *))get_peer_cfg_by_name;
this->public.create_peer_cfg_iterator = (iterator_t*(*)(local_backend_t*))create_peer_cfg_iterator;
this->public.add_peer_cfg = (void(*)(local_backend_t*, peer_cfg_t *))add_peer_cfg;
this->public.destroy = (void(*)(local_backend_t*))destroy;
/* private variables */
this->cfgs = linked_list_create();
pthread_mutex_init(&this->mutex, NULL);
return (&this->public);
}

View File

@ -0,0 +1,82 @@
/**
* @file local_backend.h
*
* @brief Interface of local_backend_t.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef LOCAL_BACKEND_H_
#define LOCAL_BACKEND_H_
typedef struct local_backend_t local_backend_t;
#include <library.h>
#include <config/backends/backend.h>
/**
* @brief An in-memory backend to store configuration information.
*
* The local_backend_t stores the configuration in a simple list. Additional
* to the backend_t functionality, it adds the modification (add/remove).
*
* @b Constructors:
* - local_backend_create()
*
* @ingroup backends
*/
struct local_backend_t {
/**
* Implements backend_t interface
*/
backend_t backend;
/**
* @brief Add a peer_config to the backend.
*
* @param this calling object
* @param config peer_config to add to the backend
*/
void (*add_peer_cfg)(local_backend_t *this, peer_cfg_t *config);
/**
* @brief Create an iterator over all peer configs.
*
* @param this calling object
* @return iterator over peer configs
*/
iterator_t* (*create_peer_cfg_iterator)(local_backend_t *this);
/**
* @brief Destroy a local backend.
*
* @param this calling object
*/
void (*destroy)(local_backend_t *this);
};
/**
* @brief Creates a local_backend_t instance.
*
* @return local_backend instance.
*
* @ingroup config
*/
local_backend_t *local_backend_create(void);
#endif /* LOCAL_BACKEND_H_ */

View File

@ -0,0 +1,164 @@
/**
* @file cfg_store.c
*
* @brief Implementation of cfg_store_t.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <pthread.h>
#include "cfg_store.h"
#include <library.h>
#include <utils/linked_list.h>
typedef struct private_cfg_store_t private_cfg_store_t;
/**
* Private data of an cfg_store_t object.
*/
struct private_cfg_store_t {
/**
* Public part of cfg_store_t object.
*/
cfg_store_t public;
/**
* list of registered backends
*/
linked_list_t *backends;
/**
* mutex to lock backend list
*/
pthread_mutex_t mutex;
};
/**
* implements cfg_store_t.get_ike.
*/
static ike_cfg_t *get_ike_cfg(private_cfg_store_t *this,
host_t *my_host, host_t *other_host)
{
backend_t *backend;
ike_cfg_t *config = NULL;
iterator_t *iterator = this->backends->create_iterator_locked(
this->backends, &this->mutex);
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
{
config = backend->get_ike_cfg(backend, my_host, other_host);
}
iterator->destroy(iterator);
return config;
}
/**
* implements cfg_store_t.get_peer.
*/
static peer_cfg_t *get_peer_cfg(private_cfg_store_t *this,
identification_t *my_id,
identification_t *other_id)
{
backend_t *backend;
peer_cfg_t *config = NULL;
iterator_t *iterator = this->backends->create_iterator_locked(
this->backends, &this->mutex);
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
{
config = backend->get_peer_cfg(backend, my_id, other_id);
}
iterator->destroy(iterator);
return config;
}
/**
* implements cfg_store_t.get_peer_by_name.
*/
static peer_cfg_t *get_peer_cfg_by_name(private_cfg_store_t *this, char *name)
{
backend_t *backend;
peer_cfg_t *config = NULL;
iterator_t *iterator = this->backends->create_iterator_locked(
this->backends, &this->mutex);
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
{
config = backend->get_peer_cfg_by_name(backend, name);
}
iterator->destroy(iterator);
return config;
}
/**
* implements cfg_store_t.register_backend.
*/
static void register_backend(private_cfg_store_t *this, backend_t *backend)
{
pthread_mutex_lock(&this->mutex);
this->backends->insert_last(this->backends, backend);
pthread_mutex_unlock(&this->mutex);
}
/**
* implements cfg_store_t.unregister_backend.
*/
static void unregister_backend(private_cfg_store_t *this, backend_t *backend)
{
backend_t *current;
iterator_t *iterator = this->backends->create_iterator_locked(
this->backends, &this->mutex);
while (iterator->iterate(iterator, (void**)&current))
{
if (backend == current)
{
iterator->remove(iterator);
break;
}
}
iterator->destroy(iterator);
}
/**
* Implementation of cfg_store_t.destroy.
*/
static void destroy(private_cfg_store_t *this)
{
this->backends->destroy(this->backends);
free(this);
}
/*
* Described in header-file
*/
cfg_store_t *cfg_store_create()
{
private_cfg_store_t *this = malloc_thing(private_cfg_store_t);
this->public.get_ike_cfg = (ike_cfg_t*(*)(cfg_store_t*, host_t *, host_t *))get_ike_cfg;
this->public.get_peer_cfg = (peer_cfg_t*(*)(cfg_store_t*, identification_t *, identification_t *))get_peer_cfg;
this->public.get_peer_cfg_by_name = (peer_cfg_t*(*)(cfg_store_t*, char *name))get_peer_cfg_by_name;
this->public.register_backend = (void(*)(cfg_store_t*, backend_t *))register_backend;
this->public.unregister_backend = (void(*)(cfg_store_t*, backend_t *))unregister_backend;
this->public.destroy = (void(*)(cfg_store_t*))destroy;
this->backends = linked_list_create();
pthread_mutex_init(&this->mutex, NULL);
return &this->public;
}

View File

@ -0,0 +1,135 @@
/**
* @file cfg_store.h
*
* @brief Interface cfg_store_t.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CFG_STORE_H_
#define CFG_STORE_H_
typedef struct cfg_store_t cfg_store_t;
#include <library.h>
#include <utils/host.h>
#include <utils/identification.h>
#include <config/ike_cfg.h>
#include <config/peer_cfg.h>
#include <config/backends/backend.h>
/**
* @brief A multiplexer to use multiple cfg_store backends.
*
* Charon allows the use of multiple cfg_store backends simultaneously. To
* access all this backends by a single call, this class wraps multiple
* backends behind a single object.
* Backends may be registered and unregister at runtime dynamically.
*
* +---------+ +---------+ +--------------+ |
* | | | | +--------------+ | |
* | |----->| config | +--------------+ |-+ <==|==> IPC
* | | | |------>| backends |-+ |
* | daemon |----->| | +--------------+ |
* | core | +---------+ |
* | | |
* | | +---------+ +--------------+ |
* | |<-----| | +--------------+ | |
* | | | control-| +--------------+ |-+ <==|==> IPC
* | |<-----| ler |------>| controllers |-+ |
* | | | | +--------------+ |
* +---------+ +---------+ |
*
* The daemon core only knows the simple and single cfg_store interface.
* The cfg_store wraps two kind of objects, backends and trustchains.
* If the daemon needs something, it asks the cfg_store. cfg_store
* asks all of its backends if they can fullfil the request.
*
*
* @b Constructors:
* - stroke_create()
*
* @ingroup config
*/
struct cfg_store_t {
/**
* @brief Get an ike_config identified by two hosts.
*
* @param this calling object
* @param my_host address of own host
* @param other_host address of remote host
* @return matching ike_config, or NULL if none found
*/
ike_cfg_t *(*get_ike_cfg)(cfg_store_t *this,
host_t *my_host, host_t *other_host);
/**
* @brief Get a peer_config identified by two IDs.
*
* @param this calling object
* @param my_id own ID
* @param other_id peers ID
* @return matching peer_config, or NULL if none found
*/
peer_cfg_t *(*get_peer_cfg)(cfg_store_t *this, identification_t *my_id,
identification_t *other_id);
/**
* @brief Get a peer_config identified by its name.
*
* @param this calling object
* @param name name of the peer config
* @return matching peer_config, or NULL if none found
*/
peer_cfg_t *(*get_peer_cfg_by_name)(cfg_store_t *this, char *name);
/**
* @brief Register a backend to be queried by the calls above.
*
* The backend first added is the most preferred.
*
* @param this calling object
*/
void (*register_backend) (cfg_store_t *this, backend_t *backend);
/**
* @brief Unregister a backend.
*
* @param this calling object
*/
void (*unregister_backend) (cfg_store_t *this, backend_t *backend);
/**
* @brief Destroys a cfg_store_t object.
*
* @param this calling object
*/
void (*destroy) (cfg_store_t *this);
};
/**
* @brief Create a new instance of the store.
*
* @return cfg_store instance
*
* @ingroup config
*/
cfg_store_t *cfg_store_create(void);
#endif /*CFG_STORE_H_*/

View File

@ -0,0 +1,397 @@
/**
* @file child_cfg.c
*
* @brief Implementation of child_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 "child_cfg.h"
#include <daemon.h>
ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
"TRANSPORT",
"TUNNEL",
"2",
"3",
"BEET",
);
typedef struct private_child_cfg_t private_child_cfg_t;
/**
* Private data of an child_cfg_t object
*/
struct private_child_cfg_t {
/**
* Public part
*/
child_cfg_t public;
/**
* Number of references hold by others to this child_cfg
*/
refcount_t refcount;
/**
* Name of the child_cfg, used to query it
*/
char *name;
/**
* 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;
/**
* updown script
*/
char *updown;
/**
* allow host access
*/
bool hostaccess;
/**
* Mode to propose for a initiated CHILD: tunnel/transport
*/
mode_t mode;
/**
* Time before an SA gets invalid
*/
u_int32_t lifetime;
/**
* Time before an SA gets rekeyed
*/
u_int32_t rekeytime;
/**
* Time, which specifies the range of a random value
* substracted from rekeytime.
*/
u_int32_t jitter;
};
/**
* Implementation of child_cfg_t.get_name
*/
static char *get_name(private_child_cfg_t *this)
{
return this->name;
}
/**
* Implementation of child_cfg_t.add_proposal
*/
static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
{
this->proposals->insert_last(this->proposals, proposal);
}
/**
* Implementation of child_cfg_t.get_proposals
*/
static linked_list_t* get_proposals(private_child_cfg_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, current);
}
iterator->destroy(iterator);
return proposals;
}
/**
* Implementation of child_cfg_t.get_name
*/
static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals)
{
iterator_t *stored_iter, *supplied_iter;
proposal_t *stored, *supplied, *selected = NULL;
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)
{
break;
}
}
if (selected)
{
break;
}
}
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return selected;
}
/**
* Implementation of child_cfg_t.get_name
*/
static void add_traffic_selector(private_child_cfg_t *this, bool local,
traffic_selector_t *ts)
{
if (local)
{
this->my_ts->insert_last(this->my_ts, ts);
}
else
{
this->other_ts->insert_last(this->other_ts, ts);
}
}
/**
* Implementation of child_cfg_t.get_name
*/
static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
linked_list_t *supplied,
host_t *host)
{
iterator_t *i1, *i2;
traffic_selector_t *ts1, *ts2, *selected;
linked_list_t *result = linked_list_create();
if (local)
{
i1 = this->my_ts->create_iterator(this->my_ts, TRUE);
}
else
{
i1 = this->other_ts->create_iterator(this->other_ts, FALSE);
}
/* no list supplied, just fetch the stored traffic selectors */
if (supplied == NULL)
{
while (i1->iterate(i1, (void**)&ts1))
{
/* we make a copy of the TS, this allows us to update dynamic TS' */
ts1 = ts1->clone(ts1);
if (host)
{
ts1->set_address(ts1, host);
}
result->insert_last(result, ts1);
}
i1->destroy(i1);
}
else
{
DBG2(DBG_CFG, "selecting traffic selectors");
i2 = supplied->create_iterator(supplied, TRUE);
/* iterate over all stored selectors */
while (i1->iterate(i1, (void**)&ts1))
{
/* we make a copy of the TS, as we have to update dynamic TS' */
ts1 = ts1->clone(ts1);
if (host)
{
ts1->set_address(ts1, host);
}
i2->reset(i2);
/* iterate over all supplied traffic selectors */
while (i2->iterate(i2, (void**)&ts2))
{
DBG2(DBG_CFG, "stored %R <=> %R received", ts1, ts2);
selected = ts1->get_subset(ts1, ts2);
if (selected)
{
result->insert_last(result, selected);
DBG2(DBG_CFG, "found traffic selector for %s: %R",
local ? "us" : "other", selected);
}
}
ts1->destroy(ts1);
}
i1->destroy(i1);
i2->destroy(i2);
}
/* remove any redundant traffic selectors in the list */
i1 = result->create_iterator(result, TRUE);
i2 = result->create_iterator(result, TRUE);
while (i1->iterate(i1, (void**)&ts1))
{
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 result;
}
/**
* Implementation of child_cfg_t.get_name
*/
static char* get_updown(private_child_cfg_t *this)
{
return this->updown;
}
/**
* Implementation of child_cfg_t.get_name
*/
static bool get_hostaccess(private_child_cfg_t *this)
{
return this->hostaccess;
}
/**
* Implementation of child_cfg_t.get_name
*/
static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
{
if (rekey)
{
if (this->jitter == 0)
{
return this->rekeytime;
}
return this->rekeytime - (random() % this->jitter);
}
return this->lifetime;
}
/**
* Implementation of child_cfg_t.get_name
*/
static mode_t get_mode(private_child_cfg_t *this)
{
return this->mode;
}
/**
* Implementation of child_cfg_t.get_name
*/
static void get_ref(private_child_cfg_t *this)
{
ref_get(&this->refcount);
}
/**
* Implements child_cfg_t.destroy.
*/
static void destroy(private_child_cfg_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));
if (this->updown)
{
free(this->updown);
}
free(this->name);
free(this);
}
}
/*
* Described in header-file
*/
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, mode_t mode)
{
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
/* public functions */
this->public.get_name = (char* (*) (child_cfg_t*))get_name;
this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*))get_proposals;
this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*))select_proposal;
this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
this->public.get_ref = (void (*) (child_cfg_t*))get_ref;
this->public.destroy = (void (*) (child_cfg_t*))destroy;
/* apply init values */
this->name = strdup(name);
this->lifetime = lifetime;
this->rekeytime = rekeytime;
this->jitter = jitter;
this->updown = updown ? strdup(updown) : NULL;
this->hostaccess = hostaccess;
this->mode = mode;
/* initialize private members*/
this->refcount = 1;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
return &this->public;
}

View File

@ -0,0 +1,239 @@
/**
* @file child_cfg.h
*
* @brief Interface of child_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 CHILD_CFG_H_
#define CHILD_CFG_H_
typedef enum mode_t mode_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
#include <config/proposal.h>
#include <config/traffic_selector.h>
/**
* @brief Mode of an CHILD_SA.
*
* These are equal to those defined in XFRM, so don't change.
*
* @ingroup child_cfg
*/
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 child_cfg_t defines the config template for a CHILD_SA.
*
* After creation, proposals and traffic selectors may be added to the config.
* A child_cfg object is referenced multiple times, and is not thread save.
* Reading from the object is save, adding things is not allowed when other
* threads may access the object.
* A reference counter handles the number of references hold to this config.
*
* @b Constructors:
* - child_cfg_create()
*
* @ingroup child_cfg
*/
struct child_cfg_t {
/**
* @brief Get the name of the child_cfg.
*
* @param this calling object
* @return child_cfg's name
*/
char *(*get_name) (child_cfg_t *this);
/**
* @brief Add a proposal to the list.
*
* The proposals are stored by priority, first added
* is the most prefered.
* After add, proposal is owned by child_cfg.
*
* @param this calling object
* @param proposal proposal to add
*/
void (*add_proposal) (child_cfg_t *this, proposal_t *proposal);
/**
* @brief Get the list of proposals for the CHILD_SA.
*
* Resulting list and all of its proposals must be freed after use.
*
* @param this calling object
* @return list of proposals
*/
linked_list_t* (*get_proposals)(child_cfg_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)(child_cfg_t*this, linked_list_t *proposals);
/**
* @brief Add a traffic selector to the config.
*
* Use the "local" parameter to add it for the local or the remote side.
* After add, traffic selector is owned by child_cfg.
*
* @param this calling object
* @param local TRUE for local side, FALSE for remote
* @param ts traffic_selector to add
*/
void (*add_traffic_selector)(child_cfg_t *this, bool local,
traffic_selector_t *ts);
/**
* @brief Get a list of traffic selectors to use for the CHILD_SA.
*
* The config contains two set of traffic selectors, one for the local
* side, one for the remote side.
* If a list with traffic selectors is supplied, these are used to narrow
* down the traffic selector list to the greatest common divisor.
* Some traffic selector may be "dymamic", meaning they are narrowed down
* to a specific address (host-to-host or virtual-IP setups). Use
* the "host" parameter to narrow such traffic selectors to that address.
* Resulted list and its traffic selectors must be destroyed after use.
*
* @param this calling object
* @param local TRUE for TS on local side, FALSE for remote
* @param supplied list with TS to select from, or NULL
* @param host address to use for narrowing "dynamic" TS', or NULL
* @return list containing the traffic selectors
*/
linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
linked_list_t *supplied,
host_t *host);
/**
* @brief Get the updown script to run for the CHILD_SA.
*
* @param this calling object
* @return path to updown script
*/
char* (*get_updown)(child_cfg_t *this);
/**
* @brief Should we allow access to the local host (gateway)?
*
* @param this calling object
* @return value of hostaccess flag
*/
bool (*get_hostaccess) (child_cfg_t *this);
/**
* @brief Get the lifetime of a CHILD_SA.
*
* If "rekey" is set to TRUE, a lifetime is returned before the first
* rekeying should be started. If it is FALSE, the actual lifetime is
* returned when the CHILD_SA must be deleted.
* The rekey time automatically contains a jitter to avoid simlutaneous
* rekeying.
*
* @param this child_cfg
* @param rekey TRUE to get rekey time
* @return lifetime in seconds
*/
u_int32_t (*get_lifetime) (child_cfg_t *this, bool rekey);
/**
* @brief Get the mode to use for the CHILD_SA.
*
* The mode is either tunnel, transport or BEET. The peer must agree
* on the method, fallback is tunnel mode.
*
* @param this child_cfg
* @return lifetime in seconds
*/
mode_t (*get_mode) (child_cfg_t *this);
/**
* @brief Get a new reference.
*
* Get a new reference to this child_cfg by increasing
* it's internal reference counter.
* Do not call get_ref or any other function until you
* already have a reference. Otherwise the object may get
* destroyed while calling get_ref(),
*
* @param this calling object
*/
void (*get_ref) (child_cfg_t *this);
/**
* @brief Destroys the child_cfg object.
*
* Decrements the internal reference counter and
* destroys the child_cfg when it reaches zero.
*
* @param this calling object
*/
void (*destroy) (child_cfg_t *this);
};
/**
* @brief Create a configuration template for CHILD_SA setup.
*
* The "name" string gets cloned.
* 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
* (rekeytime - random(0, jitter)). You should specify
* lifetime > rekeytime > jitter.
* After a call to create, a reference is obtained (refcount = 1).
*
* @param name name of the child_cfg
* @param lifetime lifetime after CHILD_SA expires and gets deleted
* @param rekeytime time when rekeying should be initiated
* @param jitter range of randomization time to remove from rekeytime
* @param updown updown script to execute on up/down event
* @param hostaccess TRUE to allow access to the local host
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
* @return child_cfg_t object
*
* @ingroup child_cfg
*/
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess,
mode_t mode);
#endif /* CHILD_CFG_H_ */

View File

@ -1,404 +0,0 @@
/**
* @file connection.c
*
* @brief Implementation of connection_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 <string.h>
#include <config/connections/connection.h>
#include <utils/linked_list.h>
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"CERT_ALWAYS_SEND",
"CERT_SEND_IF_ASKED",
"CERT_NEVER_SEND"
);
typedef struct private_connection_t private_connection_t;
/**
* Private data of an connection_t object
*/
struct private_connection_t {
/**
* Public part
*/
connection_t public;
/**
* Number of references hold by others to this connection
*/
refcount_t refcount;
/**
* Name of the connection
*/
char *name;
/**
* Does charon handle this connection? Or can he ignore it?
*/
bool ikev2;
/**
* should we send a certificate request?
*/
cert_policy_t certreq_policy;
/**
* should we send a certificates?
*/
cert_policy_t cert_policy;
/**
* ID of us
*/
identification_t *my_id;
/**
* Host information of my host.
*/
host_t *my_host;
/**
* Host information of other host.
*/
host_t *other_host;
/**
* Interval to send DPD liveness checks on inactivity
*/
u_int32_t dpd_delay;
/**
* Number of retransmission sequences to send bevore giving up
*/
u_int32_t keyingtries;
/**
* Supported proposals
*/
linked_list_t *proposals;
/**
* Time before an SA gets invalid
*/
u_int32_t soft_lifetime;
/**
* Time before an SA gets rekeyed
*/
u_int32_t hard_lifetime;
/**
* Use full reauthentication instead of rekeying
*/
bool reauth;
/**
* Time, which specifies the range of a random value
* substracted from soft_lifetime.
*/
u_int32_t jitter;
};
/**
* Implementation of connection_t.get_name.
*/
static char *get_name (private_connection_t *this)
{
return this->name;
}
/**
* Implementation of connection_t.is_ikev2.
*/
static bool is_ikev2 (private_connection_t *this)
{
return this->ikev2;
}
/**
* Implementation of connection_t.get_certreq_policy.
*/
static cert_policy_t get_certreq_policy (private_connection_t *this)
{
return this->certreq_policy;
}
/**
* Implementation of connection_t.get_cert_policy.
*/
static cert_policy_t get_cert_policy (private_connection_t *this)
{
return this->cert_policy;
}
/**
* 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.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)
{
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 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->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 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.get_dpd_delay.
*/
static u_int32_t get_dpd_delay(private_connection_t *this)
{
return this->dpd_delay;
}
/**
* Implementation of connection_t.get_keyingtries.
*/
static u_int32_t get_keyingtries(private_connection_t *this)
{
return this->keyingtries;
}
/**
* 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;
diffie_hellman_group_t dh_group = MODP_NONE;
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->iterate(iterator, (void**)&proposal))
{
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
{
dh_group = algo->algorithm;
break;
}
}
iterator->destroy(iterator);
return dh_group;
}
/**
* 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->iterate(prop_iter, (void**)&proposal))
{
alg_iter = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP);
while (alg_iter->iterate(alg_iter, (void**)&algo))
{
if (algo->algorithm == dh_group)
{
prop_iter->destroy(prop_iter);
alg_iter->destroy(alg_iter);
return TRUE;
}
}
alg_iter->destroy(alg_iter);
}
prop_iter->destroy(prop_iter);
return FALSE;
}
/**
* Implementation of connection_t.get_soft_lifetime
*/
static u_int32_t get_soft_lifetime(private_connection_t *this)
{
if (this->jitter == 0)
{
return this->soft_lifetime ;
}
return this->soft_lifetime - (random() % this->jitter);
}
/**
* Implementation of connection_t.get_hard_lifetime.
*/
static u_int32_t get_hard_lifetime(private_connection_t *this)
{
return this->hard_lifetime;
}
/**
* Implementation of connection_t.get_reauth.
*/
static bool get_reauth(private_connection_t *this)
{
return this->reauth;
}
/**
* Implementation of connection_t.get_ref.
*/
static void get_ref(private_connection_t *this)
{
ref_get(&this->refcount);
}
/**
* Implementation of connection_t.destroy.
*/
static void destroy(private_connection_t *this)
{
if (ref_put(&this->refcount))
{
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
this->my_host->destroy(this->my_host);
this->other_host->destroy(this->other_host);
free(this->name);
free(this);
}
}
/**
* Described in header.
*/
connection_t * connection_create(char *name, bool ikev2,
cert_policy_t cert_policy,
cert_policy_t certreq_policy,
host_t *my_host, host_t *other_host,
u_int32_t dpd_delay, bool reauth,
u_int32_t keyingtries,
u_int32_t hard_lifetime,
u_int32_t soft_lifetime, u_int32_t jitter)
{
private_connection_t *this = malloc_thing(private_connection_t);
/* public functions */
this->public.get_name = (char*(*)(connection_t*))get_name;
this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy;
this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy;
this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
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_dpd_delay = (u_int32_t(*)(connection_t*)) get_dpd_delay;
this->public.get_reauth = (bool(*)(connection_t*)) get_reauth;
this->public.get_keyingtries = (u_int32_t(*)(connection_t*)) get_keyingtries;
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.get_soft_lifetime = (u_int32_t (*) (connection_t *))get_soft_lifetime;
this->public.get_hard_lifetime = (u_int32_t (*) (connection_t *))get_hard_lifetime;
this->public.get_ref = (void(*)(connection_t*))get_ref;
this->public.destroy = (void(*)(connection_t*))destroy;
/* private variables */
this->refcount = 1;
this->name = strdup(name);
this->ikev2 = ikev2;
this->cert_policy = cert_policy;
this->certreq_policy = certreq_policy;
this->my_host = my_host;
this->other_host = other_host;
this->dpd_delay = dpd_delay;
this->reauth = reauth;
this->keyingtries = keyingtries;
this->hard_lifetime = hard_lifetime;
this->soft_lifetime = soft_lifetime;
this->jitter = jitter;
this->proposals = linked_list_create();
return &this->public;
}

View File

@ -1,292 +0,0 @@
/**
* @file connection.h
*
* @brief Interface of connection_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 CONNECTION_H_
#define CONNECTION_H_
typedef enum cert_policy_t cert_policy_t;
typedef struct connection_t connection_t;
#include <library.h>
#include <utils/host.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <config/proposal.h>
#include <crypto/diffie_hellman.h>
/**
* Certificate sending policy. This is also used for certificate
* requests when using this definition for the other peer. If
* it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
* included.
*
* @ingroup config
*
* @warning These definitions must be the same as in pluto/starter,
* as they are sent over the stroke socket.
*/
enum cert_policy_t {
/** always send certificates, even when not requested */
CERT_ALWAYS_SEND = 0,
/** send certificate upon cert request */
CERT_SEND_IF_ASKED = 1,
/** never send a certificate, even when requested */
CERT_NEVER_SEND = 2,
};
/**
* enum strings for cert_policy_t
*
* @ingroup config
*/
extern enum_name_t *cert_policy_names;
/**
* @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 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 Returns a list of all supported proposals.
*
* Returned list and its proposals must be destroyed after usage.
*
* @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 DPD check interval.
*
* @param this calling object
* @return dpd_delay in seconds
*/
u_int32_t (*get_dpd_delay) (connection_t *this);
/**
* @brief Should a full reauthentication be done instead of rekeying?
*
* @param this calling object
* @return TRUE to use full reauthentication
*/
bool (*get_reauth) (connection_t *this);
/**
* @brief Get the max number of retransmission sequences.
*
* @param this calling object
* @return max number of retransmission sequences
*/
u_int32_t (*get_keyingtries) (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 Check if the connection is marked as an IKEv2 connection.
*
* Since all connections (IKEv1+2) are loaded, but charon handles
* only those marked with IKEv2, this flag can tell us if we must
* ignore a connection on initiaton. Then pluto will do it for us.
*
* @param this calling object
* @return - TRUE, if this is an IKEv2 connection
*/
bool (*is_ikev2) (connection_t *this);
/**
* @brief Should be sent a certificate request for this connection?
*
* A certificate request contains serials of our trusted CA certificates.
* This flag says if such a request is sent on connection setup to
* the peer. It should be omitted when CERT_SEND_NEVER, sended otherwise.
*
* @param this calling object
* @return certificate request sending policy
*/
cert_policy_t (*get_certreq_policy) (connection_t *this);
/**
* @brief Should be sent a certificate for this connection?
*
* Return the policy used to send the certificate.
*
* @param this calling object
* @return certificate sending policy
*/
cert_policy_t (*get_cert_policy) (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 Get the lifetime of a connection, before IKE_SA rekeying starts.
*
* A call to this function automatically adds a jitter to
* avoid simultanous rekeying.
*
* @param this calling object
* @return lifetime in seconds
*/
u_int32_t (*get_soft_lifetime) (connection_t *this);
/**
* @brief Get the lifetime of a connection, before IKE_SA gets deleted.
*
* @param this calling object
* @return lifetime in seconds
*/
u_int32_t (*get_hard_lifetime) (connection_t *this);
/**
* @brief Get a new reference to this connection.
*
* Get a new reference to this connection 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) (connection_t *this);
/**
* @brief Destroys a connection_t object.
*
* Decrements the internal reference counter and
* destroys the connection when it reaches zero.
*
* @param this calling object
*/
void (*destroy) (connection_t *this);
};
/**
* @brief Creates a connection_t object.
*
* Supplied hosts become owned by connection, so
* do not modify or destroy them after a call to
* connection_create(). Name gets cloned internally.
* The retrasmit sequence number says how fast we give up when the peer
* does not respond. A high value may bridge-over temporary connection
* problems, a small value can detect dead peers faster.
*
* @param name connection identifier
* @param ikev2 TRUE if this is an IKEv2 connection
* @param cert_policy certificate send policy
* @param cert_req_policy certificate request send policy
* @param my_host host_t representing local address
* @param other_host host_t representing remote address
* @param dpd_delay interval of DPD liveness checks
* @param reauth use full reauthentication instead of rekeying
* @param keyingtries number of retransmit sequences to use
* @param hard_lifetime lifetime before deleting an IKE_SA
* @param soft_lifetime lifetime before rekeying an IKE_SA
* @param jitter range of randomization time
* @return connection_t object.
*
* @ingroup config
*/
connection_t * connection_create(char *name, bool ikev2,
cert_policy_t cert_pol, cert_policy_t req_pol,
host_t *my_host, host_t *other_host,
u_int32_t dpd_delay, bool reauth,
u_int32_t keyingtries,
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
u_int32_t jitter);
#endif /* CONNECTION_H_ */

View File

@ -1,118 +0,0 @@
/**
* @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_
typedef struct connection_store_t connection_store_t;
#include <library.h>
#include <config/connections/connection.h>
#include <utils/iterator.h>
/**
* @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 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 Delete a connection from the store.
*
* Remove a connection from the connection store, identified
* by the connections name.
*
* @param this calling object
* @param name name of the connection to delete
* @return
* - SUCCESS, or
* - NOT_FOUND
*/
status_t (*delete_connection) (connection_store_t *this, char *name);
/**
* @brief Get an iterator for the stored connections.
*
* @param this calling object
* @return iterator over all stored connections
*/
iterator_t* (*create_iterator) (connection_store_t *this);
/**
* @brief Destroys a connection_store_t object.
*
* @param this calling object
*/
void (*destroy) (connection_store_t *this);
};
#endif /* CONNECTION_STORE_H_ */

View File

@ -1,237 +0,0 @@
/**
* @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 <daemon.h>
#include <utils/linked_list.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;
/**
* Mutex to exclusivly access connection list
*/
pthread_mutex_t mutex;
};
/**
* 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)
{
typedef enum {
PRIO_UNDEFINED= 0x00,
PRIO_ADDR_ANY= 0x01,
PRIO_ADDR_MATCH= 0x02
} prio_t;
prio_t best_prio = PRIO_UNDEFINED;
iterator_t *iterator;
connection_t *candidate;
connection_t *found = NULL;
DBG2(DBG_CFG, "looking for connection for host pair %H...%H",
my_host, other_host);
pthread_mutex_lock(&(this->mutex));
iterator = this->connections->create_iterator(this->connections, TRUE);
/* determine closest matching connection */
while (iterator->iterate(iterator, (void**)&candidate))
{
host_t *candidate_my_host;
host_t *candidate_other_host;
candidate_my_host = candidate->get_my_host(candidate);
candidate_other_host = candidate->get_other_host(candidate);
/* my_host addresses must match*/
if (my_host->ip_equals(my_host, candidate_my_host))
{
prio_t prio = PRIO_UNDEFINED;
/* exact match of peer host address or wildcard address? */
if (other_host->ip_equals(other_host, candidate_other_host))
{
prio |= PRIO_ADDR_MATCH;
}
else if (candidate_other_host->is_anyaddr(candidate_other_host))
{
prio |= PRIO_ADDR_ANY;
}
DBG2(DBG_CFG, "candidate connection \"%s\": %H...%H (prio=%d)",
candidate->get_name(candidate),
candidate_my_host, candidate_other_host, prio);
if (prio > best_prio)
{
found = candidate;
best_prio = prio;
}
}
}
iterator->destroy(iterator);
if (found)
{
DBG2(DBG_CFG, "found matching connection \"%s\": %H...%H (prio=%d)",
found->get_name(found), found->get_my_host(found),
found->get_other_host(found), best_prio);
/* give out a new reference to it */
found->get_ref(found);
}
pthread_mutex_unlock(&(this->mutex));
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;
pthread_mutex_lock(&(this->mutex));
iterator = this->connections->create_iterator(this->connections, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (strcmp(name, current->get_name(current)) == 0)
{
found = current;
break;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
if (found)
{
/* get a new reference for it */
found->get_ref(found);
}
return found;
}
/**
* Implementation of connection_store_t.delete_connection.
*/
static status_t delete_connection(private_local_connection_store_t *this, char *name)
{
iterator_t *iterator;
connection_t *current;
bool found = FALSE;
pthread_mutex_lock(&(this->mutex));
iterator = this->connections->create_iterator(this->connections, TRUE);
while (iterator->iterate(iterator, (void **)&current))
{
if (strcmp(current->get_name(current), name) == 0)
{
/* remove connection from list, and destroy it */
iterator->remove(iterator);
current->destroy(current);
found = TRUE;
break;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
if (found)
{
return SUCCESS;
}
return NOT_FOUND;
}
/**
* Implementation of connection_store_t.add_connection.
*/
static status_t add_connection(private_local_connection_store_t *this, connection_t *connection)
{
pthread_mutex_lock(&(this->mutex));
this->connections->insert_last(this->connections, connection);
pthread_mutex_unlock(&(this->mutex));
return SUCCESS;
}
/**
* Implementation of connection_store_t.create_iterator.
*/
static iterator_t* create_iterator(private_local_connection_store_t *this)
{
return this->connections->create_iterator_locked(this->connections,
&this->mutex);
}
/**
* Implementation of connection_store_t.destroy.
*/
static void destroy (private_local_connection_store_t *this)
{
pthread_mutex_lock(&(this->mutex));
this->connections->destroy_offset(this->connections, offsetof(connection_t, destroy));
pthread_mutex_unlock(&(this->mutex));
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_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name;
this->public.connection_store.delete_connection = (status_t(*)(connection_store_t*,char*))delete_connection;
this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection;
this->public.connection_store.create_iterator = (iterator_t*(*)(connection_store_t*))create_iterator;
this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy;
/* private variables */
this->connections = linked_list_create();
pthread_mutex_init(&(this->mutex), NULL);
return (&this->public);
}

View File

@ -1,62 +0,0 @@
/**
* @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_
typedef struct local_connection_store_t local_connection_store_t;
#include <library.h>
#include <config/connections/connection_store.h>
/**
* @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_ */

259
src/charon/config/ike_cfg.c Normal file
View File

@ -0,0 +1,259 @@
/**
* @file ike_cfg.c
*
* @brief Implementation of ike_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 "ike_cfg.h"
#include <string.h>
typedef struct private_ike_cfg_t private_ike_cfg_t;
/**
* Private data of an ike_cfg_t object
*/
struct private_ike_cfg_t {
/**
* Public part
*/
ike_cfg_t public;
/**
* Number of references hold by others to this ike_cfg
*/
refcount_t refcount;
/**
* Address of local host
*/
host_t *my_host;
/**
* Address of remote host
*/
host_t *other_host;
/**
* should we send a certificate request?
*/
bool certreq;
/**
* List of proposals to use
*/
linked_list_t *proposals;
};
/**
* Implementation of ike_cfg_t.certreq.
*/
static bool send_certreq(private_ike_cfg_t *this)
{
return this->certreq;
}
/**
* Implementation of ike_cfg_t.get_my_host.
*/
static host_t *get_my_host (private_ike_cfg_t *this)
{
return this->my_host;
}
/**
* Implementation of ike_cfg_t.get_other_host.
*/
static host_t *get_other_host (private_ike_cfg_t *this)
{
return this->other_host;
}
/**
* Implementation of ike_cfg_t.add_proposal.
*/
static void add_proposal(private_ike_cfg_t *this, proposal_t *proposal)
{
this->proposals->insert_last(this->proposals, proposal);
}
/**
* Implementation of ike_cfg_t.get_proposals.
*/
static linked_list_t* get_proposals(private_ike_cfg_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 ike_cfg_t.select_proposal.
*/
static proposal_t *select_proposal(private_ike_cfg_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 ike_cfg_t.get_dh_group.
*/
static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this)
{
iterator_t *iterator;
proposal_t *proposal;
algorithm_t *algo;
diffie_hellman_group_t dh_group = MODP_NONE;
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->iterate(iterator, (void**)&proposal))
{
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
{
dh_group = algo->algorithm;
break;
}
}
iterator->destroy(iterator);
return dh_group;
}
/**
* Implementation of ike_cfg_t.check_dh_group.
*/
static bool check_dh_group(private_ike_cfg_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->iterate(prop_iter, (void**)&proposal))
{
alg_iter = proposal->create_algorithm_iterator(proposal,
DIFFIE_HELLMAN_GROUP);
while (alg_iter->iterate(alg_iter, (void**)&algo))
{
if (algo->algorithm == dh_group)
{
prop_iter->destroy(prop_iter);
alg_iter->destroy(alg_iter);
return TRUE;
}
}
alg_iter->destroy(alg_iter);
}
prop_iter->destroy(prop_iter);
return FALSE;
}
/**
* Implementation of ike_cfg_t.get_ref.
*/
static void get_ref(private_ike_cfg_t *this)
{
ref_get(&this->refcount);
}
/**
* Implementation of ike_cfg_t.destroy.
*/
static void destroy(private_ike_cfg_t *this)
{
if (ref_put(&this->refcount))
{
this->proposals->destroy_offset(this->proposals,
offsetof(proposal_t, destroy));
this->my_host->destroy(this->my_host);
this->other_host->destroy(this->other_host);
free(this);
}
}
/**
* Described in header.
*/
ike_cfg_t *ike_cfg_create(bool certreq, host_t *my_host, host_t *other_host)
{
private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t);
/* public functions */
this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq;
this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host;
this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host;
this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal;
this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal;
this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group;
this->public.check_dh_group = (bool(*)(ike_cfg_t*,diffie_hellman_group_t)) check_dh_group;
this->public.get_ref = (void(*)(ike_cfg_t*))get_ref;
this->public.destroy = (void(*)(ike_cfg_t*))destroy;
/* private variables */
this->refcount = 1;
this->certreq = certreq;
this->my_host = my_host;
this->other_host = other_host;
this->proposals = linked_list_create();
return &this->public;
}

160
src/charon/config/ike_cfg.h Normal file
View File

@ -0,0 +1,160 @@
/**
* @file ike_cfg.h
*
* @brief Interface of ike_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 IKE_CFG_H_
#define IKE_CFG_H_
typedef struct ike_cfg_t ike_cfg_t;
#include <library.h>
#include <utils/host.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <config/proposal.h>
#include <crypto/diffie_hellman.h>
/**
* @brief An ike_cfg_t defines the rules to set up an IKE_SA.
*
* @b Constructors:
* - ike_cfg_create()
*
* @ingroup ike_cfg
*/
struct ike_cfg_t {
/**
* @brief Get own address.
*
* @param this calling object
* @return host information as host_t object
*/
host_t* (*get_my_host) (ike_cfg_t *this);
/**
* @brief Get peers address.
*
* @param this calling object
* @return host information as host_t object
*/
host_t* (*get_other_host) (ike_cfg_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) (ike_cfg_t *this, proposal_t *proposal);
/**
* @brief Returns a list of all supported proposals.
*
* Returned list and its proposals must be destroyed after use.
*
* @param this calling object
* @return list containing all the proposals
*/
linked_list_t* (*get_proposals) (ike_cfg_t *this);
/**
* @brief Select a proposed from suggested proposals.
*
* Returned proposal must be destroyed after use.
*
* @param this calling object
* @param proposals list of proposals to select from
* @return selected proposal, or NULL if none matches.
*/
proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals);
/**
* @brief Should we send a certificate request in IKE_SA_INIT?
*
* @param this calling object
* @return certificate request sending policy
*/
bool (*send_certreq) (ike_cfg_t *this);
/**
* @brief Get the DH group to use for IKE_SA setup.
*
* @param this calling object
* @return dh group to use for initialization
*/
diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this);
/**
* @brief 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) (ike_cfg_t *this, diffie_hellman_group_t dh_group);
/**
* @brief Get a new reference to this ike_cfg.
*
* Get a new reference to this ike_cfg by increasing
* it's internal reference counter.
* Do not call get_ref or any other function until you
* already have a reference. Otherwise the object may get
* destroyed while calling get_ref(),
*
* @param this calling object
*/
void (*get_ref) (ike_cfg_t *this);
/**
* @brief Destroys a ike_cfg_t object.
*
* Decrements the internal reference counter and
* destroys the ike_cfg when it reaches zero.
*
* @param this calling object
*/
void (*destroy) (ike_cfg_t *this);
};
/**
* @brief Creates a ike_cfg_t object.
*
* Supplied hosts become owned by ike_cfg, the name gets cloned.
*
* @param name ike_cfg identifier
* @param certreq TRUE to send a certificate request
* @param my_host host_t representing local address
* @param other_host host_t representing remote address
* @return ike_cfg_t object.
*
* @ingroup config
*/
ike_cfg_t *ike_cfg_create(bool certreq, host_t *my_host, host_t *other_host);
#endif /* IKE_CFG_H_ */

View File

@ -0,0 +1,470 @@
/**
* @file peer_cfg.c
*
* @brief Implementation of peer_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 <string.h>
#include <pthread.h>
#include "peer_cfg.h"
#include <utils/linked_list.h>
#include <utils/identification.h>
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"CERT_ALWAYS_SEND",
"CERT_SEND_IF_ASKED",
"CERT_NEVER_SEND"
);
ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
"DPD_NONE",
"DPD_CLEAR",
"DPD_ROUTE",
"DPD_RESTART"
);
typedef struct private_peer_cfg_t private_peer_cfg_t;
/**
* Private data of an peer_cfg_t object
*/
struct private_peer_cfg_t {
/**
* Public part
*/
peer_cfg_t public;
/**
* Number of references hold by others to this peer_cfg
*/
refcount_t refcount;
/**
* Name of the peer_cfg, used to query it
*/
char *name;
/**
* IKE version to use for initiation
*/
u_int ike_version;
/**
* IKE config associated to this peer config
*/
ike_cfg_t *ike_cfg;
/**
* list of child configs associated to this peer config
*/
linked_list_t *child_cfgs;
/**
* mutex to lock access to list of child_cfgs
*/
pthread_mutex_t mutex;
/**
* id to use to identify us
*/
identification_t *my_id;
/**
* allowed id for other
*/
identification_t *other_id;
/**
* we have a cert issued by this CA
*/
identification_t *my_ca;
/**
* we require the other end to have a cert issued by this CA
*/
identification_t *other_ca;
/**
* should we send a certificate
*/
cert_policy_t cert_policy;
/**
* Method to use for own authentication data
*/
auth_method_t auth_method;
/**
* EAP type to use for peer authentication
*/
eap_type_t eap_type;
/**
* number of tries after giving up if peer does not respond
*/
u_int32_t keyingtries;
/**
* user reauthentication instead of rekeying
*/
bool use_reauth;
/**
* Time before an SA gets invalid
*/
u_int32_t lifetime;
/**
* Time before an SA gets rekeyed
*/
u_int32_t rekeytime;
/**
* Time, which specifies the range of a random value
* substracted from lifetime.
*/
u_int32_t jitter;
/**
* What to do with an SA when other peer seams to be dead?
*/
bool dpd_delay;
/**
* What to do with CHILDren when other peer seams to be dead?
*/
bool dpd_action;
/**
* virtual IP to use locally
*/
host_t *my_virtual_ip;
/**
* virtual IP to use remotly
*/
host_t *other_virtual_ip;
};
/**
* Implementation of peer_cfg_t.get_name
*/
static char *get_name(private_peer_cfg_t *this)
{
return this->name;
}
/**
* Implementation of peer_cfg_t.get_ike_version
*/
static u_int get_ike_version(private_peer_cfg_t *this)
{
return this->ike_version;
}
/**
* Implementation of peer_cfg_t.get_ike_cfg
*/
static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
{
return this->ike_cfg;
}
/**
* Implementation of peer_cfg_t.add_child_cfg.
*/
static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
{
pthread_mutex_lock(&this->mutex);
this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
pthread_mutex_unlock(&this->mutex);
}
/**
* Implementation of peer_cfg_t.create_child_cfg_iterator.
*/
static iterator_t* create_child_cfg_iterator(private_peer_cfg_t *this)
{
return this->child_cfgs->create_iterator_locked(this->child_cfgs,
&this->mutex);
}
/**
* Check if child_cfg contains traffic selectors
*/
static bool contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
host_t *host)
{
linked_list_t *selected;
bool contains = FALSE;
selected = child->get_traffic_selectors(child, mine, ts, host);
contains = selected->get_count(selected);
selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
return contains;
}
/**
* Implementation of peer_cfg_t.select_child_cfg
*/
static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
linked_list_t *my_ts,
linked_list_t *other_ts,
host_t *my_host, host_t *other_host)
{
child_cfg_t *current, *found = NULL;
iterator_t *iterator;
iterator = create_child_cfg_iterator(this);
while (iterator->iterate(iterator, (void**)&current))
{
if (contains_ts(current, TRUE, my_ts, my_host) &&
contains_ts(current, FALSE, other_ts, other_host))
{
found = current;
found->get_ref(found);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of peer_cfg_t.get_my_id
*/
static identification_t *get_my_id(private_peer_cfg_t *this)
{
return this->my_id;
}
/**
* Implementation of peer_cfg_t.get_other_id
*/
static identification_t *get_other_id(private_peer_cfg_t *this)
{
return this->other_id;
}
/**
* Implementation of peer_cfg_t.get_my_ca
*/
static identification_t *get_my_ca(private_peer_cfg_t *this)
{
return this->my_ca;
}
static identification_t *get_other_ca(private_peer_cfg_t *this)
{
return this->other_ca;
}
/**
* Implementation of peer_cfg_t.get_cert_policy.
*/
static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
{
return this->cert_policy;
}
/**
* Implementation of connection_t.auth_method_t.
*/
static auth_method_t get_auth_method(private_peer_cfg_t *this)
{
return this->auth_method;
}
/**
* Implementation of connection_t.get_eap_type.
*/
static eap_type_t get_eap_type(private_peer_cfg_t *this)
{
return this->eap_type;
}
/**
* Implementation of connection_t.get_keyingtries.
*/
static u_int32_t get_keyingtries(private_peer_cfg_t *this)
{
return this->keyingtries;
}
/**
* Implementation of peer_cfg_t.get_soft_lifetime
*/
static u_int32_t get_lifetime(private_peer_cfg_t *this, bool rekey)
{
if (rekey)
{
if (this->jitter == 0)
{
return this->rekeytime;
}
return this->rekeytime - (random() % this->jitter);
}
return this->lifetime;
}
/**
* Implementation of peer_cfg_t.use_reauth.
*/
static bool use_reauth(private_peer_cfg_t *this, bool rekey)
{
return this->use_reauth;
}
/**
* Implements peer_cfg_t.get_dpd_delay
*/
static u_int32_t get_dpd_delay(private_peer_cfg_t *this)
{
return this->dpd_action;
}
/**
* Implements peer_cfg_t.get_dpd_action
*/
static dpd_action_t get_dpd_action(private_peer_cfg_t *this)
{
return this->dpd_action;
}
/**
* Implementation of peer_cfg_t.get_virtual_ip.
*/
static host_t* get_virtual_ip(private_peer_cfg_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 peer_cfg_t.get_ref.
*/
static void get_ref(private_peer_cfg_t *this)
{
ref_get(&this->refcount);
}
/**
* Implements peer_cfg_t.destroy.
*/
static void destroy(private_peer_cfg_t *this)
{
if (ref_put(&this->refcount))
{
this->ike_cfg->destroy(this->ike_cfg);
this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy));
this->my_id->destroy(this->my_id);
this->other_id->destroy(this->other_id);
DESTROY_IF(this->my_ca);
DESTROY_IF(this->other_ca);
DESTROY_IF(this->my_virtual_ip);
DESTROY_IF(this->other_virtual_ip);
free(this->name);
free(this);
}
}
/*
* Described in header-file
*/
peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
identification_t *my_id, identification_t *other_id,
identification_t *my_ca, identification_t *other_ca,
cert_policy_t cert_policy, auth_method_t auth_method,
eap_type_t eap_type, u_int32_t keyingtries,
u_int32_t lifetime, u_int32_t rekeytime,
u_int32_t jitter, bool reauth,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip)
{
private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
/* public functions */
this->public.get_name = (char* (*) (peer_cfg_t *))get_name;
this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version;
this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg;
this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg;
this->public.create_child_cfg_iterator = (iterator_t* (*) (peer_cfg_t *))create_child_cfg_iterator;
this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg;
this->public.get_my_id = (identification_t* (*)(peer_cfg_t*))get_my_id;
this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca;
this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca;
this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type;
this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
this->public.get_lifetime = (u_int32_t (*) (peer_cfg_t *, bool rekey))get_lifetime;
this->public.use_reauth = (bool (*) (peer_cfg_t *))use_reauth;
this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_virtual_ip;
this->public.get_ref = (void(*)(peer_cfg_t *))get_ref;
this->public.destroy = (void(*)(peer_cfg_t *))destroy;
/* apply init values */
this->name = strdup(name);
this->ike_version = ike_version;
this->ike_cfg = ike_cfg;
this->child_cfgs = linked_list_create();
pthread_mutex_init(&this->mutex, NULL);
this->my_id = my_id;
this->other_id = other_id;
this->my_ca = my_ca;
this->other_ca = other_ca;
this->cert_policy = cert_policy;
this->auth_method = auth_method;
this->eap_type = eap_type;
this->keyingtries = keyingtries;
this->lifetime = lifetime;
this->rekeytime = rekeytime;
this->jitter = jitter;
this->use_reauth = reauth;
this->dpd_delay = dpd_delay;
this->dpd_action = dpd_action;
this->my_virtual_ip = my_virtual_ip;
this->other_virtual_ip = other_virtual_ip;
this->refcount = 1;
return &this->public;
}

View File

@ -0,0 +1,345 @@
/**
* @file peer_cfg.h
*
* @brief Interface of peer_cfg_t.
*
*/
/*
* Copyright (C) 2005-2007 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 PEER_CFG_H_
#define PEER_CFG_H_
typedef enum dpd_action_t dpd_action_t;
typedef enum cert_policy_t cert_policy_t;
typedef struct peer_cfg_t peer_cfg_t;
#include <library.h>
#include <utils/identification.h>
#include <config/traffic_selector.h>
#include <config/proposal.h>
#include <config/ike_cfg.h>
#include <config/child_cfg.h>
#include <sa/authenticators/authenticator.h>
#include <sa/authenticators/eap/eap_method.h>
/**
* Certificate sending policy. This is also used for certificate
* requests when using this definition for the other peer. If
* it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
* included.
*
* @ingroup config
*
* @warning These definitions must be the same as in pluto/starter,
* as they are sent over the stroke socket.
*/
enum cert_policy_t {
/** always send certificates, even when not requested */
CERT_ALWAYS_SEND = 0,
/** send certificate upon cert request */
CERT_SEND_IF_ASKED = 1,
/** never send a certificate, even when requested */
CERT_NEVER_SEND = 2,
};
/**
* enum strings for cert_policy_t
*
* @ingroup config
*/
extern enum_name_t *cert_policy_names;
/**
* @brief Actions to take when a peer does not respond (dead peer detected).
*
* These values are the same as in pluto/starter, so do not modify them!
*
* @ingroup peer_cfg
*/
enum dpd_action_t {
/** DPD disabled */
DPD_NONE,
/** remove CHILD_SAs without replacement */
DPD_CLEAR,
/** route the CHILD_SAs to resetup when needed */
DPD_ROUTE,
/** restart CHILD_SAs in a new IKE_SA, immediately */
DPD_RESTART,
};
/**
* enum names for dpd_action_t.
*/
extern enum_name_t *dpd_action_names;
/**
* @brief Configuration of a peer, specified by IDs.
*
* @b Constructors:
* - peer_cfg_create()
*
* @ingroup peer_cfg
*/
struct peer_cfg_t {
/**
* @brief Get the name of the peer_cfg.
*
* Returned object is not getting cloned.
*
* @param this calling object
* @return peer_cfg's name
*/
char* (*get_name) (peer_cfg_t *this);
/**
* @brief Get the IKE version to use for initiating.
*
* @param this calling object
* @return IKE major version
*/
u_int (*get_ike_version)(peer_cfg_t *this);
/**
* @brief Get the IKE config to use for initiaton.
*
* @param this calling object
* @return the IKE config to use
*/
ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this);
/**
* @brief Attach a CHILD config.
*
* @param this calling object
* @param child_cfg CHILD config to add
*/
void (*add_child_cfg) (peer_cfg_t *this, child_cfg_t *child_cfg);
/**
* @brief Create an iterator for all attached CHILD configs.
*
* @param this calling object
* @return an iterator over all CHILD configs.
*/
iterator_t* (*create_child_cfg_iterator) (peer_cfg_t *this);
/**
* @brief Select a CHILD config from traffic selectors.
*
* @param this calling object
* @param my_ts TS for local side
* @param other_ts TS for remote side
* @param my_host host to narrow down dynamic TS for local side
* @param other_host host to narrow down dynamic TS for remote side
* @return selected CHILD config, or NULL if no match found
*/
child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, linked_list_t *my_ts,
linked_list_t *other_ts, host_t *my_host,
host_t *other_host);
/**
* @brief Get own ID.
*
* @param this calling object
* @return own id
*/
identification_t* (*get_my_id)(peer_cfg_t *this);
/**
* @brief Get peers ID.
*
* @param this calling object
* @return other id
*/
identification_t* (*get_other_id)(peer_cfg_t *this);
/**
* @brief Get own CA.
*
* @param this calling object
* @return own ca
*/
identification_t* (*get_my_ca)(peer_cfg_t *this);
/**
* @brief Get peers CA.
*
* @param this calling object
* @return other ca
*/
identification_t* (*get_other_ca)(peer_cfg_t *this);
/**
* @brief Should be sent a certificate for this connection?
*
* @param this calling object
* @return certificate sending policy
*/
cert_policy_t (*get_cert_policy) (peer_cfg_t *this);
/**
* @brief Get the authentication method to use to authenticate us.
*
* @param this calling object
* @return authentication method
*/
auth_method_t (*get_auth_method) (peer_cfg_t *this);
/**
* @brief Get the EAP type to use for peer authentication.
*
* @param this calling object
* @return authentication method
*/
eap_type_t (*get_eap_type) (peer_cfg_t *this);
/**
* @brief Get the max number of retries after timeout.
*
* @param this calling object
* @return max number retries
*/
u_int32_t (*get_keyingtries) (peer_cfg_t *this);
/**
* @brief Get the lifetime of a IKE_SA.
*
* If "rekey" is set to TRUE, a lifetime is returned before the first
* rekeying should be started. If it is FALSE, the actual lifetime is
* returned when the IKE_SA must be deleted.
* The rekey time automatically contains a jitter to avoid simlutaneous
* rekeying.
*
* @param this child_config
* @param rekey TRUE to get rekey time
* @return lifetime in seconds
*/
u_int32_t (*get_lifetime) (peer_cfg_t *this, bool rekey);
/**
* @brief Should a full reauthentication be done instead of rekeying?
*
* @param this calling object
* @return TRUE to use full reauthentication
*/
bool (*use_reauth) (peer_cfg_t *this);
/**
* @brief Get the DPD check interval.
*
* @param this calling object
* @return dpd_delay in seconds
*/
u_int32_t (*get_dpd_delay) (peer_cfg_t *this);
/**
* @brief What should be done with a CHILD_SA, when other peer does not respond.
*
* @param this calling object
* @return dpd action
*/
dpd_action_t (*get_dpd_action) (peer_cfg_t *this);
/**
* @brief Get a virtual IP for the local 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 peer_cfg
* @param suggestion NULL, %any or specific, see description
* @return clone of an IP to use, or NULL
*/
host_t* (*get_virtual_ip) (peer_cfg_t *this, host_t *suggestion);
/**
* @brief Get a new reference.
*
* Get a new reference to this peer_cfg by increasing
* it's internal reference counter.
* Do not call get_ref or any other function until you
* already have a reference. Otherwise the object may get
* destroyed while calling get_ref(),
*
* @param this calling object
*/
void (*get_ref) (peer_cfg_t *this);
/**
* @brief Destroys the peer_cfg object.
*
* Decrements the internal reference counter and
* destroys the peer_cfg when it reaches zero.
*
* @param this calling object
*/
void (*destroy) (peer_cfg_t *this);
};
/**
* @brief Create a configuration object for IKE_AUTH and later.
*
* 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
* (rekeylifetime - random(0, jitter)).
*
* @param name name of the peer_cfg
* @param ike_version which IKE version we sould use for this peer
* @param ike_cfg IKE config to use when acting as initiator
* @param my_id identification_t for ourselves
* @param other_id identification_t for the remote guy
* @param my_ca CA to use for us
* @param other_ca CA to use for other
* @param cert_policy should we send a certificate payload?
* @param auth_method auth method to use to authenticate us
* @param eap_type EAP type to use for peer authentication
* @param keyingtries how many keying tries should be done before giving up
* @param lifetime lifetime before deleting an SA
* @param rekeytime lifetime before rekeying an SA
* @param jitter range of random to substract from rekeytime
* @param use_reauth sould be done reauthentication instead of rekeying?
* @param dpd_delay after how many seconds of inactivity to check DPD
* @param dpd_action what to do with CHILD_SAs when detected a dead peer
* @param my_virtual_ip virtual IP for local host, or NULL
* @param other_virtual_ip virtual IP for remote host, or NULL
* @return peer_cfg_t object
*
* @ingroup config
*/
peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
identification_t *my_id, identification_t *other_id,
identification_t *my_ca, identification_t *other_ca,
cert_policy_t cert_policy, auth_method_t auth_method,
eap_type_t eap_type, u_int32_t keyingtries,
u_int32_t lifetime, u_int32_t rekeytime,
u_int32_t jitter, bool use_reauth,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip);
#endif /* PEER_CFG_H_ */

View File

@ -1,282 +0,0 @@
/**
* @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);
}

View File

@ -1,60 +0,0 @@
/**
* @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_ */

View File

@ -1,635 +0,0 @@
/**
* @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;
}

View File

@ -1,413 +0,0 @@
/**
* @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_ */

View File

@ -1,119 +0,0 @@
/**
* @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_*/

View File

@ -167,6 +167,8 @@ static int print(FILE *stream, const struct printf_info *info,
const void *const *args)
{
private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
linked_list_t *list = *((linked_list_t**)(args[0]));
iterator_t *iterator;
char addr_str[INET6_ADDRSTRLEN] = "";
char *serv_proto = NULL;
u_int8_t mask;
@ -179,6 +181,24 @@ static int print(FILE *stream, const struct printf_info *info,
return fprintf(stream, "(null)");
}
if (info->alt)
{
iterator = list->create_iterator(list, TRUE);
while (iterator->iterate(iterator, (void**)&this))
{
/* call recursivly */
written += fprintf(stream, "%R ", this);
}
iterator->destroy(iterator);
return written;
}
if (this->dynamic)
{
return fprintf(stream, "dynamic/%d",
this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
}
if (this->type == TS_IPV4_ADDR_RANGE)
{
inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));

View File

View File

View File

@ -1,12 +1,12 @@
/**
* @file stroke.c
* @file stroke_interface.c
*
* @brief Implementation of stroke_t.
* @brief Implementation of stroke_interface_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Copyright (C) 2006-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -40,23 +40,23 @@
#include <crypto/x509.h>
#include <crypto/ca.h>
#include <crypto/crl.h>
#include <queues/jobs/initiate_job.h>
#include <queues/jobs/route_job.h>
#include <processing/jobs/initiate_job.h>
#include <processing/jobs/route_job.h>
#include <utils/leak_detective.h>
#define IKE_PORT 500
#define PATH_BUF 256
#define STROKE_THREADS 3
struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
typedef struct private_stroke_t private_stroke_t;
typedef struct private_stroke_interface_t private_stroke_interface_t;
/**
* Private data of an stroke_t object.
*/
struct private_stroke_t {
struct private_stroke_interface_t {
/**
* Public part of stroke_t object.
@ -64,9 +64,9 @@ struct private_stroke_t {
stroke_t public;
/**
* Output stream (stroke console)
* backend to store configurations
*/
FILE *out;
local_backend_t *backend;
/**
* Unix socket to listen for strokes
@ -76,7 +76,7 @@ struct private_stroke_t {
/**
* Thread which reads from the Socket
*/
pthread_t assigned_thread;
pthread_t threads[STROKE_THREADS];
};
/**
@ -187,10 +187,12 @@ static x509_t* load_ca_certificate(const char *filename)
/**
* Add a connection to the configuration list
*/
static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
static void stroke_add_conn(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
connection_t *connection;
policy_t *policy;
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
identification_t *my_id, *other_id;
identification_t *my_ca = NULL;
identification_t *other_ca = NULL;
@ -201,6 +203,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
proposal_t *proposal;
traffic_selector_t *my_ts, *other_ts;
char *interface;
bool use_existing = FALSE;
iterator_t *iterator;
pop_string(msg, &msg->add_conn.name);
pop_string(msg, &msg->add_conn.me.address);
@ -421,67 +425,102 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
DBG2(DBG_CFG, " other ca:'%D'", other_ca);
DBG2(DBG_CFG, " updown: '%s'", msg->add_conn.me.updown);
connection = connection_create(msg->add_conn.name,
msg->add_conn.ikev2,
msg->add_conn.me.sendcert,
msg->add_conn.other.sendcert,
my_host, other_host,
msg->add_conn.dpd.delay,
msg->add_conn.rekey.reauth,
msg->add_conn.rekey.tries,
msg->add_conn.rekey.ike_lifetime,
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
if (msg->add_conn.algorithms.ike)
/* have a look for an (almost) identical peer config to reuse */
iterator = this->backend->create_peer_cfg_iterator(this->backend);
while (iterator->iterate(iterator, (void**)&peer_cfg))
{
char *proposal_string;
char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
if (*strict == '!')
*strict = '\0';
else
strict = NULL;
while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg)) &&
other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg)) &&
my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg)) &&
other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg)) &&
peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) &&
peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method &&
peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
{
proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
if (proposal == NULL)
{
DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
my_id->destroy(my_id);
other_id->destroy(other_id);
my_ts->destroy(my_ts);
other_ts->destroy(other_ts);
my_ca->destroy(my_ca);
other_ca->destroy(other_ca);
connection->destroy(connection);
return;
}
connection->add_proposal(connection, proposal);
}
if (!strict)
{
proposal = proposal_create_default(PROTO_IKE);
connection->add_proposal(connection, proposal);
DBG1(DBG_CFG, "reusing existing configuration '%s'",
peer_cfg->get_name(peer_cfg));
use_existing = TRUE;
break;
}
}
iterator->destroy(iterator);
if (use_existing)
{
my_host->destroy(my_host);
my_id->destroy(my_id);
my_ca->destroy(my_ca);
other_host->destroy(other_host);
other_id->destroy(other_id);
other_ca->destroy(other_ca);
}
else
{
proposal = proposal_create_default(PROTO_IKE);
connection->add_proposal(connection, proposal);
ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
my_host, other_host);
if (msg->add_conn.algorithms.ike)
{
char *proposal_string;
char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
if (*strict == '!')
*strict = '\0';
else
strict = NULL;
while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
{
proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
if (proposal == NULL)
{
DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
my_id->destroy(my_id);
other_id->destroy(other_id);
my_ts->destroy(my_ts);
other_ts->destroy(other_ts);
my_ca->destroy(my_ca);
other_ca->destroy(other_ca);
ike_cfg->destroy(ike_cfg);
return;
}
ike_cfg->add_proposal(ike_cfg, proposal);
}
if (!strict)
{
proposal = proposal_create_default(PROTO_IKE);
ike_cfg->add_proposal(ike_cfg, proposal);
}
}
else
{
proposal = proposal_create_default(PROTO_IKE);
ike_cfg->add_proposal(ike_cfg, proposal);
}
peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
ike_cfg, my_id, other_id, my_ca, other_ca, msg->add_conn.me.sendcert,
msg->add_conn.auth_method, msg->add_conn.eap_type,
msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.rekey.reauth, msg->add_conn.dpd.delay,
msg->add_conn.dpd.action,my_vip, other_vip);
}
policy = policy_create(msg->add_conn.name, my_id, other_id, my_vip, other_vip,
msg->add_conn.auth_method, msg->add_conn.eap_type,
msg->add_conn.rekey.ipsec_lifetime,
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode, msg->add_conn.dpd.action);
policy->add_my_traffic_selector(policy, my_ts);
policy->add_other_traffic_selector(policy, other_ts);
policy->add_authorities(policy, my_ca, other_ca);
child_cfg = child_cfg_create(
msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode);
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
child_cfg->add_traffic_selector(child_cfg, TRUE, my_ts);
child_cfg->add_traffic_selector(child_cfg, FALSE, other_ts);
if (msg->add_conn.algorithms.esp)
{
@ -499,31 +538,30 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
if (proposal == NULL)
{
DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
policy->destroy(policy);
connection->destroy(connection);
peer_cfg->destroy(peer_cfg);
return;
}
policy->add_proposal(policy, proposal);
child_cfg->add_proposal(child_cfg, proposal);
}
if (!strict)
{
proposal = proposal_create_default(PROTO_ESP);
policy->add_proposal(policy, proposal);
child_cfg->add_proposal(child_cfg, proposal);
}
}
else
{
proposal = proposal_create_default(PROTO_ESP);
policy->add_proposal(policy, proposal);
child_cfg->add_proposal(child_cfg, proposal);
}
/* add to global connection list */
charon->connections->add_connection(charon->connections, connection);
DBG1(DBG_CFG, "added connection '%s': %H[%D]...%H[%D]",
msg->add_conn.name, my_host, my_id, other_host, other_id);
/* add to global policy list */
charon->policies->add_policy(charon->policies, policy);
if (!use_existing)
{
/* add config to backend */
this->backend->add_peer_cfg(this->backend, peer_cfg);
DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]",
msg->add_conn.name, my_host, my_id, other_host, other_id);
}
return;
/* mopping up after parsing errors */
@ -540,69 +578,109 @@ destroy_hosts:
/**
* Delete a connection from the list
*/
static void stroke_del_conn(stroke_msg_t *msg, FILE *out)
static void stroke_del_conn(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
status_t status;
iterator_t *peer_iter, *child_iter;
peer_cfg_t *peer, *child;
pop_string(msg, &(msg->del_conn.name));
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
status = charon->connections->delete_connection(charon->connections,
msg->del_conn.name);
charon->policies->delete_policy(charon->policies, msg->del_conn.name);
if (status == SUCCESS)
peer_iter = this->backend->create_peer_cfg_iterator(this->backend);
while (peer_iter->iterate(peer_iter, (void**)&peer))
{
fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
/* remove peer config with such a name */
if (streq(peer->get_name(peer), msg->del_conn.name))
{
peer_iter->remove(peer_iter);
peer->destroy(peer);
continue;
}
/* remove any child with such a name */
child_iter = peer->create_child_cfg_iterator(peer);
while (child_iter->iterate(child_iter, (void**)&child))
{
if (streq(child->get_name(child), msg->del_conn.name))
{
child_iter->remove(child_iter);
child->destroy(child);
}
}
child_iter->destroy(child_iter);
}
else
peer_iter->destroy(peer_iter);
fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
}
/**
* get the child_cfg with the same name as the peer cfg
*/
static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg)
{
child_cfg_t *current, *found = NULL;
iterator_t *iterator;
iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
while (iterator->iterate(iterator, (void**)&current))
{
fprintf(out, "no connection named '%s'\n", msg->del_conn.name);
if (streq(current->get_name(current), peer_cfg->get_name(peer_cfg)))
{
found = current;
found->get_ref(found);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* initiate a connection by name
*/
static void stroke_initiate(stroke_msg_t *msg, FILE *out)
static void stroke_initiate(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
initiate_job_t *job;
connection_t *connection;
policy_t *policy;
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
ike_sa_t *init_ike_sa = NULL;
signal_t signal;
pop_string(msg, &(msg->initiate.name));
DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
connection = charon->connections->get_connection_by_name(charon->connections,
msg->initiate.name);
if (connection == NULL)
peer_cfg = charon->cfg_store->get_peer_cfg_by_name(charon->cfg_store,
msg->initiate.name);
if (peer_cfg == NULL)
{
if (msg->output_verbosity >= 0)
{
fprintf(out, "no connection named '%s'\n", msg->initiate.name);
fprintf(out, "no config named '%s'\n", msg->initiate.name);
}
return;
}
if (!connection->is_ikev2(connection))
if (peer_cfg->get_ike_version(peer_cfg) != 2)
{
connection->destroy(connection);
DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
peer_cfg->get_ike_version(peer_cfg));
peer_cfg->destroy(peer_cfg);
return;
}
policy = charon->policies->get_policy_by_name(charon->policies,
msg->initiate.name);
if (policy == NULL)
child_cfg = get_child_from_peer(peer_cfg);
if (child_cfg == NULL)
{
if (msg->output_verbosity >= 0)
{
fprintf(out, "no policy named '%s'\n", msg->initiate.name);
fprintf(out, "no child config named '%s'\n", msg->initiate.name);
}
connection->destroy(connection);
peer_cfg->destroy(peer_cfg);
return;
}
job = initiate_job_create(connection, policy);
job = initiate_job_create(peer_cfg, child_cfg);
charon->bus->set_listen_state(charon->bus, TRUE);
charon->job_queue->add(charon->job_queue, (job_t*)job);
while (TRUE)
@ -654,49 +732,48 @@ static void stroke_initiate(stroke_msg_t *msg, FILE *out)
/**
* route/unroute a policy (install SPD entries)
*/
static void stroke_route(stroke_msg_t *msg, FILE *out, bool route)
static void stroke_route(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out, bool route)
{
route_job_t *job;
connection_t *connection;
policy_t *policy;
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
pop_string(msg, &(msg->route.name));
DBG1(DBG_CFG, "received stroke: %s '%s'",
route ? "route" : "unroute", msg->route.name);
/* we wouldn't need a connection, but we only want to route policies
* whose connections are keyexchange=ikev2. */
connection = charon->connections->get_connection_by_name(charon->connections,
msg->route.name);
if (connection == NULL)
peer_cfg = charon->cfg_store->get_peer_cfg_by_name(charon->cfg_store,
msg->route.name);
if (peer_cfg == NULL)
{
fprintf(out, "no connection named '%s'\n", msg->route.name);
fprintf(out, "no config named '%s'\n", msg->route.name);
return;
}
if (!connection->is_ikev2(connection))
if (peer_cfg->get_ike_version(peer_cfg) != 2)
{
connection->destroy(connection);
peer_cfg->destroy(peer_cfg);
return;
}
policy = charon->policies->get_policy_by_name(charon->policies,
msg->route.name);
if (policy == NULL)
child_cfg = get_child_from_peer(peer_cfg);
if (child_cfg == NULL)
{
fprintf(out, "no policy named '%s'\n", msg->route.name);
connection->destroy(connection);
fprintf(out, "no child config named '%s'\n", msg->route.name);
peer_cfg->destroy(peer_cfg);
return;
}
fprintf(out, "%s policy '%s'\n",
route ? "routing" : "unrouting", msg->route.name);
job = route_job_create(connection, policy, route);
job = route_job_create(peer_cfg, child_cfg, route);
charon->job_queue->add(charon->job_queue, (job_t*)job);
}
/**
* terminate a connection by name
*/
static void stroke_terminate(stroke_msg_t *msg, FILE *out)
static void stroke_terminate(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
char *string, *pos = NULL, *name = NULL;
u_int32_t id = 0;
@ -797,7 +874,8 @@ static void stroke_terminate(stroke_msg_t *msg, FILE *out)
/**
* Add a ca information record to the cainfo list
*/
static void stroke_add_ca(stroke_msg_t *msg, FILE *out)
static void stroke_add_ca(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
x509_t *cacert;
ca_info_t *ca_info;
@ -864,7 +942,8 @@ static void stroke_add_ca(stroke_msg_t *msg, FILE *out)
/**
* Delete a ca information record from the cainfo list
*/
static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
static void stroke_del_ca(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
status_t status;
@ -887,13 +966,15 @@ static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
/**
* show status of daemon
*/
static void stroke_statusall(stroke_msg_t *msg, FILE *out)
static void stroke_statusall(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
iterator_t *iterator;
iterator_t *iterator, *children;
linked_list_t *list;
host_t *host;
connection_t *connection;
policy_t *policy;
peer_cfg_t *peer_cfg;
ike_cfg_t *ike_cfg;
child_cfg_t *child_cfg;
ike_sa_t *ike_sa;
char *name = NULL;
@ -923,40 +1004,35 @@ static void stroke_statusall(stroke_msg_t *msg, FILE *out)
name = msg->status.name;
}
iterator = charon->connections->create_iterator(charon->connections);
if (iterator->get_count(iterator) > 0)
fprintf(out, "Connections:\n");
iterator = this->backend->create_peer_cfg_iterator(this->backend);
while (iterator->iterate(iterator, (void**)&peer_cfg))
{
fprintf(out, "Connections:\n");
}
while (iterator->iterate(iterator, (void**)&connection))
{
if (connection->is_ikev2(connection)
&& (name == NULL || streq(name, connection->get_name(connection))))
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
{
fprintf(out, "%12s: %H...%H\n",
connection->get_name(connection),
connection->get_my_host(connection),
connection->get_other_host(connection));
}
}
iterator->destroy(iterator);
iterator = charon->policies->create_iterator(charon->policies);
if (iterator->get_count(iterator) > 0)
{
fprintf(out, "Policies:\n");
}
while (iterator->iterate(iterator, (void**)&policy))
{
if (name == NULL || streq(name, policy->get_name(policy)))
{
fprintf(out, "%12s: '%D'...'%D'\n",
policy->get_name(policy),
policy->get_my_id(policy),
policy->get_other_id(policy));
continue;
}
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
children = peer_cfg->create_child_cfg_iterator(peer_cfg);
while (children->iterate(children, (void**)&child_cfg))
{
linked_list_t *my_ts, *other_ts;
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg),
my_ts, other_ts);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
}
children->destroy(children);
}
iterator->destroy(iterator);
iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
if (iterator->get_count(iterator) > 0)
@ -970,7 +1046,7 @@ static void stroke_statusall(stroke_msg_t *msg, FILE *out)
iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
/* print IKE_SA */
if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
if (name == NULL || strcmp(name, ike_sa->get_name(ike_sa)) == 0)
{
fprintf(out, "%#K\n", ike_sa);
ike_sa_printed = TRUE;
@ -979,7 +1055,7 @@ static void stroke_statusall(stroke_msg_t *msg, FILE *out)
while (children->iterate(children, (void**)&child_sa))
{
bool child_sa_match = name == NULL ||
strncmp(name, child_sa->get_name(child_sa), strlen(name)) == 0;
strcmp(name, child_sa->get_name(child_sa)) == 0;
/* print IKE_SA if its name differs from the CHILD_SA's name */
if (!ike_sa_printed && child_sa_match)
@ -1002,7 +1078,8 @@ static void stroke_statusall(stroke_msg_t *msg, FILE *out)
/**
* show status of daemon
*/
static void stroke_status(stroke_msg_t *msg, FILE *out)
static void stroke_status(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
iterator_t *iterator;
ike_sa_t *ike_sa;
@ -1022,7 +1099,7 @@ static void stroke_status(stroke_msg_t *msg, FILE *out)
iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
/* print IKE_SA */
if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
if (name == NULL || strcmp(name, ike_sa->get_name(ike_sa)) == 0)
{
fprintf(out, "%K\n", ike_sa);
ike_sa_printed = TRUE;
@ -1031,7 +1108,7 @@ static void stroke_status(stroke_msg_t *msg, FILE *out)
while (children->iterate(children, (void**)&child_sa))
{
bool child_sa_match = name == NULL ||
strncmp(name, child_sa->get_name(child_sa), strlen(name)) == 0;
strcmp(name, child_sa->get_name(child_sa)) == 0;
/* print IKE_SA if its name differs from the CHILD_SA's name */
if (!ike_sa_printed && child_sa_match)
@ -1054,7 +1131,8 @@ static void stroke_status(stroke_msg_t *msg, FILE *out)
/**
* list all authority certificates matching a specified flag
*/
static void list_auth_certificates(u_int flag, const char *label, bool utc, FILE *out)
static void list_auth_certificates(private_stroke_interface_t *this, u_int flag,
const char *label, bool utc, FILE *out)
{
bool first = TRUE;
x509_t *cert;
@ -1081,7 +1159,8 @@ static void list_auth_certificates(u_int flag, const char *label, bool utc, FILE
/**
* list various information
*/
static void stroke_list(stroke_msg_t *msg, FILE *out)
static void stroke_list(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
iterator_t *iterator;
@ -1111,7 +1190,7 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
}
if (msg->list.flags & LIST_CACERTS)
{
list_auth_certificates(AUTH_CA, "CA", msg->list.utc, out);
list_auth_certificates(this, AUTH_CA, "CA", msg->list.utc, out);
}
if (msg->list.flags & LIST_CAINFOS)
{
@ -1132,60 +1211,59 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
}
if (msg->list.flags & LIST_CRLS)
{
ca_info_t *ca_info;
bool first = TRUE;
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
while (iterator->iterate(iterator, (void **)&ca_info))
{
if (ca_info->has_crl(ca_info))
{
if (first)
{
fprintf(out, "\n");
fprintf(out, "List of X.509 CRLs:\n");
fprintf(out, "\n");
first = FALSE;
}
ca_info->list_crl(ca_info, out, msg->list.utc);
}
}
iterator->destroy(iterator);
ca_info_t *ca_info;
bool first = TRUE;
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
while (iterator->iterate(iterator, (void **)&ca_info))
{
if (ca_info->has_crl(ca_info))
{
if (first)
{
fprintf(out, "\n");
fprintf(out, "List of X.509 CRLs:\n");
fprintf(out, "\n");
first = FALSE;
}
ca_info->list_crl(ca_info, out, msg->list.utc);
}
}
iterator->destroy(iterator);
}
if (msg->list.flags & LIST_OCSPCERTS)
{
list_auth_certificates(AUTH_OCSP, "OCSP", msg->list.utc, out);
list_auth_certificates(this, AUTH_OCSP, "OCSP", msg->list.utc, out);
}
if (msg->list.flags & LIST_OCSP)
{
ca_info_t *ca_info;
bool first = TRUE;
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
while (iterator->iterate(iterator, (void **)&ca_info))
{
if (ca_info->has_certinfos(ca_info))
{
if (first)
{
fprintf(out, "\n");
fprintf(out, "List of OCSP responses:\n");
first = FALSE;
}
fprintf(out, "\n");
ca_info->list_certinfos(ca_info, out, msg->list.utc);
}
}
iterator->destroy(iterator);
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
while (iterator->iterate(iterator, (void **)&ca_info))
{
if (ca_info->has_certinfos(ca_info))
{
if (first)
{
fprintf(out, "\n");
fprintf(out, "List of OCSP responses:\n");
first = FALSE;
}
fprintf(out, "\n");
ca_info->list_certinfos(ca_info, out, msg->list.utc);
}
}
iterator->destroy(iterator);
}
}
/**
* reread various information
*/
static void stroke_reread(stroke_msg_t *msg, FILE *out)
static void stroke_reread(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
if (msg->reread.flags & REREAD_CACERTS)
{
@ -1204,7 +1282,8 @@ static void stroke_reread(stroke_msg_t *msg, FILE *out)
/**
* purge various information
*/
static void stroke_purge(stroke_msg_t *msg, FILE *out)
static void stroke_purge(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
if (msg->purge.flags & PURGE_OCSP)
{
@ -1237,7 +1316,8 @@ signal_t get_signal_from_logtype(char *type)
/**
* set the verbosity debug output
*/
static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
static void stroke_loglevel(private_stroke_interface_t *this,
stroke_msg_t *msg, FILE *out)
{
signal_t signal;
@ -1259,13 +1339,12 @@ static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
/**
* process a stroke request from the socket pointed by "fd"
*/
static void stroke_process(int *fd)
static void stroke_process(private_stroke_interface_t *this, int strokefd)
{
stroke_msg_t *msg;
u_int16_t msg_length;
ssize_t bytes_read;
FILE *out;
int strokefd = *fd;
/* peek the length */
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
@ -1300,46 +1379,46 @@ static void stroke_process(int *fd)
switch (msg->type)
{
case STR_INITIATE:
stroke_initiate(msg, out);
stroke_initiate(this, msg, out);
break;
case STR_ROUTE:
stroke_route(msg, out, TRUE);
stroke_route(this, msg, out, TRUE);
break;
case STR_UNROUTE:
stroke_route(msg, out, FALSE);
stroke_route(this, msg, out, FALSE);
break;
case STR_TERMINATE:
stroke_terminate(msg, out);
stroke_terminate(this, msg, out);
break;
case STR_STATUS:
stroke_status(msg, out);
stroke_status(this, msg, out);
break;
case STR_STATUS_ALL:
stroke_statusall(msg, out);
stroke_statusall(this, msg, out);
break;
case STR_ADD_CONN:
stroke_add_conn(msg, out);
stroke_add_conn(this, msg, out);
break;
case STR_DEL_CONN:
stroke_del_conn(msg, out);
stroke_del_conn(this, msg, out);
break;
case STR_ADD_CA:
stroke_add_ca(msg, out);
stroke_add_ca(this, msg, out);
break;
case STR_DEL_CA:
stroke_del_ca(msg, out);
stroke_del_ca(this, msg, out);
break;
case STR_LOGLEVEL:
stroke_loglevel(msg, out);
stroke_loglevel(this, msg, out);
break;
case STR_LIST:
stroke_list(msg, out);
stroke_list(this, msg, out);
break;
case STR_REREAD:
stroke_reread(msg, out);
stroke_reread(this, msg, out);
break;
case STR_PURGE:
stroke_purge(msg, out);
stroke_purge(this, msg, out);
break;
default:
DBG1(DBG_CFG, "received unknown stroke");
@ -1350,15 +1429,14 @@ static void stroke_process(int *fd)
}
/**
* Implementation of private_stroke_t.stroke_receive.
* Implementation of private_stroke_interface_t.stroke_receive.
*/
static void stroke_receive(private_stroke_t *this)
static void stroke_receive(private_stroke_interface_t *this)
{
struct sockaddr_un strokeaddr;
int strokeaddrlen = sizeof(strokeaddr);
int strokefd;
int oldstate;
pthread_t thread;
int strokefd;
/* ignore sigpipe. writing over the pipe back to the console
* only fails if SIGPIPE is ignored. */
@ -1379,24 +1457,22 @@ static void stroke_receive(private_stroke_t *this)
DBG1(DBG_CFG, "accepting stroke connection failed: %m");
continue;
}
/* handle request asynchronously */
if (pthread_create(&thread, NULL, (void*(*)(void*))stroke_process, (void*)&strokefd) != 0)
{
DBG1(DBG_CFG, "failed to spawn stroke thread: %m");
}
/* detach so the thread terminates cleanly */
pthread_detach(thread);
stroke_process(this, strokefd);
}
}
/**
* Implementation of stroke_t.destroy.
*/
static void destroy(private_stroke_t *this)
static void destroy(private_stroke_interface_t *this)
{
pthread_cancel(this->assigned_thread);
pthread_join(this->assigned_thread, NULL);
int i;
for (i = 0; i < STROKE_THREADS; i++)
{
pthread_cancel(this->threads[i]);
pthread_join(this->threads[i], NULL);
}
close(this->socket);
unlink(socket_addr.sun_path);
@ -1406,14 +1482,17 @@ static void destroy(private_stroke_t *this)
/*
* Described in header-file
*/
stroke_t *stroke_create()
stroke_t *stroke_create(local_backend_t *backend)
{
private_stroke_t *this = malloc_thing(private_stroke_t);
private_stroke_interface_t *this = malloc_thing(private_stroke_interface_t);
mode_t old;
int i;
/* public functions */
this->public.destroy = (void (*)(stroke_t*))destroy;
this->backend = backend;
/* set up unix socket */
this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (this->socket == -1)
@ -1442,14 +1521,13 @@ stroke_t *stroke_create()
return NULL;
}
/* start a thread reading from the socket */
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))stroke_receive, this) != 0)
/* start threads reading from the socket */
for (i = 0; i < STROKE_THREADS; i++)
{
DBG1(DBG_CFG, "could not spawn stroke thread");
close(this->socket);
unlink(socket_addr.sun_path);
free(this);
return NULL;
if (pthread_create(&this->threads[i], NULL, (void*(*)(void*))stroke_receive, this) != 0)
{
charon->kill(charon, "unable to create stroke thread");
}
}
return (&this->public);

View File

@ -25,11 +25,14 @@
typedef struct stroke_t stroke_t;
#include <config/backends/local_backend.h>
/**
* @brief Stroke is a configuration and control interface which
* allows other processes to modify charons behavior.
*
* stroke_t allows config manipulation (as whack in pluto).
* stroke_t allows config manipulation (as whack in pluto). Configurations
* are stored in a special backend, the in-memory local_backend_t.
* Messages of type stroke_msg_t's are sent over a unix socket
* (/var/run/charon.ctl).
*
@ -52,10 +55,11 @@ struct stroke_t {
/**
* @brief Create the stroke interface and listen on the socket.
*
* @return stroke_t object
* @param backend backend to store received configurations
* @return stroke_t object
*
* @ingroup threads
*/
stroke_t *stroke_create(void);
stroke_t *stroke_create(local_backend_t *backend);
#endif /* STROKE_INTERFACE_H_ */

View File

@ -42,8 +42,7 @@
#include <crypto/ca.h>
#include <utils/fetcher.h>
#include <config/credentials/local_credential_store.h>
#include <config/connections/local_connection_store.h>
#include <config/policies/local_policy_store.h>
#include <config/backends/local_backend.h>
#include <sa/authenticators/eap/eap_method.h>
@ -179,8 +178,8 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.event_queue);
DESTROY_IF(this->public.configuration);
DESTROY_IF(this->public.credentials);
DESTROY_IF(this->public.connections);
DESTROY_IF(this->public.policies);
DESTROY_IF(this->public.cfg_store);
DESTROY_IF(this->public.local_backend);
sched_yield();
/* we hope the sender could send the outstanding deletes, but
* we shut down here at any cost */
@ -264,9 +263,11 @@ static void initialize(private_daemon_t *this, bool strict, bool syslog,
this->public.ike_sa_manager = ike_sa_manager_create();
this->public.job_queue = job_queue_create();
this->public.event_queue = event_queue_create();
this->public.connections = (connection_store_t*)local_connection_store_create();
this->public.policies = (policy_store_t*)local_policy_store_create();
this->public.credentials = (credential_store_t*)local_credential_store_create(strict);
this->public.cfg_store = cfg_store_create();
this->public.local_backend = local_backend_create();
this->public.cfg_store->register_backend(this->public.cfg_store,
&this->public.local_backend->backend);
/* initialize fetcher_t class */
fetcher_initialize();
@ -279,7 +280,7 @@ static void initialize(private_daemon_t *this, bool strict, bool syslog,
credentials->load_secrets(credentials);
/* start building threads, we are multi-threaded NOW */
this->public.stroke = stroke_create();
this->public.stroke = stroke_create(this->public.local_backend);
this->public.sender = sender_create();
this->public.receiver = receiver_create();
this->public.scheduler = scheduler_create();
@ -335,8 +336,8 @@ private_daemon_t *daemon_create(void)
this->public.event_queue = NULL;
this->public.configuration = NULL;
this->public.credentials = NULL;
this->public.connections = NULL;
this->public.policies = NULL;
this->public.cfg_store = NULL;
this->public.local_backend = NULL;
this->public.sender= NULL;
this->public.receiver = NULL;
this->public.scheduler = NULL;

View File

@ -29,22 +29,21 @@ typedef struct daemon_t daemon_t;
#include <credential_store.h>
#include <threads/sender.h>
#include <threads/receiver.h>
#include <threads/scheduler.h>
#include <threads/kernel_interface.h>
#include <threads/thread_pool.h>
#include <threads/stroke_interface.h>
#include <network/sender.h>
#include <network/receiver.h>
#include <network/socket.h>
#include <processing/scheduler.h>
#include <processing/thread_pool.h>
#include <processing/job_queue.h>
#include <processing/event_queue.h>
#include <kernel/kernel_interface.h>
#include <control/stroke_interface.h>
#include <bus/bus.h>
#include <bus/listeners/file_logger.h>
#include <bus/listeners/sys_logger.h>
#include <sa/ike_sa_manager.h>
#include <queues/job_queue.h>
#include <queues/event_queue.h>
#include <config/configuration.h>
#include <config/connections/connection_store.h>
#include <config/policies/policy_store.h>
#include <config/cfg_store.h>
#include <config/backends/local_backend.h>
/**
* @defgroup charon charon
@ -324,12 +323,12 @@ struct daemon_t {
/**
* A connection_store_t instance.
*/
connection_store_t *connections;
cfg_store_t *cfg_store;
/**
* A policy_store_t instance.
* A backend for cfg_store using in-memory lists
*/
policy_store_t *policies;
local_backend_t *local_backend;
/**
* A credential_store_t instance.

View File

@ -45,9 +45,9 @@
#include <daemon.h>
#include <utils/linked_list.h>
#include <queues/jobs/delete_child_sa_job.h>
#include <queues/jobs/rekey_child_sa_job.h>
#include <queues/jobs/acquire_job.h>
#include <processing/jobs/delete_child_sa_job.h>
#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/acquire_job.h>
/** kernel level protocol identifiers */
#define KERNEL_ESP 50

View File

@ -29,9 +29,9 @@
#include <daemon.h>
#include <network/socket.h>
#include <network/packet.h>
#include <queues/job_queue.h>
#include <queues/jobs/job.h>
#include <queues/jobs/process_message_job.h>
#include <processing/job_queue.h>
#include <processing/jobs/job.h>
#include <processing/jobs/process_message_job.h>
/** length of the full cookie, including time (u_int32_t + SHA1()) */
#define COOKIE_LENGTH 24

View File

@ -29,7 +29,7 @@ typedef struct event_queue_t event_queue_t;
#include <sys/time.h>
#include <library.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**
* @brief Event-Queue used to store timed events.

View File

@ -27,7 +27,7 @@
typedef struct job_queue_t job_queue_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**
* @brief The job queue stores jobs, which will be processed by the thread_pool_t.

View File

@ -26,7 +26,7 @@
typedef struct acquire_job_t acquire_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**
* @brief Class representing an ACQUIRE Job.

View File

@ -27,7 +27,7 @@ typedef struct delete_child_sa_job_t delete_child_sa_job_t;
#include <library.h>
#include <sa/ike_sa_id.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
#include <config/proposal.h>

View File

@ -28,7 +28,7 @@ typedef struct delete_ike_sa_job_t delete_ike_sa_job_t;
#include <library.h>
#include <sa/ike_sa_id.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -40,14 +40,14 @@ struct private_initiate_job_t {
initiate_job_t public;
/**
* associated connection to initiate
* associated peer config to use for IKE_SA setup
*/
connection_t *connection;
peer_cfg_t *peer_cfg;
/**
* associated policy to initiate
* child config to use for CHILD_SA
*/
policy_t *policy;
child_cfg_t *child_cfg;
};
/**
@ -64,14 +64,20 @@ static job_type_t get_type(private_initiate_job_t *this)
static status_t execute(private_initiate_job_t *this)
{
ike_sa_t *ike_sa;
ike_cfg_t *ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
this->connection->get_my_host(this->connection),
this->connection->get_other_host(this->connection),
this->policy->get_my_id(this->policy),
this->policy->get_other_id(this->policy));
ike_cfg->get_my_host(ike_cfg),
ike_cfg->get_other_host(ike_cfg),
this->peer_cfg->get_my_id(this->peer_cfg),
this->peer_cfg->get_other_id(this->peer_cfg));
if (ike_sa->initiate(ike_sa, this->connection, this->policy) != SUCCESS)
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
{
ike_sa->set_peer_cfg(ike_sa, this->peer_cfg);
}
if (ike_sa->initiate(ike_sa, this->child_cfg) != SUCCESS)
{
DBG1(DBG_JOB, "initiation failed, going to delete IKE_SA");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
@ -87,15 +93,15 @@ static status_t execute(private_initiate_job_t *this)
*/
static void destroy(private_initiate_job_t *this)
{
this->connection->destroy(this->connection);
this->policy->destroy(this->policy);
this->peer_cfg->destroy(this->peer_cfg);
this->child_cfg->destroy(this->child_cfg);
free(this);
}
/*
* Described in header
*/
initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy)
initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg)
{
private_initiate_job_t *this = malloc_thing(private_initiate_job_t);
@ -105,8 +111,8 @@ initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy)
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
/* private variables */
this->connection = connection;
this->policy = policy;
this->peer_cfg = peer_cfg;
this->child_cfg = child_cfg;
return &this->public;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -20,15 +20,15 @@
* for more details.
*/
#ifndef INITIATE_IKE_SA_JOB_H_
#define INITIATE_IKE_SA_JOB_H_
#ifndef INITIATE_JOB_H_
#define INITIATE_JOB_H_
typedef struct initiate_job_t initiate_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <config/connections/connection.h>
#include <config/policies/policy.h>
#include <processing/jobs/job.h>
#include <config/peer_cfg.h>
#include <config/child_cfg.h>
/**
* @brief Class representing an INITIATE_IKE_SA Job.
@ -48,14 +48,14 @@ struct initiate_job_t {
};
/**
* @brief Creates a job of type INITIATE_IKE_SA.
* @brief Creates a job of type INITIATE.
*
* @param connection connection_t to initialize
* @param policy policy to set up
* @param peer_cfg peer configuration to use (if not yet established)
* @param child_cfg config to create a CHILD from
* @return initiate_job_t object
*
* @ingroup jobs
*/
initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy);
initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg);
#endif /*INITIATE_IKE_SA_JOB_H_*/
#endif /*INITIATE_JOB_H_*/

View File

@ -28,7 +28,7 @@ typedef struct process_message_job_t process_message_job_t;
#include <library.h>
#include <encoding/message.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**
* @brief Class representing an PROCESS_MESSAGE job.

View File

@ -27,7 +27,7 @@ typedef struct rekey_child_sa_job_t rekey_child_sa_job_t;
#include <library.h>
#include <sa/ike_sa_id.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
#include <config/proposal.h>
/**

View File

@ -27,7 +27,7 @@ typedef struct rekey_ike_sa_job_t rekey_ike_sa_job_t;
#include <library.h>
#include <sa/ike_sa_id.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
/**
* @brief Class representing an REKEY_IKE_SA Job.

View File

@ -27,7 +27,7 @@
typedef struct retransmit_job_t retransmit_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <processing/jobs/job.h>
#include <sa/ike_sa_id.h>
/**

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -39,14 +39,14 @@ struct private_route_job_t {
route_job_t public;
/**
* associated connection to route
* peer config for route
*/
connection_t *connection;
peer_cfg_t *peer_cfg;
/**
* associated policy to route
* child config to route
*/
policy_t *policy;
child_cfg_t *child_cfg;
/**
* route or unroute?
@ -68,22 +68,29 @@ static job_type_t get_type(private_route_job_t *this)
static status_t execute(private_route_job_t *this)
{
ike_sa_t *ike_sa;
ike_cfg_t *ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
this->connection->get_my_host(this->connection),
this->connection->get_other_host(this->connection),
this->policy->get_my_id(this->policy),
this->policy->get_other_id(this->policy));
ike_cfg->get_my_host(ike_cfg),
ike_cfg->get_other_host(ike_cfg),
this->peer_cfg->get_my_id(this->peer_cfg),
this->peer_cfg->get_other_id(this->peer_cfg));
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
{
ike_sa->set_peer_cfg(ike_sa, this->peer_cfg);
}
if (this->route)
{
if (ike_sa->route(ike_sa, this->connection, this->policy) != SUCCESS)
if (ike_sa->route(ike_sa, this->child_cfg) != SUCCESS)
{
DBG1(DBG_JOB, "routing failed");
}
}
else
{
if (ike_sa->unroute(ike_sa, this->policy) == DESTROY_ME)
if (ike_sa->unroute(ike_sa, this->child_cfg) == DESTROY_ME)
{
DBG1(DBG_JOB, "removing IKE_SA, as last routed CHILD_SA unrouted");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
@ -99,15 +106,16 @@ static status_t execute(private_route_job_t *this)
*/
static void destroy(private_route_job_t *this)
{
this->connection->destroy(this->connection);
this->policy->destroy(this->policy);
this->peer_cfg->destroy(this->peer_cfg);
this->child_cfg->destroy(this->child_cfg);
free(this);
}
/*
* Described in header
*/
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route)
route_job_t *route_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
bool route)
{
private_route_job_t *this = malloc_thing(private_route_job_t);
@ -117,8 +125,8 @@ route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool r
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
/* private variables */
this->connection = connection;
this->policy = policy;
this->peer_cfg = peer_cfg;
this->child_cfg = child_cfg;
this->route = route;
return &this->public;

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -25,9 +25,8 @@
typedef struct route_job_t route_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <config/policies/policy.h>
#include <config/connections/connection.h>
#include <processing/jobs/job.h>
#include <config/peer_cfg.h>
/**
* @brief Class representing an ROUTE Job.
@ -47,13 +46,14 @@ struct route_job_t {
/**
* @brief Creates a job of type ROUTE.
*
* @param connection connection used for routing
* @param policy policy to set up
* @param peer_cfg peer config to use for acquire
* @param child_cfg route to install
* @param route TRUE to route, FALSE to unroute
* @return route_job_t object
*
* @ingroup jobs
*/
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route);
route_job_t *route_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
bool route);
#endif /*ROUTE_JOB_H_*/

View File

@ -25,8 +25,7 @@
typedef struct send_dpd_job_t send_dpd_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <config/connections/connection.h>
#include <processing/jobs/job.h>
#include <sa/ike_sa_id.h>
/**

View File

@ -25,8 +25,7 @@
typedef struct send_keepalive_job_t send_keepalive_job_t;
#include <library.h>
#include <queues/jobs/job.h>
#include <config/connections/connection.h>
#include <processing/jobs/job.h>
#include <sa/ike_sa_id.h>
/**

View File

@ -27,7 +27,7 @@
#include "scheduler.h"
#include <daemon.h>
#include <queues/job_queue.h>
#include <processing/job_queue.h>
typedef struct private_scheduler_t private_scheduler_t;

View File

@ -29,7 +29,7 @@
#include "thread_pool.h"
#include <daemon.h>
#include <queues/job_queue.h>
#include <processing/job_queue.h>
typedef struct private_thread_pool_t private_thread_pool_t;

View File

@ -25,7 +25,7 @@
#include "eap_authenticator.h"
#include <daemon.h>
#include <config/policies/policy.h>
#include <config/peer_cfg.h>
#include <sa/authenticators/eap/eap_method.h>
typedef struct private_eap_authenticator_t private_eap_authenticator_t;

View File

@ -25,7 +25,6 @@
#include "psk_authenticator.h"
#include <config/policies/policy.h>
#include <daemon.h>
/**

View File

@ -25,7 +25,6 @@
#include "rsa_authenticator.h"
#include <config/policies/policy.h>
#include <daemon.h>

View File

@ -154,9 +154,9 @@ struct private_child_sa_t {
host_t *virtual_ip;
/**
* policy used to create this child
* config used to create this child
*/
policy_t *policy;
child_cfg_t *config;
};
/**
@ -164,7 +164,7 @@ struct private_child_sa_t {
*/
static char *get_name(private_child_sa_t *this)
{
return this->policy->get_name(this->policy);;
return this->config->get_name(this->config);
}
/**
@ -204,11 +204,11 @@ static child_sa_state_t get_state(private_child_sa_t *this)
}
/**
* Implements child_sa_t.get_policy
* Implements child_sa_t.get_config
*/
static policy_t* get_policy(private_child_sa_t *this)
static child_cfg_t* get_config(private_child_sa_t *this)
{
return this->policy;
return this->config;
}
/**
@ -220,7 +220,7 @@ static void updown(private_child_sa_t *this, bool up)
iterator_t *iterator;
char *script;
script = this->policy->get_updown(this->policy);
script = this->config->get_updown(this->config);
if (script == NULL)
{
@ -300,7 +300,7 @@ static void updown(private_child_sa_t *this, bool up)
policy->my_ts->is_host(policy->my_ts,
this->me.addr) ? "-host" : "-client",
this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-ipv6",
this->policy->get_name(this->policy),
this->config->get_name(this->config),
ifname ? ifname : "(unknown)",
this->reqid,
this->me.addr,
@ -316,7 +316,7 @@ static void updown(private_child_sa_t *this, bool up)
policy->other_ts->get_from_port(policy->other_ts),
policy->other_ts->get_protocol(policy->other_ts),
virtual_ip,
this->policy->get_hostaccess(this->policy) ?
this->config->get_hostaccess(this->config) ?
"PLUTO_HOST_ACCESS='1' " : "",
script);
free(ifname);
@ -528,8 +528,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
natt = NULL;
}
soft = this->policy->get_soft_lifetime(this->policy);
hard = this->policy->get_hard_lifetime(this->policy);
soft = this->config->get_lifetime(this->config, TRUE);
hard = this->config->get_lifetime(this->config, FALSE);
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
@ -665,10 +665,10 @@ static status_t add_policies(private_child_sa_t *this,
policy = malloc_thing(sa_policy_t);
policy->my_ts = my_ts->clone(my_ts);
policy->other_ts = other_ts->clone(other_ts);
this->policies->insert_last(this->policies, (void*)policy);
this->policies->insert_last(this->policies, policy);
/* add to separate list to query them via get_*_traffic_selectors() */
this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
this->my_ts->insert_last(this->my_ts, policy->my_ts);
this->other_ts->insert_last(this->other_ts, policy->other_ts);
}
}
my_iter->destroy(my_iter);
@ -685,18 +685,14 @@ static status_t add_policies(private_child_sa_t *this,
}
/**
* Implementation of child_sa_t.get_my_traffic_selectors.
* Implementation of child_sa_t.get_traffic_selectors.
*/
static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this)
{
return this->my_ts;
}
/**
* Implementation of child_sa_t.get_my_traffic_selectors.
*/
static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this)
static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
{
if (local)
{
return this->my_ts;
}
return this->other_ts;
}
@ -762,7 +758,7 @@ static int print(FILE *stream, const struct printf_info *info,
now = time(NULL);
written += fprintf(stream, "%12s{%d}: %N, %N",
this->policy->get_name(this->policy), this->reqid,
this->config->get_name(this->config), this->reqid,
child_sa_state_names, this->state,
mode_names, this->mode);
@ -775,7 +771,7 @@ static int print(FILE *stream, const struct printf_info *info,
if (info->alt)
{
written += fprintf(stream, "\n%12s{%d}: ",
this->policy->get_name(this->policy),
this->config->get_name(this->config),
this->reqid);
if (this->protocol == PROTO_ESP)
@ -814,7 +810,7 @@ static int print(FILE *stream, const struct printf_info *info,
while (iterator->iterate(iterator, (void**)&policy))
{
written += fprintf(stream, "\n%12s{%d}: %R===%R, last use: ",
this->policy->get_name(this->policy), this->reqid,
this->config->get_name(this->config), this->reqid,
policy->my_ts, policy->other_ts);
/* query time of last policy use */
@ -1066,7 +1062,7 @@ static void destroy(private_child_sa_t *this)
this->other.addr->destroy(this->other.addr);
this->me.id->destroy(this->me.id);
this->other.id->destroy(this->other.id);
this->policy->destroy(this->policy);
this->config->destroy(this->config);
DESTROY_IF(this->virtual_ip);
free(this);
}
@ -1076,7 +1072,7 @@ static void destroy(private_child_sa_t *this)
*/
child_sa_t * child_sa_create(host_t *me, host_t* other,
identification_t *my_id, identification_t *other_id,
policy_t *policy, u_int32_t rekey, bool use_natt)
child_cfg_t *config, u_int32_t rekey, bool use_natt)
{
static u_int32_t reqid = 0;
private_child_sa_t *this = malloc_thing(private_child_sa_t);
@ -1091,12 +1087,11 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update;
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies;
this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
this->public.get_policy = (policy_t*(*)(child_sa_t*))get_policy;
this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
this->public.destroy = (void(*)(child_sa_t*))destroy;
@ -1123,8 +1118,8 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->protocol = PROTO_NONE;
this->mode = MODE_TUNNEL;
this->virtual_ip = NULL;
this->policy = policy;
policy->get_ref(policy);
this->config = config;
config->get_ref(config);
return &this->public;
}

View File

@ -32,7 +32,7 @@ typedef struct child_sa_t child_sa_t;
#include <crypto/prf_plus.h>
#include <encoding/payloads/proposal_substructure.h>
#include <config/proposal.h>
#include <config/policies/policy.h>
#include <config/child_cfg.h>
/**
* Where we should start with reqid enumeration
@ -101,7 +101,7 @@ extern enum_name_t *child_sa_state_names;
struct child_sa_t {
/**
* @brief Get the name of the policy this CHILD_SA uses.
* @brief Get the name of the config this CHILD_SA uses.
*
* @param this calling object
* @return name
@ -214,17 +214,10 @@ struct child_sa_t {
* @brief Get the traffic selectors of added policies of local host.
*
* @param this calling object
* @param local TRUE for own traffic selectors, FALSE for remote
* @return list of traffic selectors
*/
linked_list_t* (*get_my_traffic_selectors) (child_sa_t *this);
/**
* @brief Get the traffic selectors of added policies of remote host.
*
* @param this calling object
* @return list of traffic selectors
*/
linked_list_t* (*get_other_traffic_selectors) (child_sa_t *this);
linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
/**
* @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
@ -251,12 +244,12 @@ struct child_sa_t {
void (*set_state) (child_sa_t *this, child_sa_state_t state);
/**
* @brief Get the policy used to set up this child sa.
* @brief Get the config used to set up this child sa.
*
* @param this calling object
* @return policy
* @return child_cfg
*/
policy_t* (*get_policy) (child_sa_t *this);
child_cfg_t* (*get_config) (child_sa_t *this);
/**
* @brief Set the virtual IP used received from IRAS.
@ -284,7 +277,7 @@ struct child_sa_t {
* @param other remote address
* @param my_id id of own peer
* @param other_id id of remote peer
* @param policy policy this CHILD_SA instantiates
* @param config config to use for this CHILD_SA
* @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
* @param use_natt TRUE if NAT traversal is used
* @return child_sa_t object
@ -293,6 +286,6 @@ struct child_sa_t {
*/
child_sa_t * child_sa_create(host_t *me, host_t *other,
identification_t *my_id, identification_t* other_id,
policy_t *policy, u_int32_t reqid, bool use_natt);
child_cfg_t *config, u_int32_t reqid, bool use_natt);
#endif /*CHILD_SA_H_*/

View File

@ -56,13 +56,13 @@
#include <sa/tasks/child_create.h>
#include <sa/tasks/child_delete.h>
#include <sa/tasks/child_rekey.h>
#include <queues/jobs/retransmit_job.h>
#include <queues/jobs/delete_ike_sa_job.h>
#include <queues/jobs/send_dpd_job.h>
#include <queues/jobs/send_keepalive_job.h>
#include <queues/jobs/rekey_ike_sa_job.h>
#include <queues/jobs/route_job.h>
#include <queues/jobs/initiate_job.h>
#include <processing/jobs/retransmit_job.h>
#include <processing/jobs/delete_ike_sa_job.h>
#include <processing/jobs/send_dpd_job.h>
#include <processing/jobs/send_keepalive_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
#include <processing/jobs/route_job.h>
#include <processing/jobs/initiate_job.h>
#ifndef RESOLV_CONF
@ -105,14 +105,14 @@ struct private_ike_sa_t {
ike_sa_state_t state;
/**
* connection used to establish this IKE_SA.
* IKE configuration used to set up this IKE_SA
*/
connection_t *connection;
ike_cfg_t *ike_cfg;
/**
* Peer and authentication information to establish IKE_SA.
*/
policy_t *policy;
peer_cfg_t *peer_cfg;
/**
* Juggles tasks to process messages
@ -273,47 +273,13 @@ static u_int32_t get_unique_id(private_ike_sa_t *this)
*/
static char *get_name(private_ike_sa_t *this)
{
if (this->connection)
if (this->peer_cfg)
{
return this->connection->get_name(this->connection);
return this->peer_cfg->get_name(this->peer_cfg);
}
return "(unnamed)";
}
/**
* Implementation of ike_sa_t.get_connection
*/
static connection_t* get_connection(private_ike_sa_t *this)
{
return this->connection;
}
/**
* Implementation of ike_sa_t.set_connection
*/
static void set_connection(private_ike_sa_t *this, connection_t *connection)
{
this->connection = connection;
connection->get_ref(connection);
}
/**
* Implementation of ike_sa_t.get_policy
*/
static policy_t *get_policy(private_ike_sa_t *this)
{
return this->policy;
}
/**
* Implementation of ike_sa_t.set_policy
*/
static void set_policy(private_ike_sa_t *this, policy_t *policy)
{
policy->get_ref(policy);
this->policy = policy;
}
/**
* Implementation of ike_sa_t.get_my_host.
*/
@ -348,6 +314,66 @@ static void set_other_host(private_ike_sa_t *this, host_t *other)
this->other_host = other;
}
/**
* Implementation of ike_sa_t.get_peer_cfg
*/
static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this)
{
return this->peer_cfg;
}
/**
* Implementation of ike_sa_t.set_peer_cfg
*/
static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
{
host_t *me, *other;
identification_t *my_id, *other_id;
peer_cfg->get_ref(peer_cfg);
this->peer_cfg = peer_cfg;
if (this->ike_cfg == NULL)
{
this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
this->ike_cfg->get_ref(this->ike_cfg);
}
/* apply values, so we are ready to initate/acquire */
if (this->my_host->is_anyaddr(this->my_host))
{
me = this->ike_cfg->get_my_host(this->ike_cfg);
set_my_host(this, me->clone(me));
}
if (this->other_host->is_anyaddr(this->other_host))
{
other = this->ike_cfg->get_other_host(this->ike_cfg);
set_other_host(this, other->clone(other));
}
my_id = this->peer_cfg->get_my_id(this->peer_cfg);
other_id = this->peer_cfg->get_other_id(this->peer_cfg);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
this->my_id = my_id->clone(my_id);
this->other_id = other_id->clone(other_id);
}
/**
* Implementation of ike_sa_t.get_ike_cfg
*/
static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this)
{
return this->ike_cfg;
}
/**
* Implementation of ike_sa_t.set_ike_cfg
*/
static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg)
{
ike_cfg->get_ref(ike_cfg);
this->ike_cfg = ike_cfg;
}
/**
* Implementation of ike_sa_t.send_dpd
*/
@ -356,7 +382,7 @@ static status_t send_dpd(private_ike_sa_t *this)
send_dpd_job_t *job;
time_t diff, delay;
delay = this->connection->get_dpd_delay(this->connection);
delay = this->peer_cfg->get_dpd_delay(this->peer_cfg);
if (delay == 0)
{
@ -464,9 +490,9 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
send_dpd(this);
/* schedule rekeying/reauthentication */
soft = this->connection->get_soft_lifetime(this->connection);
hard = this->connection->get_hard_lifetime(this->connection);
reauth = this->connection->get_reauth(this->connection);
soft = this->peer_cfg->get_lifetime(this->peer_cfg, TRUE);
hard = this->peer_cfg->get_lifetime(this->peer_cfg, FALSE);
reauth = this->peer_cfg->use_reauth(this->peer_cfg);
DBG1(DBG_IKE, "scheduling %s in %ds, maximum lifetime %ds",
reauth ? "reauthentication": "rekeying", soft, hard);
@ -521,7 +547,7 @@ static void reset(private_ike_sa_t *this)
}
/**
* Update connection host, as addresses may change (NAT)
* Update hosts, as addresses may change (NAT)
*/
static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
{
@ -696,16 +722,16 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
me = message->get_destination(message);
other = message->get_source(message);
/* if this IKE_SA is virgin, we check for a connection */
if (this->connection == NULL)
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_cfg == NULL)
{
job_t *job;
this->connection = charon->connections->get_connection_by_hosts(
charon->connections, me, other);
if (this->connection == NULL)
this->ike_cfg = charon->cfg_store->get_ike_cfg(charon->cfg_store,
me, other);
if (this->ike_cfg == NULL)
{
/* no connection found for these hosts, destroy */
DBG1(DBG_IKE, "no connection found for %H...%H, sending %N",
/* no config found for these hosts, destroy */
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
return DESTROY_ME;
@ -717,7 +743,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
charon->configuration));
}
/* check if message is trustworthy, and update connection information */
/* check if message is trustworthy, and update host information */
if (this->state == IKE_CREATED ||
message->get_exchange_type(message) != IKE_SA_INIT)
{
@ -728,47 +754,15 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
}
/**
* apply the connection/policy information to this IKE_SA
*/
static void apply_config(private_ike_sa_t *this,
connection_t *connection, policy_t *policy)
{
host_t *me, *other;
identification_t *my_id, *other_id;
if (this->connection == NULL && this->policy == NULL)
{
this->connection = connection;
connection->get_ref(connection);
this->policy = policy;
policy->get_ref(policy);
me = connection->get_my_host(connection);
other = connection->get_other_host(connection);
my_id = policy->get_my_id(policy);
other_id = policy->get_other_id(policy);
set_my_host(this, me->clone(me));
set_other_host(this, other->clone(other));
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
this->my_id = my_id->clone(my_id);
this->other_id = other_id->clone(other_id);
}
}
/**
* Implementation of ike_sa_t.initiate.
*/
static status_t initiate(private_ike_sa_t *this,
connection_t *connection, policy_t *policy)
static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
task_t *task;
if (this->state == IKE_CREATED)
{
/* if we aren't established/establishing, do so */
apply_config(this, connection, policy);
if (this->other_host->is_anyaddr(this->other_host))
{
@ -785,11 +779,11 @@ static status_t initiate(private_ike_sa_t *this,
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_auth_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_config_create(&this->public, policy);
task = (task_t*)ike_config_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
}
task = (task_t*)child_create_create(&this->public, policy);
task = (task_t*)child_create_create(&this->public, child_cfg);
this->task_manager->queue_task(this->task_manager, task);
return this->task_manager->initiate(this->task_manager);
@ -800,7 +794,7 @@ static status_t initiate(private_ike_sa_t *this,
*/
static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
{
policy_t *policy;
child_cfg_t *child_cfg;
iterator_t *iterator;
child_sa_t *current, *child_sa = NULL;
task_t *task;
@ -833,7 +827,6 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
return FAILED;
}
policy = child_sa->get_policy(child_sa);
if (this->state == IKE_CREATED)
{
@ -845,52 +838,24 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_auth_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_config_create(&this->public, policy);
task = (task_t*)ike_config_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
}
child_create = child_create_create(&this->public, policy);
child_cfg = child_sa->get_config(child_sa);
child_create = child_create_create(&this->public, child_cfg);
child_create->use_reqid(child_create, reqid);
this->task_manager->queue_task(this->task_manager, (task_t*)child_create);
return this->task_manager->initiate(this->task_manager);
}
/**
* compare two lists of traffic selectors for equality
*/
static bool ts_list_equals(linked_list_t *l1, linked_list_t *l2)
{
bool equals = TRUE;
iterator_t *i1, *i2;
traffic_selector_t *t1, *t2;
if (l1->get_count(l1) != l2->get_count(l2))
{
return FALSE;
}
i1 = l1->create_iterator(l1, TRUE);
i2 = l2->create_iterator(l2, TRUE);
while (i1->iterate(i1, (void**)&t1) && i2->iterate(i2, (void**)&t2))
{
if (!t1->equals(t1, t2))
{
equals = FALSE;
break;
}
}
i1->destroy(i1);
i2->destroy(i2);
return equals;
}
/**
* Implementation of ike_sa_t.route.
*/
static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t *policy)
static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
child_sa_t *child_sa = NULL;
child_sa_t *child_sa;
iterator_t *iterator;
linked_list_t *my_ts, *other_ts;
status_t status;
@ -901,27 +866,12 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
{
linked_list_t *my_ts_conf, *other_ts_conf;
my_ts = child_sa->get_my_traffic_selectors(child_sa);
other_ts = child_sa->get_other_traffic_selectors(child_sa);
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
if (ts_list_equals(my_ts, my_ts_conf) &&
ts_list_equals(other_ts, other_ts_conf))
{
iterator->destroy(iterator);
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a policy already routed");
return FAILED;
}
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
iterator->destroy(iterator);
SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config already routed");
return FAILED;
}
}
iterator->destroy(iterator);
@ -934,9 +884,6 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
"unable to route CHILD_SA, as its IKE_SA gets deleted");
return FAILED;
case IKE_CREATED:
/* apply connection information, we need it to acquire */
apply_config(this, connection, policy);
break;
case IKE_CONNECTING:
case IKE_ESTABLISHED:
default:
@ -944,29 +891,37 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
}
/* install kernel policies */
child_sa = child_sa_create(this->my_host, this->other_host,
this->my_id, this->other_id, policy, FALSE, 0);
child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
this->other_id, child_cfg, FALSE, 0);
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
this->my_host);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL,
this->other_host);
status = child_sa->add_policies(child_sa, my_ts, other_ts,
policy->get_mode(policy));
child_cfg->get_mode(child_cfg));
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
this->child_sas->insert_last(this->child_sas, child_sa);
SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed");
if (status == SUCCESS)
{
this->child_sas->insert_last(this->child_sas, child_sa);
SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed");
}
else
{
SIG(CHILD_ROUTE_FAILED, "routing CHILD_SA failed");
}
return status;
}
/**
* Implementation of ike_sa_t.unroute.
*/
static status_t unroute(private_ike_sa_t *this, policy_t *policy)
static status_t unroute(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
iterator_t *iterator;
child_sa_t *child_sa = NULL;
child_sa_t *child_sa;
bool found = FALSE;
linked_list_t *my_ts, *other_ts, *my_ts_conf, *other_ts_conf;
SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA");
@ -974,27 +929,14 @@ static status_t unroute(private_ike_sa_t *this, policy_t *policy)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
{
my_ts = child_sa->get_my_traffic_selectors(child_sa);
other_ts = child_sa->get_other_traffic_selectors(child_sa);
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
if (ts_list_equals(my_ts, my_ts_conf) &&
ts_list_equals(other_ts, other_ts_conf))
{
iterator->remove(iterator);
SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
child_sa->destroy(child_sa);
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
found = TRUE;
break;
}
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
iterator->remove(iterator);
SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
child_sa->destroy(child_sa);
found = TRUE;
break;
}
}
iterator->destroy(iterator);
@ -1021,7 +963,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
this->time.outbound = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
policy_t *policy;
child_cfg_t *child_cfg;
child_sa_t* child_sa;
linked_list_t *to_route, *to_restart;
iterator_t *iterator;
@ -1032,7 +974,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
case IKE_CONNECTING:
{
/* retry IKE_SA_INIT if we have multiple keyingtries */
u_int32_t tries = this->connection->get_keyingtries(this->connection);
u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
{
@ -1060,23 +1002,23 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
policy = child_sa->get_policy(child_sa);
child_cfg = child_sa->get_config(child_sa);
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
{
/* reroute routed CHILD_SAs */
to_route->insert_last(to_route, policy);
to_route->insert_last(to_route, child_cfg);
}
else
{
/* use DPD action for established CHILD_SAs */
switch (policy->get_dpd_action(policy))
switch (this->peer_cfg->get_dpd_action(this->peer_cfg))
{
case DPD_ROUTE:
to_route->insert_last(to_route, policy);
to_route->insert_last(to_route, child_cfg);
break;
case DPD_RESTART:
to_restart->insert_last(to_restart, policy);
to_restart->insert_last(to_restart, child_cfg);
break;
default:
break;
@ -1094,15 +1036,15 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
charon->ike_sa_manager, TRUE);
apply_config(new, this->connection, this->policy);
/* use actual used host, not the wildcarded one in connection */
set_peer_cfg(new, this->peer_cfg);
/* use actual used host, not the wildcarded one in config */
new->other_host->destroy(new->other_host);
new->other_host = this->other_host->clone(this->other_host);
/* install routes */
while (to_route->remove_last(to_route, (void**)&policy) == SUCCESS)
while (to_route->remove_last(to_route, (void**)&child_cfg) == SUCCESS)
{
route(new, new->connection, policy);
route(new, child_cfg);
}
/* restart children */
@ -1114,14 +1056,14 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_cert_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_config_create(&new->public, new->policy);
task = (task_t*)ike_config_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_auth_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
while (to_restart->remove_last(to_restart, (void**)&policy) == SUCCESS)
while (to_restart->remove_last(to_restart, (void**)&child_cfg) == SUCCESS)
{
task = (task_t*)child_create_create(&new->public, policy);
task = (task_t*)child_create_create(&new->public, child_cfg);
new->task_manager->queue_task(new->task_manager, task);
}
new->task_manager->initiate(new->task_manager);
@ -1542,14 +1484,14 @@ static void reestablish(private_ike_sa_t *this)
private_ike_sa_t *other;
iterator_t *iterator;
child_sa_t *child_sa;
policy_t *policy;
child_cfg_t *child_cfg;
task_t *task;
job_t *job;
other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
charon->ike_sa_manager, TRUE);
apply_config(other, this->connection, this->policy);
set_peer_cfg(other, this->peer_cfg);
other->other_host->destroy(other->other_host);
other->other_host = this->other_host->clone(this->other_host);
@ -1561,7 +1503,7 @@ static void reestablish(private_ike_sa_t *this)
other->task_manager->queue_task(other->task_manager, task);
task = (task_t*)ike_cert_create(&other->public, TRUE);
other->task_manager->queue_task(other->task_manager, task);
task = (task_t*)ike_config_create(&other->public, other->policy);
task = (task_t*)ike_config_create(&other->public, TRUE);
other->task_manager->queue_task(other->task_manager, task);
task = (task_t*)ike_auth_create(&other->public, TRUE);
other->task_manager->queue_task(other->task_manager, task);
@ -1583,8 +1525,8 @@ static void reestablish(private_ike_sa_t *this)
}
default:
{
policy = child_sa->get_policy(child_sa);
task = (task_t*)child_create_create(&other->public, policy);
child_cfg = child_sa->get_config(child_sa);
task = (task_t*)child_create_create(&other->public, child_cfg);
other->task_manager->queue_task(other->task_manager, task);
break;
}
@ -1865,9 +1807,9 @@ static int print(FILE *stream, const struct printf_info *info,
bool reauth = FALSE;
private_ike_sa_t *this = *((private_ike_sa_t**)(args[0]));
if (this->connection)
if (this->peer_cfg)
{
reauth = this->connection->get_reauth(this->connection);
reauth = this->peer_cfg->use_reauth(this->peer_cfg);
}
if (this == NULL)
@ -1879,15 +1821,19 @@ static int print(FILE *stream, const struct printf_info *info,
this->unique_id, ike_sa_state_names, this->state,
this->my_host, this->my_id, this->other_host,
this->other_id);
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds",
get_name(this), this->unique_id, this->ike_sa_id,
this->connection && reauth? "reauthentication":"rekeying",
this->time.rekey - time(NULL));
if (info->alt)
if (this->time.rekey)
{
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds",
get_name(this), this->unique_id, this->ike_sa_id,
reauth ? "reauthentication" : "rekeying",
this->time.rekey - time(NULL));
}
else
{
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, rekeying disabled",
get_name(this), this->unique_id, this->ike_sa_id);
}
return written;
}
@ -1931,8 +1877,8 @@ static void destroy(private_ike_sa_t *this)
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
DESTROY_IF(this->connection);
DESTROY_IF(this->policy);
DESTROY_IF(this->ike_cfg);
DESTROY_IF(this->peer_cfg);
this->ike_sa_id->destroy(this->ike_sa_id);
this->task_manager->destroy(this->task_manager);
@ -1952,14 +1898,14 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state;
this->public.get_name = (char*(*)(ike_sa_t*))get_name;
this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) initiate;
this->public.route = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) route;
this->public.unroute = (status_t(*)(ike_sa_t*,policy_t*)) unroute;
this->public.initiate = (status_t(*)(ike_sa_t*,child_cfg_t*)) initiate;
this->public.route = (status_t(*)(ike_sa_t*,child_cfg_t*)) route;
this->public.unroute = (status_t(*)(ike_sa_t*,child_cfg_t*)) unroute;
this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
this->public.get_connection = (connection_t*(*)(ike_sa_t*))get_connection;
this->public.set_connection = (void(*)(ike_sa_t*,connection_t*))set_connection;
this->public.get_policy = (policy_t*(*)(ike_sa_t*))get_policy;
this->public.set_policy = (void(*)(ike_sa_t*,policy_t*))set_policy;
this->public.get_ike_cfg = (ike_cfg_t*(*)(ike_sa_t*))get_ike_cfg;
this->public.set_ike_cfg = (void(*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
this->public.get_peer_cfg = (peer_cfg_t*(*)(ike_sa_t*))get_peer_cfg;
this->public.set_peer_cfg = (void(*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
this->public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
this->public.set_my_host = (void(*)(ike_sa_t*,host_t*)) set_my_host;
@ -2019,8 +1965,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->time.established = 0;
this->time.rekey = 0;
this->time.delete = 0;
this->connection = NULL;
this->policy = NULL;
this->ike_cfg = NULL;
this->peer_cfg = NULL;
this->task_manager = task_manager_create(&this->public);
this->unique_id = ++unique_id;
this->my_virtual_ip = NULL;

View File

@ -39,9 +39,8 @@ typedef struct ike_sa_t ike_sa_t;
#include <crypto/prfs/prf.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <config/connections/connection.h>
#include <config/policies/policy.h>
#include <config/proposal.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
/**
* @brief State of an IKE_SA.
@ -237,51 +236,49 @@ struct ike_sa_t {
void (*set_other_id) (ike_sa_t *this, identification_t *other);
/**
* @brief Get the connection used by this IKE_SA.
* @brief Get the config used to setup this IKE_SA.
*
* @param this calling object
* @return connection
* @return ike_config
*/
connection_t* (*get_connection) (ike_sa_t *this);
ike_cfg_t* (*get_ike_cfg) (ike_sa_t *this);
/**
* @brief Set the connection to use with this IKE_SA.
* @brief Set the config to setup this IKE_SA.
*
* @param this calling object
* @param connection connection to use
* @param config ike_config to use
*/
void (*set_connection) (ike_sa_t *this, connection_t* connection);
void (*set_ike_cfg) (ike_sa_t *this, ike_cfg_t* config);
/**
* @brief Get the policy used by this IKE_SA.
* @brief Get the peer config used by this IKE_SA.
*
* @param this calling object
* @return policy
* @return peer_config
*/
policy_t* (*get_policy) (ike_sa_t *this);
peer_cfg_t* (*get_peer_cfg) (ike_sa_t *this);
/**
* @brief Set the policy to use with this IKE_SA.
* @brief Set the peer config to use with this IKE_SA.
*
* @param this calling object
* @param policy policy to use
* @param config peer_config to use
*/
void (*set_policy) (ike_sa_t *this, policy_t *policy);
void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
/**
* @brief Initiate a new connection.
*
* The policy/connection is owned by the IKE_SA after the call, so
* do not modify or destroy it.
* The configs are owned by the IKE_SA after the call.
*
* @param this calling object
* @param connection connection to initiate
* @param policy policy to set up
* @param child_cfg child config to create CHILD from
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
* - DESTROY_ME if initialization failed
*/
status_t (*initiate) (ike_sa_t *this, connection_t *connection, policy_t *policy);
status_t (*initiate) (ike_sa_t *this, child_cfg_t *child_cfg);
/**
* @brief Route a policy in the kernel.
@ -290,28 +287,26 @@ struct ike_sa_t {
* the kernel requests connection setup from the IKE_SA via acquire().
*
* @param this calling object
* @param connection connection definition used for routing
* @param policy policy to route
* @param child_cfg child config to route
* @return
* - SUCCESS if routed successfully
* - FAILED if routing failed
*/
status_t (*route) (ike_sa_t *this, connection_t *connection, policy_t *policy);
status_t (*route) (ike_sa_t *this, child_cfg_t *child_cfg);
/**
* @brief Unroute a policy in the kernel previously routed.
*
* @param this calling object
* @param policy policy to route
* @param child_cfg child config to unroute
* @return
* - SUCCESS if route removed
* - DESTROY_ME if last route was removed from
* an IKE_SA which was not established
* - DESTROY_ME if last CHILD_SA was unrouted
*/
status_t (*unroute) (ike_sa_t *this, policy_t *policy);
status_t (*unroute) (ike_sa_t *this, child_cfg_t *child_cfg);
/**
* @brief Acquire connection setup for a policy.
* @brief Acquire connection setup for an installed kernel policy.
*
* If an installed policy raises an acquire, the kernel calls
* this function to establish the CHILD_SA (and maybe the IKE_SA).
@ -320,7 +315,7 @@ struct ike_sa_t {
* @param reqid reqid of the CHILD_SA the policy belongs to.
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
* - DESTROY_ME if initialization failed
*/
status_t (*acquire) (ike_sa_t *this, u_int32_t reqid);

View File

@ -363,6 +363,7 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
pthread_mutex_unlock(&this->mutex);
DBG2(DBG_MGR, "created IKE_SA: %J, %d IKE_SAs in manager",
id, this->ike_sa_list->get_count(this->ike_sa_list));
id->destroy(id);
return entry->ike_sa;
}

View File

@ -35,7 +35,7 @@
#include <sa/tasks/child_rekey.h>
#include <sa/tasks/child_delete.h>
#include <encoding/payloads/delete_payload.h>
#include <queues/jobs/retransmit_job.h>
#include <processing/jobs/retransmit_job.h>
typedef struct exchange_t exchange_t;
@ -577,7 +577,7 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_config_create(this->ike_sa, NULL);
task = (task_t*)ike_config_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)child_create_create(this->ike_sa, NULL);
this->passive_tasks->insert_last(this->passive_tasks, task);

View File

@ -64,9 +64,9 @@ struct private_child_create_t {
chunk_t other_nonce;
/**
* policy to create the CHILD_SA from
* config to create the CHILD_SA from
*/
policy_t *policy;
child_cfg_t *config;
/**
* list of proposal candidates
@ -198,7 +198,7 @@ static status_t select_and_install(private_child_create_t *this)
my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
this->proposal = this->policy->select_proposal(this->policy, this->proposals);
this->proposal = this->config->select_proposal(this->config, this->proposals);
if (this->proposal == NULL)
{
@ -206,28 +206,31 @@ static status_t select_and_install(private_child_create_t *this)
return FAILED;
}
if (this->initiator && my_vip)
{ /* if we have a virtual IP, shorten our TS to the minimum */
my_ts = this->policy->select_my_traffic_selectors(this->policy, my_ts,
my_vip);
if (my_vip == NULL)
{
my_vip = me;
}
else if (this->initiator)
{
/* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
this->child_sa->set_virtual_ip(this->child_sa, my_vip);
}
else
{ /* shorten in the host2host case only */
my_ts = this->policy->select_my_traffic_selectors(this->policy,
my_ts, me);
if (other_vip == NULL)
{
other_vip = other;
}
if (other_vip)
{ /* if other has a virtual IP, shorten it's traffic selectors to it */
other_ts = this->policy->select_other_traffic_selectors(this->policy,
other_ts, other_vip);
}
else
{ /* use his host for the host2host case */
other_ts = this->policy->select_other_traffic_selectors(this->policy,
other_ts, other);
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
my_vip);
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
other_vip);
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
{
SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
return FAILED;
}
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
if (this->initiator)
@ -241,13 +244,6 @@ static status_t select_and_install(private_child_create_t *this)
this->tsi = other_ts;
}
if (this->tsi->get_count(this->tsi) == 0 ||
this->tsr->get_count(this->tsr) == 0)
{
SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
return FAILED;
}
if (!this->initiator)
{
/* check if requested mode is acceptable, downgrade if required */
@ -421,6 +417,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
static status_t build_i(private_child_create_t *this, message_t *message)
{
host_t *me, *other, *vip;
peer_cfg_t *peer_cfg;
switch (message->get_exchange_type(message))
{
@ -448,25 +445,29 @@ static status_t build_i(private_child_create_t *this, message_t *message)
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
vip = this->policy->get_virtual_ip(this->policy, NULL);
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = peer_cfg->get_virtual_ip(peer_cfg, NULL);
if (vip)
{ /* propose a 0.0.0.0/0 subnet when we use virtual ip */
this->tsi = this->policy->get_my_traffic_selectors(this->policy, NULL);
this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
NULL, NULL);
vip->destroy(vip);
}
else
{ /* but shorten a 0.0.0.0/0 subnet to the actual address if host2host */
this->tsi = this->policy->get_my_traffic_selectors(this->policy, me);
this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
NULL, me);
}
this->tsr = this->policy->get_other_traffic_selectors(this->policy, other);
this->proposals = this->policy->get_proposals(this->policy);
this->mode = this->policy->get_mode(this->policy);
this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
NULL, other);
this->proposals = this->config->get_proposals(this->config);
this->mode = this->config->get_mode(this->config);
this->child_sa = child_sa_create(me, other,
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->policy, this->reqid,
this->config, this->reqid,
this->ike_sa->is_natt_enabled(this->ike_sa));
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
@ -492,6 +493,8 @@ static status_t build_i(private_child_create_t *this, message_t *message)
*/
static status_t process_r(private_child_create_t *this, message_t *message)
{
peer_cfg_t *peer_cfg;
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@ -517,18 +520,13 @@ static status_t process_r(private_child_create_t *this, message_t *message)
return NEED_MORE;
}
this->policy = charon->policies->get_policy(charon->policies,
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->tsr, this->tsi,
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa));
if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg)
{
this->ike_sa->set_policy(this->ike_sa, this->policy);
this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr, this->tsi,
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa));
}
return NEED_MORE;
}
@ -565,10 +563,11 @@ static status_t build_r(private_child_create_t *this, message_t *message)
return SUCCESS;
}
if (this->policy == NULL)
if (this->config == NULL)
{
SIG(CHILD_UP_FAILED, "no acceptable policy found");
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
SIG(CHILD_UP_FAILED, "traffic selectors %#R=== %#R inacceptable",
this->tsr, this->tsi);
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
return SUCCESS;
}
@ -576,12 +575,12 @@ static status_t build_r(private_child_create_t *this, message_t *message)
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->policy, this->reqid,
this->config, this->reqid,
this->ike_sa->is_natt_enabled(this->ike_sa));
if (select_and_install(this) != SUCCESS)
{
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
return SUCCESS;
}
@ -756,14 +755,14 @@ static void destroy(private_child_create_t *this)
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
}
DESTROY_IF(this->policy);
DESTROY_IF(this->config);
free(this);
}
/*
* Described in header.
*/
child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
{
private_child_create_t *this = malloc_thing(private_child_create_t);
@ -773,12 +772,12 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
if (policy)
if (config)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
this->initiator = TRUE;
policy->get_ref(policy);
config->get_ref(config);
}
else
{
@ -788,7 +787,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
}
this->ike_sa = ike_sa;
this->policy = policy;
this->config = config;
this->my_nonce = chunk_empty;
this->other_nonce = chunk_empty;
this->proposals = NULL;

View File

@ -28,7 +28,7 @@ typedef struct child_create_t child_create_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
#include <config/policies/policy.h>
#include <config/child_cfg.h>
/**
* @brief Task of type CHILD_CREATE, established a new CHILD_SA.
@ -80,9 +80,9 @@ struct child_create_t {
* @brief Create a new child_create task.
*
* @param ike_sa IKE_SA this task works for
* @param policy policy if task initiator, NULL if responder
* @param config child_cfg if task initiator, NULL if responder
* @return child_create task to handle by the task_manager
*/
child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy);
child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config);
#endif /* CHILD_CREATE_H_ */

View File

@ -27,7 +27,7 @@
#include <encoding/payloads/notify_payload.h>
#include <sa/tasks/child_create.h>
#include <sa/tasks/child_delete.h>
#include <queues/jobs/rekey_child_sa_job.h>
#include <processing/jobs/rekey_child_sa_job.h>
typedef struct private_child_rekey_t private_child_rekey_t;
@ -315,8 +315,8 @@ static void destroy(private_child_rekey_t *this)
*/
child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa)
{
child_cfg_t *config;
private_child_rekey_t *this = malloc_thing(private_child_rekey_t);
policy_t *policy;
this->public.collide = (void (*)(child_rekey_t*,task_t*))collide;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
@ -327,8 +327,8 @@ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa)
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
this->initiator = TRUE;
policy = child_sa->get_policy(child_sa);
this->child_create = child_create_create(ike_sa, policy);
config = child_sa->get_config(child_sa);
this->child_create = child_create_create(ike_sa, config);
}
else
{

View File

@ -100,18 +100,18 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
{
authenticator_t *auth;
auth_payload_t *auth_payload;
policy_t *policy;
peer_cfg_t *config;
auth_method_t method;
status_t status;
/* create own authenticator and add auth payload */
policy = this->ike_sa->get_policy(this->ike_sa);
if (!policy)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!config)
{
SIG(IKE_UP_FAILED, "unable to authenticate, no policy found");
SIG(IKE_UP_FAILED, "unable to authenticate, no peer config found");
return FAILED;
}
method = policy->get_auth_method(policy);
method = config->get_auth_method(config);
auth = authenticator_create(this->ike_sa, method);
if (auth == NULL)
@ -140,15 +140,15 @@ static status_t build_id(private_ike_auth_t *this, message_t *message)
{
identification_t *me, *other;
id_payload_t *id;
policy_t *policy;
peer_cfg_t *config;
me = this->ike_sa->get_my_id(this->ike_sa);
other = this->ike_sa->get_other_id(this->ike_sa);
policy = this->ike_sa->get_policy(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (me->contains_wildcards(me))
{
me = policy->get_my_id(policy);
me = config->get_my_id(config);
if (me->contains_wildcards(me))
{
SIG(IKE_UP_FAILED, "negotiation of own ID failed");
@ -459,7 +459,7 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
*/
static status_t build_i(private_ike_auth_t *this, message_t *message)
{
policy_t *policy;
peer_cfg_t *config;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
@ -471,8 +471,8 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
return FAILED;
}
policy = this->ike_sa->get_policy(this->ike_sa);
if (policy->get_auth_method(policy) == AUTH_EAP)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config->get_auth_method(config) == AUTH_EAP)
{
this->eap_auth = eap_authenticator_create(this->ike_sa);
}
@ -491,7 +491,9 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
* Implementation of task_t.process for initiator
*/
static status_t process_r(private_ike_auth_t *this, message_t *message)
{
{
peer_cfg_t *config;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
return collect_other_init_data(this, message);
@ -502,6 +504,15 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
}
config = charon->cfg_store->get_peer_cfg(charon->cfg_store,
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
if (config)
{
this->ike_sa->set_peer_cfg(this->ike_sa, config);
config->destroy(config);
}
switch (process_auth(this, message))
{
case SUCCESS:
@ -522,7 +533,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
*/
static status_t build_r(private_ike_auth_t *this, message_t *message)
{
policy_t *policy;
peer_cfg_t *config;
eap_type_t eap_type;
eap_payload_t *eap_payload;
status_t status;
@ -532,10 +543,12 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
return collect_my_init_data(this, message);
}
policy = this->ike_sa->get_policy(this->ike_sa);
if (policy == NULL)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config == NULL)
{
SIG(IKE_UP_FAILED, "no acceptable policy found");
SIG(IKE_UP_FAILED, "no acceptable peer config found for %D...%D",
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
return FAILED;
}
@ -567,7 +580,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
}
/* initiate EAP authenitcation */
eap_type = policy->get_eap_type(policy);
eap_type = config->get_eap_type(config);
status = this->eap_auth->initiate(this->eap_auth, eap_type, &eap_payload);
message->add_payload(message, (payload_t*)eap_payload);
if (status != NEED_MORE)

View File

@ -171,20 +171,20 @@ static void process_certs(private_ike_cert_t *this, message_t *message)
*/
static void build_certreqs(private_ike_cert_t *this, message_t *message)
{
connection_t *connection;
policy_t *policy;
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
identification_t *ca;
certreq_payload_t *certreq;
connection = this->ike_sa->get_connection(this->ike_sa);
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
if (connection->get_certreq_policy(connection) != CERT_NEVER_SEND)
if (ike_cfg->send_certreq(ike_cfg) != CERT_NEVER_SEND)
{
policy = this->ike_sa->get_policy(this->ike_sa);
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (policy)
if (peer_cfg)
{
ca = policy->get_other_ca(policy);
ca = peer_cfg->get_other_ca(peer_cfg);
if (ca && ca->get_type(ca) != ID_ANY)
{
@ -212,17 +212,15 @@ static void build_certreqs(private_ike_cert_t *this, message_t *message)
*/
static void build_certs(private_ike_cert_t *this, message_t *message)
{
policy_t *policy;
connection_t *connection;
peer_cfg_t *peer_cfg;
x509_t *cert;
cert_payload_t *payload;
policy = this->ike_sa->get_policy(this->ike_sa);
connection = this->ike_sa->get_connection(this->ike_sa);
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (policy && policy->get_auth_method(policy) == AUTH_RSA)
if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == AUTH_RSA)
{
switch (connection->get_cert_policy(connection))
switch (peer_cfg->get_cert_policy(peer_cfg))
{
case CERT_NEVER_SEND:
break;
@ -236,7 +234,7 @@ static void build_certs(private_ike_cert_t *this, message_t *message)
{
/* TODO: respect CA cert request */
cert = charon->credentials->get_certificate(charon->credentials,
policy->get_my_id(policy));
peer_cfg->get_my_id(peer_cfg));
if (cert)
{
payload = cert_payload_create_from_x509(cert);

View File

@ -48,11 +48,6 @@ struct private_ike_config_t {
*/
bool initiator;
/**
* associated policy with virtual IP configuration
*/
policy_t *policy;
/**
* virtual ip
*/
@ -266,7 +261,8 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, ID_INITIATOR))
{
this->virtual_ip = this->policy->get_virtual_ip(this->policy, NULL);
peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
this->virtual_ip = config->get_virtual_ip(config, NULL);
build_payloads(this, message, CFG_REQUEST);
}
@ -295,14 +291,14 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, EXTENSIBLE_AUTHENTICATION) == NULL)
{
this->policy = this->ike_sa->get_policy(this->ike_sa);
peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (this->policy && this->virtual_ip)
if (config && this->virtual_ip)
{
host_t *ip;
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
ip = this->policy->get_virtual_ip(this->policy, this->virtual_ip);
ip = config->get_virtual_ip(config, this->virtual_ip);
if (ip == NULL || ip->is_anyaddr(ip))
{
DBG1(DBG_IKE, "not assigning a virtual IP to peer");
@ -398,7 +394,7 @@ static void destroy(private_ike_config_t *this)
/*
* Described in header.
*/
ike_config_t *ike_config_create(ike_sa_t *ike_sa, policy_t *policy)
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_config_t *this = malloc_thing(private_ike_config_t);
@ -406,21 +402,18 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, policy_t *policy)
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
if (policy)
if (initiator)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
this->initiator = TRUE;
}
else
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
this->initiator = FALSE;
}
this->initiator = initiator;
this->ike_sa = ike_sa;
this->policy = policy;
this->virtual_ip = NULL;
this->dns = linked_list_create();

View File

@ -28,7 +28,6 @@ typedef struct ike_config_t ike_config_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
#include <config/policies/policy.h>
/**
* @brief Task of type IKE_CONFIG, sets up a virtual IP and other
@ -51,9 +50,9 @@ struct ike_config_t {
* @brief Create a new ike_config task.
*
* @param ike_sa IKE_SA this task works for
* @param policy policy for the initiator, NULL for the responder
* @param initiator TRUE for initiator
* @return ike_config task to handle by the task_manager
*/
ike_config_t *ike_config_create(ike_sa_t *ike_sa, policy_t *policy);
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator);
#endif /* IKE_CONFIG_H_ */

Some files were not shown because too many files have changed in this diff Show More