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
|
- configure flag which allows to ommit vendor id in pluto
|
||||||
- reduce printf handlers count to 10, as uClibc does not support more
|
- 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
|
Certificate support
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
CFLAGS="-Wall -Wno-format -Wno-pointer-sign -Wno-strict-aliasing -g -O2" ./configure \
|
CFLAGS="-Wall -Wno-format -Wno-pointer-sign -Wno-strict-aliasing -g -O2" ./configure \
|
||||||
--sysconfdir=/etc --with-random-device=/dev/urandom --enable-ldap --enable-http \
|
--sysconfdir=/etc --with-random-device=/dev/urandom \
|
||||||
--enable-leak-detective
|
--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 = \
|
charon_SOURCES = \
|
||||||
bus/bus.c bus/bus.h \
|
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 \
|
bus/listeners/file_logger.c bus/listeners/file_logger.h \
|
||||||
config/connections/connection.c config/connections/connection.h \
|
bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
|
||||||
config/connections/local_connection_store.c config/connections/local_connection_store.h config/connections/connection_store.h \
|
config/backends/backend.h \
|
||||||
config/policies/policy.c config/policies/policy.h \
|
config/backends/local_backend.c config/backends/local_backend.h \
|
||||||
config/policies/local_policy_store.c config/policies/policy_store.h config/policies/local_policy_store.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/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/traffic_selector.c config/traffic_selector.h \
|
||||||
config/proposal.c config/proposal.h config/configuration.c config/configuration.h \
|
control/controller.c control/controller.h \
|
||||||
sa/authenticators/eap_authenticator.h sa/authenticators/eap_authenticator.c \
|
control/stroke_interface.c control/stroke_interface.h \
|
||||||
sa/authenticators/eap/eap_method.h sa/authenticators/eap/eap_method.c \
|
daemon.c daemon.h \
|
||||||
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 \
|
encoding/generator.c encoding/generator.h \
|
||||||
sa/ike_sa_id.c sa/ike_sa_id.h sa/tasks/task.c sa/tasks/task.h \
|
encoding/message.c encoding/message.h \
|
||||||
sa/tasks/ike_init.c sa/tasks/ike_init.h \
|
encoding/parser.c encoding/parser.h \
|
||||||
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
|
encoding/payloads/auth_payload.c encoding/payloads/auth_payload.h \
|
||||||
sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
|
encoding/payloads/cert_payload.c encoding/payloads/cert_payload.h \
|
||||||
sa/tasks/ike_config.c sa/tasks/ike_config.h \
|
encoding/payloads/certreq_payload.c encoding/payloads/certreq_payload.h \
|
||||||
sa/tasks/ike_cert.c sa/tasks/ike_cert.h \
|
encoding/payloads/configuration_attribute.c encoding/payloads/configuration_attribute.h \
|
||||||
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
|
encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
|
||||||
sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
|
encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
|
||||||
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.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_create.c sa/tasks/child_create.h \
|
||||||
sa/tasks/child_delete.c sa/tasks/child_delete.h \
|
sa/tasks/child_delete.c sa/tasks/child_delete.h \
|
||||||
sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
|
sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
|
||||||
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
|
sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
|
||||||
sa/authenticators/rsa_authenticator.c sa/authenticators/rsa_authenticator.h \
|
sa/tasks/ike_cert.c sa/tasks/ike_cert.h \
|
||||||
sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
|
sa/tasks/ike_config.c sa/tasks/ike_config.h \
|
||||||
sa/task_manager.c sa/task_manager.h encoding/payloads/encryption_payload.c \
|
sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
|
||||||
encoding/payloads/cert_payload.c encoding/payloads/payload.h encoding/payloads/traffic_selector_substructure.c \
|
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
|
||||||
encoding/payloads/configuration_attribute.h encoding/payloads/proposal_substructure.h \
|
sa/tasks/ike_init.c sa/tasks/ike_init.h \
|
||||||
encoding/payloads/transform_attribute.c encoding/payloads/transform_attribute.h \
|
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
|
||||||
encoding/payloads/configuration_attribute.c encoding/payloads/transform_substructure.c \
|
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
|
||||||
encoding/payloads/encryption_payload.h encoding/payloads/auth_payload.c encoding/payloads/ike_header.c \
|
sa/tasks/task.c sa/tasks/task.h
|
||||||
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
|
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke
|
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}\"
|
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)
|
const void *const *args)
|
||||||
{
|
{
|
||||||
private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
|
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 addr_str[INET6_ADDRSTRLEN] = "";
|
||||||
char *serv_proto = NULL;
|
char *serv_proto = NULL;
|
||||||
u_int8_t mask;
|
u_int8_t mask;
|
||||||
|
@ -179,6 +181,24 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||||
return fprintf(stream, "(null)");
|
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)
|
if (this->type == TS_IPV4_ADDR_RANGE)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
|
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
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
@ -40,23 +40,23 @@
|
||||||
#include <crypto/x509.h>
|
#include <crypto/x509.h>
|
||||||
#include <crypto/ca.h>
|
#include <crypto/ca.h>
|
||||||
#include <crypto/crl.h>
|
#include <crypto/crl.h>
|
||||||
#include <queues/jobs/initiate_job.h>
|
#include <processing/jobs/initiate_job.h>
|
||||||
#include <queues/jobs/route_job.h>
|
#include <processing/jobs/route_job.h>
|
||||||
#include <utils/leak_detective.h>
|
#include <utils/leak_detective.h>
|
||||||
|
|
||||||
#define IKE_PORT 500
|
#define IKE_PORT 500
|
||||||
#define PATH_BUF 256
|
#define PATH_BUF 256
|
||||||
|
#define STROKE_THREADS 3
|
||||||
|
|
||||||
struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
|
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.
|
* Private data of an stroke_t object.
|
||||||
*/
|
*/
|
||||||
struct private_stroke_t {
|
struct private_stroke_interface_t {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public part of stroke_t object.
|
* Public part of stroke_t object.
|
||||||
|
@ -64,9 +64,9 @@ struct private_stroke_t {
|
||||||
stroke_t public;
|
stroke_t public;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output stream (stroke console)
|
* backend to store configurations
|
||||||
*/
|
*/
|
||||||
FILE *out;
|
local_backend_t *backend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix socket to listen for strokes
|
* Unix socket to listen for strokes
|
||||||
|
@ -76,7 +76,7 @@ struct private_stroke_t {
|
||||||
/**
|
/**
|
||||||
* Thread which reads from the Socket
|
* 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
|
* 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;
|
ike_cfg_t *ike_cfg;
|
||||||
policy_t *policy;
|
peer_cfg_t *peer_cfg;
|
||||||
|
child_cfg_t *child_cfg;
|
||||||
identification_t *my_id, *other_id;
|
identification_t *my_id, *other_id;
|
||||||
identification_t *my_ca = NULL;
|
identification_t *my_ca = NULL;
|
||||||
identification_t *other_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;
|
proposal_t *proposal;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
char *interface;
|
char *interface;
|
||||||
|
bool use_existing = FALSE;
|
||||||
|
iterator_t *iterator;
|
||||||
|
|
||||||
pop_string(msg, &msg->add_conn.name);
|
pop_string(msg, &msg->add_conn.name);
|
||||||
pop_string(msg, &msg->add_conn.me.address);
|
pop_string(msg, &msg->add_conn.me.address);
|
||||||
|
@ -421,67 +425,102 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||||
DBG2(DBG_CFG, " other ca:'%D'", other_ca);
|
DBG2(DBG_CFG, " other ca:'%D'", other_ca);
|
||||||
DBG2(DBG_CFG, " updown: '%s'", msg->add_conn.me.updown);
|
DBG2(DBG_CFG, " updown: '%s'", msg->add_conn.me.updown);
|
||||||
|
|
||||||
connection = connection_create(msg->add_conn.name,
|
/* have a look for an (almost) identical peer config to reuse */
|
||||||
msg->add_conn.ikev2,
|
iterator = this->backend->create_peer_cfg_iterator(this->backend);
|
||||||
msg->add_conn.me.sendcert,
|
while (iterator->iterate(iterator, (void**)&peer_cfg))
|
||||||
msg->add_conn.other.sendcert,
|
|
||||||
my_host, other_host,
|
|
||||||
msg->add_conn.dpd.delay,
|
|
||||||
msg->add_conn.rekey.reauth,
|
|
||||||
msg->add_conn.rekey.tries,
|
|
||||||
msg->add_conn.rekey.ike_lifetime,
|
|
||||||
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
|
|
||||||
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
|
|
||||||
|
|
||||||
if (msg->add_conn.algorithms.ike)
|
|
||||||
{
|
{
|
||||||
char *proposal_string;
|
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
|
||||||
char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
|
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)) &&
|
||||||
if (*strict == '!')
|
my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg)) &&
|
||||||
*strict = '\0';
|
other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg)) &&
|
||||||
else
|
peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) &&
|
||||||
strict = NULL;
|
peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method &&
|
||||||
|
peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
|
||||||
while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
|
|
||||||
{
|
{
|
||||||
proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
|
DBG1(DBG_CFG, "reusing existing configuration '%s'",
|
||||||
if (proposal == NULL)
|
peer_cfg->get_name(peer_cfg));
|
||||||
{
|
use_existing = TRUE;
|
||||||
DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
|
break;
|
||||||
my_id->destroy(my_id);
|
|
||||||
other_id->destroy(other_id);
|
|
||||||
my_ts->destroy(my_ts);
|
|
||||||
other_ts->destroy(other_ts);
|
|
||||||
my_ca->destroy(my_ca);
|
|
||||||
other_ca->destroy(other_ca);
|
|
||||||
connection->destroy(connection);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
connection->add_proposal(connection, proposal);
|
|
||||||
}
|
|
||||||
if (!strict)
|
|
||||||
{
|
|
||||||
proposal = proposal_create_default(PROTO_IKE);
|
|
||||||
connection->add_proposal(connection, proposal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
proposal = proposal_create_default(PROTO_IKE);
|
ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
|
||||||
connection->add_proposal(connection, proposal);
|
my_host, other_host);
|
||||||
|
|
||||||
|
if (msg->add_conn.algorithms.ike)
|
||||||
|
{
|
||||||
|
char *proposal_string;
|
||||||
|
char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
|
||||||
|
|
||||||
|
if (*strict == '!')
|
||||||
|
*strict = '\0';
|
||||||
|
else
|
||||||
|
strict = NULL;
|
||||||
|
|
||||||
|
while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
|
||||||
|
{
|
||||||
|
proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
|
||||||
|
if (proposal == NULL)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
|
||||||
|
my_id->destroy(my_id);
|
||||||
|
other_id->destroy(other_id);
|
||||||
|
my_ts->destroy(my_ts);
|
||||||
|
other_ts->destroy(other_ts);
|
||||||
|
my_ca->destroy(my_ca);
|
||||||
|
other_ca->destroy(other_ca);
|
||||||
|
ike_cfg->destroy(ike_cfg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||||
|
}
|
||||||
|
if (!strict)
|
||||||
|
{
|
||||||
|
proposal = proposal_create_default(PROTO_IKE);
|
||||||
|
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proposal = proposal_create_default(PROTO_IKE);
|
||||||
|
ike_cfg->add_proposal(ike_cfg, proposal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
|
||||||
|
ike_cfg, my_id, other_id, my_ca, other_ca, msg->add_conn.me.sendcert,
|
||||||
|
msg->add_conn.auth_method, msg->add_conn.eap_type,
|
||||||
|
msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
|
||||||
|
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
|
||||||
|
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
|
||||||
|
msg->add_conn.rekey.reauth, msg->add_conn.dpd.delay,
|
||||||
|
msg->add_conn.dpd.action,my_vip, other_vip);
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = policy_create(msg->add_conn.name, my_id, other_id, my_vip, other_vip,
|
child_cfg = child_cfg_create(
|
||||||
msg->add_conn.auth_method, msg->add_conn.eap_type,
|
msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
|
||||||
msg->add_conn.rekey.ipsec_lifetime,
|
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
|
||||||
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.rekey.margin * msg->add_conn.rekey.fuzz / 100,
|
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
|
||||||
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
|
msg->add_conn.mode);
|
||||||
msg->add_conn.mode, msg->add_conn.dpd.action);
|
|
||||||
policy->add_my_traffic_selector(policy, my_ts);
|
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
|
||||||
policy->add_other_traffic_selector(policy, other_ts);
|
|
||||||
policy->add_authorities(policy, my_ca, other_ca);
|
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)
|
if (msg->add_conn.algorithms.esp)
|
||||||
{
|
{
|
||||||
|
@ -499,31 +538,30 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||||
if (proposal == NULL)
|
if (proposal == NULL)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
|
DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
|
||||||
policy->destroy(policy);
|
peer_cfg->destroy(peer_cfg);
|
||||||
connection->destroy(connection);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
policy->add_proposal(policy, proposal);
|
child_cfg->add_proposal(child_cfg, proposal);
|
||||||
}
|
}
|
||||||
if (!strict)
|
if (!strict)
|
||||||
{
|
{
|
||||||
proposal = proposal_create_default(PROTO_ESP);
|
proposal = proposal_create_default(PROTO_ESP);
|
||||||
policy->add_proposal(policy, proposal);
|
child_cfg->add_proposal(child_cfg, proposal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
proposal = proposal_create_default(PROTO_ESP);
|
proposal = proposal_create_default(PROTO_ESP);
|
||||||
policy->add_proposal(policy, proposal);
|
child_cfg->add_proposal(child_cfg, proposal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add to global connection list */
|
if (!use_existing)
|
||||||
charon->connections->add_connection(charon->connections, connection);
|
{
|
||||||
DBG1(DBG_CFG, "added connection '%s': %H[%D]...%H[%D]",
|
/* add config to backend */
|
||||||
msg->add_conn.name, my_host, my_id, other_host, other_id);
|
this->backend->add_peer_cfg(this->backend, peer_cfg);
|
||||||
/* add to global policy list */
|
DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]",
|
||||||
charon->policies->add_policy(charon->policies, policy);
|
msg->add_conn.name, my_host, my_id, other_host, other_id);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* mopping up after parsing errors */
|
/* mopping up after parsing errors */
|
||||||
|
@ -540,69 +578,109 @@ destroy_hosts:
|
||||||
/**
|
/**
|
||||||
* Delete a connection from the list
|
* 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));
|
pop_string(msg, &(msg->del_conn.name));
|
||||||
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
|
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
|
||||||
|
|
||||||
status = charon->connections->delete_connection(charon->connections,
|
peer_iter = this->backend->create_peer_cfg_iterator(this->backend);
|
||||||
msg->del_conn.name);
|
while (peer_iter->iterate(peer_iter, (void**)&peer))
|
||||||
charon->policies->delete_policy(charon->policies, msg->del_conn.name);
|
|
||||||
if (status == SUCCESS)
|
|
||||||
{
|
{
|
||||||
fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
|
/* remove peer config with such a name */
|
||||||
|
if (streq(peer->get_name(peer), msg->del_conn.name))
|
||||||
|
{
|
||||||
|
peer_iter->remove(peer_iter);
|
||||||
|
peer->destroy(peer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* remove any child with such a name */
|
||||||
|
child_iter = peer->create_child_cfg_iterator(peer);
|
||||||
|
while (child_iter->iterate(child_iter, (void**)&child))
|
||||||
|
{
|
||||||
|
if (streq(child->get_name(child), msg->del_conn.name))
|
||||||
|
{
|
||||||
|
child_iter->remove(child_iter);
|
||||||
|
child->destroy(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child_iter->destroy(child_iter);
|
||||||
}
|
}
|
||||||
else
|
peer_iter->destroy(peer_iter);
|
||||||
|
|
||||||
|
fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the child_cfg with the same name as the peer cfg
|
||||||
|
*/
|
||||||
|
static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg)
|
||||||
|
{
|
||||||
|
child_cfg_t *current, *found = NULL;
|
||||||
|
iterator_t *iterator;
|
||||||
|
|
||||||
|
iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
|
||||||
|
while (iterator->iterate(iterator, (void**)¤t))
|
||||||
{
|
{
|
||||||
fprintf(out, "no connection named '%s'\n", msg->del_conn.name);
|
if (streq(current->get_name(current), peer_cfg->get_name(peer_cfg)))
|
||||||
|
{
|
||||||
|
found = current;
|
||||||
|
found->get_ref(found);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initiate a connection by name
|
* 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;
|
initiate_job_t *job;
|
||||||
connection_t *connection;
|
peer_cfg_t *peer_cfg;
|
||||||
policy_t *policy;
|
child_cfg_t *child_cfg;
|
||||||
ike_sa_t *init_ike_sa = NULL;
|
ike_sa_t *init_ike_sa = NULL;
|
||||||
signal_t signal;
|
signal_t signal;
|
||||||
|
|
||||||
pop_string(msg, &(msg->initiate.name));
|
pop_string(msg, &(msg->initiate.name));
|
||||||
DBG1(DBG_CFG, "received stroke: initiate '%s'", 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);
|
msg->initiate.name);
|
||||||
if (connection == NULL)
|
if (peer_cfg == NULL)
|
||||||
{
|
{
|
||||||
if (msg->output_verbosity >= 0)
|
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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = charon->policies->get_policy_by_name(charon->policies,
|
child_cfg = get_child_from_peer(peer_cfg);
|
||||||
msg->initiate.name);
|
if (child_cfg == NULL)
|
||||||
if (policy == NULL)
|
|
||||||
{
|
{
|
||||||
if (msg->output_verbosity >= 0)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
job = initiate_job_create(connection, policy);
|
job = initiate_job_create(peer_cfg, child_cfg);
|
||||||
charon->bus->set_listen_state(charon->bus, TRUE);
|
charon->bus->set_listen_state(charon->bus, TRUE);
|
||||||
charon->job_queue->add(charon->job_queue, (job_t*)job);
|
charon->job_queue->add(charon->job_queue, (job_t*)job);
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
|
@ -654,49 +732,48 @@ static void stroke_initiate(stroke_msg_t *msg, FILE *out)
|
||||||
/**
|
/**
|
||||||
* route/unroute a policy (install SPD entries)
|
* 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;
|
route_job_t *job;
|
||||||
connection_t *connection;
|
peer_cfg_t *peer_cfg;
|
||||||
policy_t *policy;
|
child_cfg_t *child_cfg;
|
||||||
|
|
||||||
pop_string(msg, &(msg->route.name));
|
pop_string(msg, &(msg->route.name));
|
||||||
DBG1(DBG_CFG, "received stroke: %s '%s'",
|
DBG1(DBG_CFG, "received stroke: %s '%s'",
|
||||||
route ? "route" : "unroute", msg->route.name);
|
route ? "route" : "unroute", msg->route.name);
|
||||||
|
|
||||||
/* we wouldn't need a connection, but we only want to route policies
|
peer_cfg = charon->cfg_store->get_peer_cfg_by_name(charon->cfg_store,
|
||||||
* whose connections are keyexchange=ikev2. */
|
msg->route.name);
|
||||||
connection = charon->connections->get_connection_by_name(charon->connections,
|
if (peer_cfg == NULL)
|
||||||
msg->route.name);
|
|
||||||
if (connection == NULL)
|
|
||||||
{
|
{
|
||||||
fprintf(out, "no connection named '%s'\n", msg->route.name);
|
fprintf(out, "no config named '%s'\n", msg->route.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!connection->is_ikev2(connection))
|
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||||
{
|
{
|
||||||
connection->destroy(connection);
|
peer_cfg->destroy(peer_cfg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = charon->policies->get_policy_by_name(charon->policies,
|
child_cfg = get_child_from_peer(peer_cfg);
|
||||||
msg->route.name);
|
if (child_cfg == NULL)
|
||||||
if (policy == NULL)
|
|
||||||
{
|
{
|
||||||
fprintf(out, "no policy named '%s'\n", msg->route.name);
|
fprintf(out, "no child config named '%s'\n", msg->route.name);
|
||||||
connection->destroy(connection);
|
peer_cfg->destroy(peer_cfg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf(out, "%s policy '%s'\n",
|
fprintf(out, "%s policy '%s'\n",
|
||||||
route ? "routing" : "unrouting", msg->route.name);
|
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);
|
charon->job_queue->add(charon->job_queue, (job_t*)job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* terminate a connection by name
|
* 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;
|
char *string, *pos = NULL, *name = NULL;
|
||||||
u_int32_t id = 0;
|
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
|
* 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;
|
x509_t *cacert;
|
||||||
ca_info_t *ca_info;
|
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
|
* 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;
|
status_t status;
|
||||||
|
|
||||||
|
@ -887,13 +966,15 @@ static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
|
||||||
/**
|
/**
|
||||||
* show status of daemon
|
* 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;
|
linked_list_t *list;
|
||||||
host_t *host;
|
host_t *host;
|
||||||
connection_t *connection;
|
peer_cfg_t *peer_cfg;
|
||||||
policy_t *policy;
|
ike_cfg_t *ike_cfg;
|
||||||
|
child_cfg_t *child_cfg;
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
|
|
||||||
|
@ -923,40 +1004,35 @@ static void stroke_statusall(stroke_msg_t *msg, FILE *out)
|
||||||
name = msg->status.name;
|
name = msg->status.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator = charon->connections->create_iterator(charon->connections);
|
fprintf(out, "Connections:\n");
|
||||||
if (iterator->get_count(iterator) > 0)
|
iterator = this->backend->create_peer_cfg_iterator(this->backend);
|
||||||
|
while (iterator->iterate(iterator, (void**)&peer_cfg))
|
||||||
{
|
{
|
||||||
fprintf(out, "Connections:\n");
|
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
|
||||||
}
|
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
|
||||||
while (iterator->iterate(iterator, (void**)&connection))
|
|
||||||
{
|
|
||||||
if (connection->is_ikev2(connection)
|
|
||||||
&& (name == NULL || streq(name, connection->get_name(connection))))
|
|
||||||
{
|
{
|
||||||
fprintf(out, "%12s: %H...%H\n",
|
continue;
|
||||||
connection->get_name(connection),
|
|
||||||
connection->get_my_host(connection),
|
|
||||||
connection->get_other_host(connection));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->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);
|
iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
|
||||||
if (iterator->get_count(iterator) > 0)
|
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);
|
iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
|
||||||
|
|
||||||
/* print 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);
|
fprintf(out, "%#K\n", ike_sa);
|
||||||
ike_sa_printed = TRUE;
|
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))
|
while (children->iterate(children, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
bool child_sa_match = name == NULL ||
|
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 */
|
/* print IKE_SA if its name differs from the CHILD_SA's name */
|
||||||
if (!ike_sa_printed && child_sa_match)
|
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
|
* 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;
|
iterator_t *iterator;
|
||||||
ike_sa_t *ike_sa;
|
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);
|
iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
|
||||||
|
|
||||||
/* print 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);
|
fprintf(out, "%K\n", ike_sa);
|
||||||
ike_sa_printed = TRUE;
|
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))
|
while (children->iterate(children, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
bool child_sa_match = name == NULL ||
|
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 */
|
/* print IKE_SA if its name differs from the CHILD_SA's name */
|
||||||
if (!ike_sa_printed && child_sa_match)
|
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
|
* 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;
|
bool first = TRUE;
|
||||||
x509_t *cert;
|
x509_t *cert;
|
||||||
|
@ -1081,7 +1159,8 @@ static void list_auth_certificates(u_int flag, const char *label, bool utc, FILE
|
||||||
/**
|
/**
|
||||||
* list various information
|
* 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;
|
iterator_t *iterator;
|
||||||
|
|
||||||
|
@ -1111,7 +1190,7 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
||||||
}
|
}
|
||||||
if (msg->list.flags & LIST_CACERTS)
|
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)
|
if (msg->list.flags & LIST_CAINFOS)
|
||||||
{
|
{
|
||||||
|
@ -1132,60 +1211,59 @@ static void stroke_list(stroke_msg_t *msg, FILE *out)
|
||||||
}
|
}
|
||||||
if (msg->list.flags & LIST_CRLS)
|
if (msg->list.flags & LIST_CRLS)
|
||||||
{
|
{
|
||||||
ca_info_t *ca_info;
|
ca_info_t *ca_info;
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
|
|
||||||
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
|
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
|
||||||
|
while (iterator->iterate(iterator, (void **)&ca_info))
|
||||||
while (iterator->iterate(iterator, (void **)&ca_info))
|
{
|
||||||
{
|
if (ca_info->has_crl(ca_info))
|
||||||
if (ca_info->has_crl(ca_info))
|
{
|
||||||
{
|
if (first)
|
||||||
if (first)
|
{
|
||||||
{
|
fprintf(out, "\n");
|
||||||
fprintf(out, "\n");
|
fprintf(out, "List of X.509 CRLs:\n");
|
||||||
fprintf(out, "List of X.509 CRLs:\n");
|
fprintf(out, "\n");
|
||||||
fprintf(out, "\n");
|
first = FALSE;
|
||||||
first = FALSE;
|
}
|
||||||
}
|
ca_info->list_crl(ca_info, out, msg->list.utc);
|
||||||
ca_info->list_crl(ca_info, out, msg->list.utc);
|
}
|
||||||
}
|
}
|
||||||
}
|
iterator->destroy(iterator);
|
||||||
iterator->destroy(iterator);
|
|
||||||
}
|
}
|
||||||
if (msg->list.flags & LIST_OCSPCERTS)
|
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)
|
if (msg->list.flags & LIST_OCSP)
|
||||||
{
|
{
|
||||||
ca_info_t *ca_info;
|
ca_info_t *ca_info;
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
|
|
||||||
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
|
iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
|
||||||
|
while (iterator->iterate(iterator, (void **)&ca_info))
|
||||||
while (iterator->iterate(iterator, (void **)&ca_info))
|
{
|
||||||
{
|
if (ca_info->has_certinfos(ca_info))
|
||||||
if (ca_info->has_certinfos(ca_info))
|
{
|
||||||
{
|
if (first)
|
||||||
if (first)
|
{
|
||||||
{
|
fprintf(out, "\n");
|
||||||
fprintf(out, "\n");
|
fprintf(out, "List of OCSP responses:\n");
|
||||||
fprintf(out, "List of OCSP responses:\n");
|
first = FALSE;
|
||||||
first = FALSE;
|
}
|
||||||
}
|
fprintf(out, "\n");
|
||||||
fprintf(out, "\n");
|
ca_info->list_certinfos(ca_info, out, msg->list.utc);
|
||||||
ca_info->list_certinfos(ca_info, out, msg->list.utc);
|
}
|
||||||
}
|
}
|
||||||
}
|
iterator->destroy(iterator);
|
||||||
iterator->destroy(iterator);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reread various information
|
* 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)
|
if (msg->reread.flags & REREAD_CACERTS)
|
||||||
{
|
{
|
||||||
|
@ -1204,7 +1282,8 @@ static void stroke_reread(stroke_msg_t *msg, FILE *out)
|
||||||
/**
|
/**
|
||||||
* purge various information
|
* 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)
|
if (msg->purge.flags & PURGE_OCSP)
|
||||||
{
|
{
|
||||||
|
@ -1237,7 +1316,8 @@ signal_t get_signal_from_logtype(char *type)
|
||||||
/**
|
/**
|
||||||
* set the verbosity debug output
|
* 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;
|
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"
|
* 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;
|
stroke_msg_t *msg;
|
||||||
u_int16_t msg_length;
|
u_int16_t msg_length;
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
int strokefd = *fd;
|
|
||||||
|
|
||||||
/* peek the length */
|
/* peek the length */
|
||||||
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
|
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
|
||||||
|
@ -1300,46 +1379,46 @@ static void stroke_process(int *fd)
|
||||||
switch (msg->type)
|
switch (msg->type)
|
||||||
{
|
{
|
||||||
case STR_INITIATE:
|
case STR_INITIATE:
|
||||||
stroke_initiate(msg, out);
|
stroke_initiate(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_ROUTE:
|
case STR_ROUTE:
|
||||||
stroke_route(msg, out, TRUE);
|
stroke_route(this, msg, out, TRUE);
|
||||||
break;
|
break;
|
||||||
case STR_UNROUTE:
|
case STR_UNROUTE:
|
||||||
stroke_route(msg, out, FALSE);
|
stroke_route(this, msg, out, FALSE);
|
||||||
break;
|
break;
|
||||||
case STR_TERMINATE:
|
case STR_TERMINATE:
|
||||||
stroke_terminate(msg, out);
|
stroke_terminate(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_STATUS:
|
case STR_STATUS:
|
||||||
stroke_status(msg, out);
|
stroke_status(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_STATUS_ALL:
|
case STR_STATUS_ALL:
|
||||||
stroke_statusall(msg, out);
|
stroke_statusall(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_ADD_CONN:
|
case STR_ADD_CONN:
|
||||||
stroke_add_conn(msg, out);
|
stroke_add_conn(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_DEL_CONN:
|
case STR_DEL_CONN:
|
||||||
stroke_del_conn(msg, out);
|
stroke_del_conn(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_ADD_CA:
|
case STR_ADD_CA:
|
||||||
stroke_add_ca(msg, out);
|
stroke_add_ca(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_DEL_CA:
|
case STR_DEL_CA:
|
||||||
stroke_del_ca(msg, out);
|
stroke_del_ca(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_LOGLEVEL:
|
case STR_LOGLEVEL:
|
||||||
stroke_loglevel(msg, out);
|
stroke_loglevel(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_LIST:
|
case STR_LIST:
|
||||||
stroke_list(msg, out);
|
stroke_list(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_REREAD:
|
case STR_REREAD:
|
||||||
stroke_reread(msg, out);
|
stroke_reread(this, msg, out);
|
||||||
break;
|
break;
|
||||||
case STR_PURGE:
|
case STR_PURGE:
|
||||||
stroke_purge(msg, out);
|
stroke_purge(this, msg, out);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBG1(DBG_CFG, "received unknown stroke");
|
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;
|
struct sockaddr_un strokeaddr;
|
||||||
int strokeaddrlen = sizeof(strokeaddr);
|
int strokeaddrlen = sizeof(strokeaddr);
|
||||||
int strokefd;
|
|
||||||
int oldstate;
|
int oldstate;
|
||||||
pthread_t thread;
|
int strokefd;
|
||||||
|
|
||||||
/* ignore sigpipe. writing over the pipe back to the console
|
/* ignore sigpipe. writing over the pipe back to the console
|
||||||
* only fails if SIGPIPE is ignored. */
|
* 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");
|
DBG1(DBG_CFG, "accepting stroke connection failed: %m");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
stroke_process(this, strokefd);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of stroke_t.destroy.
|
* 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);
|
int i;
|
||||||
pthread_join(this->assigned_thread, NULL);
|
|
||||||
|
for (i = 0; i < STROKE_THREADS; i++)
|
||||||
|
{
|
||||||
|
pthread_cancel(this->threads[i]);
|
||||||
|
pthread_join(this->threads[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
close(this->socket);
|
close(this->socket);
|
||||||
unlink(socket_addr.sun_path);
|
unlink(socket_addr.sun_path);
|
||||||
|
@ -1406,14 +1482,17 @@ static void destroy(private_stroke_t *this)
|
||||||
/*
|
/*
|
||||||
* Described in header-file
|
* 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;
|
mode_t old;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
this->public.destroy = (void (*)(stroke_t*))destroy;
|
this->public.destroy = (void (*)(stroke_t*))destroy;
|
||||||
|
|
||||||
|
this->backend = backend;
|
||||||
|
|
||||||
/* set up unix socket */
|
/* set up unix socket */
|
||||||
this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (this->socket == -1)
|
if (this->socket == -1)
|
||||||
|
@ -1442,14 +1521,13 @@ stroke_t *stroke_create()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start a thread reading from the socket */
|
/* start threads reading from the socket */
|
||||||
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))stroke_receive, this) != 0)
|
for (i = 0; i < STROKE_THREADS; i++)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "could not spawn stroke thread");
|
if (pthread_create(&this->threads[i], NULL, (void*(*)(void*))stroke_receive, this) != 0)
|
||||||
close(this->socket);
|
{
|
||||||
unlink(socket_addr.sun_path);
|
charon->kill(charon, "unable to create stroke thread");
|
||||||
free(this);
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (&this->public);
|
return (&this->public);
|
|
@ -25,11 +25,14 @@
|
||||||
|
|
||||||
typedef struct stroke_t stroke_t;
|
typedef struct stroke_t stroke_t;
|
||||||
|
|
||||||
|
#include <config/backends/local_backend.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stroke is a configuration and control interface which
|
* @brief Stroke is a configuration and control interface which
|
||||||
* allows other processes to modify charons behavior.
|
* 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
|
* Messages of type stroke_msg_t's are sent over a unix socket
|
||||||
* (/var/run/charon.ctl).
|
* (/var/run/charon.ctl).
|
||||||
*
|
*
|
||||||
|
@ -52,10 +55,11 @@ struct stroke_t {
|
||||||
/**
|
/**
|
||||||
* @brief Create the stroke interface and listen on the socket.
|
* @brief Create the stroke interface and listen on the socket.
|
||||||
*
|
*
|
||||||
* @return stroke_t object
|
* @param backend backend to store received configurations
|
||||||
|
* @return stroke_t object
|
||||||
*
|
*
|
||||||
* @ingroup threads
|
* @ingroup threads
|
||||||
*/
|
*/
|
||||||
stroke_t *stroke_create(void);
|
stroke_t *stroke_create(local_backend_t *backend);
|
||||||
|
|
||||||
#endif /* STROKE_INTERFACE_H_ */
|
#endif /* STROKE_INTERFACE_H_ */
|
|
@ -42,8 +42,7 @@
|
||||||
#include <crypto/ca.h>
|
#include <crypto/ca.h>
|
||||||
#include <utils/fetcher.h>
|
#include <utils/fetcher.h>
|
||||||
#include <config/credentials/local_credential_store.h>
|
#include <config/credentials/local_credential_store.h>
|
||||||
#include <config/connections/local_connection_store.h>
|
#include <config/backends/local_backend.h>
|
||||||
#include <config/policies/local_policy_store.h>
|
|
||||||
#include <sa/authenticators/eap/eap_method.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.event_queue);
|
||||||
DESTROY_IF(this->public.configuration);
|
DESTROY_IF(this->public.configuration);
|
||||||
DESTROY_IF(this->public.credentials);
|
DESTROY_IF(this->public.credentials);
|
||||||
DESTROY_IF(this->public.connections);
|
DESTROY_IF(this->public.cfg_store);
|
||||||
DESTROY_IF(this->public.policies);
|
DESTROY_IF(this->public.local_backend);
|
||||||
sched_yield();
|
sched_yield();
|
||||||
/* we hope the sender could send the outstanding deletes, but
|
/* we hope the sender could send the outstanding deletes, but
|
||||||
* we shut down here at any cost */
|
* 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.ike_sa_manager = ike_sa_manager_create();
|
||||||
this->public.job_queue = job_queue_create();
|
this->public.job_queue = job_queue_create();
|
||||||
this->public.event_queue = event_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.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 */
|
/* initialize fetcher_t class */
|
||||||
fetcher_initialize();
|
fetcher_initialize();
|
||||||
|
@ -279,7 +280,7 @@ static void initialize(private_daemon_t *this, bool strict, bool syslog,
|
||||||
credentials->load_secrets(credentials);
|
credentials->load_secrets(credentials);
|
||||||
|
|
||||||
/* start building threads, we are multi-threaded NOW */
|
/* 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.sender = sender_create();
|
||||||
this->public.receiver = receiver_create();
|
this->public.receiver = receiver_create();
|
||||||
this->public.scheduler = scheduler_create();
|
this->public.scheduler = scheduler_create();
|
||||||
|
@ -335,8 +336,8 @@ private_daemon_t *daemon_create(void)
|
||||||
this->public.event_queue = NULL;
|
this->public.event_queue = NULL;
|
||||||
this->public.configuration = NULL;
|
this->public.configuration = NULL;
|
||||||
this->public.credentials = NULL;
|
this->public.credentials = NULL;
|
||||||
this->public.connections = NULL;
|
this->public.cfg_store = NULL;
|
||||||
this->public.policies = NULL;
|
this->public.local_backend = NULL;
|
||||||
this->public.sender= NULL;
|
this->public.sender= NULL;
|
||||||
this->public.receiver = NULL;
|
this->public.receiver = NULL;
|
||||||
this->public.scheduler = NULL;
|
this->public.scheduler = NULL;
|
||||||
|
|
|
@ -29,22 +29,21 @@ typedef struct daemon_t daemon_t;
|
||||||
|
|
||||||
#include <credential_store.h>
|
#include <credential_store.h>
|
||||||
|
|
||||||
#include <threads/sender.h>
|
#include <network/sender.h>
|
||||||
#include <threads/receiver.h>
|
#include <network/receiver.h>
|
||||||
#include <threads/scheduler.h>
|
|
||||||
#include <threads/kernel_interface.h>
|
|
||||||
#include <threads/thread_pool.h>
|
|
||||||
#include <threads/stroke_interface.h>
|
|
||||||
#include <network/socket.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/bus.h>
|
||||||
#include <bus/listeners/file_logger.h>
|
#include <bus/listeners/file_logger.h>
|
||||||
#include <bus/listeners/sys_logger.h>
|
#include <bus/listeners/sys_logger.h>
|
||||||
#include <sa/ike_sa_manager.h>
|
#include <sa/ike_sa_manager.h>
|
||||||
#include <queues/job_queue.h>
|
#include <config/cfg_store.h>
|
||||||
#include <queues/event_queue.h>
|
#include <config/backends/local_backend.h>
|
||||||
#include <config/configuration.h>
|
|
||||||
#include <config/connections/connection_store.h>
|
|
||||||
#include <config/policies/policy_store.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup charon charon
|
* @defgroup charon charon
|
||||||
|
@ -324,12 +323,12 @@ struct daemon_t {
|
||||||
/**
|
/**
|
||||||
* A connection_store_t instance.
|
* 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.
|
* A credential_store_t instance.
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
#include <queues/jobs/delete_child_sa_job.h>
|
#include <processing/jobs/delete_child_sa_job.h>
|
||||||
#include <queues/jobs/rekey_child_sa_job.h>
|
#include <processing/jobs/rekey_child_sa_job.h>
|
||||||
#include <queues/jobs/acquire_job.h>
|
#include <processing/jobs/acquire_job.h>
|
||||||
|
|
||||||
/** kernel level protocol identifiers */
|
/** kernel level protocol identifiers */
|
||||||
#define KERNEL_ESP 50
|
#define KERNEL_ESP 50
|
|
@ -29,9 +29,9 @@
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <network/socket.h>
|
#include <network/socket.h>
|
||||||
#include <network/packet.h>
|
#include <network/packet.h>
|
||||||
#include <queues/job_queue.h>
|
#include <processing/job_queue.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <queues/jobs/process_message_job.h>
|
#include <processing/jobs/process_message_job.h>
|
||||||
|
|
||||||
/** length of the full cookie, including time (u_int32_t + SHA1()) */
|
/** length of the full cookie, including time (u_int32_t + SHA1()) */
|
||||||
#define COOKIE_LENGTH 24
|
#define COOKIE_LENGTH 24
|
|
@ -29,7 +29,7 @@ typedef struct event_queue_t event_queue_t;
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Event-Queue used to store timed events.
|
* @brief Event-Queue used to store timed events.
|
|
@ -27,7 +27,7 @@
|
||||||
typedef struct job_queue_t job_queue_t;
|
typedef struct job_queue_t job_queue_t;
|
||||||
|
|
||||||
#include <library.h>
|
#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.
|
* @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;
|
typedef struct acquire_job_t acquire_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class representing an ACQUIRE Job.
|
* @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 <library.h>
|
||||||
#include <sa/ike_sa_id.h>
|
#include <sa/ike_sa_id.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/proposal.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 <library.h>
|
||||||
#include <sa/ike_sa_id.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
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
|
@ -40,14 +40,14 @@ struct private_initiate_job_t {
|
||||||
initiate_job_t public;
|
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)
|
static status_t execute(private_initiate_job_t *this)
|
||||||
{
|
{
|
||||||
ike_sa_t *ike_sa;
|
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,
|
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
|
||||||
this->connection->get_my_host(this->connection),
|
ike_cfg->get_my_host(ike_cfg),
|
||||||
this->connection->get_other_host(this->connection),
|
ike_cfg->get_other_host(ike_cfg),
|
||||||
this->policy->get_my_id(this->policy),
|
this->peer_cfg->get_my_id(this->peer_cfg),
|
||||||
this->policy->get_other_id(this->policy));
|
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");
|
DBG1(DBG_JOB, "initiation failed, going to delete IKE_SA");
|
||||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, 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)
|
static void destroy(private_initiate_job_t *this)
|
||||||
{
|
{
|
||||||
this->connection->destroy(this->connection);
|
this->peer_cfg->destroy(this->peer_cfg);
|
||||||
this->policy->destroy(this->policy);
|
this->child_cfg->destroy(this->child_cfg);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Described in header
|
* 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);
|
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;
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
|
|
||||||
/* private variables */
|
/* private variables */
|
||||||
this->connection = connection;
|
this->peer_cfg = peer_cfg;
|
||||||
this->policy = policy;
|
this->child_cfg = child_cfg;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2006 Martin Willi
|
* Copyright (C) 2005-2007 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
|
@ -20,15 +20,15 @@
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INITIATE_IKE_SA_JOB_H_
|
#ifndef INITIATE_JOB_H_
|
||||||
#define INITIATE_IKE_SA_JOB_H_
|
#define INITIATE_JOB_H_
|
||||||
|
|
||||||
typedef struct initiate_job_t initiate_job_t;
|
typedef struct initiate_job_t initiate_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/connections/connection.h>
|
#include <config/peer_cfg.h>
|
||||||
#include <config/policies/policy.h>
|
#include <config/child_cfg.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class representing an INITIATE_IKE_SA Job.
|
* @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 peer_cfg peer configuration to use (if not yet established)
|
||||||
* @param policy policy to set up
|
* @param child_cfg config to create a CHILD from
|
||||||
* @return initiate_job_t object
|
* @return initiate_job_t object
|
||||||
*
|
*
|
||||||
* @ingroup jobs
|
* @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 <library.h>
|
||||||
#include <encoding/message.h>
|
#include <encoding/message.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class representing an PROCESS_MESSAGE job.
|
* @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 <library.h>
|
||||||
#include <sa/ike_sa_id.h>
|
#include <sa/ike_sa_id.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/proposal.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 <library.h>
|
||||||
#include <sa/ike_sa_id.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.
|
* @brief Class representing an REKEY_IKE_SA Job.
|
|
@ -27,7 +27,7 @@
|
||||||
typedef struct retransmit_job_t retransmit_job_t;
|
typedef struct retransmit_job_t retransmit_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <sa/ike_sa_id.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
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* 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;
|
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?
|
* 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)
|
static status_t execute(private_route_job_t *this)
|
||||||
{
|
{
|
||||||
ike_sa_t *ike_sa;
|
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,
|
ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
|
||||||
this->connection->get_my_host(this->connection),
|
ike_cfg->get_my_host(ike_cfg),
|
||||||
this->connection->get_other_host(this->connection),
|
ike_cfg->get_other_host(ike_cfg),
|
||||||
this->policy->get_my_id(this->policy),
|
this->peer_cfg->get_my_id(this->peer_cfg),
|
||||||
this->policy->get_other_id(this->policy));
|
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 (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");
|
DBG1(DBG_JOB, "routing failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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");
|
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);
|
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)
|
static void destroy(private_route_job_t *this)
|
||||||
{
|
{
|
||||||
this->connection->destroy(this->connection);
|
this->peer_cfg->destroy(this->peer_cfg);
|
||||||
this->policy->destroy(this->policy);
|
this->child_cfg->destroy(this->child_cfg);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Described in header
|
* 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);
|
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;
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
|
|
||||||
/* private variables */
|
/* private variables */
|
||||||
this->connection = connection;
|
this->peer_cfg = peer_cfg;
|
||||||
this->policy = policy;
|
this->child_cfg = child_cfg;
|
||||||
this->route = route;
|
this->route = route;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2006 Martin Willi
|
* Copyright (C) 2005-2007 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* 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;
|
typedef struct route_job_t route_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/policies/policy.h>
|
#include <config/peer_cfg.h>
|
||||||
#include <config/connections/connection.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class representing an ROUTE Job.
|
* @brief Class representing an ROUTE Job.
|
||||||
|
@ -47,13 +46,14 @@ struct route_job_t {
|
||||||
/**
|
/**
|
||||||
* @brief Creates a job of type ROUTE.
|
* @brief Creates a job of type ROUTE.
|
||||||
*
|
*
|
||||||
* @param connection connection used for routing
|
* @param peer_cfg peer config to use for acquire
|
||||||
* @param policy policy to set up
|
* @param child_cfg route to install
|
||||||
* @param route TRUE to route, FALSE to unroute
|
* @param route TRUE to route, FALSE to unroute
|
||||||
* @return route_job_t object
|
* @return route_job_t object
|
||||||
*
|
*
|
||||||
* @ingroup jobs
|
* @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_*/
|
#endif /*ROUTE_JOB_H_*/
|
|
@ -25,8 +25,7 @@
|
||||||
typedef struct send_dpd_job_t send_dpd_job_t;
|
typedef struct send_dpd_job_t send_dpd_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/connections/connection.h>
|
|
||||||
#include <sa/ike_sa_id.h>
|
#include <sa/ike_sa_id.h>
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -25,8 +25,7 @@
|
||||||
typedef struct send_keepalive_job_t send_keepalive_job_t;
|
typedef struct send_keepalive_job_t send_keepalive_job_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <queues/jobs/job.h>
|
#include <processing/jobs/job.h>
|
||||||
#include <config/connections/connection.h>
|
|
||||||
#include <sa/ike_sa_id.h>
|
#include <sa/ike_sa_id.h>
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -27,7 +27,7 @@
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <queues/job_queue.h>
|
#include <processing/job_queue.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct private_scheduler_t private_scheduler_t;
|
typedef struct private_scheduler_t private_scheduler_t;
|
|
@ -29,7 +29,7 @@
|
||||||
#include "thread_pool.h"
|
#include "thread_pool.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <queues/job_queue.h>
|
#include <processing/job_queue.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct private_thread_pool_t private_thread_pool_t;
|
typedef struct private_thread_pool_t private_thread_pool_t;
|
|
@ -25,7 +25,7 @@
|
||||||
#include "eap_authenticator.h"
|
#include "eap_authenticator.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <config/policies/policy.h>
|
#include <config/peer_cfg.h>
|
||||||
#include <sa/authenticators/eap/eap_method.h>
|
#include <sa/authenticators/eap/eap_method.h>
|
||||||
|
|
||||||
typedef struct private_eap_authenticator_t private_eap_authenticator_t;
|
typedef struct private_eap_authenticator_t private_eap_authenticator_t;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include "psk_authenticator.h"
|
#include "psk_authenticator.h"
|
||||||
|
|
||||||
#include <config/policies/policy.h>
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include "rsa_authenticator.h"
|
#include "rsa_authenticator.h"
|
||||||
|
|
||||||
#include <config/policies/policy.h>
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,9 @@ struct private_child_sa_t {
|
||||||
host_t *virtual_ip;
|
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)
|
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;
|
iterator_t *iterator;
|
||||||
char *script;
|
char *script;
|
||||||
|
|
||||||
script = this->policy->get_updown(this->policy);
|
script = this->config->get_updown(this->config);
|
||||||
|
|
||||||
if (script == NULL)
|
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,
|
policy->my_ts->is_host(policy->my_ts,
|
||||||
this->me.addr) ? "-host" : "-client",
|
this->me.addr) ? "-host" : "-client",
|
||||||
this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-ipv6",
|
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)",
|
ifname ? ifname : "(unknown)",
|
||||||
this->reqid,
|
this->reqid,
|
||||||
this->me.addr,
|
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_from_port(policy->other_ts),
|
||||||
policy->other_ts->get_protocol(policy->other_ts),
|
policy->other_ts->get_protocol(policy->other_ts),
|
||||||
virtual_ip,
|
virtual_ip,
|
||||||
this->policy->get_hostaccess(this->policy) ?
|
this->config->get_hostaccess(this->config) ?
|
||||||
"PLUTO_HOST_ACCESS='1' " : "",
|
"PLUTO_HOST_ACCESS='1' " : "",
|
||||||
script);
|
script);
|
||||||
free(ifname);
|
free(ifname);
|
||||||
|
@ -528,8 +528,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
|
||||||
natt = NULL;
|
natt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
soft = this->policy->get_soft_lifetime(this->policy);
|
soft = this->config->get_lifetime(this->config, TRUE);
|
||||||
hard = this->policy->get_hard_lifetime(this->policy);
|
hard = this->config->get_lifetime(this->config, FALSE);
|
||||||
|
|
||||||
/* send SA down to the kernel */
|
/* send SA down to the kernel */
|
||||||
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
|
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 = malloc_thing(sa_policy_t);
|
||||||
policy->my_ts = my_ts->clone(my_ts);
|
policy->my_ts = my_ts->clone(my_ts);
|
||||||
policy->other_ts = other_ts->clone(other_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() */
|
/* add to separate list to query them via get_*_traffic_selectors() */
|
||||||
this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
|
this->my_ts->insert_last(this->my_ts, policy->my_ts);
|
||||||
this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
|
this->other_ts->insert_last(this->other_ts, policy->other_ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
my_iter->destroy(my_iter);
|
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)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
if (local)
|
||||||
|
{
|
||||||
|
return this->my_ts;
|
||||||
|
}
|
||||||
return this->other_ts;
|
return this->other_ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +758,7 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
|
|
||||||
written += fprintf(stream, "%12s{%d}: %N, %N",
|
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,
|
child_sa_state_names, this->state,
|
||||||
mode_names, this->mode);
|
mode_names, this->mode);
|
||||||
|
|
||||||
|
@ -775,7 +771,7 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||||
if (info->alt)
|
if (info->alt)
|
||||||
{
|
{
|
||||||
written += fprintf(stream, "\n%12s{%d}: ",
|
written += fprintf(stream, "\n%12s{%d}: ",
|
||||||
this->policy->get_name(this->policy),
|
this->config->get_name(this->config),
|
||||||
this->reqid);
|
this->reqid);
|
||||||
|
|
||||||
if (this->protocol == PROTO_ESP)
|
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))
|
while (iterator->iterate(iterator, (void**)&policy))
|
||||||
{
|
{
|
||||||
written += fprintf(stream, "\n%12s{%d}: %R===%R, last use: ",
|
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);
|
policy->my_ts, policy->other_ts);
|
||||||
|
|
||||||
/* query time of last policy use */
|
/* 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->other.addr->destroy(this->other.addr);
|
||||||
this->me.id->destroy(this->me.id);
|
this->me.id->destroy(this->me.id);
|
||||||
this->other.id->destroy(this->other.id);
|
this->other.id->destroy(this->other.id);
|
||||||
this->policy->destroy(this->policy);
|
this->config->destroy(this->config);
|
||||||
DESTROY_IF(this->virtual_ip);
|
DESTROY_IF(this->virtual_ip);
|
||||||
free(this);
|
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,
|
child_sa_t * child_sa_create(host_t *me, host_t* other,
|
||||||
identification_t *my_id, identification_t *other_id,
|
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;
|
static u_int32_t reqid = 0;
|
||||||
private_child_sa_t *this = malloc_thing(private_child_sa_t);
|
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 = (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.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.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_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
|
||||||
this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
|
|
||||||
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
|
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.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_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.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
|
||||||
this->public.destroy = (void(*)(child_sa_t*))destroy;
|
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->protocol = PROTO_NONE;
|
||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
this->virtual_ip = NULL;
|
this->virtual_ip = NULL;
|
||||||
this->policy = policy;
|
this->config = config;
|
||||||
policy->get_ref(policy);
|
config->get_ref(config);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ typedef struct child_sa_t child_sa_t;
|
||||||
#include <crypto/prf_plus.h>
|
#include <crypto/prf_plus.h>
|
||||||
#include <encoding/payloads/proposal_substructure.h>
|
#include <encoding/payloads/proposal_substructure.h>
|
||||||
#include <config/proposal.h>
|
#include <config/proposal.h>
|
||||||
#include <config/policies/policy.h>
|
#include <config/child_cfg.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where we should start with reqid enumeration
|
* Where we should start with reqid enumeration
|
||||||
|
@ -101,7 +101,7 @@ extern enum_name_t *child_sa_state_names;
|
||||||
struct child_sa_t {
|
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
|
* @param this calling object
|
||||||
* @return name
|
* @return name
|
||||||
|
@ -214,17 +214,10 @@ struct child_sa_t {
|
||||||
* @brief Get the traffic selectors of added policies of local host.
|
* @brief Get the traffic selectors of added policies of local host.
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
|
* @param local TRUE for own traffic selectors, FALSE for remote
|
||||||
* @return list of traffic selectors
|
* @return list of traffic selectors
|
||||||
*/
|
*/
|
||||||
linked_list_t* (*get_my_traffic_selectors) (child_sa_t *this);
|
linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
|
* @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);
|
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
|
* @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.
|
* @brief Set the virtual IP used received from IRAS.
|
||||||
|
@ -284,7 +277,7 @@ struct child_sa_t {
|
||||||
* @param other remote address
|
* @param other remote address
|
||||||
* @param my_id id of own peer
|
* @param my_id id of own peer
|
||||||
* @param other_id id of remote 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 reqid reqid of old CHILD_SA when rekeying, 0 otherwise
|
||||||
* @param use_natt TRUE if NAT traversal is used
|
* @param use_natt TRUE if NAT traversal is used
|
||||||
* @return child_sa_t object
|
* @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,
|
child_sa_t * child_sa_create(host_t *me, host_t *other,
|
||||||
identification_t *my_id, identification_t* other_id,
|
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_*/
|
#endif /*CHILD_SA_H_*/
|
||||||
|
|
|
@ -56,13 +56,13 @@
|
||||||
#include <sa/tasks/child_create.h>
|
#include <sa/tasks/child_create.h>
|
||||||
#include <sa/tasks/child_delete.h>
|
#include <sa/tasks/child_delete.h>
|
||||||
#include <sa/tasks/child_rekey.h>
|
#include <sa/tasks/child_rekey.h>
|
||||||
#include <queues/jobs/retransmit_job.h>
|
#include <processing/jobs/retransmit_job.h>
|
||||||
#include <queues/jobs/delete_ike_sa_job.h>
|
#include <processing/jobs/delete_ike_sa_job.h>
|
||||||
#include <queues/jobs/send_dpd_job.h>
|
#include <processing/jobs/send_dpd_job.h>
|
||||||
#include <queues/jobs/send_keepalive_job.h>
|
#include <processing/jobs/send_keepalive_job.h>
|
||||||
#include <queues/jobs/rekey_ike_sa_job.h>
|
#include <processing/jobs/rekey_ike_sa_job.h>
|
||||||
#include <queues/jobs/route_job.h>
|
#include <processing/jobs/route_job.h>
|
||||||
#include <queues/jobs/initiate_job.h>
|
#include <processing/jobs/initiate_job.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef RESOLV_CONF
|
#ifndef RESOLV_CONF
|
||||||
|
@ -105,14 +105,14 @@ struct private_ike_sa_t {
|
||||||
ike_sa_state_t state;
|
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.
|
* Peer and authentication information to establish IKE_SA.
|
||||||
*/
|
*/
|
||||||
policy_t *policy;
|
peer_cfg_t *peer_cfg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Juggles tasks to process messages
|
* 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)
|
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)";
|
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.
|
* 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;
|
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
|
* 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;
|
send_dpd_job_t *job;
|
||||||
time_t diff, delay;
|
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)
|
if (delay == 0)
|
||||||
{
|
{
|
||||||
|
@ -464,9 +490,9 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
|
||||||
send_dpd(this);
|
send_dpd(this);
|
||||||
|
|
||||||
/* schedule rekeying/reauthentication */
|
/* schedule rekeying/reauthentication */
|
||||||
soft = this->connection->get_soft_lifetime(this->connection);
|
soft = this->peer_cfg->get_lifetime(this->peer_cfg, TRUE);
|
||||||
hard = this->connection->get_hard_lifetime(this->connection);
|
hard = this->peer_cfg->get_lifetime(this->peer_cfg, FALSE);
|
||||||
reauth = this->connection->get_reauth(this->connection);
|
reauth = this->peer_cfg->use_reauth(this->peer_cfg);
|
||||||
DBG1(DBG_IKE, "scheduling %s in %ds, maximum lifetime %ds",
|
DBG1(DBG_IKE, "scheduling %s in %ds, maximum lifetime %ds",
|
||||||
reauth ? "reauthentication": "rekeying", soft, hard);
|
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)
|
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);
|
me = message->get_destination(message);
|
||||||
other = message->get_source(message);
|
other = message->get_source(message);
|
||||||
|
|
||||||
/* if this IKE_SA is virgin, we check for a connection */
|
/* if this IKE_SA is virgin, we check for a config */
|
||||||
if (this->connection == NULL)
|
if (this->ike_cfg == NULL)
|
||||||
{
|
{
|
||||||
job_t *job;
|
job_t *job;
|
||||||
this->connection = charon->connections->get_connection_by_hosts(
|
this->ike_cfg = charon->cfg_store->get_ike_cfg(charon->cfg_store,
|
||||||
charon->connections, me, other);
|
me, other);
|
||||||
if (this->connection == NULL)
|
if (this->ike_cfg == NULL)
|
||||||
{
|
{
|
||||||
/* no connection found for these hosts, destroy */
|
/* no config found for these hosts, destroy */
|
||||||
DBG1(DBG_IKE, "no connection found for %H...%H, sending %N",
|
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
|
||||||
me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
|
me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
|
||||||
send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
|
send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
|
||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
|
@ -717,7 +743,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
|
||||||
charon->configuration));
|
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 ||
|
if (this->state == IKE_CREATED ||
|
||||||
message->get_exchange_type(message) != IKE_SA_INIT)
|
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.
|
* Implementation of ike_sa_t.initiate.
|
||||||
*/
|
*/
|
||||||
static status_t initiate(private_ike_sa_t *this,
|
static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
|
||||||
connection_t *connection, policy_t *policy)
|
|
||||||
{
|
{
|
||||||
task_t *task;
|
task_t *task;
|
||||||
|
|
||||||
if (this->state == IKE_CREATED)
|
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))
|
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);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
task = (task_t*)ike_auth_create(&this->public, TRUE);
|
task = (task_t*)ike_auth_create(&this->public, TRUE);
|
||||||
this->task_manager->queue_task(this->task_manager, task);
|
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);
|
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);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
|
|
||||||
return this->task_manager->initiate(this->task_manager);
|
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)
|
static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
|
||||||
{
|
{
|
||||||
policy_t *policy;
|
child_cfg_t *child_cfg;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
child_sa_t *current, *child_sa = NULL;
|
child_sa_t *current, *child_sa = NULL;
|
||||||
task_t *task;
|
task_t *task;
|
||||||
|
@ -833,7 +827,6 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = child_sa->get_policy(child_sa);
|
|
||||||
|
|
||||||
if (this->state == IKE_CREATED)
|
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);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
task = (task_t*)ike_auth_create(&this->public, TRUE);
|
task = (task_t*)ike_auth_create(&this->public, TRUE);
|
||||||
this->task_manager->queue_task(this->task_manager, task);
|
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);
|
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);
|
child_create->use_reqid(child_create, reqid);
|
||||||
this->task_manager->queue_task(this->task_manager, (task_t*)child_create);
|
this->task_manager->queue_task(this->task_manager, (task_t*)child_create);
|
||||||
|
|
||||||
return this->task_manager->initiate(this->task_manager);
|
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.
|
* 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;
|
iterator_t *iterator;
|
||||||
linked_list_t *my_ts, *other_ts;
|
linked_list_t *my_ts, *other_ts;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
@ -901,27 +866,12 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
|
||||||
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
|
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
|
||||||
|
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
|
||||||
{
|
{
|
||||||
linked_list_t *my_ts_conf, *other_ts_conf;
|
iterator->destroy(iterator);
|
||||||
|
SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config already routed");
|
||||||
my_ts = child_sa->get_my_traffic_selectors(child_sa);
|
return FAILED;
|
||||||
other_ts = child_sa->get_other_traffic_selectors(child_sa);
|
|
||||||
|
|
||||||
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
|
|
||||||
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
|
|
||||||
|
|
||||||
if (ts_list_equals(my_ts, my_ts_conf) &&
|
|
||||||
ts_list_equals(other_ts, other_ts_conf))
|
|
||||||
{
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a policy already routed");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
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");
|
"unable to route CHILD_SA, as its IKE_SA gets deleted");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
case IKE_CREATED:
|
case IKE_CREATED:
|
||||||
/* apply connection information, we need it to acquire */
|
|
||||||
apply_config(this, connection, policy);
|
|
||||||
break;
|
|
||||||
case IKE_CONNECTING:
|
case IKE_CONNECTING:
|
||||||
case IKE_ESTABLISHED:
|
case IKE_ESTABLISHED:
|
||||||
default:
|
default:
|
||||||
|
@ -944,29 +891,37 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
|
||||||
}
|
}
|
||||||
|
|
||||||
/* install kernel policies */
|
/* install kernel policies */
|
||||||
child_sa = child_sa_create(this->my_host, this->other_host,
|
child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
|
||||||
this->my_id, this->other_id, policy, FALSE, 0);
|
this->other_id, child_cfg, FALSE, 0);
|
||||||
|
|
||||||
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
|
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
|
||||||
other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
|
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,
|
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));
|
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||||
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
||||||
this->child_sas->insert_last(this->child_sas, child_sa);
|
if (status == SUCCESS)
|
||||||
SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed");
|
{
|
||||||
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_t.unroute.
|
* 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;
|
iterator_t *iterator;
|
||||||
child_sa_t *child_sa = NULL;
|
child_sa_t *child_sa;
|
||||||
bool found = FALSE;
|
bool found = FALSE;
|
||||||
linked_list_t *my_ts, *other_ts, *my_ts_conf, *other_ts_conf;
|
|
||||||
|
|
||||||
SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA");
|
SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA");
|
||||||
|
|
||||||
|
@ -974,27 +929,14 @@ static status_t unroute(private_ike_sa_t *this, policy_t *policy)
|
||||||
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
|
if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
|
||||||
|
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
|
||||||
{
|
{
|
||||||
my_ts = child_sa->get_my_traffic_selectors(child_sa);
|
iterator->remove(iterator);
|
||||||
other_ts = child_sa->get_other_traffic_selectors(child_sa);
|
SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
|
||||||
|
child_sa->destroy(child_sa);
|
||||||
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
|
found = TRUE;
|
||||||
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
|
break;
|
||||||
|
|
||||||
if (ts_list_equals(my_ts, my_ts_conf) &&
|
|
||||||
ts_list_equals(other_ts, other_ts_conf))
|
|
||||||
{
|
|
||||||
iterator->remove(iterator);
|
|
||||||
SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
|
|
||||||
child_sa->destroy(child_sa);
|
|
||||||
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
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);
|
this->time.outbound = time(NULL);
|
||||||
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
|
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
|
||||||
{
|
{
|
||||||
policy_t *policy;
|
child_cfg_t *child_cfg;
|
||||||
child_sa_t* child_sa;
|
child_sa_t* child_sa;
|
||||||
linked_list_t *to_route, *to_restart;
|
linked_list_t *to_route, *to_restart;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
|
@ -1032,7 +974,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
|
||||||
case IKE_CONNECTING:
|
case IKE_CONNECTING:
|
||||||
{
|
{
|
||||||
/* retry IKE_SA_INIT if we have multiple keyingtries */
|
/* 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++;
|
this->keyingtry++;
|
||||||
if (tries == 0 || tries > 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);
|
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
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)
|
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
|
||||||
{
|
{
|
||||||
/* reroute routed CHILD_SAs */
|
/* reroute routed CHILD_SAs */
|
||||||
to_route->insert_last(to_route, policy);
|
to_route->insert_last(to_route, child_cfg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* use DPD action for established CHILD_SAs */
|
/* 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:
|
case DPD_ROUTE:
|
||||||
to_route->insert_last(to_route, policy);
|
to_route->insert_last(to_route, child_cfg);
|
||||||
break;
|
break;
|
||||||
case DPD_RESTART:
|
case DPD_RESTART:
|
||||||
to_restart->insert_last(to_restart, policy);
|
to_restart->insert_last(to_restart, child_cfg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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(
|
new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
|
||||||
charon->ike_sa_manager, TRUE);
|
charon->ike_sa_manager, TRUE);
|
||||||
|
|
||||||
apply_config(new, this->connection, this->policy);
|
set_peer_cfg(new, this->peer_cfg);
|
||||||
/* use actual used host, not the wildcarded one in connection */
|
/* use actual used host, not the wildcarded one in config */
|
||||||
new->other_host->destroy(new->other_host);
|
new->other_host->destroy(new->other_host);
|
||||||
new->other_host = this->other_host->clone(this->other_host);
|
new->other_host = this->other_host->clone(this->other_host);
|
||||||
|
|
||||||
/* install routes */
|
/* 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 */
|
/* 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);
|
new->task_manager->queue_task(new->task_manager, task);
|
||||||
task = (task_t*)ike_cert_create(&new->public, TRUE);
|
task = (task_t*)ike_cert_create(&new->public, TRUE);
|
||||||
new->task_manager->queue_task(new->task_manager, task);
|
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);
|
new->task_manager->queue_task(new->task_manager, task);
|
||||||
task = (task_t*)ike_auth_create(&new->public, TRUE);
|
task = (task_t*)ike_auth_create(&new->public, TRUE);
|
||||||
new->task_manager->queue_task(new->task_manager, task);
|
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->queue_task(new->task_manager, task);
|
||||||
}
|
}
|
||||||
new->task_manager->initiate(new->task_manager);
|
new->task_manager->initiate(new->task_manager);
|
||||||
|
@ -1542,14 +1484,14 @@ static void reestablish(private_ike_sa_t *this)
|
||||||
private_ike_sa_t *other;
|
private_ike_sa_t *other;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
policy_t *policy;
|
child_cfg_t *child_cfg;
|
||||||
task_t *task;
|
task_t *task;
|
||||||
job_t *job;
|
job_t *job;
|
||||||
|
|
||||||
other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
|
other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
|
||||||
charon->ike_sa_manager, TRUE);
|
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->destroy(other->other_host);
|
||||||
other->other_host = this->other_host->clone(this->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);
|
other->task_manager->queue_task(other->task_manager, task);
|
||||||
task = (task_t*)ike_cert_create(&other->public, TRUE);
|
task = (task_t*)ike_cert_create(&other->public, TRUE);
|
||||||
other->task_manager->queue_task(other->task_manager, task);
|
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);
|
other->task_manager->queue_task(other->task_manager, task);
|
||||||
task = (task_t*)ike_auth_create(&other->public, TRUE);
|
task = (task_t*)ike_auth_create(&other->public, TRUE);
|
||||||
other->task_manager->queue_task(other->task_manager, task);
|
other->task_manager->queue_task(other->task_manager, task);
|
||||||
|
@ -1583,8 +1525,8 @@ static void reestablish(private_ike_sa_t *this)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
policy = child_sa->get_policy(child_sa);
|
child_cfg = child_sa->get_config(child_sa);
|
||||||
task = (task_t*)child_create_create(&other->public, policy);
|
task = (task_t*)child_create_create(&other->public, child_cfg);
|
||||||
other->task_manager->queue_task(other->task_manager, task);
|
other->task_manager->queue_task(other->task_manager, task);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1865,9 +1807,9 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||||
bool reauth = FALSE;
|
bool reauth = FALSE;
|
||||||
private_ike_sa_t *this = *((private_ike_sa_t**)(args[0]));
|
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)
|
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->unique_id, ike_sa_state_names, this->state,
|
||||||
this->my_host, this->my_id, this->other_host,
|
this->my_host, this->my_id, this->other_host,
|
||||||
this->other_id);
|
this->other_id);
|
||||||
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds",
|
if (this->time.rekey)
|
||||||
get_name(this), this->unique_id, this->ike_sa_id,
|
|
||||||
this->connection && reauth? "reauthentication":"rekeying",
|
|
||||||
this->time.rekey - time(NULL));
|
|
||||||
|
|
||||||
if (info->alt)
|
|
||||||
{
|
{
|
||||||
|
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds",
|
||||||
|
get_name(this), this->unique_id, this->ike_sa_id,
|
||||||
|
reauth ? "reauthentication" : "rekeying",
|
||||||
|
this->time.rekey - time(NULL));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, rekeying disabled",
|
||||||
|
get_name(this), this->unique_id, this->ike_sa_id);
|
||||||
|
}
|
||||||
|
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1931,8 +1877,8 @@ static void destroy(private_ike_sa_t *this)
|
||||||
DESTROY_IF(this->my_id);
|
DESTROY_IF(this->my_id);
|
||||||
DESTROY_IF(this->other_id);
|
DESTROY_IF(this->other_id);
|
||||||
|
|
||||||
DESTROY_IF(this->connection);
|
DESTROY_IF(this->ike_cfg);
|
||||||
DESTROY_IF(this->policy);
|
DESTROY_IF(this->peer_cfg);
|
||||||
|
|
||||||
this->ike_sa_id->destroy(this->ike_sa_id);
|
this->ike_sa_id->destroy(this->ike_sa_id);
|
||||||
this->task_manager->destroy(this->task_manager);
|
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.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state;
|
||||||
this->public.get_name = (char*(*)(ike_sa_t*))get_name;
|
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.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.initiate = (status_t(*)(ike_sa_t*,child_cfg_t*)) initiate;
|
||||||
this->public.route = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) route;
|
this->public.route = (status_t(*)(ike_sa_t*,child_cfg_t*)) route;
|
||||||
this->public.unroute = (status_t(*)(ike_sa_t*,policy_t*)) unroute;
|
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.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
|
||||||
this->public.get_connection = (connection_t*(*)(ike_sa_t*))get_connection;
|
this->public.get_ike_cfg = (ike_cfg_t*(*)(ike_sa_t*))get_ike_cfg;
|
||||||
this->public.set_connection = (void(*)(ike_sa_t*,connection_t*))set_connection;
|
this->public.set_ike_cfg = (void(*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
|
||||||
this->public.get_policy = (policy_t*(*)(ike_sa_t*))get_policy;
|
this->public.get_peer_cfg = (peer_cfg_t*(*)(ike_sa_t*))get_peer_cfg;
|
||||||
this->public.set_policy = (void(*)(ike_sa_t*,policy_t*))set_policy;
|
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_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.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;
|
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.established = 0;
|
||||||
this->time.rekey = 0;
|
this->time.rekey = 0;
|
||||||
this->time.delete = 0;
|
this->time.delete = 0;
|
||||||
this->connection = NULL;
|
this->ike_cfg = NULL;
|
||||||
this->policy = NULL;
|
this->peer_cfg = NULL;
|
||||||
this->task_manager = task_manager_create(&this->public);
|
this->task_manager = task_manager_create(&this->public);
|
||||||
this->unique_id = ++unique_id;
|
this->unique_id = ++unique_id;
|
||||||
this->my_virtual_ip = NULL;
|
this->my_virtual_ip = NULL;
|
||||||
|
|
|
@ -39,9 +39,8 @@ typedef struct ike_sa_t ike_sa_t;
|
||||||
#include <crypto/prfs/prf.h>
|
#include <crypto/prfs/prf.h>
|
||||||
#include <crypto/crypters/crypter.h>
|
#include <crypto/crypters/crypter.h>
|
||||||
#include <crypto/signers/signer.h>
|
#include <crypto/signers/signer.h>
|
||||||
#include <config/connections/connection.h>
|
#include <config/peer_cfg.h>
|
||||||
#include <config/policies/policy.h>
|
#include <config/ike_cfg.h>
|
||||||
#include <config/proposal.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief State of an IKE_SA.
|
* @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);
|
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
|
* @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 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
|
* @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 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.
|
* @brief Initiate a new connection.
|
||||||
*
|
*
|
||||||
* The policy/connection is owned by the IKE_SA after the call, so
|
* The configs are owned by the IKE_SA after the call.
|
||||||
* do not modify or destroy it.
|
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param connection connection to initiate
|
* @param child_cfg child config to create CHILD from
|
||||||
* @param policy policy to set up
|
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if initialization started
|
* - 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.
|
* @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().
|
* the kernel requests connection setup from the IKE_SA via acquire().
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param connection connection definition used for routing
|
* @param child_cfg child config to route
|
||||||
* @param policy policy to route
|
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if routed successfully
|
* - SUCCESS if routed successfully
|
||||||
* - FAILED if routing failed
|
* - 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.
|
* @brief Unroute a policy in the kernel previously routed.
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param policy policy to route
|
* @param child_cfg child config to unroute
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if route removed
|
* - SUCCESS if route removed
|
||||||
* - DESTROY_ME if last route was removed from
|
* - DESTROY_ME if last CHILD_SA was unrouted
|
||||||
* an IKE_SA which was not established
|
|
||||||
*/
|
*/
|
||||||
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
|
* If an installed policy raises an acquire, the kernel calls
|
||||||
* this function to establish the CHILD_SA (and maybe the IKE_SA).
|
* 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.
|
* @param reqid reqid of the CHILD_SA the policy belongs to.
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS if initialization started
|
* - 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);
|
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);
|
pthread_mutex_unlock(&this->mutex);
|
||||||
DBG2(DBG_MGR, "created IKE_SA: %J, %d IKE_SAs in manager",
|
DBG2(DBG_MGR, "created IKE_SA: %J, %d IKE_SAs in manager",
|
||||||
id, this->ike_sa_list->get_count(this->ike_sa_list));
|
id, this->ike_sa_list->get_count(this->ike_sa_list));
|
||||||
|
id->destroy(id);
|
||||||
return entry->ike_sa;
|
return entry->ike_sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <sa/tasks/child_rekey.h>
|
#include <sa/tasks/child_rekey.h>
|
||||||
#include <sa/tasks/child_delete.h>
|
#include <sa/tasks/child_delete.h>
|
||||||
#include <encoding/payloads/delete_payload.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;
|
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);
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
|
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
|
||||||
this->passive_tasks->insert_last(this->passive_tasks, task);
|
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);
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
task = (task_t*)child_create_create(this->ike_sa, NULL);
|
task = (task_t*)child_create_create(this->ike_sa, NULL);
|
||||||
this->passive_tasks->insert_last(this->passive_tasks, task);
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
|
|
|
@ -64,9 +64,9 @@ struct private_child_create_t {
|
||||||
chunk_t other_nonce;
|
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
|
* 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);
|
my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
|
||||||
other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
|
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)
|
if (this->proposal == NULL)
|
||||||
{
|
{
|
||||||
|
@ -206,28 +206,31 @@ static status_t select_and_install(private_child_create_t *this)
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->initiator && my_vip)
|
if (my_vip == NULL)
|
||||||
{ /* 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 = me;
|
||||||
my_vip);
|
}
|
||||||
|
else if (this->initiator)
|
||||||
|
{
|
||||||
/* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
|
/* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
|
||||||
this->child_sa->set_virtual_ip(this->child_sa, my_vip);
|
this->child_sa->set_virtual_ip(this->child_sa, my_vip);
|
||||||
}
|
}
|
||||||
else
|
if (other_vip == NULL)
|
||||||
{ /* shorten in the host2host case only */
|
{
|
||||||
my_ts = this->policy->select_my_traffic_selectors(this->policy,
|
other_vip = other;
|
||||||
my_ts, me);
|
|
||||||
}
|
}
|
||||||
if (other_vip)
|
|
||||||
{ /* if other has a virtual IP, shorten it's traffic selectors to it */
|
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
|
||||||
other_ts = this->policy->select_other_traffic_selectors(this->policy,
|
my_vip);
|
||||||
other_ts, other_vip);
|
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
|
||||||
}
|
other_vip);
|
||||||
else
|
|
||||||
{ /* use his host for the host2host case */
|
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
|
||||||
other_ts = this->policy->select_other_traffic_selectors(this->policy,
|
{
|
||||||
other_ts, other);
|
SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
|
||||||
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
|
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
|
||||||
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
|
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
|
||||||
if (this->initiator)
|
if (this->initiator)
|
||||||
|
@ -241,13 +244,6 @@ static status_t select_and_install(private_child_create_t *this)
|
||||||
this->tsi = other_ts;
|
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)
|
if (!this->initiator)
|
||||||
{
|
{
|
||||||
/* check if requested mode is acceptable, downgrade if required */
|
/* 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)
|
static status_t build_i(private_child_create_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
host_t *me, *other, *vip;
|
host_t *me, *other, *vip;
|
||||||
|
peer_cfg_t *peer_cfg;
|
||||||
|
|
||||||
switch (message->get_exchange_type(message))
|
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);
|
me = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
other = this->ike_sa->get_other_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)
|
if (vip)
|
||||||
{ /* propose a 0.0.0.0/0 subnet when we use virtual ip */
|
{ /* 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);
|
vip->destroy(vip);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* but shorten a 0.0.0.0/0 subnet to the actual address if host2host */
|
{ /* 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->tsr = this->config->get_traffic_selectors(this->config, FALSE,
|
||||||
this->proposals = this->policy->get_proposals(this->policy);
|
NULL, other);
|
||||||
this->mode = this->policy->get_mode(this->policy);
|
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->child_sa = child_sa_create(me, other,
|
||||||
this->ike_sa->get_my_id(this->ike_sa),
|
this->ike_sa->get_my_id(this->ike_sa),
|
||||||
this->ike_sa->get_other_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));
|
this->ike_sa->is_natt_enabled(this->ike_sa));
|
||||||
|
|
||||||
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
|
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)
|
static status_t process_r(private_child_create_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
|
peer_cfg_t *peer_cfg;
|
||||||
|
|
||||||
switch (message->get_exchange_type(message))
|
switch (message->get_exchange_type(message))
|
||||||
{
|
{
|
||||||
case IKE_SA_INIT:
|
case IKE_SA_INIT:
|
||||||
|
@ -517,18 +520,13 @@ static status_t process_r(private_child_create_t *this, message_t *message)
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->policy = charon->policies->get_policy(charon->policies,
|
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
this->ike_sa->get_my_id(this->ike_sa),
|
if (peer_cfg)
|
||||||
this->ike_sa->get_other_id(this->ike_sa),
|
|
||||||
this->tsr, this->tsi,
|
|
||||||
this->ike_sa->get_my_host(this->ike_sa),
|
|
||||||
this->ike_sa->get_other_host(this->ike_sa));
|
|
||||||
|
|
||||||
if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
|
|
||||||
{
|
{
|
||||||
this->ike_sa->set_policy(this->ike_sa, this->policy);
|
this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr, this->tsi,
|
||||||
|
this->ike_sa->get_my_host(this->ike_sa),
|
||||||
|
this->ike_sa->get_other_host(this->ike_sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,10 +563,11 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->policy == NULL)
|
if (this->config == NULL)
|
||||||
{
|
{
|
||||||
SIG(CHILD_UP_FAILED, "no acceptable policy found");
|
SIG(CHILD_UP_FAILED, "traffic selectors %#R=== %#R inacceptable",
|
||||||
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
|
this->tsr, this->tsi);
|
||||||
|
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
|
||||||
return SUCCESS;
|
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_other_host(this->ike_sa),
|
||||||
this->ike_sa->get_my_id(this->ike_sa),
|
this->ike_sa->get_my_id(this->ike_sa),
|
||||||
this->ike_sa->get_other_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));
|
this->ike_sa->is_natt_enabled(this->ike_sa));
|
||||||
|
|
||||||
if (select_and_install(this) != SUCCESS)
|
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;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,14 +755,14 @@ static void destroy(private_child_create_t *this)
|
||||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||||
}
|
}
|
||||||
|
|
||||||
DESTROY_IF(this->policy);
|
DESTROY_IF(this->config);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Described in header.
|
* 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);
|
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.get_type = (task_type_t(*)(task_t*))get_type;
|
||||||
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
|
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
|
||||||
this->public.task.destroy = (void(*)(task_t*))destroy;
|
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.build = (status_t(*)(task_t*,message_t*))build_i;
|
||||||
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
||||||
this->initiator = TRUE;
|
this->initiator = TRUE;
|
||||||
policy->get_ref(policy);
|
config->get_ref(config);
|
||||||
}
|
}
|
||||||
else
|
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->ike_sa = ike_sa;
|
||||||
this->policy = policy;
|
this->config = config;
|
||||||
this->my_nonce = chunk_empty;
|
this->my_nonce = chunk_empty;
|
||||||
this->other_nonce = chunk_empty;
|
this->other_nonce = chunk_empty;
|
||||||
this->proposals = NULL;
|
this->proposals = NULL;
|
||||||
|
|
|
@ -28,7 +28,7 @@ typedef struct child_create_t child_create_t;
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <sa/ike_sa.h>
|
#include <sa/ike_sa.h>
|
||||||
#include <sa/tasks/task.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.
|
* @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.
|
* @brief Create a new child_create task.
|
||||||
*
|
*
|
||||||
* @param ike_sa IKE_SA this task works for
|
* @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
|
* @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_ */
|
#endif /* CHILD_CREATE_H_ */
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <encoding/payloads/notify_payload.h>
|
#include <encoding/payloads/notify_payload.h>
|
||||||
#include <sa/tasks/child_create.h>
|
#include <sa/tasks/child_create.h>
|
||||||
#include <sa/tasks/child_delete.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;
|
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_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);
|
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.collide = (void (*)(child_rekey_t*,task_t*))collide;
|
||||||
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
|
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.build = (status_t(*)(task_t*,message_t*))build_i;
|
||||||
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
||||||
this->initiator = TRUE;
|
this->initiator = TRUE;
|
||||||
policy = child_sa->get_policy(child_sa);
|
config = child_sa->get_config(child_sa);
|
||||||
this->child_create = child_create_create(ike_sa, policy);
|
this->child_create = child_create_create(ike_sa, config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,18 +100,18 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
authenticator_t *auth;
|
authenticator_t *auth;
|
||||||
auth_payload_t *auth_payload;
|
auth_payload_t *auth_payload;
|
||||||
policy_t *policy;
|
peer_cfg_t *config;
|
||||||
auth_method_t method;
|
auth_method_t method;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
/* create own authenticator and add auth payload */
|
/* create own authenticator and add auth payload */
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
if (!policy)
|
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;
|
return FAILED;
|
||||||
}
|
}
|
||||||
method = policy->get_auth_method(policy);
|
method = config->get_auth_method(config);
|
||||||
|
|
||||||
auth = authenticator_create(this->ike_sa, method);
|
auth = authenticator_create(this->ike_sa, method);
|
||||||
if (auth == NULL)
|
if (auth == NULL)
|
||||||
|
@ -140,15 +140,15 @@ static status_t build_id(private_ike_auth_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
identification_t *me, *other;
|
identification_t *me, *other;
|
||||||
id_payload_t *id;
|
id_payload_t *id;
|
||||||
policy_t *policy;
|
peer_cfg_t *config;
|
||||||
|
|
||||||
me = this->ike_sa->get_my_id(this->ike_sa);
|
me = this->ike_sa->get_my_id(this->ike_sa);
|
||||||
other = this->ike_sa->get_other_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))
|
if (me->contains_wildcards(me))
|
||||||
{
|
{
|
||||||
me = policy->get_my_id(policy);
|
me = config->get_my_id(config);
|
||||||
if (me->contains_wildcards(me))
|
if (me->contains_wildcards(me))
|
||||||
{
|
{
|
||||||
SIG(IKE_UP_FAILED, "negotiation of own ID failed");
|
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)
|
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)
|
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;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
if (policy->get_auth_method(policy) == AUTH_EAP)
|
if (config->get_auth_method(config) == AUTH_EAP)
|
||||||
{
|
{
|
||||||
this->eap_auth = eap_authenticator_create(this->ike_sa);
|
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)
|
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)
|
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||||
{
|
{
|
||||||
return collect_other_init_data(this, message);
|
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;
|
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))
|
switch (process_auth(this, message))
|
||||||
{
|
{
|
||||||
case SUCCESS:
|
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)
|
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_type_t eap_type;
|
||||||
eap_payload_t *eap_payload;
|
eap_payload_t *eap_payload;
|
||||||
status_t status;
|
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);
|
return collect_my_init_data(this, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
if (policy == NULL)
|
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);
|
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
@ -567,7 +580,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initiate EAP authenitcation */
|
/* 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);
|
status = this->eap_auth->initiate(this->eap_auth, eap_type, &eap_payload);
|
||||||
message->add_payload(message, (payload_t*)eap_payload);
|
message->add_payload(message, (payload_t*)eap_payload);
|
||||||
if (status != NEED_MORE)
|
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)
|
static void build_certreqs(private_ike_cert_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
connection_t *connection;
|
ike_cfg_t *ike_cfg;
|
||||||
policy_t *policy;
|
peer_cfg_t *peer_cfg;
|
||||||
identification_t *ca;
|
identification_t *ca;
|
||||||
certreq_payload_t *certreq;
|
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)
|
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)
|
static void build_certs(private_ike_cert_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
policy_t *policy;
|
peer_cfg_t *peer_cfg;
|
||||||
connection_t *connection;
|
|
||||||
x509_t *cert;
|
x509_t *cert;
|
||||||
cert_payload_t *payload;
|
cert_payload_t *payload;
|
||||||
|
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
connection = this->ike_sa->get_connection(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:
|
case CERT_NEVER_SEND:
|
||||||
break;
|
break;
|
||||||
|
@ -236,7 +234,7 @@ static void build_certs(private_ike_cert_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
/* TODO: respect CA cert request */
|
/* TODO: respect CA cert request */
|
||||||
cert = charon->credentials->get_certificate(charon->credentials,
|
cert = charon->credentials->get_certificate(charon->credentials,
|
||||||
policy->get_my_id(policy));
|
peer_cfg->get_my_id(peer_cfg));
|
||||||
if (cert)
|
if (cert)
|
||||||
{
|
{
|
||||||
payload = cert_payload_create_from_x509(cert);
|
payload = cert_payload_create_from_x509(cert);
|
||||||
|
|
|
@ -48,11 +48,6 @@ struct private_ike_config_t {
|
||||||
*/
|
*/
|
||||||
bool initiator;
|
bool initiator;
|
||||||
|
|
||||||
/**
|
|
||||||
* associated policy with virtual IP configuration
|
|
||||||
*/
|
|
||||||
policy_t *policy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virtual ip
|
* 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 &&
|
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||||
message->get_payload(message, ID_INITIATOR))
|
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);
|
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 &&
|
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||||
message->get_payload(message, EXTENSIBLE_AUTHENTICATION) == NULL)
|
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;
|
host_t *ip;
|
||||||
|
|
||||||
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_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))
|
if (ip == NULL || ip->is_anyaddr(ip))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "not assigning a virtual IP to peer");
|
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.
|
* 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);
|
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.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
|
||||||
this->public.task.destroy = (void(*)(task_t*))destroy;
|
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.build = (status_t(*)(task_t*,message_t*))build_i;
|
||||||
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
||||||
this->initiator = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
|
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->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
|
||||||
this->initiator = FALSE;
|
|
||||||
}
|
}
|
||||||
|
this->initiator = initiator;
|
||||||
this->ike_sa = ike_sa;
|
this->ike_sa = ike_sa;
|
||||||
this->policy = policy;
|
|
||||||
this->virtual_ip = NULL;
|
this->virtual_ip = NULL;
|
||||||
this->dns = linked_list_create();
|
this->dns = linked_list_create();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ typedef struct ike_config_t ike_config_t;
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <sa/ike_sa.h>
|
#include <sa/ike_sa.h>
|
||||||
#include <sa/tasks/task.h>
|
#include <sa/tasks/task.h>
|
||||||
#include <config/policies/policy.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task of type IKE_CONFIG, sets up a virtual IP and other
|
* @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.
|
* @brief Create a new ike_config task.
|
||||||
*
|
*
|
||||||
* @param ike_sa IKE_SA this task works for
|
* @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
|
* @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_ */
|
#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