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:
parent
1628cd6bda
commit
e0fe765152
1
TODO
1
TODO
|
@ -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
|
||||
-------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,17 +425,40 @@ 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);
|
||||
/* 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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
|
||||
my_host, other_host);
|
||||
|
||||
if (msg->add_conn.algorithms.ike)
|
||||
{
|
||||
|
@ -455,33 +482,45 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
|||
other_ts->destroy(other_ts);
|
||||
my_ca->destroy(my_ca);
|
||||
other_ca->destroy(other_ca);
|
||||
connection->destroy(connection);
|
||||
ike_cfg->destroy(ike_cfg);
|
||||
return;
|
||||
}
|
||||
connection->add_proposal(connection, proposal);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||
}
|
||||
if (!strict)
|
||||
{
|
||||
proposal = proposal_create_default(PROTO_IKE);
|
||||
connection->add_proposal(connection, proposal);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
proposal = proposal_create_default(PROTO_IKE);
|
||||
connection->add_proposal(connection, proposal);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||
}
|
||||
|
||||
policy = policy_create(msg->add_conn.name, my_id, other_id, my_vip, other_vip,
|
||||
|
||||
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.ipsec_lifetime,
|
||||
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);
|
||||
}
|
||||
|
||||
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, 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);
|
||||
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]",
|
||||
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);
|
||||
/* add to global policy list */
|
||||
charon->policies->add_policy(charon->policies, policy);
|
||||
|
||||
}
|
||||
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))
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
peer_iter->destroy(peer_iter);
|
||||
|
||||
fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
peer_cfg = charon->cfg_store->get_peer_cfg_by_name(charon->cfg_store,
|
||||
msg->initiate.name);
|
||||
if (connection == NULL)
|
||||
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,
|
||||
peer_cfg = charon->cfg_store->get_peer_cfg_by_name(charon->cfg_store,
|
||||
msg->route.name);
|
||||
if (connection == NULL)
|
||||
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");
|
||||
}
|
||||
while (iterator->iterate(iterator, (void**)&connection))
|
||||
iterator = this->backend->create_peer_cfg_iterator(this->backend);
|
||||
while (iterator->iterate(iterator, (void**)&peer_cfg))
|
||||
{
|
||||
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));
|
||||
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->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));
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -1136,7 +1215,6 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
|||
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))
|
||||
|
@ -1155,7 +1233,7 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
|||
}
|
||||
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)
|
||||
{
|
||||
|
@ -1163,7 +1241,6 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
|||
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))
|
||||
|
@ -1185,7 +1262,8 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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_ */
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -29,9 +29,9 @@
|
|||
#include <daemon.h>
|
||||
#include <network/socket.h>
|
||||
#include <network/packet.h>
|
||||
#include <queues/job_queue.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <queues/jobs/process_message_job.h>
|
||||
#include <processing/job_queue.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <processing/jobs/process_message_job.h>
|
||||
|
||||
/** length of the full cookie, including time (u_int32_t + SHA1()) */
|
||||
#define COOKIE_LENGTH 24
|
|
@ -29,7 +29,7 @@ typedef struct event_queue_t event_queue_t;
|
|||
#include <sys/time.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
/**
|
||||
* @brief Event-Queue used to store timed events.
|
|
@ -27,7 +27,7 @@
|
|||
typedef struct job_queue_t job_queue_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
/**
|
||||
* @brief The job queue stores jobs, which will be processed by the thread_pool_t.
|
|
@ -26,7 +26,7 @@
|
|||
typedef struct acquire_job_t acquire_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
/**
|
||||
* @brief Class representing an ACQUIRE Job.
|
|
@ -27,7 +27,7 @@ typedef struct delete_child_sa_job_t delete_child_sa_job_t;
|
|||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <config/proposal.h>
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ typedef struct delete_ike_sa_job_t delete_ike_sa_job_t;
|
|||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
|
||||
/**
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
|
@ -40,14 +40,14 @@ struct private_initiate_job_t {
|
|||
initiate_job_t public;
|
||||
|
||||
/**
|
||||
* associated connection to initiate
|
||||
* associated peer config to use for IKE_SA setup
|
||||
*/
|
||||
connection_t *connection;
|
||||
peer_cfg_t *peer_cfg;
|
||||
|
||||
/**
|
||||
* associated policy to initiate
|
||||
* child config to use for CHILD_SA
|
||||
*/
|
||||
policy_t *policy;
|
||||
child_cfg_t *child_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -64,14 +64,20 @@ static job_type_t get_type(private_initiate_job_t *this)
|
|||
static status_t execute(private_initiate_job_t *this)
|
||||
{
|
||||
ike_sa_t *ike_sa;
|
||||
ike_cfg_t *ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
|
||||
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
|
||||
this->connection->get_my_host(this->connection),
|
||||
this->connection->get_other_host(this->connection),
|
||||
this->policy->get_my_id(this->policy),
|
||||
this->policy->get_other_id(this->policy));
|
||||
ike_cfg->get_my_host(ike_cfg),
|
||||
ike_cfg->get_other_host(ike_cfg),
|
||||
this->peer_cfg->get_my_id(this->peer_cfg),
|
||||
this->peer_cfg->get_other_id(this->peer_cfg));
|
||||
|
||||
if (ike_sa->initiate(ike_sa, this->connection, this->policy) != SUCCESS)
|
||||
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, this->peer_cfg);
|
||||
}
|
||||
|
||||
if (ike_sa->initiate(ike_sa, this->child_cfg) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_JOB, "initiation failed, going to delete IKE_SA");
|
||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
|
@ -87,15 +93,15 @@ static status_t execute(private_initiate_job_t *this)
|
|||
*/
|
||||
static void destroy(private_initiate_job_t *this)
|
||||
{
|
||||
this->connection->destroy(this->connection);
|
||||
this->policy->destroy(this->policy);
|
||||
this->peer_cfg->destroy(this->peer_cfg);
|
||||
this->child_cfg->destroy(this->child_cfg);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy)
|
||||
initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg)
|
||||
{
|
||||
private_initiate_job_t *this = malloc_thing(private_initiate_job_t);
|
||||
|
||||
|
@ -105,8 +111,8 @@ initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy)
|
|||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||
|
||||
/* private variables */
|
||||
this->connection = connection;
|
||||
this->policy = policy;
|
||||
this->peer_cfg = peer_cfg;
|
||||
this->child_cfg = child_cfg;
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
|
@ -20,15 +20,15 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef INITIATE_IKE_SA_JOB_H_
|
||||
#define INITIATE_IKE_SA_JOB_H_
|
||||
#ifndef INITIATE_JOB_H_
|
||||
#define INITIATE_JOB_H_
|
||||
|
||||
typedef struct initiate_job_t initiate_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <config/connections/connection.h>
|
||||
#include <config/policies/policy.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <config/peer_cfg.h>
|
||||
#include <config/child_cfg.h>
|
||||
|
||||
/**
|
||||
* @brief Class representing an INITIATE_IKE_SA Job.
|
||||
|
@ -48,14 +48,14 @@ struct initiate_job_t {
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a job of type INITIATE_IKE_SA.
|
||||
* @brief Creates a job of type INITIATE.
|
||||
*
|
||||
* @param connection connection_t to initialize
|
||||
* @param policy policy to set up
|
||||
* @param peer_cfg peer configuration to use (if not yet established)
|
||||
* @param child_cfg config to create a CHILD from
|
||||
* @return initiate_job_t object
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
initiate_job_t *initiate_job_create(connection_t *connection, policy_t *policy);
|
||||
initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg);
|
||||
|
||||
#endif /*INITIATE_IKE_SA_JOB_H_*/
|
||||
#endif /*INITIATE_JOB_H_*/
|
|
@ -28,7 +28,7 @@ typedef struct process_message_job_t process_message_job_t;
|
|||
|
||||
#include <library.h>
|
||||
#include <encoding/message.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
/**
|
||||
* @brief Class representing an PROCESS_MESSAGE job.
|
|
@ -27,7 +27,7 @@ typedef struct rekey_child_sa_job_t rekey_child_sa_job_t;
|
|||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <config/proposal.h>
|
||||
|
||||
/**
|
|
@ -27,7 +27,7 @@ typedef struct rekey_ike_sa_job_t rekey_ike_sa_job_t;
|
|||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
/**
|
||||
* @brief Class representing an REKEY_IKE_SA Job.
|
|
@ -27,7 +27,7 @@
|
|||
typedef struct retransmit_job_t retransmit_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
|
||||
/**
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -39,14 +39,14 @@ struct private_route_job_t {
|
|||
route_job_t public;
|
||||
|
||||
/**
|
||||
* associated connection to route
|
||||
* peer config for route
|
||||
*/
|
||||
connection_t *connection;
|
||||
peer_cfg_t *peer_cfg;
|
||||
|
||||
/**
|
||||
* associated policy to route
|
||||
* child config to route
|
||||
*/
|
||||
policy_t *policy;
|
||||
child_cfg_t *child_cfg;
|
||||
|
||||
/**
|
||||
* route or unroute?
|
||||
|
@ -68,22 +68,29 @@ static job_type_t get_type(private_route_job_t *this)
|
|||
static status_t execute(private_route_job_t *this)
|
||||
{
|
||||
ike_sa_t *ike_sa;
|
||||
ike_cfg_t *ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
|
||||
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
|
||||
this->connection->get_my_host(this->connection),
|
||||
this->connection->get_other_host(this->connection),
|
||||
this->policy->get_my_id(this->policy),
|
||||
this->policy->get_other_id(this->policy));
|
||||
ike_cfg->get_my_host(ike_cfg),
|
||||
ike_cfg->get_other_host(ike_cfg),
|
||||
this->peer_cfg->get_my_id(this->peer_cfg),
|
||||
this->peer_cfg->get_other_id(this->peer_cfg));
|
||||
|
||||
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, this->peer_cfg);
|
||||
}
|
||||
|
||||
if (this->route)
|
||||
{
|
||||
if (ike_sa->route(ike_sa, this->connection, this->policy) != SUCCESS)
|
||||
if (ike_sa->route(ike_sa, this->child_cfg) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_JOB, "routing failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ike_sa->unroute(ike_sa, this->policy) == DESTROY_ME)
|
||||
if (ike_sa->unroute(ike_sa, this->child_cfg) == DESTROY_ME)
|
||||
{
|
||||
DBG1(DBG_JOB, "removing IKE_SA, as last routed CHILD_SA unrouted");
|
||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
|
@ -99,15 +106,16 @@ static status_t execute(private_route_job_t *this)
|
|||
*/
|
||||
static void destroy(private_route_job_t *this)
|
||||
{
|
||||
this->connection->destroy(this->connection);
|
||||
this->policy->destroy(this->policy);
|
||||
this->peer_cfg->destroy(this->peer_cfg);
|
||||
this->child_cfg->destroy(this->child_cfg);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route)
|
||||
route_job_t *route_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
|
||||
bool route)
|
||||
{
|
||||
private_route_job_t *this = malloc_thing(private_route_job_t);
|
||||
|
||||
|
@ -117,8 +125,8 @@ route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool r
|
|||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||
|
||||
/* private variables */
|
||||
this->connection = connection;
|
||||
this->policy = policy;
|
||||
this->peer_cfg = peer_cfg;
|
||||
this->child_cfg = child_cfg;
|
||||
this->route = route;
|
||||
|
||||
return &this->public;
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,9 +25,8 @@
|
|||
typedef struct route_job_t route_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <config/policies/policy.h>
|
||||
#include <config/connections/connection.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <config/peer_cfg.h>
|
||||
|
||||
/**
|
||||
* @brief Class representing an ROUTE Job.
|
||||
|
@ -47,13 +46,14 @@ struct route_job_t {
|
|||
/**
|
||||
* @brief Creates a job of type ROUTE.
|
||||
*
|
||||
* @param connection connection used for routing
|
||||
* @param policy policy to set up
|
||||
* @param peer_cfg peer config to use for acquire
|
||||
* @param child_cfg route to install
|
||||
* @param route TRUE to route, FALSE to unroute
|
||||
* @return route_job_t object
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route);
|
||||
route_job_t *route_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
|
||||
bool route);
|
||||
|
||||
#endif /*ROUTE_JOB_H_*/
|
|
@ -25,8 +25,7 @@
|
|||
typedef struct send_dpd_job_t send_dpd_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <config/connections/connection.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
|
||||
/**
|
|
@ -25,8 +25,7 @@
|
|||
typedef struct send_keepalive_job_t send_keepalive_job_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <queues/jobs/job.h>
|
||||
#include <config/connections/connection.h>
|
||||
#include <processing/jobs/job.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
|
||||
/**
|
|
@ -27,7 +27,7 @@
|
|||
#include "scheduler.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <queues/job_queue.h>
|
||||
#include <processing/job_queue.h>
|
||||
|
||||
|
||||
typedef struct private_scheduler_t private_scheduler_t;
|
|
@ -29,7 +29,7 @@
|
|||
#include "thread_pool.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <queues/job_queue.h>
|
||||
#include <processing/job_queue.h>
|
||||
|
||||
|
||||
typedef struct private_thread_pool_t private_thread_pool_t;
|
|
@ -25,7 +25,7 @@
|
|||
#include "eap_authenticator.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <config/policies/policy.h>
|
||||
#include <config/peer_cfg.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
|
||||
typedef struct private_eap_authenticator_t private_eap_authenticator_t;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "psk_authenticator.h"
|
||||
|
||||
#include <config/policies/policy.h>
|
||||
#include <daemon.h>
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "rsa_authenticator.h"
|
||||
|
||||
#include <config/policies/policy.h>
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
|
||||
{
|
||||
if (local)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
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_*/
|
||||
|
|
|
@ -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,28 +866,13 @@ 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)
|
||||
{
|
||||
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))
|
||||
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
|
||||
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
|
||||
{
|
||||
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");
|
||||
SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config 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);
|
||||
|
||||
|
@ -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));
|
||||
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,28 +929,15 @@ 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)
|
||||
{
|
||||
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))
|
||||
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
|
||||
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
|
||||
{
|
||||
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->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);
|
||||
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,
|
||||
this->connection && reauth? "reauthentication":"rekeying",
|
||||
reauth ? "reauthentication" : "rekeying",
|
||||
this->time.rekey - time(NULL));
|
||||
|
||||
if (info->alt)
|
||||
{
|
||||
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
if (peer_cfg)
|
||||
{
|
||||
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));
|
||||
|
||||
if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
|
||||
{
|
||||
this->ike_sa->set_policy(this->ike_sa, this->policy);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -492,6 +492,8 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
|
|||
*/
|
||||
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_ */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue