summaryrefslogtreecommitdiff
path: root/src/charon/sa
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2008-10-29 20:30:44 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2008-10-29 20:30:44 +0000
commit74f0bbfc53cb5fa519e4e27ece53735ab51b397c (patch)
tree0dbab9c835be15577ff05b474b6361bb326d66ce /src/charon/sa
parent5c1fa2516bda1ccf8eb00178c0beb196c2020a94 (diff)
downloadvyos-strongswan-74f0bbfc53cb5fa519e4e27ece53735ab51b397c.tar.gz
vyos-strongswan-74f0bbfc53cb5fa519e4e27ece53735ab51b397c.zip
- New upstream release.
Diffstat (limited to 'src/charon/sa')
-rw-r--r--src/charon/sa/authenticators/authenticator.c30
-rw-r--r--src/charon/sa/authenticators/authenticator.h75
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.c10
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.h13
-rw-r--r--src/charon/sa/authenticators/eap/sim_manager.c125
-rw-r--r--src/charon/sa/authenticators/eap/sim_manager.h136
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.c183
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.h6
-rw-r--r--src/charon/sa/child_sa.c50
-rw-r--r--src/charon/sa/child_sa.h28
-rw-r--r--src/charon/sa/connect_manager.c4
-rw-r--r--src/charon/sa/ike_sa.c213
-rw-r--r--src/charon/sa/ike_sa.h26
-rw-r--r--src/charon/sa/ike_sa_manager.c52
-rw-r--r--src/charon/sa/task_manager.c16
-rw-r--r--src/charon/sa/tasks/child_create.c187
-rw-r--r--src/charon/sa/tasks/child_delete.c48
-rw-r--r--src/charon/sa/tasks/ike_auth.c131
-rw-r--r--src/charon/sa/tasks/ike_cert_post.c9
-rw-r--r--src/charon/sa/tasks/ike_cert_pre.c43
-rw-r--r--src/charon/sa/tasks/ike_config.c7
-rw-r--r--src/charon/sa/tasks/ike_delete.c35
-rw-r--r--src/charon/sa/tasks/ike_init.c38
-rw-r--r--src/charon/sa/tasks/ike_me.c18
-rw-r--r--src/charon/sa/tasks/ike_mobike.c73
-rw-r--r--src/charon/sa/tasks/ike_mobike.h7
-rw-r--r--src/charon/sa/tasks/ike_natd.c45
-rw-r--r--src/charon/sa/tasks/ike_natd.h11
-rw-r--r--src/charon/sa/tasks/ike_reauth.c5
-rw-r--r--src/charon/sa/tasks/ike_rekey.c22
30 files changed, 1289 insertions, 357 deletions
diff --git a/src/charon/sa/authenticators/authenticator.c b/src/charon/sa/authenticators/authenticator.c
index c301e4933..827c7a69a 100644
--- a/src/charon/sa/authenticators/authenticator.c
+++ b/src/charon/sa/authenticators/authenticator.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: authenticator.c 4051 2008-06-10 09:08:27Z tobias $
+ * $Id: authenticator.c 4276 2008-08-22 10:44:51Z martin $
*/
#include <string.h>
@@ -33,22 +33,27 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
"ECDSA-256 signature",
"ECDSA-384 signature",
"ECDSA-521 signature");
-ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_ECDSA_521,
- "EAP");
-ENUM_END(auth_method_names, AUTH_EAP);
+ENUM_END(auth_method_names, AUTH_ECDSA_521);
+
+ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP,
+ "public key",
+ "pre-shared key",
+ "EAP",
+);
/**
* Described in header.
*/
-authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method)
+authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa,
+ auth_class_t class)
{
- switch (auth_method)
+ switch (class)
{
- case CONF_AUTH_PUBKEY:
+ case AUTH_CLASS_PUBKEY:
return (authenticator_t*)pubkey_authenticator_create(ike_sa);
- case CONF_AUTH_PSK:
+ case AUTH_CLASS_PSK:
return (authenticator_t*)psk_authenticator_create(ike_sa);
- case CONF_AUTH_EAP:
+ case AUTH_CLASS_EAP:
return (authenticator_t*)eap_authenticator_create(ike_sa);
default:
return NULL;
@@ -58,9 +63,10 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t aut
/**
* Described in header.
*/
-authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload)
+authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa,
+ auth_method_t method)
{
- switch (auth_payload->get_auth_method(auth_payload))
+ switch (method)
{
case AUTH_RSA:
case AUTH_ECDSA_256:
diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h
index 3c961d23e..aa5a73e86 100644
--- a/src/charon/sa/authenticators/authenticator.h
+++ b/src/charon/sa/authenticators/authenticator.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: authenticator.h 4051 2008-06-10 09:08:27Z tobias $
+ * $Id: authenticator.h 4276 2008-08-22 10:44:51Z martin $
*/
/**
@@ -26,6 +26,7 @@
#define AUTHENTICATOR_H_
typedef enum auth_method_t auth_method_t;
+typedef enum auth_class_t auth_class_t;
typedef struct authenticator_t authenticator_t;
#include <library.h>
@@ -34,7 +35,7 @@ typedef struct authenticator_t authenticator_t;
#include <encoding/payloads/auth_payload.h>
/**
- * Method to use for authentication.
+ * Method to use for authentication, as defined in IKEv2.
*/
enum auth_method_t {
/**
@@ -70,12 +71,6 @@ enum auth_method_t {
* ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754
*/
AUTH_ECDSA_521 = 11,
-
- /**
- * EAP authentication. This value is never negotiated and therefore
- * a value from private use.
- */
- AUTH_EAP = 201,
};
/**
@@ -84,11 +79,31 @@ enum auth_method_t {
extern enum_name_t *auth_method_names;
/**
+ * Class of authentication to use. This is different to auth_method_t in that
+ * it does not specify a method, but a class of acceptable methods. The found
+ * certificate finally dictates wich method is used.
+ */
+enum auth_class_t {
+ /** authentication using public keys (RSA, ECDSA) */
+ AUTH_CLASS_PUBKEY = 1,
+ /** authentication using a pre-shared secrets */
+ AUTH_CLASS_PSK = 2,
+ /** authentication using EAP */
+ AUTH_CLASS_EAP = 3,
+};
+
+/**
+ * enum strings for auth_class_t
+ */
+extern enum_name_t *auth_class_names;
+
+/**
* Authenticator interface implemented by the various authenticators.
*
* Currently the following two AUTH methods are supported:
* - shared key message integrity code
* - RSA digital signature
+ * - EAP using the EAP framework and one of the EAP plugins
* - ECDSA is supported using OpenSSL
*/
struct authenticator_t {
@@ -96,15 +111,14 @@ struct authenticator_t {
/**
* Verify a received authentication payload.
*
- * @param ike_sa_init binary representation of received ike_sa_init
- * @param my_nonce the sent nonce
- * @param auth_payload authentication payload to verify
- *
+ * @param ike_sa_init binary representation of received ike_sa_init
+ * @param my_nonce the sent nonce
+ * @param auth_payload authentication payload to verify
* @return
- * - SUCCESS,
- * - FAILED if verification failed
- * - INVALID_ARG if auth_method does not match
- * - NOT_FOUND if credentials not found
+ * - SUCCESS,
+ * - FAILED if verification failed
+ * - INVALID_ARG if auth_method does not match
+ * - NOT_FOUND if credentials not found
*/
status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init,
chunk_t my_nonce, auth_payload_t *auth_payload);
@@ -112,13 +126,12 @@ struct authenticator_t {
/**
* Build an authentication payload to send to the other peer.
*
- * @param ike_sa_init binary representation of sent ike_sa_init
- * @param other_nonce the received nonce
- * @param[out] auth_payload the resulting authentication payload
- *
+ * @param ike_sa_init binary representation of sent ike_sa_init
+ * @param other_nonce the received nonce
+ * @param auth_payload the resulting authentication payload
* @return
- * - SUCCESS,
- * - NOT_FOUND if the data for AUTH method could not be found
+ * - SUCCESS,
+ * - NOT_FOUND if credentials not found
*/
status_t (*build) (authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload);
@@ -130,23 +143,23 @@ struct authenticator_t {
};
/**
- * Creates an authenticator for the specified auth method (as configured).
+ * Creates an authenticator for the specified auth class (as configured).
*
* @param ike_sa associated ike_sa
- * @param auth_method authentication method to use for build()/verify()
- *
+ * @param class class of authentication to use
* @return authenticator_t object
*/
-authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method);
+authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa,
+ auth_class_t class);
/**
- * Creates an authenticator from the given auth payload.
+ * Creates an authenticator for method (as received in payload).
*
* @param ike_sa associated ike_sa
- * @param auth_payload auth payload
- *
+ * @param method method as found in payload
* @return authenticator_t object
*/
-authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload);
+authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa,
+ auth_method_t method);
#endif /* AUTHENTICATOR_H_ @} */
diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c
index 5e2db5489..11b12fb49 100644
--- a/src/charon/sa/authenticators/eap/eap_method.c
+++ b/src/charon/sa/authenticators/eap/eap_method.c
@@ -12,19 +12,19 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_method.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_method.c 4269 2008-08-21 12:10:07Z martin $
*/
#include "eap_method.h"
-ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_TOKEN_CARD,
+ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
"EAP_IDENTITY",
"EAP_NOTIFICATION",
"EAP_NAK",
"EAP_MD5",
- "EAP_ONE_TIME_PASSWORD",
- "EAP_TOKEN_CARD");
-ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_TOKEN_CARD,
+ "EAP_OTP",
+ "EAP_GTC");
+ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC,
"EAP_SIM");
ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
"EAP_AKA");
diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h
index eda6f545e..663117931 100644
--- a/src/charon/sa/authenticators/eap/eap_method.h
+++ b/src/charon/sa/authenticators/eap/eap_method.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_method.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_method.h 4276 2008-08-22 10:44:51Z martin $
*/
/**
@@ -52,8 +52,8 @@ enum eap_type_t {
EAP_NOTIFICATION = 2,
EAP_NAK = 3,
EAP_MD5 = 4,
- EAP_ONE_TIME_PASSWORD = 5,
- EAP_TOKEN_CARD = 6,
+ EAP_OTP = 5,
+ EAP_GTC = 6,
EAP_SIM = 18,
EAP_AKA = 23,
EAP_EXPANDED = 254,
@@ -95,6 +95,8 @@ extern enum_name_t *eap_code_names;
* authentication. Even if a mutual EAP method is used, the traditional
* AUTH payloads are required. Only these include the nonces and messages from
* ike_sa_init and therefore prevent man in the middle attacks.
+ * The EAP method must use an initial EAP identifier value != 0, as a preceding
+ * EAP-Identity exchange always uses identifier 0.
*/
struct eap_method_t {
@@ -148,7 +150,8 @@ struct eap_method_t {
/**
* Get the MSK established by this EAP method.
*
- * Not all EAP methods establish a shared secret.
+ * Not all EAP methods establish a shared secret. For implementations of
+ * the EAP-Identity method, get_msk() returns the received identity.
*
* @param msk chunk receiving internal stored MSK
* @return
@@ -171,6 +174,8 @@ struct eap_method_t {
* Constructors for server and peers are identical, to support both roles
* of a EAP method, a plugin needs register two constructors in the
* eap_manager_t.
+ * The passed identites are of type ID_EAP and valid only during the
+ * constructor invocation.
*
* @param server ID of the server to use for credential lookup
* @param peer ID of the peer to use for credential lookup
diff --git a/src/charon/sa/authenticators/eap/sim_manager.c b/src/charon/sa/authenticators/eap/sim_manager.c
new file mode 100644
index 000000000..e6817ca20
--- /dev/null
+++ b/src/charon/sa/authenticators/eap/sim_manager.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "sim_manager.h"
+
+#include <utils/linked_list.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 *provider;
+};
+
+/**
+ * Implementation of sim_manager_t.add_card
+ */
+static void add_card(private_sim_manager_t *this, sim_card_t *card)
+{
+ this->cards->insert_last(this->cards, card);
+}
+
+/**
+ * Implementation of sim_manager_t.remove_card
+ */
+static void remove_card(private_sim_manager_t *this, sim_card_t *card)
+{
+ this->cards->remove(this->cards, card, NULL);
+}
+
+/**
+ * Implementation of sim_manager_t.create_card_enumerator
+ */
+static enumerator_t* create_card_enumerator(private_sim_manager_t *this)
+{
+ return this->cards->create_enumerator(this->cards);
+}
+
+/**
+ * Implementation of sim_manager_t.add_provider
+ */
+static void add_provider(private_sim_manager_t *this,
+ sim_provider_t *provider)
+{
+ this->provider->insert_last(this->provider, provider);
+}
+
+/**
+ * Implementation of sim_manager_t.remove_provider
+ */
+static void remove_provider(private_sim_manager_t *this,
+ sim_provider_t *provider)
+{
+ this->provider->remove(this->provider, provider, NULL);
+}
+
+/**
+ * Implementation of sim_manager_t.create_provider_enumerator
+ */
+static enumerator_t* create_provider_enumerator(private_sim_manager_t *this)
+{
+ return this->provider->create_enumerator(this->provider);
+}
+
+/**
+ * Implementation of sim_manager_t.destroy.
+ */
+static void destroy(private_sim_manager_t *this)
+{
+ this->cards->destroy(this->cards);
+ this->provider->destroy(this->provider);
+ free(this);
+}
+
+/**
+ * See header
+ */
+sim_manager_t *sim_manager_create()
+{
+ private_sim_manager_t *this = malloc_thing(private_sim_manager_t);
+
+ this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card;
+ this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card;
+ this->public.create_card_enumerator = (enumerator_t*(*)(sim_manager_t*))create_card_enumerator;
+ this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider;
+ this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider;
+ this->public.create_provider_enumerator = (enumerator_t*(*)(sim_manager_t*))create_provider_enumerator;
+ this->public.destroy = (void(*)(sim_manager_t*))destroy;
+
+ this->cards = linked_list_create();
+ this->provider = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/charon/sa/authenticators/eap/sim_manager.h b/src/charon/sa/authenticators/eap/sim_manager.h
new file mode 100644
index 000000000..7fb1f2858
--- /dev/null
+++ b/src/charon/sa/authenticators/eap/sim_manager.h
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup sim_manager sim_manager
+ * @{ @ingroup eap
+ */
+
+#ifndef SIM_MANAGER_H_
+#define SIM_MANAGER_H_
+
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+
+typedef struct sim_manager_t sim_manager_t;
+typedef struct sim_card_t sim_card_t;
+typedef struct sim_provider_t sim_provider_t;
+
+/**
+ * Interface for a SIM card (used as EAP client).
+ */
+struct sim_card_t {
+
+ /**
+ * Get the identity of a SIM card.
+ *
+ * The returned identity owned by the sim_card and not destroyed outside.
+ * The SIM card may return ID_ANY if it does not support/use an IMSI.
+ *
+ * @return identity of type ID_EAP/ID_ANY
+ */
+ identification_t* (*get_imsi)(sim_card_t *this);
+
+ /**
+ * Calculate SRES/KC from a RAND.
+ *
+ * @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
+ */
+ bool (*get_triplet)(sim_card_t *this,
+ char rand[16], char sres[4], char kc[8]);
+};
+
+/**
+ * Interface for a triplet provider (used as EAP server).
+ */
+struct sim_provider_t {
+
+ /**
+ * Get a single triplet to authenticate a EAP client.
+ *
+ * @param imsi client identity of type ID_EAP
+ * @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 *imsi,
+ char rand[16], char sres[4], char kc[8]);
+};
+
+/**
+ * The EAP-SIM manager handles multiple SIM cards and providers.
+ */
+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);
+
+ /**
+ * Create an enumerator over all registered cards.
+ *
+ * @return enumerator over sim_card_t's
+ */
+ enumerator_t* (*create_card_enumerator)(sim_manager_t *this);
+
+ /**
+ * 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);
+
+ /**
+ * Create an enumerator over all registered provider.
+ *
+ * @return enumerator over sim_provider_t's
+ */
+ enumerator_t* (*create_provider_enumerator)(sim_manager_t *this);
+
+ /**
+ * Destroy a manager instance.
+ */
+ void (*destroy)(sim_manager_t *this);
+};
+
+/**
+ * Create an SIM manager to handle multiple SIM cards/providers.
+ *
+ * @return sim_t object
+ */
+sim_manager_t *sim_manager_create();
+
+#endif /* SIM_MANAGER_H_ @}*/
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c
index 95bb5e57f..0909d6563 100644
--- a/src/charon/sa/authenticators/eap_authenticator.c
+++ b/src/charon/sa/authenticators/eap_authenticator.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_authenticator.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_authenticator.c 4292 2008-08-26 19:54:47Z andreas $
*/
#include <string.h>
@@ -54,6 +54,21 @@ struct private_eap_authenticator_t {
* MSK used to build and verify auth payload
*/
chunk_t msk;
+
+ /**
+ * should we do a EAP-Identity exchange as server?
+ */
+ bool do_eap_identity;
+
+ /**
+ * saved EAP type if we do eap_identity
+ */
+ eap_type_t type;
+
+ /**
+ * saved vendor id if we do eap_identity
+ */
+ u_int32_t vendor;
};
/**
@@ -93,7 +108,7 @@ static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
chunk_free(&auth_data);
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
- other_id, auth_method_names, AUTH_EAP);
+ other_id, auth_class_names, AUTH_CLASS_EAP);
return SUCCESS;
}
@@ -107,7 +122,7 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
- my_id, auth_method_names, AUTH_EAP);
+ my_id, auth_class_names, AUTH_CLASS_EAP);
if (this->msk.len)
{ /* use MSK if EAP method established one... */
@@ -130,6 +145,79 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
}
/**
+ * get the peers identity to use in the EAP method
+ */
+static identification_t *get_peer_id(private_eap_authenticator_t *this)
+{
+ identification_t *id;
+ peer_cfg_t *config;
+ auth_info_t *auth;
+
+ id = this->ike_sa->get_eap_identity(this->ike_sa);
+ if (!id)
+ {
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ auth = config->get_auth(config);
+ if (!auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id))
+ {
+ if (this->role == EAP_PEER)
+ {
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ else
+ {
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ }
+ }
+ }
+ if (id->get_type(id) == ID_EAP)
+ {
+ return id->clone(id);
+ }
+ return identification_create_from_encoding(ID_EAP, id->get_encoding(id));
+}
+
+/**
+ * get the servers identity to use in the EAP method
+ */
+static identification_t *get_server_id(private_eap_authenticator_t *this)
+{
+ identification_t *id;
+
+ if (this->role == EAP_SERVER)
+ {
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ else
+ {
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ }
+ if (id->get_type(id) == ID_EAP)
+ {
+ return id->clone(id);
+ }
+ return identification_create_from_encoding(ID_EAP, id->get_encoding(id));
+}
+
+/**
+ * load an EAP method using the correct identities
+ */
+static eap_method_t *load_method(private_eap_authenticator_t *this,
+ eap_type_t type, u_int32_t vendor, eap_role_t role)
+{
+ identification_t *server, *peer;
+ eap_method_t *method;
+
+ server = get_server_id(this);
+ peer = get_peer_id(this);
+ method = charon->eap->create_instance(charon->eap, type, vendor, role,
+ server, peer);
+ server->destroy(server);
+ peer->destroy(peer);
+ return method;
+}
+
+/**
* Implementation of eap_authenticator_t.initiate
*/
static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
@@ -138,6 +226,14 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
/* if initiate() is called, role is always server */
this->role = EAP_SERVER;
+ if (this->do_eap_identity)
+ { /* do an EAP-Identity request first */
+ this->type = type;
+ this->vendor = vendor;
+ vendor = 0;
+ type = EAP_IDENTITY;
+ }
+
if (type == 0)
{
DBG1(DBG_IKE,
@@ -148,20 +244,23 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
if (vendor)
{
- DBG1(DBG_IKE, "requesting vendor specific EAP authentication %d-%d",
+ DBG1(DBG_IKE, "requesting vendor specific EAP method %d-%d",
type, vendor);
}
else
{
- DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type);
+ DBG1(DBG_IKE, "requesting EAP method %N", eap_type_names, type);
}
- this->method = charon->eap->create_instance(charon->eap, type, vendor,
- this->role, this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
-
+ this->method = load_method(this, type, vendor, this->role);
if (this->method == NULL)
{
-
+ if (vendor == 0 && type == EAP_IDENTITY)
+ {
+ DBG1(DBG_IKE, "skipping %N, no implementation found",
+ eap_type_names, type);
+ this->do_eap_identity = FALSE;
+ return initiate(this, this->type, this->vendor, out);
+ }
DBG1(DBG_IKE, "configured EAP server method not supported, sending %N",
eap_code_names, EAP_FAILURE);
*out = eap_payload_create_code(EAP_FAILURE, 0);
@@ -192,10 +291,7 @@ static status_t process_peer(private_eap_authenticator_t *this,
{
eap_method_t *method;
- method = charon->eap->create_instance(charon->eap, type, 0, EAP_PEER,
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa));
-
+ method = load_method(this, type, 0, EAP_PEER);
if (method == NULL || method->process(method, in, out) != SUCCESS)
{
DBG1(DBG_IKE, "EAP server requested %N, but unable to process",
@@ -203,10 +299,7 @@ static status_t process_peer(private_eap_authenticator_t *this,
DESTROY_IF(method);
return FAILED;
}
-
- DBG1(DBG_IKE, "EAP server requested %N, sending IKE identity",
- eap_type_names, type);
-
+ DBG1(DBG_IKE, "EAP server requested %N", eap_type_names, type);
method->destroy(method);
return NEED_MORE;
}
@@ -224,10 +317,7 @@ static status_t process_peer(private_eap_authenticator_t *this,
DBG1(DBG_IKE, "EAP server requested %N authentication",
eap_type_names, type);
}
- this->method = charon->eap->create_instance(charon->eap,
- type, vendor, EAP_PEER,
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa));
+ this->method = load_method(this, type, vendor, EAP_PEER);
if (this->method == NULL)
{
DBG1(DBG_IKE, "EAP server requested unsupported "
@@ -251,7 +341,7 @@ static status_t process_peer(private_eap_authenticator_t *this,
}
else
{
- DBG1(DBG_IKE, "EAP method %N succeded", eap_type_names, type);
+ DBG1(DBG_IKE, "EAP method %N succeeded", eap_type_names, type);
}
return SUCCESS;
case FAILED:
@@ -271,6 +361,27 @@ static status_t process_peer(private_eap_authenticator_t *this,
}
/**
+ * handle an EAP-Identity response on the server
+ */
+static status_t process_eap_identity(private_eap_authenticator_t *this,
+ eap_payload_t **out)
+{
+ chunk_t data;
+ identification_t *id;
+
+ if (this->method->get_msk(this->method, &data) == SUCCESS)
+ {
+ id = identification_create_from_encoding(ID_EAP, data);
+ DBG1(DBG_IKE, "using EAP identity '%D'", id);
+ this->ike_sa->set_eap_identity(this->ike_sa, id);
+ }
+ /* restart EAP exchange, but with real method */
+ this->method->destroy(this->method);
+ this->do_eap_identity = FALSE;
+ return initiate(this, this->type, this->vendor, out);
+}
+
+/**
* Processing method for a server
*/
static status_t process_server(private_eap_authenticator_t *this,
@@ -286,6 +397,10 @@ static status_t process_server(private_eap_authenticator_t *this,
case NEED_MORE:
return NEED_MORE;
case SUCCESS:
+ if (this->do_eap_identity)
+ {
+ return process_eap_identity(this, out);
+ }
if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
{
this->msk = chunk_clone(this->msk);
@@ -409,6 +524,9 @@ static void destroy(private_eap_authenticator_t *this)
*/
eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa)
{
+ peer_cfg_t *config;
+ auth_info_t *auth;
+ identification_t *id;
private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t);
/* public functions */
@@ -425,6 +543,25 @@ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa)
this->role = EAP_PEER;
this->method = NULL;
this->msk = chunk_empty;
+ this->do_eap_identity = FALSE;
+ this->type = 0;
+ this->vendor = 0;
+ config = ike_sa->get_peer_cfg(ike_sa);
+ if (config)
+ {
+ auth = config->get_auth(config);
+ if (auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id))
+ {
+ if (id->get_type(id) == ID_ANY)
+ { /* %any as configured EAP identity runs EAP-Identity first */
+ this->do_eap_identity = TRUE;
+ }
+ else
+ {
+ ike_sa->set_eap_identity(ike_sa, id->clone(id));
+ }
+ }
+ }
return &this->public;
}
diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h
index 2dad59fbb..bd300a584 100644
--- a/src/charon/sa/authenticators/eap_authenticator.h
+++ b/src/charon/sa/authenticators/eap_authenticator.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_authenticator.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_authenticator.h 4276 2008-08-22 10:44:51Z martin $
*/
/**
@@ -29,7 +29,7 @@ typedef struct eap_authenticator_t eap_authenticator_t;
#include <encoding/payloads/eap_payload.h>
/**
- * Implementation of the authenticator_t interface using AUTH_EAP.
+ * Implementation of the authenticator_t interface using AUTH_CLASS_EAP.
*
* Authentication using EAP involves the most complex authenticator. It stays
* alive over multiple ike_auth transactions and handles multiple EAP
@@ -137,7 +137,7 @@ struct eap_authenticator_t {
};
/**
- * Creates an authenticator for AUTH_EAP.
+ * Creates an authenticator for AUTH_CLASS_EAP.
*
* @param ike_sa associated ike_sa
* @return eap_authenticator_t object
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 2a6b6f67c..7c4b398cf 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_sa.c 3920 2008-05-08 16:19:11Z tobias $
+ * $Id: child_sa.c 4358 2008-09-25 13:56:23Z tobias $
*/
#define _GNU_SOURCE
@@ -163,7 +163,7 @@ struct private_child_sa_t {
/**
* mode this SA uses, tunnel/transport
*/
- mode_t mode;
+ ipsec_mode_t mode;
/**
* virtual IP assinged to local host
@@ -210,6 +210,18 @@ u_int32_t get_spi(private_child_sa_t *this, bool inbound)
}
/**
+ * Implements child_sa_t.get_cpi
+ */
+u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
+{
+ if (inbound)
+ {
+ return this->me.cpi;
+ }
+ return this->other.cpi;
+}
+
+/**
* Implements child_sa_t.get_protocol
*/
protocol_id_t get_protocol(private_child_sa_t *this)
@@ -236,7 +248,7 @@ static child_cfg_t* get_config(private_child_sa_t *this)
/**
* Implementation of child_sa_t.get_stats.
*/
-static void get_stats(private_child_sa_t *this, mode_t *mode,
+static void get_stats(private_child_sa_t *this, ipsec_mode_t *mode,
encryption_algorithm_t *encr_algo, size_t *encr_len,
integrity_algorithm_t *int_algo, size_t *int_len,
u_int32_t *rekey, u_int32_t *use_in, u_int32_t *use_out,
@@ -514,7 +526,7 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
}
static status_t install(private_child_sa_t *this, proposal_t *proposal,
- mode_t mode, prf_plus_t *prf_plus, bool mine)
+ ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine)
{
u_int32_t spi, soft, hard;
host_t *src;
@@ -605,7 +617,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
}
static status_t add(private_child_sa_t *this, proposal_t *proposal,
- mode_t mode, prf_plus_t *prf_plus)
+ ipsec_mode_t mode, prf_plus_t *prf_plus)
{
u_int32_t outbound_spi, inbound_spi;
@@ -637,7 +649,7 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal,
}
static status_t update(private_child_sa_t *this, proposal_t *proposal,
- mode_t mode, prf_plus_t *prf_plus)
+ ipsec_mode_t mode, prf_plus_t *prf_plus)
{
u_int32_t inbound_spi;
@@ -662,14 +674,19 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal,
}
static status_t add_policies(private_child_sa_t *this,
- linked_list_t *my_ts_list,
- linked_list_t *other_ts_list, mode_t mode)
+ linked_list_t *my_ts_list, linked_list_t *other_ts_list,
+ ipsec_mode_t mode, protocol_id_t proto)
{
iterator_t *my_iter, *other_iter;
traffic_selector_t *my_ts, *other_ts;
/* use low prio for ROUTED policies */
bool high_prio = (this->state != CHILD_CREATED);
+ if (this->protocol == PROTO_NONE)
+ { /* update if not set yet */
+ this->protocol = proto;
+ }
+
/* iterate over both lists */
my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
@@ -919,9 +936,9 @@ static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
}
/**
- * Implementation of child_sa_t.get_my_cpi.
+ * Implementation of child_sa_t.allocate_cpi.
*/
-static u_int16_t get_my_cpi(private_child_sa_t *this)
+static u_int16_t allocate_cpi(private_child_sa_t *this)
{
if (!this->cpi_allocated)
{
@@ -968,7 +985,7 @@ static void destroy(private_child_sa_t *this)
if (this->me.cpi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
+ this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
}
if (this->other.cpi)
{
@@ -1023,20 +1040,21 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.get_name = (char*(*)(child_sa_t*))get_name;
this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
+ this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
- this->public.get_stats = (void(*)(child_sa_t*, mode_t*,encryption_algorithm_t*,size_t*,integrity_algorithm_t*,size_t*,u_int32_t*,u_int32_t*,u_int32_t*,u_int32_t*))get_stats;
+ this->public.get_stats = (void(*)(child_sa_t*, ipsec_mode_t*,encryption_algorithm_t*,size_t*,integrity_algorithm_t*,size_t*,u_int32_t*,u_int32_t*,u_int32_t*,u_int32_t*))get_stats;
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
- this->public.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add;
- this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update;
+ this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add;
+ this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update;
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
- this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies;
+ this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
- this->public.get_my_cpi = (u_int16_t(*)(child_sa_t*))get_my_cpi;
+ this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
this->public.destroy = (void(*)(child_sa_t*))destroy;
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index 5bd66acad..2f7961e03 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_sa.h 3920 2008-05-08 16:19:11Z tobias $
+ * $Id: child_sa.h 4358 2008-09-25 13:56:23Z tobias $
*/
/**
@@ -114,11 +114,23 @@ struct child_sa_t {
* FALSE to get those we use for sending packets.
*
* @param inbound TRUE to get inbound SPI, FALSE for outbound.
- * @return spi of the CHILD SA
+ * @return SPI of the CHILD SA
*/
u_int32_t (*get_spi) (child_sa_t *this, bool inbound);
/**
+ * Get the CPI of this CHILD_SA.
+ *
+ * Set the boolean parameter inbound to TRUE to
+ * get the CPI for which we receive packets, use
+ * FALSE to get those we use for sending packets.
+ *
+ * @param inbound TRUE to get inbound CPI, FALSE for outbound.
+ * @return CPI of the CHILD SA
+ */
+ u_int16_t (*get_cpi) (child_sa_t *this, bool inbound);
+
+ /**
* Get the protocol which this CHILD_SA uses to protect traffic.
*
* @return AH | ESP
@@ -138,7 +150,7 @@ struct child_sa_t {
* @param use_out time when last traffic was seen going out
* @param use_fwd time when last traffic was getting forwarded
*/
- void (*get_stats)(child_sa_t *this, mode_t *mode,
+ void (*get_stats)(child_sa_t *this, ipsec_mode_t *mode,
encryption_algorithm_t *encr, size_t *encr_len,
integrity_algorithm_t *int_algo, size_t *int_len,
u_int32_t *rekey, u_int32_t *use_in, u_int32_t *use_out,
@@ -165,7 +177,7 @@ struct child_sa_t {
* @param prf_plus key material to use for key derivation
* @return SUCCESS or FAILED
*/
- status_t (*add)(child_sa_t *this, proposal_t *proposal, mode_t mode,
+ status_t (*add)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
prf_plus_t *prf_plus);
/**
@@ -178,7 +190,7 @@ struct child_sa_t {
* @param prf_plus key material to use for key derivation
* @return SUCCESS or FAILED
*/
- status_t (*update)(child_sa_t *this, proposal_t *proposal, mode_t mode,
+ status_t (*update)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
prf_plus_t *prf_plus);
/**
@@ -203,10 +215,12 @@ struct child_sa_t {
* @param my_ts traffic selectors for local site
* @param other_ts traffic selectors for remote site
* @param mode mode for the SA: tunnel/transport
+ * @param proto protocol for policy, ESP/AH
* @return SUCCESS or FAILED
*/
status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
- linked_list_t *other_ts_list, mode_t mode);
+ linked_list_t *other_ts_list, ipsec_mode_t mode,
+ protocol_id_t proto);
/**
* Get the traffic selectors of added policies of local host.
@@ -268,7 +282,7 @@ struct child_sa_t {
*
* @return allocated CPI
*/
- u_int16_t (*get_my_cpi) (child_sa_t *this);
+ u_int16_t (*allocate_cpi) (child_sa_t *this);
/**
* Destroys a child_sa.
diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c
index 19ceea666..d24ce8fc7 100644
--- a/src/charon/sa/connect_manager.c
+++ b/src/charon/sa/connect_manager.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: connect_manager.c 3792 2008-04-10 12:51:04Z tobias $
+ * $Id: connect_manager.c 4192 2008-07-18 15:51:40Z martin $
*/
#include "connect_manager.h"
@@ -1160,7 +1160,7 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
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)
{
- SIG(IKE_UP_FAILED, "establishing the mediated connection failed");
+ SIG_IKE(UP_FAILED, "establishing the mediated connection failed");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 384226380..7b2608e07 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.c 4106 2008-06-25 11:40:50Z martin $
+ * $Id: ike_sa.c 4394 2008-10-09 08:25:11Z martin $
*/
#include <sys/time.h>
@@ -170,6 +170,11 @@ struct private_ike_sa_t {
identification_t *other_id;
/**
+ * EAP Identity exchange in EAP-Identity method
+ */
+ identification_t *eap_identity;;
+
+ /**
* set of extensions the peer supports
*/
ike_extension_t extensions;
@@ -250,11 +255,21 @@ struct private_ike_sa_t {
linked_list_t *additional_addresses;
/**
+ * previously value of received DESTINATION_IP hash
+ */
+ chunk_t nat_detection_dest;
+
+ /**
* number pending UPDATE_SA_ADDRESS (MOBIKE)
*/
u_int32_t pending_updates;
/**
+ * NAT keep alive interval
+ */
+ u_int32_t keepalive_interval;
+
+ /**
* Timestamps for this IKE_SA
*/
struct {
@@ -454,7 +469,7 @@ static void send_keepalive(private_ike_sa_t *this)
send_keepalive_job_t *job;
time_t last_out, now, diff;
- if (!(this->conditions & COND_NAT_HERE))
+ if (!(this->conditions & COND_NAT_HERE) || this->keepalive_interval == 0)
{ /* disable keep alives if we are not NATed anymore */
return;
}
@@ -464,7 +479,7 @@ static void send_keepalive(private_ike_sa_t *this)
diff = now - last_out;
- if (diff >= KEEPALIVE_INTERVAL)
+ if (diff >= this->keepalive_interval)
{
packet_t *packet;
chunk_t data;
@@ -482,7 +497,7 @@ static void send_keepalive(private_ike_sa_t *this)
}
job = send_keepalive_job_create(this->ike_sa_id);
charon->scheduler->schedule_job(charon->scheduler, (job_t*)job,
- (KEEPALIVE_INTERVAL - diff) * 1000);
+ (this->keepalive_interval - diff) * 1000);
}
/**
@@ -616,8 +631,20 @@ static status_t send_dpd(private_ike_sa_t *this)
{
/* to long ago, initiate dead peer detection */
task_t *task;
+ ike_mobike_t *mobike;
- task = (task_t*)ike_dpd_create(TRUE);
+ if (supports_extension(this, EXT_MOBIKE) &&
+ has_condition(this, COND_NAT_HERE))
+ {
+ /* use mobike enabled DPD to detect NAT mapping changes */
+ mobike = ike_mobike_create(&this->public, TRUE);
+ mobike->dpd(mobike);
+ task = &mobike->task;
+ }
+ else
+ {
+ task = (task_t*)ike_dpd_create(TRUE);
+ }
diff = 0;
DBG1(DBG_IKE, "sending DPD request");
@@ -645,8 +672,8 @@ static ike_sa_state_t get_state(private_ike_sa_t *this)
*/
static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
{
- DBG1(DBG_IKE, "IKE_SA '%s' state change: %N => %N",
- get_name(this),
+ DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
+ get_name(this), this->unique_id,
ike_sa_state_names, this->state,
ike_sa_state_names, state);
@@ -807,7 +834,26 @@ static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
return this->additional_addresses->create_iterator(
this->additional_addresses, TRUE);
}
-
+
+/**
+ * Implementation of ike_sa_t.has_mapping_changed
+ */
+static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
+{
+ if (this->nat_detection_dest.ptr == NULL)
+ {
+ this->nat_detection_dest = chunk_clone(hash);
+ return FALSE;
+ }
+ if (chunk_equals(hash, this->nat_detection_dest))
+ {
+ return FALSE;
+ }
+ free(this->nat_detection_dest.ptr);
+ this->nat_detection_dest = chunk_clone(hash);
+ return TRUE;
+}
+
/**
* Implementation of ike_sa_t.set_pending_updates.
*/
@@ -831,11 +877,6 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
{
bool update = FALSE;
- if (supports_extension(this, EXT_MOBIKE))
- { /* if peer speaks mobike, address updates are explicit only */
- return;
- }
-
if (me == NULL)
{
me = this->my_host;
@@ -1041,18 +1082,31 @@ static void resolve_hosts(private_ike_sa_t *this)
{
host_t *host;
- host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg), 0,
- IKEV2_UDP_PORT);
+ host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+ 0, IKEV2_UDP_PORT);
if (host)
{
- set_my_host(this, host);
+ set_other_host(this, host);
}
- host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+
+ host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
this->my_host->get_family(this->my_host),
IKEV2_UDP_PORT);
+
+ if (host && host->is_anyaddr(host) &&
+ !this->other_host->is_anyaddr(this->other_host))
+ {
+ host->destroy(host);
+ host = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, this->other_host, NULL);
+ if (host)
+ {
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ }
if (host)
{
- set_other_host(this, host);
+ set_my_host(this, host);
}
}
@@ -1074,8 +1128,8 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
)
{
child_cfg->destroy(child_cfg);
- SIG(IKE_UP_START, "initiating IKE_SA");
- SIG(IKE_UP_FAILED, "unable to initiate to %%any");
+ SIG_IKE(UP_START, "initiating IKE_SA");
+ SIG_IKE(UP_FAILED, "unable to initiate to %%any");
return DESTROY_ME;
}
@@ -1112,7 +1166,7 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
/* mediation connection */
if (this->state == IKE_ESTABLISHED)
{ /* FIXME: we should try to find a better solution to this */
- SIG(CHILD_UP_SUCCESS, "mediation connection is already up and running");
+ SIG_CHD(UP_SUCCESS, NULL, "mediation connection is already up and running");
}
DESTROY_IF(child_cfg);
}
@@ -1162,8 +1216,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
if (this->state == IKE_DELETING)
{
- SIG(CHILD_UP_START, "acquiring CHILD_SA on kernel request");
- SIG(CHILD_UP_FAILED, "acquiring CHILD_SA (reqid %d) failed: "
+ SIG_CHD(UP_START, NULL, "acquiring CHILD_SA on kernel request");
+ SIG_CHD(UP_FAILED, NULL, "acquiring CHILD_SA {reqid %d} failed: "
"IKE_SA is deleting", reqid);
return FAILED;
}
@@ -1181,8 +1235,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
iterator->destroy(iterator);
if (!child_sa)
{
- SIG(CHILD_UP_START, "acquiring CHILD_SA on kernel request");
- SIG(CHILD_UP_FAILED, "acquiring CHILD_SA (reqid %d) failed: "
+ SIG_CHD(UP_START, NULL, "acquiring CHILD_SA on kernel request");
+ SIG_CHD(UP_FAILED, NULL, "acquiring CHILD_SA {reqid %d} failed: "
"CHILD_SA not found", reqid);
return FAILED;
}
@@ -1204,7 +1258,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
host_t *me, *other;
status_t status;
- SIG(CHILD_ROUTE_START, "routing CHILD_SA");
+ SIG_CHD(ROUTE_START, NULL, "routing CHILD_SA");
/* check if not already routed*/
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -1214,7 +1268,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
{
iterator->destroy(iterator);
- SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config already routed");
+ SIG_CHD(ROUTE_FAILED, child_sa, "CHILD_SA with such a config already routed");
return FAILED;
}
}
@@ -1224,7 +1278,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
case IKE_DELETING:
case IKE_REKEYING:
- SIG(CHILD_ROUTE_FAILED,
+ SIG_CHD(ROUTE_FAILED, NULL,
"unable to route CHILD_SA, as its IKE_SA gets deleted");
return FAILED;
case IKE_CREATED:
@@ -1253,17 +1307,17 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, me);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, other);
status = child_sa->add_policies(child_sa, my_ts, other_ts,
- child_cfg->get_mode(child_cfg));
+ child_cfg->get_mode(child_cfg), PROTO_NONE);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
if (status == SUCCESS)
{
this->child_sas->insert_last(this->child_sas, child_sa);
- SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed");
+ SIG_CHD(ROUTE_SUCCESS, child_sa, "CHILD_SA routed");
}
else
{
- SIG(CHILD_ROUTE_FAILED, "routing CHILD_SA failed");
+ SIG_CHD(ROUTE_FAILED, child_sa, "routing CHILD_SA failed");
}
return status;
}
@@ -1277,7 +1331,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
child_sa_t *child_sa;
bool found = FALSE;
- SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA");
+ SIG_CHD(UNROUTE_START, NULL, "unrouting CHILD_SA");
/* find CHILD_SA in ROUTED state */
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -1287,7 +1341,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
child_sa->get_reqid(child_sa) == reqid)
{
iterator->remove(iterator);
- SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted");
+ SIG_CHD(UNROUTE_SUCCESS, child_sa, "CHILD_SA unrouted");
child_sa->destroy(child_sa);
found = TRUE;
break;
@@ -1297,7 +1351,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
if (!found)
{
- SIG(CHILD_UNROUTE_FAILED, "CHILD_SA to unroute not found");
+ SIG_CHD(UNROUTE_FAILED, NULL, "CHILD_SA to unroute not found");
return FAILED;
}
/* if we are not established, and we have no more routed childs, remove whole SA */
@@ -1397,13 +1451,15 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
charon->scheduler->schedule_job(charon->scheduler, job,
HALF_OPEN_IKE_SA_TIMEOUT);
}
-
+ this->time.inbound = time(NULL);
/* check if message is trustworthy, and update host information */
if (this->state == IKE_CREATED || this->state == IKE_CONNECTING ||
message->get_exchange_type(message) != IKE_SA_INIT)
{
- update_hosts(this, me, other);
- this->time.inbound = time(NULL);
+ if (!supports_extension(this, EXT_MOBIKE))
+ { /* with MOBIKE, we do no implicit updates */
+ update_hosts(this, me, other);
+ }
}
status = this->task_manager->process_message(this->task_manager, message);
if (status != DESTROY_ME)
@@ -1528,6 +1584,23 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other)
}
/**
+ * Implementation of ike_sa_t.get_eap_identity.
+ */
+static identification_t* get_eap_identity(private_ike_sa_t *this)
+{
+ return this->eap_identity;
+}
+
+/**
+ * Implementation of ike_sa_t.set_eap_identity.
+ */
+static void set_eap_identity(private_ike_sa_t *this, identification_t *id)
+{
+ DESTROY_IF(this->eap_identity);
+ this->eap_identity = id;
+}
+
+/**
* Implementation of ike_sa_t.derive_keys.
*/
static status_t derive_keys(private_ike_sa_t *this,
@@ -1866,10 +1939,10 @@ static status_t delete_(private_ike_sa_t *this)
this->task_manager->queue_task(this->task_manager, &ike_delete->task);
return this->task_manager->initiate(this->task_manager);
case IKE_CREATED:
- SIG(IKE_DOWN_SUCCESS, "deleting unestablished IKE_SA");
+ SIG_IKE(DOWN_SUCCESS, "deleting unestablished IKE_SA");
break;
default:
- SIG(IKE_DOWN_SUCCESS, "destroying IKE_SA in state %N "
+ SIG_IKE(DOWN_SUCCESS, "destroying IKE_SA in state %N "
"without notification", ike_sa_state_names, this->state);
break;
}
@@ -2073,19 +2146,19 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
{
- SIG(IKE_UP_FAILED, "peer not responding, trying again "
+ SIG_IKE(UP_FAILED, "peer not responding, trying again "
"(%d/%d) in background ", this->keyingtry + 1, tries);
reset(this);
return this->task_manager->initiate(this->task_manager);
}
- SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding");
+ SIG_IKE(UP_FAILED, "establishing IKE_SA failed, peer not responding");
break;
}
case IKE_DELETING:
- SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
+ SIG_IKE(DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
break;
case IKE_REKEYING:
- SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
+ SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
/* FALL */
default:
reestablish(this);
@@ -2101,24 +2174,29 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
*/
static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
{
- job_t *job;
u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg);
+ u_int32_t reauth_time = time(NULL) + lifetime - reduction;
- this->time.reauth = time(NULL) + lifetime - reduction;
- job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
-
if (lifetime < reduction)
{
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, starting reauthentication",
lifetime);
- charon->processor->queue_job(charon->processor, job);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
}
- else
+ else if (this->time.reauth == 0 || this->time.reauth > reauth_time)
{
+ this->time.reauth = reauth_time;
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
" in %ds", lifetime, lifetime - reduction);
- charon->scheduler->schedule_job(charon->scheduler, job,
- (lifetime - reduction) * 1000);
+ charon->scheduler->schedule_job(charon->scheduler,
+ (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE),
+ (lifetime - reduction) * 1000);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, reauthentication already "
+ "scheduled in %ds", lifetime, this->time.reauth - time(NULL));
}
}
@@ -2127,7 +2205,7 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
*/
static status_t roam(private_ike_sa_t *this, bool address)
{
- host_t *me, *other;
+ host_t *src;
ike_mobike_t *mobike;
switch (this->state)
@@ -2151,21 +2229,19 @@ static status_t roam(private_ike_sa_t *this, bool address)
return SUCCESS;
}
- /* get best address pair to use */
- other = this->other_host;
- me = charon->kernel_interface->get_source_addr(charon->kernel_interface,
- other);
-
- if (me)
+ /* keep existing path if possible */
+ src = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ this->other_host, this->my_host);
+ if (src)
{
- if (me->ip_equals(me, this->my_host) &&
- other->ip_equals(other, this->other_host))
+ if (src->ip_equals(src, this->my_host))
{
- DBG2(DBG_IKE, "keeping connection path %H - %H", this->other_host, me);
- me->destroy(me);
+ DBG2(DBG_IKE, "keeping connection path %H - %H",
+ src, this->other_host);
+ src->destroy(src);
return SUCCESS;
}
- me->destroy(me);
+ src->destroy(src);
}
/* update addresses with mobike, if supported ... */
@@ -2177,7 +2253,7 @@ static status_t roam(private_ike_sa_t *this, bool address)
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
- DBG1(DBG_IKE, "reauthenticating IKE_SA due address change");
+ DBG1(DBG_IKE, "reauthenticating IKE_SA due to address change");
/* ... reauth if not */
return reauth(this);
}
@@ -2453,11 +2529,13 @@ static void destroy(private_ike_sa_t *this)
DESTROY_IF(this->server_reflexive_host);
chunk_free(&this->connect_id);
#endif /* ME */
+ free(this->nat_detection_dest.ptr);
DESTROY_IF(this->my_host);
DESTROY_IF(this->other_host);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
+ DESTROY_IF(this->eap_identity);
DESTROY_IF(this->ike_cfg);
DESTROY_IF(this->peer_cfg);
@@ -2502,6 +2580,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id;
this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id;
this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id;
+ this->public.get_eap_identity = (identification_t* (*)(ike_sa_t*)) get_eap_identity;
+ this->public.set_eap_identity = (void (*)(ike_sa_t*,identification_t*)) set_eap_identity;
this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
@@ -2511,6 +2591,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.is_ike_initiator = (bool (*)(ike_sa_t*))is_ike_initiator;
this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
+ this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed;
this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
this->public.delete = (status_t (*)(ike_sa_t*))delete_;
this->public.destroy = (void (*)(ike_sa_t*))destroy;
@@ -2560,6 +2641,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ this->eap_identity = NULL;
this->extensions = 0;
this->conditions = 0;
this->selected_proposal = NULL;
@@ -2572,6 +2654,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->skp_build = chunk_empty;
this->child_prf = NULL;
this->state = IKE_CREATED;
+ this->keepalive_interval = lib->settings->get_time(lib->settings,
+ "charon.keep_alive", KEEPALIVE_INTERVAL);
this->time.inbound = this->time.outbound = time(NULL);
this->time.established = 0;
this->time.rekey = 0;
@@ -2587,6 +2671,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->other_virtual_ip = NULL;
this->dns_servers = linked_list_create();
this->additional_addresses = linked_list_create();
+ this->nat_detection_dest = chunk_empty;
this->pending_updates = 0;
this->keyingtry = 0;
this->ike_initiator = FALSE;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 0935f5d6b..717d41647 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.h 4086 2008-06-22 11:24:33Z andreas $
+ * $Id: ike_sa.h 4368 2008-10-06 13:37:04Z martin $
*/
/**
@@ -330,6 +330,22 @@ struct ike_sa_t {
void (*set_other_id) (ike_sa_t *this, identification_t *other);
/**
+ * Get the peers EAP identity.
+ *
+ * The EAP identity is exchanged in a EAP-Identity exchange.
+ *
+ * @return identification, NULL if none set
+ */
+ identification_t* (*get_eap_identity) (ike_sa_t *this);
+
+ /**
+ * Set the peer's EAP identity.
+ *
+ * @param id identification
+ */
+ void (*set_eap_identity) (ike_sa_t *this, identification_t *id);
+
+ /**
* Get the config used to setup this IKE_SA.
*
* @return ike_config
@@ -391,6 +407,14 @@ struct ike_sa_t {
iterator_t* (*create_additional_address_iterator)(ike_sa_t *this);
/**
+ * Check if mappings have changed on a NAT for our source address.
+ *
+ * @param hash received DESTINATION_IP hash
+ * @return TRUE if mappings have changed
+ */
+ bool (*has_mapping_changed)(ike_sa_t *this, chunk_t hash);
+
+ /**
* Enable an extension the peer supports.
*
* If support for an IKE extension is detected, this method is called
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index 9c1b2d413..bd7b84c6f 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa_manager.c 4044 2008-06-06 15:05:54Z martin $
+ * $Id: ike_sa_manager.c 4234 2008-07-30 14:15:08Z martin $
*/
#include <pthread.h>
@@ -80,6 +80,16 @@ struct entry_t {
host_t *other;
/**
+ * own identity, required for duplicate checking
+ */
+ identification_t *my_id;
+
+ /**
+ * remote identity, required for duplicate checking
+ */
+ identification_t *other_id;
+
+ /**
* message ID currently processing, if any
*/
u_int32_t message_id;
@@ -95,6 +105,8 @@ static status_t entry_destroy(entry_t *this)
this->ike_sa_id->destroy(this->ike_sa_id);
chunk_free(&this->init_hash);
DESTROY_IF(this->other);
+ DESTROY_IF(this->my_id);
+ DESTROY_IF(this->other_id);
free(this);
return SUCCESS;
}
@@ -116,6 +128,8 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
this->message_id = -1;
this->init_hash = chunk_empty;
this->other = NULL;
+ this->my_id = NULL;
+ this->other_id = NULL;
/* ike_sa_id is always cloned */
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
@@ -157,6 +171,11 @@ struct private_ike_sa_manager_t {
* SHA1 hasher for IKE_SA_INIT retransmit detection
*/
hasher_t *hasher;
+
+ /**
+ * reuse existing IKE_SAs in checkout_by_config
+ */
+ bool reuse_ikesa;
};
/**
@@ -504,7 +523,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
pthread_mutex_lock(&(this->mutex));
- if (my_host && other_host)
+ if (my_host && other_host && this->reuse_ikesa)
{
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
@@ -721,10 +740,13 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
{ /* self is not a duplicate */
continue;
}
- if (wait_for_entry(this, entry))
- {
- if (me->equals(me, entry->ike_sa->get_my_id(entry->ike_sa)) &&
- other->equals(other, entry->ike_sa->get_other_id(entry->ike_sa)))
+ if (entry->my_id && me->equals(me, entry->my_id) &&
+ entry->other_id && other->equals(other, entry->other_id))
+ {
+ /* we are sure that the other entry is not calling
+ * checkout_duplicate here, as the identities in entry would not
+ * have been set yet. Otherwise we would risk a deadlock. */
+ if (wait_for_entry(this, entry))
{
duplicate = entry->ike_sa;
entry->checked_out = TRUE;
@@ -784,6 +806,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
entry_t *entry;
ike_sa_id_t *ike_sa_id;
host_t *other;
+ identification_t *my_id, *other_id;
ike_sa_id = ike_sa->get_id(ike_sa);
@@ -806,6 +829,21 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
DESTROY_IF(entry->other);
entry->other = other->clone(other);
}
+ /* apply identities for diplicate test */
+ my_id = ike_sa->get_my_id(ike_sa);
+ other_id = ike_sa->get_other_id(ike_sa);
+ if (!entry->my_id ||
+ entry->my_id->get_type(entry->my_id) == ID_ANY)
+ {
+ DESTROY_IF(entry->my_id);
+ entry->my_id = my_id->clone(my_id);
+ }
+ if (!entry->other_id ||
+ entry->other_id->get_type(entry->other_id) == ID_ANY)
+ {
+ DESTROY_IF(entry->other_id);
+ entry->other_id = other_id->clone(other_id);
+ }
DBG2(DBG_MGR, "check-in of IKE_SA successful.");
pthread_cond_signal(&(entry->condvar));
retval = SUCCESS;
@@ -1009,6 +1047,8 @@ ike_sa_manager_t *ike_sa_manager_create()
}
this->ike_sa_list = linked_list_create();
pthread_mutex_init(&this->mutex, NULL);
+ this->reuse_ikesa = lib->settings->get_bool(lib->settings,
+ "charon.reuse_ikesa", TRUE);
return &this->public;
}
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index e453fff00..25089477b 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: task_manager.c 3666 2008-03-26 18:40:19Z tobias $
+ * $Id: task_manager.c 4320 2008-09-02 14:02:40Z martin $
*/
#include "task_manager.h"
@@ -159,22 +159,22 @@ static void flush(private_task_manager_t *this)
switch (task->get_type(task))
{
case IKE_AUTH:
- SIG(IKE_UP_FAILED, "establishing IKE_SA failed");
+ SIG_IKE(UP_FAILED, "establishing IKE_SA failed");
break;
case IKE_DELETE:
- SIG(IKE_DOWN_FAILED, "IKE_SA deleted");
+ SIG_IKE(DOWN_FAILED, "IKE_SA deleted");
break;
case IKE_REKEY:
- SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed");
+ SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed");
break;
case CHILD_CREATE:
- SIG(CHILD_UP_FAILED, "establishing CHILD_SA failed");
+ SIG_CHD(UP_FAILED, NULL, "establishing CHILD_SA failed");
break;
case CHILD_DELETE:
- SIG(CHILD_DOWN_FAILED, "deleting CHILD_SA failed");
+ SIG_CHD(DOWN_FAILED, NULL, "deleting CHILD_SA failed");
break;
case CHILD_REKEY:
- SIG(IKE_REKEY_FAILED, "rekeying CHILD_SA failed");
+ SIG_IKE(REKEY_FAILED, "rekeying CHILD_SA failed");
break;
default:
break;
@@ -775,6 +775,8 @@ static status_t process_request(private_task_manager_t *this,
case UNACCEPTABLE_ADDRESSES:
case UNEXPECTED_NAT_DETECTED:
case COOKIE2:
+ case NAT_DETECTION_SOURCE_IP:
+ case NAT_DETECTION_DESTINATION_IP:
task = (task_t*)ike_mobike_create(
this->ike_sa, FALSE);
break;
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index 4638da03e..bddca621b 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_create.c 3920 2008-05-08 16:19:11Z tobias $
+ * $Id: child_create.c 4358 2008-09-25 13:56:23Z tobias $
*/
#include "child_create.h"
@@ -26,6 +26,7 @@
#include <encoding/payloads/ts_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/notify_payload.h>
+#include <processing/jobs/delete_ike_sa_job.h>
typedef struct private_child_create_t private_child_create_t;
@@ -98,7 +99,7 @@ struct private_child_create_t {
/**
* mode the new CHILD_SA uses (transport/tunnel/beet)
*/
- mode_t mode;
+ ipsec_mode_t mode;
/**
* IPComp transform to use
@@ -198,12 +199,12 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
if (this->proposals == NULL)
{
- SIG(CHILD_UP_FAILED, "SA payload missing in message");
+ SIG_CHD(UP_FAILED, this->child_sa, "SA payload missing in message");
return FAILED;
}
if (this->tsi == NULL || this->tsr == NULL)
{
- SIG(CHILD_UP_FAILED, "TS payloads missing in message");
+ SIG_CHD(UP_FAILED, this->child_sa, "TS payloads missing in message");
return NOT_FOUND;
}
@@ -231,7 +232,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
no_dh);
if (this->proposal == NULL)
{
- SIG(CHILD_UP_FAILED, "no acceptable proposal found");
+ SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
return FAILED;
}
@@ -242,15 +243,15 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
{
- SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N",
- diffie_hellman_group_names, this->dh_group,
- diffie_hellman_group_names, group);
+ SIG_CHD(UP_FAILED, this->child_sa, "DH group %N inacceptable, "
+ "requesting %N", diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
this->dh_group = group;
return INVALID_ARG;
}
else
{
- SIG(CHILD_UP_FAILED, "no acceptable proposal found");
+ SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
return FAILED;
}
}
@@ -278,7 +279,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
- SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
+ SIG_CHD(UP_FAILED, this->child_sa, "no acceptable traffic selectors found");
return NOT_FOUND;
}
@@ -330,7 +331,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
{
- SIG(CHILD_UP_FAILED, "DH exchange incomplete");
+ SIG_CHD(UP_FAILED, this->child_sa, "DH exchange incomplete");
return FAILED;
}
DBG3(DBG_IKE, "DH secret %B", &secret);
@@ -340,7 +341,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
seed = chunk_cata("cc", nonce_i, nonce_r);
}
- prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
if (this->ipcomp != IPCOMP_NONE)
{
@@ -348,6 +348,16 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
this->other_cpi);
}
+ status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
+ this->mode, this->proposal->get_protocol(this->proposal));
+ if (status != SUCCESS)
+ {
+ SIG_CHD(UP_FAILED, this->child_sa,
+ "unable to install IPsec policies (SPD) in kernel");
+ return NOT_FOUND;
+ }
+
+ prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
if (this->initiator)
{
status = this->child_sa->update(this->child_sa, this->proposal,
@@ -362,18 +372,10 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
if (status != SUCCESS)
{
- SIG(CHILD_UP_FAILED, "unable to install IPsec SA (SAD) in kernel");
+ SIG_CHD(UP_FAILED, this->child_sa,
+ "unable to install IPsec SA (SAD) in kernel");
return FAILED;
}
-
- status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
- this->mode);
-
- if (status != SUCCESS)
- {
- SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
- return NOT_FOUND;
- }
/* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
@@ -440,29 +442,30 @@ static void build_payloads(private_child_create_t *this, message_t *message)
/**
* Adds an IPCOMP_SUPPORTED notify to the message, if possible
*/
-static void build_ipcomp_supported_notify(private_child_create_t *this, message_t *message)
+static void build_ipcomp_supported_notify(private_child_create_t *this,
+ message_t *message)
{
+ u_int16_t cpi;
+ u_int8_t tid;
+
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
{
- DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, IPComp is disabled");
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
+ "IPComp disabled");
this->ipcomp = IPCOMP_NONE;
return;
}
- u_int16_t cpi = this->child_sa->get_my_cpi(this->child_sa);
+ cpi = this->child_sa->allocate_cpi(this->child_sa);
+ tid = this->ipcomp;
if (cpi)
{
- chunk_t cpi_chunk, tid_chunk, data;
- u_int8_t tid = this->ipcomp;
- cpi_chunk = chunk_from_thing(cpi);
- tid_chunk = chunk_from_thing(tid);
- data = chunk_cat("cc", cpi_chunk, tid_chunk);
- message->add_notify(message, FALSE, IPCOMP_SUPPORTED, data);
- chunk_free(&data);
+ message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
+ chunk_cata("cc", chunk_from_thing(cpi), chunk_from_thing(tid)));
}
else
{
- DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp is disabled");
+ DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
this->ipcomp = IPCOMP_NONE;
}
}
@@ -587,7 +590,16 @@ static status_t build_i(private_child_create_t *this, message_t *message)
break;
}
- SIG(CHILD_UP_START, "establishing CHILD_SA");
+ if (this->reqid)
+ {
+ SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{%d}",
+ this->config->get_name(this->config), this->reqid);
+ }
+ else
+ {
+ SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s",
+ this->config->get_name(this->config));
+ }
/* reuse virtual IP if we already have one */
me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
@@ -638,7 +650,8 @@ static status_t build_i(private_child_create_t *this, message_t *message)
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
{
- SIG(CHILD_UP_FAILED, "unable to allocate SPIs from kernel");
+ SIG_CHD(UP_FAILED, this->child_sa,
+ "unable to allocate SPIs from kernel");
return FAILED;
}
@@ -720,10 +733,31 @@ static status_t process_r(private_child_create_t *this, message_t *message)
}
/**
+ * handle CHILD_SA setup failure
+ */
+static void handle_child_sa_failure(private_child_create_t *this,
+ message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_AUTH &&
+ lib->settings->get_bool(lib->settings,
+ "charon.close_ike_on_child_failure", FALSE))
+ {
+ /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
+ * first */
+ DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)
+ delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
+ 100);
+ }
+}
+
+/**
* Implementation of task_t.build for responder
*/
static status_t build_r(private_child_create_t *this, message_t *message)
{
+ payload_t *payload;
+ iterator_t *iterator;
bool no_dh = TRUE;
switch (message->get_exchange_type(message))
@@ -733,7 +767,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
case CREATE_CHILD_SA:
if (generate_nonce(&this->my_nonce) != SUCCESS)
{
- message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
+ chunk_empty);
return SUCCESS;
}
no_dh = FALSE;
@@ -750,19 +785,47 @@ static status_t build_r(private_child_create_t *this, message_t *message)
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
{
- SIG(CHILD_UP_FAILED, "unable to create CHILD_SA while rekeying IKE_SA");
+ SIG_CHD(UP_FAILED, NULL,
+ "unable to create CHILD_SA while rekeying IKE_SA");
message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
return SUCCESS;
}
if (this->config == NULL)
{
- SIG(CHILD_UP_FAILED, "traffic selectors %#R=== %#R inacceptable",
+ SIG_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable",
this->tsr, this->tsi);
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
+ handle_child_sa_failure(this, message);
return SUCCESS;
}
+ /* check if ike_config_t included non-critical error notifies */
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ switch (notify->get_notify_type(notify))
+ {
+ case INTERNAL_ADDRESS_FAILURE:
+ case FAILED_CP_REQUIRED:
+ {
+ SIG_CHD(UP_FAILED, NULL, "configuration payload negotation "
+ "failed, no CHILD_SA built");
+ iterator->destroy(iterator);
+ handle_child_sa_failure(this, message);
+ return SUCCESS;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
this->child_sa = child_sa_create(
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa),
@@ -770,14 +833,16 @@ static status_t build_r(private_child_create_t *this, message_t *message)
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
- if (this->config->use_ipcomp(this->config) && this->ipcomp_received != IPCOMP_NONE)
+ if (this->config->use_ipcomp(this->config) &&
+ this->ipcomp_received != IPCOMP_NONE)
{
this->ipcomp = this->ipcomp_received;
build_ipcomp_supported_notify(this, message);
}
else if (this->ipcomp_received != IPCOMP_NONE)
{
- DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify but IPComp is disabled, ignoring");
+ DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
+ notify_type_names, IPCOMP_SUPPORTED);
}
switch (select_and_install(this, no_dh))
@@ -786,24 +851,33 @@ static status_t build_r(private_child_create_t *this, message_t *message)
break;
case NOT_FOUND:
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
+ handle_child_sa_failure(this, message);
return SUCCESS;
case INVALID_ARG:
{
u_int16_t group = htons(this->dh_group);
message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
chunk_from_thing(group));
+ handle_child_sa_failure(this, message);
return SUCCESS;
}
case FAILED:
default:
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ handle_child_sa_failure(this, message);
return SUCCESS;
}
build_payloads(this, message);
- SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully",
- this->child_sa->get_name(this->child_sa));
+ SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
return SUCCESS;
}
@@ -855,9 +929,10 @@ static status_t process_i(private_child_create_t *this, message_t *message)
case TS_UNACCEPTABLE:
case INVALID_SELECTORS:
{
- SIG(CHILD_UP_FAILED, "received %N notify, no CHILD_SA built",
- notify_type_names, type);
+ SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, "
+ "no CHILD_SA built", notify_type_names, type);
iterator->destroy(iterator);
+ handle_child_sa_failure(this, message);
/* an error in CHILD_SA creation is not critical */
return SUCCESS;
}
@@ -888,8 +963,9 @@ static status_t process_i(private_child_create_t *this, message_t *message)
if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
{
- SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify but we did not "
- "send one previously, no CHILD_SA built");
+ SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
+ " but we did not send one previously, no CHILD_SA built");
+ handle_child_sa_failure(this, message);
return SUCCESS;
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
@@ -900,15 +976,26 @@ static status_t process_i(private_child_create_t *this, message_t *message)
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
{
- SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify for a transform "
- "we did not propose, no CHILD_SA built");
+ SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
+ " for a transform we did not propose, no CHILD_SA built");
+ handle_child_sa_failure(this, message);
return SUCCESS;
}
if (select_and_install(this, no_dh) == SUCCESS)
{
- SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully",
- this->child_sa->get_name(this->child_sa));
+ SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+ }
+ else
+ {
+ handle_child_sa_failure(this, message);
}
return SUCCESS;
}
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index 4156f9704..a3c74dc90 100644
--- a/src/charon/sa/tasks/child_delete.c
+++ b/src/charon/sa/tasks/child_delete.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_delete.c 3802 2008-04-14 08:17:18Z martin $
+ * $Id: child_delete.c 4366 2008-10-03 16:01:14Z martin $
*/
#include "child_delete.h"
@@ -44,6 +44,11 @@ struct private_child_delete_t {
bool initiator;
/**
+ * wheter to enforce delete action policy
+ */
+ bool check_delete_action;
+
+ /**
* CHILD_SAs which get deleted
*/
linked_list_t *child_sas;
@@ -54,16 +59,17 @@ struct private_child_delete_t {
*/
static void build_payloads(private_child_delete_t *this, message_t *message)
{
- iterator_t *iterator;
delete_payload_t *ah = NULL, *esp = NULL;
- u_int32_t spi;
+ iterator_t *iterator;
child_sa_t *child_sa;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- spi = child_sa->get_spi(child_sa, TRUE);
- switch (child_sa->get_protocol(child_sa))
+ protocol_id_t protocol = child_sa->get_protocol(child_sa);
+ u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
+
+ switch (protocol)
{
case PROTO_ESP:
if (esp == NULL)
@@ -72,6 +78,8 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
message->add_payload(message, (payload_t*)esp);
}
esp->add_spi(esp, spi);
+ DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(spi));
break;
case PROTO_AH:
if (ah == NULL)
@@ -80,6 +88,8 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
message->add_payload(message, (payload_t*)ah);
}
ah->add_spi(ah, spi);
+ DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
+ protocol_id_names, protocol, ntohl(spi));
break;
default:
break;
@@ -119,11 +129,11 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
*spi, FALSE);
if (child_sa == NULL)
{
- DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI 0x%x, "
+ DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, "
"but no such SA", protocol_id_names, protocol, ntohl(*spi));
continue;
}
- DBG2(DBG_IKE, "received DELETE for %N CHILD_SA with SPI 0x%x",
+ DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
protocol_id_names, protocol, ntohl(*spi));
switch (child_sa->get_state(child_sa))
@@ -139,6 +149,11 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
protocol, *spi);
continue;
}
+ case CHILD_INSTALLED:
+ if (!this->initiator)
+ { /* reestablish installed children if required */
+ this->check_delete_action = TRUE;
+ }
default:
break;
}
@@ -171,7 +186,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
- if (!this->initiator)
+ if (this->check_delete_action)
{ /* enforce child_cfg policy if deleted passively */
switch (child_cfg->get_close_action(child_cfg))
{
@@ -207,9 +222,14 @@ static void log_children(private_child_delete_t *this)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- SIG(CHILD_DOWN_START, "closing CHILD_SA %#R=== %#R",
- child_sa->get_traffic_selectors(child_sa, TRUE),
- child_sa->get_traffic_selectors(child_sa, FALSE));
+ SIG_CHD(DOWN_START, child_sa, "closing CHILD_SA %s{%d} "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)),
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
}
iterator->destroy(iterator);
}
@@ -234,7 +254,7 @@ static status_t process_i(private_child_delete_t *this, message_t *message)
this->child_sas = linked_list_create();
process_payloads(this, message);
- SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
+ SIG_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
@@ -258,7 +278,7 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
{
build_payloads(this, message);
}
- SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
+ SIG_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
@@ -285,6 +305,7 @@ static child_sa_t* get_child(private_child_delete_t *this)
*/
static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa)
{
+ this->check_delete_action = FALSE;
this->ike_sa = ike_sa;
this->child_sas->destroy(this->child_sas);
@@ -313,6 +334,7 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa)
this->public.task.destroy = (void(*)(task_t*))destroy;
this->ike_sa = ike_sa;
+ this->check_delete_action = FALSE;
this->child_sas = linked_list_create();
if (child_sa != NULL)
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
index fd5012ee6..51f37f1b0 100644
--- a/src/charon/sa/tasks/ike_auth.c
+++ b/src/charon/sa/tasks/ike_auth.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details
*
- * $Id: ike_auth.c 4051 2008-06-10 09:08:27Z tobias $
+ * $Id: ike_auth.c 4276 2008-08-22 10:44:51Z martin $
*/
#include "ike_auth.h"
@@ -29,7 +29,6 @@
#include <sa/authenticators/eap_authenticator.h>
-
typedef struct private_ike_auth_t private_ike_auth_t;
/**
@@ -151,6 +150,44 @@ static bool check_uniqueness(private_ike_auth_t *this)
}
/**
+ * get the authentication class of a config
+ */
+auth_class_t get_auth_class(peer_cfg_t *config)
+{
+ auth_class_t *class;
+ auth_info_t *auth_info;
+
+ auth_info = config->get_auth(config);
+ if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
+ {
+ return *class;
+ }
+ /* fallback to pubkey authentication */
+ return AUTH_CLASS_PUBKEY;
+}
+
+/**
+ * get the eap type/vendor
+ */
+static eap_type_t get_eap_type(peer_cfg_t *config, u_int32_t *vendor)
+{
+ auth_info_t *auth_info;
+ u_int *ptr;
+
+ *vendor = 0;
+ auth_info = config->get_auth(config);
+ if (auth_info->get_item(auth_info, AUTHN_EAP_VENDOR, (void**)&ptr))
+ {
+ *vendor = *ptr;
+ }
+ if (auth_info->get_item(auth_info, AUTHN_EAP_TYPE, (void**)&ptr))
+ {
+ return *ptr;
+ }
+ return EAP_NAK;
+}
+
+/**
* build the AUTH payload
*/
static status_t build_auth(private_ike_auth_t *this, message_t *message)
@@ -158,23 +195,21 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
authenticator_t *auth;
auth_payload_t *auth_payload;
peer_cfg_t *config;
- config_auth_method_t method;
status_t status;
/* create own authenticator and add auth payload */
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!config)
{
- SIG(IKE_UP_FAILED, "unable to authenticate, no peer config found");
+ SIG_IKE(UP_FAILED, "unable to authenticate, no peer config found");
return FAILED;
}
- method = config->get_auth_method(config);
- auth = authenticator_create(this->ike_sa, method);
+ auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
if (auth == NULL)
{
- SIG(IKE_UP_FAILED, "configured authentication method %N not supported",
- config_auth_method_names, method);
+ SIG_IKE(UP_FAILED, "configured authentication class %N not supported",
+ auth_class_names, get_auth_class(config));
return FAILED;
}
@@ -183,7 +218,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
auth->destroy(auth);
if (status != SUCCESS)
{
- SIG(IKE_UP_FAILED, "generating authentication data failed");
+ SIG_IKE(UP_FAILED, "generating authentication data failed");
return FAILED;
}
message->add_payload(message, (payload_t*)auth_payload);
@@ -208,7 +243,7 @@ static status_t build_id(private_ike_auth_t *this, message_t *message)
me = config->get_my_id(config);
if (me->contains_wildcards(me))
{
- SIG(IKE_UP_FAILED, "negotiation of own ID failed");
+ SIG_IKE(UP_FAILED, "negotiation of own ID failed");
return FAILED;
}
this->ike_sa->set_my_id(this->ike_sa, me->clone(me));
@@ -245,11 +280,11 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
}
auth_method = auth_payload->get_auth_method(auth_payload);
- auth = authenticator_create_from_auth_payload(this->ike_sa, auth_payload);
-
+ auth = authenticator_create_from_method(this->ike_sa,
+ auth_payload->get_auth_method(auth_payload));
if (auth == NULL)
{
- SIG(IKE_UP_FAILED, "authentication method %N used by '%D' not "
+ SIG_IKE(UP_FAILED, "authentication method %N used by '%D' not "
"supported", auth_method_names, auth_method,
this->ike_sa->get_other_id(this->ike_sa));
return NOT_SUPPORTED;
@@ -259,7 +294,7 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
auth->destroy(auth);
if (status != SUCCESS)
{
- SIG(IKE_UP_FAILED, "authentication of '%D' with %N failed",
+ SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
auth_method_names, auth_method);
return FAILED;
@@ -280,7 +315,7 @@ static status_t process_id(private_ike_auth_t *this, message_t *message)
if ((this->initiator && idr == NULL) || (!this->initiator && idi == NULL))
{
- SIG(IKE_UP_FAILED, "ID payload missing in message");
+ SIG_IKE(UP_FAILED, "ID payload missing in message");
return FAILED;
}
@@ -290,7 +325,7 @@ static status_t process_id(private_ike_auth_t *this, message_t *message)
req = this->ike_sa->get_other_id(this->ike_sa);
if (!id->matches(id, req))
{
- SIG(IKE_UP_FAILED, "peer ID '%D' unacceptable, '%D' required", id, req);
+ SIG_IKE(UP_FAILED, "peer ID '%D' unacceptable, '%D' required", id, req);
id->destroy(id);
return FAILED;
}
@@ -367,7 +402,7 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
if (auth->build(auth, this->my_packet->get_data(this->my_packet),
this->other_nonce, &auth_payload) != SUCCESS)
{
- SIG(IKE_UP_FAILED, "generating authentication data failed");
+ SIG_IKE(UP_FAILED, "generating authentication data failed");
if (!this->initiator)
{
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -378,12 +413,13 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
if (!this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -412,9 +448,9 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
if (!this->peer_authenticated)
{
- SIG(IKE_UP_FAILED, "authentication of '%D' with %N failed",
+ SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
- auth_method_names, AUTH_EAP);
+ auth_class_names, AUTH_CLASS_EAP);
if (this->initiator)
{
return FAILED;
@@ -424,12 +460,13 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
if (this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -445,7 +482,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
eap = (eap_payload_t*)message->get_payload(message, EXTENSIBLE_AUTHENTICATION);
if (eap == NULL)
{
- SIG(IKE_UP_FAILED, "EAP payload missing");
+ SIG_IKE(UP_FAILED, "EAP payload missing");
return FAILED;
}
switch (this->eap_auth->process(this->eap_auth, eap, &eap))
@@ -461,7 +498,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
default:
this->eap_payload = NULL;
- SIG(IKE_UP_FAILED, "failed to authenticate against '%D' using EAP",
+ SIG_IKE(UP_FAILED, "failed to authenticate against '%D' using EAP",
this->ike_sa->get_other_id(this->ike_sa));
return FAILED;
}
@@ -496,7 +533,7 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
if (this->eap_payload == NULL)
{
- SIG(IKE_UP_FAILED, "EAP payload missing");
+ SIG_IKE(UP_FAILED, "EAP payload missing");
return FAILED;
}
@@ -511,9 +548,9 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
break;
default:
- SIG(IKE_UP_FAILED, "authentication of '%D' with %N failed",
+ SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
- auth_method_names, AUTH_EAP);
+ auth_class_names, AUTH_CLASS_EAP);
status = FAILED;
break;
}
@@ -539,7 +576,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
}
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (config->get_auth_method(config) == CONF_AUTH_EAP)
+ if (get_auth_class(config) == AUTH_CLASS_EAP)
{
this->eap_auth = eap_authenticator_create(this->ike_sa);
}
@@ -579,13 +616,14 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
case NOT_FOUND:
/* use EAP if no AUTH payload found */
this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE);
- this->eap_auth = eap_authenticator_create(this->ike_sa);
break;
default:
return NEED_MORE;
}
config = charon->backends->get_peer_cfg(charon->backends,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_other_auth(this->ike_sa));
@@ -594,7 +632,10 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
this->ike_sa->set_peer_cfg(this->ike_sa, config);
config->destroy(config);
}
-
+ if (!this->peer_authenticated)
+ {
+ this->eap_auth = eap_authenticator_create(this->ike_sa);
+ }
return NEED_MORE;
}
@@ -624,7 +665,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config == NULL)
{
- SIG(IKE_UP_FAILED, "no matching config found for '%D'...'%D'",
+ SIG_IKE(UP_FAILED, "no matching config found for '%D'...'%D'",
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -648,23 +689,24 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
if (this->peer_authenticated)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
/* initiate EAP authenitcation */
- eap_type = config->get_eap_type(config, &eap_vendor);
+ eap_type = get_eap_type(config, &eap_vendor);
status = this->eap_auth->initiate(this->eap_auth, eap_type,
eap_vendor, &eap_payload);
message->add_payload(message, (payload_t*)eap_payload);
if (status != NEED_MORE)
{
- SIG(IKE_UP_FAILED, "unable to initiate EAP authentication");
+ SIG_IKE(UP_FAILED, "unable to initiate EAP authentication");
return FAILED;
}
@@ -724,7 +766,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
{
if (type < 16383)
{
- SIG(IKE_UP_FAILED, "received %N notify error",
+ SIG_IKE(UP_FAILED, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -756,17 +798,18 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
auth = this->ike_sa->get_other_auth(this->ike_sa);
if (!auth->complies(auth, config->get_auth(config)))
{
- SIG(IKE_UP_FAILED, "authorization of '%D' for config %s failed",
+ SIG_IKE(UP_FAILED, "authorization of '%D' for config %s failed",
this->ike_sa->get_other_id(this->ike_sa), config->get_name(config));
return FAILED;
}
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa));
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c
index 184868b28..cb533236e 100644
--- a/src/charon/sa/tasks/ike_cert_post.c
+++ b/src/charon/sa/tasks/ike_cert_post.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_cert_post.c 4051 2008-06-10 09:08:27Z tobias $
+ * $Id: ike_cert_post.c 4276 2008-08-22 10:44:51Z martin $
*/
#include "ike_cert_post.h"
@@ -98,6 +98,11 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certifi
}
/**
+ * from ike_auth.c
+ */
+auth_class_t get_auth_class(peer_cfg_t *config);
+
+/**
* add certificates to message
*/
static void build_certs(private_ike_cert_post_t *this, message_t *message)
@@ -105,7 +110,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
peer_cfg_t *peer_cfg;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == CONF_AUTH_PUBKEY)
+ if (peer_cfg && get_auth_class(peer_cfg) == AUTH_CLASS_PUBKEY)
{
switch (peer_cfg->get_cert_policy(peer_cfg))
{
diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c
index 3568a214e..353b76a22 100644
--- a/src/charon/sa/tasks/ike_cert_pre.c
+++ b/src/charon/sa/tasks/ike_cert_pre.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_cert_pre.c 3852 2008-04-18 21:27:08Z andreas $
+ * $Id: ike_cert_pre.c 4285 2008-08-26 05:15:34Z andreas $
*/
#include "ike_cert_pre.h"
@@ -320,11 +320,10 @@ static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
enumerator_t *enumerator;
certificate_t *cert;
- auth_info_t *auth;
bool restricted = FALSE;
- auth_item_t item;
certreq_payload_t *x509_req = NULL;
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
@@ -332,19 +331,43 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
return;
}
- auth = this->ike_sa->get_other_auth(this->ike_sa);
/* check if we require a specific CA for that peer */
- enumerator = auth->create_item_enumerator(auth);
- while (enumerator->enumerate(enumerator, &item, &cert))
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg)
{
- if (item == AUTHN_CA_CERT)
+ void *ptr;
+ identification_t *id;
+ auth_item_t item;
+ auth_info_t *auth = peer_cfg->get_auth(peer_cfg);
+ enumerator_t *auth_enumerator = auth->create_item_enumerator(auth);
+
+ while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
{
- restricted = TRUE;
- add_certreq_payload(message, &x509_req, cert);
+ switch (item)
+ {
+ case AUTHZ_CA_CERT:
+ cert = (certificate_t *)ptr;
+ add_certreq_payload(message, &x509_req, cert);
+ restricted = TRUE;
+ break;
+ case AUTHZ_CA_CERT_NAME:
+ id = (identification_t *)ptr;
+ enumerator = charon->credentials->create_cert_enumerator(
+ charon->credentials, CERT_ANY, KEY_ANY, id, TRUE);
+ while (enumerator->enumerate(enumerator, &cert, TRUE))
+ {
+ add_certreq_payload(message, &x509_req, cert);
+ restricted = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ break;
+ default:
+ break;
+ }
}
+ auth_enumerator->destroy(auth_enumerator);
}
- enumerator->destroy(enumerator);
if (!restricted)
{
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index c31e62750..e89f381d3 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_config.c 3800 2008-04-14 07:18:16Z martin $
+ * $Id: ike_config.c 4129 2008-07-01 06:36:52Z martin $
*/
#include "ike_config.h"
@@ -315,7 +315,10 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
}
if (ip == NULL)
{
- DBG1(DBG_IKE, "not assigning a virtual IP to peer");
+ DBG1(DBG_IKE, "no virtual IP found, sending %N",
+ notify_type_names, INTERNAL_ADDRESS_FAILURE);
+ message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
+ chunk_empty);
return SUCCESS;
}
DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip);
diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c
index aa7950ef7..295f908cb 100644
--- a/src/charon/sa/tasks/ike_delete.c
+++ b/src/charon/sa/tasks/ike_delete.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_delete.c 3802 2008-04-14 08:17:18Z martin $
+ * $Id: ike_delete.c 4211 2008-07-23 18:46:34Z andreas $
*/
#include "ike_delete.h"
@@ -56,11 +56,22 @@ static status_t build_i(private_ike_delete_t *this, message_t *message)
{
delete_payload_t *delete_payload;
+ SIG_IKE(DOWN_START, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
delete_payload = delete_payload_create(PROTO_IKE);
message->add_payload(message, (payload_t*)delete_payload);
-
this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
-
+
+ DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+
return NEED_MORE;
}
@@ -74,16 +85,26 @@ static status_t process_i(private_ike_delete_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator
+ * Implementation of task_t.process for responder
*/
static status_t process_r(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 */
+ DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+ SIG_IKE(DOWN_START, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
switch (this->ike_sa->get_state(this->ike_sa))
{
case IKE_ESTABLISHED:
- DBG1(DBG_IKE, "deleting IKE_SA on request");
this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
this->ike_sa->reestablish(this->ike_sa);
break;
@@ -102,9 +123,11 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
*/
static status_t build_r(private_ike_delete_t *this, message_t *message)
{
+ SIG_IKE(DOWN_SUCCESS, "IKE_SA deleted");
+
if (this->simultaneous)
{
- /* wait for peers response for our delete request, but set a timeout */
+ /* wait for peer's response for our delete request, but set a timeout */
return SUCCESS;
}
/* completed, delete IKE_SA by returning FAILED */
diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c
index 7def3a556..609b37a39 100644
--- a/src/charon/sa/tasks/ike_init.c
+++ b/src/charon/sa/tasks/ike_init.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_init.c 4086 2008-06-22 11:24:33Z andreas $
+ * $Id: ike_init.c 4206 2008-07-22 17:10:10Z andreas $
*/
#include "ike_init.h"
@@ -26,6 +26,7 @@
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/ke_payload.h>
#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/vendor_id_payload.h>
/** maximum retries to do with cookies/other dh groups */
#define MAX_RETRIES 5
@@ -203,9 +204,17 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
case NONCE:
{
nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
+
this->other_nonce = nonce_payload->get_nonce(nonce_payload);
break;
}
+ case VENDOR_ID:
+ {
+ vendor_id_payload_t *vendor_id = (vendor_id_payload_t*)payload;
+ chunk_t vid = vendor_id->get_data(vendor_id);
+
+ DBG1(DBG_ENC, "received vendor id: %#B", &vid);
+ }
default:
break;
}
@@ -221,14 +230,15 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
- SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H",
+ SIG_IKE(UP_START, "initiating IKE_SA %s[%d] to %H",
this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
if (this->retry++ >= MAX_RETRIES)
{
- SIG(IKE_UP_FAILED, "giving up after %d retries", MAX_RETRIES);
+ SIG_IKE(UP_FAILED, "giving up after %d retries", MAX_RETRIES);
return FAILED;
}
@@ -239,7 +249,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
if (this->dh == NULL)
{
- SIG(IKE_UP_FAILED, "configured DH group %N not supported",
+ SIG_IKE(UP_FAILED, "configured DH group %N not supported",
diffie_hellman_group_names, this->dh_group);
return FAILED;
}
@@ -251,7 +261,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
{
- SIG(IKE_UP_FAILED, "error generating nonce");
+ SIG_IKE(UP_FAILED, "error generating nonce");
return FAILED;
}
rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
@@ -286,7 +296,7 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
- SIG(IKE_UP_START, "%H is initiating an IKE_SA",
+ SIG_IKE(UP_START, "%H is initiating an IKE_SA",
message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
@@ -366,7 +376,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG(IKE_UP_FAILED, "received proposals inacceptable");
+ SIG_IKE(UP_FAILED, "received proposals inacceptable");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
@@ -380,7 +390,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
{
- SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N",
+ SIG_CHD(UP_FAILED, NULL, "DH group %N inacceptable, requesting %N",
diffie_hellman_group_names, this->dh_group,
diffie_hellman_group_names, group);
this->dh_group = group;
@@ -390,7 +400,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
}
else
{
- SIG(IKE_UP_FAILED, "no acceptable proposal found");
+ SIG_IKE(UP_FAILED, "no acceptable proposal found");
}
return FAILED;
}
@@ -420,7 +430,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
}
if (status != SUCCESS)
{
- SIG(IKE_UP_FAILED, "key derivation failed");
+ SIG_IKE(UP_FAILED, "key derivation failed");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
@@ -495,7 +505,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
{
if (type < 16383)
{
- SIG(IKE_UP_FAILED, "received %N notify error",
+ SIG_IKE(UP_FAILED, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -515,7 +525,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG(IKE_UP_FAILED, "peer's proposal selection invalid");
+ SIG_IKE(UP_FAILED, "peer's proposal selection invalid");
return FAILED;
}
@@ -523,7 +533,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
!this->proposal->has_dh_group(this->proposal, this->dh_group) ||
this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
{
- SIG(IKE_UP_FAILED, "peer's DH group selection invalid");
+ SIG_IKE(UP_FAILED, "peer's DH group selection invalid");
return FAILED;
}
@@ -552,7 +562,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
}
if (status != SUCCESS)
{
- SIG(IKE_UP_FAILED, "key derivation failed");
+ SIG_IKE(UP_FAILED, "key derivation failed");
return FAILED;
}
diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c
index 2d7c64d70..a203dee58 100644
--- a/src/charon/sa/tasks/ike_me.c
+++ b/src/charon/sa/tasks/ike_me.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_me.c 3806 2008-04-15 05:56:35Z martin $
+ * $Id: ike_me.c 4355 2008-09-25 07:56:58Z tobias $
*/
#include "ike_me.h"
@@ -128,7 +128,7 @@ static void add_endpoints_to_message(message_t *message, linked_list_t *endpoint
*/
static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
host_t *addr, *host;
u_int16_t port;
@@ -136,9 +136,9 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
host = this->ike_sa->get_my_host(this->ike_sa);
port = host->get_port(host);
- iterator = charon->kernel_interface->create_address_iterator(
- charon->kernel_interface);
- while (iterator->iterate(iterator, (void**)&addr))
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&addr))
{
host = addr->clone(addr);
host->set_port(host, port);
@@ -148,7 +148,7 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
host->destroy(host);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
if (host)
@@ -461,7 +461,8 @@ static status_t process_i(private_ike_me_t *this, message_t *message)
this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint->clone(endpoint));
}
/* FIXME: what if it failed? e.g. AUTH failure */
- SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
+ SIG_CHD(UP_SUCCESS, NULL, "established mediation connection "
+ "without CHILD_SA successfully");
break;
}
@@ -641,7 +642,8 @@ static status_t build_r_ms(private_ike_me_t *this, message_t *message)
/* FIXME: we actually must delete any existing IKE_SAs with the same remote id */
this->ike_sa->act_as_mediation_server(this->ike_sa);
- SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
+ SIG_CHD(UP_SUCCESS, NULL, "established mediation connection "
+ "without CHILD_SA successfully");
break;
}
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index 23c68b9e9..f6ee3f6ad 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_mobike.c 4006 2008-05-23 15:43:42Z martin $
+ * $Id: ike_mobike.c 4394 2008-10-09 08:25:11Z martin $
*/
#include "ike_mobike.h"
@@ -117,8 +117,19 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
{
case MOBIKE_SUPPORTED:
{
- DBG1(DBG_IKE, "peer supports MOBIKE");
- this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (!this->initiator &&
+ peer_cfg && !peer_cfg->use_mobike(peer_cfg))
+ {
+ DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "peer supports MOBIKE");
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
+ }
break;
}
case COOKIE2:
@@ -177,15 +188,15 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
*/
static void build_address_list(private_ike_mobike_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
host_t *host, *me;
notify_type_t type;
bool additional = FALSE;
me = this->ike_sa->get_my_host(this->ike_sa);
- iterator = charon->kernel_interface->create_address_iterator(
- charon->kernel_interface);
- while (iterator->iterate(iterator, (void**)&host))
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&host))
{
if (me->ip_equals(me, host))
{ /* "ADDITIONAL" means do not include IKE_SAs host */
@@ -209,7 +220,7 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
{
message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -266,7 +277,7 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet)
other_old = this->ike_sa->get_other_host(this->ike_sa);
me = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, other_old);
+ charon->kernel_interface, other_old, NULL);
if (me)
{
me->set_port(me, me->ip_equals(me, me_old) ?
@@ -278,7 +289,7 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet)
while (iterator->iterate(iterator, (void**)&other))
{
me = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, other);
+ charon->kernel_interface, other, NULL);
if (me)
{
if (me->get_family(me) != other->get_family(other))
@@ -318,6 +329,24 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message)
}
else if (message->get_exchange_type(message) == INFORMATIONAL)
{
+ host_t *old, *new;
+
+ /* we check if the existing address is still valid */
+ old = message->get_source(message);
+ new = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ message->get_destination(message), old);
+ if (new)
+ {
+ if (!new->ip_equals(new, old))
+ {
+ new->set_port(new, old->get_port(old));
+ message->set_source(message, new);
+ }
+ else
+ {
+ new->destroy(new);
+ }
+ }
if (this->update)
{
message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty);
@@ -423,7 +452,7 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
return SUCCESS;
}
if (this->cookie2.ptr)
- { /* check cookie if we included none */
+ { /* check cookie if we included one */
chunk_t cookie2;
cookie2 = this->cookie2;
@@ -444,6 +473,13 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
if (this->natd)
{
this->natd->task.process(&this->natd->task, message);
+ if (this->natd->has_mapping_changed(this->natd))
+ {
+ /* force an update if mappings have changed */
+ this->update = this->check = TRUE;
+ DBG1(DBG_IKE, "detected changes in NAT mappings, "
+ "initiating MOBIKE update");
+ }
}
if (this->update)
{
@@ -496,6 +532,20 @@ static void roam(private_ike_mobike_t *this, bool address)
}
/**
+ * Implementation of ike_mobike_t.dpd
+ */
+static void dpd(private_ike_mobike_t *this)
+{
+ if (!this->natd)
+ {
+ this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ }
+ this->address = FALSE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+}
+
+/**
* Implementation of ike_mobike_t.is_probing.
*/
static bool is_probing(private_ike_mobike_t *this)
@@ -545,6 +595,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
this->public.roam = (void(*)(ike_mobike_t*,bool))roam;
+ this->public.dpd = (void(*)(ike_mobike_t*))dpd;
this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit;
this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h
index 9dd29970e..f8f094456 100644
--- a/src/charon/sa/tasks/ike_mobike.h
+++ b/src/charon/sa/tasks/ike_mobike.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_mobike.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: ike_mobike.h 4368 2008-10-06 13:37:04Z martin $
*/
/**
@@ -55,6 +55,11 @@ struct ike_mobike_t {
void (*roam)(ike_mobike_t *this, bool address);
/**
+ * Use the task for a DPD check which detects changes in NAT mappings.
+ */
+ void (*dpd)(ike_mobike_t *this);
+
+ /**
* Transmision hook, called by task manager.
*
* The task manager calls this hook whenever it transmits a packet. It
diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c
index 69e5bac26..9e62fcbdf 100644
--- a/src/charon/sa/tasks/ike_natd.c
+++ b/src/charon/sa/tasks/ike_natd.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_natd.c 3806 2008-04-15 05:56:35Z martin $
+ * $Id: ike_natd.c 4386 2008-10-08 08:23:46Z martin $
*/
#include "ike_natd.h"
@@ -72,6 +72,11 @@ struct private_ike_natd_t {
* Have we found a matching destination address NAT hash?
*/
bool dst_matched;
+
+ /**
+ * whether NAT mappings for our NATed address has changed
+ */
+ bool mapping_changed;
};
@@ -192,15 +197,24 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
case NAT_DETECTION_DESTINATION_IP:
{
this->dst_seen = TRUE;
+ hash = notify->get_notification_data(notify);
if (!this->dst_matched)
{
- hash = notify->get_notification_data(notify);
DBG3(DBG_IKE, "received dst_hash %B", &hash);
if (chunk_equals(hash, dst_hash))
{
this->dst_matched = TRUE;
}
}
+ /* RFC4555 says we should also compare against IKE_SA_INIT
+ * NATD payloads, but this does not work: We are running
+ * there at port 500, but use 4500 afterwards... */
+ if (message->get_exchange_type(message) == INFORMATIONAL &&
+ this->initiator && !this->dst_matched)
+ {
+ this->mapping_changed = this->ike_sa->has_mapping_changed(
+ this->ike_sa, hash);
+ }
break;
}
case NAT_DETECTION_SOURCE_IP:
@@ -300,7 +314,7 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
static status_t build_i(private_ike_natd_t *this, message_t *message)
{
notify_payload_t *notify;
- iterator_t *iterator;
+ enumerator_t *enumerator;
host_t *host;
if (this->hasher == NULL)
@@ -327,9 +341,8 @@ static status_t build_i(private_ike_natd_t *this, message_t *message)
}
else
{
- host = charon->kernel_interface->get_source_addr(
- charon->kernel_interface,
- this->ike_sa->get_other_host(this->ike_sa));
+ host = charon->kernel_interface->get_source_addr(charon->kernel_interface,
+ this->ike_sa->get_other_host(this->ike_sa), NULL);
if (host)
{ /* 2. */
host->set_port(host, IKEV2_UDP_PORT);
@@ -339,14 +352,14 @@ static status_t build_i(private_ike_natd_t *this, message_t *message)
}
else
{ /* 3. */
- iterator = charon->kernel_interface->create_address_iterator(
- charon->kernel_interface);
- while (iterator->iterate(iterator, (void**)&host))
+ enumerator = charon->kernel_interface->create_address_enumerator(
+ charon->kernel_interface, FALSE, FALSE);
+ while (enumerator->enumerate(enumerator, (void**)&host))
{
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
message->add_payload(message, (payload_t*)notify);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
}
return NEED_MORE;
@@ -415,6 +428,15 @@ static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa)
this->dst_seen = FALSE;
this->src_matched = FALSE;
this->dst_matched = FALSE;
+ this->mapping_changed = FALSE;
+}
+
+/**
+ * Implementation of ike_natd_t.has_mapping_changed
+ */
+static bool has_mapping_changed(private_ike_natd_t *this)
+{
+ return this->mapping_changed;
}
/**
@@ -448,6 +470,8 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
this->public.task.process = (status_t(*)(task_t*,message_t*))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);
@@ -455,6 +479,7 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
this->dst_seen = FALSE;
this->src_matched = FALSE;
this->dst_matched = FALSE;
+ this->mapping_changed = FALSE;
return &this->public;
}
diff --git a/src/charon/sa/tasks/ike_natd.h b/src/charon/sa/tasks/ike_natd.h
index d78c931d9..7e1e58bc0 100644
--- a/src/charon/sa/tasks/ike_natd.h
+++ b/src/charon/sa/tasks/ike_natd.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_natd.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: ike_natd.h 4368 2008-10-06 13:37:04Z martin $
*/
/**
@@ -38,6 +38,15 @@ struct ike_natd_t {
* Implements the task_t interface
*/
task_t task;
+
+ /**
+ * Check if the NAT mapping has changed for our address.
+ *
+ * MOBIKE uses NAT payloads in DPD to detect changes in the NAT mappings.
+ *
+ * @return TRUE if mappings have changed
+ */
+ bool (*has_mapping_changed)(ike_natd_t *this);
};
/**
diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c
index 854e9359d..b84b2a387 100644
--- a/src/charon/sa/tasks/ike_reauth.c
+++ b/src/charon/sa/tasks/ike_reauth.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_reauth.c 3793 2008-04-11 08:14:48Z martin $
+ * $Id: ike_reauth.c 4211 2008-07-23 18:46:34Z andreas $
*/
#include "ike_reauth.h"
@@ -65,7 +65,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
/* process delete response first */
this->ike_delete->task.process(&this->ike_delete->task, message);
-
+ SIG_IKE(DOWN_SUCCESS, "IKE_SA deleted");
+
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
/* reauthenticate only if we have children */
diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c
index 9c0d1805c..6c4ef4354 100644
--- a/src/charon/sa/tasks/ike_rekey.c
+++ b/src/charon/sa/tasks/ike_rekey.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_rekey.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: ike_rekey.c 4211 2008-07-23 18:46:34Z andreas $
*/
#include "ike_rekey.h"
@@ -69,6 +69,7 @@ struct private_ike_rekey_t {
static status_t build_i(private_ike_rekey_t *this, message_t *message)
{
peer_cfg_t *peer_cfg;
+ host_t *other_host;
/* create new SA only on first try */
if (this->new_sa == NULL)
@@ -77,7 +78,9 @@ static status_t build_i(private_ike_rekey_t *this, message_t *message)
TRUE);
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ other_host = this->ike_sa->get_other_host(this->ike_sa);
this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
+ this->new_sa->set_other_host(this->new_sa, other_host->clone(other_host));
this->ike_init = ike_init_create(this->new_sa, TRUE, this->ike_sa);
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
}
@@ -87,7 +90,7 @@ static status_t build_i(private_ike_rekey_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator
+ * Implementation of task_t.process for responder
*/
static status_t process_r(private_ike_rekey_t *this, message_t *message)
{
@@ -149,6 +152,13 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message)
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
@@ -188,6 +198,14 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
}
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
+ SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+
to_delete = this->ike_sa->get_id(this->ike_sa);
/* check for collisions */