summaryrefslogtreecommitdiff
path: root/src/charon/sa
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2008-12-05 16:15:54 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2008-12-05 16:15:54 +0000
commitc7f1b0530b85bc7654e68992f25ed8ced5d0a80d (patch)
tree861798cd7da646014ed6919766b053099646710d /src/charon/sa
parent8b80ab5a6950ce6515f477624794defd7531642a (diff)
downloadvyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.tar.gz
vyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.2.9)
Diffstat (limited to 'src/charon/sa')
-rw-r--r--src/charon/sa/authenticators/eap/eap_manager.c22
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.c57
-rw-r--r--src/charon/sa/authenticators/psk_authenticator.c97
-rw-r--r--src/charon/sa/authenticators/pubkey_authenticator.c47
-rw-r--r--src/charon/sa/child_sa.c1112
-rw-r--r--src/charon/sa/child_sa.h138
-rw-r--r--src/charon/sa/connect_manager.c72
-rw-r--r--src/charon/sa/ike_sa.c694
-rw-r--r--src/charon/sa/ike_sa.h143
-rw-r--r--src/charon/sa/ike_sa_manager.c97
-rw-r--r--src/charon/sa/ike_sa_manager.h8
-rw-r--r--src/charon/sa/keymat.c568
-rw-r--r--src/charon/sa/keymat.h154
-rw-r--r--src/charon/sa/mediation_manager.c34
-rw-r--r--src/charon/sa/task_manager.c39
-rw-r--r--src/charon/sa/tasks/child_create.c223
-rw-r--r--src/charon/sa/tasks/child_delete.c21
-rw-r--r--src/charon/sa/tasks/child_rekey.c28
-rw-r--r--src/charon/sa/tasks/ike_auth.c108
-rw-r--r--src/charon/sa/tasks/ike_auth_lifetime.c7
-rw-r--r--src/charon/sa/tasks/ike_delete.c41
-rw-r--r--src/charon/sa/tasks/ike_init.c160
-rw-r--r--src/charon/sa/tasks/ike_me.c10
-rw-r--r--src/charon/sa/tasks/ike_mobike.c16
-rw-r--r--src/charon/sa/tasks/ike_reauth.c11
-rw-r--r--src/charon/sa/tasks/ike_rekey.c65
-rw-r--r--src/charon/sa/tasks/task.c25
27 files changed, 2143 insertions, 1854 deletions
diff --git a/src/charon/sa/authenticators/eap/eap_manager.c b/src/charon/sa/authenticators/eap/eap_manager.c
index 44d84156c..c1c2d6fce 100644
--- a/src/charon/sa/authenticators/eap/eap_manager.c
+++ b/src/charon/sa/authenticators/eap/eap_manager.c
@@ -12,14 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_manager.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "eap_manager.h"
-#include <pthread.h>
-
#include <utils/linked_list.h>
+#include <utils/mutex.h>
typedef struct private_eap_manager_t private_eap_manager_t;
typedef struct eap_entry_t eap_entry_t;
@@ -68,7 +67,7 @@ struct private_eap_manager_t {
/**
* mutex to lock methods
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
};
/**
@@ -85,9 +84,9 @@ static void add_method(private_eap_manager_t *this, eap_type_t type,
entry->role = role;
entry->constructor = constructor;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->methods->insert_last(this->methods, entry);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -98,7 +97,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
enumerator_t *enumerator;
eap_entry_t *entry;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -109,7 +108,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -124,7 +123,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
eap_entry_t *entry;
eap_method_t *method = NULL;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -139,7 +138,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return method;
}
@@ -149,6 +148,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
static void destroy(private_eap_manager_t *this)
{
this->methods->destroy_function(this->methods, free);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -165,7 +165,7 @@ eap_manager_t *eap_manager_create()
this->public.destroy = (void(*)(eap_manager_t*))destroy;
this->methods = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return &this->public;
}
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c
index 0909d6563..5c22f3df2 100644
--- a/src/charon/sa/authenticators/eap_authenticator.c
+++ b/src/charon/sa/authenticators/eap_authenticator.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_authenticator.c 4292 2008-08-26 19:54:47Z andreas $
+ * $Id: eap_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -70,36 +70,24 @@ struct private_eap_authenticator_t {
*/
u_int32_t vendor;
};
-
-/**
- * reuse shared key signature function from PSK authenticator
- */
-extern chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
- chunk_t secret, identification_t *id,
- chunk_t skp, prf_t *prf);
/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
chunk_t my_nonce, auth_payload_t *auth_payload)
{
- chunk_t auth_data, recv_auth_data, secret;
- identification_t *other_id = this->ike_sa->get_other_id(this->ike_sa);
+ chunk_t auth_data, recv_auth_data;
+ identification_t *other_id;
+ keymat_t *keymat;
- if (this->msk.len)
- { /* use MSK if EAP method established one... */
- secret = this->msk;
- }
- else
- { /* ... or use SKp if not */
- secret = this->ike_sa->get_skp_verify(this->ike_sa);
- }
- auth_data = build_shared_key_signature(ike_sa_init, my_nonce, secret,
- other_id, this->ike_sa->get_skp_verify(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+
+ auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
+ this->msk, other_id);
recv_auth_data = auth_payload->get_data(auth_payload);
- if (!chunk_equals(auth_data, recv_auth_data))
+ if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "verification of AUTH payload created from EAP MSK failed");
chunk_free(&auth_data);
@@ -118,23 +106,18 @@ static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload)
{
- chunk_t auth_data, secret;
- identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa);
+ identification_t *my_id;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
my_id, auth_class_names, AUTH_CLASS_EAP);
-
- if (this->msk.len)
- { /* use MSK if EAP method established one... */
- secret = this->msk;
- }
- else
- { /* ... or use SKp if not */
- secret = this->ike_sa->get_skp_build(this->ike_sa);
- }
- auth_data = build_shared_key_signature(ike_sa_init, other_nonce, secret,
- my_id, this->ike_sa->get_skp_build(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
+
+ auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
+ this->msk, my_id);
*auth_payload = auth_payload_create();
(*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c
index d003dc2c9..ae5a66479 100644
--- a/src/charon/sa/authenticators/psk_authenticator.c
+++ b/src/charon/sa/authenticators/psk_authenticator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: psk_authenticator.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: psk_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -23,12 +23,6 @@
#include <daemon.h>
#include <credentials/auth_info.h>
-/**
- * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
- */
-#define IKEV2_KEY_PAD "Key Pad for IKEv2"
-#define IKEV2_KEY_PAD_LENGTH 17
-
typedef struct private_psk_authenticator_t private_psk_authenticator_t;
@@ -49,55 +43,6 @@ struct private_psk_authenticator_t {
};
/**
- * Builds the octets to be signed as described in section 2.15 of RFC 4306
- */
-chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce,
- identification_t *id, prf_t *prf)
-{
- u_int8_t id_header_buf[] = {0x00, 0x00, 0x00, 0x00};
- chunk_t id_header = chunk_from_buf(id_header_buf);
- chunk_t id_with_header, id_prfd, id_encoding;
-
- id_header_buf[0] = id->get_type(id);
- id_encoding = id->get_encoding(id);
-
- id_with_header = chunk_cat("cc", id_header, id_encoding);
- prf->allocate_bytes(prf, id_with_header, &id_prfd);
- chunk_free(&id_with_header);
-
- return chunk_cat("ccm", ike_sa_init, nonce, id_prfd);
-}
-
-/**
- * Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
- */
-chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
- chunk_t secret, identification_t *id,
- chunk_t skp, prf_t *prf)
-{
- chunk_t key_pad, key, auth_data, octets;
-
- prf->set_key(prf, skp);
- octets = build_tbs_octets(ike_sa_init, nonce, id, prf);
- /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
- key_pad.ptr = IKEV2_KEY_PAD;
- key_pad.len = IKEV2_KEY_PAD_LENGTH;
- prf->set_key(prf, secret);
- prf->allocate_bytes(prf, key_pad, &key);
- prf->set_key(prf, key);
- prf->allocate_bytes(prf, octets, &auth_data);
- DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
- DBG3(DBG_IKE, "secret %B", &secret);
- DBG3(DBG_IKE, "keypad %B", &key_pad);
- DBG3(DBG_IKE, "prf(secret, keypad) %B", &key);
- DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &auth_data);
- chunk_free(&octets);
- chunk_free(&key);
-
- return auth_data;
-}
-
-/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
@@ -105,25 +50,25 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
{
chunk_t auth_data, recv_auth_data;
identification_t *my_id, *other_id;
- shared_key_t *shared_key;
+ shared_key_t *key;
enumerator_t *enumerator;
bool authenticated = FALSE;
int keys_found = 0;
+ keymat_t *keymat;
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
enumerator = charon->credentials->create_shared_enumerator(
charon->credentials, SHARED_IKE, my_id, other_id);
- while (!authenticated && enumerator->enumerate(enumerator, &shared_key, NULL, NULL))
+ while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
{
keys_found++;
- auth_data = build_shared_key_signature(ike_sa_init, my_nonce,
- shared_key->get_key(shared_key), other_id,
- this->ike_sa->get_skp_verify(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
- recv_auth_data = auth_payload->get_data(auth_payload);
- if (auth_data.len == recv_auth_data.len &&
- memeq(auth_data.ptr, recv_auth_data.ptr, auth_data.len))
+
+ auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
+ key->get_key(key), other_id);
+ if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
other_id, auth_method_names, AUTH_PSK);
@@ -153,26 +98,26 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
static status_t build(private_psk_authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload)
{
- shared_key_t *shared_key;
- chunk_t auth_data;
identification_t *my_id, *other_id;
+ shared_key_t *key;
+ chunk_t auth_data;
+ keymat_t *keymat;
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
my_id, auth_method_names, AUTH_PSK);
- shared_key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
- my_id, other_id);
- if (shared_key == NULL)
+ key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
+ my_id, other_id);
+ if (key == NULL)
{
DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id);
return NOT_FOUND;
}
- auth_data = build_shared_key_signature(ike_sa_init, other_nonce,
- shared_key->get_key(shared_key), my_id,
- this->ike_sa->get_skp_build(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
- shared_key->destroy(shared_key);
+ auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
+ key->get_key(key), my_id);
+ key->destroy(key);
DBG2(DBG_IKE, "successfully created shared key MAC");
*auth_payload = auth_payload_create();
(*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
diff --git a/src/charon/sa/authenticators/pubkey_authenticator.c b/src/charon/sa/authenticators/pubkey_authenticator.c
index 2c02ca84c..c16f3b888 100644
--- a/src/charon/sa/authenticators/pubkey_authenticator.c
+++ b/src/charon/sa/authenticators/pubkey_authenticator.c
@@ -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: pubkey_authenticator.c 4054 2008-06-10 20:31:53Z andreas $
+ * $Id: pubkey_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -44,12 +44,6 @@ struct private_pubkey_authenticator_t {
};
/**
- * Function implemented in psk_authenticator.c
- */
-extern chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce,
- identification_t *id, prf_t *prf);
-
-/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
@@ -58,15 +52,15 @@ static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init
public_key_t *public;
auth_method_t auth_method;
chunk_t auth_data, octets;
- identification_t *other_id;
- prf_t *prf;
+ identification_t *id;
auth_info_t *auth, *current_auth;
enumerator_t *enumerator;
key_type_t key_type = KEY_ECDSA;
signature_scheme_t scheme;
status_t status = FAILED;
+ keymat_t *keymat;
- other_id = this->ike_sa->get_other_id(this->ike_sa);
+ id = this->ike_sa->get_other_id(this->ike_sa);
auth_method = auth_payload->get_auth_method(auth_payload);
switch (auth_method)
{
@@ -89,19 +83,17 @@ static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init
return INVALID_ARG;
}
auth_data = auth_payload->get_data(auth_payload);
- prf = this->ike_sa->get_prf(this->ike_sa);
- prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa));
- octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf);
-
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, TRUE, ike_sa_init, my_nonce, id);
auth = this->ike_sa->get_other_auth(this->ike_sa);
enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, key_type, other_id, auth);
+ charon->credentials, key_type, id, auth);
while (enumerator->enumerate(enumerator, &public, &current_auth))
{
if (public->verify(public, scheme, octets, auth_data))
{
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
- other_id, auth_method_names, auth_method);
+ id, auth_method_names, auth_method);
status = SUCCESS;
auth->merge(auth, current_auth);
break;
@@ -125,19 +117,19 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
chunk_t octets, auth_data;
status_t status = FAILED;
private_key_t *private;
- identification_t *my_id;
- prf_t *prf;
+ identification_t *id;
auth_info_t *auth;
auth_method_t auth_method;
signature_scheme_t scheme;
+ keymat_t *keymat;
- my_id = this->ike_sa->get_my_id(this->ike_sa);
+ id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_my_auth(this->ike_sa);
private = charon->credentials->get_private(charon->credentials, KEY_ANY,
- my_id, auth);
+ id, auth);
if (private == NULL)
{
- DBG1(DBG_IKE, "no private key found for '%D'", my_id);
+ DBG1(DBG_IKE, "no private key found for '%D'", id);
return NOT_FOUND;
}
@@ -176,9 +168,8 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
key_type_names, private->get_type(private));
return status;
}
- prf = this->ike_sa->get_prf(this->ike_sa);
- prf->set_key(prf, this->ike_sa->get_skp_build(this->ike_sa));
- octets = build_tbs_octets(ike_sa_init, other_nonce, my_id, prf);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, FALSE, ike_sa_init, other_nonce, id);
if (private->sign(private, scheme, octets, &auth_data))
{
@@ -189,9 +180,9 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
chunk_free(&auth_data);
status = SUCCESS;
}
- DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", my_id,
- auth_method_names, auth_method,
- (status == SUCCESS)? "successful":"failed");
+ DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", id,
+ auth_method_names, auth_method,
+ (status == SUCCESS)? "successful":"failed");
chunk_free(&octets);
private->destroy(private);
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 7c4b398cf..d7a63d5e8 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_sa.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_sa.c 4665 2008-11-17 00:01:34Z andreas $
*/
#define _GNU_SOURCE
@@ -23,36 +23,21 @@
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <daemon.h>
-ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DELETING,
+ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"CREATED",
"ROUTED",
+ "INSTALLING",
"INSTALLED",
+ "UPDATING",
"REKEYING",
"DELETING",
+ "DESTROYING",
);
-typedef struct sa_policy_t sa_policy_t;
-
-/**
- * Struct used to store information for a policy. This
- * is needed since we must provide all this information
- * for deleting a policy...
- */
-struct sa_policy_t {
- /**
- * Traffic selector for us
- */
- traffic_selector_t *my_ts;
-
- /**
- * Traffic selector for other
- */
- traffic_selector_t *other_ts;
-};
-
typedef struct private_child_sa_t private_child_sa_t;
/**
@@ -64,83 +49,77 @@ struct private_child_sa_t {
*/
child_sa_t public;
- struct {
- /** address of peer */
- host_t *addr;
- /** id of peer */
- identification_t *id;
- /** actual used SPI, 0 if unused */
- u_int32_t spi;
- /** Compression Parameter Index (CPI) used, 0 if unused */
- u_int16_t cpi;
- } me, other;
-
/**
- * Allocated SPI for a ESP proposal candidates
+ * address of us
*/
- u_int32_t alloc_esp_spi;
+ host_t *my_addr;
/**
- * Allocated SPI for a AH proposal candidates
+ * address of remote
*/
- u_int32_t alloc_ah_spi;
+ host_t *other_addr;
/**
- * Protocol used to protect this SA, ESP|AH
+ * our actually used SPI, 0 if unused
*/
- protocol_id_t protocol;
+ u_int32_t my_spi;
/**
- * List containing sa_policy_t objects
+ * others used SPI, 0 if unused
*/
- linked_list_t *policies;
+ u_int32_t other_spi;
/**
- * Seperate list for local traffic selectors
+ * our Compression Parameter Index (CPI) used, 0 if unused
*/
- linked_list_t *my_ts;
+ u_int16_t my_cpi;
/**
- * Seperate list for remote traffic selectors
+ * others Compression Parameter Index (CPI) used, 0 if unused
*/
- linked_list_t *other_ts;
+ u_int16_t other_cpi;
/**
- * reqid used for this child_sa
+ * List for local traffic selectors
*/
- u_int32_t reqid;
+ linked_list_t *my_ts;
/**
- * encryption algorithm used for this SA
+ * List for remote traffic selectors
*/
- u_int16_t enc_alg;
+ linked_list_t *other_ts;
/**
- * key size of enc_alg
+ * Allocated SPI for a ESP proposal candidates
*/
- u_int16_t enc_size;
+ u_int32_t alloc_esp_spi;
/**
- * integrity protection algorithm used for this SA
+ * Allocated SPI for a AH proposal candidates
*/
- u_int16_t int_alg;
+ u_int32_t alloc_ah_spi;
/**
- * key size of int_alg
+ * Protocol used to protect this SA, ESP|AH
*/
- u_int16_t int_size;
+ protocol_id_t protocol;
/**
- * time, on which SA was installed
+ * reqid used for this child_sa
*/
- time_t install_time;
+ u_int32_t reqid;
/**
- * absolute time when rekeying is sceduled
+ * absolute time when rekeying is scheduled
*/
time_t rekey_time;
/**
+ * absolute time when the SA expires
+ */
+ time_t expire_time;
+
+ /**
* state of the CHILD_SA
*/
child_sa_state_t state;
@@ -166,23 +145,18 @@ struct private_child_sa_t {
ipsec_mode_t mode;
/**
- * virtual IP assinged to local host
- */
- host_t *virtual_ip;
+ * selected proposal
+ */
+ proposal_t *proposal;
/**
* config used to create this child
*/
child_cfg_t *config;
-
- /**
- * cached interface name for iptables
- */
- char *iface;
};
/**
- * Implementation of child_sa_t.get_name.
+ * Implementation of child_sa_t.get_name
*/
static char *get_name(private_child_sa_t *this)
{
@@ -202,11 +176,7 @@ static u_int32_t get_reqid(private_child_sa_t *this)
*/
u_int32_t get_spi(private_child_sa_t *this, bool inbound)
{
- if (inbound)
- {
- return this->me.spi;
- }
- return this->other.spi;
+ return inbound ? this->my_spi : this->other_spi;
}
/**
@@ -214,11 +184,7 @@ u_int32_t get_spi(private_child_sa_t *this, bool inbound)
*/
u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
{
- if (inbound)
- {
- return this->me.cpi;
- }
- return this->other.cpi;
+ return inbound ? this->my_cpi : this->other_cpi;
}
/**
@@ -230,6 +196,30 @@ protocol_id_t get_protocol(private_child_sa_t *this)
}
/**
+ * Implementation of child_sa_t.get_mode
+ */
+static ipsec_mode_t get_mode(private_child_sa_t *this)
+{
+ return this->mode;
+}
+
+/**
+ * Implementation of child_sa_t.has_encap
+ */
+static bool has_encap(private_child_sa_t *this)
+{
+ return this->encap;
+}
+
+/**
+ * Implementation of child_sa_t.get_ipcomp
+ */
+static ipcomp_transform_t get_ipcomp(private_child_sa_t *this)
+{
+ return this->ipcomp;
+}
+
+/**
* Implements child_sa_t.get_state
*/
static child_sa_state_t get_state(private_child_sa_t *this)
@@ -245,207 +235,134 @@ static child_cfg_t* get_config(private_child_sa_t *this)
return this->config;
}
+typedef struct policy_enumerator_t policy_enumerator_t;
+
/**
- * Implementation of child_sa_t.get_stats.
+ * Private policy enumerator
*/
-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,
- u_int32_t *use_fwd)
+struct policy_enumerator_t {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over own TS */
+ enumerator_t *mine;
+ /** enumerator over others TS */
+ enumerator_t *other;
+ /** list of others TS, to recreate enumerator */
+ linked_list_t *list;
+ /** currently enumerating TS for "me" side */
+ traffic_selector_t *ts;
+};
+
+/**
+ * enumerator function of create_policy_enumerator()
+ */
+static bool policy_enumerate(policy_enumerator_t *this,
+ traffic_selector_t **my_out, traffic_selector_t **other_out)
{
- sa_policy_t *policy;
- iterator_t *iterator;
- u_int32_t in = 0, out = 0, fwd = 0, time;
+ traffic_selector_t *other_ts;
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
+ while (this->ts || this->mine->enumerate(this->mine, &this->ts))
{
-
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_IN, &time) == SUCCESS)
- {
- in = max(in, time);
+ if (!this->other->enumerate(this->other, &other_ts))
+ { /* end of others list, restart with new of mine */
+ this->other->destroy(this->other);
+ this->other = this->list->create_enumerator(this->list);
+ this->ts = NULL;
+ continue;
}
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts, POLICY_OUT, &time) == SUCCESS)
- {
- out = max(out, time);
+ if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
+ { /* family mismatch */
+ continue;
}
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_FWD, &time) == SUCCESS)
- {
- fwd = max(fwd, time);
+ if (this->ts->get_protocol(this->ts) &&
+ other_ts->get_protocol(other_ts) &&
+ this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
+ { /* protocol mismatch */
+ continue;
}
+ *my_out = this->ts;
+ *other_out = other_ts;
+ return TRUE;
}
- iterator->destroy(iterator);
+ return FALSE;
+}
- *mode = this->mode;
- *encr_algo = this->enc_alg;
- *encr_len = this->enc_size;
- *int_algo = this->int_alg;
- *int_len = this->int_size;
- *rekey = this->rekey_time;
- *use_in = in;
- *use_out = out;
- *use_fwd = fwd;
+/**
+ * destroy function of create_policy_enumerator()
+ */
+static void policy_destroy(policy_enumerator_t *this)
+{
+ this->mine->destroy(this->mine);
+ this->other->destroy(this->other);
+ free(this);
}
/**
- * Run the up/down script
+ * Implementation of child_sa_t.create_policy_enumerator
*/
-static void updown(private_child_sa_t *this, bool up)
+static enumerator_t* create_policy_enumerator(private_child_sa_t *this)
{
- sa_policy_t *policy;
- iterator_t *iterator;
- char *script;
-
- script = this->config->get_updown(this->config);
+ policy_enumerator_t *e = malloc_thing(policy_enumerator_t);
- if (script == NULL)
- {
- return;
- }
+ e->public.enumerate = (void*)policy_enumerate;
+ e->public.destroy = (void*)policy_destroy;
+ e->mine = this->my_ts->create_enumerator(this->my_ts);
+ e->other = this->other_ts->create_enumerator(this->other_ts);
+ e->list = this->other_ts;
+ e->ts = NULL;
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
- {
- char command[1024];
- char *my_client, *other_client, *my_client_mask, *other_client_mask;
- char *pos, *virtual_ip;
- FILE *shell;
-
- /* get subnet/bits from string */
- asprintf(&my_client, "%R", policy->my_ts);
- pos = strchr(my_client, '/');
- *pos = '\0';
- my_client_mask = pos + 1;
- pos = strchr(my_client_mask, '[');
- if (pos)
- {
- *pos = '\0';
- }
- asprintf(&other_client, "%R", policy->other_ts);
- pos = strchr(other_client, '/');
- *pos = '\0';
- other_client_mask = pos + 1;
- pos = strchr(other_client_mask, '[');
- if (pos)
- {
- *pos = '\0';
- }
-
- if (this->virtual_ip)
- {
- asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ",
- this->virtual_ip);
- }
- else
- {
- asprintf(&virtual_ip, "");
- }
+ return &e->public;
+}
- /* we cache the iface name, as it may not be available when
- * the SA gets deleted */
- if (up)
- {
- free(this->iface);
- this->iface = charon->kernel_interface->get_interface(
- charon->kernel_interface, this->me.addr);
- }
-
- /* build the command with all env variables.
- * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
- */
- snprintf(command, sizeof(command),
- "2>&1 "
- "PLUTO_VERSION='1.1' "
- "PLUTO_VERB='%s%s%s' "
- "PLUTO_CONNECTION='%s' "
- "PLUTO_INTERFACE='%s' "
- "PLUTO_REQID='%u' "
- "PLUTO_ME='%H' "
- "PLUTO_MY_ID='%D' "
- "PLUTO_MY_CLIENT='%s/%s' "
- "PLUTO_MY_CLIENT_NET='%s' "
- "PLUTO_MY_CLIENT_MASK='%s' "
- "PLUTO_MY_PORT='%u' "
- "PLUTO_MY_PROTOCOL='%u' "
- "PLUTO_PEER='%H' "
- "PLUTO_PEER_ID='%D' "
- "PLUTO_PEER_CLIENT='%s/%s' "
- "PLUTO_PEER_CLIENT_NET='%s' "
- "PLUTO_PEER_CLIENT_MASK='%s' "
- "PLUTO_PEER_PORT='%u' "
- "PLUTO_PEER_PROTOCOL='%u' "
- "%s"
- "%s"
- "%s",
- up ? "up" : "down",
- policy->my_ts->is_host(policy->my_ts,
- this->me.addr) ? "-host" : "-client",
- this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-v6",
- this->config->get_name(this->config),
- this->iface ? this->iface : "unknown",
- this->reqid,
- this->me.addr,
- this->me.id,
- my_client, my_client_mask,
- my_client, my_client_mask,
- policy->my_ts->get_from_port(policy->my_ts),
- policy->my_ts->get_protocol(policy->my_ts),
- this->other.addr,
- this->other.id,
- other_client, other_client_mask,
- other_client, other_client_mask,
- policy->other_ts->get_from_port(policy->other_ts),
- policy->other_ts->get_protocol(policy->other_ts),
- virtual_ip,
- this->config->get_hostaccess(this->config) ?
- "PLUTO_HOST_ACCESS='1' " : "",
- script);
- free(my_client);
- free(other_client);
- free(virtual_ip);
-
- DBG3(DBG_CHD, "running updown script: %s", command);
- shell = popen(command, "r");
+/**
+ * Implementation of child_sa_t.get_usetime
+ */
+static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ u_int32_t last_use = 0;
- if (shell == NULL)
- {
- DBG1(DBG_CHD, "could not execute updown script '%s'", script);
- return;
- }
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ u_int32_t in, out, fwd;
- while (TRUE)
+ if (inbound)
{
- char resp[128];
-
- if (fgets(resp, sizeof(resp), shell) == NULL)
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
{
- if (ferror(shell))
- {
- DBG1(DBG_CHD, "error reading output from updown script");
- return;
- }
- else
+ last_use = max(last_use, in);
+ }
+ if (this->mode != MODE_TRANSPORT)
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
{
- break;
+ last_use = max(last_use, fwd);
}
}
- else
+ }
+ else
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
{
- char *e = resp + strlen(resp);
- if (e > resp && e[-1] == '\n')
- { /* trim trailing '\n' */
- e[-1] = '\0';
- }
- DBG1(DBG_CHD, "updown: %s", resp);
+ last_use = max(last_use, out);
}
}
- pclose(shell);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
+ return last_use;
+}
+
+/**
+ * Implementation of child_sa_t.get_lifetime
+ */
+static u_int32_t get_lifetime(private_child_sa_t *this, bool hard)
+{
+ return hard ? this->expire_time : this->rekey_time;
}
/**
@@ -453,11 +370,8 @@ static void updown(private_child_sa_t *this, bool up)
*/
static void set_state(private_child_sa_t *this, child_sa_state_t state)
{
+ charon->bus->child_state_change(charon->bus, &this->public, state);
this->state = state;
- if (state == CHILD_INSTALLED)
- {
- updown(this, TRUE);
- }
}
/**
@@ -474,7 +388,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
{
if (charon->kernel_interface->get_spi(
charon->kernel_interface,
- this->other.addr, this->me.addr,
+ this->other_addr, this->my_addr,
PROTO_AH, this->reqid,
&this->alloc_ah_spi) != SUCCESS)
{
@@ -490,7 +404,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
{
if (charon->kernel_interface->get_spi(
charon->kernel_interface,
- this->other.addr, this->me.addr,
+ this->other_addr, this->my_addr,
PROTO_ESP, this->reqid,
&this->alloc_esp_spi) != SUCCESS)
{
@@ -502,7 +416,6 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
return SUCCESS;
}
-
/**
* Implements child_sa_t.alloc
*/
@@ -525,237 +438,213 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
return SUCCESS;
}
+/**
+ * Install an SA for one direction
+ */
static status_t install(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine)
+ ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in)
{
- u_int32_t spi, soft, hard;
- host_t *src;
- host_t *dst;
+ u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
+ u_int32_t spi, soft, hard, now;
+ host_t *src, *dst;
status_t status;
- this->protocol = proposal->get_protocol(proposal);
-
- /* now we have to decide which spi to use. Use self allocated, if "mine",
- * or the one in the proposal, if not "mine" (others). Additionally,
+ /* now we have to decide which spi to use. Use self allocated, if "in",
+ * or the one in the proposal, if not "in" (others). Additionally,
* source and dest host switch depending on the role */
- if (mine)
+ if (in)
{
/* if we have allocated SPIs for AH and ESP, we must delete the unused
* one. */
if (this->protocol == PROTO_ESP)
{
- this->me.spi = this->alloc_esp_spi;
+ this->my_spi = this->alloc_esp_spi;
if (this->alloc_ah_spi)
{
- charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
- this->alloc_ah_spi, PROTO_AH);
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->my_addr, this->alloc_ah_spi, 0, PROTO_AH);
}
}
else
{
- this->me.spi = this->alloc_ah_spi;
+ this->my_spi = this->alloc_ah_spi;
if (this->alloc_esp_spi)
{
- charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
- this->alloc_esp_spi, PROTO_ESP);
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->my_addr, this->alloc_esp_spi, 0, PROTO_ESP);
}
}
- spi = this->me.spi;
- dst = this->me.addr;
- src = this->other.addr;
+ spi = this->my_spi;
+ dst = this->my_addr;
+ src = this->other_addr;
}
else
{
- this->other.spi = proposal->get_spi(proposal);
- spi = this->other.spi;
- src = this->me.addr;
- dst = this->other.addr;
+ this->other_spi = proposal->get_spi(proposal);
+ spi = this->other_spi;
+ src = this->my_addr;
+ dst = this->other_addr;
}
- DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound",
+ DBG2(DBG_CHD, "adding %s %N SA", in ? "inbound" : "outbound",
protocol_id_names, this->protocol);
- /* select encryption algo */
- if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
- &this->enc_alg, &this->enc_size))
- {
- DBG2(DBG_CHD, " using %N for encryption",
- encryption_algorithm_names, this->enc_alg);
- }
-
- /* select integrity algo */
- if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
- &this->int_alg, &this->int_size))
- {
- DBG2(DBG_CHD, " using %N for integrity",
- integrity_algorithm_names, this->int_alg);
- }
- soft = this->config->get_lifetime(this->config, TRUE);
- hard = this->config->get_lifetime(this->config, FALSE);
-
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* we install an additional IPComp SA */
- u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
- status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
- ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode,
- this->ipcomp, FALSE, mine);
- }
+ proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size);
+ proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size);
+ soft = this->config->get_lifetime(this->config, TRUE);
+ hard = this->config->get_lifetime(this->config, FALSE);
+
status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
- this->enc_alg, this->enc_size, this->int_alg, this->int_size,
- prf_plus, mode, IPCOMP_NONE, this->encap, mine);
-
- this->install_time = time(NULL);
- this->rekey_time = this->install_time + soft;
+ src, dst, spi, this->protocol, this->reqid,
+ in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
+ mode, this->ipcomp, in ? this->my_cpi : this->other_cpi,
+ this->encap, in);
+
+ now = time(NULL);
+ this->rekey_time = now + soft;
+ this->expire_time = now + hard;
return status;
}
-static status_t add(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus)
+/**
+ * Implementation of child_sa_t.add
+ */
+static status_t add(private_child_sa_t *this,
+ proposal_t *proposal, ipsec_mode_t mode,
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out)
{
- u_int32_t outbound_spi, inbound_spi;
-
- /* backup outbound spi, as alloc overwrites it */
- outbound_spi = proposal->get_spi(proposal);
+ this->proposal = proposal->clone(proposal);
+ this->protocol = proposal->get_protocol(proposal);
- /* get SPIs inbound SAs */
+ /* get SPIs for inbound SAs, write to proposal */
if (alloc_proposal(this, proposal) != SUCCESS)
{
return FAILED;
}
- inbound_spi = proposal->get_spi(proposal);
-
- /* install inbound SAs */
- if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
+ /* install inbound SAs using allocated SPI */
+ if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
{
return FAILED;
}
-
- /* install outbound SAs, restore spi*/
- proposal->set_spi(proposal, outbound_spi);
- if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
+ /* install outbound SAs using received SPI*/
+ if (install(this, this->proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
{
return FAILED;
}
- proposal->set_spi(proposal, inbound_spi);
-
return SUCCESS;
}
-static status_t update(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus)
+/**
+ * Implementation of child_sa_t.update
+ */
+static status_t update(private_child_sa_t *this,
+ proposal_t *proposal, ipsec_mode_t mode,
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out)
{
- u_int32_t inbound_spi;
-
- /* backup received spi, as install() overwrites it */
- inbound_spi = proposal->get_spi(proposal);
+ this->proposal = proposal->clone(proposal);
+ this->protocol = proposal->get_protocol(proposal);
/* install outbound SAs */
- if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
+ if (install(this, proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
{
return FAILED;
}
-
- /* restore spi */
- proposal->set_spi(proposal, inbound_spi);
/* install inbound SAs */
- if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
+ if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
{
return FAILED;
}
-
return SUCCESS;
}
+/**
+ * Implementation of child_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_child_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of child_sa_t.add_policies
+ */
static status_t add_policies(private_child_sa_t *this,
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;
+ enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
- /* use low prio for ROUTED policies */
- bool high_prio = (this->state != CHILD_CREATED);
+ status_t status = SUCCESS;
+ bool routed = (this->state == CHILD_CREATED);
if (this->protocol == PROTO_NONE)
{ /* update if not set yet */
this->protocol = proto;
}
+
+ /* apply traffic selectors */
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ while (enumerator->enumerate(enumerator, &my_ts))
+ {
+ this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts));
+ }
+ enumerator->destroy(enumerator);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ while (enumerator->enumerate(enumerator, &other_ts))
+ {
+ this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts));
+ }
+ enumerator->destroy(enumerator);
- /* 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);
- while (my_iter->iterate(my_iter, (void**)&my_ts))
+ if (this->config->install_policy(this->config))
{
- other_iter->reset(other_iter);
- while (other_iter->iterate(other_iter, (void**)&other_ts))
+ /* enumerate pairs of traffic selectors */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
- status_t status;
- sa_policy_t *policy;
-
- if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
- {
- DBG2(DBG_CHD,
- "CHILD_SA policy uses two different IP families - ignored");
- continue;
- }
-
- /* only set up policies if protocol matches, or if one is zero (any) */
- if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
- my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
- {
- DBG2(DBG_CHD,
- "CHILD_SA policy uses two different protocols - ignored");
- continue;
- }
-
/* install 3 policies: out, in and forward */
- status = charon->kernel_interface->add_policy(charon->kernel_interface,
- this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
-
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
+ this->other_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
+ if (mode != MODE_TRANSPORT)
+ {
+ status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
+ }
if (status != SUCCESS)
{
- my_iter->destroy(my_iter);
- other_iter->destroy(other_iter);
- return status;
+ break;
}
-
- /* store policy to delete/update them later */
- policy = malloc_thing(sa_policy_t);
- policy->my_ts = my_ts->clone(my_ts);
- policy->other_ts = other_ts->clone(other_ts);
- this->policies->insert_last(this->policies, policy);
- /* add to separate list to query them via get_*_traffic_selectors() */
- this->my_ts->insert_last(this->my_ts, policy->my_ts);
- this->other_ts->insert_last(this->other_ts, policy->other_ts);
}
+ enumerator->destroy(enumerator);
}
- my_iter->destroy(my_iter);
- other_iter->destroy(other_iter);
- /* switch to routed state if no SAD entry set up */
- if (this->state == CHILD_CREATED)
+ if (status == SUCCESS)
{
- this->state = CHILD_ROUTED;
+ /* switch to routed state if no SAD entry set up */
+ if (this->state == CHILD_CREATED)
+ {
+ set_state(this, CHILD_ROUTED);
+ }
+ /* needed to update hosts */
+ this->mode = mode;
}
- /* needed to update hosts */
- this->mode = mode;
- return SUCCESS;
+ return status;
}
/**
@@ -763,166 +652,143 @@ static status_t add_policies(private_child_sa_t *this,
*/
static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
{
- if (local)
- {
- return this->my_ts;
- }
- return this->other_ts;
-}
-
-/**
- * Implementation of child_sa_t.get_use_time
- */
-static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
-{
- iterator_t *iterator;
- sa_policy_t *policy;
- status_t status = FAILED;
-
- *use_time = UNDEFINED_TIME;
-
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
- {
- if (inbound)
- {
- time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
-
- status = charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_IN, (u_int32_t*)&in);
- status |= charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_FWD, (u_int32_t*)&fwd);
- *use_time = max(in, fwd);
- }
- else
- {
- status = charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->my_ts, policy->other_ts,
- POLICY_OUT, (u_int32_t*)use_time);
- }
- }
- iterator->destroy(iterator);
- return status;
+ return local ? this->my_ts : this->other_ts;
}
/**
* Implementation of child_sa_t.update_hosts.
*/
static status_t update_hosts(private_child_sa_t *this,
- host_t *me, host_t *other, bool encap)
+ host_t *me, host_t *other, host_t *vip, bool encap)
{
+ child_sa_state_t old;
+ bool transport_proxy_mode;
+
/* anything changed at all? */
- if (me->equals(me, this->me.addr) &&
- other->equals(other, this->other.addr) && this->encap == encap)
+ if (me->equals(me, this->my_addr) &&
+ other->equals(other, this->other_addr) && this->encap == encap)
{
return SUCCESS;
}
- /* run updown script to remove iptables rules */
- updown(this, FALSE);
-
- this->encap = encap;
-
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* update our (initator) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
- IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
- /* update his (responder) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)),
- IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
- }
- /* update our (initator) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
- this->protocol, this->other.addr, this->me.addr, other, me, encap);
- /* update his (responder) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
- this->protocol, this->me.addr, this->other.addr, me, other, encap);
+ old = this->state;
+ set_state(this, CHILD_UPDATING);
+ transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
+ this->mode == MODE_TRANSPORT;
- /* update policies */
- if (!me->ip_equals(me, this->me.addr) ||
- !other->ip_equals(other, this->other.addr))
+ if (!transport_proxy_mode)
{
- iterator_t *iterator;
- sa_policy_t *policy;
-
- /* always use high priorities, as hosts getting updated are INSTALLED */
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
+ /* update our (initator) SA */
+ if (this->my_spi)
{
- /* remove old policies first */
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts, POLICY_OUT);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_IN);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_FWD);
-
- /* check wether we have to update a "dynamic" traffic selector */
- if (!me->ip_equals(me, this->me.addr) &&
- policy->my_ts->is_host(policy->my_ts, this->me.addr))
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->my_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ this->other_addr, this->my_addr, other, me,
+ this->encap, encap) == NOT_SUPPORTED)
{
- policy->my_ts->set_address(policy->my_ts, me);
+ return NOT_SUPPORTED;
}
- if (!other->ip_equals(other, this->other.addr) &&
- policy->other_ts->is_host(policy->other_ts, this->other.addr))
+ }
+
+ /* update his (responder) SA */
+ if (this->other_spi)
+ {
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->other_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ this->my_addr, this->other_addr, me, other,
+ this->encap, encap) == NOT_SUPPORTED)
{
- policy->other_ts->set_address(policy->other_ts, other);
+ return NOT_SUPPORTED;
}
+ }
+ }
+
+ if (this->config->install_policy(this->config))
+ {
+ /* update policies */
+ if (!me->ip_equals(me, this->my_addr) ||
+ !other->ip_equals(other, this->other_addr))
+ {
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
- /* we reinstall the virtual IP to handle interface romaing
- * correctly */
- if (this->virtual_ip)
+ /* always use high priorities, as hosts getting updated are INSTALLED */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- charon->kernel_interface->del_ip(charon->kernel_interface,
- this->virtual_ip);
- charon->kernel_interface->add_ip(charon->kernel_interface,
- this->virtual_ip, me);
+ /* remove old policies first */
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, FALSE);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, FALSE);
+ }
+
+ /* check whether we have to update a "dynamic" traffic selector */
+ if (!me->ip_equals(me, this->my_addr) &&
+ my_ts->is_host(my_ts, this->my_addr))
+ {
+ my_ts->set_address(my_ts, me);
+ }
+ if (!other->ip_equals(other, this->other_addr) &&
+ other_ts->is_host(other_ts, this->other_addr))
+ {
+ other_ts->set_address(other_ts, other);
+ }
+
+ /* we reinstall the virtual IP to handle interface roaming
+ * correctly */
+ if (vip)
+ {
+ charon->kernel_interface->del_ip(charon->kernel_interface, vip);
+ charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
+ }
+
+ /* reinstall updated policies */
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->other_cpi, FALSE);
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ }
}
-
- /* reinstall updated policies */
- charon->kernel_interface->add_policy(charon->kernel_interface,
- me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, policy->other_ts, policy->my_ts, POLICY_IN,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
+ enumerator->destroy(enumerator);
}
- iterator->destroy(iterator);
}
- /* apply hosts */
- if (!me->equals(me, this->me.addr))
+ if (!transport_proxy_mode)
{
- this->me.addr->destroy(this->me.addr);
- this->me.addr = me->clone(me);
- }
- if (!other->equals(other, this->other.addr))
- {
- this->other.addr->destroy(this->other.addr);
- this->other.addr = other->clone(other);
+ /* apply hosts */
+ if (!me->equals(me, this->my_addr))
+ {
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = me->clone(me);
+ }
+ if (!other->equals(other, this->other_addr))
+ {
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = other->clone(other);
+ }
}
-
- /* install new iptables rules */
- updown(this, TRUE);
-
- return SUCCESS;
-}
-/**
- * Implementation of child_sa_t.set_virtual_ip.
- */
-static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
-{
- this->virtual_ip = ip->clone(ip);
+ this->encap = encap;
+ set_state(this, old);
+
+ return SUCCESS;
}
/**
@@ -932,7 +798,7 @@ static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
u_int16_t other_cpi)
{
this->ipcomp = ipcomp;
- this->other.cpi = other_cpi;
+ this->other_cpi = other_cpi;
}
/**
@@ -943,10 +809,10 @@ static u_int16_t allocate_cpi(private_child_sa_t *this)
if (!this->cpi_allocated)
{
charon->kernel_interface->get_cpi(charon->kernel_interface,
- this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
+ this->other_addr, this->my_addr, this->reqid, &this->my_cpi);
this->cpi_allocated = TRUE;
}
- return this->me.cpi;
+ return this->my_cpi;
}
/**
@@ -954,75 +820,61 @@ static u_int16_t allocate_cpi(private_child_sa_t *this)
*/
static void destroy(private_child_sa_t *this)
{
- sa_policy_t *policy;
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ bool unrouted = (this->state == CHILD_ROUTED);
- if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
- {
- updown(this, FALSE);
- }
+ set_state(this, CHILD_DESTROYING);
/* delete SAs in the kernel, if they are set up */
- if (this->me.spi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->me.spi, this->protocol);
- }
- if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
+ if (this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->my_spi, this->protocol,
+ this->my_cpi);
}
- if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
+ if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_esp_spi, PROTO_ESP, 0);
}
- if (this->other.spi)
+ if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other.addr, this->other.spi, this->protocol);
+ this->my_addr, this->alloc_ah_spi, PROTO_AH, 0);
}
- if (this->me.cpi)
+ if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
- }
- if (this->other.cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP);
+ this->other_addr, this->other_spi, this->protocol,
+ this->other_cpi);
}
- /* delete all policies in the kernel */
- while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
+ if (this->config->install_policy(this->config))
{
- /* let rekeyed policies, as they are used by another child_sa */
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts,
- POLICY_OUT);
-
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_IN);
-
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_FWD);
- policy->my_ts->destroy(policy->my_ts);
- policy->other_ts->destroy(policy->other_ts);
- free(policy);
+ /* delete all policies in the kernel */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, unrouted);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, unrouted);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, unrouted);
+ }
+ }
+ enumerator->destroy(enumerator);
}
- this->policies->destroy(this->policies);
- this->my_ts->destroy(this->my_ts);
- this->other_ts->destroy(this->other_ts);
- this->me.addr->destroy(this->me.addr);
- this->other.addr->destroy(this->other.addr);
- this->me.id->destroy(this->me.id);
- this->other.id->destroy(this->other.id);
+ this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
+ this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
+ this->my_addr->destroy(this->my_addr);
+ this->other_addr->destroy(this->other_addr);
+ DESTROY_IF(this->proposal);
this->config->destroy(this->config);
- free(this->iface);
- DESTROY_IF(this->virtual_ip);
free(this);
}
@@ -1030,7 +882,6 @@ static void destroy(private_child_sa_t *this)
* Described in header.
*/
child_sa_t * child_sa_create(host_t *me, host_t* other,
- identification_t *my_id, identification_t *other_id,
child_cfg_t *config, u_int32_t rekey, bool encap)
{
static u_int32_t reqid = 0;
@@ -1042,31 +893,33 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
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*, 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.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode;
+ this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
+ this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
+ this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
+ this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime;
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
- 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 = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))add;
+ this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))update;
+ this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
+ this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update_hosts;
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.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
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.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;
/* private data */
- this->me.addr = me->clone(me);
- this->other.addr = other->clone(other);
- this->me.id = my_id->clone(my_id);
- this->other.id = other_id->clone(other_id);
- this->me.spi = 0;
- this->me.cpi = 0;
- this->other.spi = 0;
- this->other.cpi = 0;
+ this->my_addr = me->clone(me);
+ this->other_addr = other->clone(other);
+ this->my_spi = 0;
+ this->my_cpi = 0;
+ this->other_spi = 0;
+ this->other_cpi = 0;
this->alloc_ah_spi = 0;
this->alloc_esp_spi = 0;
this->encap = encap;
@@ -1075,19 +928,70 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->state = CHILD_CREATED;
/* reuse old reqid if we are rekeying an existing CHILD_SA */
this->reqid = rekey ? rekey : ++reqid;
- this->enc_alg = ENCR_UNDEFINED;
- this->enc_size = 0;
- this->int_alg = AUTH_UNDEFINED;
- this->int_size = 0;
- this->policies = linked_list_create();
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
this->protocol = PROTO_NONE;
this->mode = MODE_TUNNEL;
- this->virtual_ip = NULL;
- this->iface = NULL;
+ this->proposal = NULL;
this->config = config;
config->get_ref(config);
+
+ /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
+ if (config->get_mode(config) == MODE_TRANSPORT &&
+ config->use_proxy_mode(config))
+ {
+ ts_type_t type;
+ int family;
+ chunk_t addr;
+ host_t *host;
+ enumerator_t *enumerator;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+
+ this->mode = MODE_TRANSPORT;
+
+ my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ if (enumerator->enumerate(enumerator, &my_ts))
+ {
+ if (my_ts->is_host(my_ts, NULL) &&
+ !my_ts->is_host(my_ts, this->my_addr))
+ {
+ type = my_ts->get_type(my_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = my_ts->get_from_address(my_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
+ this->my_addr, host);
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
+
+ other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ if (enumerator->enumerate(enumerator, &other_ts))
+ {
+ if (other_ts->is_host(other_ts, NULL) &&
+ !other_ts->is_host(other_ts, this->other_addr))
+ {
+ type = other_ts->get_type(other_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = other_ts->get_from_address(other_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
+ this->other_addr, host);
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
+ }
return &this->public;
}
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index 2f7961e03..7109de5cd 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 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_sa.h 4618 2008-11-11 09:22:00Z tobias $
*/
/**
@@ -50,11 +50,21 @@ enum child_sa_state_t {
CHILD_ROUTED,
/**
+ * Installing an in-use CHILD_SA
+ */
+ CHILD_INSTALLING,
+
+ /**
* Installed an in-use CHILD_SA
*/
CHILD_INSTALLED,
/**
+ * While updating hosts, in update_hosts()
+ */
+ CHILD_UPDATING,
+
+ /**
* CHILD_SA which is rekeying
*/
CHILD_REKEYING,
@@ -63,6 +73,11 @@ enum child_sa_state_t {
* CHILD_SA in progress of delete
*/
CHILD_DELETING,
+
+ /**
+ * CHILD_SA object gets destroyed
+ */
+ CHILD_DESTROYING,
};
/**
@@ -138,23 +153,41 @@ struct child_sa_t {
protocol_id_t (*get_protocol) (child_sa_t *this);
/**
- * Get info and statistics about this CHILD_SA.
+ * Get the IPsec mode of this CHILD_SA.
+ *
+ * @return TUNNEL | TRANSPORT | BEET
+ */
+ ipsec_mode_t (*get_mode)(child_sa_t *this);
+
+ /**
+ * Get the used IPComp algorithm.
+ *
+ * @return IPComp compression algorithm.
+ */
+ ipcomp_transform_t (*get_ipcomp)(child_sa_t *this);
+
+ /**
+ * Check if this CHILD_SA uses UDP encapsulation.
+ *
+ * @return TRUE if SA encapsulates ESP packets
+ */
+ bool (*has_encap)(child_sa_t *this);
+
+ /**
+ * Get the lifetime of the CHILD_SA.
*
- * @param mode mode this IKE_SA uses
- * @param encr_algo encryption algorithm used by this CHILD_SA.
- * @param encr_len key length of the algorithm, if any
- * @param int_algo integrity algorithm used by this CHILD_SA
- * @param int_len key length of the algorithm, if any
- * @param rekey time when rekeying is scheduled
- * @param use_in time when last traffic was seen coming in
- * @param use_out time when last traffic was seen going out
- * @param use_fwd time when last traffic was getting forwarded
+ * @param hard TRUE for hard lifetime, FALSE for soft (rekey) lifetime
+ * @return lifetime in seconds
*/
- 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,
- u_int32_t *use_fwd);
+ u_int32_t (*get_lifetime)(child_sa_t *this, bool hard);
+
+ /**
+ * Get last use time of the CHILD_SA.
+ *
+ * @param inbound TRUE for inbound traffic, FALSE for outbound
+ * @return time of last use in seconds
+ */
+ u_int32_t (*get_usetime)(child_sa_t *this, bool inbound);
/**
* Allocate SPIs for given proposals.
@@ -174,12 +207,15 @@ struct child_sa_t {
*
* @param proposal proposal for which SPIs are allocated
* @param mode mode for the CHILD_SA
- * @param prf_plus key material to use for key derivation
+ * @param integ_in integrity key for inbound traffic
+ * @param integ_out integrity key for outbound traffic
+ * @param encr_in encryption key for inbound traffic
+ * @param enc_out encryption key for outbound traffic
* @return SUCCESS or FAILED
*/
status_t (*add)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
- prf_plus_t *prf_plus);
-
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out);
/**
* Install the kernel SAs for a proposal, after SPIs have been allocated.
*
@@ -187,12 +223,22 @@ struct child_sa_t {
*
* @param proposal proposal for which SPIs are allocated
* @param mode mode for the CHILD_SA
- * @param prf_plus key material to use for key derivation
+ * @param integ_in integrity key for inbound traffic
+ * @param integ_out integrity key for outbound traffic
+ * @param encr_in encryption key for inbound traffic
+ * @param enc_out encryption key for outbound traffic
* @return SUCCESS or FAILED
*/
status_t (*update)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
- prf_plus_t *prf_plus);
-
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out);
+ /**
+ * Get the selected proposal passed to add()/update().
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(child_sa_t *this);
+
/**
* Update the hosts in the kernel SAs and policies.
*
@@ -200,11 +246,12 @@ struct child_sa_t {
*
* @param me the new local host
* @param other the new remote host
+ * @param vip virtual IP, if any
* @param TRUE to use UDP encapsulation for NAT traversal
* @return SUCCESS or FAILED
*/
status_t (*update_hosts)(child_sa_t *this, host_t *me, host_t *other,
- bool encap);
+ host_t *vip, bool encap);
/**
* Install the policies using some traffic selectors.
@@ -231,13 +278,11 @@ struct child_sa_t {
linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
/**
- * Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
- *
- * @param inbound query for in- or outbound usage
- * @param use_time the time
- * @return SUCCESS or FAILED
- */
- status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
+ * Create an enumerator over installed policies.
+ *
+ * @return enumerator over pairs of traffic selectors.
+ */
+ enumerator_t* (*create_policy_enumerator)(child_sa_t *this);
/**
* Get the state of the CHILD_SA.
@@ -259,23 +304,13 @@ struct child_sa_t {
child_cfg_t* (*get_config) (child_sa_t *this);
/**
- * Set the virtual IP used received from IRAS.
- *
- * To allow proper setup of firewall rules, the virtual IP is required
- * for filtering.
- *
- * @param ip own virtual IP
- */
- void (*set_virtual_ip) (child_sa_t *this, host_t *ip);
-
- /**
* Activate IPComp by setting the transform ID and CPI values.
*
* @param ipcomp the IPComp transform to use
* @param other_cpi other Compression Parameter Index
*/
void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp,
- u_int16_t other_cpi);
+ u_int16_t other_cpi);
/**
* Returns the Compression Parameter Index (CPI) allocated from the kernel.
@@ -293,17 +328,16 @@ struct child_sa_t {
/**
* Constructor to create a new child_sa_t.
*
- * @param me own address
- * @param other remote address
- * @param my_id id of own peer
- * @param other_id id of remote peer
- * @param config config to use for this CHILD_SA
- * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
- * @param encap TRUE to enable UDP encapsulation (NAT traversal)
- * @return child_sa_t object
+ * @param me own address
+ * @param other remote address
+ * @param my_id id of own peer
+ * @param other_id id of remote peer
+ * @param config config to use for this CHILD_SA
+ * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
+ * @param encap TRUE to enable UDP encapsulation (NAT traversal)
+ * @return child_sa_t object
*/
-child_sa_t * child_sa_create(host_t *me, host_t *other,
- identification_t *my_id, identification_t* other_id,
- child_cfg_t *config, u_int32_t reqid, bool encap);
+child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
+ u_int32_t reqid, bool encap);
#endif /*CHILD_SA_H_ @} */
diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c
index d24ce8fc7..b9141ffc1 100644
--- a/src/charon/sa/connect_manager.c
+++ b/src/charon/sa/connect_manager.c
@@ -12,15 +12,15 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: connect_manager.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: connect_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "connect_manager.h"
-#include <pthread.h>
#include <math.h>
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
@@ -59,7 +59,7 @@ struct private_connect_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Hasher to generate signatures
@@ -845,20 +845,20 @@ static job_requeue_t initiator_finish(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't finish connectivity checks",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
finish_checks(this, checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -929,14 +929,14 @@ static job_requeue_t retransmit(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't retransmit connectivity check",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -980,7 +980,7 @@ retransmit_end:
break;
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
/* we reschedule it manually */
return JOB_REQUEUE_NONE;
@@ -1078,14 +1078,14 @@ static job_requeue_t sender(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't send connectivity check",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -1100,7 +1100,7 @@ static job_requeue_t sender(callback_data_t *data)
if (checklist->pairs->find_first(checklist->pairs,
(linked_list_match_t)match_waiting_pair, (void**)&pair) != SUCCESS)
{
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
DBG1(DBG_IKE, "no pairs in waiting state, aborting");
return JOB_REQUEUE_NONE;
}
@@ -1126,7 +1126,7 @@ static job_requeue_t sender(callback_data_t *data)
/* schedule this job again */
schedule_checks(this, checklist, ME_INTERVAL);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
/* we reschedule it manually */
return JOB_REQUEUE_NONE;
@@ -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");
+ DBG1(DBG_IKE, "establishing 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);
@@ -1345,7 +1345,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
return;
}
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, check->connect_id, &checklist) != SUCCESS)
@@ -1353,7 +1353,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&check->connect_id);
check_destroy(check);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
@@ -1363,7 +1363,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
DBG1(DBG_IKE, "connectivity check verification failed");
check_destroy(check);
chunk_free(&sig);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
chunk_free(&sig);
@@ -1377,7 +1377,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
process_response(this, check, checklist);
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
check_destroy(check);
}
@@ -1392,7 +1392,7 @@ static bool check_and_register(private_connect_manager_t *this,
initiated_t *initiated;
bool already_there = TRUE;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
{
@@ -1408,7 +1408,7 @@ static bool check_and_register(private_connect_manager_t *this,
initiated->mediated->insert_last(initiated->mediated, mediated_sa->clone(mediated_sa));
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return already_there;
}
@@ -1421,12 +1421,12 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med
{
initiated_t *initiated;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
{
DBG2(DBG_IKE, "no waiting mediated connections with '%D'", peer_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
@@ -1439,7 +1439,7 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med
}
iterator->destroy(iterator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -1451,20 +1451,20 @@ static status_t set_initiator_data(private_connect_manager_t *this,
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, NULL) == SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' already exists, aborting",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return FAILED;
}
checklist = check_list_create(initiator, responder, connect_id, key, endpoints, is_initiator);
this->checklists->insert_last(this->checklists, checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1477,13 +1477,13 @@ static status_t set_responder_data(private_connect_manager_t *this,
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NOT_FOUND;
}
@@ -1496,7 +1496,7 @@ static status_t set_responder_data(private_connect_manager_t *this,
/* send the first check immediately */
schedule_checks(this, checklist, 0);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1508,13 +1508,13 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NOT_FOUND;
}
@@ -1523,7 +1523,7 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
remove_checklist(this, checklist);
check_list_destroy(checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1533,14 +1533,14 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
*/
static void destroy(private_connect_manager_t *this)
{
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
this->hasher->destroy(this->hasher);
this->checklists->destroy_function(this->checklists, (void*)check_list_destroy);
this->initiated->destroy_function(this->initiated, (void*)initiated_destroy);
- pthread_mutex_unlock(&(this->mutex));
- pthread_mutex_destroy(&(this->mutex));
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -1570,7 +1570,7 @@ connect_manager_t *connect_manager_create()
this->checklists = linked_list_create();
this->initiated = linked_list_create();
- pthread_mutex_init(&(this->mutex), NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return (connect_manager_t*)this;
}
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 7b2608e07..d9bb01c60 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.c 4394 2008-10-09 08:25:11Z martin $
+ * $Id: ike_sa.c 4652 2008-11-14 08:38:53Z martin $
*/
#include <sys/time.h>
@@ -23,6 +23,7 @@
#include <printf.h>
#include <sys/stat.h>
#include <errno.h>
+#include <time.h>
#include "ike_sa.h"
@@ -30,17 +31,6 @@
#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
-#include <crypto/diffie_hellman.h>
-#include <crypto/prf_plus.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/hashers/hasher.h>
-#include <encoding/payloads/sa_payload.h>
-#include <encoding/payloads/nonce_payload.h>
-#include <encoding/payloads/ke_payload.h>
-#include <encoding/payloads/delete_payload.h>
-#include <encoding/payloads/transform_substructure.h>
-#include <encoding/payloads/transform_attribute.h>
-#include <encoding/payloads/ts_payload.h>
#include <sa/task_manager.h>
#include <sa/tasks/ike_init.h>
#include <sa/tasks/ike_natd.h>
@@ -72,12 +62,13 @@
#define RESOLV_CONF "/etc/resolv.conf"
#endif
-ENUM(ike_sa_state_names, IKE_CREATED, IKE_DELETING,
+ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING,
"CREATED",
"CONNECTING",
"ESTABLISHED",
"REKEYING",
"DELETING",
+ "DESTROYING",
);
typedef struct private_ike_sa_t private_ike_sa_t;
@@ -128,6 +119,11 @@ struct private_ike_sa_t {
auth_info_t *other_auth;
/**
+ * Selected IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
* Juggles tasks to process messages
*/
task_manager_t *task_manager;
@@ -190,49 +186,9 @@ struct private_ike_sa_t {
linked_list_t *child_sas;
/**
- * String describing the selected IKE proposal
- */
- char *selected_proposal;
-
- /**
- * crypter for inbound traffic
- */
- crypter_t *crypter_in;
-
- /**
- * crypter for outbound traffic
- */
- crypter_t *crypter_out;
-
- /**
- * Signer for inbound traffic
- */
- signer_t *signer_in;
-
- /**
- * Signer for outbound traffic
+ * keymat of this IKE_SA
*/
- signer_t *signer_out;
-
- /**
- * Multi purpose prf, set key, use it, forget it
- */
- prf_t *prf;
-
- /**
- * Prf function for derivating keymat child SAs
- */
- prf_t *child_prf;
-
- /**
- * Key to build outging authentication data (SKp)
- */
- chunk_t skp_build;
-
- /**
- * Key to verify incoming authentication data (SKp)
- */
- chunk_t skp_verify;
+ keymat_t *keymat;
/**
* Virtual IP on local host, if any
@@ -268,34 +224,26 @@ struct private_ike_sa_t {
* NAT keep alive interval
*/
u_int32_t keepalive_interval;
-
+
/**
* Timestamps for this IKE_SA
*/
- struct {
- /** last IKE message received */
- u_int32_t inbound;
- /** last IKE message sent */
- u_int32_t outbound;
- /** when IKE_SA became established */
- u_int32_t established;
- /** when IKE_SA gets rekeyed */
- u_int32_t rekey;
- /** when IKE_SA gets reauthenticated */
- u_int32_t reauth;
- /** when IKE_SA gets deleted */
- u_int32_t delete;
- } time;
+ u_int32_t stats[STAT_MAX];
/**
* how many times we have retried so far (keyingtries)
*/
u_int32_t keyingtry;
-
+
/**
- * are we the initiator of this IKE_SA (rekeying does not affect this flag)
+ * local host address to be used for IKE, set via MIGRATE kernel message
*/
- bool ike_initiator;
+ host_t *local_host;
+
+ /**
+ * remote host address to be used for IKE, set via MIGRATE kernel message
+ */
+ host_t *remote_host;
};
/**
@@ -303,28 +251,26 @@ struct private_ike_sa_t {
*/
static time_t get_use_time(private_ike_sa_t* this, bool inbound)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
- time_t latest = 0, use_time;
-
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
- {
- if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS)
- {
- latest = max(latest, use_time);
- }
- }
- iterator->destroy(iterator);
+ time_t use_time;
if (inbound)
{
- return max(this->time.inbound, latest);
+ use_time = this->stats[STAT_INBOUND];
}
else
{
- return max(this->time.outbound, latest);
+ use_time = this->stats[STAT_OUTBOUND];
+ }
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ use_time = max(use_time, child_sa->get_usetime(child_sa, inbound));
}
+ enumerator->destroy(enumerator);
+
+ return use_time;
}
/**
@@ -352,24 +298,9 @@ static char *get_name(private_ike_sa_t *this)
*/
static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
{
- time_t now = time(NULL);
-
- switch (kind)
+ if (kind < STAT_MAX)
{
- case STAT_REKEY_TIME:
- if (this->time.rekey > now)
- {
- return this->time.rekey - now;
- }
- break;
- case STAT_REAUTH_TIME:
- if (this->time.reauth > now)
- {
- return this->time.reauth - now;
- }
- break;
- default:
- break;
+ return this->stats[kind];
}
return 0;
}
@@ -462,6 +393,23 @@ static auth_info_t* get_other_auth(private_ike_sa_t *this)
}
/**
+ * Implementation of ike_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_ike_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of ike_sa_t.set_proposal
+ */
+static void set_proposal(private_ike_sa_t *this, proposal_t *proposal)
+{
+ DESTROY_IF(this->proposal);
+ this->proposal = proposal->clone(proposal);
+}
+
+/**
* Implementation of ike_sa_t.send_keepalive
*/
static void send_keepalive(private_ike_sa_t *this)
@@ -518,14 +466,6 @@ static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg)
}
/**
- * Implementation of ike_sa_t.is_ike_initiator
- */
-static bool is_ike_initiator(private_ike_sa_t *this)
-{
- return this->ike_initiator;
-}
-
-/**
* Implementation of ike_sa_t.enable_extension.
*/
static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
@@ -687,47 +627,48 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
u_int32_t t;
/* calculate rekey, reauth and lifetime */
- this->time.established = time(NULL);
+ this->stats[STAT_ESTABLISHED] = time(NULL);
/* schedule rekeying if we have a time which is smaller than
* an already scheduled rekeying */
t = this->peer_cfg->get_rekey_time(this->peer_cfg);
- if (t && (this->time.rekey == 0 ||
- (this->time.rekey > t + this->time.established)))
+ if (t && (this->stats[STAT_REKEY] == 0 ||
+ (this->stats[STAT_REKEY] > t + this->stats[STAT_ESTABLISHED])))
{
- this->time.rekey = t + this->time.established;
+ this->stats[STAT_REKEY] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, FALSE);
charon->scheduler->schedule_job(charon->scheduler,
job, t * 1000);
DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
}
t = this->peer_cfg->get_reauth_time(this->peer_cfg);
- if (t && (this->time.reauth == 0 ||
- (this->time.reauth > t + this->time.established)))
+ if (t && (this->stats[STAT_REAUTH] == 0 ||
+ (this->stats[STAT_REAUTH] > t + this->stats[STAT_ESTABLISHED])))
{
- this->time.reauth = t + this->time.established;
+ this->stats[STAT_REAUTH] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
charon->scheduler->schedule_job(charon->scheduler,
job, t * 1000);
DBG1(DBG_IKE, "scheduling reauthentication in %ds", t);
}
t = this->peer_cfg->get_over_time(this->peer_cfg);
- if (this->time.rekey || this->time.reauth)
+ if (this->stats[STAT_REKEY] || this->stats[STAT_REAUTH])
{
- if (this->time.reauth == 0)
+ if (this->stats[STAT_REAUTH] == 0)
{
- this->time.delete = this->time.rekey;
+ this->stats[STAT_DELETE] = this->stats[STAT_REKEY];
}
- else if (this->time.rekey == 0)
+ else if (this->stats[STAT_REKEY] == 0)
{
- this->time.delete = this->time.reauth;
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH];
}
else
{
- this->time.delete = min(this->time.rekey, this->time.reauth);
+ this->stats[STAT_DELETE] = min(this->stats[STAT_REKEY],
+ this->stats[STAT_REAUTH]);
}
- this->time.delete += t;
- t = this->time.delete - this->time.established;
+ this->stats[STAT_DELETE] += t;
+ t = this->stats[STAT_DELETE] - this->stats[STAT_ESTABLISHED];
job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
charon->scheduler->schedule_job(charon->scheduler, job,
t * 1000);
@@ -750,7 +691,7 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
default:
break;
}
-
+ charon->bus->ike_state_change(charon->bus, &this->public, state);
this->state = state;
}
@@ -771,6 +712,14 @@ static void reset(private_ike_sa_t *this)
}
/**
+ * Implementation of ike_sa_t.get_keymat
+ */
+static keymat_t* get_keymat(private_ike_sa_t *this)
+{
+ return this->keymat;
+}
+
+/**
* Implementation of ike_sa_t.set_virtual_ip
*/
static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
@@ -925,8 +874,14 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa, this->my_host, this->other_host,
- has_condition(this, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa, this->my_host,
+ this->other_host, this->my_virtual_ip,
+ has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->public.rekey_child_sa(&this->public,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
@@ -938,9 +893,11 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
static status_t generate_message(private_ike_sa_t *this, message_t *message,
packet_t **packet)
{
- this->time.outbound = time(NULL);
+ this->stats[STAT_OUTBOUND] = time(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
- return message->generate(message, this->crypter_out, this->signer_out, packet);
+ return message->generate(message,
+ this->keymat->get_crypter(this->keymat, FALSE),
+ this->keymat->get_signer(this->keymat, FALSE), packet);
}
/**
@@ -978,6 +935,17 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
+/**
+ * Implementation of ike_sa_t.set_kmaddress.
+ */
+static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
+{
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
+ this->local_host = local->clone(local);
+ this->remote_host = remote->clone(remote);
+}
+
#ifdef ME
/**
* Implementation of ike_sa_t.act_as_mediation_server.
@@ -1082,26 +1050,42 @@ static void resolve_hosts(private_ike_sa_t *this)
{
host_t *host;
- host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
- 0, IKEV2_UDP_PORT);
+ if (this->remote_host)
+ {
+ host = this->remote_host->clone(this->remote_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+ 0, IKEV2_UDP_PORT);
+ }
if (host)
{
set_other_host(this, host);
}
- 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))
+ if (this->local_host)
{
- host->destroy(host);
- host = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, this->other_host, NULL);
- if (host)
+ host = this->local_host->clone(this->local_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ 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->set_port(host, IKEV2_UDP_PORT);
+ 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)
@@ -1128,12 +1112,11 @@ 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");
+ DBG1(DBG_IKE, "unable to initiate to %%any");
return DESTROY_ME;
}
- this->ike_initiator = TRUE;
+ set_condition(this, COND_ORIGINAL_INITIATOR, TRUE);
task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
this->task_manager->queue_task(this->task_manager, task);
@@ -1163,10 +1146,12 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
#ifdef ME
if (this->peer_cfg->is_mediation(this->peer_cfg))
{
- /* mediation connection */
if (this->state == IKE_ESTABLISHED)
- { /* FIXME: we should try to find a better solution to this */
- SIG_CHD(UP_SUCCESS, NULL, "mediation connection is already up and running");
+ {
+ /* mediation connection is already established, retrigger state change
+ * to notify bus listeners */
+ DBG1(DBG_IKE, "mediation connection is already up");
+ set_state(this, IKE_ESTABLISHED);
}
DESTROY_IF(child_cfg);
}
@@ -1216,9 +1201,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
if (this->state == IKE_DELETING)
{
- 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);
+ DBG1(DBG_IKE, "acquiring CHILD_SA {reqid %d} failed: "
+ "IKE_SA is deleting", reqid);
return FAILED;
}
@@ -1235,9 +1219,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
iterator->destroy(iterator);
if (!child_sa)
{
- 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);
+ DBG1(DBG_IKE, "acquiring CHILD_SA {reqid %d} failed: "
+ "CHILD_SA not found", reqid);
return FAILED;
}
@@ -1258,8 +1241,6 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
host_t *me, *other;
status_t status;
- SIG_CHD(ROUTE_START, NULL, "routing CHILD_SA");
-
/* check if not already routed*/
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
@@ -1268,7 +1249,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_CHD(ROUTE_FAILED, child_sa, "CHILD_SA with such a config already routed");
+ DBG1(DBG_IKE, "routing CHILD_SA failed: already routed");
return FAILED;
}
}
@@ -1278,8 +1259,8 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
case IKE_DELETING:
case IKE_REKEYING:
- SIG_CHD(ROUTE_FAILED, NULL,
- "unable to route CHILD_SA, as its IKE_SA gets deleted");
+ DBG1(DBG_IKE, "routing CHILD_SA failed: IKE_SA is %N",
+ ike_sa_state_names, this->state);
return FAILED;
case IKE_CREATED:
case IKE_CONNECTING:
@@ -1291,8 +1272,8 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
resolve_hosts(this);
/* install kernel policies */
- child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
- this->other_id, child_cfg, 0, FALSE);
+ child_sa = child_sa_create(this->my_host, this->other_host,
+ child_cfg, 0, FALSE);
me = this->my_host;
if (this->my_virtual_ip)
{
@@ -1306,18 +1287,21 @@ 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), PROTO_NONE);
+ 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_CHD(ROUTE_SUCCESS, child_sa, "CHILD_SA routed");
+ DBG1(DBG_IKE, "CHILD_SA routed");
}
else
{
- SIG_CHD(ROUTE_FAILED, child_sa, "routing CHILD_SA failed");
+ child_sa->destroy(child_sa);
+ DBG1(DBG_IKE, "routing CHILD_SA failed");
}
return status;
}
@@ -1331,8 +1315,6 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
child_sa_t *child_sa;
bool found = FALSE;
- SIG_CHD(UNROUTE_START, NULL, "unrouting CHILD_SA");
-
/* find CHILD_SA in ROUTED state */
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
@@ -1341,7 +1323,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_CHD(UNROUTE_SUCCESS, child_sa, "CHILD_SA unrouted");
+ DBG1(DBG_IKE, "CHILD_SA unrouted");
child_sa->destroy(child_sa);
found = TRUE;
break;
@@ -1351,7 +1333,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
if (!found)
{
- SIG_CHD(UNROUTE_FAILED, NULL, "CHILD_SA to unroute not found");
+ DBG1(DBG_IKE, "unrouting CHILD_SA failed: reqid %d not found", reqid);
return FAILED;
}
/* if we are not established, and we have no more routed childs, remove whole SA */
@@ -1362,6 +1344,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
}
return SUCCESS;
}
+
/**
* Implementation of ike_sa_t.process_message.
*/
@@ -1372,7 +1355,9 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
is_request = message->get_request(message);
- status = message->parse_body(message, this->crypter_in, this->signer_in);
+ status = message->parse_body(message,
+ this->keymat->get_crypter(this->keymat, TRUE),
+ this->keymat->get_signer(this->keymat, TRUE));
if (status != SUCCESS)
{
@@ -1431,7 +1416,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
me = message->get_destination(message);
other = message->get_source(message);
-
+
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_cfg == NULL)
{
@@ -1451,7 +1436,7 @@ 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);
+ this->stats[STAT_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)
@@ -1510,38 +1495,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
/**
- * Implementation of ike_sa_t.get_prf.
- */
-static prf_t *get_prf(private_ike_sa_t *this)
-{
- return this->prf;
-}
-
-/**
- * Implementation of ike_sa_t.get_prf.
- */
-static prf_t *get_child_prf(private_ike_sa_t *this)
-{
- return this->child_prf;
-}
-
-/**
- * Implementation of ike_sa_t.get_skp_bild
- */
-static chunk_t get_skp_build(private_ike_sa_t *this)
-{
- return this->skp_build;
-}
-
-/**
- * Implementation of ike_sa_t.get_skp_verify
- */
-static chunk_t get_skp_verify(private_ike_sa_t *this)
-{
- return this->skp_verify;
-}
-
-/**
* Implementation of ike_sa_t.get_id.
*/
static ike_sa_id_t* get_id(private_ike_sa_t *this)
@@ -1601,230 +1554,6 @@ static void set_eap_identity(private_ike_sa_t *this, identification_t *id)
}
/**
- * Implementation of ike_sa_t.derive_keys.
- */
-static status_t derive_keys(private_ike_sa_t *this,
- proposal_t *proposal, chunk_t secret,
- chunk_t nonce_i, chunk_t nonce_r,
- bool initiator, prf_t *child_prf, prf_t *old_prf)
-{
- prf_plus_t *prf_plus;
- chunk_t skeyseed, key, full_nonce, fixed_nonce, prf_plus_seed;
- u_int16_t alg, key_size;
- crypter_t *crypter_i, *crypter_r;
- signer_t *signer_i, *signer_r;
- u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)];
- chunk_t spi_i = chunk_from_buf(spi_i_buf);
- chunk_t spi_r = chunk_from_buf(spi_r_buf);
-
- /* Create SAs general purpose PRF first, we may use it here */
- if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, PSEUDO_RANDOM_FUNCTION);
- return FAILED;
- }
- this->prf = lib->crypto->create_prf(lib->crypto, alg);
- if (this->prf == NULL)
- {
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, PSEUDO_RANDOM_FUNCTION,
- pseudo_random_function_names, alg);
- return FAILED;
- }
- DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
- /* full nonce is used as seed for PRF+ ... */
- full_nonce = chunk_cat("cc", nonce_i, nonce_r);
- /* but the PRF may need a fixed key which only uses the first bytes of
- * the nonces. */
- switch (alg)
- {
- case PRF_AES128_XCBC:
- /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
- * not and therefore fixed key semantics apply to XCBC for key
- * derivation. */
- nonce_i.len = min(nonce_i.len, this->prf->get_key_size(this->prf)/2);
- nonce_r.len = min(nonce_r.len, this->prf->get_key_size(this->prf)/2);
- break;
- default:
- /* all other algorithms use variable key length, full nonce */
- break;
- }
- fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
- *((u_int64_t*)spi_i.ptr) = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
- *((u_int64_t*)spi_r.ptr) = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
- prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
-
- /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
- *
- * if we are rekeying, SKEYSEED is built on another way
- */
- if (child_prf == NULL) /* not rekeying */
- {
- /* SKEYSEED = prf(Ni | Nr, g^ir) */
- this->prf->set_key(this->prf, fixed_nonce);
- this->prf->allocate_bytes(this->prf, secret, &skeyseed);
- DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
- this->prf->set_key(this->prf, skeyseed);
- chunk_free(&skeyseed);
- chunk_free(&secret);
- prf_plus = prf_plus_create(this->prf, prf_plus_seed);
- }
- else
- {
- /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
- * use OLD SAs PRF functions for both prf_plus and prf */
- secret = chunk_cat("mc", secret, full_nonce);
- child_prf->allocate_bytes(child_prf, secret, &skeyseed);
- DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
- old_prf->set_key(old_prf, skeyseed);
- chunk_free(&skeyseed);
- chunk_free(&secret);
- prf_plus = prf_plus_create(old_prf, prf_plus_seed);
- }
- chunk_free(&full_nonce);
- chunk_free(&fixed_nonce);
- chunk_free(&prf_plus_seed);
-
- /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
-
- /* SK_d is used for generating CHILD_SA key mat => child_prf */
- proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL);
- this->child_prf = lib->crypto->create_prf(lib->crypto, alg);
- key_size = this->child_prf->get_key_size(this->child_prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_d secret %B", &key);
- this->child_prf->set_key(this->child_prf, key);
- chunk_free(&key);
-
- /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
- if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, INTEGRITY_ALGORITHM);
- return FAILED;
- }
- signer_i = lib->crypto->create_signer(lib->crypto, alg);
- signer_r = lib->crypto->create_signer(lib->crypto, alg);
- if (signer_i == NULL || signer_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, INTEGRITY_ALGORITHM,
- integrity_algorithm_names ,alg);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- key_size = signer_i->get_key_size(signer_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ai secret %B", &key);
- signer_i->set_key(signer_i, key);
- chunk_free(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ar secret %B", &key);
- signer_r->set_key(signer_r, key);
- chunk_free(&key);
-
- if (initiator)
- {
- this->signer_in = signer_r;
- this->signer_out = signer_i;
- }
- else
- {
- this->signer_in = signer_i;
- this->signer_out = signer_r;
- }
-
- /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
- if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, ENCRYPTION_ALGORITHM);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
- crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
- if (crypter_i == NULL || crypter_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
- transform_type_names, ENCRYPTION_ALGORITHM,
- encryption_algorithm_names, alg, key_size);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- key_size = crypter_i->get_key_size(crypter_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- crypter_i->set_key(crypter_i, key);
- chunk_free(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- crypter_r->set_key(crypter_r, key);
- chunk_free(&key);
-
- if (initiator)
- {
- this->crypter_in = crypter_r;
- this->crypter_out = crypter_i;
- }
- else
- {
- this->crypter_in = crypter_i;
- this->crypter_out = crypter_r;
- }
-
- /* SK_pi/SK_pr used for authentication => stored for later */
- key_size = this->prf->get_key_size(this->prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pi secret %B", &key);
- if (initiator)
- {
- this->skp_build = key;
- }
- else
- {
- this->skp_verify = key;
- }
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pr secret %B", &key);
- if (initiator)
- {
- this->skp_verify = key;
- }
- else
- {
- this->skp_build = key;
- }
-
- /* all done, prf_plus not needed anymore */
- prf_plus->destroy(prf_plus);
-
- return SUCCESS;
-}
-
-/**
- * Implementation of ike_sa_t.get_proposal.
- */
-static char* get_proposal(private_ike_sa_t *this)
-{
- return this->selected_proposal;
-}
-
-/**
- * Implementation of ike_sa_t.set_proposal.
- */
-static void set_proposal(private_ike_sa_t *this, char *proposal)
-{
- free(this->selected_proposal);
- this->selected_proposal = strdup(proposal);
-}
-
-/**
* Implementation of ike_sa_t.add_child_sa.
*/
static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
@@ -1939,10 +1668,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");
+ DBG1(DBG_IKE, "deleting unestablished IKE_SA");
break;
default:
- SIG_IKE(DOWN_SUCCESS, "destroying IKE_SA in state %N "
+ DBG1(DBG_IKE, "destroying IKE_SA in state %N "
"without notification", ike_sa_state_names, this->state);
break;
}
@@ -1972,7 +1701,7 @@ static status_t reauth(private_ike_sa_t *this)
/* we can't reauthenticate as responder when we use EAP or virtual IPs.
* If the peer does not support RFC4478, there is no way to keep the
* IKE_SA up. */
- if (!this->ike_initiator)
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR))
{
DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
if (this->other_virtual_ip != NULL ||
@@ -1985,7 +1714,8 @@ static status_t reauth(private_ike_sa_t *this)
{
time_t now = time(NULL);
- DBG1(DBG_IKE, "IKE_SA will timeout in %#V", &now, &this->time.delete);
+ DBG1(DBG_IKE, "IKE_SA will timeout in %#V",
+ &now, &this->stats[STAT_DELETE]);
return FAILED;
}
else
@@ -2049,7 +1779,7 @@ static status_t reestablish(private_ike_sa_t *this)
}
/* check if we are able to reestablish this IKE_SA */
- if (!this->ike_initiator &&
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
(this->other_virtual_ip != NULL ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
@@ -2133,7 +1863,7 @@ static status_t reestablish(private_ike_sa_t *this)
*/
static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
{
- this->time.outbound = time(NULL);
+ this->stats[STAT_OUTBOUND] = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
/* send a proper signal to brief interested bus listeners */
@@ -2146,19 +1876,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 "
- "(%d/%d) in background ", this->keyingtry + 1, tries);
+ DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
+ 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");
+ DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
break;
}
case IKE_DELETING:
- SIG_IKE(DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
+ DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
break;
case IKE_REKEYING:
- SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
+ DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
/* FALL */
default:
reestablish(this);
@@ -2184,9 +1914,10 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
charon->processor->queue_job(charon->processor,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
}
- else if (this->time.reauth == 0 || this->time.reauth > reauth_time)
+ else if (this->stats[STAT_REAUTH] == 0 ||
+ this->stats[STAT_REAUTH] > reauth_time)
{
- this->time.reauth = reauth_time;
+ this->stats[STAT_REAUTH] = reauth_time;
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
" in %ds", lifetime, lifetime - reduction);
charon->scheduler->schedule_job(charon->scheduler,
@@ -2196,7 +1927,7 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
else
{
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, reauthentication already "
- "scheduled in %ds", lifetime, this->time.reauth - time(NULL));
+ "scheduled in %ds", lifetime, this->stats[STAT_REAUTH] - time(NULL));
}
}
@@ -2275,7 +2006,6 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->other_host = other->other_host->clone(other->other_host);
this->my_id = other->my_id->clone(other->my_id);
this->other_id = other->other_id->clone(other->other_id);
- this->ike_initiator = other->ike_initiator;
/* apply virtual assigned IPs... */
if (other->my_virtual_ip)
@@ -2296,7 +2026,7 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->dns_servers->insert_first(this->dns_servers, ip);
}
- /* inherit NAT-T conditions */
+ /* inherit all conditions */
this->conditions = other->conditions;
if (this->conditions & COND_NAT_HERE)
{
@@ -2326,14 +2056,14 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->task_manager->adopt_tasks(this->task_manager, other->task_manager);
/* reauthentication timeout survives a rekeying */
- if (other->time.reauth)
+ if (other->stats[STAT_REAUTH])
{
time_t reauth, delete, now = time(NULL);
- this->time.reauth = other->time.reauth;
- reauth = this->time.reauth - now;
+ this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];
+ reauth = this->stats[STAT_REAUTH] - now;
delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);
- this->time.delete = this->time.reauth + delete;
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;
DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
"lifetime reduced to %ds", reauth, delete);
charon->scheduler->schedule_job(charon->scheduler,
@@ -2421,7 +2151,7 @@ static void remove_dns_servers(private_ike_sa_t *this)
if (!found)
{
/* write line untouched back to file */
- fwrite(orig_line.ptr, orig_line.len, 1, file);
+ ignore_result(fwrite(orig_line.ptr, orig_line.len, 1, file));
fprintf(file, "\n");
}
}
@@ -2475,7 +2205,7 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns)
{
this->dns_servers->insert_last(this->dns_servers, dns->clone(dns));
}
- fwrite(contents.ptr, contents.len, 1, file);
+ ignore_result(fwrite(contents.ptr, contents.len, 1, file));
fclose(file);
}
@@ -2485,19 +2215,17 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns)
*/
static void destroy(private_ike_sa_t *this)
{
+ charon->bus->set_sa(charon->bus, &this->public);
+
+ set_state(this, IKE_DESTROYING);
+
this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
- this->task_manager->destroy(this->task_manager);
+ /* unset SA after here to avoid usage by the listeners */
+ charon->bus->set_sa(charon->bus, NULL);
- DESTROY_IF(this->crypter_in);
- DESTROY_IF(this->crypter_out);
- DESTROY_IF(this->signer_in);
- DESTROY_IF(this->signer_out);
- DESTROY_IF(this->prf);
- DESTROY_IF(this->child_prf);
- chunk_free(&this->skp_verify);
- chunk_free(&this->skp_build);
- free(this->selected_proposal);
+ this->task_manager->destroy(this->task_manager);
+ this->keymat->destroy(this->keymat);
if (this->my_virtual_ip)
{
@@ -2535,12 +2263,15 @@ static void destroy(private_ike_sa_t *this)
DESTROY_IF(this->other_host);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
DESTROY_IF(this->eap_identity);
DESTROY_IF(this->ike_cfg);
DESTROY_IF(this->peer_cfg);
DESTROY_IF(this->my_auth);
DESTROY_IF(this->other_auth);
+ DESTROY_IF(this->proposal);
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
@@ -2570,6 +2301,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
this->public.get_my_auth = (auth_info_t*(*)(ike_sa_t*))get_my_auth;
this->public.get_other_auth = (auth_info_t*(*)(ike_sa_t*))get_other_auth;
+ this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
+ this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host;
this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host;
@@ -2588,7 +2321,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates;
this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates;
- this->public.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;
@@ -2597,13 +2329,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.destroy = (void (*)(ike_sa_t*))destroy;
this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
- this->public.get_prf = (prf_t* (*)(ike_sa_t*)) get_prf;
- this->public.get_child_prf = (prf_t* (*)(ike_sa_t *)) get_child_prf;
- this->public.get_skp_verify = (chunk_t (*)(ike_sa_t *)) get_skp_verify;
- this->public.get_skp_build = (chunk_t (*)(ike_sa_t *)) get_skp_build;
- this->public.derive_keys = (status_t (*)(ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys;
- this->public.get_proposal = (char* (*)(ike_sa_t*)) get_proposal;
- this->public.set_proposal = (void (*)(ike_sa_t*,char*)) set_proposal;
+ this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat;
this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa;
this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
@@ -2622,6 +2348,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server;
+ this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
#ifdef ME
this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
@@ -2637,34 +2364,24 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* initialize private fields */
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
this->child_sas = linked_list_create();
- this->my_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
- this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
+ this->my_host = host_create_any(AF_INET);
+ this->other_host = host_create_any(AF_INET);
this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->eap_identity = NULL;
this->extensions = 0;
this->conditions = 0;
- this->selected_proposal = NULL;
- this->crypter_in = NULL;
- this->crypter_out = NULL;
- this->signer_in = NULL;
- this->signer_out = NULL;
- this->prf = NULL;
- this->skp_verify = chunk_empty;
- this->skp_build = chunk_empty;
- this->child_prf = NULL;
+ this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id));
this->state = IKE_CREATED;
this->keepalive_interval = lib->settings->get_time(lib->settings,
"charon.keep_alive", KEEPALIVE_INTERVAL);
- this->time.inbound = this->time.outbound = time(NULL);
- this->time.established = 0;
- this->time.rekey = 0;
- this->time.reauth = 0;
- this->time.delete = 0;
+ memset(this->stats, 0, sizeof(this->stats));
+ this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time(NULL);
this->ike_cfg = NULL;
this->peer_cfg = NULL;
this->my_auth = auth_info_create();
this->other_auth = auth_info_create();
+ this->proposal = NULL;
this->task_manager = task_manager_create(&this->public);
this->unique_id = ++unique_id;
this->my_virtual_ip = NULL;
@@ -2674,7 +2391,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->nat_detection_dest = chunk_empty;
this->pending_updates = 0;
this->keyingtry = 0;
- this->ike_initiator = FALSE;
+ this->local_host = NULL;
+ this->remote_host = NULL;
#ifdef ME
this->is_mediation_server = FALSE;
this->server_reflexive_host = NULL;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 717d41647..5aa458704 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.h 4368 2008-10-06 13:37:04Z martin $
+ * $Id: ike_sa.h 4640 2008-11-12 16:07:17Z martin $
*/
/**
@@ -38,9 +38,7 @@ typedef struct ike_sa_t ike_sa_t;
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
#include <sa/tasks/task.h>
-#include <crypto/prfs/prf.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
+#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
#include <credentials/auth_info.h>
@@ -110,32 +108,41 @@ enum ike_condition_t {
* Faking NAT to enforce UDP encapsulation
*/
COND_NAT_FAKE = (1<<3),
-
+
/**
* peer has ben authenticated using EAP
*/
COND_EAP_AUTHENTICATED = (1<<4),
-
+
/**
* received a certificate request from the peer
*/
COND_CERTREQ_SEEN = (1<<5),
+
+ /**
+ * Local peer is the "original" IKE initiator. Unaffected from rekeying.
+ */
+ COND_ORIGINAL_INITIATOR = (1<<6),
};
/**
- * Information and statistics to query from an SA
+ * Timing information and statistics to query from an SA
*/
enum statistic_t {
-
- /**
- * Relative time for scheduled rekeying
- */
- STAT_REKEY_TIME,
-
- /**
- * Relative time for scheduled reauthentication
- */
- STAT_REAUTH_TIME,
+ /** Timestamp of SA establishement */
+ STAT_ESTABLISHED = 0,
+ /** Timestamp of scheudled rekeying */
+ STAT_REKEY,
+ /** Timestamp of scheudled reauthentication */
+ STAT_REAUTH,
+ /** Timestamp of scheudled delete */
+ STAT_DELETE,
+ /** Timestamp of last inbound IKE packet */
+ STAT_INBOUND,
+ /** Timestamp of last outbound IKE packet */
+ STAT_OUTBOUND,
+
+ STAT_MAX
};
/**
@@ -201,6 +208,11 @@ enum ike_sa_state_t {
* IKE_SA is in progress of deletion
*/
IKE_DELETING,
+
+ /**
+ * IKE_SA object gets destroyed
+ */
+ IKE_DESTROYING,
};
/**
@@ -388,6 +400,20 @@ struct ike_sa_t {
auth_info_t* (*get_other_auth)(ike_sa_t *this);
/**
+ * Get the selected proposal of this IKE_SA.
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(ike_sa_t *this);
+
+ /**
+ * Set the proposal selected for this IKE_SA.
+ *
+ * @param selected proposal
+ */
+ void (*set_proposal)(ike_sa_t *this, proposal_t *proposal);
+
+ /**
* Add an additional address for the peer.
*
* In MOBIKE, a peer may transmit additional addresses where it is
@@ -462,13 +488,6 @@ struct ike_sa_t {
*/
void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates);
- /**
- * Check if we are the original initiator of this IKE_SA (rekeying does not
- * change this flag).
- */
- bool (*is_ike_initiator)(ike_sa_t *this);
-
-
#ifdef ME
/**
* Activate mediation server functionality for this IKE_SA.
@@ -705,70 +724,13 @@ struct ike_sa_t {
* was sent.
*/
void (*send_keepalive) (ike_sa_t *this);
-
- /**
- * Derive all keys and create the transforms for IKE communication.
- *
- * Keys are derived using the diffie hellman secret, nonces and internal
- * stored SPIs.
- * Key derivation differs when an IKE_SA is set up to replace an
- * existing IKE_SA (rekeying). The SK_d key from the old IKE_SA
- * is included in the derivation process.
- *
- * @param proposal proposal which contains algorithms to use
- * @param secret secret derived from DH exchange, gets freed
- * @param nonce_i initiators nonce
- * @param nonce_r responders nonce
- * @param initiator TRUE if initiator, FALSE otherwise
- * @param child_prf PRF with SK_d key when rekeying, NULL otherwise
- * @param old_prf general purpose PRF of old SA when rekeying
- */
- status_t (*derive_keys)(ike_sa_t *this, proposal_t* proposal, chunk_t secret,
- chunk_t nonce_i, chunk_t nonce_r,
- bool initiator, prf_t *child_prf, prf_t *old_prf);
/**
- * Get the selected IKE proposal string
+ * Get the keying material of this IKE_SA.
*
- * @return string describing the selected IKE proposal
- */
- char* (*get_proposal)(ike_sa_t *this);
-
- /**
- * Set the selected IKE proposal string for status information purposes
- * (the "%P" printf format handler is used)
- *
- * @param proposal string describing the selected IKE proposal
- */
- void (*set_proposal)(ike_sa_t *this, char *proposal);
-
- /**
- * Get a multi purpose prf for the negotiated PRF function.
- *
- * @return pointer to prf_t object
- */
- prf_t *(*get_prf) (ike_sa_t *this);
-
- /**
- * Get the prf-object, which is used to derive keys for child SAs.
- *
- * @return pointer to prf_t object
- */
- prf_t *(*get_child_prf) (ike_sa_t *this);
-
- /**
- * Get the key to build outgoing authentication data.
- *
- * @return pointer to prf_t object
- */
- chunk_t (*get_skp_build) (ike_sa_t *this);
-
- /**
- * Get the key to verify incoming authentication data.
- *
- * @return pointer to prf_t object
+ * @return per IKE_SA keymat instance
*/
- chunk_t (*get_skp_verify) (ike_sa_t *this);
+ keymat_t* (*get_keymat)(ike_sa_t *this);
/**
* Associates a child SA to this IKE SA
@@ -901,6 +863,17 @@ struct ike_sa_t {
void (*add_dns_server) (ike_sa_t *this, host_t *dns);
/**
+ * Set local and remote host addresses to be used for IKE.
+ *
+ * These addresses are communicated via the KMADDRESS field of a MIGRATE
+ * message sent via the NETLINK or PF _KEY kernel socket interface.
+ *
+ * @param local local kmaddress
+ * @param remote remote kmaddress
+ */
+ void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
+
+ /**
* Inherit all attributes of other to this after rekeying.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index bd7b84c6f..a760409c0 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -13,10 +13,9 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa_manager.c 4234 2008-07-30 14:15:08Z martin $
+ * $Id: ike_sa_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
-#include <pthread.h>
#include <string.h>
#include "ike_sa_manager.h"
@@ -24,6 +23,7 @@
#include <daemon.h>
#include <sa/ike_sa_id.h>
#include <bus/bus.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
@@ -42,7 +42,7 @@ struct entry_t {
/**
* Condvar where threads can wait until ike_sa_t object is free for use again.
*/
- pthread_cond_t condvar;
+ condvar_t *condvar;
/**
* Is this ike_sa currently checked out?
@@ -107,6 +107,7 @@ static status_t entry_destroy(entry_t *this)
DESTROY_IF(this->other);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
+ this->condvar->destroy(this->condvar);
free(this);
return SUCCESS;
}
@@ -119,7 +120,7 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
entry_t *this = malloc_thing(entry_t);
this->waiting_threads = 0;
- pthread_cond_init(&this->condvar, NULL);
+ this->condvar = condvar_create(CONDVAR_DEFAULT);
/* we set checkout flag when we really give it out */
this->checked_out = FALSE;
@@ -155,7 +156,7 @@ struct private_ike_sa_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Linked list with entries for the ike_sa_t objects.
@@ -278,9 +279,9 @@ static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry)
while (entry->waiting_threads)
{
/* wake up all */
- pthread_cond_broadcast(&(entry->condvar));
+ entry->condvar->broadcast(entry->condvar);
/* they will wake us again when their work is done */
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
}
DBG2(DBG_MGR, "found entry by pointer, deleting it");
@@ -310,14 +311,14 @@ static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry)
/* so wait until we can get it for us.
* we register us as waiting. */
entry->waiting_threads++;
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
entry->waiting_threads--;
}
/* hm, a deletion request forbids us to get this SA, get next one */
if (entry->driveout_waiting_threads)
{
/* we must signal here, others may be waiting on it, too */
- pthread_cond_signal(&(entry->condvar));
+ entry->condvar->signal(entry->condvar);
return FALSE;
}
return TRUE;
@@ -345,7 +346,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
DBG2(DBG_MGR, "checkout IKE_SA, %d IKE_SAs in manager",
this->ike_sa_list->get_count(this->ike_sa_list));
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
{
if (wait_for_entry(this, entry))
@@ -355,7 +356,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
ike_sa = entry->ike_sa;
}
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
}
@@ -378,10 +379,10 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
}
entry = entry_create(id);
id->destroy(id);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
entry->checked_out = TRUE;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
DBG2(DBG_MGR, "created IKE_SA, %d IKE_SAs in manager",
this->ike_sa_list->get_count(this->ike_sa_list));
return entry->ike_sa;
@@ -413,7 +414,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
this->hasher->allocate_hash(this->hasher, data, &hash);
chunk_free(&data);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -422,7 +423,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
if (entry->message_id == 0)
{
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
chunk_free(&hash);
id->destroy(id);
DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
@@ -439,7 +440,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
if (ike_sa == NULL)
{
@@ -450,11 +451,11 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
id->set_responder_spi(id, get_next_spi(this));
entry = entry_create(id);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
entry->init_hash = hash;
ike_sa = entry->ike_sa;
}
@@ -473,7 +474,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
return ike_sa;
}
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_id(this, id, &entry) == SUCCESS)
{
/* only check out if we are not processing this request */
@@ -496,7 +497,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
ike_sa = entry->ike_sa;
}
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
id->destroy(id);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -521,7 +522,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (my_host && other_host && this->reuse_ikesa)
{
@@ -553,8 +554,9 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
/* IKE_SA has no IDs yet, so we can't use it */
continue;
}
- DBG2(DBG_MGR, "candidate IKE_SA for \n\t"
- "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
+ DBG2(DBG_MGR, "candidate IKE_SA for \n"
+ " %H[%D]...%H[%D]\n"
+ " %H[%D]...%H[%D]",
my_host, my_id, other_host, other_id,
found_my_host, found_my_id, found_other_host, found_other_id);
/* compare ID and hosts. Supplied ID may contain wildcards, and IP
@@ -603,7 +605,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
new_entry->checked_out = TRUE;
ike_sa = new_entry->ike_sa;
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
}
@@ -620,7 +622,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
@@ -657,7 +659,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -675,7 +677,7 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
@@ -712,7 +714,7 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -732,7 +734,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
me = ike_sa->get_my_id(ike_sa);
other = ike_sa->get_other_id(ike_sa);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -755,7 +757,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return duplicate;
}
@@ -764,7 +766,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
*/
static void enumerator_unlock(private_ike_sa_manager_t *this)
{
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -786,7 +788,7 @@ static bool enumerator_filter(private_ike_sa_manager_t *this,
*/
static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
return enumerator_create_filter(
this->ike_sa_list->create_enumerator(this->ike_sa_list),
(void*)enumerator_filter, this, (void*)enumerator_unlock);
@@ -812,7 +814,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
DBG2(DBG_MGR, "checkin IKE_SA");
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
/* look for the entry */
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
@@ -845,7 +847,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
entry->other_id = other_id->clone(other_id);
}
DBG2(DBG_MGR, "check-in of IKE_SA successful.");
- pthread_cond_signal(&(entry->condvar));
+ entry->condvar->signal(entry->condvar);
retval = SUCCESS;
}
else
@@ -857,7 +859,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
DBG2(DBG_MGR, "%d IKE_SAs in manager now",
this->ike_sa_list->get_count(this->ike_sa_list));
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, NULL);
return retval;
@@ -880,9 +882,8 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
ike_sa_id = ike_sa->get_id(ike_sa);
DBG2(DBG_MGR, "checkin and destroy IKE_SA");
- charon->bus->set_sa(charon->bus, NULL);
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
{
@@ -899,8 +900,9 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
DBG2(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
retval = NOT_FOUND;
}
+ charon->bus->set_sa(charon->bus, NULL);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return retval;
}
@@ -913,7 +915,7 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
entry_t *entry;
int count = 0;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -937,7 +939,7 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return count;
}
@@ -950,7 +952,7 @@ static void flush(private_ike_sa_manager_t *this)
enumerator_t *enumerator;
entry_t *entry;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
/* Step 1: drive out all waiting threads */
DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
@@ -970,9 +972,9 @@ static void flush(private_ike_sa_manager_t *this)
while (entry->waiting_threads)
{
/* wake up all */
- pthread_cond_broadcast(&(entry->condvar));
+ entry->condvar->broadcast(entry->condvar);
/* go sleeping until they are gone */
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
}
}
enumerator->destroy(enumerator);
@@ -981,6 +983,7 @@ static void flush(private_ike_sa_manager_t *this)
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
entry->ike_sa->delete(entry->ike_sa);
}
enumerator->destroy(enumerator);
@@ -990,9 +993,11 @@ static void flush(private_ike_sa_manager_t *this)
while (this->ike_sa_list->remove_last(this->ike_sa_list,
(void**)&entry) == SUCCESS)
{
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
entry_destroy(entry);
}
- pthread_mutex_unlock(&(this->mutex));
+ charon->bus->set_sa(charon->bus, NULL);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -1003,7 +1008,7 @@ static void destroy(private_ike_sa_manager_t *this)
this->ike_sa_list->destroy(this->ike_sa_list);
this->rng->destroy(this->rng);
this->hasher->destroy(this->hasher);
-
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -1046,7 +1051,7 @@ ike_sa_manager_t *ike_sa_manager_create()
return NULL;
}
this->ike_sa_list = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
this->reuse_ikesa = lib->settings->get_bool(lib->settings,
"charon.reuse_ikesa", TRUE);
return &this->public;
diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h
index 04b6d96c2..3f0752cc8 100644
--- a/src/charon/sa/ike_sa_manager.h
+++ b/src/charon/sa/ike_sa_manager.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa_manager.h 3819 2008-04-17 10:46:25Z martin $
+ * $Id: ike_sa_manager.h 4624 2008-11-11 13:11:44Z tobias $
*/
/**
@@ -59,7 +59,7 @@ struct ike_sa_manager_t {
* Create and check out a new IKE_SA.
*
* @param initiator TRUE for initiator, FALSE otherwise
- * @returns created andchecked out IKE_SA
+ * @returns created and checked out IKE_SA
*/
ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
@@ -67,13 +67,13 @@ struct ike_sa_manager_t {
* Checkout an IKE_SA by a message.
*
* In some situations, it is necessary that the manager knows the
- * message to use for the checkout. This has the folloing reasons:
+ * message to use for the checkout. This has the following reasons:
*
* 1. If the targeted IKE_SA is already processing a message, we do not
* check it out if the message ID is the same.
* 2. If it is an IKE_SA_INIT request, we have to check if it is a
* retransmission. If so, we have to drop the message, we would
- * create another unneded IKE_SA for each retransmitted packet.
+ * create another unneeded IKE_SA for each retransmitted packet.
*
* A call to checkout_by_message() returns a (maybe new created) IKE_SA.
* If processing the message does not make sense (for the reasons above),
diff --git a/src/charon/sa/keymat.c b/src/charon/sa/keymat.c
new file mode 100644
index 000000000..c65bfc3b7
--- /dev/null
+++ b/src/charon/sa/keymat.c
@@ -0,0 +1,568 @@
+/*
+ * 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 "keymat.h"
+
+#include <daemon.h>
+#include <crypto/prf_plus.h>
+
+typedef struct private_keymat_t private_keymat_t;
+
+/**
+ * Private data of an keymat_t object.
+ */
+struct private_keymat_t {
+
+ /**
+ * Public keymat_t interface.
+ */
+ keymat_t public;
+
+ /**
+ * IKE_SA Role, initiator or responder
+ */
+ bool initiator;
+
+ /**
+ * inbound signer (verify)
+ */
+ signer_t *signer_in;
+
+ /**
+ * outbound signer (sign)
+ */
+ signer_t *signer_out;
+
+ /**
+ * inbound crypter (decrypt)
+ */
+ crypter_t *crypter_in;
+
+ /**
+ * outbound crypter (encrypt)
+ */
+ crypter_t *crypter_out;
+
+ /**
+ * General purpose PRF
+ */
+ prf_t *prf;
+
+ /**
+ * Key to derive key material from for CHILD_SAs, rekeying
+ */
+ chunk_t skd;
+
+ /**
+ * Key to build outging authentication data (SKp)
+ */
+ chunk_t skp_build;
+
+ /**
+ * Key to verify incoming authentication data (SKp)
+ */
+ chunk_t skp_verify;
+};
+
+typedef struct keylen_entry_t keylen_entry_t;
+
+/**
+ * Implicit key length for an algorithm
+ */
+struct keylen_entry_t {
+ /** IKEv2 algorithm identifier */
+ int algo;
+ /** key length in bits */
+ int len;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Keylen for encryption algos
+ */
+keylen_entry_t keylen_enc[] = {
+ {ENCR_DES, 64},
+ {ENCR_3DES, 192},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Keylen for integrity algos
+ */
+keylen_entry_t keylen_int[] = {
+ {AUTH_HMAC_MD5_96, 128},
+ {AUTH_HMAC_SHA1_96, 160},
+ {AUTH_HMAC_SHA2_256_128, 256},
+ {AUTH_HMAC_SHA2_384_192, 384},
+ {AUTH_HMAC_SHA2_512_256, 512},
+ {AUTH_AES_XCBC_96, 128},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Lookup key length of an algorithm
+ */
+static int lookup_keylen(keylen_entry_t *list, int algo)
+{
+ while (list->algo != END_OF_LIST)
+ {
+ if (algo == list->algo)
+ {
+ return list->len;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of keymat_t.create_dh
+ */
+static diffie_hellman_t* create_dh(private_keymat_t *this,
+ diffie_hellman_group_t group)
+{
+ return lib->crypto->create_dh(lib->crypto, group);;
+}
+
+/**
+ * Implementation of keymat_t.derive_keys
+ */
+static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id,
+ private_keymat_t *rekey)
+{
+ chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
+ chunk_t spi_i, spi_r;
+ crypter_t *crypter_i, *crypter_r;
+ signer_t *signer_i, *signer_r;
+ prf_plus_t *prf_plus;
+ u_int16_t alg, key_size;
+
+ spi_i = chunk_alloca(sizeof(u_int64_t));
+ spi_r = chunk_alloca(sizeof(u_int64_t));
+
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+
+ /* Create SAs general purpose PRF first, we may use it here */
+ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return FALSE;
+ }
+ this->prf = lib->crypto->create_prf(lib->crypto, alg);
+ if (this->prf == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
+ /* full nonce is used as seed for PRF+ ... */
+ full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ /* but the PRF may need a fixed key which only uses the first bytes of
+ * the nonces. */
+ switch (alg)
+ {
+ case PRF_AES128_XCBC:
+ /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ * not and therefore fixed key semantics apply to XCBC for key
+ * derivation. */
+ key_size = this->prf->get_key_size(this->prf)/2;
+ nonce_i.len = min(nonce_i.len, key_size);
+ nonce_r.len = min(nonce_r.len, key_size);
+ break;
+ default:
+ /* all other algorithms use variable key length, full nonce */
+ break;
+ }
+ fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
+
+ /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
+ *
+ * if we are rekeying, SKEYSEED is built on another way
+ */
+ if (rekey == NULL) /* not rekeying */
+ {
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+ this->prf->set_key(this->prf, fixed_nonce);
+ this->prf->allocate_bytes(this->prf, secret, &skeyseed);
+ this->prf->set_key(this->prf, skeyseed);
+ prf_plus = prf_plus_create(this->prf, prf_plus_seed);
+ }
+ else
+ {
+ /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
+ * use OLD SAs PRF functions for both prf_plus and prf */
+ secret = chunk_cat("mc", secret, full_nonce);
+ rekey->prf->set_key(rekey->prf, rekey->skd);
+ rekey->prf->allocate_bytes(rekey->prf, secret, &skeyseed);
+ rekey->prf->set_key(rekey->prf, skeyseed);
+ prf_plus = prf_plus_create(rekey->prf, prf_plus_seed);
+ }
+ DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
+
+ chunk_clear(&skeyseed);
+ chunk_clear(&secret);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+
+ /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
+
+ /* SK_d is used for generating CHILD_SA key mat => store for later use */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &this->skd);
+ DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
+
+ /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, INTEGRITY_ALGORITHM);
+ return FALSE;
+ }
+ signer_i = lib->crypto->create_signer(lib->crypto, alg);
+ signer_r = lib->crypto->create_signer(lib->crypto, alg);
+ if (signer_i == NULL || signer_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, INTEGRITY_ALGORITHM,
+ integrity_algorithm_names ,alg);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ key_size = signer_i->get_key_size(signer_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ai secret %B", &key);
+ signer_i->set_key(signer_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ar secret %B", &key);
+ signer_r->set_key(signer_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->signer_in = signer_r;
+ this->signer_out = signer_i;
+ }
+ else
+ {
+ this->signer_in = signer_i;
+ this->signer_out = signer_r;
+ }
+
+ /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
+ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (crypter_i == NULL || crypter_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, alg, key_size);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ key_size = crypter_i->get_key_size(crypter_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ei secret %B", &key);
+ crypter_i->set_key(crypter_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_er secret %B", &key);
+ crypter_r->set_key(crypter_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->crypter_in = crypter_r;
+ this->crypter_out = crypter_i;
+ }
+ else
+ {
+ this->crypter_in = crypter_i;
+ this->crypter_out = crypter_r;
+ }
+
+ /* SK_pi/SK_pr used for authentication => stored for later */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pi secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_build = key;
+ }
+ else
+ {
+ this->skp_verify = key;
+ }
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pr secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_verify = key;
+ }
+ else
+ {
+ this->skp_build = key;
+ }
+
+ /* all done, prf_plus not needed anymore */
+ prf_plus->destroy(prf_plus);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.derive_child_keys
+ */
+static bool derive_child_keys(private_keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r)
+{
+ u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ chunk_t seed, secret = chunk_empty;
+ prf_plus_t *prf_plus;
+
+ if (dh)
+ {
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_CHD, "DH secret %B", &secret);
+ }
+ seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ DBG4(DBG_CHD, "seed %B", &seed);
+
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &enc_size))
+ {
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, enc_alg);
+
+ if (!enc_size)
+ {
+ enc_size = lookup_keylen(keylen_enc, enc_alg);
+ }
+ if (!enc_size)
+ {
+ DBG1(DBG_CHD, "no keylenth defined for %N",
+ encryption_algorithm_names, enc_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ enc_size /= 8;
+
+ /* CCM/GCM needs additional bytes */
+ switch (enc_alg)
+ {
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ enc_size += 3;
+ break;
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ enc_size += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size))
+ {
+ DBG2(DBG_CHD, " using %N for integrity",
+ integrity_algorithm_names, int_alg);
+
+ if (!int_size)
+ {
+ int_size = lookup_keylen(keylen_int, int_alg);
+ }
+ if (!int_size)
+ {
+ DBG1(DBG_CHD, "no keylenth defined for %N",
+ integrity_algorithm_names, int_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ int_size /= 8;
+ }
+
+ this->prf->set_key(this->prf, this->skd);
+ prf_plus = prf_plus_create(this->prf, seed);
+
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
+
+ prf_plus->destroy(prf_plus);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.get_signer
+ */
+static signer_t* get_signer(private_keymat_t *this, bool in)
+{
+ return in ? this->signer_in : this->signer_out;
+}
+
+/**
+ * Implementation of keymat_t.get_crypter
+ */
+static crypter_t* get_crypter(private_keymat_t *this, bool in)
+{
+ return in ? this->crypter_in : this->crypter_out;
+}
+
+/**
+ * Implementation of keymat_t.get_auth_octets
+ */
+static chunk_t get_auth_octets(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce,
+ identification_t *id)
+{
+ chunk_t chunk, idx, octets;
+ chunk_t skp;
+
+ skp = verify ? this->skp_verify : this->skp_build;
+
+ chunk = chunk_alloca(4);
+ memset(chunk.ptr, 0, chunk.len);
+ chunk.ptr[0] = id->get_type(id);
+ idx = chunk_cata("cc", chunk, id->get_encoding(id));
+
+ DBG3(DBG_IKE, "IDx' %B", &idx);
+ DBG3(DBG_IKE, "SK_p %B", &skp);
+ this->prf->set_key(this->prf, skp);
+ this->prf->allocate_bytes(this->prf, idx, &chunk);
+
+ octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
+ DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
+ return octets;
+}
+
+/**
+ * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
+ */
+#define IKEV2_KEY_PAD "Key Pad for IKEv2"
+#define IKEV2_KEY_PAD_LENGTH 17
+
+/**
+ * Implementation of keymat_t.get_psk_sig
+ */
+static chunk_t get_psk_sig(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce, chunk_t secret,
+ identification_t *id)
+{
+ chunk_t key_pad, key, sig, octets;
+
+ if (!secret.len)
+ { /* EAP uses SK_p if no MSK has been established */
+ secret = verify ? this->skp_verify : this->skp_build;
+ }
+ octets = get_auth_octets(this, verify, ike_sa_init, nonce, id);
+ /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
+ key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
+ this->prf->set_key(this->prf, secret);
+ this->prf->allocate_bytes(this->prf, key_pad, &key);
+ this->prf->set_key(this->prf, key);
+ this->prf->allocate_bytes(this->prf, octets, &sig);
+ DBG4(DBG_IKE, "secret %B", &secret);
+ DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
+ DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
+ chunk_free(&octets);
+ chunk_free(&key);
+
+ return sig;
+}
+
+/**
+ * Implementation of keymat_t.destroy.
+ */
+static void destroy(private_keymat_t *this)
+{
+ DESTROY_IF(this->signer_in);
+ DESTROY_IF(this->signer_out);
+ DESTROY_IF(this->crypter_in);
+ DESTROY_IF(this->crypter_out);
+ DESTROY_IF(this->prf);
+ chunk_clear(&this->skd);
+ chunk_clear(&this->skp_verify);
+ chunk_clear(&this->skp_build);
+ free(this);
+}
+
+/**
+ * See header
+ */
+keymat_t *keymat_create(bool initiator)
+{
+ private_keymat_t *this = malloc_thing(private_keymat_t);
+
+ this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh;
+ this->public.derive_ike_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey))derive_ike_keys;
+ this->public.derive_child_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r))derive_child_keys;
+ this->public.get_signer = (signer_t*(*)(keymat_t*, bool in))get_signer;
+ this->public.get_crypter = (crypter_t*(*)(keymat_t*, bool in))get_crypter;
+ this->public.get_auth_octets = (chunk_t(*)(keymat_t *, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id))get_auth_octets;
+ this->public.get_psk_sig = (chunk_t(*)(keymat_t*, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id))get_psk_sig;
+ this->public.destroy = (void(*)(keymat_t*))destroy;
+
+ this->initiator = initiator;
+
+ this->signer_in = NULL;
+ this->signer_out = NULL;
+ this->crypter_in = NULL;
+ this->crypter_out = NULL;
+ this->prf = NULL;
+ this->skd = chunk_empty;
+ this->skp_verify = chunk_empty;
+ this->skp_build = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/charon/sa/keymat.h b/src/charon/sa/keymat.h
new file mode 100644
index 000000000..3ca25da9e
--- /dev/null
+++ b/src/charon/sa/keymat.h
@@ -0,0 +1,154 @@
+/*
+ * 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$
+ */
+
+/**
+ * @defgroup keymat keymat
+ * @{ @ingroup sa
+ */
+
+#ifndef KEYMAT_H_
+#define KEYMAT_H_
+
+#include <library.h>
+#include <utils/identification.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <config/proposal.h>
+#include <sa/ike_sa_id.h>
+
+typedef struct keymat_t keymat_t;
+
+/**
+ * Derivation an management of sensitive keying material.
+ */
+struct keymat_t {
+
+ /**
+ * Create a diffie hellman object for key agreement.
+ *
+ * The diffie hellman is either for IKE negotiation/rekeying or
+ * CHILD_SA rekeying (using PFS). The resulting DH object must be passed
+ * to derive_keys or to derive_child_keys and destroyed after use
+ *
+ * @param group diffie hellman group
+ * @return DH object, NULL if group not supported
+ */
+ diffie_hellman_t* (*create_dh)(keymat_t *this, diffie_hellman_group_t group);
+
+ /**
+ * Derive keys for the IKE_SA.
+ *
+ * These keys are not handed out, but are used by the associated signers,
+ * crypters and authentication functions.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh()
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param id IKE_SA identifier
+ * @param rekey keymat of old SA if we are rekeying
+ * @return TRUE on success
+ */
+ bool (*derive_ike_keys)(keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey);
+ /**
+ * Derive keys for a CHILD_SA.
+ *
+ * The keys for the CHILD_SA are allocated in the integ and encr chunks.
+ * An implementation might hand out encrypted keys only, which are
+ * decrypted in the kernel before use.
+ * If no PFS is used for the CHILD_SA, dh can be NULL.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh(), or NULL
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param encr_i chunk to write initiators encryption key to
+ * @param integ_i chunk to write initiators integrity key to
+ * @param encr_r chunk to write responders encryption key to
+ * @param integ_r chunk to write responders integrity key to
+ * @return TRUE on success
+ */
+ bool (*derive_child_keys)(keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r);
+ /**
+ * Get a signer to sign/verify IKE messages.
+ *
+ * @param in TRUE for inbound (verify), FALSE for outbound (sign)
+ * @return signer
+ */
+ signer_t* (*get_signer)(keymat_t *this, bool in);
+
+ /*
+ * Get a crypter to en-/decrypt IKE messages.
+ *
+ * @param in TRUE for inbound (decrypt), FALSE for outbound (encrypt)
+ * @return crypter
+ */
+ crypter_t* (*get_crypter)(keymat_t *this, bool in);
+
+ /**
+ * Generate octets to use for authentication procedure (RFC4306 2.15).
+ *
+ * This method creates the plain octets and is usually signed by a private
+ * key. PSK and EAP authentication include a secret into the data, use
+ * the get_psk_sig() method instead.
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param id identity
+ * @return authentication octets
+ */
+ chunk_t (*get_auth_octets)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, identification_t *id);
+ /**
+ * Build the shared secret signature used for PSK and EAP authentication.
+ *
+ * This method wraps the get_auth_octets() method and additionally
+ * includes the secret into the signature. If no secret is given, SK_p is
+ * used as secret (used for EAP methods without MSK).
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param secret optional secret to include into signature
+ * @param id identity
+ * @return signature octets
+ */
+ chunk_t (*get_psk_sig)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, chunk_t secret, identification_t *id);
+ /**
+ * Destroy a keymat_t.
+ */
+ void (*destroy)(keymat_t *this);
+};
+
+/**
+ * Create a keymat instance.
+ *
+ * @param initiator TRUE if we are the initiator
+ * @return keymat instance
+ */
+keymat_t *keymat_create(bool initiator);
+
+#endif /* KEYMAT_ @}*/
diff --git a/src/charon/sa/mediation_manager.c b/src/charon/sa/mediation_manager.c
index d15f4c100..b508c48c3 100644
--- a/src/charon/sa/mediation_manager.c
+++ b/src/charon/sa/mediation_manager.c
@@ -12,13 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: mediation_manager.c 3773 2008-04-07 09:36:52Z tobias $
+ * $Id: mediation_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "mediation_manager.h"
-#include <pthread.h>
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <processing/jobs/mediation_job.h>
@@ -80,7 +80,7 @@ struct private_mediation_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Linked list with state entries.
@@ -182,7 +182,7 @@ static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
iterator_t *iterator;
peer_t *peer;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
@@ -199,7 +199,7 @@ static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
}
iterator->destroy(iterator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -211,7 +211,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
peer_t *peer;
bool found = FALSE;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
@@ -244,7 +244,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
requester->destroy(requester);
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -256,17 +256,17 @@ static ike_sa_id_t *check(private_mediation_manager_t *this,
peer_t *peer;
ike_sa_id_t *ike_sa_id;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NULL;
}
ike_sa_id = peer->ike_sa_id;
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return ike_sa_id;
}
@@ -280,7 +280,7 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
peer_t *peer;
ike_sa_id_t *ike_sa_id;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
@@ -294,13 +294,13 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
/* the peer is not online */
DBG2(DBG_IKE, "requested peer '%D' is offline, registering peer '%D'", peer_id, requester);
register_peer(peer, requester);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NULL;
}
ike_sa_id = peer->ike_sa_id;
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return ike_sa_id;
}
@@ -310,12 +310,12 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
*/
static void destroy(private_mediation_manager_t *this)
{
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
this->peers->destroy_function(this->peers, (void*)peer_destroy);
- pthread_mutex_unlock(&(this->mutex));
- pthread_mutex_destroy(&(this->mutex));
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -333,7 +333,7 @@ mediation_manager_t *mediation_manager_create()
this->public.check_and_register = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*,identification_t*))check_and_register;
this->peers = linked_list_create();
- pthread_mutex_init(&(this->mutex), NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return (mediation_manager_t*)this;
}
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index 25089477b..0630647c9 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 4320 2008-09-02 14:02:40Z martin $
+ * $Id: task_manager.c 4484 2008-10-27 11:13:33Z martin $
*/
#include "task_manager.h"
@@ -145,44 +145,15 @@ struct private_task_manager_t {
*/
static void flush(private_task_manager_t *this)
{
- task_t *task;
-
this->queued_tasks->destroy_offset(this->queued_tasks,
offsetof(task_t, destroy));
this->passive_tasks->destroy_offset(this->passive_tasks,
offsetof(task_t, destroy));
-
- /* emmit outstanding signals for tasks */
- while (this->active_tasks->remove_last(this->active_tasks,
- (void**)&task) == SUCCESS)
- {
- switch (task->get_type(task))
- {
- case IKE_AUTH:
- SIG_IKE(UP_FAILED, "establishing IKE_SA failed");
- break;
- case IKE_DELETE:
- SIG_IKE(DOWN_FAILED, "IKE_SA deleted");
- break;
- case IKE_REKEY:
- SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed");
- break;
- case CHILD_CREATE:
- SIG_CHD(UP_FAILED, NULL, "establishing CHILD_SA failed");
- break;
- case CHILD_DELETE:
- SIG_CHD(DOWN_FAILED, NULL, "deleting CHILD_SA failed");
- break;
- case CHILD_REKEY:
- SIG_IKE(REKEY_FAILED, "rekeying CHILD_SA failed");
- break;
- default:
- break;
- }
- task->destroy(task);
- }
+ this->active_tasks->destroy_offset(this->active_tasks,
+ offsetof(task_t, destroy));
this->queued_tasks = linked_list_create();
this->passive_tasks = linked_list_create();
+ this->active_tasks = linked_list_create();
}
/**
@@ -648,6 +619,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
DESTROY_IF(this->responding.packet);
status = this->ike_sa->generate_message(this->ike_sa, message,
&this->responding.packet);
+ charon->bus->message(charon->bus, message, FALSE);
message->destroy(message);
if (status != SUCCESS)
{
@@ -867,6 +839,7 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
{
if (mid == this->responding.mid)
{
+ charon->bus->message(charon->bus, msg, TRUE);
if (process_request(this, msg) != SUCCESS)
{
flush(this);
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index bddca621b..767ceef55 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2007 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: child_create.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_create.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "child_create.h"
@@ -97,6 +97,11 @@ struct private_child_create_t {
diffie_hellman_group_t dh_group;
/**
+ * IKE_SAs keymat
+ */
+ keymat_t *keymat;
+
+ /**
* mode the new CHILD_SA uses (transport/tunnel/beet)
*/
ipsec_mode_t mode;
@@ -191,38 +196,22 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host)
*/
static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
- prf_plus_t *prf_plus;
status_t status;
- chunk_t nonce_i, nonce_r, secret, seed;
+ chunk_t nonce_i, nonce_r, encr_i, integ_i, encr_r, integ_r;
linked_list_t *my_ts, *other_ts;
host_t *me, *other, *other_vip, *my_vip;
if (this->proposals == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "SA payload missing in message");
+ DBG1(DBG_IKE, "SA payload missing in message");
return FAILED;
}
if (this->tsi == NULL || this->tsr == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "TS payloads missing in message");
+ DBG1(DBG_IKE, "TS payloads missing in message");
return NOT_FOUND;
}
- if (this->initiator)
- {
- nonce_i = this->my_nonce;
- nonce_r = this->other_nonce;
- my_ts = this->tsi;
- other_ts = this->tsr;
- }
- else
- {
- nonce_r = this->my_nonce;
- nonce_i = this->other_nonce;
- my_ts = this->tsr;
- other_ts = this->tsi;
- }
-
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
@@ -232,7 +221,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
no_dh);
if (this->proposal == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
return FAILED;
}
@@ -243,15 +232,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_CHD(UP_FAILED, this->child_sa, "DH group %N inacceptable, "
- "requesting %N", diffie_hellman_group_names, this->dh_group,
- diffie_hellman_group_names, group);
+ DBG1(DBG_IKE, "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_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
return FAILED;
}
}
@@ -260,16 +249,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
my_vip = me;
}
- else if (this->initiator)
- {
- /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
- this->child_sa->set_virtual_ip(this->child_sa, my_vip);
- }
if (other_vip == NULL)
{
other_vip = other;
}
+ if (this->initiator)
+ {
+ nonce_i = this->my_nonce;
+ nonce_r = this->other_nonce;
+ my_ts = this->tsi;
+ other_ts = this->tsr;
+ }
+ else
+ {
+ nonce_r = this->my_nonce;
+ nonce_i = this->other_nonce;
+ my_ts = this->tsr;
+ other_ts = this->tsi;
+ }
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
my_vip);
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
@@ -279,7 +277,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_CHD(UP_FAILED, this->child_sa, "no acceptable traffic selectors found");
+ DBG1(DBG_IKE, "no acceptable traffic selectors found");
return NOT_FOUND;
}
@@ -302,16 +300,18 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
switch (this->mode)
{
case MODE_TRANSPORT:
- if (!ts_list_is_host(this->tsi, other) ||
- !ts_list_is_host(this->tsr, me))
+ if (!this->config->use_proxy_mode(this->config) &&
+ (!ts_list_is_host(this->tsi, other) ||
+ !ts_list_is_host(this->tsr, me))
+ )
{
this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
+ DBG1(DBG_IKE, "not using transport mode, not host-to-host");
}
else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
{
this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, connection NATed");
+ DBG1(DBG_IKE, "not using transport mode, connection NATed");
}
break;
case MODE_BEET:
@@ -327,55 +327,51 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
- if (this->dh)
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+
+ if (this->ipcomp != IPCOMP_NONE)
{
- if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
- {
- SIG_CHD(UP_FAILED, this->child_sa, "DH exchange incomplete");
- return FAILED;
- }
- DBG3(DBG_IKE, "DH secret %B", &secret);
- seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
+ this->other_cpi);
}
- else
+
+ status = FAILED;
+ if (this->keymat->derive_child_keys(this->keymat, this->proposal,
+ this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
{
- seed = chunk_cata("cc", nonce_i, nonce_r);
+ if (this->initiator)
+ {
+ status = this->child_sa->update(this->child_sa, this->proposal,
+ this->mode, integ_r, integ_i, encr_r, encr_i);
+ }
+ else
+ {
+ status = this->child_sa->add(this->child_sa, this->proposal,
+ this->mode, integ_i, integ_r, encr_i, encr_r);
+ }
}
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
- if (this->ipcomp != IPCOMP_NONE)
+ if (status != SUCCESS)
{
- this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
- this->other_cpi);
+ DBG1(DBG_IKE, "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, this->proposal->get_protocol(this->proposal));
if (status != SUCCESS)
{
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to install IPsec policies (SPD) in kernel");
+ DBG1(DBG_IKE, "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,
- this->mode, prf_plus);
- }
- else
- {
- status = this->child_sa->add(this->child_sa, this->proposal,
- this->mode, prf_plus);
- }
- prf_plus->destroy(prf_plus);
+ charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
+ nonce_i, nonce_r);
- if (status != SUCCESS)
- {
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to install IPsec SA (SAD) in kernel");
- return FAILED;
- }
/* 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);
@@ -499,7 +495,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
if (!this->initiator)
{
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
if (this->dh)
{
@@ -592,13 +588,13 @@ static status_t build_i(private_child_create_t *this, message_t *message)
if (this->reqid)
{
- SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{%d}",
- this->config->get_name(this->config), this->reqid);
+ DBG0(DBG_IKE, "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));
+ DBG0(DBG_IKE, "establishing CHILD_SA %s",
+ this->config->get_name(this->config));
}
/* reuse virtual IP if we already have one */
@@ -641,23 +637,19 @@ static status_t build_i(private_child_create_t *this, message_t *message)
this->dh_group == MODP_NONE);
this->mode = this->config->get_mode(this->config);
- this->child_sa = child_sa_create(
- 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->config, this->reqid,
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
{
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to allocate SPIs from kernel");
+ DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
return FAILED;
}
if (this->dh_group != MODP_NONE)
{
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
if (this->config->use_ipcomp(this->config)) {
@@ -679,7 +671,7 @@ static status_t build_i(private_child_create_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_child_create_t *this, message_t *message)
{
@@ -785,16 +777,15 @@ 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_CHD(UP_FAILED, NULL,
- "unable to create CHILD_SA while rekeying IKE_SA");
+ DBG1(DBG_IKE, "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_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable",
- this->tsr, this->tsi);
+ DBG1(DBG_IKE, "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;
@@ -813,8 +804,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
case INTERNAL_ADDRESS_FAILURE:
case FAILED_CP_REQUIRED:
{
- SIG_CHD(UP_FAILED, NULL, "configuration payload negotation "
- "failed, no CHILD_SA built");
+ DBG1(DBG_IKE,"configuration payload negotation "
+ "failed, no CHILD_SA built");
iterator->destroy(iterator);
handle_child_sa_failure(this, message);
return SUCCESS;
@@ -826,11 +817,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
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),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(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) &&
@@ -870,14 +858,14 @@ static status_t build_r(private_child_create_t *this, message_t *message)
build_payloads(this, message);
- 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));
+ DBG0(DBG_IKE, "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;
}
@@ -929,8 +917,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
case TS_UNACCEPTABLE:
case INVALID_SELECTORS:
{
- SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, "
- "no CHILD_SA built", notify_type_names, type);
+ DBG1(DBG_IKE, "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 */
@@ -963,35 +951,35 @@ static status_t process_i(private_child_create_t *this, message_t *message)
if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
{
- SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
- " but we did not send one previously, no CHILD_SA built");
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
+ " one, no CHILD_SA built");
handle_child_sa_failure(this, message);
return SUCCESS;
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
{
DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
- "IPComp is disabled");
+ "IPComp is disabled");
this->ipcomp = IPCOMP_NONE;
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
{
- SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
- " for a transform we did not propose, no CHILD_SA built");
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
+ "no CHILD_SA built");
handle_child_sa_failure(this, message);
return SUCCESS;
}
if (select_and_install(this, no_dh) == SUCCESS)
{
- 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));
+ DBG0(DBG_IKE, "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
{
@@ -1144,6 +1132,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
this->tsr = NULL;
this->dh = NULL;
this->dh_group = MODP_NONE;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
this->ipcomp = IPCOMP_NONE;
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index a3c74dc90..cab1d63f0 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 4366 2008-10-03 16:01:14Z martin $
+ * $Id: child_delete.c 4434 2008-10-14 08:52:13Z martin $
*/
#include "child_delete.h"
@@ -222,14 +222,13 @@ 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_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));
+ DBG0(DBG_IKE, "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);
}
@@ -254,7 +253,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_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
+ DBG1(DBG_IKE, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
@@ -278,7 +277,7 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
{
build_payloads(this, message);
}
- SIG_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
+ DBG1(DBG_IKE, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c
index 3953951a3..e50ad33be 100644
--- a/src/charon/sa/tasks/child_rekey.c
+++ b/src/charon/sa/tasks/child_rekey.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_rekey.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: child_rekey.c 4659 2008-11-14 14:05:47Z martin $
*/
#include "child_rekey.h"
@@ -23,6 +23,7 @@
#include <sa/tasks/child_create.h>
#include <sa/tasks/child_delete.h>
#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
typedef struct private_child_rekey_t private_child_rekey_t;
@@ -177,6 +178,31 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
protocol_id_t protocol;
u_int32_t spi;
child_sa_t *to_delete;
+ iterator_t *iterator;
+ payload_t *payload;
+
+ /* handle NO_ADDITIONAL_SAS notify */
+ 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;
+
+ if (notify->get_notify_type(notify) == NO_ADDITIONAL_SAS)
+ {
+ DBG1(DBG_IKE, "peer seems to not support CHILD_SA rekeying, "
+ "starting reauthentication");
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ iterator->destroy(iterator);
+ return SUCCESS;
+ }
+ }
+ }
+ iterator->destroy(iterator);
if (this->child_create->task.process(&this->child_create->task, message) == NEED_MORE)
{
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
index 51f37f1b0..5c3f33cbd 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 4276 2008-08-22 10:44:51Z martin $
+ * $Id: ike_auth.c 4463 2008-10-20 11:38:16Z martin $
*/
#include "ike_auth.h"
@@ -146,6 +146,8 @@ static bool check_uniqueness(private_ike_auth_t *this)
charon->ike_sa_manager->checkin(charon->ike_sa_manager, duplicate);
}
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
return cancel;
}
@@ -201,15 +203,15 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!config)
{
- SIG_IKE(UP_FAILED, "unable to authenticate, no peer config found");
+ DBG1(DBG_IKE, "unable to authenticate, no peer config found");
return FAILED;
}
auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
if (auth == NULL)
{
- SIG_IKE(UP_FAILED, "configured authentication class %N not supported",
- auth_class_names, get_auth_class(config));
+ DBG1(DBG_IKE, "configured authentication class %N not supported",
+ auth_class_names, get_auth_class(config));
return FAILED;
}
@@ -218,7 +220,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");
+ DBG1(DBG_IKE, "generating authentication data failed");
return FAILED;
}
message->add_payload(message, (payload_t*)auth_payload);
@@ -243,7 +245,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");
+ DBG1(DBG_IKE, "negotiation of own ID failed");
return FAILED;
}
this->ike_sa->set_my_id(this->ike_sa, me->clone(me));
@@ -284,8 +286,8 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
auth_payload->get_auth_method(auth_payload));
if (auth == NULL)
{
- SIG_IKE(UP_FAILED, "authentication method %N used by '%D' not "
- "supported", auth_method_names, auth_method,
+ DBG1(DBG_IKE, "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;
}
@@ -294,7 +296,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",
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
auth_method_names, auth_method);
return FAILED;
@@ -315,7 +317,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");
+ DBG1(DBG_IKE, "ID payload missing in message");
return FAILED;
}
@@ -325,7 +327,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);
+ DBG0(DBG_IKE, "peer ID '%D' unacceptable, '%D' required", id, req);
id->destroy(id);
return FAILED;
}
@@ -402,7 +404,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");
+ DBG1(DBG_IKE, "generating authentication data failed");
if (!this->initiator)
{
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -413,13 +415,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[%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_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "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_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -448,7 +450,7 @@ 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",
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
auth_class_names, AUTH_CLASS_EAP);
if (this->initiator)
@@ -460,13 +462,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[%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_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "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_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -482,7 +484,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");
+ DBG1(DBG_IKE, "EAP payload missing");
return FAILED;
}
switch (this->eap_auth->process(this->eap_auth, eap, &eap))
@@ -498,7 +500,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",
+ DBG0(DBG_IKE, "failed to authenticate against '%D' using EAP",
this->ike_sa->get_other_id(this->ike_sa));
return FAILED;
}
@@ -533,7 +535,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");
+ DBG1(DBG_IKE, "EAP payload missing");
return FAILED;
}
@@ -548,9 +550,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",
- this->ike_sa->get_other_id(this->ike_sa),
- auth_class_names, AUTH_CLASS_EAP);
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
+ this->ike_sa->get_other_id(this->ike_sa),
+ auth_class_names, AUTH_CLASS_EAP);
status = FAILED;
break;
}
@@ -665,9 +667,9 @@ 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'",
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG1(DBG_IKE, "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);
return FAILED;
}
@@ -689,13 +691,13 @@ 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[%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_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "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_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
@@ -706,7 +708,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
message->add_payload(message, (payload_t*)eap_payload);
if (status != NEED_MORE)
{
- SIG_IKE(UP_FAILED, "unable to initiate EAP authentication");
+ DBG1(DBG_IKE, "unable to initiate EAP authentication");
return FAILED;
}
@@ -766,7 +768,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",
+ DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -798,18 +800,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",
+ DBG0(DBG_IKE, "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[%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_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "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_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c
index 2d18c6a1e..cb17cc2dc 100644
--- a/src/charon/sa/tasks/ike_auth_lifetime.c
+++ b/src/charon/sa/tasks/ike_auth_lifetime.c
@@ -12,11 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_auth_lifetime.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: ike_auth_lifetime.c 4576 2008-11-05 08:32:38Z martin $
*/
#include "ike_auth_lifetime.h"
+#include <time.h>
+
#include <daemon.h>
#include <encoding/payloads/notify_payload.h>
@@ -47,9 +49,10 @@ static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *mess
chunk_t chunk;
u_int32_t lifetime;
- lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH_TIME);
+ lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH);
if (lifetime)
{
+ lifetime -= time(NULL);
chunk = chunk_from_thing(lifetime);
*(u_int32_t*)chunk.ptr = htonl(lifetime);
message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c
index 295f908cb..1c051853c 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 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_delete.c 4458 2008-10-17 03:44:06Z andreas $
*/
#include "ike_delete.h"
@@ -56,21 +56,21 @@ 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));
+ DBG0(DBG_IKE, "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));
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
return NEED_MORE;
}
@@ -80,6 +80,7 @@ static status_t build_i(private_ike_delete_t *this, message_t *message)
*/
static status_t process_i(private_ike_delete_t *this, message_t *message)
{
+ DBG0(DBG_IKE, "IKE_SA deleted");
/* completed, delete IKE_SA by returning FAILED */
return FAILED;
}
@@ -92,15 +93,15 @@ 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));
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+ DBG0(DBG_IKE, "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))
{
@@ -123,7 +124,7 @@ 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");
+ DBG0(DBG_IKE, "IKE_SA deleted");
if (this->simultaneous)
{
diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c
index 609b37a39..bd2cd39bb 100644
--- a/src/charon/sa/tasks/ike_init.c
+++ b/src/charon/sa/tasks/ike_init.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2007 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: ike_init.c 4206 2008-07-22 17:10:10Z andreas $
+ * $Id: ike_init.c 4531 2008-10-30 12:58:54Z martin $
*/
#include "ike_init.h"
@@ -64,11 +64,16 @@ struct private_ike_init_t {
diffie_hellman_group_t dh_group;
/**
- * Diffie hellman object used to generate public DH value.
+ * diffie hellman key exchange
*/
diffie_hellman_t *dh;
/**
+ * Keymat derivation (from IKE_SA)
+ */
+ keymat_t *keymat;
+
+ /**
* nonce chosen by us
*/
chunk_t my_nonce;
@@ -192,7 +197,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
if (!this->initiator)
{
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat,
+ this->dh_group);
}
if (this->dh)
{
@@ -230,26 +236,26 @@ 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[%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));
+ DBG0(DBG_IKE, "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);
+ DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES);
return FAILED;
}
-
+
/* if the DH group is set via use_dh_group(), we already have a DH object */
if (!this->dh)
{
this->dh_group = this->config->get_dh_group(this->config);
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
- if (this->dh == NULL)
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ if (!this->dh)
{
- SIG_IKE(UP_FAILED, "configured DH group %N not supported",
+ DBG1(DBG_IKE, "configured DH group %N not supported",
diffie_hellman_group_names, this->dh_group);
return FAILED;
}
@@ -261,7 +267,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");
+ DBG1(DBG_IKE, "error generating nonce");
return FAILED;
}
rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
@@ -296,8 +302,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",
- message->get_source(message));
+ DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
@@ -369,30 +374,30 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
*/
static status_t build_r(private_ike_init_t *this, message_t *message)
{
- chunk_t secret;
- status_t status;
-
+ keymat_t *old_keymat = NULL;
+ ike_sa_id_t *id;
+
/* check if we have everything we need */
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG_IKE(UP_FAILED, "received proposals inacceptable");
+ DBG1(DBG_IKE, "received proposals inacceptable");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
if (this->dh == NULL ||
- !this->proposal->has_dh_group(this->proposal, this->dh_group) ||
- this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
{
u_int16_t group;
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
{
- SIG_CHD(UP_FAILED, NULL, "DH group %N inacceptable, requesting %N",
- diffie_hellman_group_names, this->dh_group,
- diffie_hellman_group_names, group);
+ DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
+ diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
this->dh_group = group;
group = htons(group);
message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
@@ -400,49 +405,28 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
}
else
{
- SIG_IKE(UP_FAILED, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
}
return FAILED;
}
+ id = this->ike_sa->get_id(this->ike_sa);
if (this->old_sa)
- {
- ike_sa_id_t *id;
- prf_t *prf, *child_prf;
-
- /* Apply SPI if we are rekeying */
- id = this->ike_sa->get_id(this->ike_sa);
+ { /* rekeying: Apply SPI, include keymat from old SA in key derivation */
id->set_initiator_spi(id, this->proposal->get_spi(this->proposal));
-
- /* setup crypto keys for the rekeyed SA */
- prf = this->old_sa->get_prf(this->old_sa);
- child_prf = this->old_sa->get_child_prf(this->old_sa);
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->other_nonce, this->my_nonce,
- FALSE, child_prf, prf);
+ old_keymat = this->old_sa->get_keymat(this->old_sa);
}
- else
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ this->other_nonce, this->my_nonce, id, old_keymat))
{
- /* setup crypto keys */
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->other_nonce, this->my_nonce,
- FALSE, NULL, NULL);
- }
- if (status != SUCCESS)
- {
- SIG_IKE(UP_FAILED, "key derivation failed");
+ DBG1(DBG_IKE, "key derivation failed");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
-
- /* Keep the selected IKE proposal for status information purposes */
- {
- char buf[BUF_LEN];
-
- snprintf(buf, BUF_LEN, "%P", this->proposal);
- this->ike_sa->set_proposal(this->ike_sa, buf+4);
- }
-
+
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
+ this->other_nonce, this->my_nonce, this->old_sa);
+
build_payloads(this, message);
return SUCCESS;
}
@@ -452,8 +436,8 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
*/
static status_t process_i(private_ike_init_t *this, message_t *message)
{
- chunk_t secret;
- status_t status;
+ keymat_t *old_keymat = NULL;
+ ike_sa_id_t *id;
iterator_t *iterator;
payload_t *payload;
@@ -505,7 +489,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",
+ DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -525,55 +509,34 @@ 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");
+ DBG1(DBG_IKE, "peers proposal selection invalid");
return FAILED;
}
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
if (this->dh == NULL ||
- !this->proposal->has_dh_group(this->proposal, this->dh_group) ||
- this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
{
- SIG_IKE(UP_FAILED, "peer's DH group selection invalid");
+ DBG1(DBG_IKE, "peer DH group selection invalid");
return FAILED;
}
- /* Apply SPI if we are rekeying */
+ id = this->ike_sa->get_id(this->ike_sa);
if (this->old_sa)
- {
- ike_sa_id_t *id;
- prf_t *prf, *child_prf;
-
- id = this->ike_sa->get_id(this->ike_sa);
+ { /* rekeying: Apply SPI, include keymat from old SA in key derivation */
id->set_responder_spi(id, this->proposal->get_spi(this->proposal));
-
- /* setup crypto keys for the rekeyed SA */
- prf = this->old_sa->get_prf(this->old_sa);
- child_prf = this->old_sa->get_child_prf(this->old_sa);
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->my_nonce, this->other_nonce,
- TRUE, child_prf, prf);
+ old_keymat = this->old_sa->get_keymat(this->old_sa);
}
- else
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ this->my_nonce, this->other_nonce, id, old_keymat))
{
- /* setup crypto keys for a new SA */
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->my_nonce, this->other_nonce,
- TRUE, NULL, NULL);
- }
- if (status != SUCCESS)
- {
- SIG_IKE(UP_FAILED, "key derivation failed");
+ DBG1(DBG_IKE, "key derivation failed");
return FAILED;
}
-
- /* Keep the selected IKE proposal for status information purposes */
- {
- char buf[BUF_LEN];
-
- snprintf(buf, BUF_LEN, "%P", this->proposal);
- this->ike_sa->set_proposal(this->ike_sa, buf+4);
- }
-
+
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
+ this->my_nonce, this->other_nonce, this->old_sa);
+
return SUCCESS;
}
@@ -607,12 +570,12 @@ static chunk_t get_lower_nonce(private_ike_init_t *this)
static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->proposal);
- DESTROY_IF(this->dh);
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
this->proposal = NULL;
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ DESTROY_IF(this->dh);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
/**
@@ -620,8 +583,8 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
*/
static void destroy(private_ike_init_t *this)
{
- DESTROY_IF(this->proposal);
DESTROY_IF(this->dh);
+ DESTROY_IF(this->proposal);
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
chunk_free(&this->cookie);
@@ -654,6 +617,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
this->initiator = initiator;
this->dh_group = MODP_NONE;
this->dh = NULL;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->my_nonce = chunk_empty;
this->other_nonce = chunk_empty;
this->cookie = chunk_empty;
diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c
index a203dee58..f58d51341 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 4355 2008-09-25 07:56:58Z tobias $
+ * $Id: ike_me.c 4640 2008-11-12 16:07:17Z martin $
*/
#include "ike_me.h"
@@ -461,8 +461,7 @@ 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_CHD(UP_SUCCESS, NULL, "established mediation connection "
- "without CHILD_SA successfully");
+ DBG1(DBG_IKE, "established mediation connection successfully");
break;
}
@@ -642,8 +641,7 @@ 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_CHD(UP_SUCCESS, NULL, "established mediation connection "
- "without CHILD_SA successfully");
+ DBG1(DBG_IKE, "established mediation connection successfully");
break;
}
@@ -787,7 +785,7 @@ ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
- if (ike_sa->is_ike_initiator(ike_sa))
+ if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
{
if (initiator)
{
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index f6ee3f6ad..a791d1892 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 4394 2008-10-09 08:25:11Z martin $
+ * $Id: ike_mobike.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "ike_mobike.h"
@@ -251,10 +251,16 @@ static void update_children(private_ike_mobike_t *this)
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa,
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->ike_sa->rekey_child_sa(this->ike_sa,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c
index b84b2a387..61701075f 100644
--- a/src/charon/sa/tasks/ike_reauth.c
+++ b/src/charon/sa/tasks/ike_reauth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 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
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_reauth.c 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_reauth.c 4495 2008-10-28 16:07:06Z martin $
*/
#include "ike_reauth.h"
@@ -65,7 +65,6 @@ 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);
@@ -105,6 +104,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
{
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
@@ -132,6 +133,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
iterator->destroy(iterator);
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
@@ -141,6 +144,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
}
iterator->destroy(iterator);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
/* we always return failed to delete the obsolete IKE_SA */
return FAILED;
diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c
index 6c4ef4354..28d63cca7 100644
--- a/src/charon/sa/tasks/ike_rekey.c
+++ b/src/charon/sa/tasks/ike_rekey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_rekey.c 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_rekey.c 4659 2008-11-14 14:05:47Z martin $
*/
#include "ike_rekey.h"
@@ -144,7 +144,7 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message)
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return SUCCESS;
}
-
+
if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
{
return SUCCESS;
@@ -152,13 +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));
+ DBG0(DBG_IKE, "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;
}
@@ -170,7 +170,32 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
{
job_t *job;
ike_sa_id_t *to_delete;
+ iterator_t *iterator;
+ payload_t *payload;
+ /* handle NO_ADDITIONAL_SAS notify */
+ 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;
+
+ if (notify->get_notify_type(notify) == NO_ADDITIONAL_SAS)
+ {
+ DBG1(DBG_IKE, "peer seems to not support IKE rekeying, "
+ "starting reauthentication");
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ iterator->destroy(iterator);
+ return SUCCESS;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
switch (this->ike_init->task.process(&this->ike_init->task, message))
{
case FAILED:
@@ -198,13 +223,13 @@ 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));
+ DBG0(DBG_IKE, "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);
@@ -242,6 +267,8 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
this->new_sa = other->new_sa;
other->new_sa = NULL;
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
job = (job_t*)delete_ike_sa_job_create(to_delete, TRUE);
@@ -277,6 +304,8 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa)
{
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
this->new_sa);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
DESTROY_IF(this->collision);
@@ -303,6 +332,8 @@ static void destroy(private_ike_rekey_t *this)
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
this->new_sa);
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
if (this->ike_init)
{
diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c
index 3192b688a..fd15379f3 100644
--- a/src/charon/sa/tasks/task.c
+++ b/src/charon/sa/tasks/task.c
@@ -13,11 +13,12 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: task.c 3666 2008-03-26 18:40:19Z tobias $
+ * $Id: task.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "task.h"
+#ifdef ME
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_INIT",
"IKE_NATD",
@@ -31,11 +32,27 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DPD",
-#ifdef ME
"IKE_ME",
-#endif /* ME */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
);
-
+#else
+ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ "IKE_INIT",
+ "IKE_NATD",
+ "IKE_MOBIKE",
+ "IKE_AUTHENTICATE",
+ "IKE_AUTH_LIFETIME",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
+ "IKE_CONFIG",
+ "IKE_REKEY",
+ "IKE_REAUTH",
+ "IKE_DELETE",
+ "IKE_DPD",
+ "CHILD_CREATE",
+ "CHILD_DELETE",
+ "CHILD_REKEY",
+);
+#endif /* ME */