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:
1 parent
1628cd6bda
commit
e0fe765152
104 files changed
+3466
-3470
No files matched your search
@@ -47,6 +47,7 @@ Build system
|
||||
------------
|
||||
- configure flag which allows to ommit vendor id in pluto
|
||||
- reduce printf handlers count to 10, as uClibc does not support more
|
||||
- remove %m printf handlers, as error may have changed until it reaches fprintf()
|
||||
|
||||
Certificate support
|
||||
-------------------
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
CFLAGS="-Wall -Wno-format -Wno-pointer-sign -Wno-strict-aliasing -g -O2" ./configure \
|
||||
--sysconfdir=/etc --with-random-device=/dev/urandom --enable-ldap --enable-http \
|
||||
--enable-leak-detective
|
||||
--sysconfdir=/etc --with-random-device=/dev/urandom \
|
||||
--enable-leak-detective --enable-eap-sim --with-sim-reader=/home/martin/strongswan/trunk/src/charon/sa/authenticators/eap/sim_reader/sim_api.so
|
||||
+78
-53
@@ -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}\"
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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**)¤t))
|
||||
{
|
||||
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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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 **)¤t))
|
||||
{
|
||||
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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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 **)¤t))
|
||||
{
|
||||
if (strcmp(current->get_name(current), name) == 0)
|
||||
{
|
||||
found = current;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
|
||||
/* give out a new reference */
|
||||
found->get_ref(found);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.delete_policy.
|
||||
*/
|
||||
static status_t delete_policy(private_local_policy_store_t *this, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
policy_t *current;
|
||||
bool found = FALSE;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||
while (iterator->iterate(iterator, (void **)¤t))
|
||||
{
|
||||
if (strcmp(current->get_name(current), name) == 0)
|
||||
{
|
||||
/* remove policy from list, and destroy it */
|
||||
iterator->remove(iterator);
|
||||
current->destroy(current);
|
||||
found = TRUE;
|
||||
/* we do not break here, as there may be multipe policies */
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
if (found)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.create_iterator.
|
||||
*/
|
||||
static iterator_t* create_iterator(private_local_policy_store_t *this)
|
||||
{
|
||||
return this->policies->create_iterator_locked(this->policies,
|
||||
&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.destroy.
|
||||
*/
|
||||
static void destroy(private_local_policy_store_t *this)
|
||||
{
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->policies->destroy_offset(this->policies, offsetof(policy_t, destroy));
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
local_policy_store_t *local_policy_store_create(void)
|
||||
{
|
||||
private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
|
||||
|
||||
this->public.policy_store.add_policy = (void (*) (policy_store_t*,policy_t*))add_policy;
|
||||
this->public.policy_store.get_policy = (policy_t* (*) (policy_store_t*,identification_t*,identification_t*,
|
||||
linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy;
|
||||
this->public.policy_store.get_policy_by_name = (policy_t* (*) (policy_store_t*,char*))get_policy_by_name;
|
||||
this->public.policy_store.delete_policy = (status_t (*) (policy_store_t*,char*))delete_policy;
|
||||
this->public.policy_store.create_iterator = (iterator_t* (*) (policy_store_t*))create_iterator;
|
||||
this->public.policy_store.destroy = (void (*) (policy_store_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->policies = linked_list_create();
|
||||
pthread_mutex_init(&(this->mutex), NULL);
|
||||
|
||||
return (&this->public);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
/* we make a copy of the TS, this allows us to update wildcard
|
||||
* addresses in it. We won't pollute the shared policy. */
|
||||
current = current->clone(current);
|
||||
if (host)
|
||||
{
|
||||
current->set_address(current, host);
|
||||
}
|
||||
|
||||
result->insert_last(result, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_my_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *get_my_traffic_selectors(private_policy_t *this, host_t *me)
|
||||
{
|
||||
return get_traffic_selectors(this, this->my_ts, me);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_other_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *get_other_traffic_selectors(private_policy_t *this, host_t *other)
|
||||
{
|
||||
return get_traffic_selectors(this, this->other_ts, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrow traffic selectors, with wildcard-address update in "stored".
|
||||
*/
|
||||
static linked_list_t *select_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *stored,
|
||||
linked_list_t *supplied,
|
||||
host_t *host)
|
||||
{
|
||||
iterator_t *supplied_iter, *stored_iter, *i1, *i2;
|
||||
traffic_selector_t *supplied_ts, *stored_ts, *selected_ts, *ts1, *ts2;
|
||||
linked_list_t *selected = linked_list_create();
|
||||
|
||||
DBG2(DBG_CFG, "selecting traffic selectors");
|
||||
|
||||
stored_iter = stored->create_iterator(stored, TRUE);
|
||||
supplied_iter = supplied->create_iterator(supplied, TRUE);
|
||||
|
||||
/* iterate over all stored selectors */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored_ts))
|
||||
{
|
||||
/* we make a copy of the TS, this allows us to update wildcard
|
||||
* addresses in it. We won't pollute the shared policy. */
|
||||
stored_ts = stored_ts->clone(stored_ts);
|
||||
if (host)
|
||||
{
|
||||
stored_ts->set_address(stored_ts, host);
|
||||
}
|
||||
|
||||
supplied_iter->reset(supplied_iter);
|
||||
/* iterate over all supplied traffic selectors */
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied_ts))
|
||||
{
|
||||
DBG2(DBG_CFG, "stored %R <=> %R received",
|
||||
stored_ts, supplied_ts);
|
||||
|
||||
selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
|
||||
if (selected_ts)
|
||||
{
|
||||
/* got a match, add to list */
|
||||
selected->insert_last(selected, (void*)selected_ts);
|
||||
|
||||
DBG2(DBG_CFG, "found traffic selector for %s: %R",
|
||||
stored == this->my_ts ? "us" : "other", selected_ts);
|
||||
}
|
||||
}
|
||||
stored_ts->destroy(stored_ts);
|
||||
}
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
/* remove any redundant traffic selectors in the list */
|
||||
i1 = selected->create_iterator(selected, TRUE);
|
||||
i2 = selected->create_iterator(selected, TRUE);
|
||||
while (i1->iterate(i1, (void**)&ts1))
|
||||
{
|
||||
while (i2->iterate(i2, (void**)&ts2))
|
||||
{
|
||||
if (ts1 != ts2)
|
||||
{
|
||||
if (ts2->is_contained_in(ts2, ts1))
|
||||
{
|
||||
i2->remove(i2);
|
||||
ts2->destroy(ts2);
|
||||
i1->reset(i1);
|
||||
break;
|
||||
}
|
||||
if (ts1->is_contained_in(ts1, ts2))
|
||||
{
|
||||
i1->remove(i1);
|
||||
ts1->destroy(ts1);
|
||||
i2->reset(i2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i1->destroy(i1);
|
||||
i2->destroy(i2);
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_policy_t.select_my_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *select_my_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t *me)
|
||||
{
|
||||
return select_traffic_selectors(this, this->my_ts, supplied, me);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_policy_t.select_other_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *select_other_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t* other)
|
||||
{
|
||||
return select_traffic_selectors(this, this->other_ts, supplied, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_proposal_iterator
|
||||
*/
|
||||
static linked_list_t *get_proposals(private_policy_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *current;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
current = current->clone(current);
|
||||
proposals->insert_last(proposals, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.select_proposal
|
||||
*/
|
||||
static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals)
|
||||
{
|
||||
iterator_t *stored_iter, *supplied_iter;
|
||||
proposal_t *stored, *supplied, *selected;
|
||||
|
||||
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
supplied_iter = proposals->create_iterator(proposals, TRUE);
|
||||
|
||||
/* compare all stored proposals with all supplied. Stored ones are preferred. */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored))
|
||||
{
|
||||
supplied_iter->reset(supplied_iter);
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
|
||||
{
|
||||
selected = stored->select(stored, supplied);
|
||||
if (selected)
|
||||
{
|
||||
/* they match, return */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_authorities
|
||||
*/
|
||||
static void add_authorities(private_policy_t *this, identification_t *my_ca, identification_t *other_ca)
|
||||
{
|
||||
this->my_ca = my_ca;
|
||||
this->other_ca = other_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_updown
|
||||
*/
|
||||
static char* get_updown(private_policy_t *this)
|
||||
{
|
||||
return this->updown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_hostaccess
|
||||
*/
|
||||
static bool get_hostaccess(private_policy_t *this)
|
||||
{
|
||||
return this->hostaccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.get_dpd_action
|
||||
*/
|
||||
static dpd_action_t get_dpd_action(private_policy_t *this)
|
||||
{
|
||||
return this->dpd_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_my_traffic_selector
|
||||
*/
|
||||
static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
|
||||
{
|
||||
this->my_ts->insert_last(this->my_ts, (void*)traffic_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_other_traffic_selector
|
||||
*/
|
||||
static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
|
||||
{
|
||||
this->other_ts->insert_last(this->other_ts, (void*)traffic_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_proposal
|
||||
*/
|
||||
static void add_proposal(private_policy_t *this, proposal_t *proposal)
|
||||
{
|
||||
this->proposals->insert_last(this->proposals, (void*)proposal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_soft_lifetime
|
||||
*/
|
||||
static u_int32_t get_soft_lifetime(private_policy_t *this)
|
||||
{
|
||||
if (this->jitter == 0)
|
||||
{
|
||||
return this->soft_lifetime ;
|
||||
}
|
||||
return this->soft_lifetime - (random() % this->jitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_hard_lifetime
|
||||
*/
|
||||
static u_int32_t get_hard_lifetime(private_policy_t *this)
|
||||
{
|
||||
return this->hard_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_mode.
|
||||
*/
|
||||
static mode_t get_mode(private_policy_t *this)
|
||||
{
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_virtual_ip.
|
||||
*/
|
||||
static host_t* get_virtual_ip(private_policy_t *this, host_t *suggestion)
|
||||
{
|
||||
if (suggestion == NULL)
|
||||
{
|
||||
if (this->my_virtual_ip)
|
||||
{
|
||||
return this->my_virtual_ip->clone(this->my_virtual_ip);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (this->other_virtual_ip)
|
||||
{
|
||||
return this->other_virtual_ip->clone(this->other_virtual_ip);
|
||||
}
|
||||
if (suggestion->is_anyaddr(suggestion))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return suggestion->clone(suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.get_ref.
|
||||
*/
|
||||
static void get_ref(private_policy_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.destroy.
|
||||
*/
|
||||
static void destroy(private_policy_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
|
||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
|
||||
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
|
||||
|
||||
/* delete certification authorities */
|
||||
DESTROY_IF(this->my_ca);
|
||||
DESTROY_IF(this->other_ca);
|
||||
|
||||
/* delete updown script */
|
||||
if (this->updown)
|
||||
{
|
||||
free(this->updown);
|
||||
}
|
||||
|
||||
/* delete ids */
|
||||
this->my_id->destroy(this->my_id);
|
||||
this->other_id->destroy(this->other_id);
|
||||
DESTROY_IF(this->my_virtual_ip);
|
||||
DESTROY_IF(this->other_virtual_ip);
|
||||
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip,
|
||||
auth_method_t auth_method, eap_type_t eap_type,
|
||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||
u_int32_t jitter, char *updown, bool hostaccess,
|
||||
mode_t mode, dpd_action_t dpd_action)
|
||||
{
|
||||
private_policy_t *this = malloc_thing(private_policy_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_name = (char* (*) (policy_t*))get_name;
|
||||
this->public.get_my_id = (identification_t* (*) (policy_t*))get_my_id;
|
||||
this->public.get_other_id = (identification_t* (*) (policy_t*))get_other_id;
|
||||
this->public.get_my_ca = (identification_t* (*) (policy_t*))get_my_ca;
|
||||
this->public.get_other_ca = (identification_t* (*) (policy_t*))get_other_ca;
|
||||
this->public.get_auth_method = (auth_method_t (*) (policy_t*)) get_auth_method;
|
||||
this->public.get_eap_type = (eap_type_t (*) (policy_t*)) get_eap_type;
|
||||
this->public.get_my_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_my_traffic_selectors;
|
||||
this->public.get_other_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_other_traffic_selectors;
|
||||
this->public.select_my_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_t*))select_my_traffic_selectors;
|
||||
this->public.select_other_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_t*))select_other_traffic_selectors;
|
||||
this->public.get_proposals = (linked_list_t* (*) (policy_t*))get_proposals;
|
||||
this->public.select_proposal = (proposal_t* (*) (policy_t*,linked_list_t*))select_proposal;
|
||||
this->public.add_my_traffic_selector = (void (*) (policy_t*,traffic_selector_t*))add_my_traffic_selector;
|
||||
this->public.add_other_traffic_selector = (void (*) (policy_t*,traffic_selector_t*))add_other_traffic_selector;
|
||||
this->public.add_proposal = (void (*) (policy_t*,proposal_t*))add_proposal;
|
||||
this->public.add_authorities = (void (*) (policy_t*,identification_t*,identification_t*))add_authorities;
|
||||
this->public.get_updown = (char* (*) (policy_t*))get_updown;
|
||||
this->public.get_hostaccess = (bool (*) (policy_t*))get_hostaccess;
|
||||
this->public.get_dpd_action = (dpd_action_t (*) (policy_t*))get_dpd_action;
|
||||
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
|
||||
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
|
||||
this->public.get_mode = (mode_t (*) (policy_t *))get_mode;
|
||||
this->public.get_virtual_ip = (host_t* (*)(policy_t*,host_t*))get_virtual_ip;
|
||||
this->public.get_ref = (void (*) (policy_t*))get_ref;
|
||||
this->public.destroy = (void (*) (policy_t*))destroy;
|
||||
|
||||
/* apply init values */
|
||||
this->name = strdup(name);
|
||||
this->my_id = my_id;
|
||||
this->other_id = other_id;
|
||||
this->my_virtual_ip = my_virtual_ip;
|
||||
this->other_virtual_ip = other_virtual_ip;
|
||||
this->auth_method = auth_method;
|
||||
this->eap_type = eap_type;
|
||||
this->hard_lifetime = hard_lifetime;
|
||||
this->soft_lifetime = soft_lifetime;
|
||||
this->jitter = jitter;
|
||||
this->updown = (updown == NULL) ? NULL : strdup(updown);
|
||||
this->hostaccess = hostaccess;
|
||||
this->dpd_action = dpd_action;
|
||||
this->mode = mode;
|
||||
|
||||
/* initialize private members*/
|
||||
this->refcount = 1;
|
||||
this->my_ca = NULL;
|
||||
this->other_ca = NULL;
|
||||
this->proposals = linked_list_create();
|
||||
this->my_ts = linked_list_create();
|
||||
this->other_ts = linked_list_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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_*/
|
||||
@@ -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));
|
||||
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -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**)¤t))
|
||||
{
|
||||
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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
File renamed without changes.
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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.
|
||||
File renamed without changes.
@@ -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.
|
||||
File renamed without changes.
@@ -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.
|
||||
File renamed without changes.
+1
-1
@@ -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>
|
||||
|
||||
|
||||
File renamed without changes.
+1
-1
@@ -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_*/
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -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.
|
||||
File renamed without changes.
+1
-1
@@ -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>
|
||||
|
||||
/**
|
||||
File renamed without changes.
+1
-1
@@ -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.
|
||||
File renamed without changes.
+1
-1
@@ -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_*/
|
||||
File renamed without changes.
@@ -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>
|
||||
|
||||
/**
|
||||
File renamed without changes.
+1
-2
@@ -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;
|
||||
File renamed without changes.
@@ -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;
|
||||
File renamed without changes.
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
Loaded 100 of 104 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user