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
+78 -53
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}\"
+77
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_ */
+231
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);
}
@@ -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_ */
+164
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;
}
+135
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_*/
+397
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;
}
+239
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_ */
-404
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;
}
-292
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_ */
@@ -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_ */
@@ -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);
}
@@ -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
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
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_ */
+470
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;
}
+345
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_ */
@@ -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);
}
@@ -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_ */
-635
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;
}
-413
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_ */
-119
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_*/
+20
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
@@ -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);
@@ -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_ */
+10 -9
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;
+13 -14
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.
-5
View File
@@ -1,5 +0,0 @@
Known bugs in charon
======================
-56
View File
@@ -1,56 +0,0 @@
/** @mainpage
@section design strongSwans overall design
IKEv1 and IKEv2 is handled in different keying daemons. The ole IKEv1 stuff is
completely handled in pluto, as it was all the times. IKEv2 is handled in the
new keying daemon, which is called #charon.
Daemon control is done over unix sockets. Pluto uses whack, as it did for years.
Charon uses another socket interface, called stroke. Stroke uses another
format as whack and therefore is not compatible to whack. The starter utility,
wich does fast configuration parsing, speaks both the protocols, whack and
stroke. It also handles daemon startup and termination.
Pluto uses starter for some commands, for other it uses the whack utility. To be
as close to pluto as possible, charon has the same split up of commands to
starter and stroke. All commands are wrapped together in the ipsec script, which
allows transparent control of both daemons.
@verbatim
+-----------------------------------------+
| ipsec |
+-----+--------------+---------------+----+
| | |
| | |
| +-----+-----+ |
+-----+----+ | | +-----+----+
| | | starter | | |
| stroke | | | | whack |
| | +---+--+----+ | |
+------+---+ | | +--+-------+
| | | |
+---+------+ | | +------+--+
| | | | | |
| charon +----+ +----+ pluto |
| | | |
+-----+----+ +----+----+
| |
+-----+----+ |
| LSF | |
+-----+----+ |
| |
+-----+----+ +----+----+
| RAW Sock | | UDP/500 |
+----------+ +---------+
@endverbatim
Since IKEv2 uses the same port as IKEv1, both daemons must listen to UDP port
500. Under Linux, there is no clean way to set up two sockets at the same port.
To reslove this problem, charon uses a RAW socket, as they are used in network
sniffers. An installed Linux Socket Filter (LSF) filters out all none-IKEv2
traffic. Pluto receives any IKE message, independant of charons behavior.
Therefore plutos behavior is changed to discard any IKEv2 traffic silently.
To gain some reusability of the code, generic crypto and utility functions are
separeted in a shared library, libstrongswan.
*/
File diff suppressed because it is too large Load Diff
@@ -1,729 +0,0 @@
Network Working Group P. Eronen
Internet-Draft Nokia
Expires: December 28, 2006 H. Tschofenig
Siemens
June 26, 2006
Extension for EAP Authentication in IKEv2
draft-eronen-ipsec-ikev2-eap-auth-05.txt
Status of this Memo
By submitting this Internet-Draft, each author represents that any
applicable patent or other IPR claims of which he or she is aware
have been or will be disclosed, and any of which he or she becomes
aware will be disclosed, in accordance with Section 6 of BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that
other groups may also distribute working documents as Internet-
Drafts.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html.
This Internet-Draft will expire on December 28, 2006.
Copyright Notice
Copyright (C) The Internet Society (2006).
Abstract
IKEv2 specifies that EAP authentication must be used together with
public key signature based responder authentication. This is
necessary with old EAP methods that provide only unilateral
authentication using, e.g., one-time passwords or token cards.
This document specifies how EAP methods that provide mutual
authentication and key agreement can be used to provide extensible
Eronen & Tschofenig Expires December 28, 2006 [Page 1]
Internet-Draft Extension for EAP in IKEv2 June 2006
responder authentication for IKEv2 based on other methods than public
key signatures.
1. Introduction
The Extensible Authentication Protocol (EAP), defined in [4], is an
authentication framework which supports multiple authentication
mechanisms. Today, EAP has been implemented at end hosts and routers
that connect via switched circuits or dial-up lines using PPP [13],
IEEE 802 wired switches [9], and IEEE 802.11 wireless access points
[11].
One of the advantages of the EAP architecture is its flexibility.
EAP is used to select a specific authentication mechanism, typically
after the authenticator requests more information in order to
determine the specific authentication method to be used. Rather than
requiring the authenticator (e.g., wireless LAN access point) to be
updated to support each new authentication method, EAP permits the
use of a backend authentication server which may implement some or
all authentication methods.
IKEv2 [3] is a component of IPsec used for performing mutual
authentication and establishing and maintaining security associations
for IPsec ESP and AH. In addition to supporting authentication using
public key signatures and shared secrets, IKEv2 also supports EAP
authentication.
IKEv2 provides EAP authentication since it was recognized that public
key signatures and shared secrets are not flexible enough to meet the
requirements of many deployment scenarios. By using EAP, IKEv2 can
leverage existing authentication infrastructure and credential
databases, since EAP allows users to choose a method suitable for
existing credentials, and also makes separation of the IKEv2
responder (VPN gateway) from the EAP authentication endpoint (backend
AAA server) easier.
Some older EAP methods are designed for unilateral authentication
only (that is, EAP peer to EAP server). These methods are used in
conjunction with IKEv2 public key based authentication of the
responder to the initiator. It is expected that this approach is
especially useful for "road warrior" VPN gateways that use, for
instance, one-time passwords or token cards to authenticate the
clients.
However, most newer EAP methods, such as those typically used with
IEEE 802.11i wireless LANs, provide mutual authentication and key
agreement. Currently, IKEv2 specifies that also these EAP methods
Eronen & Tschofenig Expires December 28, 2006 [Page 2]
Internet-Draft Extension for EAP in IKEv2 June 2006
must be used together with public key signature based responder
authentication.
In some environments, requiring the deployment of PKI for just this
purpose can be counterproductive. Deploying new infrastructure can
be expensive, and it may weaken security by creating new
vulnerabilities. Mutually authenticating EAP methods alone can
provide a sufficient level of security in many circumstances, and
indeed, IEEE 802.11i uses EAP without any PKI for authenticating the
WLAN access points.
This document specifies how EAP methods that offer mutual
authentication and key agreement can be used to provide responder
authentication in IKEv2 completely based on EAP.
1.1. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [2].
2. Scenarios
In this section we describe two scenarios for extensible
authentication within IKEv2. These scenarios are intended to be
illustrative examples rather than specifying how things should be
done.
Figure 1 shows a configuration where the EAP and the IKEv2 endpoints
are co-located. Authenticating the IKEv2 responder using both EAP
and public key signatures is redundant. Offering EAP based
authentication has the advantage that multiple different
authentication and key exchange protocols are available with EAP with
different security properties (such as strong password based
protocols, protocols offering user identity confidentiality and many
more). As an example it is possible to use GSS-API support within
EAP [6] to support Kerberos based authentication which effectively
replaces the need for KINK [14].
+------+-----+ +------------+
O | IKEv2 | | IKEv2 |
/|\ | Initiator |<---////////////////////--->| Responder |
/ \ +------------+ IKEv2 +------------+
User | EAP Peer | Exchange | EAP Server |
+------------+ +------------+
Figure 1: EAP and IKEv2 endpoints are co-located
Eronen & Tschofenig Expires December 28, 2006 [Page 3]
Internet-Draft Extension for EAP in IKEv2 June 2006
Figure 2 shows a typical corporate network access scenario. The
initiator (client) interacts with the responder (VPN gateway) in the
corporate network. The EAP exchange within IKE runs between the
client and the home AAA server. As a result of a successful EAP
authentication protocol run, session keys are established and sent
from the AAA server to the VPN gateway, and then used to authenticate
the IKEv2 SA with AUTH payloads.
The protocol used between the VPN gateway and AAA server could be,
for instance, Diameter [4] or RADIUS [5]. See Section 5 for related
security considerations.
+-------------------------------+
| Corporate network |
| |
+-----------+ +--------+ |
| IKEv2 | AAA | Home | |
IKEv2 +////----->+ Responder +<---------->+ AAA | |
Exchange / | (VPN GW) | (RADIUS/ | Server | |
/ +-----------+ Diameter) +--------+ |
/ | carrying EAP |
| | |
| +-------------------------------+
v
+------+-----+
o | IKEv2 |
/|\ | Initiator |
/ \ | VPN client |
User +------------+
Figure 2: Corporate Network Access
3. Solution
IKEv2 specifies that when the EAP method establishes a shared secret
key, that key is used by both the initiator and responder to generate
an AUTH payload (thus authenticating the IKEv2 SA set up by messages
1 and 2).
When used together with public key responder authentication, the
responder is in effect authenticated using two different methods: the
public key signature AUTH payload in message 4, and the EAP-based
AUTH payload later.
If the initiator does not wish to use public key based responder
authentication, it includes an EAP_ONLY_AUTHENTICATION notification
payload (type TBD-BY-IANA) in message 3. The SPI size field is set
Eronen & Tschofenig Expires December 28, 2006 [Page 4]
Internet-Draft Extension for EAP in IKEv2 June 2006
to zero, and there is no additional data associated with this
notification.
If the responder supports this notification, it omits the public key
based AUTH payload and CERT payloads from message 4.
If the responder does not support the EAP_ONLY_AUTHENTICATION
notification, it ignores the notification payload, and includes the
AUTH payload in message 4. In this case the initiator can, based on
its local policy, choose to either ignore the AUTH payload, or verify
it and any associated certificates as usual.
Both the initiator and responder MUST verify that the EAP method
actually used provided mutual authentication and established a shared
secret key. The AUTH payloads sent after EAP Success MUST use the
EAP-generated key, and MUST NOT use SK_pi or SK_pr.
An IKEv2 message exchange with this modification is shown below:
Initiator Responder
----------- -----------
HDR, SAi1, KEi, Ni,
[N(NAT_DETECTION_SOURCE_IP),
N(NAT_DETECTION_DESTINATION_IP)] -->
<-- HDR, SAr1, KEr, Nr, [CERTREQ],
[N(NAT_DETECTION_SOURCE_IP),
N(NAT_DETECTION_DESTINATION_IP)]
HDR, SK { IDi, [IDr], SAi2, TSi, TSr,
N(EAP_ONLY_AUTHENTICATION),
[CP(CFG_REQUEST)] } -->
<-- HDR, SK { IDr, EAP(Request) }
HDR, SK { EAP(Response) } -->
<-- HDR, SK { EAP(Request) }
HDR, SK { EAP(Response) } -->
<-- HDR, SK { EAP(Success) }
HDR, SK { AUTH } -->
<-- HDR, SK { AUTH, SAr2, TSi, TSr,
[CP(CFG_REPLY] }
Eronen & Tschofenig Expires December 28, 2006 [Page 5]
Internet-Draft Extension for EAP in IKEv2 June 2006
The NAT detection and Configuration payloads are shown for
informative purposes only; they do not change how EAP authentication
works.
4. IANA considerations
This document defines a new IKEv2 Notification Payload type,
EAP_ONLY_AUTHENTICATION, described in Section 3. This payload must
be assigned a new type number from the "status types" range.
This document does not define any new namespaces to be managed by
IANA.
5. Security Considerations
Security considerations applicable to all EAP methods are discussed
in [1]. The EAP Key Management Framework [7] deals with issues that
arise when EAP is used as a part of a larger system.
5.1. Authentication of IKEv2 SA
It is important to note that the IKEv2 SA is not authenticated by
just running an EAP conversation: the crucial step is the AUTH
payload based on the EAP-generated key. Thus, EAP methods that do
not provide mutual authentication or establish a shared secret key
MUST NOT be used with the modifications presented in this document.
5.2. Authentication with separated IKEv2 responder/EAP server
As described in Section 2, the EAP conversation can terminate either
at the IKEv2 responder or at a backend AAA server.
If the EAP method terminates at the IKEv2 responder then no key
transport via the AAA infrastructure is required. Pre-shared secret
and public key based authentication offered by IKEv2 is then replaced
by a wider range of authentication and key exchange methods.
However, typically EAP will be used with a backend AAA server. See
[7] for a more complete discussion of the related security issues;
here we provide only a short summary.
When a backend server is used, there are actually two authentication
exchanges: the EAP method between the client and the AAA server, and
another authentication between the AAA server and IKEv2 gateway. The
AAA server authenticates the client using the selected EAP method,
and they establish a session key. The AAA server then sends this key
Eronen & Tschofenig Expires December 28, 2006 [Page 6]
Internet-Draft Extension for EAP in IKEv2 June 2006
to the IKEv2 gateway over a connection authenticated using, e.g.,
IPsec or TLS.
Some EAP methods do not have any concept of pass-through
authenticator (e.g., NAS or IKEv2 gateway) identity, and these two
authentications remain quite independent of each other. That is,
after the client has verified the AUTH payload sent by the IKEv2
gateway, it knows that it is talking to SOME gateway trusted by the
home AAA server, but not which one. The situation is somewhat
similar if a single cryptographic hardware accelerator, containing a
single private key, would be shared between multiple IKEv2 gateways
(perhaps in some kind of cluster configuration). In particular, if
one of the gateways is compromised, it can impersonate any of the
other gateways towards the user (until the compromise is discovered
and access rights revoked).
In some environments it is not desirable to trust the IKEv2 gateways
this much (also known as the "Lying NAS Problem"). EAP methods that
provide what is called "connection binding" or "channel binding"
transport some identity or identities of the gateway (or WLAN access
point/NAS) inside the EAP method. Then the AAA server can check that
it is indeed sending the key to the gateway expected by the client.
A potential solution is described in [16].
In some deployment configurations, AAA proxies may be present between
the IKEv2 gateway and the backend AAA server. These AAA proxies MUST
be trusted for secure operation, and therefore SHOULD be avoided when
possible; see [4] and [7] for more discussion.
5.3. Protection of EAP payloads
Although the EAP payloads are encrypted and integrity protected with
SK_e/SK_a, this does not provide any protection against active
attackers. Until the AUTH payload has been received and verified, a
man-in-the-middle can change the KEi/KEr payloads and eavesdrop or
modify the EAP payloads.
In IEEE 802.11i WLANs, the EAP payloads are neither encrypted nor
integrity protected (by the link layer), so EAP methods are typically
designed to take that into account.
In particular, EAP methods that are vulnerable to dictionary attacks
when used in WLANs are still vulnerable (to active attackers) when
run inside IKEv2.
5.4. User identity confidentiality
IKEv2 provides confidentiality for the initiator identity against
Eronen & Tschofenig Expires December 28, 2006 [Page 7]
Internet-Draft Extension for EAP in IKEv2 June 2006
passive eavesdroppers, but not against active attackers. The
initiator announces its identity first (in message #3), before the
responder has been authenticated. The usage of EAP in IKEv2 does not
change this situation, since the ID payload in message #3 is used
instead of the EAP Identity Request/Response exchange. This is
somewhat unfortunate since when EAP is used with public key
authentication of the responder, it would be possible to provide
active user identity confidentiality for the initiator.
IKEv2 protects the responder identity even against active attacks.
This property cannot be provided when using EAP. If public key
responder authentication is used in addition to EAP, the responder
reveals its identity before authenticating the initiator. If only
EAP is used (as proposed in this document), the situation depends on
the EAP method used (in some EAP methods, the server reveals its
identity first).
Hence, if active user identity confidentiality for the initiator is
required then EAP methods that offer this functionality have to be
used (see [1], Section 7.3).
6. Acknowledgments
This document borrows some text from [1], [3], and [4]. We would
also like to thank Hugo Krawczyk for interesting discussions about
this topic.
7. References
7.1. Normative References
[1] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H.
Levkowetz, "Extensible Authentication Protocol (EAP)", RFC 3748,
June 2004.
[2] Bradner, S., "Key words for use in RFCs to Indicate Requirement
Levels", RFC 2119, March 1997.
[3] Kaufman, C., "Internet Key Exchange (IKEv2) Protocol", RFC 4306,
December 2005.
[4] Eronen, P., Hiller, T., and G. Zorn, "Diameter Extensible
Authentication Protocol (EAP) Application", RFC 4072,
August 2005.
Eronen & Tschofenig Expires December 28, 2006 [Page 8]
Internet-Draft Extension for EAP in IKEv2 June 2006
7.2. Informative References
[5] Aboba, B. and P. Calhoun, "RADIUS (Remote Authentication Dial
In User Service) Support For Extensible Authentication Protocol
(EAP)", RFC 3579, September 2003.
[6] Aboba, B. and D. Simon, "EAP GSS Authentication Protocol",
draft-aboba-pppext-eapgss-12 (work in progress), April 2002.
[7] Aboba, B., "Extensible Authentication Protocol (EAP) Key
Management Framework", draft-ietf-eap-keying-13 (work in
progress), May 2006.
[8] Forsberg, D., "Protocol for Carrying Authentication for Network
Access (PANA)", draft-ietf-pana-pana-11 (work in progress),
March 2006.
[9] Institute of Electrical and Electronics Engineers, "Local and
Metropolitan Area Networks: Port-Based Network Access Control",
IEEE Standard 802.1X-2001, 2001.
[10] Institute of Electrical and Electronics Engineers, "Information
technology - Telecommunications and information exchange
between systems - Local and metropolitan area networks -
Specific Requirements Part 11: Wireless LAN Medium Access
Control (MAC) and Physical Layer (PHY) Specifications", IEEE
Standard 802.11-1999, 1999.
[11] Institute of Electrical and Electronics Engineers, "IEEE
Standard for Information technology - Telecommunications and
information exchange between systems - Local and metropolitan
area networks - Specific requirements - Part 11: Wireless
Medium Access Control (MAC) and Physical Layer (PHY)
specifications: Amendment 6: Medium Access Control (MAC)
Security Enhancements", IEEE Standard 802.11i-2004, July 2004.
[12] Rigney, C., Willens, S., Rubens, A., and W. Simpson, "Remote
Authentication Dial In User Service (RADIUS)", RFC 2865,
June 2000.
[13] Simpson, W., "The Point-to-Point Protocol (PPP)", STD 51,
RFC 1661, July 1994.
[14] Sakane, S., Kamada, K., Thomas, M., and J. Vilhuber,
"Kerberized Internet Negotiation of Keys (KINK)", RFC 4430,
March 2006.
[15] Tschofenig, H., "EAP IKEv2 Method",
Eronen & Tschofenig Expires December 28, 2006 [Page 9]
Internet-Draft Extension for EAP in IKEv2 June 2006
draft-tschofenig-eap-ikev2-11 (work in progress), June 2006.
[16] Arkko, J. and P. Eronen, "Authenticated Service Information for
the Extensible Authentication Protocol (EAP)",
draft-arkko-eap-service-identity-auth-04 (work in progress),
October 2005.
Appendix A. Alternative Approaches
In this section we list alternatives which have been considered
during the work on this document. Finally, the solution presented in
Section 3 seems to fit better into IKEv2.
A.1. Ignore AUTH payload at the initiator
With this approach, the initiator simply ignores the AUTH payload in
message #4 (but obviously must check the second AUTH payload later!).
The main advantage of this approach is that no protocol modifications
are required and no signature verification is required.
The initiator could signal the responder (using a NOTIFY payload)
that it did not verify the first AUTH payload.
A.2. Unauthenticated PKs in AUTH payload (message 4)
The first solution approach suggests the use of unauthenticated
public keys in the public key signature AUTH payload (for message 4).
That is, the initiator verifies the signature in the AUTH payload,
but does not verify that the public key indeed belongs to the
intended party (using certificates)--since it doesn't have a PKI that
would allow this. This could be used with X.509 certificates (the
initiator ignores all other fields of the certificate except the
public key), or "Raw RSA Key" CERT payloads.
This approach has the advantage that initiators that wish to perform
certificate-based responder authentication (in addition to EAP) may
do so, without requiring the responder to handle these cases
separately.
If using RSA, the overhead of signature verification is quite small
(compared to g^xy calculation).
A.3. Use EAP derived session keys for IKEv2
It has been proposed that when using an EAP methods that provides
mutual authentication and key agreement, the IKEv2 Diffie-Hellman
Eronen & Tschofenig Expires December 28, 2006 [Page 10]
Internet-Draft Extension for EAP in IKEv2 June 2006
exchange could also be omitted. This would mean that the sessions
keys for IPsec SAs established later would rely only on EAP-provided
keys.
It seems the only benefit of this approach is saving some computation
time (g^xy calculation). This approach requires designing a
completely new protocol (which would not resemble IKEv2 anymore) we
do not believe that it should be considered. Nevertheless, we
include it for completeness.
Eronen & Tschofenig Expires December 28, 2006 [Page 11]
Internet-Draft Extension for EAP in IKEv2 June 2006
Authors' Addresses
Pasi Eronen
Nokia Research Center
P.O. Box 407
FIN-00045 Nokia Group
Finland
Email: [email protected]
Hannes Tschofenig
Siemens
Otto-Hahn-Ring 6
Munich, Bayern 81739
Germany
Email: [email protected]
Eronen & Tschofenig Expires December 28, 2006 [Page 12]
Internet-Draft Extension for EAP in IKEv2 June 2006
Intellectual Property Statement
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at
[email protected].
Disclaimer of Validity
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Copyright Statement
Copyright (C) The Internet Society (2006). This document is subject
to the rights, licenses and restrictions contained in BCP 78, and
except as set forth therein, the authors retain all their rights.
Acknowledgment
Funding for the RFC Editor function is currently provided by the
Internet Society.
Eronen & Tschofenig Expires December 28, 2006 [Page 13]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,785 +0,0 @@
Network Working Group M. Myers
Internet-Draft TraceRoute Security LLC
Expires: January 12, 2007 H. Tschofenig
Siemens
July 11, 2006
OCSP Extensions to IKEv2
draft-myers-ikev2-ocsp-03.txt
Status of this Memo
By submitting this Internet-Draft, each author represents that any
applicable patent or other IPR claims of which he or she is aware
have been or will be disclosed, and any of which he or she becomes
aware will be disclosed, in accordance with Section 6 of BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that
other groups may also distribute working documents as Internet-
Drafts.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt.
The list of Internet-Draft Shadow Directories can be accessed at
http://www.ietf.org/shadow.html.
This Internet-Draft will expire on January 12, 2007.
Copyright Notice
Copyright (C) The Internet Society (2006).
Abstract
While IKEv2 supports public key based authentication (PKI), the
corresponding use of in-band CRLs is problematic due to unbounded CRL
size. The size of an OCSP response is however well-bounded and
small. This document defines the "OCSP Content" extension to IKEv2.
A CERTREQ payload with "OCSP Content" identifies one or more trusted
OCSP responders and is a request for inclusion of an OCSP response in
the IKEv2 handshake. A cooperative recipient of such a request
Myers & Tschofenig Expires January 12, 2007 [Page 1]
Internet-Draft OCSP Extensions to IKEv2 July 2006
responds with a CERT payload containing the appropriate OCSP
response. This content is recognizable via the same "OCSP Content"
identifier.
When certificates are used with IKEv2, the communicating peers need a
mechanism to determine the revocation status of the peer's
certificate. OCSP is one such mechanism. This document applies when
OCSP is desired and security policy prevents one of the IKEv2 peers
from accessing the relevant OCSP responder directly. Firewalls are
often deployed in a manner that prevents such access by IKEv2 peers
outside of an enterprise network.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 4
3. Extension Definition . . . . . . . . . . . . . . . . . . . . . 5
3.1. OCSP Request . . . . . . . . . . . . . . . . . . . . . . . 5
3.2. OCSP Response . . . . . . . . . . . . . . . . . . . . . . 5
4. Extension Requirements . . . . . . . . . . . . . . . . . . . . 6
4.1. OCSP Request . . . . . . . . . . . . . . . . . . . . . . . 6
4.2. OCSP Response . . . . . . . . . . . . . . . . . . . . . . 6
5. Examples and Discussion . . . . . . . . . . . . . . . . . . . 8
5.1. Peer to Peer . . . . . . . . . . . . . . . . . . . . . . . 8
5.2. Extended Authentication Protocol (EAP) . . . . . . . . . . 9
6. Security Considerations . . . . . . . . . . . . . . . . . . . 10
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 11
8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12
9. Normative References . . . . . . . . . . . . . . . . . . . . . 12
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 13
Intellectual Property and Copyright Statements . . . . . . . . . . 14
Myers & Tschofenig Expires January 12, 2007 [Page 2]
Internet-Draft OCSP Extensions to IKEv2 July 2006
1. Introduction
Version 2 of the Internet Key Exchange (IKE) protocol [IKEv2]
supports a range of authentication mechanisms, including the use of
public key based authentication. Confirmation of certificate
reliability is essential to achieve the security assurances public
key cryptography provides. One fundamental element of such
confirmation is reference to certificate revocation status (see
[RFC3280] for additional detail).
The historic means of determining certificate revocation status is
through the use of Certificate Revocation Lists (CRLs). IKEv2 allows
CRLs to be exchanged in-band via the CERT payload.
CRLs can however grow unbounded in size. Many real-world examples
exist to demonstrate the impracticality of including a multi-megabyte
file in an IKE exchange. This constraint is particularly acute in
bandwidth limited environments (e.g., mobile communications). The
net effect is exclusion of in-band CRLs in favor of out-of-band (OOB)
acquisition of these data, should they even be used at all.
Reliance on OOB methods can be further complicated if access to
revocation data requires use of IPsec (and therefore IKE) to
establish secure and authorized access to the CRLs of an IKE
participant. Such network access deadlock further contributes to a
reduced reliance on certificate revocation status in favor of blind
trust.
OCSP [RFC2560] offers a useful alternative. The size of an OCSP
response is bounded and small and therefore suitable for in-band
IKEv2 signaling of a certificate's revocation status.
This document defines an extension to IKEv2 that enables the use of
OCSP for in-band signaling of certificate revocation status. A new
content encoding is defined for use in the CERTREQ and CERT payloads.
A CERTREQ payload with "OCSP Content" identifies one or more trusted
OCSP responders and is a request for inclusion of an OCSP response in
the IKEv2 handshake. A cooperative recipient of such a request
responds with a CERT payload containing the appropriate OCSP
response. This content is recognizable via the same "OCSP Content"
identifier.
Myers & Tschofenig Expires January 12, 2007 [Page 3]
Internet-Draft OCSP Extensions to IKEv2 July 2006
2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in RFC 2119 [RFC2119].
Myers & Tschofenig Expires January 12, 2007 [Page 4]
Internet-Draft OCSP Extensions to IKEv2 July 2006
3. Extension Definition
With reference to Section 3.6 of [IKEv2], the values for the Cert
Encoding field of the CERT payload are extended as follows (see also
the IANA Considerations section of this document):
Certificate Encoding Value
-------------------- -----
OCSP Content 14
3.1. OCSP Request
A value of OCSP Content (14) in the Cert Encoding field of a CERTREQ
Payload indicates the presence of one or more OCSP Responder
certificate hashes in the Certificate Authority field of the CERTREQ
payload.
The presence of OCSP Content (14) in a CERTREQ message:
1. identifies one or more OCSP responders trusted by the sender;
2. notifies the recipient of sender's support for the OCSP extension
to IKEv2; and
3. notifies the recipient of sender's desire to receive OCSP
confirmation in a subsequent CERT payload.
3.2. OCSP Response
A value of OCSP Content (14) in the Cert Encoding field of a CERT
Payload indicates the presence of an OCSP Response in the Certificate
Data field of the CERT payload.
Correlation between an OCSP Response CERT payload and a corresponding
CERT payload carrying a certificate can be achieved by matching the
OCSP response CertID field to the certificate. See [RFC2560] for the
definition of OCSP response content.
Myers & Tschofenig Expires January 12, 2007 [Page 5]
Internet-Draft OCSP Extensions to IKEv2 July 2006
4. Extension Requirements
4.1. OCSP Request
Section 3.7 of [IKEv2] allows for the concatenation of trust anchor
hashes as the Certification Authority value of a single CERTREQ
message. There is no means however to indicate which among those
hashes relates to the certificate of a trusted OCSP responder.
Therefore an OCSP Request as defined in Section 3.1 above SHALL be
transmitted separate from any other CERTREQ payloads in an IKEv2
exchange.
Where it is useful to identify more than one trusted OCSP responder,
each such identification SHALL be concatenated in a manner identical
to the method documented in Section 3.7 of [IKEv2] regarding the
assembly of multiple trust anchor hashes.
The Certification Authority value in an OCSP Request CERTREQ SHALL be
computed and produced in a manner identical to that of trust anchor
hashes as documented in Section 3.7 of [IKEv2].
Upon receipt of an OCSP Response CERT payload corresponding to a
prior OCSP Request CERTREQ, the CERTREQ sender SHALL incorporate the
OCSP response into path validation logic defined by [RFC3280].
The sender of an OCSP Request CERTREQ MAY abort an IKEv2 exchange if
either:
1. the corresponding OCSP Response CERT payload indicates that the
subject certificate is revoked; OR
2. the corresponding OCSP Response CERT payload indicates an OCSP
error (e.g., malformedRequest, internalError, tryLater,
sigRequired, unauthorized, etc.).
The sender of an OCSP Request CERTREQ SHOULD accept an IKEv2 exchange
if a corresponding OCSP Response CERT payload is not received. This
might be an indication that this OCSP extension is not supported.
4.2. OCSP Response
Upon receipt of an OCSP Request CERTREQ payload, the recipient SHOULD
acquire the related OCSP-based assertion and produce and transmit an
OCSP Response CERT payload corresponding to the certificate needed to
verify its signature on IKEv2 payloads.
An OCSP Response CERT payload SHALL be transmitted separate from any
Myers & Tschofenig Expires January 12, 2007 [Page 6]
Internet-Draft OCSP Extensions to IKEv2 July 2006
other CERT payload in an IKEv2 exchange.
The means by which an OCSP response may be acquired for production of
an OCSP Response CERT payload is out of scope of this document.
The structure and encoding of the Certificate Data field of an OCSP
Response CERT payload SHALL be identical to that defined in
[RFC2560].
Myers & Tschofenig Expires January 12, 2007 [Page 7]
Internet-Draft OCSP Extensions to IKEv2 July 2006
5. Examples and Discussion
This section shows the standard IKEv2 message examples with both
peers, the initiator and the responder, using public key based
authentication, CERTREQ and CERT payloads. The first instance
corresponds to Section 1.2 of [IKEv2], the illustrations of which are
reproduced below for reference.
5.1. Peer to Peer
Application of the IKEv2 extensions defined in this document to the
peer-to-peer exchange defined in Section 1.2 of [IKEv2] is as
follows. Messages are numbered for ease of reference.
Initiator Responder
----------- -----------
(1) HDR, SAi1, KEi, Ni -->
(2) <-- HDR, SAr1, KEr, Nr,
CERTREQ(OCSP Request)
(3) HDR, SK {IDi, CERT(certificate),-->
CERT(OCSP Response),
CERTREQ(OCSP Request),
[IDr,] AUTH, SAi2, TSi, TSr}
(4) <-- HDR, SK {IDr,
CERT(certificate),
CERT(OCSP Response),
AUTH, SAr2, TSi, TSr}
In (2) Responder sends an OCSP Request CERTREQ payload identifying
one or more OCSP responders trusted by Responder. In response,
Initiator sends in (3) both a CERT payload carrying its certificate
and an OCSP Response CERT payload covering that certificate. In (3)
Initiator also requests an OCSP response via the OCSP Request CERTREQ
payload. In (4) Responder returns its certificate and a separate
OCSP Response CERT payload covering that certificate.
It is important to note that in this scenario, the Responder in (2)
does not yet possess the Initiator's certificate and therefore cannot
form an OCSP request. [RFC2560] allows for pre-produced responses.
It is thus easily inferred that OCSP responses can be produced in the
absence of a corresponding request (OCSP nonces notwithstanding). In
such instances OCSP Requests are simply index values into these data.
It is also important in extending IKEv2 towards OCSP in this scenario
that the Initiator has certain knowledge that the Responder is
Myers & Tschofenig Expires January 12, 2007 [Page 8]
Internet-Draft OCSP Extensions to IKEv2 July 2006
capable of and willing to participate in the extension. Yet the
Responder will only trust one or more OCSP responder signatures.
These factors motivate the definition of OCSP Responder Hash
extension.
5.2. Extended Authentication Protocol (EAP)
Another scenario of pressing interest is the use of EAP to
accommodate multiple end users seeking enterprise access to an IPsec
gateway. As with the preceding section, the following illustration
is extracted from [IKEv2]. In the event of a conflict between this
document and[IKEv2] regarding these illustrations, [IKEv2] SHALL
dominate.
Initiator Responder
----------- -----------
(1) HDR, SAi1, KEi, Ni -->
(2) <-- HDR, SAr1, KEr, Nr
(3) HDR, SK {IDi, -->
CERTREQ(OCSP Request),
[IDr,] AUTH, SAi2, TSi, TSr}
(4) <-- HDR, SK {IDr,
CERT(certificate),
CERT(OCSP Response),
AUTH, EAP}
(5) HDR, SK {EAP} -->
(6) <-- HDR, SK {EAP (success)}
(7) HDR, SK {AUTH} -->
(8) <-- HDR, SK {AUTH, SAr2, TSi,
TSr }
In the EAP scenario, messages (5) through (8) are not relevant to
this document. Note that while [IKEv2] allows for the optional
inclusion of a CERTREQ in (2), this document asserts no need of its
use. It is assumed that environments including this optional payload
and yet wishing to implement the OCSP extension to IKEv2 are
sufficiently robust as to accommodate this redundant payload.
Myers & Tschofenig Expires January 12, 2007 [Page 9]
Internet-Draft OCSP Extensions to IKEv2 July 2006
6. Security Considerations
For the reasons noted above, OCSP request as defined in Section 3.1
is used in place of OCSP request syntax to trigger production and
transmission of an OCSP response. OCSP as defined in [RFC2560] may
contain a nonce request extension to improve security against replay
attacks (see Section 4.4.1 of [RFC2560] for further details). The
OCSP Request defined by this document cannot accommodate nonces.
[RFC2560] deals with this aspect by allowing pre-produced responses.
[RFC2560] points to this replay vulnerability and indicates: "The use
of precomputed responses allows replay attacks in which an old (good)
response is replayed prior to its expiration date but after the
certificate has been revoked. Deployments of OCSP should carefully
evaluate the benefit of precomputed responses against the probability
of a replay attack and the costs associated with its successful
execution." Nodes SHOULD make the required freshness of an OCSP
Response configurable.
Myers & Tschofenig Expires January 12, 2007 [Page 10]
Internet-Draft OCSP Extensions to IKEv2 July 2006
7. IANA Considerations
This document defines one new field type for use in the IKEv2 Cert
Encoding field of the Certificate Payload format. Official
assignment of the "OCSP Content" extension to the Cert Encoding table
of Section 3.6 of [IKEv2] needs to be acquired from IANA.
Certificate Encoding Value
-------------------- -----
OCSP Content 14
Myers & Tschofenig Expires January 12, 2007 [Page 11]
Internet-Draft OCSP Extensions to IKEv2 July 2006
8. Acknowledgements
The authors would like to thank Russ Housley for his support.
Additionally, we would like to thank Pasi Eronen, Nicolas Williams,
Liqiang (Larry) Zhu, Lakshminath Dondeti and Paul Hoffman for their
review.
9. Normative References
[IKEv2] Kaufman, C., "Internet Key Exchange (IKEv2) Protocol",
RFC 4306, December 2005.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2560] Myers, M., Ankney, R., Malpani, A., Galperin, S., and C.
Adams, "X.509 Internet Public Key Infrastructure Online
Certificate Status Protocol - OCSP", RFC 2560, June 1999.
[RFC3280] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet
X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile", RFC 3280,
April 2002.
Myers & Tschofenig Expires January 12, 2007 [Page 12]
Internet-Draft OCSP Extensions to IKEv2 July 2006
Authors' Addresses
Michael Myers
TraceRoute Security LLC
Email: [email protected]
Hannes Tschofenig
Siemens
Otto-Hahn-Ring 6
Munich, Bavaria 81739
Germany
Email: [email protected]
URI: http://www.tschofenig.com
Myers & Tschofenig Expires January 12, 2007 [Page 13]
Internet-Draft OCSP Extensions to IKEv2 July 2006
Intellectual Property Statement
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at
[email protected].
Disclaimer of Validity
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Copyright Statement
Copyright (C) The Internet Society (2006). This document is subject
to the rights, licenses and restrictions contained in BCP 78, and
except as set forth therein, the authors retain all their rights.
Acknowledgment
Funding for the RFC Editor function is currently provided by the
Internet Society.
Myers & Tschofenig Expires January 12, 2007 [Page 14]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-339
View File
@@ -1,339 +0,0 @@
Network Working Group J. Schiller
Request for Comments: 4307 Massachusetts Institute of Technology
Category: Standards Track December 2005
Cryptographic Algorithms for Use in the
Internet Key Exchange Version 2 (IKEv2)
Status of This Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (2005).
Abstract
The IPsec series of protocols makes use of various cryptographic
algorithms in order to provide security services. The Internet Key
Exchange (IKE (RFC 2409) and IKEv2) provide a mechanism to negotiate
which algorithms should be used in any given association. However,
to ensure interoperability between disparate implementations, it is
necessary to specify a set of mandatory-to-implement algorithms to
ensure that there is at least one algorithm that all implementations
will have available. This document defines the current set of
algorithms that are mandatory to implement as part of IKEv2, as well
as algorithms that should be implemented because they may be promoted
to mandatory at some future time.
1. Introduction
The Internet Key Exchange protocol provides for the negotiation of
cryptographic algorithms between both endpoints of a cryptographic
association. Different implementations of IPsec and IKE may provide
different algorithms. However, the IETF desires that all
implementations should have some way to interoperate. In particular,
this requires that IKE define a set of mandatory-to-implement
algorithms because IKE itself uses such algorithms as part of its own
negotiations. This requires that some set of algorithms be specified
as "mandatory-to-implement" for IKE.
Schiller Standards Track [Page 1]
RFC 4307 IKEv2 Cryptographic Algorithms December 2005
The nature of cryptography is that new algorithms surface
continuously and existing algorithms are continuously attacked. An
algorithm believed to be strong today may be demonstrated to be weak
tomorrow. Given this, the choice of mandatory-to-implement algorithm
should be conservative so as to minimize the likelihood of it being
compromised quickly. Thought should also be given to performance
considerations as many uses of IPsec will be in environments where
performance is a concern.
Finally, we need to recognize that the mandatory-to-implement
algorithm(s) may need to change over time to adapt to the changing
world. For this reason, the selection of mandatory-to-implement
algorithms was removed from the main IKEv2 specification and placed
in this document. As the choice of algorithm changes, only this
document should need to be updated.
Ideally, the mandatory-to-implement algorithm of tomorrow should
already be available in most implementations of IPsec by the time it
is made mandatory. To facilitate this, we will attempt to identify
those algorithms (that are known today) in this document. There is
no guarantee that the algorithms we believe today may be mandatory in
the future will in fact become so. All algorithms known today are
subject to cryptographic attack and may be broken in the future.
2. Requirements Terminology
Keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", and
"MAY" that appear in this document are to be interpreted as described
in [RFC2119].
We define some additional terms here:
SHOULD+ This term means the same as SHOULD. However, it is likely
that an algorithm marked as SHOULD+ will be promoted at
some future time to be a MUST.
SHOULD- This term means the same as SHOULD. However, an algorithm
marked as SHOULD- may be deprecated to a MAY in a future
version of this document.
MUST- This term means the same as MUST. However, we expect at
some point that this algorithm will no longer be a MUST in
a future document. Although its status will be determined
at a later time, it is reasonable to expect that if a
future revision of a document alters the status of a MUST-
algorithm, it will remain at least a SHOULD or a SHOULD-.
Schiller Standards Track [Page 2]
RFC 4307 IKEv2 Cryptographic Algorithms December 2005
3. Algorithm Selection
3.1. IKEv2 Algorithm Selection
3.1.1. Encrypted Payload Algorithms
The IKEv2 Encrypted Payload requires both a confidentiality algorithm
and an integrity algorithm. For confidentiality, implementations
MUST- implement 3DES-CBC and SHOULD+ implement AES-128-CBC. For
integrity, HMAC-SHA1 MUST be implemented.
3.1.2. Diffie-Hellman Groups
There are several Modular Exponential (MODP) groups that are defined
for use in IKEv2. They are defined in both the [IKEv2] base document
and in the MODP extensions document. They are identified by group
number. Any groups not listed here are considered as "MAY be
implemented".
Group Number Bit Length Status Defined
2 1024 MODP Group MUST- [RFC2409]
14 2048 MODP Group SHOULD+ [RFC3526]
3.1.3. IKEv2 Transform Type 1 Algorithms
IKEv2 defines several possible algorithms for Transfer Type 1
(encryption). These are defined below with their implementation
status.
Name Number Defined In Status
RESERVED 0
ENCR_3DES 3 [RFC2451] MUST-
ENCR_NULL 11 [RFC2410] MAY
ENCR_AES_CBC 12 [AES-CBC] SHOULD+
ENCR_AES_CTR 13 [AES-CTR] SHOULD
3.1.4. IKEv2 Transform Type 2 Algorithms
Transfer Type 2 Algorithms are pseudo-random functions used to
generate random values when needed.
Name Number Defined In Status
RESERVED 0
PRF_HMAC_MD5 1 [RFC2104] MAY
PRF_HMAC_SHA1 2 [RFC2104] MUST
PRF_AES128_CBC 4 [AESPRF] SHOULD+
Schiller Standards Track [Page 3]
RFC 4307 IKEv2 Cryptographic Algorithms December 2005
3.1.5. IKEv2 Transform Type 3 Algorithms
Transfer Type 3 Algorithms are Integrity algorithms used to protect
data against tampering.
Name Number Defined In Status
NONE 0
AUTH_HMAC_MD5_96 1 [RFC2403] MAY
AUTH_HMAC_SHA1_96 2 [RFC2404] MUST
AUTH_AES_XCBC_96 5 [AES-MAC] SHOULD+
4. Security Considerations
The security of cryptographic-based systems depends on both the
strength of the cryptographic algorithms chosen and the strength of
the keys used with those algorithms. The security also depends on
the engineering of the protocol used by the system to ensure that
there are no non-cryptographic ways to bypass the security of the
overall system.
This document concerns itself with the selection of cryptographic
algorithms for the use of IKEv2, specifically with the selection of
"mandatory-to-implement" algorithms. The algorithms identified in
this document as "MUST implement" or "SHOULD implement" are not known
to be broken at the current time, and cryptographic research so far
leads us to believe that they will likely remain secure into the
foreseeable future. However, this isn't necessarily forever. We
would therefore expect that new revisions of this document will be
issued from time to time that reflect the current best practice in
this area.
5. Normative References
[RFC2409] Harkins, D. and D. Carrel, "The Internet Key Exchange
(IKE)", RFC 2409, November 1998.
[IKEv2] Kaufman, C., Ed., "Internet Key Exchange (IKEv2)
Protocol", RFC 4306, December 2005.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential
(MODP) Diffie-Hellman groups for Internet Key Exchange
(IKE)", RFC 3526, May 2003.
[RFC2451] Pereira, R. and R. Adams, "The ESP CBC-Mode Cipher
Algorithms", RFC 2451, November 1998.
Schiller Standards Track [Page 4]
RFC 4307 IKEv2 Cryptographic Algorithms December 2005
[RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm
and Its Use With IPsec", RFC 2410, November 1998.
[AES-CBC] Frankel, S., Glenn, R., and S. Kelly, "The AES-CBC
Cipher Algorithm and Its Use with IPsec", RFC 3602,
September 2003.
[AES-CTR] Housley, R., "Using Advanced Encryption Standard (AES)
Counter Mode With IPsec Encapsulating Security Payload
(ESP)", RFC 3686, January 2004.
[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC:
Keyed-Hashing for Message Authentication", RFC 2104,
February 1997.
[AESPRF] Hoffman, P., "The AES-XCBC-PRF-128 Algorithm for the
Internet Key Exchange Protocol (IKE)", RFC 3664, January
2004.
[RFC2403] Madson, C. and R. Glenn, "The Use of HMAC-MD5-96 within
ESP and AH", RFC 2403, November 1998.
[RFC2404] Madson, C. and R. Glenn, "The Use of HMAC-SHA-1-96
within ESP and AH", RFC 2404, November 1998.
[AES-MAC] Frankel, S. and H. Herbert, "The AES-XCBC-MAC-96
Algorithm and Its Use With IPsec", RFC 3566, September
2003.
Author's Address
Jeffrey I. Schiller
Massachusetts Institute of Technology
Room W92-190
77 Massachusetts Avenue
Cambridge, MA 02139-4307
USA
Phone: +1 (617) 253-0161
EMail: [email protected]
Schiller Standards Track [Page 5]
RFC 4307 IKEv2 Cryptographic Algorithms December 2005
Full Copyright Statement
Copyright (C) The Internet Society (2005).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
retain all their rights.
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at ietf-
[email protected].
Acknowledgement
Funding for the RFC Editor function is currently provided by the
Internet Society.
Schiller Standards Track [Page 6]
-283
View File
@@ -1,283 +0,0 @@
Network Working Group Y. Nir
Request for Comments: 4478 Check Point
Category: Experimental April 2006
Repeated Authentication in Internet Key Exchange (IKEv2) Protocol
Status of This Memo
This memo defines an Experimental Protocol for the Internet
community. It does not specify an Internet standard of any kind.
Discussion and suggestions for improvement are requested.
Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (2006).
Abstract
This document extends the Internet Key Exchange (IKEv2) Protocol
document [IKEv2]. With some IPsec peers, particularly in the remote
access scenario, it is desirable to repeat the mutual authentication
periodically. The purpose of this is to limit the time that security
associations (SAs) can be used by a third party who has gained
control of the IPsec peer. This document describes a mechanism to
perform this function.
1. Introduction
In several cases, such as the remote access scenario, policy dictates
that the mutual authentication needs to be repeated periodically.
Repeated authentication can usually be achieved by simply repeating
the Initial exchange by whichever side has a stricter policy.
However, in the remote access scenario it is usually up to a human
user to supply the authentication credentials, and often Extensible
Authentication Protocol (EAP) is used for authentication, which makes
it unreasonable or impossible for the remote access gateway to
initiate the IKEv2 exchange.
This document describes a new notification that the original
Responder can send to the original Initiator with the number of
seconds before the authentication needs to be repeated. The
Initiator SHOULD repeat the Initial exchange before that time is
expired. If the Initiator fails to do so, the Responder may close
all Security Associations.
Nir Experimental [Page 1]
RFC 4478 Repeated Authentication in IKEv2 April 2006
Repeated authentication is not the same as IKE SA rekeying, and need
not be tied to it. The key words "MUST", "MUST NOT", "SHOULD",
"SHOULD NOT", and "MAY" in this document are to be interpreted as
described in [RFC2119].
2. Authentication Lifetime
The Responder in an IKEv2 negotiation MAY be configured to limit the
time that an IKE SA and the associated IPsec SAs may be used before
the peer is required to repeat the authentication, through a new
Initial Exchange.
The Responder MUST send this information to the Initiator in an
AUTH_LIFETIME notification either in the last message of an IKE_AUTH
exchange, or in an INFORMATIONAL request, which may be sent at any
time.
When sent as part of the IKE SA setup, the AUTH_LIFETIME notification
is used as follows:
Initiator Responder
------------------------------- -----------------------------
HDR, SAi1, KEi, Ni -->
<-- HDR, SAr1, KEr, Nr, [CERTREQ]
HDR, SK {IDi, [CERT,] [CERTREQ,]
[IDr,] AUTH, SAi2, TSi, TSr} -->
<-- HDR, SK {IDr, [CERT,] AUTH,
SAr2, TSi, TSr,
N(AUTH_LIFETIME)}
The separate Informational exchange is formed as follows:
<-- HDR, SK {N(AUTH_LIFETIME)}
HDR SK {} -->
The AUTH_LIFETIME notification is described in Section 3.
The original Responder that sends the AUTH_LIFETIME notification
SHOULD send a DELETE notification soon after the end of the lifetime
period, unless the IKE SA is deleted before the lifetime period
elapses. If the IKE SA is rekeyed, then the time limit applies to
the new SA.
An Initiator that received an AUTH_LIFETIME notification SHOULD
repeat the Initial exchange within the time indicated in the
notification. The time is measured from the time that the original
Initiator receives the notification.
Nir Experimental [Page 2]
RFC 4478 Repeated Authentication in IKEv2 April 2006
A special case is where the notification is sent in an Informational
exchange, and the lifetime is zero. In that case, the original
responder SHOULD allow a reasonable time for the repeated
authentication to occur.
The AUTH_LIFETIME notification MUST be protected and MAY be sent by
the original Responder at any time. If the policy changes, the
original Responder MAY send it again in a new Informational.
The new Initial exchange is not altered. The initiator SHOULD delete
the old IKE SA within a reasonable time of the new Auth exchange.
3. AUTH_LIFETIME Notification
The AUTH_LIFETIME message is a notification payload formatted as
follows:
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! Notify Message Type !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Lifetime !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
o Payload Length is 12.
o Protocol ID (1 octet) MUST be 0.
o SPI size is 0 (SPI is in message header).
o Notify Message type is 16403 by IANA.
o Lifetime is the amount of time (in seconds) left before the
peer should repeat the Initial exchange. A zero value
signifies that the Initial exchange should begin immediately.
It is usually not reasonable to set this value to less than 300
(5 minutes) since that is too cumbersome for a user.
It is also usually not reasonable to set this value to more
than 86400 (1 day) as that would negate the security benefit of
repeating the authentication.
4. Interoperability with Non-Supporting IKEv2 Implementations
IKEv2 implementations that do not support the AUTH_LIFETIME
notification will ignore it and will not repeat the authentication.
In that case the original Responder will send a Delete notification
for the IKE SA in an Informational exchange. Such implementations
may be configured manually to repeat the authentication periodically.
Nir Experimental [Page 3]
RFC 4478 Repeated Authentication in IKEv2 April 2006
Non-supporting Responders are not a problem because they will simply
not send these notifications. In that case, there is no requirement
that the original Initiator re-authenticate.
5. Security Considerations
The AUTH_LIFETIME notification sent by the Responder does not
override any security policy on the Initiator. In particular, the
Initiator may have a different policy regarding re-authentication,
requiring more frequent re-authentication. Such an Initiator can
repeat the authentication earlier then is required by the
notification.
An Initiator MAY set reasonable limits on the amount of time in the
AUTH_LIFETIME notification. For example, an authentication lifetime
of less than 300 seconds from SA initiation may be considered
unreasonable.
6. IANA Considerations
The IANA has assigned a notification payload type for the
AUTH_LIFETIME notifications from the IKEv2 Notify Message Types
registry.
7. Normative References
[IKEv2] Kaufman, C., "Internet Key Exchange (IKEv2) Protocol", RFC
4306, December 2005.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
Author's Address
Yoav Nir
Check Point Software Technologies
EMail: [email protected]
Nir Experimental [Page 4]
RFC 4478 Repeated Authentication in IKEv2 April 2006
Full Copyright Statement
Copyright (C) The Internet Society (2006).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
retain all their rights.
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at
[email protected].
Acknowledgement
Funding for the RFC Editor function is provided by the IETF
Administrative Support Activity (IASA).
Nir Experimental [Page 5]
File diff suppressed because it is too large Load Diff
-619
View File
@@ -1,619 +0,0 @@
Network Working Group P. Eronen
Request for Comments: 4739 Nokia
Category: Experimental J. Korhonen
TeliaSonera
November 2006
Multiple Authentication Exchanges
in the Internet Key Exchange (IKEv2) Protocol
Status of This Memo
This memo defines an Experimental Protocol for the Internet
community. It does not specify an Internet standard of any kind.
Discussion and suggestions for improvement are requested.
Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The IETF Trust (2006).
Abstract
The Internet Key Exchange (IKEv2) protocol supports several
mechanisms for authenticating the parties, including signatures with
public-key certificates, shared secrets, and Extensible
Authentication Protocol (EAP) methods. Currently, each endpoint uses
only one of these mechanisms to authenticate itself. This document
specifies an extension to IKEv2 that allows the use of multiple
authentication exchanges, using either different mechanisms or the
same mechanism. This extension allows, for instance, performing
certificate-based authentication of the client host followed by an
EAP authentication of the user. When backend authentication servers
are used, they can belong to different administrative domains, such
as the network access provider and the service provider.
Eronen & Korhonen Experimental [Page 1]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
Table of Contents
1. Introduction ....................................................3
1.1. Usage Scenarios ............................................4
1.2. Terminology ................................................5
2. Solution ........................................................5
2.1. Solution Overview ..........................................5
2.2. Example 1: Multiple EAP Authentications ....................6
2.3. Example 2: Mixed EAP and Certificate Authentications .......7
2.4. Example 3: Multiple Initiator Certificates .................8
2.5. Example 4: Multiple Responder Certificates .................8
3. Payload Formats .................................................9
3.1. MULTIPLE_AUTH_SUPPORTED Notify Payload .....................9
3.2. ANOTHER_AUTH_FOLLOWS Notify Payload ........................9
4. IANA Considerations .............................................9
5. Security Considerations .........................................9
6. Acknowledgments ................................................10
7. References .....................................................10
7.1. Normative References ......................................10
7.2. Informative References ....................................10
Eronen & Korhonen Experimental [Page 2]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
1. Introduction
IKEv2 [IKEv2] supports several mechanisms for parties involved in the
IKE_SA (IKE security association). These include signatures with
public-key certificates, shared secrets, and Extensible
Authentication Protocol (EAP) methods.
Currently, each endpoint uses only one of these mechanisms to
authenticate itself. However, there are scenarios where making the
authorization decision in IKEv2 (whether to allow access or not)
requires using several of these methods.
For instance, it may be necessary to authenticate both the host
(machine) requesting access, and the user currently using the host.
These two authentications would use two separate sets of credentials
(such as certificates and associated private keys) and might even use
different authentication mechanisms.
To take another example, when an operator is hosting a Virtual
Private Network (VPN) gateway service for a third party, it may be
necessary to authenticate the client to both the operator (for
billing purposes) and the third party's Authentication,
Authorization, and Accounting (AAA) server (for authorizing access to
the third party's internal network).
This document specifies an extension to IKEv2 that allows the use of
multiple authentication exchanges, using either different mechanisms
or the same mechanism. This extension allows, for instance,
performing certificate-based authentication of the client host
followed by an EAP authentication of the user.
Each authentication exchange requiring communication with backend AAA
servers may be directed to different backend AAA servers, located
even in different administrative domains. However, details of the
communication between the IKEv2 gateway and the backend
authentication servers are beyond the scope of this document. In
particular, this document does not specify any changes to existing
AAA protocols, and it does not require the use of any particular AAA
protocol.
In case of several EAP authentications, it is important to notice
that they are not a "sequence" (as described in Section 2.1 of
[EAP]), but separate independent EAP conversations, which are usually
also terminated in different EAP servers. Multiple authentication
methods within a single EAP conversation are still prohibited as
described in Section 2.1 of [EAP]. Using multiple independent EAP
conversations is similar to the separate Network Access Provider
(NAP) and Internet Service Provider (ISP) authentication exchanges
Eronen & Korhonen Experimental [Page 3]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
planned for [PANA]. The discovery of the appropriate EAP server for
each EAP authentication conversation is based on AAA routing.
1.1. Usage Scenarios
Figure 1 shows an example architecture of an operator-hosted VPN
scenario that could benefit from a two-phase authentication within
the IKEv2 exchange. First, the client authenticates towards the
Network Access Provider (NAP) and gets access to the NAP-hosted VPN
gateway. The first-phase authentication involves the backend AAA
server of the NAP. After the first authentication, the client
initiates the second authentication round that also involves the
Third Party's backend AAA server. If both authentications succeed,
the required IPsec tunnels are set up and the client can access
protected networks behind the Third Party.
Client *Network Access Provider*
+---------+ +---------+ +-----+
| | | NAP's | | NAP |
|Protected| IPsec SAs | Tunnel | AAA Protocol | AAA |
|Endpoint |<------------------>|Endpoint |<------------>|Serv/|
| | | | |Proxy|
+---------+ +---------+ +-----+
^ ^
IPsec or / AAA |
Leased Line / Protocol |
/ |
v |
+---------+ *Third Party* v
|3rd Party| +-----+
Protected | Tunnel | | 3rd |
Subnet <----|Endpoint | |Party|
| | | AAA |
+---------+ +-----+
Figure 1: Two-phase authentication used to gain access to
the Third Party network via Network Access Provider. AAA
traffic goes through NAP's AAA server.
The NAP's AAA server can be used to proxy the AAA traffic to the
Third Party's backend AAA server. Alternatively, the AAA traffic
from the NAP's tunnel endpoint could go directly to the Third Party's
backend AAA servers. However, this is more or less an AAA routing
issue.
Eronen & Korhonen Experimental [Page 4]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
1.2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [KEYWORDS].
The terms and abbreviations "authenticator", "backend authentication
server", "EAP server", and "peer" in this document are to be
interpreted as described in [EAP].
When messages containing IKEv2 payloads are described, optional
payloads are shown in brackets (for instance, "[FOO]"), and a plus
sign indicates that a payload can be repeated one or more times (for
instance, "FOO+").
2. Solution
2.1. Solution Overview
The peers announce support for this IKEv2 extension by including a
MULTIPLE_AUTH_SUPPORTED notification in the IKE_SA_INIT response
(responder) and the first IKE_AUTH request (initiator).
If both peers support this extension, either of them can announce
that it wishes to have a second authentication by including an
ANOTHER_AUTH_FOLLOWS notification in any IKE_AUTH message that
contains an AUTH payload. This indicates that the peer sending the
ANOTHER_AUTH_FOLLOWS wishes to authenticate another set of
credentials to the other peer. The next IKE_AUTH message sent by
this peer will contain a second identity payload (IDi or IDr) and
starts another authentication exchange. The IKE_AUTH phase is
considered successful only if all the individual authentication
exchanges complete successfully.
It is assumed that both peers know what credentials they want to
present; there is no negotiation about, for instance, what type of
authentication is to be done. As in IKEv2, EAP-based authentication
is always requested by the initiator (by omitting the AUTH payload).
The AUTH payloads are calculated as specified in [IKEv2] Sections
2.15 and 2.16, where IDi' refers to the latest IDi payload sent by
the initiator, and IDr' refers to the latest IDr payload sent by the
responder. If EAP methods that do not generate shared keys are used,
it is possible that several AUTH payloads with identical contents are
sent. When such EAP methods are used, the purpose of the AUTH
payload is simply to delimit the authentication exchanges, and ensure
that the IKE_SA_INIT request/response messages were not modified.
Eronen & Korhonen Experimental [Page 5]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
2.2. Example 1: Multiple EAP Authentications
This example shows certificate-based authentication of the responder
followed by an EAP authentication exchange (messages 1-10). When the
first EAP exchange is ending (the initiator is sending its AUTH
payload), the initiator announces that it wishes to have a second
authentication exchange by including an ANOTHER_AUTH_FOLLOWS
notification (message 9).
After this, a second authentication exchange begins. The initiator
sends a new IDi payload but no AUTH payload (message 11), indicating
that EAP will be used. After that, another EAP authentication
exchange follows (messages 12-18).
Initiator Responder
----------- -----------
1. HDR, SA, KE, Ni -->
<-- 2. HDR, SA, KE, Nr, [CERTREQ],
N(MULTIPLE_AUTH_SUPPORTED)
3. HDR, SK { IDi, [CERTREQ+], [IDr],
SA, TSi, TSr, N(MULTIPLE_AUTH_SUPPORTED) } -->
<-- 4. HDR, SK { IDr, [CERT+], AUTH,
EAP(Request) }
5. HDR, SK { EAP(Response) } -->
<-- 6. HDR, SK { EAP(Request) }
7. HDR, SK { EAP(Response) } -->
<-- 8. HDR, SK { EAP(Success) }
9. HDR, SK { AUTH,
N(ANOTHER_AUTH_FOLLOWS) } -->
<-- 10. HDR, SK { AUTH }
11. HDR, SK { IDi } -->
<-- 12. HDR, SK { EAP(Request) }
13. HDR, SK { EAP(Response) } -->
<-- 14. HDR, SK { EAP(Request) }
15. HDR, SK { EAP(Response) } -->
<-- 16. HDR, SK { EAP(Success) }
17. HDR, SK { AUTH } -->
<-- 18. HDR, SK { AUTH, SA, TSi, TSr }
Example 1: Certificate-based authentication of the
responder, followed by two EAP authentication exchanges.
Eronen & Korhonen Experimental [Page 6]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
2.3. Example 2: Mixed EAP and Certificate Authentications
Another example is shown below: here both the initiator and the
responder are first authenticated using certificates (or shared
secrets); this is followed by an EAP authentication exchange.
Initiator Responder
----------- -----------
1. HDR, SA, KE, Ni -->
<-- 2. HDR, SA, KE, Nr, [CERTREQ],
N(MULTIPLE_AUTH_SUPPORTED)
3. HDR, SK { IDi, [CERT+], [CERTREQ+], [IDr], AUTH,
SA, TSi, TSr, N(MULTIPLE_AUTH_SUPPORTED),
N(ANOTHER_AUTH_FOLLOWS) } -->
<-- 4. HDR, SK { IDr, [CERT+], AUTH }
5. HDR, SK { IDi } -->
<-- 6. HDR, SK { EAP(Request) }
7. HDR, SK { EAP(Response) } -->
<-- 8. HDR, SK { EAP(Request) }
9. HDR, SK { EAP(Response) } -->
<-- 10. HDR, SK { EAP(Success) }
11. HDR, SK { AUTH } -->
<-- 12. HDR, SK { AUTH, SA, TSi, TSr }
Example 2: Certificate-based (or shared-secret-based)
authentication of the initiator and the responder,
followed by an EAP authentication exchange.
Eronen & Korhonen Experimental [Page 7]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
2.4. Example 3: Multiple Initiator Certificates
This example shows yet another possibility: the initiator has two
different certificates (and associated private keys), and
authenticates both of them to the responder.
Initiator Responder
----------- -----------
1. HDR, SA, KE, Ni -->
<-- 2. HDR, SA, KE, Nr, [CERTREQ],
N(MULTIPLE_AUTH_SUPPORTED)
3. HDR, SK { IDi, [CERT+], [CERTREQ+], [IDr], AUTH,
SA, TSi, TSr, N(MULTIPLE_AUTH_SUPPORTED),
N(ANOTHER_AUTH_FOLLOWS) } -->
<-- 4. HDR, SK { IDr, [CERT+], AUTH }
5. HDR, SK { IDi, [CERT+], AUTH } -->
<-- 6. HDR, SK { SA, TSi, TSr }
Example 3: Two certificate-based authentications of the
initiator, and one certificate-based authentication
of the responder.
2.5. Example 4: Multiple Responder Certificates
This example shows yet another possibility: the responder has two
different certificates (and associated private keys), and
authenticates both of them to the initiator.
Initiator Responder
----------- -----------
1. HDR, SA, KE, Ni -->
<-- 2. HDR, SA, KE, Nr, [CERTREQ],
N(MULTIPLE_AUTH_SUPPORTED)
3. HDR, SK { IDi, [CERT+], [CERTREQ+], [IDr], AUTH,
SA, TSi, TSr, N(MULTIPLE_AUTH_SUPPORTED) } -->
<-- 4. HDR, SK { IDr, [CERT+], AUTH,
N(ANOTHER_AUTH_FOLLOWS) }
5. HDR, SK { } -->
<-- 6. HDR, SK { IDr, [CERT+], AUTH,
SA, TSi, TSr }
Example 4: Two certificate-based authentications of the
responder, and one certificate-based authentication
of the initiator.
Eronen & Korhonen Experimental [Page 8]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
3. Payload Formats
3.1. MULTIPLE_AUTH_SUPPORTED Notify Payload
The MULTIPLE_AUTH_SUPPORTED notification is included in the
IKE_SA_INIT response or the first IKE_AUTH request to indicate that
the peer supports this specification. The Notify Message Type is
MULTIPLE_AUTH_SUPPORTED (16404). The Protocol ID and SPI Size fields
MUST be set to zero, and there is no data associated with this Notify
type.
3.2. ANOTHER_AUTH_FOLLOWS Notify Payload
The ANOTHER_AUTH_FOLLOWS notification payload is included in an
IKE_AUTH message containing an AUTH payload to indicate that the peer
wants to continue with another authentication exchange. The Notify
Message Type is ANOTHER_AUTH_FOLLOWS (16405). The Protocol ID and
SPI Size fields MUST be set to zero, and there is no data associated
with this Notify type.
4. IANA Considerations
This document defines two new IKEv2 notifications,
MULTIPLE_AUTH_SUPPORTED and ANOTHER_AUTH_FOLLOWS, whose values are
allocated from the "IKEv2 Notify Message Types" namespace defined in
[IKEv2].
This document does not define any new namespaces to be managed by
IANA.
5. Security Considerations
Security considerations for IKEv2 are discussed in [IKEv2]. The
reader is encouraged to pay special attention to considerations
relating to the use of EAP methods that do not generate shared keys.
However, the use of multiple authentication exchanges results in at
least one new security consideration.
In normal IKEv2, the responder authenticates the initiator before
revealing its identity (except when EAP is used). When multiple
authentication exchanges are used to authenticate the initiator, the
responder has to reveal its identity before all of the initiator
authentication exchanges have been completed.
Eronen & Korhonen Experimental [Page 9]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
6. Acknowledgments
The authors would like to thank Bernard Aboba, Jari Arkko, Spencer
Dawkins, Lakshminath Dondeti, Henry Haverinen, Russ Housley, Mika
Joutsenvirta, Charlie Kaufman, Tero Kivinen, Yoav Nir, Magnus
Nystrom, Mohan Parthasarathy, and Juha Savolainen for their valuable
comments.
7. References
7.1. Normative References
[IKEv2] Kaufman, C., "Internet Key Exchange (IKEv2) Protocol",
RFC 4306, December 2005.
[KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
7.2. Informative References
[EAP] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H.
Levkowetz, "Extensible Authentication Protocol (EAP)",
RFC 3748, June 2004.
[PANA] Yegin, A., Ohba, Y., Penno, R., Tsirtsis, G., and C.
Wang, "Protocol for Carrying Authentication for Network
Access (PANA) Requirements", RFC 4058, May 2005.
Authors' Addresses
Pasi Eronen
Nokia Research Center
P.O. Box 407
FIN-00045 Nokia Group
Finland
EMail: [email protected]
Jouni Korhonen
TeliaSonera
P.O. Box 970
FIN-00051 Sonera
Finland
EMail: [email protected]
Eronen & Korhonen Experimental [Page 10]
RFC 4739 Multiple Auth. Exchanges in IKEv2 November 2006
Full Copyright Statement
Copyright (C) The IETF Trust (2006).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
retain all their rights.
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST,
AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT
THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE.
Intellectual Property
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at
[email protected].
Acknowledgement
Funding for the RFC Editor function is currently provided by the
Internet Society.
Eronen & Korhonen Experimental [Page 11]
@@ -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
@@ -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
@@ -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.
@@ -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.
@@ -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.
@@ -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>
@@ -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>
/**
@@ -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;
}
@@ -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_*/
@@ -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.
@@ -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>
/**
@@ -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.
@@ -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>
/**
@@ -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;
@@ -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_*/
@@ -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>
/**
@@ -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>
/**
@@ -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;
@@ -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;
@@ -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;
@@ -25,7 +25,6 @@
#include "psk_authenticator.h"
#include <config/policies/policy.h>
#include <daemon.h>
/**
@@ -25,7 +25,6 @@
#include "rsa_authenticator.h"
#include <config/policies/policy.h>
#include <daemon.h>
+29 -34
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;
}
+9 -16
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_*/
+167 -221
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;
+25 -30
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);
+1
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;
}
+2 -2
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);
+53 -54
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;
+3 -3
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_ */
+4 -4
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
{
+30 -17
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)
+12 -14
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);
+8 -15
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();
+2 -3
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_ */
+1 -1
View File
@@ -28,7 +28,7 @@
typedef struct private_ike_delete_t private_ike_delete_t;
/**
/**file
* Private members of a ike_delete_t task.
*/
struct private_ike_delete_t {
+14 -16
View File
@@ -57,9 +57,9 @@ struct private_ike_init_t {
bool initiator;
/**
* Connection established by this IKE_SA
* IKE config to establish
*/
connection_t *connection;
ike_cfg_t *config;
/**
* diffie hellman group to use
@@ -117,11 +117,11 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
id = this->ike_sa->get_id(this->ike_sa);
this->connection = this->ike_sa->get_connection(this->ike_sa);
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
if (this->initiator)
{
proposal_list = this->connection->get_proposals(this->connection);
proposal_list = this->config->get_proposals(this->config);
if (this->old_sa)
{
/* include SPI of new IKE_SA when we are rekeying */
@@ -174,8 +174,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
linked_list_t *proposal_list;
proposal_list = sa_payload->get_proposals(sa_payload);
this->proposal = this->connection->select_proposal(
this->connection, proposal_list);
this->proposal = this->config->select_proposal(this->config,
proposal_list);
proposal_list->destroy_offset(proposal_list,
offsetof(proposal_t, destroy));
break;
@@ -200,8 +200,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
else
{
this->dh_group = dh_group;
if (!this->connection->check_dh_group(this->connection,
dh_group))
if (!this->config->check_dh_group(this->config, dh_group))
{
break;
}
@@ -235,9 +234,9 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
randomizer_t *randomizer;
status_t status;
this->connection = this->ike_sa->get_connection(this->ike_sa);
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
SIG(IKE_UP_START, "initiating IKE_SA to %H",
this->connection->get_other_host(this->connection));
this->config->get_other_host(this->config));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
if (this->retry++ >= MAX_RETRIES)
@@ -249,7 +248,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
/* if the DH group is set via use_dh_group(), we already have a DH object */
if (!this->diffie_hellman)
{
this->dh_group = this->connection->get_dh_group(this->connection);
this->dh_group = this->config->get_dh_group(this->config);
this->diffie_hellman = diffie_hellman_create(this->dh_group);
if (this->diffie_hellman == NULL)
{
@@ -291,7 +290,7 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
{
randomizer_t *randomizer;
this->connection = this->ike_sa->get_connection(this->ike_sa);
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
SIG(IKE_UP_FAILED, "%H is initiating an IKE_SA",
message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
@@ -335,7 +334,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
SIG(IKE_UP_FAILED, "received inacceptable DH group (%N)",
diffie_hellman_group_names, this->dh_group);
this->dh_group = this->connection->get_dh_group(this->connection);
this->dh_group = this->config->get_dh_group(this->config);
dh_enc = htons(this->dh_group);
chunk.ptr = (u_int8_t*)&dh_enc;
chunk.len = sizeof(dh_enc);
@@ -414,8 +413,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
DBG1(DBG_IKE, "peer didn't accept DH group %N, it requested"
" %N", diffie_hellman_group_names, old_dh_group,
diffie_hellman_group_names, this->dh_group);
if (!this->connection->check_dh_group(this->connection,
this->dh_group))
if (!this->config->check_dh_group(this->config, this->dh_group))
{
DBG1(DBG_IKE, "requested DH group %N not acceptable, "
"giving up", diffie_hellman_group_names,
@@ -590,7 +588,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
this->other_nonce = chunk_empty;
this->cookie = chunk_empty;
this->proposal = NULL;
this->connection = NULL;
this->config = NULL;
this->old_sa = old_sa;
this->retry = 0;

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