summaryrefslogtreecommitdiff
path: root/src/libcharon/sa
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
committerYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
commitb34738ed08c2227300d554b139e2495ca5da97d6 (patch)
tree62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libcharon/sa
parent0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff)
downloadvyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz
vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r--src/libcharon/sa/authenticators/authenticator.c7
-rw-r--r--src/libcharon/sa/authenticators/authenticator.h6
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.c20
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.h15
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_card.h125
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_hooks.h53
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_manager.c534
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_manager.h291
-rw-r--r--src/libcharon/sa/authenticators/eap/sim_provider.h124
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c25
-rw-r--r--src/libcharon/sa/child_sa.c150
-rw-r--r--src/libcharon/sa/connect_manager.c322
-rw-r--r--src/libcharon/sa/ike_sa.c391
-rw-r--r--src/libcharon/sa/ike_sa.h126
-rw-r--r--src/libcharon/sa/ike_sa_id.c103
-rw-r--r--src/libcharon/sa/ike_sa_id.h22
-rw-r--r--src/libcharon/sa/ike_sa_manager.c176
-rw-r--r--src/libcharon/sa/ike_sa_manager.h12
-rw-r--r--src/libcharon/sa/keymat.c2
-rw-r--r--src/libcharon/sa/keymat.h7
-rw-r--r--src/libcharon/sa/mediation_manager.c131
-rw-r--r--src/libcharon/sa/shunt_manager.c251
-rw-r--r--src/libcharon/sa/shunt_manager.h69
-rw-r--r--src/libcharon/sa/task_manager.c118
-rw-r--r--src/libcharon/sa/tasks/child_create.c10
-rw-r--r--src/libcharon/sa/tasks/child_delete.c109
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c93
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c82
-rw-r--r--src/libcharon/sa/tasks/ike_auth.h2
-rw-r--r--src/libcharon/sa/tasks/ike_auth_lifetime.c69
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.c72
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.h2
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c75
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.h2
-rw-r--r--src/libcharon/sa/tasks/ike_config.c79
-rw-r--r--src/libcharon/sa/tasks/ike_delete.c75
-rw-r--r--src/libcharon/sa/tasks/ike_dpd.c57
-rw-r--r--src/libcharon/sa/tasks/ike_dpd.h2
-rw-r--r--src/libcharon/sa/tasks/ike_init.c130
-rw-r--r--src/libcharon/sa/tasks/ike_init.h2
-rw-r--r--src/libcharon/sa/tasks/ike_me.c159
-rw-r--r--src/libcharon/sa/tasks/ike_mobike.c59
-rw-r--r--src/libcharon/sa/tasks/ike_natd.c95
-rw-r--r--src/libcharon/sa/tasks/ike_natd.h2
-rw-r--r--src/libcharon/sa/tasks/ike_reauth.c145
-rw-r--r--src/libcharon/sa/tasks/ike_rekey.c10
-rw-r--r--src/libcharon/sa/tasks/ike_vendor.h2
-rw-r--r--src/libcharon/sa/tasks/task.h6
-rw-r--r--src/libcharon/sa/trap_manager.c178
-rw-r--r--src/libcharon/sa/trap_manager.h5
50 files changed, 1937 insertions, 2665 deletions
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c
index 83f5fbaad..9ffe661cc 100644
--- a/src/libcharon/sa/authenticators/authenticator.c
+++ b/src/libcharon/sa/authenticators/authenticator.c
@@ -28,11 +28,12 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS,
"RSA signature",
"pre-shared key",
"DSS signature");
-ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
+ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS,
"ECDSA-256 signature",
"ECDSA-384 signature",
- "ECDSA-521 signature");
-ENUM_END(auth_method_names, AUTH_ECDSA_521);
+ "ECDSA-521 signature",
+ "secure password method");
+ENUM_END(auth_method_names, AUTH_GSPM);
/**
* Described in header.
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h
index d27e006a3..5042e4a73 100644
--- a/src/libcharon/sa/authenticators/authenticator.h
+++ b/src/libcharon/sa/authenticators/authenticator.h
@@ -67,6 +67,12 @@ enum auth_method_t {
* ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754
*/
AUTH_ECDSA_521 = 11,
+
+ /**
+ * Generic Secure Password Authentication Method as specified in RFC 6467
+ */
+ AUTH_GSPM = 12,
+
};
/**
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c
index 0fa4a00c5..a05e8c59a 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.c
+++ b/src/libcharon/sa/authenticators/eap/eap_method.c
@@ -15,8 +15,28 @@
#include "eap_method.h"
+#include <daemon.h>
+
ENUM(eap_role_names, EAP_SERVER, EAP_PEER,
"EAP_SERVER",
"EAP_PEER",
);
+/**
+ * See header
+ */
+bool eap_method_register(plugin_t *plugin, plugin_feature_t *feature,
+ bool reg, void *data)
+{
+ if (reg)
+ {
+ charon->eap->add_method(charon->eap, feature->arg.eap, 0,
+ feature->type == FEATURE_EAP_SERVER ? EAP_SERVER : EAP_PEER,
+ (eap_constructor_t)data);
+ }
+ else
+ {
+ charon->eap->remove_method(charon->eap, (eap_constructor_t)data);
+ }
+ return TRUE;
+}
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h
index 0eab2b5ff..6242a5a6e 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.h
+++ b/src/libcharon/sa/authenticators/eap/eap_method.h
@@ -25,6 +25,7 @@ typedef struct eap_method_t eap_method_t;
typedef enum eap_role_t eap_role_t;
#include <library.h>
+#include <plugins/plugin.h>
#include <utils/identification.h>
#include <eap/eap.h>
#include <encoding/payloads/eap_payload.h>
@@ -159,4 +160,18 @@ struct eap_method_t {
typedef eap_method_t *(*eap_constructor_t)(identification_t *server,
identification_t *peer);
+/**
+ * Helper function to (un-)register EAP methods from plugin features.
+ *
+ * This function is a plugin_feature_callback_t and can be used with the
+ * PLUGIN_CALLBACK macro to register a EAP method constructor.
+ *
+ * @param plugin plugin registering the EAP method constructor
+ * @param feature associated plugin feature
+ * @param reg TRUE to register, FALSE to unregister.
+ * @param data data passed to callback, an eap_constructor_t
+ */
+bool eap_method_register(plugin_t *plugin, plugin_feature_t *feature,
+ bool reg, void *data);
+
#endif /** EAP_METHOD_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/sim_card.h b/src/libcharon/sa/authenticators/eap/sim_card.h
deleted file mode 100644
index 5f5dc580b..000000000
--- a/src/libcharon/sa/authenticators/eap/sim_card.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup sim_card sim_card
- * @{ @ingroup eap
- */
-
-#ifndef SIM_CARD_H_
-#define SIM_CARD_H_
-
-typedef struct sim_card_t sim_card_t;
-
-/**
- * Interface for a (U)SIM card (used as EAP client).
- *
- * The SIM card completes triplets/quintuplets requested in a challenge
- * received from the server.
- * An implementation supporting only one of SIM/AKA authentication may
- * implement the other methods with return_false()/return NOT_SUPPORTED/NULL.
- */
-struct sim_card_t {
-
- /**
- * Calculate SRES/KC from a RAND for SIM authentication.
- *
- * @param id permanent identity to get a triplet for
- * @param rand RAND input buffer, fixed size 16 bytes
- * @param sres SRES output buffer, fixed size 4 byte
- * @param kc KC output buffer, fixed size 8 bytes
- * @return TRUE if SRES/KC calculated, FALSE on error/wrong identity
- */
- bool (*get_triplet)(sim_card_t *this, identification_t *id,
- char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
- char kc[SIM_KC_LEN]);
-
- /**
- * Calculate CK/IK/RES from RAND/AUTN for AKA authentication.
- *
- * If the received sequence number (in autn) is out of sync, INVALID_STATE
- * is returned.
- * The RES value is the only one with variable length. Pass a buffer
- * of at least AKA_RES_MAX, the actual number of bytes is written to the
- * res_len value. While the standard would allow any bit length between
- * 32 and 128 bits, we support only full bytes for now.
- *
- * @param id permanent identity to request quintuplet for
- * @param rand random value rand
- * @param autn authentication token autn
- * @param ck buffer receiving encryption key ck
- * @param ik buffer receiving integrity key ik
- * @param res buffer receiving authentication result res
- * @param res_len nubmer of bytes written to res buffer
- * @return SUCCESS, FAILED, or INVALID_STATE if out of sync
- */
- status_t (*get_quintuplet)(sim_card_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN],
- char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
- char res[AKA_RES_MAX], int *res_len);
-
- /**
- * Calculate AUTS from RAND for AKA resynchronization.
- *
- * @param id permanent identity to request quintuplet for
- * @param rand random value rand
- * @param auts resynchronization parameter auts
- * @return TRUE if parameter generated successfully
- */
- bool (*resync)(sim_card_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
-
- /**
- * Set the pseudonym to use for next authentication.
- *
- * @param id permanent identity of the peer
- * @param pseudonym pseudonym identity received from the server
- */
- void (*set_pseudonym)(sim_card_t *this, identification_t *id,
- identification_t *pseudonym);
-
- /**
- * Get the pseudonym previously stored via set_pseudonym().
- *
- * @param id permanent identity of the peer
- * @return associated pseudonym identity, NULL if none stored
- */
- identification_t* (*get_pseudonym)(sim_card_t *this, identification_t *id);
-
- /**
- * Store parameters to use for the next fast reauthentication.
- *
- * @param id permanent identity of the peer
- * @param next next fast reauthentication identity to use
- * @param mk master key MK to store for reauthentication
- * @param counter counter value to store, host order
- */
- void (*set_reauth)(sim_card_t *this, identification_t *id,
- identification_t *next, char mk[HASH_SIZE_SHA1],
- u_int16_t counter);
-
- /**
- * Retrieve parameters for fast reauthentication stored via set_reauth().
- *
- * @param id permanent identity of the peer
- * @param mk buffer receiving master key MK
- * @param counter pointer receiving counter value, in host order
- * @return fast reauthentication identity, NULL if not found
- */
- identification_t* (*get_reauth)(sim_card_t *this, identification_t *id,
- char mk[HASH_SIZE_SHA1], u_int16_t *counter);
-};
-
-#endif /** SIM_CARD_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/sim_hooks.h b/src/libcharon/sa/authenticators/eap/sim_hooks.h
deleted file mode 100644
index 0a675e4ab..000000000
--- a/src/libcharon/sa/authenticators/eap/sim_hooks.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup sim_hooks sim_hooks
- * @{ @ingroup eap
- */
-
-#ifndef SIM_HOOKS_H_
-#define SIM_HOOKS_H_
-
-typedef struct sim_hooks_t sim_hooks_t;
-
-/**
- * Additional hooks invoked during EAP-SIM/AKA message processing.
- */
-struct sim_hooks_t {
-
- /**
- * SIM/AKA message parsing.
- *
- * As a SIM/AKA optionally contains encrypted attributes, the hook
- * might get invoked twice, once before and once after decryption.
- *
- * @param message SIM/AKA message
- * @param inbound TRUE for incoming messages, FALSE for outgoing
- * @param decrypted TRUE if AT_ENCR_DATA has been decrypted
- */
- void (*message)(sim_hooks_t *this, simaka_message_t *message,
- bool inbound, bool decrypted);
-
- /**
- * SIM/AKA encryption/authentication key hooks.
- *
- * @param k_encr derived SIM/AKA encryption key k_encr
- * @param k_auth derived SIM/AKA authentication key k_auth
- */
- void (*keys)(sim_hooks_t *this, chunk_t k_encr, chunk_t k_auth);
-};
-
-#endif /** SIM_HOOKS_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.c b/src/libcharon/sa/authenticators/eap/sim_manager.c
deleted file mode 100644
index 9ccaf5298..000000000
--- a/src/libcharon/sa/authenticators/eap/sim_manager.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "sim_manager.h"
-
-#include <daemon.h>
-#include <utils/linked_list.h>
-#include <threading/rwlock.h>
-
-typedef struct private_sim_manager_t private_sim_manager_t;
-
-/**
- * Private data of an sim_manager_t object.
- */
-struct private_sim_manager_t {
-
- /**
- * Public sim_manager_t interface.
- */
- sim_manager_t public;
-
- /**
- * list of added cards
- */
- linked_list_t *cards;
-
- /**
- * list of added provider
- */
- linked_list_t *providers;
-
- /**
- * list of added hooks
- */
- linked_list_t *hooks;
-
- /**
- * lock for lists above
- */
- rwlock_t *lock;
-};
-
-METHOD(sim_manager_t, add_card, void,
- private_sim_manager_t *this, sim_card_t *card)
-{
- this->lock->write_lock(this->lock);
- this->cards->insert_last(this->cards, card);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, remove_card, void,
- private_sim_manager_t *this, sim_card_t *card)
-{
- this->lock->write_lock(this->lock);
- this->cards->remove(this->cards, card, NULL);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, card_get_triplet, bool,
- private_sim_manager_t *this, identification_t *id,
- char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
-{
- enumerator_t *enumerator;
- sim_card_t *card;
- int tried = 0;
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- if (card->get_triplet(card, id, rand, sres, kc))
- {
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return TRUE;
- }
- tried++;
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'",
- tried, id);
- return FALSE;
-}
-
-METHOD(sim_manager_t, card_get_quintuplet, status_t,
- private_sim_manager_t *this, identification_t *id, char rand[AKA_RAND_LEN],
- char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
- char res[AKA_RES_MAX], int *res_len)
-{
- enumerator_t *enumerator;
- sim_card_t *card;
- status_t status = NOT_FOUND;
- int tried = 0;
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- status = card->get_quintuplet(card, id, rand, autn, ck, ik, res, res_len);
- switch (status)
- { /* try next on error, but not on INVALID_STATE */
- case SUCCESS:
- case INVALID_STATE:
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return status;
- case NOT_SUPPORTED:
- case FAILED:
- default:
- tried++;
- continue;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'",
- tried, id);
- return status;
-}
-
-METHOD(sim_manager_t, card_resync, bool,
- private_sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
-{
- enumerator_t *enumerator;
- sim_card_t *card;
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- if (card->resync(card, id, rand, auts))
- {
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return TRUE;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return FALSE;
-}
-
-METHOD(sim_manager_t, card_set_pseudonym, void,
- private_sim_manager_t *this, identification_t *id,
- identification_t *pseudonym)
-{
- enumerator_t *enumerator;
- sim_card_t *card;
-
- DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id);
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- card->set_pseudonym(card, id, pseudonym);
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, card_get_pseudonym, identification_t*,
- private_sim_manager_t *this, identification_t *id)
-{
- enumerator_t *enumerator;
- sim_card_t *card;
- identification_t *pseudonym = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- pseudonym = card->get_pseudonym(card, id);
- if (pseudonym)
- {
- DBG1(DBG_IKE, "using stored pseudonym identity '%Y' "
- "instead of '%Y'", pseudonym, id);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return pseudonym;
-}
-
-METHOD(sim_manager_t, card_set_reauth, void,
- private_sim_manager_t *this, identification_t *id, identification_t *next,
- char mk[HASH_SIZE_SHA1], u_int16_t counter)
-{
- enumerator_t *enumerator;
- sim_card_t *card;
-
- DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'",
- next, id);
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- card->set_reauth(card, id, next, mk, counter);
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, card_get_reauth, identification_t*,
- private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1],
- u_int16_t *counter)
-{
- enumerator_t *enumerator;
- sim_card_t *card;
- identification_t *reauth = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->cards->create_enumerator(this->cards);
- while (enumerator->enumerate(enumerator, &card))
- {
- reauth = card->get_reauth(card, id, mk, counter);
- if (reauth)
- {
- DBG1(DBG_IKE, "using stored reauthentication identity '%Y' "
- "instead of '%Y'", reauth, id);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return reauth;
-}
-
-METHOD(sim_manager_t, add_provider, void,
- private_sim_manager_t *this, sim_provider_t *provider)
-{
- this->lock->write_lock(this->lock);
- this->providers->insert_last(this->providers, provider);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, remove_provider, void,
- private_sim_manager_t *this, sim_provider_t *provider)
-{
- this->lock->write_lock(this->lock);
- this->providers->remove(this->providers, provider, NULL);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, provider_get_triplet, bool,
- private_sim_manager_t *this, identification_t *id, char rand[SIM_RAND_LEN],
- char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- int tried = 0;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- if (provider->get_triplet(provider, id, rand, sres, kc))
- {
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return TRUE;
- }
- tried++;
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'",
- tried, id);
- return FALSE;
-}
-
-METHOD(sim_manager_t, provider_get_quintuplet, bool,
- private_sim_manager_t *this, identification_t *id, char rand[AKA_RAND_LEN],
- char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN],
- char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- int tried = 0;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- if (provider->get_quintuplet(provider, id, rand, xres, xres_len,
- ck, ik, autn))
- {
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return TRUE;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'",
- tried, id);
- return FALSE;
-}
-
-METHOD(sim_manager_t, provider_resync, bool,
- private_sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- if (provider->resync(provider, id, rand, auts))
- {
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return TRUE;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return FALSE;
-}
-
-METHOD(sim_manager_t, provider_is_pseudonym, identification_t*,
- private_sim_manager_t *this, identification_t *id)
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- identification_t *permanent = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- permanent = provider->is_pseudonym(provider, id);
- if (permanent)
- {
- DBG1(DBG_IKE, "received pseudonym identity '%Y' "
- "mapping to '%Y'", id, permanent);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return permanent;
-}
-
-METHOD(sim_manager_t, provider_gen_pseudonym, identification_t*,
- private_sim_manager_t *this, identification_t *id)
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- identification_t *pseudonym = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- pseudonym = provider->gen_pseudonym(provider, id);
- if (pseudonym)
- {
- DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return pseudonym;
-}
-
-METHOD(sim_manager_t, provider_is_reauth, identification_t*,
- private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1],
- u_int16_t *counter)
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- identification_t *permanent = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- permanent = provider->is_reauth(provider, id, mk, counter);
- if (permanent)
- {
- DBG1(DBG_IKE, "received reauthentication identity '%Y' "
- "mapping to '%Y'", id, permanent);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return permanent;
-}
-
-METHOD(sim_manager_t, provider_gen_reauth, identification_t*,
- private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1])
-{
- enumerator_t *enumerator;
- sim_provider_t *provider;
- identification_t *reauth = NULL;
-
- this->lock->read_lock(this->lock);
- enumerator = this->providers->create_enumerator(this->providers);
- while (enumerator->enumerate(enumerator, &provider))
- {
- reauth = provider->gen_reauth(provider, id, mk);
- if (reauth)
- {
- DBG1(DBG_IKE, "proposing new reauthentication identity '%Y'", reauth);
- break;
- }
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return reauth;
-}
-
-METHOD(sim_manager_t, add_hooks, void,
- private_sim_manager_t *this, sim_hooks_t *hooks)
-{
- this->lock->write_lock(this->lock);
- this->hooks->insert_last(this->hooks, hooks);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, remove_hooks, void,
- private_sim_manager_t *this, sim_hooks_t *hooks)
-{
- this->lock->write_lock(this->lock);
- this->hooks->remove(this->hooks, hooks, NULL);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, message_hook, void,
- private_sim_manager_t *this, simaka_message_t *message,
- bool inbound, bool decrypted)
-{
- enumerator_t *enumerator;
- sim_hooks_t *hooks;
-
- this->lock->read_lock(this->lock);
- enumerator = this->hooks->create_enumerator(this->hooks);
- while (enumerator->enumerate(enumerator, &hooks))
- {
- hooks->message(hooks, message, inbound, decrypted);
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, key_hook, void,
- private_sim_manager_t *this, chunk_t k_encr, chunk_t k_auth)
-{
- enumerator_t *enumerator;
- sim_hooks_t *hooks;
-
- this->lock->read_lock(this->lock);
- enumerator = this->hooks->create_enumerator(this->hooks);
- while (enumerator->enumerate(enumerator, &hooks))
- {
- hooks->keys(hooks, k_encr, k_auth);
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
-}
-
-METHOD(sim_manager_t, destroy, void,
- private_sim_manager_t *this)
-{
- this->cards->destroy(this->cards);
- this->providers->destroy(this->providers);
- this->hooks->destroy(this->hooks);
- this->lock->destroy(this->lock);
- free(this);
-}
-
-/**
- * See header
- */
-sim_manager_t *sim_manager_create()
-{
- private_sim_manager_t *this;
-
- INIT(this,
- .public = {
- .add_card = _add_card,
- .remove_card = _remove_card,
- .card_get_triplet = _card_get_triplet,
- .card_get_quintuplet = _card_get_quintuplet,
- .card_resync = _card_resync,
- .card_set_pseudonym = _card_set_pseudonym,
- .card_get_pseudonym = _card_get_pseudonym,
- .card_set_reauth = _card_set_reauth,
- .card_get_reauth = _card_get_reauth,
- .add_provider = _add_provider,
- .remove_provider = _remove_provider,
- .provider_get_triplet = _provider_get_triplet,
- .provider_get_quintuplet = _provider_get_quintuplet,
- .provider_resync = _provider_resync,
- .provider_is_pseudonym = _provider_is_pseudonym,
- .provider_gen_pseudonym = _provider_gen_pseudonym,
- .provider_is_reauth = _provider_is_reauth,
- .provider_gen_reauth = _provider_gen_reauth,
- .add_hooks = _add_hooks,
- .remove_hooks = _remove_hooks,
- .message_hook = _message_hook,
- .key_hook = _key_hook,
- .destroy = _destroy,
- },
- .cards = linked_list_create(),
- .providers = linked_list_create(),
- .hooks = linked_list_create(),
- .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
- );
-
- return &this->public;
-}
-
diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.h b/src/libcharon/sa/authenticators/eap/sim_manager.h
deleted file mode 100644
index db4a65011..000000000
--- a/src/libcharon/sa/authenticators/eap/sim_manager.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup sim_manager sim_manager
- * @{ @ingroup eap
- */
-
-#ifndef SIM_MANAGER_H_
-#define SIM_MANAGER_H_
-
-#include <crypto/hashers/hasher.h>
-#include <utils/identification.h>
-#include <utils/enumerator.h>
-#include <sa/authenticators/eap/eap_method.h>
-
-typedef struct sim_manager_t sim_manager_t;
-
-/** implemented in libsimaka, but we need it for the message hook */
-typedef struct simaka_message_t simaka_message_t;
-
-#define SIM_RAND_LEN 16
-#define SIM_SRES_LEN 4
-#define SIM_KC_LEN 8
-
-#define AKA_RAND_LEN 16
-#define AKA_RES_MAX 16
-#define AKA_CK_LEN 16
-#define AKA_IK_LEN 16
-#define AKA_AUTN_LEN 16
-#define AKA_AUTS_LEN 14
-
-#include <sa/authenticators/eap/sim_card.h>
-#include <sa/authenticators/eap/sim_provider.h>
-#include <sa/authenticators/eap/sim_hooks.h>
-
-/**
- * The SIM manager handles multiple (U)SIM cards/providers and hooks.
- */
-struct sim_manager_t {
-
- /**
- * Register a SIM card (client) at the manager.
- *
- * @param card sim card to register
- */
- void (*add_card)(sim_manager_t *this, sim_card_t *card);
-
- /**
- * Unregister a previously registered card from the manager.
- *
- * @param card sim card to unregister
- */
- void (*remove_card)(sim_manager_t *this, sim_card_t *card);
-
- /**
- * Calculate SIM triplets on one of the registered SIM cards.
- *
- * @param id permanent identity to get a triplet for
- * @param rand RAND input buffer, fixed size 16 bytes
- * @param sres SRES output buffer, fixed size 4 byte
- * @param kc KC output buffer, fixed size 8 bytes
- * @return TRUE if calculated, FALSE if no matching card found
- */
- bool (*card_get_triplet)(sim_manager_t *this, identification_t *id,
- char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
- char kc[SIM_KC_LEN]);
-
- /**
- * Calculate AKA quitpulets on one of the registered SIM cards.
- *
- * @param id permanent identity to request quintuplet for
- * @param rand random value rand
- * @param autn authentication token autn
- * @param ck buffer receiving encryption key ck
- * @param ik buffer receiving integrity key ik
- * @param res buffer receiving authentication result res
- * @param res_len nubmer of bytes written to res buffer
- * @return SUCCESS, FAILED, or INVALID_STATE if out of sync
- */
- status_t (*card_get_quintuplet)(sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN],
- char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
- char res[AKA_RES_MAX], int *res_len);
-
- /**
- * Calculate resynchronization data on one of the registered SIM cards.
- *
- * @param id permanent identity to request quintuplet for
- * @param rand random value rand
- * @param auts resynchronization parameter auts
- * @return TRUE if calculated, FALSE if no matcing card found
- */
- bool (*card_resync)(sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
-
- /**
- * Store a received pseudonym on one of the registered SIM cards.
- *
- * @param id permanent identity of the peer
- * @param pseudonym pseudonym identity received from the server
- */
- void (*card_set_pseudonym)(sim_manager_t *this, identification_t *id,
- identification_t *pseudonym);
-
- /**
- * Get a stored pseudonym from one of the registerd SIM cards.
- *
- * @param id permanent identity of the peer
- * @return associated pseudonym identity, NULL if none found
- */
- identification_t* (*card_get_pseudonym)(sim_manager_t *this,
- identification_t *id);
-
- /**
- * Store fast reauthentication parameters on one of the registered cards.
- *
- * @param id permanent identity of the peer
- * @param next next fast reauthentication identity to use
- * @param mk master key MK to store for reauthentication
- * @param counter counter value to store, host order
- */
- void (*card_set_reauth)(sim_manager_t *this, identification_t *id,
- identification_t *next, char mk[HASH_SIZE_SHA1],
- u_int16_t counter);
-
- /**
- * Retrieve fast reauthentication parameters from one of the registerd cards.
- *
- * @param id permanent identity of the peer
- * @param mk buffer receiving master key MK
- * @param counter pointer receiving counter value, in host order
- * @return fast reauthentication identity, NULL if none found
- */
- identification_t* (*card_get_reauth)(sim_manager_t *this,
- identification_t *id, char mk[HASH_SIZE_SHA1],
- u_int16_t *counter);
-
- /**
- * Register a triplet provider (server) at the manager.
- *
- * @param card sim card to register
- */
- void (*add_provider)(sim_manager_t *this, sim_provider_t *provider);
-
- /**
- * Unregister a previously registered provider from the manager.
- *
- * @param card sim card to unregister
- */
- void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider);
-
- /**
- * Get a SIM triplet from one of the registered providers.
- *
- * @param id permanent identity of peer to gen triplet for
- * @param rand RAND output buffer, fixed size 16 bytes
- * @param sres SRES output buffer, fixed size 4 byte
- * @param kc KC output buffer, fixed size 8 bytes
- * @return TRUE if triplet received, FALSE if no match found
- */
- bool (*provider_get_triplet)(sim_manager_t *this, identification_t *id,
- char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
- char kc[SIM_KC_LEN]);
-
- /**
- * Get a AKA quintuplet from one of the registered providers.
- *
- * @param id permanent identity of peer to create challenge for
- * @param rand buffer receiving random value rand
- * @param xres buffer receiving expected authentication result xres
- * @param ck buffer receiving encryption key ck
- * @param ik buffer receiving integrity key ik
- * @param autn authentication token autn
- * @return TRUE if quintuplet received, FALSE if no match found
- */
- bool (*provider_get_quintuplet)(sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN],
- char xres[AKA_RES_MAX], int *xres_len,
- char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
- char autn[AKA_AUTN_LEN]);
-
- /**
- * Pass AKA resynchronization data to one of the registered providers.
- *
- * @param id permanent identity of peer requesting resynchronisation
- * @param rand random value rand
- * @param auts synchronization parameter auts
- * @return TRUE if resynchronized, FALSE if not handled
- */
- bool (*provider_resync)(sim_manager_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
-
- /**
- * Check if a peer uses a pseudonym using one of the registered providers.
- *
- * @param id pseudonym identity candidate
- * @return permanent identity, NULL if id not a pseudonym
- */
- identification_t* (*provider_is_pseudonym)(sim_manager_t *this,
- identification_t *id);
-
- /**
- * Generate a new pseudonym using one of the registered providers.
- *
- * @param id permanent identity to generate a pseudonym for
- * @return generated pseudonym, NULL to not use a pseudonym identity
- */
- identification_t* (*provider_gen_pseudonym)(sim_manager_t *this,
- identification_t *id);
-
- /**
- * Check if a peer uses a reauth id using one of the registered providers.
- *
- * @param id reauthentication identity (candidate)
- * @param mk buffer receiving master key MK
- * @param counter pointer receiving current counter value, host order
- * @return permanent identity, NULL if not a known reauth identity
- */
- identification_t* (*provider_is_reauth)(sim_manager_t *this,
- identification_t *id, char mk[HASH_SIZE_SHA1],
- u_int16_t *counter);
-
- /**
- * Generate a fast reauth id using one of the registered providers.
- *
- * @param id permanent peer identity
- * @param mk master key to store along with generated identity
- * @return fast reauthentication identity, NULL to not use reauth
- */
- identification_t* (*provider_gen_reauth)(sim_manager_t *this,
- identification_t *id, char mk[HASH_SIZE_SHA1]);
-
- /**
- * Register a set of hooks to the manager.
- *
- * @param hooks hook interface implementation to register
- */
- void (*add_hooks)(sim_manager_t *this, sim_hooks_t *hooks);
-
- /**
- * Unregister a set of hooks from the manager.
- *
- * @param hooks hook interface implementation to unregister
- */
- void (*remove_hooks)(sim_manager_t *this, sim_hooks_t *hooks);
-
- /**
- * Invoke SIM/AKA message hook.
- *
- * @param message SIM message
- * @param inbound TRUE for incoming messages, FALSE for outgoing
- * @param decrypted TRUE if AT_ENCR_DATA has been decrypted
- */
- void (*message_hook)(sim_manager_t *this, simaka_message_t *message,
- bool inbound, bool decrypted);
-
- /**
- * Invoke SIM/AKA key hook.
- *
- * @param k_encr SIM/AKA encryption key k_encr
- * @param k_auth SIM/AKA authentication key k_auth
- */
- void (*key_hook)(sim_manager_t *this, chunk_t k_encr, chunk_t k_auth);
-
- /**
- * Destroy a manager instance.
- */
- void (*destroy)(sim_manager_t *this);
-};
-
-/**
- * Create an SIM manager to handle multiple (U)SIM cards/providers.
- *
- * @return sim_t object
- */
-sim_manager_t *sim_manager_create();
-
-#endif /** SIM_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap/sim_provider.h b/src/libcharon/sa/authenticators/eap/sim_provider.h
deleted file mode 100644
index 191e094db..000000000
--- a/src/libcharon/sa/authenticators/eap/sim_provider.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup sim_provider sim_provider
- * @{ @ingroup eap
- */
-
-#ifndef SIM_PROVIDER_H_
-#define SIM_PROVIDER_H_
-
-typedef struct sim_provider_t sim_provider_t;
-
-/**
- * Interface for a triplet/quintuplet provider (used as EAP server).
- *
- * A SIM provider hands out triplets for SIM authentication and quintuplets
- * for AKA authentication. Multiple SIM provider instances can serve as
- * authentication backend to authenticate clients using SIM/AKA.
- * An implementation supporting only one of SIM/AKA authentication may
- * implement the other methods with return_false().
- */
-struct sim_provider_t {
-
- /**
- * Create a challenge for SIM authentication.
- *
- * @param id permanent identity of peer to gen triplet for
- * @param rand RAND output buffer, fixed size 16 bytes
- * @param sres SRES output buffer, fixed size 4 byte
- * @param kc KC output buffer, fixed size 8 bytes
- * @return TRUE if triplet received, FALSE otherwise
- */
- bool (*get_triplet)(sim_provider_t *this, identification_t *id,
- char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN],
- char kc[SIM_KC_LEN]);
-
- /**
- * Create a challenge for AKA authentication.
- *
- * The XRES value is the only one with variable length. Pass a buffer
- * of at least AKA_RES_MAX, the actual number of bytes is written to the
- * xres_len value. While the standard would allow any bit length between
- * 32 and 128 bits, we support only full bytes for now.
- *
- * @param id permanent identity of peer to create challenge for
- * @param rand buffer receiving random value rand
- * @param xres buffer receiving expected authentication result xres
- * @param xres_len nubmer of bytes written to xres buffer
- * @param ck buffer receiving encryption key ck
- * @param ik buffer receiving integrity key ik
- * @param autn authentication token autn
- * @return TRUE if quintuplet generated successfully
- */
- bool (*get_quintuplet)(sim_provider_t *this, identification_t *id,
- char rand[AKA_RAND_LEN],
- char xres[AKA_RES_MAX], int *xres_len,
- char ck[AKA_CK_LEN], char ik[AKA_IK_LEN],
- char autn[AKA_AUTN_LEN]);
-
- /**
- * Process AKA resynchroniusation request of a peer.
- *
- * @param id permanent identity of peer requesting resynchronisation
- * @param rand random value rand
- * @param auts synchronization parameter auts
- * @return TRUE if resynchronized successfully
- */
- bool (*resync)(sim_provider_t *this, identification_t *id,
- char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]);
-
- /**
- * Check if peer uses a pseudonym, get permanent identity.
- *
- * @param id pseudonym identity candidate
- * @return permanent identity, NULL if id not a pseudonym
- */
- identification_t* (*is_pseudonym)(sim_provider_t *this,
- identification_t *id);
-
- /**
- * Generate a pseudonym identitiy for a given peer identity.
- *
- * @param id permanent identity to generate a pseudonym for
- * @return generated pseudonym, NULL to not use a pseudonym identity
- */
- identification_t* (*gen_pseudonym)(sim_provider_t *this,
- identification_t *id);
-
- /**
- * Check if peer uses reauthentication, retrieve reauth parameters.
- *
- * @param id reauthentication identity (candidate)
- * @param mk buffer receiving master key MK
- * @param counter pointer receiving current counter value, host order
- * @return permanent identity, NULL if id not a reauth identity
- */
- identification_t* (*is_reauth)(sim_provider_t *this, identification_t *id,
- char mk[HASH_SIZE_SHA1], u_int16_t *counter);
-
- /**
- * Generate a fast reauthentication identity, associated to a master key.
- *
- * @param id permanent peer identity
- * @param mk master key to store along with generated identity
- * @return fast reauthentication identity, NULL to not use reauth
- */
- identification_t* (*gen_reauth)(sim_provider_t *this, identification_t *id,
- char mk[HASH_SIZE_SHA1]);
-};
-
-#endif /** SIM_CARD_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
index d442acb00..5c8f0b6ce 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -160,7 +160,9 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
{
if (this->method->initiate(this->method, &out) == NEED_MORE)
{
- DBG1(DBG_IKE, "initiating EAP-Identity request");
+ DBG1(DBG_IKE, "initiating %N method (id 0x%02X)",
+ eap_type_names, EAP_IDENTITY,
+ this->method->get_identifier(this->method));
return out;
}
this->method->destroy(this->method);
@@ -216,23 +218,12 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
*/
static void replace_eap_identity(private_eap_authenticator_t *this)
{
- enumerator_t *enumerator;
- auth_rule_t rule;
+ identification_t *eap_identity;
auth_cfg_t *cfg;
- void *ptr;
+ eap_identity = this->eap_identity->clone(this->eap_identity);
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- enumerator = cfg->create_enumerator(cfg);
- while (enumerator->enumerate(enumerator, &rule, &ptr))
- {
- if (rule == AUTH_RULE_EAP_IDENTITY)
- {
- cfg->replace(cfg, enumerator, AUTH_RULE_EAP_IDENTITY,
- this->eap_identity->clone(this->eap_identity));
- break;
- }
- }
- enumerator->destroy(enumerator);
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity);
}
/**
@@ -349,8 +340,8 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
{
id = this->ike_sa->get_my_id(this->ike_sa);
}
- DBG1(DBG_IKE, "server requested %N, sending '%Y'",
- eap_type_names, type, id);
+ DBG1(DBG_IKE, "server requested %N (id 0x%02X), sending '%Y'",
+ eap_type_names, type, in->get_identifier(in), id);
this->eap_identity = id->clone(id);
this->method = load_method(this, type, vendor, EAP_PEER);
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index dc42ba787..2130a5998 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010 Tobias Brunner
+ * Copyright (C) 2006-2011 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -657,6 +657,55 @@ METHOD(child_sa_t, install, status_t,
return status;
}
+/**
+ * Install 3 policies: out, in and forward
+ */
+static status_t install_policies_internal(private_child_sa_t *this,
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
+{
+ status_t status = SUCCESS;
+ status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+ my_addr, other_addr, my_ts, other_ts,
+ POLICY_OUT, type, other_sa,
+ this->mark_out, priority);
+
+ status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+ other_addr, my_addr, other_ts, my_ts,
+ POLICY_IN, type, my_sa,
+ this->mark_in, priority);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+ other_addr, my_addr, other_ts, my_ts,
+ POLICY_FWD, type, my_sa,
+ this->mark_in, priority);
+ }
+ return status;
+}
+
+/**
+ * Delete 3 policies: out, in and forward
+ */
+static void del_policies_internal(private_child_sa_t *this,
+ traffic_selector_t *my_ts, traffic_selector_t *other_ts,
+ policy_priority_t priority)
+{
+ hydra->kernel_interface->del_policy(hydra->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, this->reqid,
+ this->mark_out, priority);
+ hydra->kernel_interface->del_policy(hydra->kernel_interface,
+ other_ts, my_ts, POLICY_IN, this->reqid,
+ this->mark_in, priority);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ hydra->kernel_interface->del_policy(hydra->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, this->reqid,
+ this->mark_in, priority);
+ }
+}
+
METHOD(child_sa_t, add_policies, status_t,
private_child_sa_t *this, linked_list_t *my_ts_list,
linked_list_t *other_ts_list)
@@ -664,7 +713,6 @@ METHOD(child_sa_t, add_policies, status_t,
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
status_t status = SUCCESS;
- bool routed = (this->state == CHILD_CREATED);
/* apply traffic selectors */
enumerator = my_ts_list->create_enumerator(my_ts_list);
@@ -682,6 +730,7 @@ METHOD(child_sa_t, add_policies, status_t,
if (this->config->install_policy(this->config))
{
+ policy_priority_t priority;
ipsec_sa_cfg_t my_sa = {
.mode = this->mode,
.reqid = this->reqid,
@@ -708,31 +757,28 @@ METHOD(child_sa_t, add_policies, status_t,
other_sa.ah.spi = this->other_spi;
}
+ priority = this->state == CHILD_CREATED ? POLICY_PRIORITY_ROUTED
+ : POLICY_PRIORITY_DEFAULT;
+
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- /* install 3 policies: out, in and forward */
- status |= hydra->kernel_interface->add_policy(
- hydra->kernel_interface,
- this->my_addr, this->other_addr, my_ts, other_ts,
- POLICY_OUT, POLICY_IPSEC, &other_sa,
- this->mark_out, routed);
-
- status |= hydra->kernel_interface->add_policy(
- hydra->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts,
- POLICY_IN, POLICY_IPSEC, &my_sa,
- this->mark_in, routed);
- if (this->mode != MODE_TRANSPORT)
+ /* install outbound drop policy to avoid packets leaving unencrypted
+ * when updating policies */
+ if (priority == POLICY_PRIORITY_DEFAULT)
{
- status |= hydra->kernel_interface->add_policy(
- hydra->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts,
- POLICY_FWD, POLICY_IPSEC, &my_sa,
- this->mark_in, routed);
+ status |= install_policies_internal(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK);
}
+ /* install policies */
+ status |= install_policies_internal(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_IPSEC, priority);
+
if (status != SUCCESS)
{
break;
@@ -769,7 +815,7 @@ METHOD(child_sa_t, update, status_t,
if (!transport_proxy_mode)
{
- /* update our (initator) SA */
+ /* update our (initiator) SA */
if (this->my_spi)
{
if (hydra->kernel_interface->update_sa(hydra->kernel_interface,
@@ -835,26 +881,22 @@ METHOD(child_sa_t, update, status_t,
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
+ traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
/* remove old policies first */
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE);
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_IN, this->mark_in, FALSE);
- if (this->mode != MODE_TRANSPORT)
- {
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE);
- }
+ del_policies_internal(this, my_ts, other_ts,
+ POLICY_PRIORITY_DEFAULT);
- /* check whether we have to update a "dynamic" traffic selector */
+ /* check if we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
my_ts->is_host(my_ts, this->my_addr))
{
+ old_my_ts = my_ts->clone(my_ts);
my_ts->set_address(my_ts, me);
}
if (!other->ip_equals(other, this->other_addr) &&
other_ts->is_host(other_ts, this->other_addr))
{
+ old_other_ts = other_ts->clone(other_ts);
other_ts->set_address(other_ts, other);
}
@@ -862,22 +904,28 @@ METHOD(child_sa_t, update, status_t,
* correctly */
if (vip)
{
- hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
- hydra->kernel_interface->add_ip(hydra->kernel_interface, vip, me);
+ hydra->kernel_interface->del_ip(hydra->kernel_interface,
+ vip);
+ hydra->kernel_interface->add_ip(hydra->kernel_interface,
+ vip, me);
}
/* reinstall updated policies */
- hydra->kernel_interface->add_policy(hydra->kernel_interface,
- me, other, my_ts, other_ts, POLICY_OUT, POLICY_IPSEC,
- &other_sa, this->mark_out, FALSE);
- hydra->kernel_interface->add_policy(hydra->kernel_interface,
- other, me, other_ts, my_ts, POLICY_IN, POLICY_IPSEC,
- &my_sa, this->mark_in, FALSE);
- if (this->mode != MODE_TRANSPORT)
+ install_policies_internal(this, me, other, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_IPSEC,
+ POLICY_PRIORITY_DEFAULT);
+
+ /* update fallback policies after the new policy is in place */
+ if (old_my_ts || old_other_ts)
{
- hydra->kernel_interface->add_policy(hydra->kernel_interface,
- other, me, other_ts, my_ts, POLICY_FWD, POLICY_IPSEC,
- &my_sa, this->mark_in, FALSE);
+ del_policies_internal(this, old_my_ts ?: my_ts,
+ old_other_ts ?: other_ts,
+ POLICY_PRIORITY_FALLBACK);
+ install_policies_internal(this, me, other, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK);
+ DESTROY_IF(old_my_ts);
+ DESTROY_IF(old_other_ts);
}
}
enumerator->destroy(enumerator);
@@ -910,7 +958,10 @@ METHOD(child_sa_t, destroy, void,
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
- bool unrouted = (this->state == CHILD_ROUTED);
+ policy_priority_t priority;
+
+ priority = this->state == CHILD_ROUTED ? POLICY_PRIORITY_ROUTED
+ : POLICY_PRIORITY_DEFAULT;
set_state(this, CHILD_DESTROYING);
@@ -942,14 +993,11 @@ METHOD(child_sa_t, destroy, void,
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted);
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_IN, this->mark_in, unrouted);
- if (this->mode != MODE_TRANSPORT)
+ del_policies_internal(this, my_ts, other_ts, priority);
+ if (priority == POLICY_PRIORITY_DEFAULT)
{
- hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted);
+ del_policies_internal(this, my_ts, other_ts,
+ POLICY_PRIORITY_FALLBACK);
}
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/connect_manager.c b/src/libcharon/sa/connect_manager.c
index 972cc98ad..7b6ca430f 100644
--- a/src/libcharon/sa/connect_manager.c
+++ b/src/libcharon/sa/connect_manager.c
@@ -130,25 +130,24 @@ static void endpoint_pair_destroy(endpoint_pair_t *this)
static endpoint_pair_t *endpoint_pair_create(endpoint_notify_t *initiator,
endpoint_notify_t *responder, bool initiator_is_local)
{
- endpoint_pair_t *this = malloc_thing(endpoint_pair_t);
-
- this->id = 0;
+ endpoint_pair_t *this;
u_int32_t pi = initiator->get_priority(initiator);
u_int32_t pr = responder->get_priority(responder);
- this->priority = pow(2, 32) * min(pi, pr) + 2 * max(pi, pr) + (pi > pr ? 1 : 0);
- this->local = initiator_is_local ? initiator->get_base(initiator)
- : responder->get_base(responder);
+ INIT(this,
+ .priority = pow(2, 32) * min(pi, pr) + 2 * max(pi, pr)
+ + (pi > pr ? 1 : 0),
+ .local = initiator_is_local ? initiator->get_base(initiator)
+ : responder->get_base(responder),
+ .remote = initiator_is_local ? responder->get_host(responder)
+ : initiator->get_host(initiator),
+ .state = CHECK_WAITING,
+ );
+
this->local = this->local->clone(this->local);
- this->remote = initiator_is_local ? responder->get_host(responder)
- : initiator->get_host(initiator);
this->remote = this->remote->clone(this->remote);
- this->state = CHECK_WAITING;
- this->retransmitted = 0;
- this->packet = NULL;
-
return this;
}
@@ -239,23 +238,24 @@ static check_list_t *check_list_create(identification_t *initiator,
linked_list_t *initiator_endpoints,
bool is_initiator)
{
- check_list_t *this = malloc_thing(check_list_t);
-
- this->connect_id = chunk_clone(connect_id);
-
- this->initiator.id = initiator->clone(initiator);
- this->initiator.key = chunk_clone(initiator_key);
- this->initiator.endpoints = initiator_endpoints->clone_offset(initiator_endpoints, offsetof(endpoint_notify_t, clone));
-
- this->responder.id = responder->clone(responder);
- this->responder.key = chunk_empty;
- this->responder.endpoints = NULL;
-
- this->pairs = linked_list_create();
- this->triggered = linked_list_create();
- this->state = CHECK_NONE;
- this->is_initiator = is_initiator;
- this->is_finishing = FALSE;
+ check_list_t *this;
+
+ INIT(this,
+ .connect_id = chunk_clone(connect_id),
+ .initiator = {
+ .id = initiator->clone(initiator),
+ .key = chunk_clone(initiator_key),
+ .endpoints = initiator_endpoints->clone_offset(initiator_endpoints,
+ offsetof(endpoint_notify_t, clone)),
+ },
+ .responder = {
+ .id = responder->clone(responder),
+ },
+ .pairs = linked_list_create(),
+ .triggered = linked_list_create(),
+ .state = CHECK_NONE,
+ .is_initiator = is_initiator,
+ );
return this;
}
@@ -294,11 +294,13 @@ static void initiated_destroy(initiated_t *this)
static initiated_t *initiated_create(identification_t *id,
identification_t *peer_id)
{
- initiated_t *this = malloc_thing(initiated_t);
+ initiated_t *this;
- this->id = id->clone(id);
- this->peer_id = peer_id->clone(peer_id);
- this->mediated = linked_list_create();
+ INIT(this,
+ .id = id->clone(id),
+ .peer_id = peer_id->clone(peer_id),
+ .mediated = linked_list_create(),
+ );
return this;
}
@@ -351,16 +353,11 @@ static void check_destroy(check_t *this)
*/
static check_t *check_create()
{
- check_t *this = malloc_thing(check_t);
-
- this->connect_id = chunk_empty;
- this->auth = chunk_empty;
- this->endpoint_raw = chunk_empty;
- this->src = NULL;
- this->dst = NULL;
- this->endpoint = NULL;
+ check_t *this;
- this->mid = 0;
+ INIT(this,
+ .mid = 0,
+ );
return this;
}
@@ -396,10 +393,12 @@ static void callback_data_destroy(callback_data_t *this)
static callback_data_t *callback_data_create(private_connect_manager_t *connect_manager,
chunk_t connect_id)
{
- callback_data_t *this = malloc_thing(callback_data_t);
- this->connect_manager = connect_manager;
- this->connect_id = chunk_clone(connect_id);
- this->mid = 0;
+ callback_data_t *this;
+ INIT(this,
+ .connect_manager = connect_manager,
+ .connect_id = chunk_clone(connect_id),
+ .mid = 0,
+ );
return this;
}
@@ -443,11 +442,11 @@ static void initiate_data_destroy(initiate_data_t *this)
static initiate_data_t *initiate_data_create(check_list_t *checklist,
initiated_t *initiated)
{
- initiate_data_t *this = malloc_thing(initiate_data_t);
-
- this->checklist = checklist;
- this->initiated = initiated;
-
+ initiate_data_t *this;
+ INIT(this,
+ .checklist = checklist,
+ .initiated = initiated,
+ );
return this;
}
@@ -476,19 +475,19 @@ static status_t get_initiated_by_ids(private_connect_manager_t *this,
static void remove_initiated(private_connect_manager_t *this,
initiated_t *initiated)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
initiated_t *current;
- iterator = this->initiated->create_iterator(this->initiated, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->initiated->create_enumerator(this->initiated);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current == initiated)
{
- iterator->remove(iterator);
+ this->initiated->remove_at(this->initiated, enumerator);
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -514,19 +513,19 @@ static status_t get_checklist_by_id(private_connect_manager_t *this,
static void remove_checklist(private_connect_manager_t *this,
check_list_t *checklist)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
check_list_t *current;
- iterator = this->checklists->create_iterator(this->checklists, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->checklists->create_enumerator(this->checklists);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current == checklist)
{
- iterator->remove(iterator);
+ this->checklists->remove_at(this->checklists, enumerator);
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -550,26 +549,15 @@ static status_t endpoints_contain(linked_list_t *endpoints, host_t *host,
*/
static void insert_pair_by_priority(linked_list_t *pairs, endpoint_pair_t *pair)
{
- iterator_t *iterator;
+ enumerator_t *enumerator = pairs->create_enumerator(pairs);
endpoint_pair_t *current;
- bool inserted = FALSE;
-
- iterator = pairs->create_iterator(pairs, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
- {
- if (current->priority < pair->priority)
- {
- iterator->insert_before(iterator, pair);
- inserted = TRUE;
- break;
- }
- }
- iterator->destroy(iterator);
-
- if (!inserted)
+ while (enumerator->enumerate(enumerator, (void**)&current) &&
+ current->priority >= pair->priority)
{
- pairs->insert_last(pairs, pair);
+ continue;
}
+ pairs->insert_before(pairs, enumerator, pair);
+ enumerator->destroy(enumerator);
}
/**
@@ -631,14 +619,14 @@ static bool match_waiting_pair(endpoint_pair_t *current)
static status_t get_triggered_pair(check_list_t *checklist,
endpoint_pair_t **pair)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
endpoint_pair_t *current;
status_t status = NOT_FOUND;
- iterator = checklist->triggered->create_iterator(checklist->triggered, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = checklist->triggered->create_enumerator(checklist->triggered);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
- iterator->remove(iterator);
+ checklist->triggered->remove_at(checklist->triggered, enumerator);
if (current->state == CHECK_WAITING)
{
@@ -650,7 +638,7 @@ static status_t get_triggered_pair(check_list_t *checklist,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return status;
}
@@ -660,17 +648,17 @@ static status_t get_triggered_pair(check_list_t *checklist,
*/
static void print_checklist(check_list_t *checklist)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
endpoint_pair_t *current;
DBG1(DBG_IKE, "pairs on checklist %#B:", &checklist->connect_id);
- iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = checklist->pairs->create_enumerator(checklist->pairs);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
DBG1(DBG_IKE, " * %#H - %#H (%d)", current->local, current->remote,
current->priority);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -679,17 +667,17 @@ static void print_checklist(check_list_t *checklist)
*/
static void prune_pairs(linked_list_t *pairs)
{
- iterator_t *iterator, *search;
+ enumerator_t *enumerator, *search;
endpoint_pair_t *current, *other;
u_int32_t id = 0;
- iterator = pairs->create_iterator(pairs, TRUE);
- search = pairs->create_iterator(pairs, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = pairs->create_enumerator(pairs);
+ search = pairs->create_enumerator(pairs);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
current->id = ++id;
- while (search->iterate(search, (void**)&other))
+ while (search->enumerate(search, (void**)&other))
{
if (current == other)
{
@@ -705,14 +693,14 @@ static void prune_pairs(linked_list_t *pairs)
* 'current', remove it */
DBG1(DBG_IKE, "pruning endpoint pair %#H - %#H with priority %d",
other->local, other->remote, other->priority);
- search->remove(search);
+ pairs->remove_at(pairs, search);
endpoint_pair_destroy(other);
}
}
- search->reset(search);
+ pairs->reset_enumerator(pairs, search);
}
search->destroy(search);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -721,16 +709,16 @@ static void prune_pairs(linked_list_t *pairs)
static void build_pairs(check_list_t *checklist)
{
/* FIXME: limit endpoints and pairs */
- iterator_t *iterator_i, *iterator_r;
+ enumerator_t *enumerator_i, *enumerator_r;
endpoint_notify_t *initiator, *responder;
- iterator_i = checklist->initiator.endpoints->create_iterator(
- checklist->initiator.endpoints, TRUE);
- while (iterator_i->iterate(iterator_i, (void**)&initiator))
+ enumerator_i = checklist->initiator.endpoints->create_enumerator(
+ checklist->initiator.endpoints);
+ while (enumerator_i->enumerate(enumerator_i, (void**)&initiator))
{
- iterator_r = checklist->responder.endpoints->create_iterator(
- checklist->responder.endpoints, TRUE);
- while (iterator_r->iterate(iterator_r, (void**)&responder))
+ enumerator_r = checklist->responder.endpoints->create_enumerator(
+ checklist->responder.endpoints);
+ while (enumerator_r->enumerate(enumerator_r, (void**)&responder))
{
if (initiator->get_family(initiator) != responder->get_family(responder))
{
@@ -740,9 +728,9 @@ static void build_pairs(check_list_t *checklist)
insert_pair_by_priority(checklist->pairs, endpoint_pair_create(
initiator, responder, checklist->is_initiator));
}
- iterator_r->destroy(iterator_r);
+ enumerator_r->destroy(enumerator_r);
}
- iterator_i->destroy(iterator_i);
+ enumerator_i->destroy(enumerator_i);
print_checklist(checklist);
@@ -895,19 +883,19 @@ static job_requeue_t initiator_finish(callback_data_t *data)
static void update_checklist_state(private_connect_manager_t *this,
check_list_t *checklist)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
endpoint_pair_t *current;
bool in_progress = FALSE, succeeded = FALSE;
- iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = checklist->pairs->create_enumerator(checklist->pairs);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
switch(current->state)
{
case CHECK_WAITING:
/* at least one is still waiting -> checklist remains
* in waiting state */
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return;
case CHECK_IN_PROGRESS:
in_progress = TRUE;
@@ -919,7 +907,7 @@ static void update_checklist_state(private_connect_manager_t *this,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (checklist->is_initiator && succeeded && !checklist->is_finishing)
{
@@ -1185,8 +1173,9 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
if (get_best_valid_pair(checklist, &pair) == SUCCESS)
{
ike_sa_id_t *waiting_sa;
- iterator_t *iterator = initiated->mediated->create_iterator(initiated->mediated, TRUE);
- while (iterator->iterate(iterator, (void**)&waiting_sa))
+ enumerator_t *enumerator = initiated->mediated->create_enumerator(
+ initiated->mediated);
+ while (enumerator->enumerate(enumerator, (void**)&waiting_sa))
{
ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa);
if (sa->initiate_mediated(sa, pair->local, pair->remote, checklist->connect_id) != SUCCESS)
@@ -1199,7 +1188,7 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
else
{
@@ -1355,10 +1344,8 @@ static void process_request(private_connect_manager_t *this, check_t *check,
check_destroy(response);
}
-/**
- * Implementation of connect_manager_t.process_check.
- */
-static void process_check(private_connect_manager_t *this, message_t *message)
+METHOD(connect_manager_t, process_check, void,
+ private_connect_manager_t *this, message_t *message)
{
if (message->parse_body(message, NULL) != SUCCESS)
{
@@ -1421,12 +1408,9 @@ static void process_check(private_connect_manager_t *this, message_t *message)
check_destroy(check);
}
-/**
- * Implementation of connect_manager_t.check_and_register.
- */
-static bool check_and_register(private_connect_manager_t *this,
- identification_t *id, identification_t *peer_id,
- ike_sa_id_t *mediated_sa)
+METHOD(connect_manager_t, check_and_register, bool,
+ private_connect_manager_t *this, identification_t *id,
+ identification_t *peer_id, ike_sa_id_t *mediated_sa)
{
initiated_t *initiated;
bool already_there = TRUE;
@@ -1455,12 +1439,9 @@ static bool check_and_register(private_connect_manager_t *this,
return already_there;
}
-/**
- * Implementation of connect_manager_t.check_and_initiate.
- */
-static void check_and_initiate(private_connect_manager_t *this,
- ike_sa_id_t *mediation_sa, identification_t *id,
- identification_t *peer_id)
+METHOD(connect_manager_t, check_and_initiate, void,
+ private_connect_manager_t *this, ike_sa_id_t *mediation_sa,
+ identification_t *id, identification_t *peer_id)
{
initiated_t *initiated;
@@ -1474,27 +1455,23 @@ static void check_and_initiate(private_connect_manager_t *this,
}
ike_sa_id_t *waiting_sa;
- iterator_t *iterator = initiated->mediated->create_iterator(
- initiated->mediated, TRUE);
- while (iterator->iterate(iterator, (void**)&waiting_sa))
+ enumerator_t *enumerator = initiated->mediated->create_enumerator(
+ initiated->mediated);
+ while (enumerator->enumerate(enumerator, (void**)&waiting_sa))
{
job_t *job = (job_t*)reinitiate_mediation_job_create(mediation_sa,
waiting_sa);
lib->processor->queue_job(lib->processor, job);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of connect_manager_t.set_initiator_data.
- */
-static status_t set_initiator_data(private_connect_manager_t *this,
- identification_t *initiator,
- identification_t *responder,
- chunk_t connect_id, chunk_t key,
- linked_list_t *endpoints, bool is_initiator)
+METHOD(connect_manager_t, set_initiator_data, status_t,
+ private_connect_manager_t *this, identification_t *initiator,
+ identification_t *responder, chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints, bool is_initiator)
{
check_list_t *checklist;
@@ -1517,12 +1494,9 @@ static status_t set_initiator_data(private_connect_manager_t *this,
return SUCCESS;
}
-/**
- * Implementation of connect_manager_t.set_responder_data.
- */
-static status_t set_responder_data(private_connect_manager_t *this,
- chunk_t connect_id, chunk_t key,
- linked_list_t *endpoints)
+METHOD(connect_manager_t, set_responder_data, status_t,
+ private_connect_manager_t *this, chunk_t connect_id, chunk_t key,
+ linked_list_t *endpoints)
{
check_list_t *checklist;
@@ -1551,10 +1525,8 @@ static status_t set_responder_data(private_connect_manager_t *this,
return SUCCESS;
}
-/**
- * Implementation of connect_manager_t.stop_checks.
- */
-static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
+METHOD(connect_manager_t, stop_checks, status_t,
+ private_connect_manager_t *this, chunk_t connect_id)
{
check_list_t *checklist;
@@ -1578,16 +1550,16 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
return SUCCESS;
}
-/**
- * Implementation of connect_manager_t.destroy.
- */
-static void destroy(private_connect_manager_t *this)
+METHOD(connect_manager_t, destroy, void,
+ private_connect_manager_t *this)
{
this->mutex->lock(this->mutex);
- this->hasher->destroy(this->hasher);
- this->checklists->destroy_function(this->checklists, (void*)check_list_destroy);
- this->initiated->destroy_function(this->initiated, (void*)initiated_destroy);
+ this->checklists->destroy_function(this->checklists,
+ (void*)check_list_destroy);
+ this->initiated->destroy_function(this->initiated,
+ (void*)initiated_destroy);
+ DESTROY_IF(this->hasher);
this->mutex->unlock(this->mutex);
this->mutex->destroy(this->mutex);
@@ -1599,28 +1571,30 @@ static void destroy(private_connect_manager_t *this)
*/
connect_manager_t *connect_manager_create()
{
- private_connect_manager_t *this = malloc_thing(private_connect_manager_t);
-
- this->public.destroy = (void(*)(connect_manager_t*))destroy;
- this->public.check_and_register = (bool(*)(connect_manager_t*,identification_t*,identification_t*,ike_sa_id_t*))check_and_register;
- this->public.check_and_initiate = (void(*)(connect_manager_t*,ike_sa_id_t*,identification_t*,identification_t*))check_and_initiate;
- this->public.set_initiator_data = (status_t(*)(connect_manager_t*,identification_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))set_initiator_data;
- this->public.set_responder_data = (status_t(*)(connect_manager_t*,chunk_t,chunk_t,linked_list_t*))set_responder_data;
- this->public.process_check = (void(*)(connect_manager_t*,message_t*))process_check;
- this->public.stop_checks = (status_t(*)(connect_manager_t*,chunk_t))stop_checks;
+ private_connect_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ .check_and_register = _check_and_register,
+ .check_and_initiate = _check_and_initiate,
+ .set_initiator_data = _set_initiator_data,
+ .set_responder_data = _set_responder_data,
+ .process_check = _process_check,
+ .stop_checks = _stop_checks,
+ },
+ .hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .checklists = linked_list_create(),
+ .initiated = linked_list_create(),
+ );
- this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (this->hasher == NULL)
{
DBG1(DBG_IKE, "unable to create connect manager, SHA1 not supported");
- free(this);
+ destroy(this);
return NULL;
}
- this->checklists = linked_list_create();
- this->initiated = linked_list_create();
-
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
-
- return (connect_manager_t*)this;
+ return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 2fc186fe8..07d19381d 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -208,9 +208,9 @@ struct private_ike_sa_t {
linked_list_t *attributes;
/**
- * list of peers additional addresses, transmitted via MOBIKE
+ * list of peer's addresses, additional ones transmitted via MOBIKE
*/
- linked_list_t *additional_addresses;
+ linked_list_t *peer_addresses;
/**
* previously value of received DESTINATION_IP hash
@@ -246,6 +246,11 @@ struct private_ike_sa_t {
* remote host address to be used for IKE, set via MIGRATE kernel message
*/
host_t *remote_host;
+
+ /**
+ * TRUE if we are currently reauthenticating this IKE_SA
+ */
+ bool is_reauthenticating;
};
/**
@@ -349,8 +354,8 @@ METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*,
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);
+ DESTROY_IF(this->peer_cfg);
this->peer_cfg = peer_cfg;
if (this->ike_cfg == NULL)
@@ -559,6 +564,10 @@ METHOD(ike_sa_t, send_dpd, status_t,
job_t *job;
time_t diff, delay;
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
delay = this->peer_cfg->get_dpd(this->peer_cfg);
if (this->task_manager->busy(this->task_manager))
{
@@ -615,6 +624,8 @@ METHOD(ike_sa_t, get_state, ike_sa_state_t,
METHOD(ike_sa_t, set_state, void,
private_ike_sa_t *this, ike_sa_state_t state)
{
+ bool trigger_dpd = FALSE;
+
DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
get_name(this), this->unique_id,
ike_sa_state_names, this->state,
@@ -675,28 +686,20 @@ METHOD(ike_sa_t, set_state, void,
lib->scheduler->schedule_job(lib->scheduler, job, t);
DBG1(DBG_IKE, "maximum IKE_SA lifetime %ds", t);
}
-
- /* start DPD checks */
- if (this->peer_cfg->get_dpd(this->peer_cfg))
- {
- send_dpd(this);
- }
+ trigger_dpd = this->peer_cfg->get_dpd(this->peer_cfg);
}
break;
}
- case IKE_DELETING:
- {
- /* delete may fail if a packet gets lost, so set a timeout */
- job_t *job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
- lib->scheduler->schedule_job(lib->scheduler, job,
- HALF_OPEN_IKE_SA_TIMEOUT);
- break;
- }
default:
break;
}
charon->bus->ike_state_change(charon->bus, &this->public, state);
this->state = state;
+
+ if (trigger_dpd)
+ {
+ send_dpd(this);
+ }
}
METHOD(ike_sa_t, reset, void,
@@ -768,17 +771,37 @@ METHOD(ike_sa_t, get_virtual_ip, host_t*,
}
}
-METHOD(ike_sa_t, add_additional_address, void,
+METHOD(ike_sa_t, add_peer_address, void,
private_ike_sa_t *this, host_t *host)
{
- this->additional_addresses->insert_last(this->additional_addresses, host);
+ this->peer_addresses->insert_last(this->peer_addresses, host);
}
-METHOD(ike_sa_t, create_additional_address_iterator, iterator_t*,
+METHOD(ike_sa_t, create_peer_address_enumerator, enumerator_t*,
private_ike_sa_t *this)
{
- return this->additional_addresses->create_iterator(
- this->additional_addresses, TRUE);
+ if (this->peer_addresses->get_count(this->peer_addresses))
+ {
+ return this->peer_addresses->create_enumerator(this->peer_addresses);
+ }
+ /* in case we don't have MOBIKE */
+ return enumerator_create_single(this->other_host, NULL);
+}
+
+METHOD(ike_sa_t, clear_peer_addresses, void,
+ private_ike_sa_t *this)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+
+ enumerator = this->peer_addresses->create_enumerator(this->peer_addresses);
+ while (enumerator->enumerate(enumerator, (void**)&host))
+ {
+ this->peer_addresses->remove_at(this->peer_addresses,
+ enumerator);
+ host->destroy(host);
+ }
+ enumerator->destroy(enumerator);
}
METHOD(ike_sa_t, has_mapping_changed, bool,
@@ -857,7 +880,7 @@ METHOD(ike_sa_t, update_hosts, void,
if (!other->equals(other, this->other_host))
{
- /* update others adress if we are NOT NATed */
+ /* update others address if we are NOT NATed */
if (force || !has_condition(this, COND_NAT_HERE))
{
set_other_host(this, other->clone(other));
@@ -869,11 +892,11 @@ METHOD(ike_sa_t, update_hosts, void,
/* update all associated CHILD_SAs, if required */
if (update)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa, this->my_host,
this->other_host, this->my_virtual_ip,
@@ -884,7 +907,7 @@ METHOD(ike_sa_t, update_hosts, void,
child_sa->get_spi(child_sa, TRUE));
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
}
@@ -1094,7 +1117,11 @@ METHOD(ike_sa_t, initiate, status_t,
if (this->state == IKE_CREATED)
{
- resolve_hosts(this);
+ if (this->my_host->is_anyaddr(this->my_host) ||
+ this->other_host->is_anyaddr(this->other_host))
+ {
+ resolve_hosts(this);
+ }
if (this->other_host->is_anyaddr(this->other_host)
#ifdef ME
@@ -1104,6 +1131,7 @@ METHOD(ike_sa_t, initiate, status_t,
{
child_cfg->destroy(child_cfg);
DBG1(DBG_IKE, "unable to initiate to %%any");
+ charon->bus->alert(charon->bus, ALERT_PEER_ADDR_FAILED);
return DESTROY_ME;
}
@@ -1289,7 +1317,8 @@ METHOD(ike_sa_t, process_message, status_t,
/* add a timeout if peer does not establish it completely */
job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE);
lib->scheduler->schedule_job(lib->scheduler, job,
- HALF_OPEN_IKE_SA_TIMEOUT);
+ lib->settings->get_int(lib->settings,
+ "charon.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT));
}
this->stats[STAT_INBOUND] = time_monotonic(NULL);
status = this->task_manager->process_message(this->task_manager,
@@ -1376,11 +1405,11 @@ METHOD(ike_sa_t, add_child_sa, void,
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;
+ enumerator_t *enumerator;
child_sa_t *current, *found = NULL;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current->get_spi(current, inbound) == spi &&
current->get_protocol(current) == protocol)
@@ -1388,14 +1417,26 @@ METHOD(ike_sa_t, get_child_sa, child_sa_t*,
found = current;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return found;
}
-METHOD(ike_sa_t, create_child_sa_iterator, iterator_t*,
+METHOD(ike_sa_t, get_child_count, int,
+ private_ike_sa_t *this)
+{
+ return this->child_sas->get_count(this->child_sas);
+}
+
+METHOD(ike_sa_t, create_child_sa_enumerator, enumerator_t*,
private_ike_sa_t *this)
{
- return this->child_sas->create_iterator(this->child_sas, TRUE);
+ return this->child_sas->create_enumerator(this->child_sas);
+}
+
+METHOD(ike_sa_t, remove_child_sa, void,
+ private_ike_sa_t *this, enumerator_t *enumerator)
+{
+ this->child_sas->remove_at(this->child_sas, enumerator);
}
METHOD(ike_sa_t, rekey_child_sa, status_t,
@@ -1403,6 +1444,11 @@ METHOD(ike_sa_t, rekey_child_sa, status_t,
{
child_rekey_t *child_rekey;
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
+
child_rekey = child_rekey_create(&this->public, protocol, spi);
this->task_manager->queue_task(this->task_manager, &child_rekey->task);
return this->task_manager->initiate(this->task_manager);
@@ -1413,6 +1459,11 @@ METHOD(ike_sa_t, delete_child_sa, status_t,
{
child_delete_t *child_delete;
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
+
child_delete = child_delete_create(&this->public, protocol, spi);
this->task_manager->queue_task(this->task_manager, &child_delete->task);
return this->task_manager->initiate(this->task_manager);
@@ -1421,23 +1472,23 @@ METHOD(ike_sa_t, delete_child_sa, status_t,
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;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
status_t status = NOT_FOUND;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->get_protocol(child_sa) == protocol &&
child_sa->get_spi(child_sa, TRUE) == spi)
{
+ this->child_sas->remove_at(this->child_sas, enumerator);
child_sa->destroy(child_sa);
- iterator->remove(iterator);
status = SUCCESS;
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return status;
}
@@ -1472,6 +1523,10 @@ METHOD(ike_sa_t, rekey, status_t,
{
ike_rekey_t *ike_rekey;
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
ike_rekey = ike_rekey_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, &ike_rekey->task);
@@ -1483,6 +1538,10 @@ METHOD(ike_sa_t, reauth, status_t,
{
task_t *task;
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
/* we can't reauthenticate as responder when we use EAP or virtual IPs.
* If the peer does not support RFC4478, there is no way to keep the
* IKE_SA up. */
@@ -1497,17 +1556,26 @@ METHOD(ike_sa_t, reauth, status_t,
#endif /* ME */
)
{
- time_t now = time_monotonic(NULL);
+ time_t del, now;
- DBG1(DBG_IKE, "IKE_SA will timeout in %V",
- &now, &this->stats[STAT_DELETE]);
+ del = this->stats[STAT_DELETE];
+ now = time_monotonic(NULL);
+ DBG1(DBG_IKE, "IKE_SA %s[%d] will timeout in %V",
+ get_name(this), this->unique_id, &now, &del);
return FAILED;
}
else
{
- DBG1(DBG_IKE, "reauthenticating actively");
+ DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d] actively",
+ get_name(this), this->unique_id);
}
}
+ else
+ {
+ DBG0(DBG_IKE, "reauthenticating IKE_SA %s[%d]",
+ get_name(this), this->unique_id);
+ }
+ this->is_reauthenticating = TRUE;
task = (task_t*)ike_reauth_create(&this->public);
this->task_manager->queue_task(this->task_manager, task);
@@ -1520,45 +1588,64 @@ METHOD(ike_sa_t, reestablish, status_t,
ike_sa_t *new;
host_t *host;
action_t action;
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
child_cfg_t *child_cfg;
bool restart = FALSE;
status_t status = FAILED;
- /* check if we have children to keep up at all */
- iterator = create_child_sa_iterator(this);
- while (iterator->iterate(iterator, (void**)&child_sa))
- {
- if (this->state == IKE_DELETING)
+ if (this->is_reauthenticating)
+ { /* only reauthenticate if we have children */
+ if (this->child_sas->get_count(this->child_sas) == 0
+#ifdef ME
+ /* allow reauth of mediation connections without CHILD_SAs */
+ && !this->peer_cfg->is_mediation(this->peer_cfg)
+#endif /* ME */
+ )
{
- action = child_sa->get_close_action(child_sa);
+ DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA "
+ "to recreate");
}
else
{
- action = child_sa->get_dpd_action(child_sa);
+ restart = TRUE;
}
- switch (action)
+ }
+ else
+ { /* check if we have children to keep up at all */
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
- case ACTION_RESTART:
- restart = TRUE;
- break;
- case ACTION_ROUTE:
- charon->traps->install(charon->traps, this->peer_cfg,
- child_sa->get_config(child_sa));
- break;
- default:
- break;
+ if (this->state == IKE_DELETING)
+ {
+ action = child_sa->get_close_action(child_sa);
+ }
+ else
+ {
+ action = child_sa->get_dpd_action(child_sa);
+ }
+ switch (action)
+ {
+ case ACTION_RESTART:
+ restart = TRUE;
+ break;
+ case ACTION_ROUTE:
+ charon->traps->install(charon->traps, this->peer_cfg,
+ child_sa->get_config(child_sa));
+ break;
+ default:
+ break;
+ }
}
- }
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
#ifdef ME
- /* mediation connections have no children, keep them up anyway */
- if (this->peer_cfg->is_mediation(this->peer_cfg))
- {
- restart = TRUE;
- }
+ /* mediation connections have no children, keep them up anyway */
+ if (this->peer_cfg->is_mediation(this->peer_cfg))
+ {
+ restart = TRUE;
+ }
#endif /* ME */
+ }
if (!restart)
{
return FAILED;
@@ -1598,16 +1685,37 @@ METHOD(ike_sa_t, reestablish, status_t,
else
#endif /* ME */
{
- iterator = create_child_sa_iterator(this);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
- if (this->state == IKE_DELETING)
+ if (this->is_reauthenticating)
{
- action = child_sa->get_close_action(child_sa);
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_ROUTED:
+ { /* move routed child directly */
+ this->child_sas->remove_at(this->child_sas, enumerator);
+ new->add_child_sa(new, child_sa);
+ action = ACTION_NONE;
+ break;
+ }
+ default:
+ { /* initiate/queue all other CHILD_SAs */
+ action = ACTION_RESTART;
+ break;
+ }
+ }
}
else
- {
- action = child_sa->get_dpd_action(child_sa);
+ { /* only restart CHILD_SAs that are configured accordingly */
+ if (this->state == IKE_DELETING)
+ {
+ action = child_sa->get_close_action(child_sa);
+ }
+ else
+ {
+ action = child_sa->get_dpd_action(child_sa);
+ }
}
switch (action)
{
@@ -1626,7 +1734,7 @@ METHOD(ike_sa_t, reestablish, status_t,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
if (status == DESTROY_ME)
@@ -1680,6 +1788,10 @@ static void requeue_init_tasks(private_ike_sa_t *this)
METHOD(ike_sa_t, retransmit, status_t,
private_ike_sa_t *this, u_int32_t message_id)
{
+ if (this->state == IKE_PASSIVE)
+ {
+ return INVALID_STATE;
+ }
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
@@ -1696,6 +1808,7 @@ METHOD(ike_sa_t, retransmit, status_t,
DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
this->keyingtry + 1, tries);
reset(this);
+ resolve_hosts(this);
requeue_init_tasks(this);
return this->task_manager->initiate(this->task_manager);
}
@@ -1704,6 +1817,12 @@ METHOD(ike_sa_t, retransmit, status_t,
}
case IKE_DELETING:
DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
+ if (this->is_reauthenticating)
+ {
+ DBG1(DBG_IKE, "delete during reauthentication failed, "
+ "trying to reestablish IKE_SA anyway");
+ reestablish(this);
+ }
break;
case IKE_REKEYING:
DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
@@ -1717,35 +1836,67 @@ METHOD(ike_sa_t, retransmit, status_t,
return SUCCESS;
}
-METHOD(ike_sa_t, set_auth_lifetime, void,
+METHOD(ike_sa_t, set_auth_lifetime, status_t,
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;
+ u_int32_t diff, hard, soft, now;
+ ike_auth_lifetime_t *task;
+ bool send_update;
- if (lifetime < reduction)
+ diff = this->peer_cfg->get_over_time(this->peer_cfg);
+ now = time_monotonic(NULL);
+ hard = now + lifetime;
+ soft = hard - diff;
+
+ /* check if we have to send an AUTH_LIFETIME to enforce the new lifetime.
+ * We send the notify in IKE_AUTH if not yet ESTABLISHED. */
+ send_update = this->state == IKE_ESTABLISHED &&
+ !has_condition(this, COND_ORIGINAL_INITIATOR) &&
+ (this->other_virtual_ip != NULL ||
+ has_condition(this, COND_EAP_AUTHENTICATED));
+
+ if (lifetime < diff)
{
- DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
- lifetime);
- lib->processor->queue_job(lib->processor,
+ this->stats[STAT_REAUTH] = now;
+
+ if (!send_update)
+ {
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
+ "starting reauthentication", lifetime);
+ lib->processor->queue_job(lib->processor,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
+ }
}
else if (this->stats[STAT_REAUTH] == 0 ||
- this->stats[STAT_REAUTH] > reauth_time)
+ this->stats[STAT_REAUTH] > soft)
{
- this->stats[STAT_REAUTH] = reauth_time;
- DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
- " in %ds", lifetime, lifetime - reduction);
- lib->scheduler->schedule_job(lib->scheduler,
+ this->stats[STAT_REAUTH] = soft;
+ if (!send_update)
+ {
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling "
+ "reauthentication in %ds", lifetime, lifetime - diff);
+ lib->scheduler->schedule_job(lib->scheduler,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
- lifetime - reduction);
+ lifetime - diff);
+ }
}
else
{
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, "
"reauthentication already scheduled in %ds", lifetime,
this->stats[STAT_REAUTH] - time_monotonic(NULL));
+ send_update = FALSE;
}
+ /* give at least some seconds to reauthenticate */
+ this->stats[STAT_DELETE] = max(hard, now + 10);
+
+ if (send_update)
+ {
+ task = ike_auth_lifetime_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, &task->task);
+ return this->task_manager->initiate(this->task_manager);
+ }
+ return SUCCESS;
}
/**
@@ -1776,26 +1927,21 @@ static bool is_any_path_valid(private_ike_sa_t *this)
{
bool valid = FALSE;
enumerator_t *enumerator;
- host_t *src, *addr;
+ host_t *src = NULL, *addr;
+
DBG1(DBG_IKE, "old path is not available anymore, try to find another");
- src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
- this->other_host, NULL);
- if (!src)
+ enumerator = create_peer_address_enumerator(this);
+ while (enumerator->enumerate(enumerator, &addr))
{
- enumerator = this->additional_addresses->create_enumerator(
- this->additional_addresses);
- while (enumerator->enumerate(enumerator, &addr))
+ DBG1(DBG_IKE, "looking for a route to %H ...", addr);
+ src = hydra->kernel_interface->get_source_addr(
+ hydra->kernel_interface, addr, NULL);
+ if (src)
{
- DBG1(DBG_IKE, "looking for a route to %H ...", addr);
- src = hydra->kernel_interface->get_source_addr(
- hydra->kernel_interface, addr, NULL);
- if (src)
- {
- break;
- }
+ break;
}
- enumerator->destroy(enumerator);
}
+ enumerator->destroy(enumerator);
if (src)
{
valid = TRUE;
@@ -1874,6 +2020,8 @@ METHOD(ike_sa_t, roam, status_t,
return SUCCESS;
}
DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
+ /* since our previous path is not valid anymore, try and find a new one */
+ resolve_hosts(this);
return reauth(this);
}
@@ -1902,6 +2050,8 @@ METHOD(ike_sa_t, inherit, void,
private_ike_sa_t *other = (private_ike_sa_t*)other_public;
child_sa_t *child_sa;
attribute_entry_t *entry;
+ enumerator_t *enumerator;
+ auth_cfg_t *cfg;
/* apply hosts and ids */
this->my_host->destroy(this->my_host);
@@ -1925,6 +2075,20 @@ METHOD(ike_sa_t, inherit, void,
other->other_virtual_ip = NULL;
}
+ /* authentication information */
+ enumerator = other->my_auths->create_enumerator(other->my_auths);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ this->my_auths->insert_last(this->my_auths, cfg->clone(cfg));
+ }
+ enumerator->destroy(enumerator);
+ enumerator = other->other_auths->create_enumerator(other->other_auths);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ this->other_auths->insert_last(this->other_auths, cfg->clone(cfg));
+ }
+ enumerator->destroy(enumerator);
+
/* ... and configuration attributes */
while (other->attributes->remove_last(other->attributes,
(void**)&entry) == SUCCESS)
@@ -2023,8 +2187,8 @@ METHOD(ike_sa_t, destroy, void,
}
this->other_virtual_ip->destroy(this->other_virtual_ip);
}
- this->additional_addresses->destroy_offset(this->additional_addresses,
- offsetof(host_t, destroy));
+ this->peer_addresses->destroy_offset(this->peer_addresses,
+ offsetof(host_t, destroy));
#ifdef ME
if (this->is_mediation_server)
{
@@ -2101,8 +2265,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.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,
+ .create_peer_address_enumerator = _create_peer_address_enumerator,
+ .add_peer_address = _add_peer_address,
+ .clear_peer_addresses = _clear_peer_addresses,
.has_mapping_changed = _has_mapping_changed,
.retransmit = _retransmit,
.delete = _delete_,
@@ -2112,7 +2277,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.get_keymat = _get_keymat,
.add_child_sa = _add_child_sa,
.get_child_sa = _get_child_sa,
- .create_child_sa_iterator = _create_child_sa_iterator,
+ .get_child_count = _get_child_count,
+ .create_child_sa_enumerator = _create_child_sa_enumerator,
+ .remove_child_sa = _remove_child_sa,
.rekey_child_sa = _rekey_child_sa,
.delete_child_sa = _delete_child_sa,
.destroy_child_sa = _destroy_child_sa,
@@ -2156,13 +2323,13 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
.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(),
+ .peer_addresses = linked_list_create(),
.attributes = linked_list_create(),
.keepalive_interval = lib->settings->get_time(lib->settings,
"charon.keep_alive", KEEPALIVE_INTERVAL),
);
+ this->task_manager = task_manager_create(&this->public);
this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
return &this->public;
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 69a74d8b7..537565e89 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -97,6 +97,11 @@ enum ike_extension_t {
* peer supports EAP-only authentication, draft-eronen-ipsec-ikev2-eap-auth
*/
EXT_EAP_ONLY_AUTHENTICATION = (1<<5),
+
+ /**
+ * peer is probably a Windows 7 RAS client
+ */
+ EXT_MS_WINDOWS = (1<<6),
};
/**
@@ -260,14 +265,14 @@ struct ike_sa_t {
*
* Returned ike_sa_id_t object is not getting cloned!
*
- * @return ike_sa's ike_sa_id_t
+ * @return ike_sa's ike_sa_id_t
*/
ike_sa_id_t* (*get_id) (ike_sa_t *this);
/**
* Get the numerical ID uniquely defining this IKE_SA.
*
- * @return unique ID
+ * @return unique ID
*/
u_int32_t (*get_unique_id) (ike_sa_t *this);
@@ -469,14 +474,19 @@ struct ike_sa_t {
*
* @param host host to add to list
*/
- void (*add_additional_address)(ike_sa_t *this, host_t *host);
+ void (*add_peer_address)(ike_sa_t *this, host_t *host);
/**
- * Create an iterator over all additional addresses of the peer.
+ * Create an enumerator over all known addresses of the peer.
*
- * @return iterator over addresses
+ * @return enumerator over addresses
+ */
+ enumerator_t* (*create_peer_address_enumerator)(ike_sa_t *this);
+
+ /**
+ * Remove all known addresses of the peer.
*/
- iterator_t* (*create_additional_address_iterator)(ike_sa_t *this);
+ void (*clear_peer_addresses)(ike_sa_t *this);
/**
* Check if mappings have changed on a NAT for our source address.
@@ -567,8 +577,8 @@ struct ike_sa_t {
*
* @param mediated_cfg peer_cfg of the mediated connection
* @return
- * - SUCCESS if initialization started
- * - DESTROY_ME if initialization failed
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
*/
status_t (*initiate_mediation) (ike_sa_t *this, peer_cfg_t *mediated_cfg);
@@ -579,8 +589,8 @@ struct ike_sa_t {
* @param other remote endpoint (gets cloned)
* @param connect_id connect ID (gets cloned)
* @return
- * - SUCCESS if initialization started
- * - DESTROY_ME if initialization failed
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
*/
status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other,
chunk_t connect_id);
@@ -597,8 +607,8 @@ struct ike_sa_t {
* @param endpoints endpoints
* @param response TRUE if this is a response
* @return
- * - SUCCESS if relay started
- * - DESTROY_ME if relay failed
+ * - SUCCESS if relay started
+ * - DESTROY_ME if relay failed
*/
status_t (*relay) (ike_sa_t *this, identification_t *requester,
chunk_t connect_id, chunk_t connect_key,
@@ -611,8 +621,8 @@ struct ike_sa_t {
*
* @param peer_id ID of the other peer
* @return
- * - SUCCESS if response started
- * - DESTROY_ME if response failed
+ * - SUCCESS if response started
+ * - DESTROY_ME if response failed
*/
status_t (*callback) (ike_sa_t *this, identification_t *peer_id);
@@ -624,8 +634,8 @@ struct ike_sa_t {
* @param peer_id ID of the other peer
* @param connect_id the connect ID supplied by the initiator
* @return
- * - SUCCESS if response started
- * - DESTROY_ME if response failed
+ * - SUCCESS if response started
+ * - DESTROY_ME if response failed
*/
status_t (*respond) (ike_sa_t *this, identification_t *peer_id,
chunk_t connect_id);
@@ -643,8 +653,8 @@ struct ike_sa_t {
* @param tsi source of triggering packet
* @param tsr destination of triggering packet.
* @return
- * - SUCCESS if initialization started
- * - DESTROY_ME if initialization failed
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed
*/
status_t (*initiate) (ike_sa_t *this, child_cfg_t *child_cfg,
u_int32_t reqid, traffic_selector_t *tsi,
@@ -658,10 +668,10 @@ struct ike_sa_t {
* the IKE SA gets deleted.
*
* @return
- * - SUCCESS if deletion is initialized
- * - DESTROY_ME, if the IKE_SA is not in
- * an established state and can not be
- * deleted (but destroyed).
+ * - SUCCESS if deletion is initialized
+ * - DESTROY_ME, if the IKE_SA is not in
+ * an established state and can not be
+ * deleted (but destroyed).
*/
status_t (*delete) (ike_sa_t *this);
@@ -684,13 +694,13 @@ struct ike_sa_t {
*
* Message processing may fail. If a critical failure occurs,
* process_message() return DESTROY_ME. Then the caller must
- * destroy the IKE_SA immediatly, as it is unusable.
+ * destroy the IKE_SA immediately, as it is unusable.
*
- * @param message message to process
+ * @param message message to process
* @return
- * - SUCCESS
- * - FAILED
- * - DESTROY_ME if this IKE_SA MUST be deleted
+ * - SUCCESS
+ * - FAILED
+ * - DESTROY_ME if this IKE_SA MUST be deleted
*/
status_t (*process_message) (ike_sa_t *this, message_t *message);
@@ -700,12 +710,12 @@ struct ike_sa_t {
* This method generates all payloads in the message and encrypts/signs
* the packet.
*
- * @param message message to generate
+ * @param message message to generate
* @param packet generated output packet
* @return
- * - SUCCESS
- * - FAILED
- * - DESTROY_ME if this IKE_SA MUST be deleted
+ * - SUCCESS
+ * - FAILED
+ * - DESTROY_ME if this IKE_SA MUST be deleted
*/
status_t (*generate_message) (ike_sa_t *this, message_t *message,
packet_t **packet);
@@ -715,8 +725,8 @@ struct ike_sa_t {
*
* @param message_id ID of the request to retransmit
* @return
- * - SUCCESS
- * - NOT_FOUND if request doesn't have to be retransmited
+ * - SUCCESS
+ * - NOT_FOUND if request doesn't have to be retransmited
*/
status_t (*retransmit) (ike_sa_t *this, u_int32_t message_id);
@@ -728,8 +738,8 @@ struct ike_sa_t {
* other traffic was received.
*
* @return
- * - SUCCESS
- * - DESTROY_ME, if peer did not respond
+ * - SUCCESS
+ * - DESTROY_ME, if peer did not respond
*/
status_t (*send_dpd) (ike_sa_t *this);
@@ -769,11 +779,25 @@ struct ike_sa_t {
u_int32_t spi, bool inbound);
/**
- * Create an iterator over all CHILD_SAs.
+ * Get the number of CHILD_SAs.
+ *
+ * @return number of CHILD_SAs
+ */
+ int (*get_child_count) (ike_sa_t *this);
+
+ /**
+ * Create an enumerator over all CHILD_SAs.
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_child_sa_enumerator) (ike_sa_t *this);
+
+ /**
+ * Remove the CHILD_SA the given enumerator points to from this IKE_SA.
*
- * @return iterator
+ * @param enumerator enumerator pointing to CHILD_SA
*/
- iterator_t* (*create_child_sa_iterator) (ike_sa_t *this);
+ void (*remove_child_sa) (ike_sa_t *this, enumerator_t *enumerator);
/**
* Rekey the CHILD SA with the specified reqid.
@@ -783,8 +807,8 @@ struct ike_sa_t {
* @param protocol protocol of the SA
* @param spi inbound SPI of the CHILD_SA
* @return
- * - NOT_FOUND, if IKE_SA has no such CHILD_SA
- * - SUCCESS, if rekeying initiated
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS, if rekeying initiated
*/
status_t (*rekey_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
@@ -798,8 +822,8 @@ struct ike_sa_t {
* @param protocol protocol of the SA
* @param spi inbound SPI of the CHILD_SA
* @return
- * - NOT_FOUND, if IKE_SA has no such CHILD_SA
- * - SUCCESS, if delete message sent
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS, if delete message sent
*/
status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
@@ -811,8 +835,8 @@ struct ike_sa_t {
* @param protocol protocol of the SA
* @param spi inbound SPI of the CHILD_SA
* @return
- * - NOT_FOUND, if IKE_SA has no such CHILD_SA
- * - SUCCESS
+ * - NOT_FOUND, if IKE_SA has no such CHILD_SA
+ * - SUCCESS
*/
status_t (*destroy_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
@@ -845,11 +869,15 @@ struct ike_sa_t {
status_t (*reestablish) (ike_sa_t *this);
/**
- * Set the lifetime limit received from a AUTH_LIFETIME notify.
+ * Set the lifetime limit received/to send in a AUTH_LIFETIME notify.
+ *
+ * If the IKE_SA is already ESTABLISHED, an INFORMATIONAL is sent with
+ * an AUTH_LIFETIME notify. The call never fails on unestablished SAs.
*
* @param lifetime lifetime in seconds
+ * @return DESTROY_ME to destroy the IKE_SA
*/
- void (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
+ status_t (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
/**
* Set the virtual IP to use for this IKE_SA and its children.
@@ -929,8 +957,8 @@ struct ike_sa_t {
/**
* Creates an ike_sa_t object with a specific ID.
*
- * @param ike_sa_id ike_sa_id_t object to associate with new IKE_SA
- * @return ike_sa_t object
+ * @param ike_sa_id ike_sa_id_t object to associate with new IKE_SA
+ * @return ike_sa_t object
*/
ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id);
diff --git a/src/libcharon/sa/ike_sa_id.c b/src/libcharon/sa/ike_sa_id.c
index 94c5405f2..bea4c2124 100644
--- a/src/libcharon/sa/ike_sa_id.c
+++ b/src/libcharon/sa/ike_sa_id.c
@@ -46,42 +46,32 @@ struct private_ike_sa_id_t {
bool is_initiator_flag;
};
-/**
- * Implementation of ike_sa_id_t.set_responder_spi.
- */
-static void set_responder_spi (private_ike_sa_id_t *this, u_int64_t responder_spi)
+METHOD(ike_sa_id_t, set_responder_spi, void,
+ private_ike_sa_id_t *this, u_int64_t responder_spi)
{
this->responder_spi = responder_spi;
}
-/**
- * Implementation of ike_sa_id_t.set_initiator_spi.
- */
-static void set_initiator_spi(private_ike_sa_id_t *this, u_int64_t initiator_spi)
+METHOD(ike_sa_id_t, set_initiator_spi, void,
+ private_ike_sa_id_t *this, u_int64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
-/**
- * Implementation of ike_sa_id_t.get_initiator_spi.
- */
-static u_int64_t get_initiator_spi (private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, get_initiator_spi, u_int64_t,
+ private_ike_sa_id_t *this)
{
return this->initiator_spi;
}
-/**
- * Implementation of ike_sa_id_t.get_responder_spi.
- */
-static u_int64_t get_responder_spi (private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, get_responder_spi, u_int64_t,
+ private_ike_sa_id_t *this)
{
return this->responder_spi;
}
-/**
- * Implementation of ike_sa_id_t.equals.
- */
-static bool equals (private_ike_sa_id_t *this, private_ike_sa_id_t *other)
+METHOD(ike_sa_id_t, equals, bool,
+ private_ike_sa_id_t *this, private_ike_sa_id_t *other)
{
if (other == NULL)
{
@@ -101,28 +91,22 @@ static bool equals (private_ike_sa_id_t *this, private_ike_sa_id_t *other)
}
}
-/**
- * Implementation of ike_sa_id_t.replace_values.
- */
-static void replace_values(private_ike_sa_id_t *this, private_ike_sa_id_t *other)
+METHOD(ike_sa_id_t, replace_values, void,
+ private_ike_sa_id_t *this, private_ike_sa_id_t *other)
{
this->initiator_spi = other->initiator_spi;
this->responder_spi = other->responder_spi;
this->is_initiator_flag = other->is_initiator_flag;
}
-/**
- * Implementation of ike_sa_id_t.is_initiator.
- */
-static bool is_initiator(private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, is_initiator, bool,
+ private_ike_sa_id_t *this)
{
return this->is_initiator_flag;
}
-/**
- * Implementation of ike_sa_id_t.switch_initiator.
- */
-static bool switch_initiator(private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, switch_initiator, bool,
+ private_ike_sa_id_t *this)
{
if (this->is_initiator_flag)
{
@@ -135,18 +119,15 @@ static bool switch_initiator(private_ike_sa_id_t *this)
return this->is_initiator_flag;
}
-/**
- * Implementation of ike_sa_id_t.clone.
- */
-static ike_sa_id_t* clone_(private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, clone_, ike_sa_id_t*,
+ private_ike_sa_id_t *this)
{
- return ike_sa_id_create(this->initiator_spi, this->responder_spi, this->is_initiator_flag);
+ return ike_sa_id_create(this->initiator_spi, this->responder_spi,
+ this->is_initiator_flag);
}
-/**
- * Implementation of ike_sa_id_t.destroy.
- */
-static void destroy(private_ike_sa_id_t *this)
+METHOD(ike_sa_id_t, destroy, void,
+ private_ike_sa_id_t *this)
{
free(this);
}
@@ -154,26 +135,28 @@ static void destroy(private_ike_sa_id_t *this)
/*
* Described in header.
*/
-ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiator_flag)
+ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
+ bool is_initiator_flag)
{
- private_ike_sa_id_t *this = malloc_thing(private_ike_sa_id_t);
-
- /* public functions */
- this->public.set_responder_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_responder_spi;
- this->public.set_initiator_spi = (void(*)(ike_sa_id_t*,u_int64_t)) set_initiator_spi;
- this->public.get_responder_spi = (u_int64_t(*)(ike_sa_id_t*)) get_responder_spi;
- this->public.get_initiator_spi = (u_int64_t(*)(ike_sa_id_t*)) get_initiator_spi;
- this->public.equals = (bool(*)(ike_sa_id_t*,ike_sa_id_t*)) equals;
- this->public.replace_values = (void(*)(ike_sa_id_t*,ike_sa_id_t*)) replace_values;
- this->public.is_initiator = (bool(*)(ike_sa_id_t*)) is_initiator;
- this->public.switch_initiator = (bool(*)(ike_sa_id_t*)) switch_initiator;
- this->public.clone = (ike_sa_id_t*(*)(ike_sa_id_t*)) clone_;
- this->public.destroy = (void(*)(ike_sa_id_t*))destroy;
-
- /* private data */
- this->initiator_spi = initiator_spi;
- this->responder_spi = responder_spi;
- this->is_initiator_flag = is_initiator_flag;
+ private_ike_sa_id_t *this;
+
+ INIT(this,
+ .public = {
+ .set_responder_spi = _set_responder_spi,
+ .set_initiator_spi = _set_initiator_spi,
+ .get_responder_spi = _get_responder_spi,
+ .get_initiator_spi = _get_initiator_spi,
+ .equals = (void*)_equals,
+ .replace_values = (void*)_replace_values,
+ .is_initiator = _is_initiator,
+ .switch_initiator = _switch_initiator,
+ .clone = _clone_,
+ .destroy = _destroy,
+ },
+ .initiator_spi = initiator_spi,
+ .responder_spi = responder_spi,
+ .is_initiator_flag = is_initiator_flag,
+ );
return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa_id.h b/src/libcharon/sa/ike_sa_id.h
index a833aa9d6..fb55359bc 100644
--- a/src/libcharon/sa/ike_sa_id.h
+++ b/src/libcharon/sa/ike_sa_id.h
@@ -30,7 +30,7 @@ typedef struct ike_sa_id_t ike_sa_id_t;
* An object of type ike_sa_id_t is used to identify an IKE_SA.
*
* An IKE_SA is identified by its initiator and responder spi's.
- * Additionaly it contains the role of the actual running IKEv2-Daemon
+ * Additionally it contains the role of the actual running IKEv2 daemon
* for the specific IKE_SA (original initiator or responder).
*/
struct ike_sa_id_t {
@@ -40,28 +40,28 @@ struct ike_sa_id_t {
*
* This function is called when a request or reply of a IKE_SA_INIT is received.
*
- * @param responder_spi SPI of responder to set
+ * @param responder_spi SPI of responder to set
*/
void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi);
/**
* Set the SPI of the initiator.
*
- * @param initiator_spi SPI to set
+ * @param initiator_spi SPI to set
*/
void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi);
/**
* Get the initiator SPI.
*
- * @return SPI of the initiator
+ * @return SPI of the initiator
*/
u_int64_t (*get_initiator_spi) (ike_sa_id_t *this);
/**
* Get the responder SPI.
*
- * @return SPI of the responder
+ * @return SPI of the responder
*/
u_int64_t (*get_responder_spi) (ike_sa_id_t *this);
@@ -70,8 +70,8 @@ struct ike_sa_id_t {
*
* Two ike_sa_id_t objects are equal if both SPI values and the role matches.
*
- * @param other ike_sa_id_t object to check if equal
- * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise
+ * @param other ike_sa_id_t object to check if equal
+ * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise
*/
bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other);
@@ -81,28 +81,28 @@ struct ike_sa_id_t {
*
* After calling this function, both objects are equal.
*
- * @param other ike_sa_id_t object from which values will be taken
+ * @param other ike_sa_id_t object from which values will be taken
*/
void (*replace_values) (ike_sa_id_t *this, ike_sa_id_t *other);
/**
* Get the initiator flag.
*
- * @return TRUE if we are the original initator
+ * @return TRUE if we are the original initiator
*/
bool (*is_initiator) (ike_sa_id_t *this);
/**
* Switche the original initiator flag.
*
- * @return TRUE if we are the original initator after switch, FALSE otherwise
+ * @return TRUE if we are the original initiator after switch, FALSE otherwise
*/
bool (*switch_initiator) (ike_sa_id_t *this);
/**
* Clones a given ike_sa_id_t object.
*
- * @return cloned ike_sa_id_t object
+ * @return cloned ike_sa_id_t object
*/
ike_sa_id_t *(*clone) (ike_sa_id_t *this);
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index d695c7f7c..731ae6007 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -307,72 +307,72 @@ struct private_ike_sa_manager_t {
/**
* Public interface of ike_sa_manager_t.
*/
- ike_sa_manager_t public;
-
- /**
- * Hash table with entries for the ike_sa_t objects.
- */
- linked_list_t **ike_sa_table;
-
- /**
- * The size of the hash table.
- */
- u_int table_size;
-
- /**
- * Mask to map the hashes to table rows.
- */
- u_int table_mask;
-
- /**
- * Segments of the hash table.
- */
- segment_t *segments;
-
- /**
- * The number of segments.
- */
- u_int segment_count;
-
- /**
- * Mask to map a table row to a segment.
- */
- u_int segment_mask;
-
- /**
- * Hash table with half_open_t objects.
- */
- linked_list_t **half_open_table;
-
- /**
+ ike_sa_manager_t public;
+
+ /**
+ * Hash table with entries for the ike_sa_t objects.
+ */
+ linked_list_t **ike_sa_table;
+
+ /**
+ * The size of the hash table.
+ */
+ u_int table_size;
+
+ /**
+ * Mask to map the hashes to table rows.
+ */
+ u_int table_mask;
+
+ /**
+ * Segments of the hash table.
+ */
+ segment_t *segments;
+
+ /**
+ * The number of segments.
+ */
+ u_int segment_count;
+
+ /**
+ * Mask to map a table row to a segment.
+ */
+ u_int segment_mask;
+
+ /**
+ * Hash table with half_open_t objects.
+ */
+ linked_list_t **half_open_table;
+
+ /**
* Segments of the "half-open" hash table.
- */
- shareable_segment_t *half_open_segments;
+ */
+ shareable_segment_t *half_open_segments;
- /**
- * Hash table with connected_peers_t objects.
- */
- linked_list_t **connected_peers_table;
+ /**
+ * Hash table with connected_peers_t objects.
+ */
+ linked_list_t **connected_peers_table;
- /**
- * Segments of the "connected peers" hash table.
- */
- shareable_segment_t *connected_peers_segments;
+ /**
+ * Segments of the "connected peers" hash table.
+ */
+ shareable_segment_t *connected_peers_segments;
- /**
- * RNG to get random SPIs for our side
- */
- rng_t *rng;
+ /**
+ * RNG to get random SPIs for our side
+ */
+ rng_t *rng;
- /**
- * SHA1 hasher for IKE_SA_INIT retransmit detection
- */
- hasher_t *hasher;
+ /**
+ * SHA1 hasher for IKE_SA_INIT retransmit detection
+ */
+ hasher_t *hasher;
/**
* reuse existing IKE_SAs in checkout_by_config
*/
- bool reuse_ikesa;
+ bool reuse_ikesa;
};
/**
@@ -1134,8 +1134,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
private_ike_sa_manager_t *this, u_int32_t id, bool child)
{
- enumerator_t *enumerator;
- iterator_t *children;
+ enumerator_t *enumerator, *children;
entry_t *entry;
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
@@ -1151,8 +1150,8 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
/* look for a child with such a reqid ... */
if (child)
{
- children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
- while (children->iterate(children, (void**)&child_sa))
+ children = entry->ike_sa->create_child_sa_enumerator(entry->ike_sa);
+ while (children->enumerate(children, (void**)&child_sa))
{
if (child_sa->get_reqid(child_sa) == id)
{
@@ -1188,8 +1187,7 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
private_ike_sa_manager_t *this, char *name, bool child)
{
- enumerator_t *enumerator;
- iterator_t *children;
+ enumerator_t *enumerator, *children;
entry_t *entry;
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
@@ -1203,8 +1201,8 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
/* look for a child with such a policy name ... */
if (child)
{
- children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
- while (children->iterate(children, (void**)&child_sa))
+ children = entry->ike_sa->create_child_sa_enumerator(entry->ike_sa);
+ while (children->enumerate(children, (void**)&child_sa))
{
if (streq(child_sa->get_name(child_sa), name))
{
@@ -1238,10 +1236,10 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
}
/**
- * enumerator filter function
+ * enumerator filter function, waiting variant
*/
-static bool enumerator_filter(private_ike_sa_manager_t *this,
- entry_t **in, ike_sa_t **out, u_int *segment)
+static bool enumerator_filter_wait(private_ike_sa_manager_t *this,
+ entry_t **in, ike_sa_t **out, u_int *segment)
{
if (wait_for_entry(this, *in, *segment))
{
@@ -1251,11 +1249,28 @@ static bool enumerator_filter(private_ike_sa_manager_t *this,
return FALSE;
}
+/**
+ * enumerator filter function, skipping variant
+ */
+static bool enumerator_filter_skip(private_ike_sa_manager_t *this,
+ entry_t **in, ike_sa_t **out, u_int *segment)
+{
+ if (!(*in)->driveout_new_threads &&
+ !(*in)->driveout_waiting_threads &&
+ !(*in)->checked_out)
+ {
+ *out = (*in)->ike_sa;
+ return TRUE;
+ }
+ return FALSE;
+}
+
METHOD(ike_sa_manager_t, create_enumerator, enumerator_t*,
- private_ike_sa_manager_t* this)
+ private_ike_sa_manager_t* this, bool wait)
{
return enumerator_create_filter(create_table_enumerator(this),
- (void*)enumerator_filter, this, NULL);
+ wait ? (void*)enumerator_filter_wait : (void*)enumerator_filter_skip,
+ this, NULL);
}
METHOD(ike_sa_manager_t, checkin, void,
@@ -1539,14 +1554,30 @@ METHOD(ike_sa_manager_t, has_contact, bool,
return found;
}
-METHOD(ike_sa_manager_t, get_half_open_count, int,
+METHOD(ike_sa_manager_t, get_count, u_int,
+ private_ike_sa_manager_t *this)
+{
+ u_int segment, count = 0;
+ mutex_t *mutex;
+
+ for (segment = 0; segment < this->segment_count; segment++)
+ {
+ mutex = this->segments[segment & this->segment_mask].mutex;
+ mutex->lock(mutex);
+ count += this->segments[segment].count;
+ mutex->unlock(mutex);
+ }
+ return count;
+}
+
+METHOD(ike_sa_manager_t, get_half_open_count, u_int,
private_ike_sa_manager_t *this, host_t *ip)
{
linked_list_t *list;
u_int segment, row;
rwlock_t *lock;
chunk_t addr;
- int count = 0;
+ u_int count = 0;
if (ip)
{
@@ -1728,6 +1759,7 @@ ike_sa_manager_t *ike_sa_manager_create()
.create_enumerator = _create_enumerator,
.checkin = _checkin,
.checkin_and_destroy = _checkin_and_destroy,
+ .get_count = _get_count,
.get_half_open_count = _get_half_open_count,
.flush = _flush,
.destroy = _destroy,
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index ec157ab3a..5e542e7df 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -162,9 +162,10 @@ struct ike_sa_manager_t {
* While enumerating an IKE_SA, it is temporarily checked out and
* automatically checked in after the current enumeration step.
*
+ * @param wait TRUE to wait for checked out SAs, FALSE to skip
* @return enumerator over all IKE_SAs.
*/
- enumerator_t *(*create_enumerator) (ike_sa_manager_t* this);
+ enumerator_t *(*create_enumerator) (ike_sa_manager_t* this, bool wait);
/**
* Checkin the SA after usage.
@@ -191,6 +192,13 @@ struct ike_sa_manager_t {
void (*checkin_and_destroy) (ike_sa_manager_t* this, ike_sa_t *ike_sa);
/**
+ * Get the number of IKE_SAs currently registered.
+ *
+ * @return number of registered IKE_SAs
+ */
+ u_int (*get_count)(ike_sa_manager_t *this);
+
+ /**
* Get the number of IKE_SAs which are in the connecting state.
*
* To prevent the server from resource exhaustion, cookies and other
@@ -203,7 +211,7 @@ struct ike_sa_manager_t {
* @param ip NULL for all, IP for half open IKE_SAs with IP
* @return number of half open IKE_SAs
*/
- int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
+ u_int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
/**
* Delete all existing IKE_SAs and destroy them immediately.
diff --git a/src/libcharon/sa/keymat.c b/src/libcharon/sa/keymat.c
index 33ece24b2..d762fa34e 100644
--- a/src/libcharon/sa/keymat.c
+++ b/src/libcharon/sa/keymat.c
@@ -99,7 +99,9 @@ keylen_entry_t keylen_enc[] = {
*/
keylen_entry_t keylen_int[] = {
{AUTH_HMAC_MD5_96, 128},
+ {AUTH_HMAC_MD5_128, 128},
{AUTH_HMAC_SHA1_96, 160},
+ {AUTH_HMAC_SHA1_160, 160},
{AUTH_HMAC_SHA2_256_96, 256},
{AUTH_HMAC_SHA2_256_128, 256},
{AUTH_HMAC_SHA2_384_192, 384},
diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h
index 11e0fa79a..6c2b5d4b5 100644
--- a/src/libcharon/sa/keymat.h
+++ b/src/libcharon/sa/keymat.h
@@ -40,7 +40,12 @@ struct keymat_t {
*
* The diffie hellman is either for IKE negotiation/rekeying or
* CHILD_SA rekeying (using PFS). The resulting DH object must be passed
- * to derive_keys or to derive_child_keys and destroyed after use
+ * to derive_keys or to derive_child_keys and destroyed after use.
+ *
+ * Only DH objects allocated through this method are passed to other
+ * keymat_t methods, allowing private DH implementations. In some cases
+ * (such as retrying with a COOKIE), a DH object allocated from a different
+ * keymat_t instance may be passed to other methods.
*
* @param group diffie hellman group
* @return DH object, NULL if group not supported
diff --git a/src/libcharon/sa/mediation_manager.c b/src/libcharon/sa/mediation_manager.c
index 2fbab7c7c..60eeb5d4b 100644
--- a/src/libcharon/sa/mediation_manager.c
+++ b/src/libcharon/sa/mediation_manager.c
@@ -53,13 +53,12 @@ static void peer_destroy(peer_t *this)
*/
static peer_t *peer_create(identification_t *id, ike_sa_id_t* ike_sa_id)
{
- peer_t *this = malloc_thing(peer_t);
-
- /* clone everything */
- this->id = id->clone(id);
- this->ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL;
- this->requested_by = linked_list_create();
-
+ peer_t *this;
+ INIT(this,
+ .id = id->clone(id),
+ .ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL,
+ .requested_by = linked_list_create(),
+ );
return this;
}
@@ -90,19 +89,19 @@ struct private_mediation_manager_t {
*/
static void register_peer(peer_t *peer, identification_t *peer_id)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
identification_t *current;
- iterator = peer->requested_by->create_iterator(peer->requested_by, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = peer->requested_by->create_enumerator(peer->requested_by);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (peer_id->equals(peer_id, current))
{
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
peer->requested_by->insert_last(peer->requested_by,
peer_id->clone(peer_id));
@@ -114,12 +113,12 @@ static void register_peer(peer_t *peer, identification_t *peer_id)
static status_t get_peer_by_id(private_mediation_manager_t *this,
identification_t *id, peer_t **peer)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
peer_t *current;
status_t status = NOT_FOUND;
- iterator = this->peers->create_iterator(this->peers, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->peers->create_enumerator(this->peers);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (id->equals(id, current->id))
{
@@ -131,7 +130,7 @@ static status_t get_peer_by_id(private_mediation_manager_t *this,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return status;
}
@@ -144,52 +143,50 @@ static status_t get_peer_by_id(private_mediation_manager_t *this,
static void unregister_peer(private_mediation_manager_t *this,
identification_t *peer_id)
{
- iterator_t *iterator, *iterator_r;
+ enumerator_t *enumerator, *enumerator_r;
peer_t *peer;
identification_t *registered;
- iterator = this->peers->create_iterator(this->peers, TRUE);
- while (iterator->iterate(iterator, (void**)&peer))
+ enumerator = this->peers->create_enumerator(this->peers);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
{
- iterator_r = peer->requested_by->create_iterator(peer->requested_by,
- TRUE);
- while (iterator_r->iterate(iterator_r, (void**)&registered))
+ enumerator_r = peer->requested_by->create_enumerator(peer->requested_by);
+ while (enumerator_r->enumerate(enumerator_r, (void**)&registered))
{
if (peer_id->equals(peer_id, registered))
{
- iterator_r->remove(iterator_r);
+ peer->requested_by->remove_at(peer->requested_by, enumerator_r);
registered->destroy(registered);
break;
}
}
- iterator_r->destroy(iterator_r);
+ enumerator_r->destroy(enumerator_r);
- if (!peer->ike_sa_id && !peer->requested_by->get_count(peer->requested_by))
+ if (!peer->ike_sa_id &&
+ !peer->requested_by->get_count(peer->requested_by))
{
- iterator->remove(iterator);
+ this->peers->remove_at(this->peers, enumerator);
peer_destroy(peer);
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
-/**
- * Implementation of mediation_manager_t.remove
- */
-static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
+METHOD(mediation_manager_t, remove_sa, void,
+ private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
peer_t *peer;
this->mutex->lock(this->mutex);
- iterator = this->peers->create_iterator(this->peers, TRUE);
- while (iterator->iterate(iterator, (void**)&peer))
+ enumerator = this->peers->create_enumerator(this->peers);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
{
if (ike_sa_id->equals(ike_sa_id, peer->ike_sa_id))
{
- iterator->remove(iterator);
+ this->peers->remove_at(this->peers, enumerator);
unregister_peer(this, peer->id);
@@ -197,24 +194,23 @@ static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of mediation_manager_t.update_sa_id
- */
-static void update_sa_id(private_mediation_manager_t *this, identification_t *peer_id, ike_sa_id_t *ike_sa_id)
+METHOD(mediation_manager_t, update_sa_id, void,
+ private_mediation_manager_t *this, identification_t *peer_id,
+ ike_sa_id_t *ike_sa_id)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
peer_t *peer;
bool found = FALSE;
this->mutex->lock(this->mutex);
- iterator = this->peers->create_iterator(this->peers, TRUE);
- while (iterator->iterate(iterator, (void**)&peer))
+ enumerator = this->peers->create_enumerator(this->peers);
+ while (enumerator->enumerate(enumerator, (void**)&peer))
{
if (peer_id->equals(peer_id, peer->id))
{
@@ -223,7 +219,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (!found)
{
@@ -248,11 +244,8 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of mediation_manager_t.check.
- */
-static ike_sa_id_t *check(private_mediation_manager_t *this,
- identification_t *peer_id)
+METHOD(mediation_manager_t, check, ike_sa_id_t*,
+ private_mediation_manager_t *this, identification_t *peer_id)
{
peer_t *peer;
ike_sa_id_t *ike_sa_id;
@@ -272,11 +265,9 @@ static ike_sa_id_t *check(private_mediation_manager_t *this,
return ike_sa_id;
}
-/**
- * Implementation of mediation_manager_t.check_and_register.
- */
-static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
- identification_t *peer_id, identification_t *requester)
+METHOD(mediation_manager_t, check_and_register, ike_sa_id_t*,
+ private_mediation_manager_t *this, identification_t *peer_id,
+ identification_t *requester)
{
peer_t *peer;
ike_sa_id_t *ike_sa_id;
@@ -307,10 +298,8 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
return ike_sa_id;
}
-/**
- * Implementation of mediation_manager_t.destroy.
- */
-static void destroy(private_mediation_manager_t *this)
+METHOD(mediation_manager_t, destroy, void,
+ private_mediation_manager_t *this)
{
this->mutex->lock(this->mutex);
@@ -326,16 +315,18 @@ static void destroy(private_mediation_manager_t *this)
*/
mediation_manager_t *mediation_manager_create()
{
- private_mediation_manager_t *this = malloc_thing(private_mediation_manager_t);
-
- this->public.destroy = (void(*)(mediation_manager_t*))destroy;
- this->public.remove = (void(*)(mediation_manager_t*,ike_sa_id_t*))remove_sa;
- this->public.update_sa_id = (void(*)(mediation_manager_t*,identification_t*,ike_sa_id_t*))update_sa_id;
- this->public.check = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*))check;
- this->public.check_and_register = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*,identification_t*))check_and_register;
-
- this->peers = linked_list_create();
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
-
- return (mediation_manager_t*)this;
+ private_mediation_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ .remove = _remove_sa,
+ .update_sa_id = _update_sa_id,
+ .check = _check,
+ .check_and_register = _check_and_register,
+ },
+ .peers = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+ return &this->public;
}
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
new file mode 100644
index 000000000..52b2ecd62
--- /dev/null
+++ b/src/libcharon/sa/shunt_manager.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "shunt_manager.h"
+
+#include <hydra.h>
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_shunt_manager_t private_shunt_manager_t;
+
+/**
+ * Private data of an shunt_manager_t object.
+ */
+struct private_shunt_manager_t {
+
+ /**
+ * Public shunt_manager_t interface.
+ */
+ shunt_manager_t public;
+
+ /**
+ * Installed shunts, as child_cfg_t
+ */
+ linked_list_t *shunts;
+};
+
+/**
+ * Install in and out shunt policies in the kernel
+ */
+static bool install_shunt_policy(child_cfg_t *child)
+{
+ enumerator_t *e_my_ts, *e_other_ts;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+ host_t *host_any;
+ policy_type_t policy_type;
+ status_t status = SUCCESS;
+ ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
+
+ policy_type = (child->get_mode(child) == MODE_PASS) ?
+ POLICY_PASS : POLICY_DROP;
+ my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, NULL);
+ other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, NULL);
+ host_any = host_create_any(AF_INET);
+
+ /* enumerate pairs of traffic selectors */
+ e_my_ts = my_ts_list->create_enumerator(my_ts_list);
+ while (e_my_ts->enumerate(e_my_ts, &my_ts))
+ {
+ e_other_ts = other_ts_list->create_enumerator(other_ts_list);
+ while (e_other_ts->enumerate(e_other_ts, &other_ts))
+ {
+ /* install out policy */
+ status |= hydra->kernel_interface->add_policy(
+ hydra->kernel_interface, host_any, host_any,
+ my_ts, other_ts, POLICY_OUT, policy_type,
+ &sa, child->get_mark(child, FALSE),
+ POLICY_PRIORITY_DEFAULT);
+
+ /* install in policy */
+ status |= hydra->kernel_interface->add_policy(
+ hydra->kernel_interface, host_any, host_any,
+ other_ts, my_ts, POLICY_IN, policy_type,
+ &sa, child->get_mark(child, TRUE),
+ POLICY_PRIORITY_DEFAULT);
+
+ /* install forward policy */
+ status |= hydra->kernel_interface->add_policy(
+ hydra->kernel_interface, host_any, host_any,
+ other_ts, my_ts, POLICY_FWD, policy_type,
+ &sa, child->get_mark(child, TRUE),
+ POLICY_PRIORITY_DEFAULT);
+ }
+ e_other_ts->destroy(e_other_ts);
+ }
+ e_my_ts->destroy(e_my_ts);
+
+ my_ts_list->destroy_offset(my_ts_list,
+ offsetof(traffic_selector_t, destroy));
+ other_ts_list->destroy_offset(other_ts_list,
+ offsetof(traffic_selector_t, destroy));
+ host_any->destroy(host_any);
+
+ return status == SUCCESS;
+}
+
+METHOD(shunt_manager_t, install, bool,
+ private_shunt_manager_t *this, child_cfg_t *child)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child_cfg;
+ bool found = FALSE;
+
+ /* check if not already installed */
+ enumerator = this->shunts->create_enumerator(this->shunts);
+ while (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ if (streq(child_cfg->get_name(child_cfg), child->get_name(child)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (found)
+ {
+ DBG1(DBG_CFG, "shunt %N policy '%s' already installed",
+ ipsec_mode_names, child->get_mode(child), child->get_name(child));
+ return TRUE;
+ }
+ this->shunts->insert_last(this->shunts, child->get_ref(child));
+
+ return install_shunt_policy(child);
+}
+
+/**
+ * Uninstall in and out shunt policies in the kernel
+ */
+static void uninstall_shunt_policy(child_cfg_t *child)
+{
+ enumerator_t *e_my_ts, *e_other_ts;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+ status_t status = SUCCESS;
+
+ my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, NULL);
+ other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, NULL);
+
+ /* enumerate pairs of traffic selectors */
+ e_my_ts = my_ts_list->create_enumerator(my_ts_list);
+ while (e_my_ts->enumerate(e_my_ts, &my_ts))
+ {
+ e_other_ts = other_ts_list->create_enumerator(other_ts_list);
+ while (e_other_ts->enumerate(e_other_ts, &other_ts))
+ {
+ /* uninstall out policy */
+ status |= hydra->kernel_interface->del_policy(
+ hydra->kernel_interface, my_ts, other_ts,
+ POLICY_OUT, 0, child->get_mark(child, FALSE),
+ POLICY_PRIORITY_DEFAULT);
+
+ /* uninstall in policy */
+ status |= hydra->kernel_interface->del_policy(
+ hydra->kernel_interface, other_ts, my_ts,
+ POLICY_IN, 0, child->get_mark(child, TRUE),
+ POLICY_PRIORITY_DEFAULT);
+
+ /* uninstall forward policy */
+ status |= hydra->kernel_interface->del_policy(
+ hydra->kernel_interface, other_ts, my_ts,
+ POLICY_FWD, 0, child->get_mark(child, TRUE),
+ POLICY_PRIORITY_DEFAULT);
+ }
+ e_other_ts->destroy(e_other_ts);
+ }
+ e_my_ts->destroy(e_my_ts);
+
+ my_ts_list->destroy_offset(my_ts_list,
+ offsetof(traffic_selector_t, destroy));
+ other_ts_list->destroy_offset(other_ts_list,
+ offsetof(traffic_selector_t, destroy));
+
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_CFG, "uninstalling shunt %N 'policy %s' failed",
+ ipsec_mode_names, child->get_mode(child), child->get_name(child));
+ }
+}
+
+METHOD(shunt_manager_t, uninstall, bool,
+ private_shunt_manager_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child, *found = NULL;
+
+ enumerator = this->shunts->create_enumerator(this->shunts);
+ while (enumerator->enumerate(enumerator, &child))
+ {
+ if (streq(name, child->get_name(child)))
+ {
+ this->shunts->remove_at(this->shunts, enumerator);
+ found = child;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ return FALSE;
+ }
+ uninstall_shunt_policy(child);
+ return TRUE;
+}
+
+METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
+ private_shunt_manager_t *this)
+{
+ return this->shunts->create_enumerator(this->shunts);
+}
+
+METHOD(shunt_manager_t, destroy, void,
+ private_shunt_manager_t *this)
+{
+ child_cfg_t *child;
+
+ while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
+ {
+ uninstall_shunt_policy(child);
+ child->destroy(child);
+ }
+ this->shunts->destroy(this->shunts);
+ free(this);
+}
+
+/**
+ * See header
+ */
+shunt_manager_t *shunt_manager_create()
+{
+ private_shunt_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .install = _install,
+ .uninstall = _uninstall,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .shunts = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/sa/shunt_manager.h b/src/libcharon/sa/shunt_manager.h
new file mode 100644
index 000000000..12ff08558
--- /dev/null
+++ b/src/libcharon/sa/shunt_manager.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup shunt_manager shunt_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef SHUNT_MANAGER_H_
+#define SHUNT_MANAGER_H_
+
+#include <library.h>
+#include <utils/enumerator.h>
+#include <config/child_cfg.h>
+
+typedef struct shunt_manager_t shunt_manager_t;
+
+/**
+ * Manage PASS and DROP shunt policy excepting traffic from IPsec SAs.
+ */
+struct shunt_manager_t {
+
+ /**
+ * Install a policy as a shunt.
+ *
+ * @param child child configuration to install as a shunt
+ * @return TRUE if installed successfully
+ */
+ bool (*install)(shunt_manager_t *this, child_cfg_t *child);
+
+ /**
+ * Uninstall a shunt policy.
+ *
+ * @param name name of child configuration to uninstall as a shunt
+ * @return TRUE if uninstalled successfully
+ */
+ bool (*uninstall)(shunt_manager_t *this, char *name);
+
+ /**
+ * Create an enumerator over all installed shunts.
+ *
+ * @return enumerator over (child_sa_t)
+ */
+ enumerator_t* (*create_enumerator)(shunt_manager_t *this);
+
+ /**
+ * Destroy a shunt_manager_t.
+ */
+ void (*destroy)(shunt_manager_t *this);
+};
+
+/**
+ * Create a shunt_manager instance.
+ */
+shunt_manager_t *shunt_manager_create();
+
+#endif /** SHUNT_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index f07d2e384..022a5e3d6 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -159,15 +159,15 @@ struct private_task_manager_t {
*/
static void flush(private_task_manager_t *this)
{
- this->queued_tasks->destroy_offset(this->queued_tasks,
- offsetof(task_t, destroy));
- this->queued_tasks = linked_list_create();
this->passive_tasks->destroy_offset(this->passive_tasks,
offsetof(task_t, destroy));
this->passive_tasks = linked_list_create();
this->active_tasks->destroy_offset(this->active_tasks,
offsetof(task_t, destroy));
this->active_tasks = linked_list_create();
+ this->queued_tasks->destroy_offset(this->queued_tasks,
+ offsetof(task_t, destroy));
+ this->queued_tasks = linked_list_create();
}
/**
@@ -175,23 +175,23 @@ static void flush(private_task_manager_t *this)
*/
static bool activate_task(private_task_manager_t *this, task_type_t type)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *task;
bool found = FALSE;
- iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
- while (iterator->iterate(iterator, (void**)&task))
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
{
if (task->get_type(task) == type)
{
DBG2(DBG_IKE, " activating %N task", task_type_names, type);
- iterator->remove(iterator);
+ this->queued_tasks->remove_at(this->queued_tasks, enumerator);
this->active_tasks->insert_last(this->active_tasks, task);
found = TRUE;
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return found;
}
@@ -202,14 +202,14 @@ METHOD(task_manager_t, retransmit, status_t,
{
u_int32_t timeout;
job_t *job;
- iterator_t *iterator;
+ enumerator_t *enumerator;
packet_t *packet;
task_t *task;
ike_mobike_t *mobike = NULL;
/* check if we are retransmitting a MOBIKE routability check */
- iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
- while (iterator->iterate(iterator, (void*)&task))
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
if (task->get_type(task) == IKE_MOBIKE)
{
@@ -221,7 +221,7 @@ METHOD(task_manager_t, retransmit, status_t,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (mobike == NULL)
{
@@ -282,7 +282,7 @@ METHOD(task_manager_t, retransmit, status_t,
METHOD(task_manager_t, initiate, status_t,
private_task_manager_t *this)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *task;
message_t *message;
host_t *me, *other;
@@ -366,6 +366,11 @@ METHOD(task_manager_t, initiate, status_t,
exchange = INFORMATIONAL;
break;
}
+ if (activate_task(this, IKE_AUTH_LIFETIME))
+ {
+ exchange = INFORMATIONAL;
+ break;
+ }
#ifdef ME
if (activate_task(this, IKE_ME))
{
@@ -387,8 +392,8 @@ METHOD(task_manager_t, initiate, status_t,
else
{
DBG2(DBG_IKE, "reinitiating already active tasks");
- iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
- while (iterator->iterate(iterator, (void**)&task))
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&task))
{
DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
switch (task->get_type(task))
@@ -406,12 +411,13 @@ METHOD(task_manager_t, initiate, status_t,
break;
case IKE_MOBIKE:
exchange = INFORMATIONAL;
+ break;
default:
continue;
}
break;
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
if (exchange == 0)
@@ -432,14 +438,14 @@ METHOD(task_manager_t, initiate, status_t,
this->initiating.type = exchange;
this->initiating.retransmitted = 0;
- iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
- while (iterator->iterate(iterator, (void*)&task))
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->build(task, message))
{
case SUCCESS:
/* task completed, remove it */
- iterator->remove(iterator);
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -454,13 +460,13 @@ METHOD(task_manager_t, initiate, status_t,
/* FALL */
case DESTROY_ME:
/* critical failure, destroy IKE_SA */
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
message->destroy(message);
flush(this);
return DESTROY_ME;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
/* update exchange type if a task changed it */
this->initiating.type = message->get_exchange_type(message);
@@ -487,7 +493,7 @@ METHOD(task_manager_t, initiate, status_t,
static status_t process_response(private_task_manager_t *this,
message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *task;
if (message->get_exchange_type(message) != this->initiating.type)
@@ -501,14 +507,14 @@ static status_t process_response(private_task_manager_t *this,
/* catch if we get resetted while processing */
this->reset = FALSE;
- iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
- while (iterator->iterate(iterator, (void*)&task))
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->process(task, message))
{
case SUCCESS:
/* task completed, remove it */
- iterator->remove(iterator);
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -520,19 +526,19 @@ static status_t process_response(private_task_manager_t *this,
/* FALL */
case DESTROY_ME:
/* critical failure, destroy IKE_SA */
- iterator->remove(iterator);
- iterator->destroy(iterator);
+ this->active_tasks->remove_at(this->active_tasks, enumerator);
+ enumerator->destroy(enumerator);
task->destroy(task);
return DESTROY_ME;
}
if (this->reset)
{ /* start all over again if we were reset */
this->reset = FALSE;
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return initiate(this);
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->initiating.mid++;
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
@@ -547,7 +553,7 @@ static status_t process_response(private_task_manager_t *this,
*/
static bool handle_collisions(private_task_manager_t *this, task_t *task)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *active;
task_type_t type;
@@ -558,8 +564,8 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
type == CHILD_DELETE || type == IKE_DELETE || type == IKE_REAUTH)
{
/* find an exchange collision, and notify these tasks */
- iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
- while (iterator->iterate(iterator, (void**)&active))
+ enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&active))
{
switch (active->get_type(active))
{
@@ -583,10 +589,10 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
default:
continue;
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return TRUE;
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
return FALSE;
}
@@ -596,11 +602,11 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
*/
static status_t build_response(private_task_manager_t *this, message_t *request)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *task;
message_t *message;
host_t *me, *other;
- bool delete = FALSE;
+ bool delete = FALSE, hook = FALSE;
status_t status;
me = request->get_destination(request);
@@ -614,14 +620,14 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
message->set_message_id(message, this->responding.mid);
message->set_request(message, FALSE);
- iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
- while (iterator->iterate(iterator, (void*)&task))
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->build(task, message))
{
case SUCCESS:
/* task completed, remove it */
- iterator->remove(iterator);
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
if (!handle_collisions(this, task))
{
task->destroy(task);
@@ -631,12 +637,13 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
/* processed, but task needs another exchange */
if (handle_collisions(this, task))
{
- iterator->remove(iterator);
+ this->passive_tasks->remove_at(this->passive_tasks,
+ enumerator);
}
break;
case FAILED:
default:
- charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ hook = TRUE;
/* FALL */
case DESTROY_ME:
/* destroy IKE_SA, but SEND response first */
@@ -648,7 +655,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
/* remove resonder SPI if IKE_SA_INIT failed */
if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
@@ -673,6 +680,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
this->responding.packet->clone(this->responding.packet));
if (delete)
{
+ if (hook)
+ {
+ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+ }
return DESTROY_ME;
}
return SUCCESS;
@@ -685,7 +696,6 @@ static status_t process_request(private_task_manager_t *this,
message_t *message)
{
enumerator_t *enumerator;
- iterator_t *iterator;
task_t *task = NULL;
payload_t *payload;
notify_payload_t *notify;
@@ -854,14 +864,14 @@ static status_t process_request(private_task_manager_t *this,
}
/* let the tasks process the message */
- iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
- while (iterator->iterate(iterator, (void*)&task))
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->process(task, message))
{
case SUCCESS:
/* task completed, remove it */
- iterator->remove(iterator);
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -873,13 +883,13 @@ static status_t process_request(private_task_manager_t *this,
/* FALL */
case DESTROY_ME:
/* critical failure, destroy IKE_SA */
- iterator->remove(iterator);
- iterator->destroy(iterator);
+ this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ enumerator->destroy(enumerator);
task->destroy(task);
return DESTROY_ME;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return build_response(this, message);
}
@@ -978,20 +988,20 @@ METHOD(task_manager_t, queue_task, void,
{
if (task->get_type(task) == IKE_MOBIKE)
{ /* there is no need to queue more than one mobike task */
- iterator_t *iterator;
+ enumerator_t *enumerator;
task_t *current;
- iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current->get_type(current) == IKE_MOBIKE)
{
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
task->destroy(task);
return;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
this->queued_tasks->insert_last(this->queued_tasks, task);
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
index fc02a334b..67c29d31f 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -213,13 +213,13 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host)
{
traffic_selector_t *ts;
bool is_host = TRUE;
- iterator_t *iterator = list->create_iterator(list, TRUE);
+ enumerator_t *enumerator = list->create_enumerator(list);
- while (is_host && iterator->iterate(iterator, (void**)&ts))
+ while (is_host && enumerator->enumerate(enumerator, (void**)&ts))
{
is_host = is_host && ts->is_host(ts, host);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return is_host;
}
@@ -886,6 +886,10 @@ static void handle_child_sa_failure(private_child_create_t *this,
delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
100);
}
+ else
+ {
+ DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
+ }
}
METHOD(task_t, build_r, status_t,
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c
index e6834a93c..dc4b30dd3 100644
--- a/src/libcharon/sa/tasks/child_delete.c
+++ b/src/libcharon/sa/tasks/child_delete.c
@@ -73,11 +73,11 @@ struct private_child_delete_t {
static void build_payloads(private_child_delete_t *this, message_t *message)
{
delete_payload_t *ah = NULL, *esp = NULL;
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
protocol_id_t protocol = child_sa->get_protocol(child_sa);
u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
@@ -109,7 +109,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
}
child_sa->set_state(child_sa, CHILD_DELETING);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -186,7 +186,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
*/
static status_t destroy_and_reestablish(private_child_delete_t *this)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
child_cfg_t *child_cfg;
protocol_id_t protocol;
@@ -194,8 +194,8 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
action_t action;
status_t status = SUCCESS;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
/* signal child down event if we are not rekeying */
if (!this->rekeyed)
@@ -231,7 +231,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return status;
}
@@ -240,12 +240,12 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
*/
static void log_children(private_child_delete_t *this)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
u_int64_t bytes_in, bytes_out;
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
@@ -258,13 +258,11 @@ static void log_children(private_child_delete_t *this)
child_sa->get_traffic_selectors(child_sa, TRUE),
child_sa->get_traffic_selectors(child_sa, FALSE));
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_child_delete_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_child_delete_t *this, message_t *message)
{
child_sa_t *child_sa;
@@ -291,10 +289,8 @@ static status_t build_i(private_child_delete_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_child_delete_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_child_delete_t *this, message_t *message)
{
/* flush the list before adding new SAs */
this->child_sas->destroy(this->child_sas);
@@ -305,20 +301,16 @@ static status_t process_i(private_child_delete_t *this, message_t *message)
return destroy_and_reestablish(this);
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_r(private_child_delete_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_child_delete_t *this, message_t *message)
{
process_payloads(this, message);
log_children(this);
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_child_delete_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_child_delete_t *this, message_t *message)
{
/* if we are rekeying, we send an empty informational */
if (this->ike_sa->get_state(this->ike_sa) != IKE_REKEYING)
@@ -329,28 +321,22 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
return destroy_and_reestablish(this);
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_child_delete_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_child_delete_t *this)
{
return CHILD_DELETE;
}
-/**
- * Implementation of child_delete_t.get_child
- */
-static child_sa_t* get_child(private_child_delete_t *this)
+METHOD(child_delete_t , get_child, child_sa_t*,
+ private_child_delete_t *this)
{
child_sa_t *child_sa = NULL;
this->child_sas->get_first(this->child_sas, (void**)&child_sa);
return child_sa;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_child_delete_t *this, ike_sa_t *ike_sa)
{
this->check_delete_action = FALSE;
this->ike_sa = ike_sa;
@@ -359,10 +345,8 @@ static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa)
this->child_sas = linked_list_create();
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_child_delete_t *this)
+METHOD(task_t, destroy, void,
+ private_child_delete_t *this)
{
this->child_sas->destroy(this->child_sas);
free(this);
@@ -374,30 +358,33 @@ static void destroy(private_child_delete_t *this)
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi)
{
- private_child_delete_t *this = malloc_thing(private_child_delete_t);
-
- this->public.get_child = (child_sa_t*(*)(child_delete_t*))get_child;
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->check_delete_action = FALSE;
- this->child_sas = linked_list_create();
- this->protocol = protocol;
- this->spi = spi;
- this->rekeyed = FALSE;
+ private_child_delete_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .get_child = _get_child,
+ },
+ .ike_sa = ike_sa,
+ .child_sas = linked_list_create(),
+ .protocol = protocol,
+ .spi = spi,
+ );
if (protocol != PROTO_NONE)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
this->initiator = TRUE;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
this->initiator = FALSE;
}
return &this->public;
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
index b39a5fc67..76d185590 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -128,10 +128,8 @@ static void find_child(private_child_rekey_t *this, message_t *message)
}
}
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_child_rekey_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_child_rekey_t *this, message_t *message)
{
notify_payload_t *notify;
u_int32_t reqid;
@@ -175,10 +173,8 @@ static status_t build_i(private_child_rekey_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_r(private_child_rekey_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_child_rekey_t *this, message_t *message)
{
/* let the CHILD_CREATE task process the message */
this->child_create->task.process(&this->child_create->task, message);
@@ -188,10 +184,8 @@ static status_t process_r(private_child_rekey_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_child_rekey_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_child_rekey_t *this, message_t *message)
{
u_int32_t reqid;
@@ -252,7 +246,10 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
{
/* 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);
+ if (child_sa)
+ {
+ child_sa->set_close_action(child_sa, ACTION_NONE);
+ }
}
}
else
@@ -284,10 +281,8 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
return to_delete;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_child_rekey_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_child_rekey_t *this, message_t *message)
{
protocol_id_t protocol;
u_int32_t spi;
@@ -314,7 +309,7 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
{
/* establishing new child failed, reuse old. but not when we
- * recieved a delete in the meantime */
+ * received a delete in the meantime */
if (!(this->collision &&
this->collision->get_type(this->collision) == CHILD_DELETE))
{
@@ -364,18 +359,14 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_child_rekey_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_child_rekey_t *this)
{
return CHILD_REKEY;
}
-/**
- * Implementation of child_rekey_t.collide
- */
-static void collide(private_child_rekey_t *this, task_t *other)
+METHOD(child_rekey_t, collide, void,
+ private_child_rekey_t *this, task_t *other)
{
/* the task manager only detects exchange collision, but not if
* the collision is for the same child. we check it here. */
@@ -418,10 +409,8 @@ static void collide(private_child_rekey_t *this, task_t *other)
this->collision = other;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_child_rekey_t *this, ike_sa_t *ike_sa)
{
if (this->child_create)
{
@@ -437,10 +426,8 @@ static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa)
this->collision = NULL;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_child_rekey_t *this)
+METHOD(task_t, destroy, void,
+ private_child_rekey_t *this)
{
if (this->child_create)
{
@@ -460,34 +447,36 @@ static void destroy(private_child_rekey_t *this)
child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi)
{
- private_child_rekey_t *this = malloc_thing(private_child_rekey_t);
-
- this->public.collide = (void (*)(child_rekey_t*,task_t*))collide;
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_child_rekey_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .collide = _collide,
+ },
+ .ike_sa = ike_sa,
+ .protocol = protocol,
+ .spi = spi,
+ );
+
if (protocol != PROTO_NONE)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
this->initiator = TRUE;
this->child_create = NULL;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
this->initiator = FALSE;
this->child_create = child_create_create(ike_sa, NULL, TRUE, NULL, NULL);
}
- this->ike_sa = ike_sa;
- this->child_sa = NULL;
- this->protocol = protocol;
- this->spi = spi;
- this->collision = NULL;
- this->child_delete = NULL;
- this->other_child_destroyed = FALSE;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
index 0756c7d60..665468fe8 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -417,10 +418,14 @@ METHOD(task_t, build_i, status_t,
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!idi)
- {
- DBG1(DBG_CFG, "configuration misses IDi");
- return FAILED;
+ if (!idi || idi->get_type(idi) == ID_ANY)
+ { /* ID_ANY is invalid as IDi, use local IP address instead */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDi configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ idi = identification_create_from_sockaddr(me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, idi);
}
this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
@@ -669,8 +674,7 @@ METHOD(task_t, build_r, status_t,
if (this->authentication_failed || this->peer_cfg == NULL)
{
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
+ goto peer_auth_failed;
}
if (this->my_auth == NULL && this->do_another_auth)
@@ -688,11 +692,14 @@ METHOD(task_t, build_r, status_t,
if (id->get_type(id) == ID_ANY)
{ /* no IDr received, apply configured ID */
if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
- {
- DBG1(DBG_CFG, "IDr not configured and negotiation failed");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
+ { /* no ID configured, use local IP address */
+ host_t *me;
+
+ DBG1(DBG_CFG, "no IDr configured, fall back on IP address");
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ id_cfg = identification_create_from_sockaddr(
+ me->get_sockaddr(me));
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id_cfg);
}
this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
id = id_cfg;
@@ -702,9 +709,7 @@ METHOD(task_t, build_r, status_t,
if (id_cfg && !id->matches(id, id_cfg))
{
DBG1(DBG_CFG, "received IDr %Y, but require %Y", id, id_cfg);
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
+ goto peer_auth_failed;
}
}
@@ -726,9 +731,7 @@ METHOD(task_t, build_r, status_t,
{
DBG1(DBG_IKE, "configured EAP-only authentication, but peer "
"does not support it");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
+ goto peer_auth_failed;
}
}
else
@@ -741,9 +744,7 @@ METHOD(task_t, build_r, status_t,
this->reserved);
if (!this->my_auth)
{
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
+ goto peer_auth_failed;
}
}
}
@@ -759,12 +760,11 @@ METHOD(task_t, build_r, status_t,
case NEED_MORE:
break;
default:
- if (!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+ if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
{ /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
+ goto peer_auth_failed_no_notify;
}
- return FAILED;
+ goto peer_auth_failed;
}
}
if (this->my_auth)
@@ -802,7 +802,7 @@ METHOD(task_t, build_r, status_t,
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
this->ike_sa, FALSE))
{
- DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
+ DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
chunk_empty);
return FAILED;
@@ -810,9 +810,7 @@ METHOD(task_t, build_r, status_t,
if (!charon->bus->authorize(charon->bus, TRUE))
{
DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
- chunk_empty);
- return FAILED;
+ goto peer_auth_failed;
}
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
this->ike_sa->get_name(this->ike_sa),
@@ -826,6 +824,13 @@ METHOD(task_t, build_r, status_t,
return SUCCESS;
}
return NEED_MORE;
+
+peer_auth_failed:
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+peer_auth_failed_no_notify:
+ charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
+ return FAILED;
}
METHOD(task_t, process_i, status_t,
@@ -908,7 +913,7 @@ METHOD(task_t, process_i, status_t,
if (!id_payload)
{
DBG1(DBG_IKE, "IDr payload missing");
- return FAILED;
+ goto peer_auth_failed;
}
id = id_payload->get_identification(id_payload);
get_reserved_id_bytes(this, id_payload);
@@ -926,7 +931,7 @@ METHOD(task_t, process_i, status_t,
this->reserved);
if (!this->other_auth)
{
- return FAILED;
+ goto peer_auth_failed;
}
}
else
@@ -944,7 +949,7 @@ METHOD(task_t, process_i, status_t,
case NEED_MORE:
return NEED_MORE;
default:
- return FAILED;
+ goto peer_auth_failed;
}
this->other_auth->destroy(this->other_auth);
this->other_auth = NULL;
@@ -953,7 +958,7 @@ METHOD(task_t, process_i, status_t,
if (!charon->bus->authorize(charon->bus, FALSE))
{
DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling");
- return FAILED;
+ goto peer_auth_failed;
}
/* store authentication information, reset authenticator */
@@ -986,7 +991,7 @@ METHOD(task_t, process_i, status_t,
if (!this->my_auth || !this->my_auth->is_mutual(this->my_auth))
{
DBG1(DBG_IKE, "do not allow non-mutual EAP-only authentication");
- return FAILED;
+ goto peer_auth_failed;
}
DBG1(DBG_IKE, "allow mutual EAP-only authentication");
}
@@ -999,12 +1004,13 @@ METHOD(task_t, process_i, status_t,
{
if (!update_cfg_candidates(this, TRUE))
{
- return FAILED;
+ goto peer_auth_failed;
}
if (!charon->bus->authorize(charon->bus, TRUE))
{
- DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
- return FAILED;
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, "
+ "cancelling");
+ goto peer_auth_failed;
}
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
this->ike_sa->get_name(this->ike_sa),
@@ -1018,6 +1024,10 @@ METHOD(task_t, process_i, status_t,
return SUCCESS;
}
return NEED_MORE;
+
+peer_auth_failed:
+ charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
+ return FAILED;
}
METHOD(task_t, get_type, task_type_t,
diff --git a/src/libcharon/sa/tasks/ike_auth.h b/src/libcharon/sa/tasks/ike_auth.h
index bba46d961..132907941 100644
--- a/src/libcharon/sa/tasks/ike_auth.h
+++ b/src/libcharon/sa/tasks/ike_auth.h
@@ -49,7 +49,7 @@ struct ike_auth_t {
* Create a new task of type IKE_AUTHENTICATE.
*
* @param ike_sa IKE_SA this task works for
- * @param initiator TRUE if thask is the initator of an exchange
+ * @param initiator TRUE if task is the initiator of an exchange
* @return ike_auth task to handle by the task_manager
*/
ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_auth_lifetime.c b/src/libcharon/sa/tasks/ike_auth_lifetime.c
index 75ff35168..a57cfd075 100644
--- a/src/libcharon/sa/tasks/ike_auth_lifetime.c
+++ b/src/libcharon/sa/tasks/ike_auth_lifetime.c
@@ -75,10 +75,8 @@ static void process_payloads(private_ike_auth_lifetime_t *this, message_t *messa
}
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_auth_lifetime_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_auth_lifetime_t *this, message_t *message)
{
if (message->get_exchange_type(message) == INFORMATIONAL)
{
@@ -88,10 +86,8 @@ static status_t build_i(private_ike_auth_lifetime_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_auth_lifetime_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_auth_lifetime_t *this, message_t *message)
{
if (message->get_exchange_type(message) == INFORMATIONAL)
{
@@ -101,10 +97,8 @@ static status_t process_r(private_ike_auth_lifetime_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_auth_lifetime_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_auth_lifetime_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_AUTH &&
this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
@@ -115,10 +109,8 @@ static status_t build_r(private_ike_auth_lifetime_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_auth_lifetime_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_auth_lifetime_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_AUTH &&
this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
@@ -129,26 +121,20 @@ static status_t process_i(private_ike_auth_lifetime_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_auth_lifetime_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_auth_lifetime_t *this)
{
return IKE_AUTH_LIFETIME;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_auth_lifetime_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_auth_lifetime_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_auth_lifetime_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_auth_lifetime_t *this)
{
free(this);
}
@@ -158,25 +144,30 @@ static void destroy(private_ike_auth_lifetime_t *this)
*/
ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_auth_lifetime_t *this = malloc_thing(private_ike_auth_lifetime_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_auth_lifetime_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->ike_sa = ike_sa;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c
index cc810a49a..94af50eae 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/tasks/ike_cert_post.c
@@ -87,6 +87,7 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
if (enumerator->enumerate(enumerator, &url))
{
payload = cert_payload_create_from_hash_and_url(hash, url);
+ DBG1(DBG_IKE, "sending hash-and-url \"%s\"", url);
}
else
{
@@ -167,28 +168,22 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
}
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_cert_post_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_cert_post_t *this, message_t *message)
{
build_certs(this, message);
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_cert_post_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_cert_post_t *this, message_t *message)
{
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_cert_post_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_cert_post_t *this, message_t *message)
{
build_certs(this, message);
@@ -199,10 +194,8 @@ static status_t build_r(private_ike_cert_post_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_cert_post_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_cert_post_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
{ /* stay alive, we might have additional rounds with CERTS */
@@ -211,26 +204,20 @@ static status_t process_i(private_ike_cert_post_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_cert_post_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_cert_post_t *this)
{
return IKE_CERT_POST;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_cert_post_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_cert_post_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_cert_post_t *this)
{
free(this);
}
@@ -240,26 +227,31 @@ static void destroy(private_ike_cert_post_t *this)
*/
ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_cert_post_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->ike_sa = ike_sa;
- this->initiator = initiator;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_cert_post.h b/src/libcharon/sa/tasks/ike_cert_post.h
index a21f45927..b3881a01a 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.h
+++ b/src/libcharon/sa/tasks/ike_cert_post.h
@@ -45,7 +45,7 @@ struct ike_cert_post_t {
* of the certificate request.
*
* @param ike_sa IKE_SA this task works for
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
* @return ike_cert_post task to handle by the task_manager
*/
ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
index a59b8dcce..b33aebe46 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -51,7 +51,7 @@ struct private_ike_cert_pre_t {
bool do_http_lookup;
/**
- * wheter this is the final authentication round
+ * whether this is the final authentication round
*/
bool final;
};
@@ -424,10 +424,8 @@ static bool final_auth(message_t *message)
return TRUE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_cert_pre_t *this, message_t *message)
{
if (message->get_message_id(message) == 1)
{ /* initiator sends CERTREQs in first IKE_AUTH */
@@ -436,10 +434,8 @@ static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_cert_pre_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_cert_pre_t *this, message_t *message)
{
if (message->get_exchange_type(message) != IKE_SA_INIT)
{ /* handle certreqs/certs in any IKE_AUTH, just in case */
@@ -450,10 +446,8 @@ static status_t process_r(private_ike_cert_pre_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_cert_pre_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_cert_pre_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
@@ -466,10 +460,8 @@ static status_t build_r(private_ike_cert_pre_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_cert_pre_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_cert_pre_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
@@ -484,26 +476,20 @@ static status_t process_i(private_ike_cert_pre_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_cert_pre_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_cert_pre_t *this)
{
return IKE_CERT_PRE;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_cert_pre_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_cert_pre_t *this)
{
free(this);
}
@@ -513,27 +499,30 @@ static void destroy(private_ike_cert_pre_t *this)
*/
ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_cert_pre_t *this = malloc_thing(private_ike_cert_pre_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_cert_pre_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->do_http_lookup = FALSE;
- this->final = FALSE;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.h b/src/libcharon/sa/tasks/ike_cert_pre.h
index 1541b80e5..4b2d0d470 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.h
+++ b/src/libcharon/sa/tasks/ike_cert_pre.h
@@ -45,7 +45,7 @@ struct ike_cert_pre_t {
* of the certificate request.
*
* @param ike_sa IKE_SA this task works for
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
* @return ike_cert_pre task to handle by the task_manager
*/
ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c
index a61663c48..4ef9c56a5 100644
--- a/src/libcharon/sa/tasks/ike_config.c
+++ b/src/libcharon/sa/tasks/ike_config.c
@@ -174,6 +174,11 @@ static void process_attribute(private_ike_config_t *this,
}
break;
}
+ case INTERNAL_IP4_SERVER:
+ case INTERNAL_IP6_SERVER:
+ /* assume it's a Windows client if we see proprietary attributes */
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MS_WINDOWS);
+ /* fall */
default:
{
if (this->initiator)
@@ -225,10 +230,8 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_config_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_config_t *this, message_t *message)
{
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
@@ -287,10 +290,8 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_config_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_config_t *this, message_t *message)
{
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
@@ -299,10 +300,8 @@ static status_t process_r(private_ike_config_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_config_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_config_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
@@ -366,10 +365,8 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_config_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_config_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
@@ -385,18 +382,14 @@ static status_t process_i(private_ike_config_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_config_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_config_t *this)
{
return IKE_CONFIG;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_config_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->virtual_ip);
@@ -406,10 +399,8 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
this->requested = linked_list_create();
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_config_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_config_t *this)
{
DESTROY_IF(this->virtual_ip);
this->requested->destroy_function(this->requested, free);
@@ -421,26 +412,30 @@ static void destroy(private_ike_config_t *this)
*/
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_config_t *this = malloc_thing(private_ike_config_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
-
- this->initiator = initiator;
- this->ike_sa = ike_sa;
- this->virtual_ip = NULL;
- this->requested = linked_list_create();
+ private_ike_config_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .initiator = initiator,
+ .ike_sa = ike_sa,
+ .requested = linked_list_create(),
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
return &this->public;
diff --git a/src/libcharon/sa/tasks/ike_delete.c b/src/libcharon/sa/tasks/ike_delete.c
index 130948836..d79674fe4 100644
--- a/src/libcharon/sa/tasks/ike_delete.c
+++ b/src/libcharon/sa/tasks/ike_delete.c
@@ -52,10 +52,8 @@ struct private_ike_delete_t {
bool simultaneous;
};
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_ike_delete_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_delete_t *this, message_t *message)
{
delete_payload_t *delete_payload;
@@ -83,10 +81,8 @@ static status_t build_i(private_ike_delete_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_delete_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_delete_t *this, message_t *message)
{
DBG0(DBG_IKE, "IKE_SA deleted");
if (!this->rekeyed)
@@ -97,10 +93,8 @@ static status_t process_i(private_ike_delete_t *this, message_t *message)
return DESTROY_ME;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_delete_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_delete_t *this, message_t *message)
{
/* we don't even scan the payloads, as the message wouldn't have
* come so far without being correct */
@@ -134,16 +128,14 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_delete_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_delete_t *this, message_t *message)
{
DBG0(DBG_IKE, "IKE_SA deleted");
if (this->simultaneous)
{
- /* wait for peer's response for our delete request, but set a timeout */
+ /* wait for peer's response for our delete request */
return SUCCESS;
}
if (!this->rekeyed)
@@ -154,27 +146,21 @@ static status_t build_r(private_ike_delete_t *this, message_t *message)
return DESTROY_ME;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_delete_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_delete_t *this)
{
return IKE_DELETE;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_delete_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_delete_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
this->simultaneous = FALSE;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_delete_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_delete_t *this)
{
free(this);
}
@@ -184,27 +170,30 @@ static void destroy(private_ike_delete_t *this)
*/
ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_delete_t *this = malloc_thing(private_ike_delete_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_delete_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->rekeyed = FALSE;
- this->simultaneous = FALSE;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_dpd.c b/src/libcharon/sa/tasks/ike_dpd.c
index 4c6ba7662..106eff87c 100644
--- a/src/libcharon/sa/tasks/ike_dpd.c
+++ b/src/libcharon/sa/tasks/ike_dpd.c
@@ -31,44 +31,33 @@ struct private_ike_dpd_t {
ike_dpd_t public;
};
-/**
- * Implementation of task_t.build for initiator
- * Implementation of task_t.process for responder
- */
-static status_t return_need_more(private_ike_dpd_t *this, message_t *message)
+METHOD(task_t, return_need_more, status_t,
+ private_ike_dpd_t *this, message_t *message)
{
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for initiator
- * Implementation of task_t.build for responder
- */
-static status_t return_success(private_ike_dpd_t *this, message_t *message)
+METHOD(task_t, return_success, status_t,
+ private_ike_dpd_t *this, message_t *message)
{
return SUCCESS;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_dpd_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_dpd_t *this)
{
return IKE_DPD;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_dpd_t *this, ike_sa_t *ike_sa)
+
+METHOD(task_t, migrate, void,
+ private_ike_dpd_t *this, ike_sa_t *ike_sa)
{
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_dpd_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_dpd_t *this)
{
free(this);
}
@@ -78,21 +67,27 @@ static void destroy(private_ike_dpd_t *this)
*/
ike_dpd_t *ike_dpd_create(bool initiator)
{
- private_ike_dpd_t *this = malloc_thing(private_ike_dpd_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_dpd_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))return_need_more;
- this->public.task.process = (status_t(*)(task_t*,message_t*))return_success;
+ this->public.task.build = _return_need_more;
+ this->public.task.process = _return_success;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))return_success;
- this->public.task.process = (status_t(*)(task_t*,message_t*))return_need_more;
+ this->public.task.build = _return_success;
+ this->public.task.process = _return_need_more;
}
return &this->public;
diff --git a/src/libcharon/sa/tasks/ike_dpd.h b/src/libcharon/sa/tasks/ike_dpd.h
index 36388d15b..a9f68c31c 100644
--- a/src/libcharon/sa/tasks/ike_dpd.h
+++ b/src/libcharon/sa/tasks/ike_dpd.h
@@ -43,7 +43,7 @@ struct ike_dpd_t {
/**
* Create a new ike_dpd task.
*
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
* @return ike_dpd task to handle by the task_manager
*/
ike_dpd_t *ike_dpd_create(bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c
index dd4a5f5c0..dd8a4b086 100644
--- a/src/libcharon/sa/tasks/ike_init.c
+++ b/src/libcharon/sa/tasks/ike_init.c
@@ -112,7 +112,7 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
linked_list_t *proposal_list;
ike_sa_id_t *id;
proposal_t *proposal;
- iterator_t *iterator;
+ enumerator_t *enumerator;
id = this->ike_sa->get_id(this->ike_sa);
@@ -124,12 +124,12 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
if (this->old_sa)
{
/* include SPI of new IKE_SA when we are rekeying */
- iterator = proposal_list->create_iterator(proposal_list, TRUE);
- while (iterator->iterate(iterator, (void**)&proposal))
+ enumerator = proposal_list->create_enumerator(proposal_list);
+ while (enumerator->enumerate(enumerator, (void**)&proposal))
{
proposal->set_spi(proposal, id->get_initiator_spi(id));
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
sa_payload = sa_payload_create_from_proposal_list(proposal_list);
@@ -221,10 +221,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_init_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_init_t *this, message_t *message)
{
rng_t *rng;
@@ -287,10 +285,8 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_init_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_init_t *this, message_t *message)
{
rng_t *rng;
@@ -361,10 +357,8 @@ static bool derive_keys(private_ike_init_t *this,
return TRUE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_init_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_init_t *this, message_t *message)
{
/* check if we have everything we need */
if (this->proposal == NULL ||
@@ -409,10 +403,8 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_init_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_init_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
@@ -510,34 +502,14 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_init_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_init_t *this)
{
return IKE_INIT;
}
-/**
- * Implementation of task_t.get_type
- */
-static chunk_t get_lower_nonce(private_ike_init_t *this)
-{
- if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
- min(this->my_nonce.len, this->other_nonce.len)) < 0)
- {
- return this->my_nonce;
- }
- else
- {
- return this->other_nonce;
- }
-}
-
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_init_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->proposal);
chunk_free(&this->other_nonce);
@@ -545,14 +517,15 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
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);
+ if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group)
+ { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */
+ this->dh->destroy(this->dh);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ }
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_init_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_init_t *this)
{
DESTROY_IF(this->dh);
DESTROY_IF(this->proposal);
@@ -562,40 +535,53 @@ static void destroy(private_ike_init_t *this)
free(this);
}
+METHOD(ike_init_t, get_lower_nonce, chunk_t,
+ private_ike_init_t *this)
+{
+ if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
+ min(this->my_nonce.len, this->other_nonce.len)) < 0)
+ {
+ return this->my_nonce;
+ }
+ else
+ {
+ return this->other_nonce;
+ }
+}
+
/*
* Described in header.
*/
ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
{
- private_ike_init_t *this = malloc_thing(private_ike_init_t);
+ private_ike_init_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .get_lower_nonce = _get_lower_nonce,
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .dh_group = MODP_NONE,
+ .keymat = ike_sa->get_keymat(ike_sa),
+ .old_sa = old_sa,
+ );
- this->public.get_lower_nonce = (chunk_t(*)(ike_init_t*))get_lower_nonce;
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->dh_group = MODP_NONE;
- this->dh = NULL;
- this->keymat = ike_sa->get_keymat(ike_sa);
- this->my_nonce = chunk_empty;
- this->other_nonce = chunk_empty;
- this->cookie = chunk_empty;
- this->proposal = NULL;
- this->config = NULL;
- this->old_sa = old_sa;
- this->retry = 0;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_init.h b/src/libcharon/sa/tasks/ike_init.h
index 7bd784cff..4b7f60416 100644
--- a/src/libcharon/sa/tasks/ike_init.h
+++ b/src/libcharon/sa/tasks/ike_init.h
@@ -51,7 +51,7 @@ struct ike_init_t {
* Create a new IKE_INIT task.
*
* @param ike_sa IKE_SA this task works for (new one when rekeying)
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
* @param old_sa old IKE_SA when we are rekeying
* @return ike_init task to handle by the task_manager
*/
diff --git a/src/libcharon/sa/tasks/ike_me.c b/src/libcharon/sa/tasks/ike_me.c
index 1de6ae8fc..8f90efcc3 100644
--- a/src/libcharon/sa/tasks/ike_me.c
+++ b/src/libcharon/sa/tasks/ike_me.c
@@ -111,15 +111,15 @@ struct private_ike_me_t {
*/
static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
endpoint_notify_t *endpoint;
- iterator = endpoints->create_iterator(endpoints, TRUE);
- while (iterator->iterate(iterator, (void**)&endpoint))
+ enumerator = endpoints->create_enumerator(endpoints);
+ while (enumerator->enumerate(enumerator, (void**)&endpoint))
{
message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -242,10 +242,8 @@ static void process_payloads(private_ike_me_t *this, message_t *message)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_ike_me_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -321,10 +319,8 @@ static status_t build_i(private_ike_me_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_me_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -381,10 +377,8 @@ static status_t process_r(private_ike_me_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_me_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -440,10 +434,8 @@ static status_t build_r(private_ike_me_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_me_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -520,9 +512,10 @@ static status_t process_i(private_ike_me_t *this, message_t *message)
}
/**
- * Implementation of task_t.build for initiator (mediation server)
+ * For mediation server
*/
-static status_t build_i_ms(private_ike_me_t *this, message_t *message)
+METHOD(task_t, build_i_ms, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -559,9 +552,10 @@ static status_t build_i_ms(private_ike_me_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for responder (mediation server)
+ * For mediation server
*/
-static status_t process_r_ms(private_ike_me_t *this, message_t *message)
+METHOD(task_t, process_r_ms, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -632,9 +626,10 @@ static status_t process_r_ms(private_ike_me_t *this, message_t *message)
}
/**
- * Implementation of task_t.build for responder (mediation server)
+ * For mediation server
*/
-static status_t build_r_ms(private_ike_me_t *this, message_t *message)
+METHOD(task_t, build_r_ms, status_t,
+ private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -703,9 +698,10 @@ static status_t build_r_ms(private_ike_me_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator (mediation server)
+ * For mediation server
*/
-static status_t process_i_ms(private_ike_me_t *this, message_t *message)
+METHOD(task_t, process_i_ms, status_t,
+ private_ike_me_t *this, message_t *message)
{
/* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
* here if the responding peer is not able to proceed. in this case we shall
@@ -714,40 +710,30 @@ static status_t process_i_ms(private_ike_me_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of ike_me.connect
- */
-static void me_connect(private_ike_me_t *this, identification_t *peer_id)
+METHOD(ike_me_t, me_connect, void,
+ private_ike_me_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
}
-/**
- * Implementation of ike_me.respond
- */
-static void me_respond(private_ike_me_t *this, identification_t *peer_id,
- chunk_t connect_id)
+METHOD(ike_me_t, me_respond, void,
+ private_ike_me_t *this, identification_t *peer_id, chunk_t connect_id)
{
this->peer_id = peer_id->clone(peer_id);
this->connect_id = chunk_clone(connect_id);
this->response = TRUE;
}
-/**
- * Implementation of ike_me.callback
- */
-static void me_callback(private_ike_me_t *this, identification_t *peer_id)
+METHOD(ike_me_t, me_callback, void,
+ private_ike_me_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
this->callback = TRUE;
}
-/**
- * Implementation of ike_me.relay
- */
-static void relay(private_ike_me_t *this, identification_t *requester,
- chunk_t connect_id, chunk_t connect_key,
- linked_list_t *endpoints, bool response)
+METHOD(ike_me_t, relay, void,
+ private_ike_me_t *this, identification_t *requester, chunk_t connect_id,
+ chunk_t connect_key, linked_list_t *endpoints, bool response)
{
this->peer_id = requester->clone(requester);
this->connect_id = chunk_clone(connect_id);
@@ -761,26 +747,20 @@ static void relay(private_ike_me_t *this, identification_t *requester,
this->response = response;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_me_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_me_t *this)
{
return IKE_ME;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_me_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_me_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_me_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_me_t *this)
{
DESTROY_IF(this->peer_id);
@@ -801,23 +781,37 @@ static void destroy(private_ike_me_t *this)
*/
ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_me_t *this = malloc_thing(private_ike_me_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_me_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .connect = _me_connect,
+ .respond = _me_respond,
+ .callback = _me_callback,
+ .relay = _relay,
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .local_endpoints = linked_list_create(),
+ .remote_endpoints = linked_list_create(),
+ );
if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
{
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
}
else
@@ -825,36 +819,15 @@ ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
/* mediation server */
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms;
+ this->public.task.build = _build_i_ms;
+ this->public.task.process = _process_i_ms;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms;
+ this->public.task.build = _build_r_ms;
+ this->public.task.process = _process_r_ms;
}
}
- this->public.connect = (void(*)(ike_me_t*,identification_t*))me_connect;
- this->public.respond = (void(*)(ike_me_t*,identification_t*,chunk_t))me_respond;
- this->public.callback = (void(*)(ike_me_t*,identification_t*))me_callback;
- this->public.relay = (void(*)(ike_me_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
-
- this->ike_sa = ike_sa;
- this->initiator = initiator;
-
- this->peer_id = NULL;
- this->connect_id = chunk_empty;
- this->connect_key = chunk_empty;
- this->local_endpoints = linked_list_create();
- this->remote_endpoints = linked_list_create();
- this->mediation = FALSE;
- this->response = FALSE;
- this->callback = FALSE;
- this->failed = FALSE;
- this->invalid_syntax = FALSE;
-
- this->mediated_cfg = NULL;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_mobike.c b/src/libcharon/sa/tasks/ike_mobike.c
index 5b12eaaac..fb1100028 100644
--- a/src/libcharon/sa/tasks/ike_mobike.c
+++ b/src/libcharon/sa/tasks/ike_mobike.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010-2012 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -79,24 +80,6 @@ struct private_ike_mobike_t {
};
/**
- * flush the IKE_SAs list of additional addresses
- */
-static void flush_additional_addresses(private_ike_mobike_t *this)
-{
- iterator_t *iterator;
- host_t *host;
-
- iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
- while (iterator->iterate(iterator, (void**)&host))
- {
- iterator->remove(iterator);
- host->destroy(host);
- }
- iterator->destroy(iterator);
-}
-
-
-/**
* read notifys from message and evaluate them
*/
static void process_payloads(private_ike_mobike_t *this, message_t *message)
@@ -152,13 +135,17 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
{
if (first)
{ /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
- flush_additional_addresses(this);
+ this->ike_sa->clear_peer_addresses(this->ike_sa);
first = FALSE;
+ /* add the peer's current address to the list */
+ host = message->get_source(message);
+ this->ike_sa->add_peer_address(this->ike_sa,
+ host->clone(host));
}
data = notify->get_notification_data(notify);
host = host_create_from_chunk(family, data, 0);
DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
- this->ike_sa->add_additional_address(this->ike_sa, host);
+ this->ike_sa->add_peer_address(this->ike_sa, host);
this->addresses_updated = TRUE;
break;
}
@@ -169,7 +156,10 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
}
case NO_ADDITIONAL_ADDRESSES:
{
- flush_additional_addresses(this);
+ this->ike_sa->clear_peer_addresses(this->ike_sa);
+ /* add the peer's current address to the list */
+ host = message->get_source(message);
+ this->ike_sa->add_peer_address(this->ike_sa, host->clone(host));
this->addresses_updated = TRUE;
break;
}
@@ -256,11 +246,11 @@ static void build_cookie(private_ike_mobike_t *this, message_t *message)
*/
static void update_children(private_ike_mobike_t *this)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
- iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa,
this->ike_sa->get_my_host(this->ike_sa),
@@ -273,7 +263,7 @@ static void update_children(private_ike_mobike_t *this)
child_sa->get_spi(child_sa, TRUE));
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -296,7 +286,7 @@ METHOD(ike_mobike_t, transmit, void,
private_ike_mobike_t *this, packet_t *packet)
{
host_t *me, *other, *me_old, *other_old;
- iterator_t *iterator;
+ enumerator_t *enumerator;
ike_cfg_t *ike_cfg;
packet_t *copy;
@@ -309,19 +299,8 @@ METHOD(ike_mobike_t, transmit, void,
other_old = this->ike_sa->get_other_host(this->ike_sa);
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
- me = hydra->kernel_interface->get_source_addr(
- hydra->kernel_interface, other_old, NULL);
- if (me)
- {
- apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg));
- DBG1(DBG_IKE, "checking original path %#H - %#H", me, other_old);
- copy = packet->clone(packet);
- copy->set_source(copy, me);
- charon->sender->send(charon->sender, copy);
- }
-
- iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
- while (iterator->iterate(iterator, (void**)&other))
+ enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, (void**)&other))
{
me = hydra->kernel_interface->get_source_addr(
hydra->kernel_interface, other, NULL);
@@ -343,7 +322,7 @@ METHOD(ike_mobike_t, transmit, void,
charon->sender->send(charon->sender, copy);
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
METHOD(task_t, build_i, status_t,
diff --git a/src/libcharon/sa/tasks/ike_natd.c b/src/libcharon/sa/tasks/ike_natd.c
index 7839b52eb..f06a518fa 100644
--- a/src/libcharon/sa/tasks/ike_natd.c
+++ b/src/libcharon/sa/tasks/ike_natd.c
@@ -256,10 +256,8 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
}
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_natd_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_natd_t *this, message_t *message)
{
process_payloads(this, message);
@@ -281,10 +279,8 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_natd_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_natd_t *this, message_t *message)
{
notify_payload_t *notify;
enumerator_t *enumerator;
@@ -345,15 +341,13 @@ static status_t build_i(private_ike_natd_t *this, message_t *message)
return NEED_MORE;
}
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_natd_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+ private_ike_natd_t *this, message_t *message)
{
notify_payload_t *notify;
host_t *me, *other;
- /* only add notifies on successfull responses. */
+ /* only add notifies on successful responses. */
if (message->get_exchange_type(message) == IKE_SA_INIT &&
message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
{
@@ -380,28 +374,22 @@ static status_t build_r(private_ike_natd_t *this, message_t *message)
return SUCCESS;
}
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_natd_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+ private_ike_natd_t *this, message_t *message)
{
process_payloads(this, message);
return NEED_MORE;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_natd_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_natd_t *this)
{
return IKE_NATD;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_natd_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
this->src_seen = FALSE;
@@ -411,21 +399,17 @@ static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa)
this->mapping_changed = FALSE;
}
-/**
- * Implementation of ike_natd_t.has_mapping_changed
- */
-static bool has_mapping_changed(private_ike_natd_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_natd_t *this)
{
- return this->mapping_changed;
+ DESTROY_IF(this->hasher);
+ free(this);
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_natd_t *this)
+METHOD(ike_natd_t, has_mapping_changed, bool,
+ private_ike_natd_t *this)
{
- DESTROY_IF(this->hasher);
- free(this);
+ return this->mapping_changed;
}
/*
@@ -433,33 +417,32 @@ static void destroy(private_ike_natd_t *this)
*/
ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_natd_t *this = malloc_thing(private_ike_natd_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
+ private_ike_natd_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ .has_mapping_changed = _has_mapping_changed,
+ },
+ .ike_sa = ike_sa,
+ .initiator = initiator,
+ .hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1),
+ );
if (initiator)
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ this->public.task.build = _build_i;
+ this->public.task.process = _process_i;
}
else
{
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ this->public.task.build = _build_r;
+ this->public.task.process = _process_r;
}
- this->public.has_mapping_changed = (bool(*)(ike_natd_t*))has_mapping_changed;
-
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- this->src_seen = FALSE;
- this->dst_seen = FALSE;
- this->src_matched = FALSE;
- this->dst_matched = FALSE;
- this->mapping_changed = FALSE;
-
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_natd.h b/src/libcharon/sa/tasks/ike_natd.h
index 97b652ead..68114af42 100644
--- a/src/libcharon/sa/tasks/ike_natd.h
+++ b/src/libcharon/sa/tasks/ike_natd.h
@@ -51,7 +51,7 @@ struct ike_natd_t {
* Create a new ike_natd task.
*
* @param ike_sa IKE_SA this task works for
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
* @return ike_natd task to handle by the task_manager
*/
ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/ike_reauth.c b/src/libcharon/sa/tasks/ike_reauth.c
index ac89c358b..48002d81c 100644
--- a/src/libcharon/sa/tasks/ike_reauth.c
+++ b/src/libcharon/sa/tasks/ike_reauth.c
@@ -42,134 +42,44 @@ struct private_ike_reauth_t {
ike_delete_t *ike_delete;
};
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_ike_reauth_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+ private_ike_reauth_t *this, message_t *message)
{
return this->ike_delete->task.build(&this->ike_delete->task, message);
}
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_reauth_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+ private_ike_reauth_t *this, message_t *message)
{
- ike_sa_t *new;
- host_t *host;
- iterator_t *iterator;
- child_sa_t *child_sa;
- peer_cfg_t *peer_cfg;
-
/* process delete response first */
this->ike_delete->task.process(&this->ike_delete->task, message);
- peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-
- /* reauthenticate only if we have children */
- iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
- if (iterator->get_count(iterator) == 0
-#ifdef ME
- /* we allow peers to reauth mediation connections (without children) */
- && !peer_cfg->is_mediation(peer_cfg)
-#endif /* ME */
- )
+ /* reestablish the IKE_SA with all children */
+ if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS)
{
- DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
- iterator->destroy(iterator);
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
- new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
-
- new->set_peer_cfg(new, peer_cfg);
- host = this->ike_sa->get_other_host(this->ike_sa);
- new->set_other_host(new, host->clone(host));
- host = this->ike_sa->get_my_host(this->ike_sa);
- new->set_my_host(new, host->clone(host));
- /* if we already have a virtual IP, we reuse it */
- host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (host)
- {
- new->set_virtual_ip(new, TRUE, host);
- }
-
-#ifdef ME
- /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
- if (peer_cfg->is_mediation(peer_cfg))
- {
- if (new->initiate(new, NULL, 0, NULL, NULL) == DESTROY_ME)
- {
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, new);
- /* set threads active IKE_SA after checkin */
- charon->bus->set_sa(charon->bus, this->ike_sa);
- DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
- return FAILED;
- }
- }
-#endif /* ME */
-
- while (iterator->iterate(iterator, (void**)&child_sa))
- {
- switch (child_sa->get_state(child_sa))
- {
- case CHILD_ROUTED:
- {
- /* move routed child directly */
- iterator->remove(iterator);
- new->add_child_sa(new, child_sa);
- break;
- }
- default:
- {
- /* initiate/queue all child SAs */
- child_cfg_t *child_cfg = child_sa->get_config(child_sa);
- child_cfg->get_ref(child_cfg);
- if (new->initiate(new, child_cfg, 0, NULL, NULL) == DESTROY_ME)
- {
- iterator->destroy(iterator);
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, new);
- /* set threads active IKE_SA after checkin */
- charon->bus->set_sa(charon->bus, this->ike_sa);
- DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
- return FAILED;
- }
- break;
- }
- }
- }
- iterator->destroy(iterator);
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
- /* set threads active IKE_SA after checkin */
- charon->bus->set_sa(charon->bus, this->ike_sa);
-
- /* we always return failed to delete the obsolete IKE_SA */
- return FAILED;
+ /* we always destroy the obsolete IKE_SA */
+ return DESTROY_ME;
}
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_reauth_t *this)
+METHOD(task_t, get_type, task_type_t,
+ private_ike_reauth_t *this)
{
return IKE_REAUTH;
}
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_reauth_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, migrate, void,
+ private_ike_reauth_t *this, ike_sa_t *ike_sa)
{
this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa);
this->ike_sa = ike_sa;
}
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_reauth_t *this)
+METHOD(task_t, destroy, void,
+ private_ike_reauth_t *this)
{
this->ike_delete->task.destroy(&this->ike_delete->task);
free(this);
@@ -180,16 +90,21 @@ static void destroy(private_ike_reauth_t *this)
*/
ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa)
{
- private_ike_reauth_t *this = malloc_thing(private_ike_reauth_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
-
- this->ike_sa = ike_sa;
- this->ike_delete = ike_delete_create(ike_sa, TRUE);
+ private_ike_reauth_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .migrate = _migrate,
+ .build = _build_i,
+ .process = _process_i,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ .ike_delete = ike_delete_create(ike_sa, TRUE),
+ );
return &this->public;
}
diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/tasks/ike_rekey.c
index c055dabc1..826d6e192 100644
--- a/src/libcharon/sa/tasks/ike_rekey.c
+++ b/src/libcharon/sa/tasks/ike_rekey.c
@@ -147,8 +147,8 @@ METHOD(task_t, build_i, status_t,
METHOD(task_t, process_r, status_t,
private_ike_rekey_t *this, message_t *message)
{
+ enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
- iterator_t *iterator;
child_sa_t *child_sa;
if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
@@ -157,8 +157,8 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
- iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
- while (iterator->iterate(iterator, (void**)&child_sa))
+ enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
+ while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
switch (child_sa->get_state(child_sa))
{
@@ -167,13 +167,13 @@ METHOD(task_t, process_r, status_t,
case CHILD_DELETING:
/* we do not allow rekeying while we have children in-progress */
DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open");
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return NEED_MORE;
default:
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
FALSE);
diff --git a/src/libcharon/sa/tasks/ike_vendor.h b/src/libcharon/sa/tasks/ike_vendor.h
index dcdd37424..6c353c447 100644
--- a/src/libcharon/sa/tasks/ike_vendor.h
+++ b/src/libcharon/sa/tasks/ike_vendor.h
@@ -42,7 +42,7 @@ struct ike_vendor_t {
* Create a ike_vendor instance.
*
* @param ike_sa IKE_SA this task works for
- * @param initiator TRUE if thask is the original initator
+ * @param initiator TRUE if task is the original initiator
*/
ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator);
diff --git a/src/libcharon/sa/tasks/task.h b/src/libcharon/sa/tasks/task.h
index 4468f2ebe..d57085954 100644
--- a/src/libcharon/sa/tasks/task.h
+++ b/src/libcharon/sa/tasks/task.h
@@ -89,7 +89,7 @@ extern enum_name_t *task_type_names;
* A responder does the opposite; it calls process() first to handle an incoming
* request and secondly calls build() to build an appropriate response.
* Both methods return either SUCCESS, NEED_MORE or FAILED. A SUCCESS indicates
- * that the task completed, even when the task completed unsuccesfully. The
+ * that the task completed, even when the task completed unsuccessfully. The
* manager then removes the task from the list. A NEED_MORE is returned when
* the task needs further build()/process() calls to complete, the manager
* leaves the taks in the queue. A returned FAILED indicates a critical failure.
@@ -102,7 +102,7 @@ struct task_t {
*
* @param message message to add payloads to
* @return
- * - FAILED if a critical error occured
+ * - FAILED if a critical error occurred
* - DESTROY_ME if IKE_SA has been properly deleted
* - NEED_MORE if another call to build/process needed
* - SUCCESS if task completed
@@ -114,7 +114,7 @@ struct task_t {
*
* @param message message to read payloads from
* @return
- * - FAILED if a critical error occured
+ * - FAILED if a critical error occurred
* - DESTROY_ME if IKE_SA has been properly deleted
* - NEED_MORE if another call to build/process needed
* - SUCCESS if task completed
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index f91eff077..86d9f4c22 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -74,8 +75,10 @@ typedef struct {
peer_cfg_t *peer_cfg;
/** ref to instanciated CHILD_SA */
child_sa_t *child_sa;
+ /** TRUE if an acquire is pending */
+ bool pending;
/** pending IKE_SA connecting upon acquire */
- ike_sa_t *pending;
+ ike_sa_t *ike_sa;
} entry_t;
/**
@@ -88,11 +91,8 @@ static void destroy_entry(entry_t *entry)
free(entry);
}
-/**
- * Implementation of trap_manager_t.install
- */
-static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
- child_cfg_t *child)
+METHOD(trap_manager_t, install, u_int32_t,
+ private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child)
{
entry_t *entry;
ike_cfg_t *ike_cfg;
@@ -158,8 +158,8 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
other->destroy(other);
/* while we don't know the finally negotiated protocol (ESP|AH), we
- * could iterate all proposals for a best guest (TODO). But as we
- * support ESP only for now, we set here. */
+ * could iterate all proposals for a best guess (TODO). But as we
+ * support ESP only for now, we set it here. */
child_sa->set_protocol(child_sa, PROTO_ESP);
child_sa->set_mode(child_sa, child->get_mode(child));
status = child_sa->add_policies(child_sa, my_ts, other_ts);
@@ -173,10 +173,10 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
}
reqid = child_sa->get_reqid(child_sa);
- entry = malloc_thing(entry_t);
- entry->child_sa = child_sa;
- entry->peer_cfg = peer->get_ref(peer);
- entry->pending = NULL;
+ INIT(entry,
+ .child_sa = child_sa,
+ .peer_cfg = peer->get_ref(peer),
+ );
this->lock->write_lock(this->lock);
this->traps->insert_last(this->traps, entry);
@@ -185,10 +185,8 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
return reqid;
}
-/**
- * Implementation of trap_manager_t.uninstall
- */
-static bool uninstall(private_trap_manager_t *this, u_int32_t reqid)
+METHOD(trap_manager_t, uninstall, bool,
+ private_trap_manager_t *this, u_int32_t reqid)
{
enumerator_t *enumerator;
entry_t *entry, *found = NULL;
@@ -234,10 +232,8 @@ static bool trap_filter(rwlock_t *lock, entry_t **entry, peer_cfg_t **peer_cfg,
return TRUE;
}
-/**
- * Implementation of trap_manager_t.create_enumerator
- */
-static enumerator_t* create_enumerator(private_trap_manager_t *this)
+METHOD(trap_manager_t, create_enumerator, enumerator_t*,
+ private_trap_manager_t *this)
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->traps->create_enumerator(this->traps),
@@ -245,11 +241,9 @@ static enumerator_t* create_enumerator(private_trap_manager_t *this)
(void*)this->lock->unlock);
}
-/**
- * Implementation of trap_manager_t.acquire
- */
-static void acquire(private_trap_manager_t *this, u_int32_t reqid,
- traffic_selector_t *src, traffic_selector_t *dst)
+METHOD(trap_manager_t, acquire, void,
+ private_trap_manager_t *this, u_int32_t reqid,
+ traffic_selector_t *src, traffic_selector_t *dst)
{
enumerator_t *enumerator;
entry_t *entry, *found = NULL;
@@ -272,35 +266,46 @@ static void acquire(private_trap_manager_t *this, u_int32_t reqid,
if (!found)
{
DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d",reqid);
+ this->lock->unlock(this->lock);
+ return;
}
- else if (found->pending)
+ if (!cas_bool(&found->pending, FALSE, TRUE))
{
DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
+ this->lock->unlock(this->lock);
+ return;
}
- else
+ peer = found->peer_cfg->get_ref(found->peer_cfg);
+ child = found->child_sa->get_config(found->child_sa);
+ child = child->get_ref(child);
+ reqid = found->child_sa->get_reqid(found->child_sa);
+ /* don't hold the lock while checking out the IKE_SA */
+ this->lock->unlock(this->lock);
+
+ ike_sa = charon->ike_sa_manager->checkout_by_config(
+ charon->ike_sa_manager, peer);
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
{
- child = found->child_sa->get_config(found->child_sa);
- peer = found->peer_cfg;
- ike_sa = charon->ike_sa_manager->checkout_by_config(
- charon->ike_sa_manager, peer);
- if (ike_sa->get_peer_cfg(ike_sa) == NULL)
- {
- ike_sa->set_peer_cfg(ike_sa, peer);
- }
- child->get_ref(child);
- reqid = found->child_sa->get_reqid(found->child_sa);
- if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
- {
- found->pending = ike_sa;
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- }
- else
+ ike_sa->set_peer_cfg(ike_sa, peer);
+ }
+ if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
+ {
+ /* make sure the entry is still there */
+ this->lock->read_lock(this->lock);
+ if (this->traps->find_first(this->traps, NULL,
+ (void**)&found) == SUCCESS)
{
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, ike_sa);
+ found->ike_sa = ike_sa;
}
+ this->lock->unlock(this->lock);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- this->lock->unlock(this->lock);
+ else
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ peer->destroy(peer);
}
/**
@@ -316,7 +321,7 @@ static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
enumerator = this->traps->create_enumerator(this->traps);
while (enumerator->enumerate(enumerator, &entry))
{
- if (entry->pending != ike_sa)
+ if (entry->ike_sa != ike_sa)
{
continue;
}
@@ -325,17 +330,15 @@ static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
{
continue;
}
- entry->pending = NULL;
+ entry->ike_sa = NULL;
+ entry->pending = FALSE;
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
-/**
- * Implementation of listener_t.ike_state_change
- */
-static bool ike_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
- ike_sa_state_t state)
+METHOD(listener_t, ike_state_change, bool,
+ trap_listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state)
{
switch (state)
{
@@ -347,11 +350,9 @@ static bool ike_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
}
}
-/**
- * Implementation of listener_t.child_state_change
- */
-static bool child_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
- child_sa_t *child_sa, child_sa_state_t state)
+METHOD(listener_t, child_state_change, bool,
+ trap_listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ child_sa_state_t state)
{
switch (state)
{
@@ -364,14 +365,24 @@ static bool child_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
}
}
-/**
- * Implementation of trap_manager_t.destroy.
- */
-static void destroy(private_trap_manager_t *this)
+METHOD(trap_manager_t, flush, void,
+ private_trap_manager_t *this)
+{
+ linked_list_t *traps;
+ /* since destroying the CHILD_SA results in events which require a read
+ * lock we cannot destroy the list while holding the write lock */
+ this->lock->write_lock(this->lock);
+ traps = this->traps;
+ this->traps = linked_list_create();
+ this->lock->unlock(this->lock);
+ traps->destroy_function(traps, (void*)destroy_entry);
+}
+
+METHOD(trap_manager_t, destroy, void,
+ private_trap_manager_t *this)
{
charon->bus->remove_listener(charon->bus, &this->listener.listener);
- this->traps->invoke_function(this->traps, (void*)destroy_entry);
- this->traps->destroy(this->traps);
+ this->traps->destroy_function(this->traps, (void*)destroy_entry);
this->lock->destroy(this->lock);
free(this);
}
@@ -379,24 +390,29 @@ static void destroy(private_trap_manager_t *this)
/**
* See header
*/
-trap_manager_t *trap_manager_create()
+trap_manager_t *trap_manager_create(void)
{
- private_trap_manager_t *this = malloc_thing(private_trap_manager_t);
-
- this->public.install = (u_int(*)(trap_manager_t*, peer_cfg_t *peer, child_cfg_t *child))install;
- this->public.uninstall = (bool(*)(trap_manager_t*, u_int32_t id))uninstall;
- this->public.create_enumerator = (enumerator_t*(*)(trap_manager_t*))create_enumerator;
- this->public.acquire = (void(*)(trap_manager_t*, u_int32_t reqid, traffic_selector_t *src, traffic_selector_t *dst))acquire;
- this->public.destroy = (void(*)(trap_manager_t*))destroy;
-
- this->traps = linked_list_create();
- this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
-
- /* register listener for IKE state changes */
- this->listener.traps = this;
- memset(&this->listener.listener, 0, sizeof(listener_t));
- this->listener.listener.ike_state_change = (void*)ike_state_change;
- this->listener.listener.child_state_change = (void*)child_state_change;
+ private_trap_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .install = _install,
+ .uninstall = _uninstall,
+ .create_enumerator = _create_enumerator,
+ .acquire = _acquire,
+ .flush = _flush,
+ .destroy = _destroy,
+ },
+ .listener = {
+ .traps = this,
+ .listener = {
+ .ike_state_change = _ike_state_change,
+ .child_state_change = _child_state_change,
+ },
+ },
+ .traps = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
charon->bus->add_listener(charon->bus, &this->listener.listener);
return &this->public;
diff --git a/src/libcharon/sa/trap_manager.h b/src/libcharon/sa/trap_manager.h
index 37b42e2b0..928b2a49f 100644
--- a/src/libcharon/sa/trap_manager.h
+++ b/src/libcharon/sa/trap_manager.h
@@ -68,6 +68,11 @@ struct trap_manager_t {
traffic_selector_t *src, traffic_selector_t *dst);
/**
+ * Clear any installed trap.
+ */
+ void (*flush)(trap_manager_t *this);
+
+ /**
* Destroy a trap_manager_t.
*/
void (*destroy)(trap_manager_t *this);