summaryrefslogtreecommitdiff
path: root/src/libcharon/sa
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r--src/libcharon/sa/authenticators/authenticator.c7
-rw-r--r--src/libcharon/sa/authenticators/authenticator.h24
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.c38
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.h30
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c30
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.c7
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.c7
-rw-r--r--src/libcharon/sa/child_sa.c138
-rw-r--r--src/libcharon/sa/child_sa.h28
-rw-r--r--src/libcharon/sa/ike_sa.c726
-rw-r--r--src/libcharon/sa/ike_sa.h12
-rw-r--r--src/libcharon/sa/ike_sa_manager.c34
-rw-r--r--src/libcharon/sa/task_manager.c139
-rw-r--r--src/libcharon/sa/task_manager.h21
-rw-r--r--src/libcharon/sa/tasks/child_create.c111
-rw-r--r--src/libcharon/sa/tasks/child_delete.c4
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c95
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c12
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.c10
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c14
-rw-r--r--src/libcharon/sa/tasks/ike_config.c4
-rw-r--r--src/libcharon/sa/tasks/ike_init.c1
-rw-r--r--src/libcharon/sa/trap_manager.c2
23 files changed, 726 insertions, 768 deletions
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c
index 13586a23e..cd340e53e 100644
--- a/src/libcharon/sa/authenticators/authenticator.c
+++ b/src/libcharon/sa/authenticators/authenticator.c
@@ -34,13 +34,6 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
"ECDSA-521 signature");
ENUM_END(auth_method_names, AUTH_ECDSA_521);
-ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
- "any",
- "public key",
- "pre-shared key",
- "EAP",
-);
-
/**
* Described in header.
*/
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h
index fff91ed34..89178b5cf 100644
--- a/src/libcharon/sa/authenticators/authenticator.h
+++ b/src/libcharon/sa/authenticators/authenticator.h
@@ -24,11 +24,10 @@
#define AUTHENTICATOR_H_
typedef enum auth_method_t auth_method_t;
-typedef enum auth_class_t auth_class_t;
typedef struct authenticator_t authenticator_t;
#include <library.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
#include <sa/ike_sa.h>
/**
@@ -76,27 +75,6 @@ enum auth_method_t {
extern enum_name_t *auth_method_names;
/**
- * Class of authentication to use. This is different to auth_method_t in that
- * it does not specify a method, but a class of acceptable methods. The found
- * certificate finally dictates wich method is used.
- */
-enum auth_class_t {
- /** any class acceptable */
- AUTH_CLASS_ANY = 0,
- /** authentication using public keys (RSA, ECDSA) */
- AUTH_CLASS_PUBKEY = 1,
- /** authentication using a pre-shared secrets */
- AUTH_CLASS_PSK = 2,
- /** authentication using EAP */
- AUTH_CLASS_EAP = 3,
-};
-
-/**
- * enum strings for auth_class_t
- */
-extern enum_name_t *auth_class_names;
-
-/**
* Authenticator interface implemented by the various authenticators.
*
* An authenticator implementation handles AUTH and EAP payloads. Received
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c
index 91fa5305f..ad7b92cfa 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.c
+++ b/src/libcharon/sa/authenticators/eap/eap_method.c
@@ -15,44 +15,6 @@
#include "eap_method.h"
-ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
- "EAP_IDENTITY",
- "EAP_NOTIFICATION",
- "EAP_NAK",
- "EAP_MD5",
- "EAP_OTP",
- "EAP_GTC");
-ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC,
- "EAP_SIM");
-ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
- "EAP_AKA");
-ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
- "EAP_MSCHAPV2");
-ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
- "EAP_RADIUS",
- "EAP_EXPANDED",
- "EAP_EXPERIMENTAL");
-ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
-
-ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
- "ID",
- "NTF",
- "NAK",
- "MD5",
- "OTP",
- "GTC");
-ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_GTC,
- "SIM");
-ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM,
- "AKA");
-ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
- "MSCHAPV2");
-ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
- "RAD",
- "EXP",
- "XP");
-ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
-
/*
* See header
*/
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h
index 4cab84535..df354edb4 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.h
+++ b/src/libcharon/sa/authenticators/eap/eap_method.h
@@ -23,7 +23,6 @@
typedef struct eap_method_t eap_method_t;
typedef enum eap_role_t eap_role_t;
-typedef enum eap_type_t eap_type_t;
typedef enum eap_code_t eap_code_t;
#include <library.h>
@@ -43,35 +42,6 @@ enum eap_role_t {
extern enum_name_t *eap_role_names;
/**
- * EAP types, defines the EAP method implementation
- */
-enum eap_type_t {
- EAP_IDENTITY = 1,
- EAP_NOTIFICATION = 2,
- EAP_NAK = 3,
- EAP_MD5 = 4,
- EAP_OTP = 5,
- EAP_GTC = 6,
- EAP_SIM = 18,
- EAP_AKA = 23,
- EAP_MSCHAPV2 = 26,
- /** not a method, but an implementation providing different methods */
- EAP_RADIUS = 253,
- EAP_EXPANDED = 254,
- EAP_EXPERIMENTAL = 255,
-};
-
-/**
- * enum names for eap_type_t.
- */
-extern enum_name_t *eap_type_names;
-
-/**
- * short string enum names for eap_type_t.
- */
-extern enum_name_t *eap_type_short_names;
-
-/**
* Lookup the EAP method type from a string.
*
* @param name EAP method name (such as "md5", "aka")
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
index 4617c4d8d..3c0f3c358 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -140,17 +140,26 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
if (id)
{
- this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
- if (this->method)
+ if (id->get_type(id) == ID_ANY)
{
- if (this->method->initiate(this->method, &out) == NEED_MORE)
+ this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
+ if (this->method)
{
- DBG1(DBG_IKE, "initiating EAP-Identity request");
- return out;
+ if (this->method->initiate(this->method, &out) == NEED_MORE)
+ {
+ DBG1(DBG_IKE, "initiating EAP-Identity request");
+ return out;
+ }
+ this->method->destroy(this->method);
}
- this->method->destroy(this->method);
+ DBG1(DBG_IKE, "EAP-Identity request configured, "
+ "but not supported");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "using configured EAP-Identity %Y", id);
+ this->eap_identity = id->clone(id);
}
- DBG1(DBG_IKE, "EAP-Identity request configured, but not supported");
}
}
/* invoke real EAP method */
@@ -220,7 +229,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
eap_type_t type, received_type;
u_int32_t vendor, received_vendor;
eap_payload_t *out;
- auth_cfg_t *cfg;
if (in->get_code(in) != EAP_RESPONSE)
{
@@ -283,12 +291,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
}
this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
TRUE);
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
- if (vendor)
- {
- cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
- }
this->eap_complete = TRUE;
return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
case FAILED:
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c
index 67197d690..e69f30dcf 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/authenticators/psk_authenticator.c
@@ -63,8 +63,7 @@ static status_t build(private_psk_authenticator_t *this, message_t *message)
other_id = this->ike_sa->get_other_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
my_id, auth_method_names, AUTH_PSK);
- key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
- my_id, other_id);
+ key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id, other_id);
if (key == NULL)
{
DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
@@ -107,8 +106,8 @@ static status_t process(private_psk_authenticator_t *this, message_t *message)
recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
- enumerator = charon->credentials->create_shared_enumerator(
- charon->credentials, SHARED_IKE, my_id, other_id);
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_IKE, my_id, other_id);
while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
{
keys_found++;
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c
index f1dca2702..3c67f6db6 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c
@@ -65,8 +65,7 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message)
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- private = charon->credentials->get_private(charon->credentials, KEY_ANY,
- id, auth);
+ private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
if (private == NULL)
{
DBG1(DBG_IKE, "no private key found for '%Y'", id);
@@ -178,8 +177,8 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message
octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
this->nonce, id);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, key_type, id, auth);
+ enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
+ key_type, id, auth);
while (enumerator->enumerate(enumerator, &public, &current_auth))
{
if (public->verify(public, scheme, octets, auth_data))
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 3fdfb51ad..bd41cba56 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -98,6 +98,16 @@ struct private_child_sa_t {
u_int32_t reqid;
/**
+ * inbound mark used for this child_sa
+ */
+ mark_t mark_in;
+
+ /**
+ * outbound mark used for this child_sa
+ */
+ mark_t mark_out;
+
+ /**
* absolute time when rekeying is scheduled
*/
time_t rekey_time;
@@ -128,6 +138,16 @@ struct private_child_sa_t {
ipsec_mode_t mode;
/**
+ * Action to enforce if peer closes the CHILD_SA
+ */
+ action_t close_action;
+
+ /**
+ * Action to enforce if peer is considered dead
+ */
+ action_t dpd_action;
+
+ /**
* selected proposal
*/
proposal_t *proposal;
@@ -272,6 +292,38 @@ static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp)
}
/**
+ * Implementation of child_sa_t.set_close_action.
+ */
+static void set_close_action(private_child_sa_t *this, action_t action)
+{
+ this->close_action = action;
+}
+
+/**
+ * Implementation of child_sa_t.get_close_action.
+ */
+static action_t get_close_action(private_child_sa_t *this)
+{
+ return this->close_action;
+}
+
+/**
+ * Implementation of child_sa_t.set_dpd_action.
+ */
+static void set_dpd_action(private_child_sa_t *this, action_t action)
+{
+ this->dpd_action = action;
+}
+
+/**
+ * Implementation of child_sa_t.get_dpd_action.
+ */
+static action_t get_dpd_action(private_child_sa_t *this)
+{
+ return this->dpd_action;
+}
+
+/**
* Implementation of child_sa_t.get_proposal
*/
static proposal_t* get_proposal(private_child_sa_t *this)
@@ -389,10 +441,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->my_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->other_addr, this->my_addr,
- this->my_spi, this->protocol, &bytes);
+ this->my_spi, this->protocol,
+ this->mark_in, &bytes);
if (status == SUCCESS)
{
if (bytes > this->my_usebytes)
@@ -408,10 +460,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->other_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->my_addr, this->other_addr,
- this->other_spi, this->protocol, &bytes);
+ this->other_spi, this->protocol,
+ this->mark_out, &bytes);
if (status == SUCCESS)
{
if (bytes > this->other_usebytes)
@@ -443,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
if (inbound)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
+ other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
{
last_use = max(last_use, in);
}
if (this->mode != MODE_TRANSPORT)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
+ other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
{
last_use = max(last_use, fwd);
}
@@ -459,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
else
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
+ my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
{
last_use = max(last_use, out);
}
@@ -623,9 +675,10 @@ static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
}
status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, lifetime,
- enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
- this->encap, update, src_ts, dst_ts);
+ src, dst, spi, this->protocol, this->reqid,
+ inbound ? this->mark_in : this->mark_out,
+ lifetime, enc_alg, encr, int_alg, integ, this->mode,
+ this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
free(lifetime);
@@ -666,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->other_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->other_cpi, routed);
+ this->other_spi, this->protocol, this->reqid, this->mark_out,
+ this->mode, this->ipcomp, this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
if (this->mode != MODE_TRANSPORT)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
}
if (status != SUCCESS)
@@ -726,7 +779,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->my_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
this->other_addr, this->my_addr, other, me,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_in) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -739,7 +792,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->other_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
this->my_addr, this->other_addr, me, other,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_out) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -761,13 +814,13 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, FALSE);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, FALSE);
+ other_ts, my_ts, POLICY_IN, this->mark_in, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, FALSE);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE);
}
/* check whether we have to update a "dynamic" traffic selector */
@@ -793,18 +846,18 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->other_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_out, this->mode,
+ this->ipcomp, this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
}
}
enumerator->destroy(enumerator);
@@ -854,13 +907,13 @@ static void destroy(private_child_sa_t *this)
}
charon->kernel_interface->del_sa(charon->kernel_interface,
this->other_addr, this->my_addr, this->my_spi,
- this->protocol, this->my_cpi);
+ this->protocol, this->my_cpi, this->mark_in);
}
if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
this->my_addr, this->other_addr, this->other_spi,
- this->protocol, this->other_cpi);
+ this->protocol, this->other_cpi, this->mark_out);
}
if (this->config->install_policy(this->config))
@@ -870,13 +923,13 @@ static void destroy(private_child_sa_t *this)
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, unrouted);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, unrouted);
+ other_ts, my_ts, POLICY_IN, this->mark_in, unrouted);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, unrouted);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted);
}
}
enumerator->destroy(enumerator);
@@ -919,6 +972,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
+ this->public.get_close_action = (action_t(*)(child_sa_t*))get_close_action;
+ this->public.set_close_action = (void(*)(child_sa_t*,action_t))set_close_action;
+ this->public.get_dpd_action = (action_t(*)(child_sa_t*))get_dpd_action;
+ this->public.set_dpd_action = (void(*)(child_sa_t*,action_t))set_dpd_action;
this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install;
@@ -942,17 +999,26 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->other_usetime = 0;
this->my_usebytes = 0;
this->other_usebytes = 0;
- /* reuse old reqid if we are rekeying an existing CHILD_SA */
- this->reqid = rekey ? rekey : ++reqid;
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
this->protocol = PROTO_NONE;
this->mode = MODE_TUNNEL;
+ this->close_action = config->get_close_action(config);
+ this->dpd_action = config->get_dpd_action(config);
this->proposal = NULL;
this->rekey_time = 0;
this->expire_time = 0;
this->config = config;
config->get_ref(config);
+ this->reqid = config->get_reqid(config);
+ this->mark_in = config->get_mark(config, TRUE);
+ this->mark_out = config->get_mark(config, FALSE);
+
+ if (!this->reqid)
+ {
+ /* reuse old reqid if we are rekeying an existing CHILD_SA */
+ this->reqid = rekey ? rekey : ++reqid;
+ }
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index e6c603504..95bc297b0 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -208,6 +208,34 @@ struct child_sa_t {
void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
/**
+ * Get the action to enforce if the remote peer closes the CHILD_SA.
+ *
+ * @return close action
+ */
+ action_t (*get_close_action)(child_sa_t *this);
+
+ /**
+ * Override the close action specified by the CHILD_SA config.
+ *
+ * @param close action to enforce
+ */
+ void (*set_close_action)(child_sa_t *this, action_t action);
+
+ /**
+ * Get the action to enforce if the peer is considered dead.
+ *
+ * @return dpd action
+ */
+ action_t (*get_dpd_action)(child_sa_t *this);
+
+ /**
+ * Override the DPD action specified by the CHILD_SA config.
+ *
+ * @param close action to enforce
+ */
+ void (*set_dpd_action)(child_sa_t *this, action_t action);
+
+ /**
* Get the selected proposal.
*
* @return selected proposal
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 023f0749f..7536662ca 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -287,18 +287,14 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
return use_time;
}
-/**
- * Implementation of ike_sa_t.get_unique_id
- */
-static u_int32_t get_unique_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_unique_id, u_int32_t,
+ private_ike_sa_t *this)
{
return this->unique_id;
}
-/**
- * Implementation of ike_sa_t.get_name.
- */
-static char *get_name(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_name, char*,
+ private_ike_sa_t *this)
{
if (this->peer_cfg)
{
@@ -307,10 +303,8 @@ static char *get_name(private_ike_sa_t *this)
return "(unnamed)";
}
-/**
- * Implementation of ike_sa_t.get_statistic.
- */
-static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
+METHOD(ike_sa_t, get_statistic, u_int32_t,
+ private_ike_sa_t *this, statistic_t kind)
{
if (kind < STAT_MAX)
{
@@ -319,52 +313,40 @@ static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
return 0;
}
-/**
- * Implementation of ike_sa_t.get_my_host.
- */
-static host_t *get_my_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_my_host, host_t*,
+ private_ike_sa_t *this)
{
return this->my_host;
}
-/**
- * Implementation of ike_sa_t.set_my_host.
- */
-static void set_my_host(private_ike_sa_t *this, host_t *me)
+METHOD(ike_sa_t, set_my_host, void,
+ private_ike_sa_t *this, host_t *me)
{
DESTROY_IF(this->my_host);
this->my_host = me;
}
-/**
- * Implementation of ike_sa_t.get_other_host.
- */
-static host_t *get_other_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_host, host_t*,
+ private_ike_sa_t *this)
{
return this->other_host;
}
-/**
- * Implementation of ike_sa_t.set_other_host.
- */
-static void set_other_host(private_ike_sa_t *this, host_t *other)
+METHOD(ike_sa_t, set_other_host, void,
+ private_ike_sa_t *this, host_t *other)
{
DESTROY_IF(this->other_host);
this->other_host = other;
}
-/**
- * Implementation of ike_sa_t.get_peer_cfg
- */
-static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*,
+ 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)
+METHOD(ike_sa_t, set_peer_cfg, void,
+ private_ike_sa_t *this, peer_cfg_t *peer_cfg)
{
DESTROY_IF(this->peer_cfg);
peer_cfg->get_ref(peer_cfg);
@@ -377,10 +359,8 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
}
}
-/**
- * Implementation of ike_sa_t.get_auth_cfg
- */
-static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
+METHOD(ike_sa_t, get_auth_cfg, auth_cfg_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -389,10 +369,8 @@ static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
return this->other_auth;
}
-/**
- * Implementation of ike_sa_t.add_auth_cfg
- */
-static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
+METHOD(ike_sa_t, add_auth_cfg, void,
+ private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
{
if (local)
{
@@ -404,11 +382,8 @@ static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
}
}
-/**
- * Implementation of ike_sa_t.create_auth_cfg_enumerator
- */
-static enumerator_t* create_auth_cfg_enumerator(private_ike_sa_t *this,
- bool local)
+METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -424,42 +399,33 @@ static void flush_auth_cfgs(private_ike_sa_t *this)
{
auth_cfg_t *cfg;
- if (lib->settings->get_bool(lib->settings, "charon.flush_auth_cfg", FALSE))
+ while (this->my_auths->remove_last(this->my_auths,
+ (void**)&cfg) == SUCCESS)
{
- while (this->my_auths->remove_last(this->my_auths,
- (void**)&cfg) == SUCCESS)
- {
- cfg->destroy(cfg);
- }
- while (this->other_auths->remove_last(this->other_auths,
- (void**)&cfg) == SUCCESS)
- {
- cfg->destroy(cfg);
- }
+ cfg->destroy(cfg);
+ }
+ while (this->other_auths->remove_last(this->other_auths,
+ (void**)&cfg) == SUCCESS)
+ {
+ cfg->destroy(cfg);
}
}
-/**
- * Implementation of ike_sa_t.get_proposal
- */
-static proposal_t* get_proposal(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_proposal, proposal_t*,
+ private_ike_sa_t *this)
{
return this->proposal;
}
-/**
- * Implementation of ike_sa_t.set_proposal
- */
-static void set_proposal(private_ike_sa_t *this, proposal_t *proposal)
+METHOD(ike_sa_t, set_proposal, void,
+ private_ike_sa_t *this, proposal_t *proposal)
{
DESTROY_IF(this->proposal);
this->proposal = proposal->clone(proposal);
}
-/**
- * Implementation of ike_sa_t.set_message_id
- */
-static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid)
+METHOD(ike_sa_t, set_message_id, void,
+ private_ike_sa_t *this, bool initiate, u_int32_t mid)
{
if (initiate)
{
@@ -471,10 +437,8 @@ static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid)
}
}
-/**
- * Implementation of ike_sa_t.send_keepalive
- */
-static void send_keepalive(private_ike_sa_t *this)
+METHOD(ike_sa_t, send_keepalive, void,
+ private_ike_sa_t *this)
{
send_keepalive_job_t *job;
time_t last_out, now, diff;
@@ -510,52 +474,39 @@ static void send_keepalive(private_ike_sa_t *this)
this->keepalive_interval - diff);
}
-/**
- * Implementation of ike_sa_t.get_ike_cfg
- */
-static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*,
+ 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)
+METHOD(ike_sa_t, set_ike_cfg, void,
+ 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.enable_extension.
- */
-static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
+METHOD(ike_sa_t, enable_extension, void,
+ private_ike_sa_t *this, ike_extension_t extension)
{
this->extensions |= extension;
}
-/**
- * Implementation of ike_sa_t.has_extension.
- */
-static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
+METHOD(ike_sa_t, supports_extension, bool,
+ private_ike_sa_t *this, ike_extension_t extension)
{
return (this->extensions & extension) != FALSE;
}
-/**
- * Implementation of ike_sa_t.has_condition.
- */
-static bool has_condition(private_ike_sa_t *this, ike_condition_t condition)
+METHOD(ike_sa_t, has_condition, bool,
+ private_ike_sa_t *this, ike_condition_t condition)
{
return (this->conditions & condition) != FALSE;
}
-/**
- * Implementation of ike_sa_t.enable_condition.
- */
-static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
- bool enable)
+METHOD(ike_sa_t, set_condition, void,
+ private_ike_sa_t *this, ike_condition_t condition, bool enable)
{
if (has_condition(this, condition) != enable)
{
@@ -601,10 +552,8 @@ static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
}
}
-/**
- * Implementation of ike_sa_t.send_dpd
- */
-static status_t send_dpd(private_ike_sa_t *this)
+METHOD(ike_sa_t, send_dpd, status_t,
+ private_ike_sa_t *this)
{
job_t *job;
time_t diff, delay;
@@ -660,18 +609,14 @@ static status_t send_dpd(private_ike_sa_t *this)
return SUCCESS;
}
-/**
- * Implementation of ike_sa_t.get_state.
- */
-static ike_sa_state_t get_state(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_state, ike_sa_state_t,
+ private_ike_sa_t *this)
{
return this->state;
}
-/**
- * Implementation of ike_sa_t.set_state.
- */
-static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
+METHOD(ike_sa_t, set_state, void,
+ private_ike_sa_t *this, ike_sa_state_t state)
{
DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
get_name(this), this->unique_id,
@@ -754,10 +699,8 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
this->state = state;
}
-/**
- * Implementation of ike_sa_t.reset
- */
-static void reset(private_ike_sa_t *this)
+METHOD(ike_sa_t, reset, void,
+ private_ike_sa_t *this)
{
/* the responder ID is reset, as peer may choose another one */
if (this->ike_sa_id->is_initiator(this->ike_sa_id))
@@ -767,21 +710,22 @@ static void reset(private_ike_sa_t *this)
set_state(this, IKE_CREATED);
+ flush_auth_cfgs(this);
+
+ this->keymat->destroy(this->keymat);
+ this->keymat = keymat_create(this->ike_sa_id->is_initiator(this->ike_sa_id));
+
this->task_manager->reset(this->task_manager, 0, 0);
}
-/**
- * Implementation of ike_sa_t.get_keymat
- */
-static keymat_t* get_keymat(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_keymat, keymat_t*,
+ private_ike_sa_t *this)
{
return this->keymat;
}
-/**
- * Implementation of ike_sa_t.set_virtual_ip
- */
-static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
+METHOD(ike_sa_t, set_virtual_ip, void,
+ private_ike_sa_t *this, bool local, host_t *ip)
{
if (local)
{
@@ -811,10 +755,8 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
}
}
-/**
- * Implementation of ike_sa_t.get_virtual_ip
- */
-static host_t* get_virtual_ip(private_ike_sa_t *this, bool local)
+METHOD(ike_sa_t, get_virtual_ip, host_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -826,27 +768,21 @@ static host_t* get_virtual_ip(private_ike_sa_t *this, bool local)
}
}
-/**
- * Implementation of ike_sa_t.add_additional_address.
- */
-static void add_additional_address(private_ike_sa_t *this, host_t *host)
+METHOD(ike_sa_t, add_additional_address, void,
+ private_ike_sa_t *this, host_t *host)
{
this->additional_addresses->insert_last(this->additional_addresses, host);
}
-/**
- * Implementation of ike_sa_t.create_additional_address_iterator.
- */
-static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
+METHOD(ike_sa_t, create_additional_address_iterator, iterator_t*,
+ private_ike_sa_t *this)
{
return this->additional_addresses->create_iterator(
this->additional_addresses, TRUE);
}
-/**
- * Implementation of ike_sa_t.has_mapping_changed
- */
-static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
+METHOD(ike_sa_t, has_mapping_changed, bool,
+ private_ike_sa_t *this, chunk_t hash)
{
if (this->nat_detection_dest.ptr == NULL)
{
@@ -862,26 +798,20 @@ static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
return TRUE;
}
-/**
- * Implementation of ike_sa_t.set_pending_updates.
- */
-static void set_pending_updates(private_ike_sa_t *this, u_int32_t updates)
+METHOD(ike_sa_t, set_pending_updates, void,
+ private_ike_sa_t *this, u_int32_t updates)
{
this->pending_updates = updates;
}
-/**
- * Implementation of ike_sa_t.get_pending_updates.
- */
-static u_int32_t get_pending_updates(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_pending_updates, u_int32_t,
+ private_ike_sa_t *this)
{
return this->pending_updates;
}
-/**
- * Update hosts, as addresses may change (NAT)
- */
-static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
+METHOD(ike_sa_t, update_hosts, void,
+ private_ike_sa_t *this, host_t *me, host_t *other)
{
bool update = FALSE;
@@ -946,11 +876,8 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
}
}
-/**
- * Implementation of ike_sa_t.generate
- */
-static status_t generate_message(private_ike_sa_t *this, message_t *message,
- packet_t **packet)
+METHOD(ike_sa_t, generate_message, status_t,
+ private_ike_sa_t *this, message_t *message, packet_t **packet)
{
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
@@ -994,10 +921,8 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
-/**
- * Implementation of ike_sa_t.set_kmaddress.
- */
-static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
+METHOD(ike_sa_t, set_kmaddress, void,
+ private_ike_sa_t *this, host_t *local, host_t *remote)
{
DESTROY_IF(this->local_host);
DESTROY_IF(this->remote_host);
@@ -1006,46 +931,35 @@ static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
}
#ifdef ME
-/**
- * Implementation of ike_sa_t.act_as_mediation_server.
- */
-static void act_as_mediation_server(private_ike_sa_t *this)
+METHOD(ike_sa_t, act_as_mediation_server, void,
+ private_ike_sa_t *this)
{
charon->mediation_manager->update_sa_id(charon->mediation_manager,
this->other_id, this->ike_sa_id);
this->is_mediation_server = TRUE;
}
-/**
- * Implementation of ike_sa_t.get_server_reflexive_host.
- */
-static host_t *get_server_reflexive_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_server_reflexive_host, host_t*,
+ private_ike_sa_t *this)
{
return this->server_reflexive_host;
}
-/**
- * Implementation of ike_sa_t.set_server_reflexive_host.
- */
-static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host)
+METHOD(ike_sa_t, set_server_reflexive_host, void,
+ private_ike_sa_t *this, host_t *host)
{
DESTROY_IF(this->server_reflexive_host);
this->server_reflexive_host = host;
}
-/**
- * Implementation of ike_sa_t.get_connect_id.
- */
-static chunk_t get_connect_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_connect_id, chunk_t,
+ private_ike_sa_t *this)
{
return this->connect_id;
}
-/**
- * Implementation of ike_sa_t.respond
- */
-static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
- chunk_t connect_id)
+METHOD(ike_sa_t, respond, status_t,
+ private_ike_sa_t *this, identification_t *peer_id, chunk_t connect_id)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->respond(task, peer_id, connect_id);
@@ -1053,10 +967,8 @@ static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.callback
- */
-static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
+METHOD(ike_sa_t, callback, status_t,
+ private_ike_sa_t *this, identification_t *peer_id)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->callback(task, peer_id);
@@ -1064,12 +976,9 @@ static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.relay
- */
-static status_t relay(private_ike_sa_t *this, identification_t *requester,
- chunk_t connect_id, chunk_t connect_key,
- linked_list_t *endpoints, bool response)
+METHOD(ike_sa_t, relay, status_t,
+ private_ike_sa_t *this, identification_t *requester, chunk_t connect_id,
+ chunk_t connect_key, linked_list_t *endpoints, bool response)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->relay(task, requester, connect_id, connect_key, endpoints, response);
@@ -1077,11 +986,8 @@ static status_t relay(private_ike_sa_t *this, identification_t *requester,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.initiate_mediation
- */
-static status_t initiate_mediation(private_ike_sa_t *this,
- peer_cfg_t *mediated_cfg)
+METHOD(ike_sa_t, initiate_mediation, status_t,
+ private_ike_sa_t *this, peer_cfg_t *mediated_cfg)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->connect(task, mediated_cfg->get_peer_id(mediated_cfg));
@@ -1089,11 +995,8 @@ static status_t initiate_mediation(private_ike_sa_t *this,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.initiate_mediated
- */
-static status_t initiate_mediated(private_ike_sa_t *this, host_t *me,
- host_t *other, chunk_t connect_id)
+METHOD(ike_sa_t, initiate_mediated, status_t,
+ private_ike_sa_t *this, host_t *me, host_t *other, chunk_t connect_id)
{
set_my_host(this, me->clone(me));
set_other_host(this, other->clone(other));
@@ -1166,12 +1069,9 @@ static void resolve_hosts(private_ike_sa_t *this)
}
}
-/**
- * Implementation of ike_sa_t.initiate
- */
-static status_t initiate(private_ike_sa_t *this,
- child_cfg_t *child_cfg, u_int32_t reqid,
- traffic_selector_t *tsi, traffic_selector_t *tsr)
+METHOD(ike_sa_t, initiate, status_t,
+ private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
{
task_t *task;
@@ -1259,10 +1159,8 @@ static status_t initiate(private_ike_sa_t *this,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.process_message.
- */
-static status_t process_message(private_ike_sa_t *this, message_t *message)
+METHOD(ike_sa_t, process_message, status_t,
+ private_ike_sa_t *this, message_t *message)
{
status_t status;
bool is_request;
@@ -1367,7 +1265,9 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
status = this->task_manager->process_message(this->task_manager, message);
if (message->get_exchange_type(message) == IKE_AUTH &&
- this->state == IKE_ESTABLISHED)
+ this->state == IKE_ESTABLISHED &&
+ lib->settings->get_bool(lib->settings,
+ "charon.flush_auth_cfg", FALSE))
{ /* authentication completed */
flush_auth_cfgs(this);
}
@@ -1375,43 +1275,33 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
return status;
}
-/**
- * Implementation of ike_sa_t.get_id.
- */
-static ike_sa_id_t* get_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_id, ike_sa_id_t*,
+ private_ike_sa_t *this)
{
return this->ike_sa_id;
}
-/**
- * Implementation of ike_sa_t.get_my_id.
- */
-static identification_t* get_my_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_my_id, identification_t*,
+ private_ike_sa_t *this)
{
return this->my_id;
}
-/**
- * Implementation of ike_sa_t.set_my_id.
- */
-static void set_my_id(private_ike_sa_t *this, identification_t *me)
+METHOD(ike_sa_t, set_my_id, void,
+ private_ike_sa_t *this, identification_t *me)
{
DESTROY_IF(this->my_id);
this->my_id = me;
}
-/**
- * Implementation of ike_sa_t.get_other_id.
- */
-static identification_t* get_other_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_id, identification_t*,
+ private_ike_sa_t *this)
{
return this->other_id;
}
-/**
- * Implementation of ike_sa_t.get_other_eap_id.
- */
-static identification_t* get_other_eap_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_eap_id, identification_t*,
+ private_ike_sa_t *this)
{
identification_t *id = NULL, *current;
enumerator_t *enumerator;
@@ -1440,28 +1330,21 @@ static identification_t* get_other_eap_id(private_ike_sa_t *this)
return this->other_id;
}
-/**
- * Implementation of ike_sa_t.set_other_id.
- */
-static void set_other_id(private_ike_sa_t *this, identification_t *other)
+METHOD(ike_sa_t, set_other_id, void,
+ private_ike_sa_t *this, identification_t *other)
{
DESTROY_IF(this->other_id);
this->other_id = other;
}
-/**
- * Implementation of ike_sa_t.add_child_sa.
- */
-static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
+METHOD(ike_sa_t, add_child_sa, void,
+ private_ike_sa_t *this, child_sa_t *child_sa)
{
this->child_sas->insert_last(this->child_sas, child_sa);
}
-/**
- * Implementation of ike_sa_t.get_child_sa.
- */
-static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi, bool inbound)
+METHOD(ike_sa_t, get_child_sa, child_sa_t*,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool inbound)
{
iterator_t *iterator;
child_sa_t *current, *found = NULL;
@@ -1479,19 +1362,14 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return found;
}
-/**
- * Implementation of ike_sa_t.create_child_sa_iterator.
- */
-static iterator_t* create_child_sa_iterator(private_ike_sa_t *this)
+METHOD(ike_sa_t, create_child_sa_iterator, iterator_t*,
+ private_ike_sa_t *this)
{
return this->child_sas->create_iterator(this->child_sas, TRUE);
}
-/**
- * Implementation of ike_sa_t.rekey_child_sa.
- */
-static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, rekey_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
child_rekey_t *child_rekey;
@@ -1500,11 +1378,8 @@ static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.delete_child_sa.
- */
-static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, delete_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
child_delete_t *child_delete;
@@ -1513,11 +1388,8 @@ static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.destroy_child_sa.
- */
-static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, destroy_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
iterator_t *iterator;
child_sa_t *child_sa;
@@ -1539,10 +1411,8 @@ static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return status;
}
-/**
- * Implementation of public_ike_sa_t.delete.
- */
-static status_t delete_(private_ike_sa_t *this)
+METHOD(ike_sa_t, delete_, status_t,
+ private_ike_sa_t *this)
{
ike_delete_t *ike_delete;
@@ -1567,10 +1437,8 @@ static status_t delete_(private_ike_sa_t *this)
return DESTROY_ME;
}
-/**
- * Implementation of ike_sa_t.rekey.
- */
-static status_t rekey(private_ike_sa_t *this)
+METHOD(ike_sa_t, rekey, status_t,
+ private_ike_sa_t *this)
{
ike_rekey_t *ike_rekey;
@@ -1580,10 +1448,8 @@ static status_t rekey(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.reauth
- */
-static status_t reauth(private_ike_sa_t *this)
+METHOD(ike_sa_t, reauth, status_t,
+ private_ike_sa_t *this)
{
task_t *task;
@@ -1618,10 +1484,8 @@ static status_t reauth(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.reestablish
- */
-static status_t reestablish(private_ike_sa_t *this)
+METHOD(ike_sa_t, reestablish, status_t,
+ private_ike_sa_t *this)
{
ike_sa_t *new;
host_t *host;
@@ -1636,14 +1500,13 @@ static status_t reestablish(private_ike_sa_t *this)
iterator = create_child_sa_iterator(this);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_cfg = child_sa->get_config(child_sa);
if (this->state == IKE_DELETING)
{
- action = child_cfg->get_close_action(child_cfg);
+ action = child_sa->get_close_action(child_sa);
}
else
{
- action = child_cfg->get_dpd_action(child_cfg);
+ action = child_sa->get_dpd_action(child_sa);
}
switch (action)
{
@@ -1651,7 +1514,8 @@ static status_t reestablish(private_ike_sa_t *this)
restart = TRUE;
break;
case ACTION_ROUTE:
- charon->traps->install(charon->traps, this->peer_cfg, child_cfg);
+ charon->traps->install(charon->traps, this->peer_cfg,
+ child_sa->get_config(child_sa));
break;
default:
break;
@@ -1707,18 +1571,18 @@ static status_t reestablish(private_ike_sa_t *this)
iterator = create_child_sa_iterator(this);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_cfg = child_sa->get_config(child_sa);
if (this->state == IKE_DELETING)
{
- action = child_cfg->get_close_action(child_cfg);
+ action = child_sa->get_close_action(child_sa);
}
else
{
- action = child_cfg->get_dpd_action(child_cfg);
+ action = child_sa->get_dpd_action(child_sa);
}
switch (action)
{
case ACTION_RESTART:
+ child_cfg = child_sa->get_config(child_sa);
DBG1(DBG_IKE, "restarting CHILD_SA %s",
child_cfg->get_name(child_cfg));
child_cfg->get_ref(child_cfg);
@@ -1750,9 +1614,41 @@ static status_t reestablish(private_ike_sa_t *this)
}
/**
- * Implementation of ike_sa_t.retransmit.
+ * Requeue the IKE_SA_INIT tasks for initiation, if required
*/
-static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
+static void requeue_init_tasks(private_ike_sa_t *this)
+{
+ enumerator_t *enumerator;
+ bool has_init = FALSE;
+ task_t *task;
+
+ /* if we have advanced to IKE_AUTH, the IKE_INIT and related tasks
+ * have already completed. Recreate them if necessary. */
+ enumerator = this->task_manager->create_task_enumerator(
+ this->task_manager, TASK_QUEUE_QUEUED);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == IKE_INIT)
+ {
+ has_init = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!has_init)
+ {
+ task = (task_t*)ike_vendor_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_natd_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
+ this->task_manager->queue_task(this->task_manager, task);
+ }
+}
+
+METHOD(ike_sa_t, retransmit, status_t,
+ private_ike_sa_t *this, u_int32_t message_id)
{
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
@@ -1770,6 +1666,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
this->keyingtry + 1, tries);
reset(this);
+ requeue_init_tasks(this);
return this->task_manager->initiate(this->task_manager);
}
DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
@@ -1790,10 +1687,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
return SUCCESS;
}
-/**
- * Implementation of ike_sa_t.set_auth_lifetime.
- */
-static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
+METHOD(ike_sa_t, set_auth_lifetime, void,
+ private_ike_sa_t *this, u_int32_t lifetime)
{
u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg);
u_int32_t reauth_time = time_monotonic(NULL) + lifetime - reduction;
@@ -1823,10 +1718,8 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
}
}
-/**
- * Implementation of ike_sa_t.roam.
- */
-static status_t roam(private_ike_sa_t *this, bool address)
+METHOD(ike_sa_t, roam, status_t,
+ private_ike_sa_t *this, bool address)
{
host_t *src;
ike_mobike_t *mobike;
@@ -1919,12 +1812,9 @@ static status_t roam(private_ike_sa_t *this, bool address)
return reauth(this);
}
-/**
- * Implementation of ike_sa_t.add_configuration_attribute
- */
-static void add_configuration_attribute(private_ike_sa_t *this,
- attribute_handler_t *handler,
- configuration_attribute_type_t type, chunk_t data)
+METHOD(ike_sa_t, add_configuration_attribute, void,
+ private_ike_sa_t *this, attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data)
{
attribute_entry_t *entry = malloc_thing(attribute_entry_t);
@@ -1935,11 +1825,16 @@ static void add_configuration_attribute(private_ike_sa_t *this,
this->attributes->insert_last(this->attributes, entry);
}
-/**
- * Implementation of ike_sa_t.inherit.
- */
-static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
+METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
+ private_ike_sa_t *this, task_queue_t queue)
+{
+ return this->task_manager->create_task_enumerator(this->task_manager, queue);
+}
+
+METHOD(ike_sa_t, inherit, status_t,
+ private_ike_sa_t *this, ike_sa_t *other_public)
{
+ private_ike_sa_t *other = (private_ike_sa_t*)other_public;
child_sa_t *child_sa;
attribute_entry_t *entry;
@@ -2021,10 +1916,8 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.destroy.
- */
-static void destroy(private_ike_sa_t *this)
+METHOD(ike_sa_t, destroy, void,
+ private_ike_sa_t *this)
{
attribute_entry_t *entry;
@@ -2106,122 +1999,107 @@ static void destroy(private_ike_sa_t *this)
*/
ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
{
- private_ike_sa_t *this = malloc_thing(private_ike_sa_t);
+ private_ike_sa_t *this;
static u_int32_t unique_id = 0;
- /* Public functions */
- this->public.get_state = (ike_sa_state_t (*)(ike_sa_t*)) get_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_statistic = (u_int32_t(*)(ike_sa_t*, statistic_t kind))get_statistic;
- this->public.process_message = (status_t (*)(ike_sa_t*, message_t*)) process_message;
- this->public.initiate = (status_t (*)(ike_sa_t*,child_cfg_t*,u_int32_t,traffic_selector_t*,traffic_selector_t*)) initiate;
- this->public.get_ike_cfg = (ike_cfg_t* (*)(ike_sa_t*))get_ike_cfg;
- this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
- this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg;
- this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
- this->public.get_auth_cfg = (auth_cfg_t*(*)(ike_sa_t*, bool local))get_auth_cfg;
- this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(ike_sa_t*, bool local))create_auth_cfg_enumerator;
- this->public.add_auth_cfg = (void(*)(ike_sa_t*, bool local, auth_cfg_t *cfg))add_auth_cfg;
- this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
- this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
- this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
- this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host;
- this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host;
- this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host;
- this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_other_host;
- this->public.set_message_id = (void(*)(ike_sa_t*, bool inbound, u_int32_t mid))set_message_id;
- this->public.update_hosts = (void(*)(ike_sa_t*, host_t *me, host_t *other))update_hosts;
- this->public.get_my_id = (identification_t* (*)(ike_sa_t*)) get_my_id;
- this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id;
- this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id;
- this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id;
- this->public.get_other_eap_id = (identification_t* (*)(ike_sa_t*)) get_other_eap_id;
- this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
- this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
- this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
- this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
- this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates;
- this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates;
- this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
- this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
- this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed;
- this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
- this->public.delete = (status_t (*)(ike_sa_t*))delete_;
- this->public.destroy = (void (*)(ike_sa_t*))destroy;
- this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
- this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
- this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat;
- this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa;
- this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
- this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
- this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
- this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
- this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
- this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
- this->public.reauth = (status_t (*)(ike_sa_t*))reauth;
- this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
- this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime;
- this->public.roam = (status_t(*)(ike_sa_t*,bool))roam;
- this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
- this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
- this->public.reset = (void (*)(ike_sa_t*))reset;
- this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id;
- this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
- this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
- this->public.add_configuration_attribute = (void(*)(ike_sa_t*, attribute_handler_t *handler,configuration_attribute_type_t type, chunk_t data))add_configuration_attribute;
- this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
+ INIT(this,
+ .public = {
+ .get_state = _get_state,
+ .set_state = _set_state,
+ .get_name = _get_name,
+ .get_statistic = _get_statistic,
+ .process_message = _process_message,
+ .initiate = _initiate,
+ .get_ike_cfg = _get_ike_cfg,
+ .set_ike_cfg = _set_ike_cfg,
+ .get_peer_cfg = _get_peer_cfg,
+ .set_peer_cfg = _set_peer_cfg,
+ .get_auth_cfg = _get_auth_cfg,
+ .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
+ .add_auth_cfg = _add_auth_cfg,
+ .get_proposal = _get_proposal,
+ .set_proposal = _set_proposal,
+ .get_id = _get_id,
+ .get_my_host = _get_my_host,
+ .set_my_host = _set_my_host,
+ .get_other_host = _get_other_host,
+ .set_other_host = _set_other_host,
+ .set_message_id = _set_message_id,
+ .update_hosts = _update_hosts,
+ .get_my_id = _get_my_id,
+ .set_my_id = _set_my_id,
+ .get_other_id = _get_other_id,
+ .set_other_id = _set_other_id,
+ .get_other_eap_id = _get_other_eap_id,
+ .enable_extension = _enable_extension,
+ .supports_extension = _supports_extension,
+ .set_condition = _set_condition,
+ .has_condition = _has_condition,
+ .set_pending_updates = _set_pending_updates,
+ .get_pending_updates = _get_pending_updates,
+ .create_additional_address_iterator = _create_additional_address_iterator,
+ .add_additional_address = _add_additional_address,
+ .has_mapping_changed = _has_mapping_changed,
+ .retransmit = _retransmit,
+ .delete = _delete_,
+ .destroy = _destroy,
+ .send_dpd = _send_dpd,
+ .send_keepalive = _send_keepalive,
+ .get_keymat = _get_keymat,
+ .add_child_sa = _add_child_sa,
+ .get_child_sa = _get_child_sa,
+ .create_child_sa_iterator = _create_child_sa_iterator,
+ .rekey_child_sa = _rekey_child_sa,
+ .delete_child_sa = _delete_child_sa,
+ .destroy_child_sa = _destroy_child_sa,
+ .rekey = _rekey,
+ .reauth = _reauth,
+ .reestablish = _reestablish,
+ .set_auth_lifetime = _set_auth_lifetime,
+ .roam = _roam,
+ .inherit = _inherit,
+ .generate_message = _generate_message,
+ .reset = _reset,
+ .get_unique_id = _get_unique_id,
+ .set_virtual_ip = _set_virtual_ip,
+ .get_virtual_ip = _get_virtual_ip,
+ .add_configuration_attribute = _add_configuration_attribute,
+ .set_kmaddress = _set_kmaddress,
+ .create_task_enumerator = _create_task_enumerator,
#ifdef ME
- this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
- this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
- this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
- this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id;
- this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
- this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,chunk_t)) initiate_mediated;
- this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
- this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
- this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
+ .act_as_mediation_server = _act_as_mediation_server,
+ .get_server_reflexive_host = _get_server_reflexive_host,
+ .set_server_reflexive_host = _set_server_reflexive_host,
+ .get_connect_id = _get_connect_id,
+ .initiate_mediation = _initiate_mediation,
+ .initiate_mediated = _initiate_mediated,
+ .relay = _relay,
+ .callback = _callback,
+ .respond = _respond,
#endif /* ME */
-
- /* initialize private fields */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
- this->child_sas = linked_list_create();
- this->my_host = host_create_any(AF_INET);
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .child_sas = linked_list_create(),
+ .my_host = host_create_any(AF_INET),
+ .other_host = host_create_any(AF_INET),
+ .my_id = identification_create_from_encoding(ID_ANY, chunk_empty),
+ .other_id = identification_create_from_encoding(ID_ANY, chunk_empty),
+ .keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id)),
+ .state = IKE_CREATED,
+ .stats[STAT_INBOUND] = time_monotonic(NULL),
+ .stats[STAT_OUTBOUND] = time_monotonic(NULL),
+ .my_auth = auth_cfg_create(),
+ .other_auth = auth_cfg_create(),
+ .my_auths = linked_list_create(),
+ .other_auths = linked_list_create(),
+ .task_manager = task_manager_create(&this->public),
+ .unique_id = ++unique_id,
+ .additional_addresses = linked_list_create(),
+ .attributes = linked_list_create(),
+ .keepalive_interval = lib->settings->get_time(lib->settings,
+ "charon.keep_alive", KEEPALIVE_INTERVAL),
+ );
this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
- this->other_host = host_create_any(AF_INET);
- this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
- this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
- this->extensions = 0;
- this->conditions = 0;
- this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id));
- this->state = IKE_CREATED;
- this->keepalive_interval = lib->settings->get_time(lib->settings,
- "charon.keep_alive", KEEPALIVE_INTERVAL);
- memset(this->stats, 0, sizeof(this->stats));
- this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
- this->ike_cfg = NULL;
- this->peer_cfg = NULL;
- this->my_auth = auth_cfg_create();
- this->other_auth = auth_cfg_create();
- this->my_auths = linked_list_create();
- this->other_auths = linked_list_create();
- this->proposal = NULL;
- this->task_manager = task_manager_create(&this->public);
- this->unique_id = ++unique_id;
- this->my_virtual_ip = NULL;
- this->other_virtual_ip = NULL;
- this->additional_addresses = linked_list_create();
- this->attributes = linked_list_create();
- this->nat_detection_dest = chunk_empty;
- this->pending_updates = 0;
- this->keyingtry = 0;
- this->local_host = NULL;
- this->remote_host = NULL;
-#ifdef ME
- this->is_mediation_server = FALSE;
- this->server_reflexive_host = NULL;
- this->connect_id = chunk_empty;
-#endif /* ME */
return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index c61502edf..34842a573 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -37,11 +37,11 @@ typedef struct ike_sa_t ike_sa_t;
#include <encoding/payloads/configuration_attribute.h>
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task_manager.h>
#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
/**
* Timeout in seconds after that a half open IKE_SA gets deleted.
@@ -888,6 +888,14 @@ struct ike_sa_t {
void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
/**
+ * Create enumerator over a task queue of this IKE_SA.
+ *
+ * @param queue type to enumerate
+ * @return enumerator over task_t
+ */
+ enumerator_t* (*create_task_enumerator)(ike_sa_t *this, task_queue_t queue);
+
+ /**
* Inherit all attributes of other to this after rekeying.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 3ef0f3bb0..c71c3b297 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -886,9 +886,10 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
{
if (wait_for_entry(this, entry, segment))
{
- DBG2(DBG_MGR, "IKE_SA successfully checked out");
entry->checked_out = TRUE;
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -916,7 +917,8 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
}
ike_sa = ike_sa_create(ike_sa_id);
- DBG2(DBG_MGR, "created IKE_SA");
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
if (!initiator)
{
@@ -971,10 +973,11 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
}
else if (wait_for_entry(this, entry, segment))
{
- DBG2(DBG_MGR, "IKE_SA checked out by hash");
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] checked out by hash",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -998,7 +1001,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
entry->init_hash = hash;
ike_sa = entry->ike_sa;
- DBG2(DBG_MGR, "created IKE_SA");
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
else
{
@@ -1027,7 +1031,6 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
else if (wait_for_entry(this, entry, segment))
{
ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
- DBG2(DBG_MGR, "IKE_SA successfully checked out");
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
if (ike_id->get_responder_spi(ike_id) == 0)
@@ -1035,6 +1038,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
}
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -1056,6 +1061,8 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
ike_cfg_t *current_ike;
u_int segment;
+ DBG2(DBG_MGR, "checkout IKE_SA by config");
+
if (!this->reuse_ikesa)
{ /* IKE_SA reuse disable by config */
ike_sa = checkout_new(this, TRUE);
@@ -1081,10 +1088,11 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
current_ike = current_peer->get_ike_cfg(current_peer);
if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg)))
{
- DBG2(DBG_MGR, "found an existing IKE_SA with a '%s' config",
- current_peer->get_name(current_peer));
entry->checked_out = TRUE;
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config",
+ ike_sa->get_unique_id(ike_sa),
+ current_peer->get_name(current_peer));
break;
}
}
@@ -1112,6 +1120,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
child_sa_t *child_sa;
u_int segment;
+ DBG2(DBG_MGR, "checkout IKE_SA by ID");
+
enumerator = create_table_enumerator(this);
while (enumerator->enumerate(enumerator, &entry, &segment))
{
@@ -1142,6 +1152,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
if (ike_sa)
{
entry->checked_out = TRUE;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
break;
}
}
@@ -1195,6 +1207,8 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
if (ike_sa)
{
entry->checked_out = TRUE;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
break;
}
}
@@ -1251,7 +1265,8 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
other_id = ike_sa->get_other_id(ike_sa);
other = ike_sa->get_other_host(ike_sa);
- DBG2(DBG_MGR, "checkin IKE_SA");
+ DBG2(DBG_MGR, "checkin IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
/* look for the entry */
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
@@ -1327,7 +1342,8 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa
ike_sa_id = ike_sa->get_id(ike_sa);
- DBG2(DBG_MGR, "checkin and destroy IKE_SA");
+ DBG2(DBG_MGR, "checkin and destroy IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
{
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index eeda6c860..a68826440 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -195,10 +195,8 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
return found;
}
-/**
- * Implementation of task_manager_t.retransmit
- */
-static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
+METHOD(task_manager_t, retransmit, status_t,
+ private_task_manager_t *this, u_int32_t message_id)
{
if (message_id == this->initiating.mid)
{
@@ -281,11 +279,8 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
return SUCCESS;
}
-/**
- * build a request using the active task list
- * Implementation of task_manager_t.initiate
- */
-static status_t build_request(private_task_manager_t *this)
+METHOD(task_manager_t, initiate, status_t,
+ private_task_manager_t *this)
{
iterator_t *iterator;
task_t *task;
@@ -296,7 +291,8 @@ static status_t build_request(private_task_manager_t *this)
if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
{
- DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
+ DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
+ exchange_type_names, this->initiating.type);
/* do not initiate if we already have a message in the air */
return SUCCESS;
}
@@ -534,7 +530,7 @@ static status_t process_response(private_task_manager_t *this,
{ /* start all over again if we were reset */
this->reset = FALSE;
iterator->destroy(iterator);
- return build_request(this);
+ return initiate(this);
}
}
iterator->destroy(iterator);
@@ -544,7 +540,7 @@ static status_t process_response(private_task_manager_t *this,
this->initiating.packet->destroy(this->initiating.packet);
this->initiating.packet = NULL;
- return build_request(this);
+ return initiate(this);
}
/**
@@ -883,10 +879,8 @@ static status_t process_request(private_task_manager_t *this,
return build_response(this, message);
}
-/**
- * Implementation of task_manager_t.process_message
- */
-static status_t process_message(private_task_manager_t *this, message_t *msg)
+METHOD(task_manager_t, process_message, status_t,
+ private_task_manager_t *this, message_t *msg)
{
u_int32_t mid = msg->get_message_id(msg);
@@ -943,10 +937,8 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
return SUCCESS;
}
-/**
- * Implementation of task_manager_t.queue_task
- */
-static void queue_task(private_task_manager_t *this, task_t *task)
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
{
if (task->get_type(task) == IKE_MOBIKE)
{ /* there is no need to queue more than one mobike task */
@@ -969,11 +961,10 @@ static void queue_task(private_task_manager_t *this, task_t *task)
this->queued_tasks->insert_last(this->queued_tasks, task);
}
-/**
- * Implementation of task_manager_t.adopt_tasks
- */
-static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
+METHOD(task_manager_t, adopt_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
{
+ private_task_manager_t *other = (private_task_manager_t*)other_public;
task_t *task;
/* move queued tasks from other to this */
@@ -986,20 +977,16 @@ static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *ot
}
}
-/**
- * Implementation of task_manager_t.busy
- */
-static bool busy(private_task_manager_t *this)
+METHOD(task_manager_t, busy, bool,
+ private_task_manager_t *this)
{
return (this->active_tasks->get_count(this->active_tasks) > 0);
}
-/**
- * Implementation of task_manager_t.reset
- */
-static void reset(private_task_manager_t *this,
- u_int32_t initiate, u_int32_t respond)
+METHOD(task_manager_t, reset, void,
+ private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
{
+ enumerator_t *enumerator;
task_t *task;
/* reset message counters and retransmit packets */
@@ -1017,6 +1004,14 @@ static void reset(private_task_manager_t *this,
}
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ /* reset queued tasks */
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ task->migrate(task, this->ike_sa);
+ }
+ enumerator->destroy(enumerator);
+
/* reset active tasks */
while (this->active_tasks->remove_last(this->active_tasks,
(void**)&task) == SUCCESS)
@@ -1028,10 +1023,24 @@ static void reset(private_task_manager_t *this,
this->reset = TRUE;
}
-/**
- * Implementation of task_manager_t.destroy
- */
-static void destroy(private_task_manager_t *this)
+METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ return this->active_tasks->create_enumerator(this->active_tasks);
+ case TASK_QUEUE_PASSIVE:
+ return this->passive_tasks->create_enumerator(this->passive_tasks);
+ case TASK_QUEUE_QUEUED:
+ return this->queued_tasks->create_enumerator(this->queued_tasks);
+ default:
+ return enumerator_create_empty();
+ }
+}
+
+METHOD(task_manager_t, destroy, void,
+ private_task_manager_t *this)
{
flush(this);
@@ -1049,34 +1058,32 @@ static void destroy(private_task_manager_t *this)
*/
task_manager_t *task_manager_create(ike_sa_t *ike_sa)
{
- private_task_manager_t *this = malloc_thing(private_task_manager_t);
-
- this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
- this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
- this->public.initiate = (status_t(*)(task_manager_t*))build_request;
- this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
- this->public.reset = (void(*)(task_manager_t*,u_int32_t,u_int32_t))reset;
- this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
- this->public.busy = (bool(*)(task_manager_t*))busy;
- this->public.destroy = (void(*)(task_manager_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->responding.packet = NULL;
- this->initiating.packet = NULL;
- this->responding.mid = 0;
- this->initiating.mid = 0;
- this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- this->queued_tasks = linked_list_create();
- this->active_tasks = linked_list_create();
- this->passive_tasks = linked_list_create();
- this->reset = FALSE;
-
- this->retransmit_tries = lib->settings->get_int(lib->settings,
- "charon.retransmit_tries", RETRANSMIT_TRIES);
- this->retransmit_timeout = lib->settings->get_double(lib->settings,
- "charon.retransmit_timeout", RETRANSMIT_TIMEOUT);
- this->retransmit_base = lib->settings->get_double(lib->settings,
- "charon.retransmit_base", RETRANSMIT_BASE);
+ private_task_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .process_message = _process_message,
+ .queue_task = _queue_task,
+ .initiate = _initiate,
+ .retransmit = _retransmit,
+ .reset = _reset,
+ .adopt_tasks = _adopt_tasks,
+ .busy = _busy,
+ .create_task_enumerator = _create_task_enumerator,
+ .destroy = _destroy,
+ },
+ .ike_sa = ike_sa,
+ .initiating.type = EXCHANGE_TYPE_UNDEFINED,
+ .queued_tasks = linked_list_create(),
+ .active_tasks = linked_list_create(),
+ .passive_tasks = linked_list_create(),
+ .retransmit_tries = lib->settings->get_int(lib->settings,
+ "charon.retransmit_tries", RETRANSMIT_TRIES),
+ .retransmit_timeout = lib->settings->get_double(lib->settings,
+ "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
+ .retransmit_base = lib->settings->get_double(lib->settings,
+ "charon.retransmit_base", RETRANSMIT_BASE),
+ );
return &this->public;
}
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 731ed4898..14fccd5f9 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -22,6 +22,7 @@
#define TASK_MANAGER_H_
typedef struct task_manager_t task_manager_t;
+typedef enum task_queue_t task_queue_t;
#include <limits.h>
@@ -55,6 +56,17 @@ typedef struct task_manager_t task_manager_t;
*/
#define ROUTEABILITY_CHECK_TRIES 10
+/**
+ * Type of task queues the task manager uses to handle tasks
+ */
+enum task_queue_t {
+ /** tasks currently active, initiated by us */
+ TASK_QUEUE_ACTIVE,
+ /** passive tasks initiated by the remote peer */
+ TASK_QUEUE_PASSIVE,
+ /** tasks queued for initiated, but not yet activated */
+ TASK_QUEUE_QUEUED,
+};
/**
* The task manager, juggles task and handles message exchanges.
@@ -158,6 +170,15 @@ struct task_manager_t {
bool (*busy) (task_manager_t *this);
/**
+ * Create an enumerator over tasks in a specific queue.
+ *
+ * @param queue queue to create an enumerator over
+ * @return enumerator over task_t
+ */
+ enumerator_t* (*create_task_enumerator)(task_manager_t *this,
+ task_queue_t queue);
+
+ /**
* Destroy the task_manager_t.
*/
void (*destroy) (task_manager_t *this);
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
index bea4f73d5..3de27ee3f 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
* - INVALID_ARG: diffie hellman group inacceptable
* - NOT_FOUND: TS inacceptable
*/
-static status_t select_and_install(private_child_create_t *this, bool no_dh)
+static status_t select_and_install(private_child_create_t *this,
+ bool no_dh, bool ike_auth)
{
status_t status, status_i, status_o;
chunk_t nonce_i, nonce_r;
@@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
other_vip);
+ if (this->initiator)
+ {
+ if (ike_auth)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
+ }
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER, my_ts, other_ts);
+ }
+
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
{
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
@@ -418,66 +438,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
- /* check for any certificate-based IP address block constraints */
- if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL)
- {
- auth_cfg_t *auth;
- enumerator_t *auth_enum;
- certificate_t *cert = NULL;
-
- auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
- while (auth_enum->enumerate(auth_enum, &auth))
- {
- cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
- if (cert)
- {
- break;
- }
- }
- auth_enum->destroy(auth_enum);
-
- if (cert && cert->get_type(cert) == CERT_X509)
- {
- x509_t *x509 = (x509_t*)cert;
-
- if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
- {
- enumerator_t *enumerator, *block_enum;
- traffic_selector_t *ts, *block_ts;
-
- DBG1(DBG_IKE, "checking certificate-based traffic selector "
- "constraints [RFC 3779]");
- enumerator = other_ts->create_enumerator(other_ts);
- while (enumerator->enumerate(enumerator, &ts))
- {
- bool contained = FALSE;
-
- block_enum = x509->create_ipAddrBlock_enumerator(x509);
- while (block_enum->enumerate(block_enum, &block_ts))
- {
- if (ts->is_contained_in(ts, block_ts))
- {
- DBG1(DBG_IKE, " TS %R is contained in address block"
- " constraint %R", ts, block_ts);
- contained = TRUE;
- break;
- }
- }
- block_enum->destroy(block_enum);
-
- if (!contained)
- {
- DBG1(DBG_IKE, " TS %R is not contained in any"
- " address block constraint", ts);
- enumerator->destroy(enumerator);
- return FAILED;
- }
- }
- enumerator->destroy(enumerator);
- }
- }
- }
-
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
this->child_sa->set_mode(this->child_sa, this->mode);
@@ -529,8 +489,8 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
return NOT_FOUND;
}
- charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
- nonce_i, nonce_r);
+ charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
+ this->dh, nonce_i, nonce_r);
/* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
@@ -848,6 +808,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
}
+ if (message->get_exchange_type(message) == IKE_AUTH)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
+ }
+
build_payloads(this, message);
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
@@ -914,7 +885,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
peer_cfg_t *peer_cfg;
payload_t *payload;
enumerator_t *enumerator;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -934,6 +905,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1016,7 +988,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
}
- switch (select_and_install(this, no_dh))
+ switch (select_and_install(this, no_dh, ike_auth))
{
case SUCCESS:
break;
@@ -1064,7 +1036,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -1079,6 +1051,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1159,7 +1132,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
return SUCCESS;
}
- if (select_and_install(this, no_dh) == SUCCESS)
+ if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
{
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
@@ -1229,11 +1202,11 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
- if (this->tsi)
+ if (this->tsr)
{
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
}
- if (this->tsr)
+ if (this->tsi)
{
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
}
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c
index d7c6b0541..b0cd30e1e 100644
--- a/src/libcharon/sa/tasks/child_delete.c
+++ b/src/libcharon/sa/tasks/child_delete.c
@@ -191,6 +191,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
child_cfg_t *child_cfg;
protocol_id_t protocol;
u_int32_t spi;
+ action_t action;
status_t status = SUCCESS;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -205,10 +206,11 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
protocol = child_sa->get_protocol(child_sa);
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
+ action = child_sa->get_close_action(child_sa);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
if (this->check_delete_action)
{ /* enforce child_cfg policy if deleted passively */
- switch (child_cfg->get_close_action(child_cfg))
+ switch (action)
{
case ACTION_RESTART:
child_cfg->get_ref(child_cfg);
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
index b5e4e84b4..fb3452efd 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -215,6 +215,64 @@ static status_t build_r(private_child_rekey_t *this, message_t *message)
}
/**
+ * Handle a rekey collision
+ */
+static child_sa_t *handle_collision(private_child_rekey_t *this)
+{
+ child_sa_t *to_delete;
+
+ if (this->collision->get_type(this->collision) == CHILD_REKEY)
+ {
+ chunk_t this_nonce, other_nonce;
+ private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
+
+ this_nonce = this->child_create->get_lower_nonce(this->child_create);
+ other_nonce = other->child_create->get_lower_nonce(other->child_create);
+
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ child_sa_t *child_sa;
+
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ /* disable close action for the redundand child */
+ child_sa = other->child_create->get_child(other->child_create);
+ child_sa->set_close_action(child_sa, ACTION_NONE);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey collision lost, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ else
+ { /* CHILD_DELETE */
+ child_delete_t *del = (child_delete_t*)this->collision;
+
+ /* we didn't had a chance to compare the nonces, so we delete
+ * the CHILD_SA the other is not deleting. */
+ if (del->get_child(del) != this->child_sa)
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ return to_delete;
+}
+
+/**
* Implementation of task_t.process for initiator
*/
static status_t process_i(private_child_rekey_t *this, message_t *message)
@@ -263,35 +321,14 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
return SUCCESS;
}
- to_delete = this->child_sa;
-
/* check for rekey collisions */
- if (this->collision &&
- this->collision->get_type(this->collision) == CHILD_REKEY)
+ if (this->collision)
{
- chunk_t this_nonce, other_nonce;
- private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
-
- this_nonce = this->child_create->get_lower_nonce(this->child_create);
- other_nonce = other->child_create->get_lower_nonce(other->child_create);
-
- /* if we have the lower nonce, delete rekeyed SA. If not, delete
- * the redundant. */
- if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) < 0)
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child");
- }
- else
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child");
- to_delete = this->child_create->get_child(this->child_create);
- if (to_delete == NULL)
- {
- /* ooops, should not happen, fallback */
- to_delete = this->child_sa;
- }
- }
+ to_delete = handle_collision(this);
+ }
+ else
+ {
+ to_delete = this->child_sa;
}
if (to_delete != this->child_create->get_child(this->child_create))
@@ -300,6 +337,10 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
this->child_create->get_child(this->child_create));
}
+ if (to_delete == NULL)
+ {
+ return SUCCESS;
+ }
spi = to_delete->get_spi(to_delete, TRUE);
protocol = to_delete->get_protocol(to_delete);
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
index a07f96767..a954782f2 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -518,6 +518,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
{ /* peer requested EAP, but current config does not match */
+ DBG1(DBG_IKE, "peer requested EAP, config inacceptable");
this->peer_cfg->destroy(this->peer_cfg);
this->peer_cfg = NULL;
if (!update_cfg_candidates(this, FALSE))
@@ -527,7 +528,16 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
}
cand = get_auth_cfg(this, FALSE);
}
- cfg->merge(cfg, cand, TRUE);
+ /* copy over the EAP specific rules for authentication */
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE,
+ cand->get(cand, AUTH_RULE_EAP_TYPE));
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR,
+ cand->get(cand, AUTH_RULE_EAP_VENDOR));
+ id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ }
}
/* verify authentication data */
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c
index c831df975..cc810a49a 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/tasks/ike_cert_post.c
@@ -72,14 +72,18 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
return cert_payload_create_from_cert(cert);
}
- encoded = cert->get_encoding(cert);
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
+ {
+ DBG1(DBG_IKE, "encoding certificate for cert payload failed");
+ hasher->destroy(hasher);
+ return NULL;
+ }
hasher->allocate_hash(hasher, encoded, &hash);
chunk_free(&encoded);
hasher->destroy(hasher);
id = identification_create_from_encoding(ID_KEY_ID, hash);
- enumerator = charon->credentials->create_cdp_enumerator(charon->credentials,
- CERT_X509, id);
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509, id);
if (enumerator->enumerate(enumerator, &url))
{
payload = cert_payload_create_from_hash_and_url(hash, url);
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
index 0805d0290..1c0c54727 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -93,8 +93,8 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
certificate_t *cert;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, TRUE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, TRUE);
if (cert)
{
DBG1(DBG_IKE, "received cert request for \"%Y\"",
@@ -156,8 +156,8 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload)
break;
}
id = identification_create_from_encoding(ID_KEY_ID, hash);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, FALSE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, FALSE);
id->destroy(id);
break;
}
@@ -299,7 +299,7 @@ static void add_certreq(certreq_payload_t **req, certificate_t *cert)
{
*req = certreq_payload_create_type(CERT_X509);
}
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
{
(*req)->add_keyid(*req, keyid);
DBG1(DBG_IKE, "sending cert request for \"%Y\"",
@@ -370,8 +370,8 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
if (!req)
{
/* otherwise add all trusted CA certificates */
- enumerator = charon->credentials->create_cert_enumerator(
- charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_ANY, KEY_ANY, NULL, TRUE);
while (enumerator->enumerate(enumerator, &cert))
{
add_certreq(&req, cert);
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c
index 58bcf0762..c92b5bca5 100644
--- a/src/libcharon/sa/tasks/ike_config.c
+++ b/src/libcharon/sa/tasks/ike_config.c
@@ -333,7 +333,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
chunk_empty);
return SUCCESS;
}
- DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp = cp_payload_create_type(CFG_REPLY);
@@ -342,7 +342,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, id, vip);
+ hydra->attributes, config->get_pool(config), id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c
index 5eb33b540..38fb572f4 100644
--- a/src/libcharon/sa/tasks/ike_init.c
+++ b/src/libcharon/sa/tasks/ike_init.c
@@ -543,6 +543,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
DESTROY_IF(this->dh);
this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 878170c83..80bf647cd 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -128,7 +128,7 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
ike_cfg = peer->get_ike_cfg(peer);
other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg),
0, ike_cfg->get_other_port(ike_cfg));
- if (!other)
+ if (!other || other->is_anyaddr(other))
{
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
return 0;