diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
commit | 1e980d6be0ef0e243c6fe82b5e855454b97e24a4 (patch) | |
tree | 0d59eec2ce2ed332434ae80fc78a44db9ad293c5 /src/libhydra | |
parent | 5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (diff) | |
download | vyos-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.mk | 1 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_interface.c | 27 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_interface.h | 53 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_ipsec.c | 7 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_ipsec.h | 23 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_net.c | 7 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c | 81 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 19 |
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**)¤t_sa)) + /* insert the SA according to its priority */ + enumerator = policy->used_by->create_enumerator(policy->used_by); + while (enumerator->enumerate(enumerator, (void**)¤t_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; |