diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-08-09 08:09:54 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-08-09 08:09:54 +0000 |
commit | b8064f4099997a9e2179f3ad4ace605f5ccac3a1 (patch) | |
tree | 81778e976b476374c48b4fe83d084b986b890421 /src/libcharon/sa | |
parent | 1ac70afcc1f7d6d2738a34308810719b0976d29f (diff) | |
download | vyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.tar.gz vyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.zip |
[svn-upgrade] new version strongswan (4.4.1)
Diffstat (limited to 'src/libcharon/sa')
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, ¤t_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; |