summaryrefslogtreecommitdiff
path: root/src/libhydra
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-11-18 14:49:27 +0100
committerYves-Alexis Perez <corsac@debian.org>2015-11-18 14:49:27 +0100
commit1e980d6be0ef0e243c6fe82b5e855454b97e24a4 (patch)
tree0d59eec2ce2ed332434ae80fc78a44db9ad293c5 /src/libhydra
parent5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (diff)
downloadvyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.tar.gz
vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.zip
Imported Upstream version 5.3.4
Diffstat (limited to 'src/libhydra')
-rw-r--r--src/libhydra/Android.mk1
-rw-r--r--src/libhydra/kernel/kernel_interface.c27
-rw-r--r--src/libhydra/kernel/kernel_interface.h53
-rw-r--r--src/libhydra/kernel/kernel_ipsec.c7
-rw-r--r--src/libhydra/kernel/kernel_ipsec.h23
-rw-r--r--src/libhydra/kernel/kernel_net.c7
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c81
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c19
8 files changed, 114 insertions, 104 deletions
diff --git a/src/libhydra/Android.mk b/src/libhydra/Android.mk
index af39f04ec..7b62e9529 100644
--- a/src/libhydra/Android.mk
+++ b/src/libhydra/Android.mk
@@ -20,7 +20,6 @@ LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink)
# build libhydra ---------------------------------------------------------------
LOCAL_C_INCLUDES += \
- $(strongswan_PATH)/src/include \
$(strongswan_PATH)/src/libstrongswan
LOCAL_CFLAGS := $(strongswan_CFLAGS)
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index ce31bd410..89e95ade9 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2013 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -509,16 +509,17 @@ METHOD(kernel_interface_t, query_policy, status_t,
}
METHOD(kernel_interface_t, del_policy, status_t,
- private_kernel_interface_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ private_kernel_interface_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
mark_t mark, policy_priority_t priority)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
- return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
- direction, reqid, mark, priority);
+ return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts,
+ direction, type, sa, mark, priority);
}
METHOD(kernel_interface_t, flush_policies, status_t,
@@ -738,44 +739,52 @@ METHOD(kernel_interface_t, get_address_by_ts, status_t,
}
-METHOD(kernel_interface_t, add_ipsec_interface, void,
+METHOD(kernel_interface_t, add_ipsec_interface, bool,
private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
{
if (!this->ipsec)
{
this->ipsec_constructor = constructor;
this->ipsec = constructor();
+ return this->ipsec != NULL;
}
+ return FALSE;
}
-METHOD(kernel_interface_t, remove_ipsec_interface, void,
+METHOD(kernel_interface_t, remove_ipsec_interface, bool,
private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
{
if (constructor == this->ipsec_constructor && this->ipsec)
{
this->ipsec->destroy(this->ipsec);
this->ipsec = NULL;
+ return TRUE;
}
+ return FALSE;
}
-METHOD(kernel_interface_t, add_net_interface, void,
+METHOD(kernel_interface_t, add_net_interface, bool,
private_kernel_interface_t *this, kernel_net_constructor_t constructor)
{
if (!this->net)
{
this->net_constructor = constructor;
this->net = constructor();
+ return this->net != NULL;
}
+ return FALSE;
}
-METHOD(kernel_interface_t, remove_net_interface, void,
+METHOD(kernel_interface_t, remove_net_interface, bool,
private_kernel_interface_t *this, kernel_net_constructor_t constructor)
{
if (constructor == this->net_constructor && this->net)
{
this->net->destroy(this->net);
this->net = NULL;
+ return TRUE;
}
+ return FALSE;
}
METHOD(kernel_interface_t, add_listener, void,
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index 96ce9e26d..45efe8946 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2013 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -265,9 +265,6 @@ struct kernel_interface_t {
/**
* Add a policy to the SPD.
*
- * A policy is always associated to an SA. Traffic which matches a
- * policy is handled by the SA with the same reqid.
- *
* @param src source address of SA
* @param dst dest address of SA
* @param src_ts traffic selector to match traffic source
@@ -309,24 +306,24 @@ struct kernel_interface_t {
/**
* Remove a policy from the SPD.
*
- * The kernel interface implements reference counting for policies.
- * If the same policy is installed multiple times (in the case of rekeying),
- * the reference counter is increased. del_policy() decreases the ref counter
- * and removes the policy only when no more references are available.
- *
+ * @param src source address of SA
+ * @param dst dest address of SA
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
- * @param reqid unique ID of the associated SA
- * @param mark optional mark
+ * @param type type of policy, POLICY_(IPSEC|PASS|DROP)
+ * @param sa details about the SA(s) tied to this policy
+ * @param mark mark for this policy
* @param priority priority of the policy
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_interface_t *this,
+ host_t *src, host_t *dst,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t reqid,
- mark_t mark, policy_priority_t priority);
+ policy_dir_t direction, policy_type_t type,
+ ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority);
/**
* Flush all policies from the SPD.
@@ -502,39 +499,49 @@ struct kernel_interface_t {
/**
* Register an ipsec kernel interface constructor on the manager.
*
- * @param create constructor to register
+ * @param create constructor to register
+ * @return TRUE if the ipsec kernel interface was registered
+ * successfully, FALSE if an interface was already
+ * registered or the registration failed
*/
- void (*add_ipsec_interface)(kernel_interface_t *this,
+ bool (*add_ipsec_interface)(kernel_interface_t *this,
kernel_ipsec_constructor_t create);
/**
* Unregister an ipsec kernel interface constructor.
*
- * @param create constructor to unregister
+ * @param create constructor to unregister
+ * @return TRUE if the ipsec kernel interface was unregistered
+ * successfully, FALSE otherwise
*/
- void (*remove_ipsec_interface)(kernel_interface_t *this,
+ bool (*remove_ipsec_interface)(kernel_interface_t *this,
kernel_ipsec_constructor_t create);
/**
* Register a network kernel interface constructor on the manager.
*
- * @param create constructor to register
+ * @param create constructor to register
+ * @return TRUE if the kernel net interface was registered
+ * successfully, FALSE if an interface was already
+ * registered or the registration failed
*/
- void (*add_net_interface)(kernel_interface_t *this,
+ bool (*add_net_interface)(kernel_interface_t *this,
kernel_net_constructor_t create);
/**
* Unregister a network kernel interface constructor.
*
- * @param create constructor to unregister
+ * @param create constructor to unregister
+ * @return TRUE if the kernel net interface was unregistered
+ * successfully, FALSE otherwise
*/
- void (*remove_net_interface)(kernel_interface_t *this,
+ bool (*remove_net_interface)(kernel_interface_t *this,
kernel_net_constructor_t create);
/**
* Add a listener to the kernel interface.
*
- * @param listener listener to add
+ * @param listener listener to add
*/
void (*add_listener)(kernel_interface_t *this,
kernel_listener_t *listener);
@@ -542,7 +549,7 @@ struct kernel_interface_t {
/**
* Remove a listener from the kernel interface.
*
- * @param listener listener to remove
+ * @param listener listener to remove
*/
void (*remove_listener)(kernel_interface_t *this,
kernel_listener_t *listener);
diff --git a/src/libhydra/kernel/kernel_ipsec.c b/src/libhydra/kernel/kernel_ipsec.c
index 1a32ab4e7..697b1b33d 100644
--- a/src/libhydra/kernel/kernel_ipsec.c
+++ b/src/libhydra/kernel/kernel_ipsec.c
@@ -25,13 +25,14 @@ bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
{
if (reg)
{
- hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface,
+ return hydra->kernel_interface->add_ipsec_interface(
+ hydra->kernel_interface,
(kernel_ipsec_constructor_t)data);
}
else
{
- hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface,
+ return hydra->kernel_interface->remove_ipsec_interface(
+ hydra->kernel_interface,
(kernel_ipsec_constructor_t)data);
}
- return TRUE;
}
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
index 19caaa400..2458db5b9 100644
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ b/src/libhydra/kernel/kernel_ipsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2012 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -186,9 +186,6 @@ struct kernel_ipsec_t {
/**
* Add a policy to the SPD.
*
- * A policy is always associated to an SA. Traffic which matches a
- * policy is handled by the SA with the same reqid.
- *
* @param src source address of SA
* @param dst dest address of SA
* @param src_ts traffic selector to match traffic source
@@ -231,24 +228,24 @@ struct kernel_ipsec_t {
/**
* Remove a policy from the SPD.
*
- * The kernel interface implements reference counting for policies.
- * If the same policy is installed multiple times (in the case of rekeying),
- * the reference counter is increased. del_policy() decreases the ref counter
- * and removes the policy only when no more references are available.
- *
+ * @param src source address of SA
+ * @param dst dest address of SA
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
- * @param reqid unique ID of the associated SA
- * @param mark optional mark
+ * @param type type of policy, POLICY_(IPSEC|PASS|DROP)
+ * @param sa details about the SA(s) tied to this policy
+ * @param mark mark for this policy
* @param priority priority of the policy
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_ipsec_t *this,
+ host_t *src, host_t *dst,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t reqid,
- mark_t mark, policy_priority_t priority);
+ policy_dir_t direction, policy_type_t type,
+ ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority);
/**
* Flush all policies from the SPD.
diff --git a/src/libhydra/kernel/kernel_net.c b/src/libhydra/kernel/kernel_net.c
index 0841ed803..07d8b2999 100644
--- a/src/libhydra/kernel/kernel_net.c
+++ b/src/libhydra/kernel/kernel_net.c
@@ -25,13 +25,14 @@ bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature,
{
if (reg)
{
- hydra->kernel_interface->add_net_interface(hydra->kernel_interface,
+ return hydra->kernel_interface->add_net_interface(
+ hydra->kernel_interface,
(kernel_net_constructor_t)data);
}
else
{
- hydra->kernel_interface->remove_net_interface(hydra->kernel_interface,
+ return hydra->kernel_interface->remove_net_interface(
+ hydra->kernel_interface,
(kernel_net_constructor_t)data);
}
- return TRUE;
}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 605476ef1..8c506d9f4 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2013 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2008 Andreas Steffen
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
@@ -318,11 +318,6 @@ struct private_kernel_netlink_ipsec_t {
bool proto_port_transport;
/**
- * Whether to track the history of a policy
- */
- bool policy_history;
-
- /**
* Whether to always use UPDATE to install policies
*/
bool policy_update;
@@ -2140,7 +2135,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
{
continue;
}
- tmpl->reqid = policy->reqid;
+ tmpl->reqid = ipsec->cfg.reqid;
tmpl->id.proto = protos[i].proto;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = mode2kernel(proto_mode);
@@ -2322,7 +2317,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
current = this->policies->get(this->policies, policy);
if (current)
{
- if (current->reqid != sa->reqid)
+ if (current->reqid && sa->reqid && current->reqid != sa->reqid)
{
DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark "
"%u/0x%08x) for reqid %u, the same policy for reqid %u exists",
@@ -2352,26 +2347,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
dst_ts, mark, sa);
assigned_sa->priority = get_priority(policy, priority);
- if (this->policy_history)
- { /* insert the SA according to its priority */
- enumerator = policy->used_by->create_enumerator(policy->used_by);
- while (enumerator->enumerate(enumerator, (void**)&current_sa))
+ /* insert the SA according to its priority */
+ enumerator = policy->used_by->create_enumerator(policy->used_by);
+ while (enumerator->enumerate(enumerator, (void**)&current_sa))
+ {
+ if (current_sa->priority >= assigned_sa->priority)
{
- if (current_sa->priority >= assigned_sa->priority)
- {
- break;
- }
- update = FALSE;
+ break;
}
- policy->used_by->insert_before(policy->used_by, enumerator,
- assigned_sa);
- enumerator->destroy(enumerator);
- }
- else
- { /* simply insert it last and only update if it is not installed yet */
- policy->used_by->insert_last(policy->used_by, assigned_sa);
- update = !found;
+ update = FALSE;
}
+ policy->used_by->insert_before(policy->used_by, enumerator,
+ assigned_sa);
+ enumerator->destroy(enumerator);
if (!update)
{ /* we don't update the policy if the priority is lower than that of
@@ -2482,8 +2470,9 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
}
METHOD(kernel_ipsec_t, del_policy, status_t,
- private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
mark_t mark, policy_priority_t prio)
{
policy_entry_t *current, policy;
@@ -2494,6 +2483,12 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct xfrm_userpolicy_id *policy_id;
bool is_installed = TRUE;
u_int32_t priority;
+ ipsec_sa_t assigned_sa = {
+ .src = src,
+ .dst = dst,
+ .mark = mark,
+ .cfg = *sa,
+ };
DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%08x)",
src_ts, dst_ts, policy_dir_names, direction,
@@ -2508,7 +2503,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
/* find the policy */
this->mutex->lock(this->mutex);
current = this->policies->get(this->policies, &policy);
- if (!current || current->reqid != reqid)
+ if (!current)
{
if (mark.value)
{
@@ -2525,28 +2520,21 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return NOT_FOUND;
}
- if (this->policy_history)
- { /* remove mapping to SA by reqid and priority */
- priority = get_priority(current, prio);
- enumerator = current->used_by->create_enumerator(current->used_by);
- while (enumerator->enumerate(enumerator, (void**)&mapping))
+ /* remove mapping to SA by reqid and priority */
+ priority = get_priority(current, prio);
+ enumerator = current->used_by->create_enumerator(current->used_by);
+ while (enumerator->enumerate(enumerator, (void**)&mapping))
+ {
+ if (priority == mapping->priority && type == mapping->type &&
+ ipsec_sa_equals(mapping->sa, &assigned_sa))
{
- if (priority == mapping->priority)
- {
- current->used_by->remove_at(current->used_by, enumerator);
- policy_sa_destroy(mapping, &direction, this);
- break;
- }
- is_installed = FALSE;
+ current->used_by->remove_at(current->used_by, enumerator);
+ policy_sa_destroy(mapping, &direction, this);
+ break;
}
- enumerator->destroy(enumerator);
- }
- else
- { /* remove one of the SAs but don't update the policy */
- current->used_by->remove_last(current->used_by, (void**)&mapping);
- policy_sa_destroy(mapping, &direction, this);
is_installed = FALSE;
}
+ enumerator->destroy(enumerator);
if (current->used_by->get_count(current->used_by) > 0)
{ /* policy is used by more SAs, keep in kernel */
@@ -2915,7 +2903,6 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
(hashtable_equals_t)ipsec_sa_equals, 32),
.bypass = array_create(sizeof(bypass_t), 0),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- .policy_history = TRUE,
.policy_update = lib->settings->get_bool(lib->settings,
"%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
.install_routes = lib->settings->get_bool(lib->settings,
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 5027e1759..c67366b86 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
@@ -843,7 +843,9 @@ static kernel_algorithm_t encryption_algs[] = {
/* {ENCR_DES_IV32, 0 }, */
{ENCR_NULL, SADB_EALG_NULL },
{ENCR_AES_CBC, SADB_X_EALG_AESCBC },
-/* {ENCR_AES_CTR, SADB_X_EALG_AESCTR }, */
+#ifdef SADB_X_EALG_AESCTR
+ {ENCR_AES_CTR, SADB_X_EALG_AESCTR },
+#endif
/* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */
/* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */
/* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */
@@ -2689,8 +2691,9 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
}
METHOD(kernel_ipsec_t, del_policy, status_t,
- private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
mark_t mark, policy_priority_t prio)
{
unsigned char request[PFKEY_BUFFER_SIZE];
@@ -2702,6 +2705,11 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
bool first = TRUE, is_installed = TRUE;
u_int32_t priority;
size_t len;
+ ipsec_sa_t assigned_sa = {
+ .src = src,
+ .dst = dst,
+ .cfg = *sa,
+ };
if (dir2kernel(direction) == IPSEC_DIR_INVALID)
{ /* FWD policies are not supported on all platforms */
@@ -2735,7 +2743,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
enumerator = policy->used_by->create_enumerator(policy->used_by);
while (enumerator->enumerate(enumerator, (void**)&mapping))
{
- if (reqid == mapping->sa->cfg.reqid && priority == mapping->priority)
+ if (priority == mapping->priority &&
+ ipsec_sa_equals(mapping->sa, &assigned_sa))
{
to_remove = mapping;
is_installed = first;