summaryrefslogtreecommitdiff
path: root/src/charon/sa/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/tasks')
-rw-r--r--src/charon/sa/tasks/child_create.c147
-rw-r--r--src/charon/sa/tasks/child_create.h34
-rw-r--r--src/charon/sa/tasks/child_delete.c44
-rw-r--r--src/charon/sa/tasks/child_delete.h28
-rw-r--r--src/charon/sa/tasks/child_rekey.c9
-rw-r--r--src/charon/sa/tasks/child_rekey.h28
-rw-r--r--src/charon/sa/tasks/ike_auth.c165
-rw-r--r--src/charon/sa/tasks/ike_auth.h25
-rw-r--r--src/charon/sa/tasks/ike_auth_lifetime.c9
-rw-r--r--src/charon/sa/tasks/ike_auth_lifetime.h26
-rw-r--r--src/charon/sa/tasks/ike_cert.c366
-rw-r--r--src/charon/sa/tasks/ike_cert_post.c260
-rw-r--r--src/charon/sa/tasks/ike_cert_post.h55
-rw-r--r--src/charon/sa/tasks/ike_cert_pre.c476
-rw-r--r--src/charon/sa/tasks/ike_cert_pre.h (renamed from src/charon/sa/tasks/ike_cert.h)40
-rw-r--r--src/charon/sa/tasks/ike_config.c49
-rw-r--r--src/charon/sa/tasks/ike_config.h25
-rw-r--r--src/charon/sa/tasks/ike_delete.c21
-rw-r--r--src/charon/sa/tasks/ike_delete.h25
-rw-r--r--src/charon/sa/tasks/ike_dpd.c9
-rw-r--r--src/charon/sa/tasks/ike_dpd.h25
-rw-r--r--src/charon/sa/tasks/ike_init.c144
-rw-r--r--src/charon/sa/tasks/ike_init.h28
-rw-r--r--src/charon/sa/tasks/ike_me.c (renamed from src/charon/sa/tasks/ike_p2p.c)300
-rw-r--r--src/charon/sa/tasks/ike_me.h (renamed from src/charon/sa/tasks/ike_p2p.h)72
-rw-r--r--src/charon/sa/tasks/ike_mobike.c64
-rw-r--r--src/charon/sa/tasks/ike_mobike.h35
-rw-r--r--src/charon/sa/tasks/ike_natd.c45
-rw-r--r--src/charon/sa/tasks/ike_natd.h25
-rw-r--r--src/charon/sa/tasks/ike_reauth.c41
-rw-r--r--src/charon/sa/tasks/ike_reauth.h26
-rw-r--r--src/charon/sa/tasks/ike_rekey.c9
-rw-r--r--src/charon/sa/tasks/ike_rekey.h28
-rw-r--r--src/charon/sa/tasks/task.c18
-rw-r--r--src/charon/sa/tasks/task.h58
35 files changed, 1689 insertions, 1070 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index 3947a84d1..4638da03e 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -1,11 +1,5 @@
-/**
- * @file child_create.c
- *
- * @brief Implementation of the child_create task.
- *
- */
-
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -19,6 +13,8 @@
* 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: child_create.c 3920 2008-05-08 16:19:11Z tobias $
*/
#include "child_create.h"
@@ -105,6 +101,21 @@ struct private_child_create_t {
mode_t mode;
/**
+ * IPComp transform to use
+ */
+ ipcomp_transform_t ipcomp;
+
+ /**
+ * IPComp transform proposed or accepted by the other peer
+ */
+ ipcomp_transform_t ipcomp_received;
+
+ /**
+ * Other Compression Parameter Index (CPI)
+ */
+ u_int16_t other_cpi;
+
+ /**
* reqid to use if we are rekeying
*/
u_int32_t reqid;
@@ -141,17 +152,16 @@ static status_t get_nonce(message_t *message, chunk_t *nonce)
*/
static status_t generate_nonce(chunk_t *nonce)
{
- status_t status;
- randomizer_t *randomizer = randomizer_create();
+ rng_t *rng;
- status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE,
- nonce);
- randomizer->destroy(randomizer);
- if (status != SUCCESS)
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
{
- DBG1(DBG_IKE, "error generating random nonce value");
+ DBG1(DBG_IKE, "error generating nonce value, no RNG found");
return FAILED;
}
+ rng->allocate_bytes(rng, NONCE_SIZE, nonce);
+ rng->destroy(rng);
return SUCCESS;
}
@@ -227,11 +237,11 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
{
- algorithm_t *algo;
+ u_int16_t group;
+
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
- &algo))
+ &group, NULL))
{
- u_int16_t group = algo->algorithm;
SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N",
diffie_hellman_group_names, this->dh_group,
diffie_hellman_group_names, group);
@@ -332,6 +342,12 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
+ if (this->ipcomp != IPCOMP_NONE)
+ {
+ this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
+ this->other_cpi);
+ }
+
if (this->initiator)
{
status = this->child_sa->update(this->child_sa, this->proposal,
@@ -422,6 +438,36 @@ static void build_payloads(private_child_create_t *this, message_t *message)
}
/**
+ * Adds an IPCOMP_SUPPORTED notify to the message, if possible
+ */
+static void build_ipcomp_supported_notify(private_child_create_t *this, message_t *message)
+{
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ return;
+ }
+
+ u_int16_t cpi = this->child_sa->get_my_cpi(this->child_sa);
+ if (cpi)
+ {
+ chunk_t cpi_chunk, tid_chunk, data;
+ u_int8_t tid = this->ipcomp;
+ cpi_chunk = chunk_from_thing(cpi);
+ tid_chunk = chunk_from_thing(tid);
+ data = chunk_cat("cc", cpi_chunk, tid_chunk);
+ message->add_notify(message, FALSE, IPCOMP_SUPPORTED, data);
+ chunk_free(&data);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ }
+}
+
+/**
* Read payloads from message
*/
static void process_payloads(private_child_create_t *this, message_t *message)
@@ -450,7 +496,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 = diffie_hellman_create(this->dh_group);
+ this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
}
if (this->dh)
{
@@ -476,6 +522,25 @@ static void process_payloads(private_child_create_t *this, message_t *message)
case USE_BEET_MODE:
this->mode = MODE_BEET;
break;
+ case IPCOMP_SUPPORTED:
+ {
+ chunk_t data = notify_payload->get_notification_data(notify_payload);
+ u_int16_t cpi = *(u_int16_t*)data.ptr;
+ ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
+ switch(ipcomp)
+ {
+ case IPCOMP_DEFLATE:
+ this->other_cpi = cpi;
+ this->ipcomp_received = ipcomp;
+ break;
+ case IPCOMP_LZS:
+ case IPCOMP_LZJH:
+ default:
+ DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
+ " ID we don't support %N", ipcomp_transform_names, ipcomp);
+ break;
+ }
+ }
default:
break;
}
@@ -540,11 +605,10 @@ static status_t build_i(private_child_create_t *this, message_t *message)
if (!this->reqid)
{
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = peer_cfg->get_my_virtual_ip(peer_cfg);
+ vip = peer_cfg->get_virtual_ip(peer_cfg);
if (vip)
{
propose_all = TRUE;
- vip->destroy(vip);
}
}
@@ -580,7 +644,13 @@ static status_t build_i(private_child_create_t *this, message_t *message)
if (this->dh_group != MODP_NONE)
{
- this->dh = diffie_hellman_create(this->dh_group);
+ this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ }
+
+ if (this->config->use_ipcomp(this->config)) {
+ /* IPCOMP_DEFLATE is the only transform we support at the moment */
+ this->ipcomp = IPCOMP_DEFLATE;
+ build_ipcomp_supported_notify(this, message);
}
build_payloads(this, message);
@@ -700,6 +770,16 @@ static status_t build_r(private_child_create_t *this, message_t *message)
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ if (this->config->use_ipcomp(this->config) && this->ipcomp_received != IPCOMP_NONE)
+ {
+ this->ipcomp = this->ipcomp_received;
+ build_ipcomp_supported_notify(this, message);
+ }
+ else if (this->ipcomp_received != IPCOMP_NONE)
+ {
+ DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify but IPComp is disabled, ignoring");
+ }
+
switch (select_and_install(this, no_dh))
{
case SUCCESS:
@@ -806,6 +886,25 @@ static status_t process_i(private_child_create_t *this, message_t *message)
process_payloads(this, message);
+ if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
+ {
+ SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify but we did not "
+ "send one previously, no CHILD_SA built");
+ 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");
+ this->ipcomp = IPCOMP_NONE;
+ }
+ else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
+ {
+ SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify for a transform "
+ "we did not propose, no CHILD_SA built");
+ return SUCCESS;
+ }
+
if (select_and_install(this, no_dh) == SUCCESS)
{
SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully",
@@ -884,6 +983,9 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
this->dh = NULL;
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->other_cpi = 0;
this->reqid = 0;
this->established = FALSE;
}
@@ -957,6 +1059,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
this->dh_group = MODP_NONE;
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->other_cpi = 0;
this->reqid = 0;
this->established = FALSE;
diff --git a/src/charon/sa/tasks/child_create.h b/src/charon/sa/tasks/child_create.h
index 9f4815215..cee37121e 100644
--- a/src/charon/sa/tasks/child_create.h
+++ b/src/charon/sa/tasks/child_create.h
@@ -1,10 +1,3 @@
-/**
- * @file child_create.h
- *
- * @brief Interface child_create_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: child_create.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup child_create child_create
+ * @{ @ingroup tasks
*/
#ifndef CHILD_CREATE_H_
@@ -31,15 +31,10 @@ typedef struct child_create_t child_create_t;
#include <config/child_cfg.h>
/**
- * @brief Task of type CHILD_CREATE, established a new CHILD_SA.
+ * Task of type CHILD_CREATE, established a new CHILD_SA.
*
* This task may be included in the IKE_AUTH message or in a separate
* CREATE_CHILD_SA exchange.
- *
- * @b Constructors:
- * - child_create_create()
- *
- * @ingroup tasks
*/
struct child_create_t {
@@ -49,35 +44,32 @@ struct child_create_t {
task_t task;
/**
- * @brief Use a specific reqid for the CHILD_SA.
+ * Use a specific reqid for the CHILD_SA.
*
* When this task is used for rekeying, the same reqid is used
* for the new CHILD_SA.
*
- * @param this calling object
* @param reqid reqid to use
*/
void (*use_reqid) (child_create_t *this, u_int32_t reqid);
/**
- * @brief Get the lower of the two nonces, used for rekey collisions.
+ * Get the lower of the two nonces, used for rekey collisions.
*
- * @param this calling object
* @return lower nonce
*/
chunk_t (*get_lower_nonce) (child_create_t *this);
/**
- * @brief Get the CHILD_SA established/establishing by this task.
+ * Get the CHILD_SA established/establishing by this task.
*
- * @param this calling object
* @return child_sa
*/
child_sa_t* (*get_child) (child_create_t *this);
};
/**
- * @brief Create a new child_create task.
+ * Create a new child_create task.
*
* @param ike_sa IKE_SA this task works for
* @param config child_cfg if task initiator, NULL if responder
@@ -85,4 +77,4 @@ struct child_create_t {
*/
child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config);
-#endif /* CHILD_CREATE_H_ */
+#endif /* CHILD_CREATE_H_ @} */
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index d0b34a276..4156f9704 100644
--- a/src/charon/sa/tasks/child_delete.c
+++ b/src/charon/sa/tasks/child_delete.c
@@ -1,10 +1,3 @@
-/**
- * @file child_delete.c
- *
- * @brief Implementation of the child_delete task.
- *
- */
-
/*
* Copyright (C) 2006-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: child_delete.c 3802 2008-04-14 08:17:18Z martin $
*/
#include "child_delete.h"
@@ -157,23 +152,48 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
}
/**
- * destroy the children listed in this->child_sas
+ * destroy the children listed in this->child_sas, reestablish by policy
*/
-static void destroy_children(private_child_delete_t *this)
+static status_t destroy_and_reestablish(private_child_delete_t *this)
{
iterator_t *iterator;
child_sa_t *child_sa;
+ child_cfg_t *child_cfg;
protocol_id_t protocol;
u_int32_t spi;
+ status_t status = SUCCESS;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
spi = child_sa->get_spi(child_sa, TRUE);
protocol = child_sa->get_protocol(child_sa);
+ child_cfg = child_sa->get_config(child_sa);
+ child_cfg->get_ref(child_cfg);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
+ if (!this->initiator)
+ { /* enforce child_cfg policy if deleted passively */
+ switch (child_cfg->get_close_action(child_cfg))
+ {
+ case ACTION_RESTART:
+ child_cfg->get_ref(child_cfg);
+ status = this->ike_sa->initiate(this->ike_sa, child_cfg);
+ break;
+ case ACTION_ROUTE:
+ status = this->ike_sa->route(this->ike_sa, child_cfg);
+ break;
+ default:
+ break;
+ }
+ }
+ child_cfg->destroy(child_cfg);
+ if (status != SUCCESS)
+ {
+ break;
+ }
}
iterator->destroy(iterator);
+ return status;
}
/**
@@ -214,9 +234,8 @@ static status_t process_i(private_child_delete_t *this, message_t *message)
this->child_sas = linked_list_create();
process_payloads(this, message);
- destroy_children(this);
SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
- return SUCCESS;
+ return destroy_and_reestablish(this);
}
/**
@@ -239,9 +258,8 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
{
build_payloads(this, message);
}
- destroy_children(this);
SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
- return SUCCESS;
+ return destroy_and_reestablish(this);
}
/**
diff --git a/src/charon/sa/tasks/child_delete.h b/src/charon/sa/tasks/child_delete.h
index a7e676a50..c304ea9d8 100644
--- a/src/charon/sa/tasks/child_delete.h
+++ b/src/charon/sa/tasks/child_delete.h
@@ -1,10 +1,3 @@
-/**
- * @file child_delete.h
- *
- * @brief Interface child_delete_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: child_delete.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup child_delete child_delete
+ * @{ @ingroup tasks
*/
#ifndef CHILD_DELETE_H_
@@ -31,12 +31,7 @@ typedef struct child_delete_t child_delete_t;
#include <sa/child_sa.h>
/**
- * @brief Task of type child_delete, delete a CHILD_SA.
- *
- * @b Constructors:
- * - child_delete_create()
- *
- * @ingroup tasks
+ * Task of type child_delete, delete a CHILD_SA.
*/
struct child_delete_t {
@@ -46,16 +41,15 @@ struct child_delete_t {
task_t task;
/**
- * @brief Get the CHILD_SA to delete by this task.
+ * Get the CHILD_SA to delete by this task.
*
- * @param this calling object
* @return child_sa
*/
child_sa_t* (*get_child) (child_delete_t *this);
};
/**
- * @brief Create a new child_delete task.
+ * Create a new child_delete task.
*
* @param ike_sa IKE_SA this task works for
* @param child_sa CHILD_SA to delete, or NULL as responder
@@ -63,4 +57,4 @@ struct child_delete_t {
*/
child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa);
-#endif /* CHILD_DELETE_H_ */
+#endif /* CHILD_DELETE_H_ @} */
diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c
index 3667d8fad..3953951a3 100644
--- a/src/charon/sa/tasks/child_rekey.c
+++ b/src/charon/sa/tasks/child_rekey.c
@@ -1,10 +1,3 @@
-/**
- * @file child_rekey.c
- *
- * @brief Implementation of the child_rekey task.
- *
- */
-
/*
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,8 @@
* 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: child_rekey.c 3589 2008-03-13 14:14:44Z martin $
*/
#include "child_rekey.h"
diff --git a/src/charon/sa/tasks/child_rekey.h b/src/charon/sa/tasks/child_rekey.h
index 3515f0c3f..b386ef3c6 100644
--- a/src/charon/sa/tasks/child_rekey.h
+++ b/src/charon/sa/tasks/child_rekey.h
@@ -1,10 +1,3 @@
-/**
- * @file child_rekey.h
- *
- * @brief Interface child_rekey_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: child_rekey.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup child_rekey child_rekey
+ * @{ @ingroup tasks
*/
#ifndef CHILD_REKEY_H_
@@ -31,12 +31,7 @@ typedef struct child_rekey_t child_rekey_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type CHILD_REKEY, rekey an established CHILD_SA.
- *
- * @b Constructors:
- * - child_rekey_create()
- *
- * @ingroup tasks
+ * Task of type CHILD_REKEY, rekey an established CHILD_SA.
*/
struct child_rekey_t {
@@ -46,20 +41,19 @@ struct child_rekey_t {
task_t task;
/**
- * @brief Register a rekeying task which collides with this one
+ * Register a rekeying task which collides with this one
*
* If two peers initiate rekeying at the same time, the collision must
* be handled gracefully. The task manager is aware of what exchanges
* are going on and notifies the outgoing task by passing the incoming.
*
- * @param this task initated by us
* @param other incoming task
*/
void (*collide)(child_rekey_t* this, task_t *other);
};
/**
- * @brief Create a new CHILD_REKEY task.
+ * Create a new CHILD_REKEY task.
*
* @param ike_sa IKE_SA this task works for
* @param child_sa child_sa to rekey, NULL if responder
@@ -67,4 +61,4 @@ struct child_rekey_t {
*/
child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa);
-#endif /* CHILD_REKEY_H_ */
+#endif /* CHILD_REKEY_H_ @} */
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
index de88a0abe..fd5012ee6 100644
--- a/src/charon/sa/tasks/ike_auth.c
+++ b/src/charon/sa/tasks/ike_auth.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_auth.c
- *
- * @brief Implementation of the ike_auth task.
- *
- */
-
/*
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -18,7 +11,9 @@
* 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.
+ * for more details
+ *
+ * $Id: ike_auth.c 4051 2008-06-10 09:08:27Z tobias $
*/
#include "ike_auth.h"
@@ -94,6 +89,68 @@ struct private_ike_auth_t {
};
/**
+ * check uniqueness and delete duplicates
+ */
+static bool check_uniqueness(private_ike_auth_t *this)
+{
+ ike_sa_t *duplicate;
+ unique_policy_t policy;
+ status_t status = SUCCESS;
+ peer_cfg_t *peer_cfg;
+ bool cancel = FALSE;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ policy = peer_cfg->get_unique_policy(peer_cfg);
+ if (policy == UNIQUE_NO)
+ {
+ return FALSE;
+ }
+ duplicate = charon->ike_sa_manager->checkout_duplicate(
+ charon->ike_sa_manager, this->ike_sa);
+ if (duplicate)
+ {
+ peer_cfg = duplicate->get_peer_cfg(duplicate);
+ if (peer_cfg &&
+ peer_cfg->equals(peer_cfg, this->ike_sa->get_peer_cfg(this->ike_sa)))
+ {
+ switch (duplicate->get_state(duplicate))
+ {
+ case IKE_ESTABLISHED:
+ case IKE_REKEYING:
+ switch (policy)
+ {
+ case UNIQUE_REPLACE:
+ DBG1(DBG_IKE, "deleting duplicate IKE_SA due "
+ "uniqueness policy");
+ status = duplicate->delete(duplicate);
+ break;
+ case UNIQUE_KEEP:
+ DBG1(DBG_IKE, "cancelling IKE_SA setup due "
+ "uniqueness policy");
+ cancel = TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (status == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ duplicate);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, duplicate);
+ }
+ }
+ return cancel;
+}
+
+/**
* build the AUTH payload
*/
static status_t build_auth(private_ike_auth_t *this, message_t *message)
@@ -101,7 +158,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
authenticator_t *auth;
auth_payload_t *auth_payload;
peer_cfg_t *config;
- auth_method_t method;
+ config_auth_method_t method;
status_t status;
/* create own authenticator and add auth payload */
@@ -117,7 +174,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
if (auth == NULL)
{
SIG(IKE_UP_FAILED, "configured authentication method %N not supported",
- auth_method_names, method);
+ config_auth_method_names, method);
return FAILED;
}
@@ -186,13 +243,13 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
/* AUTH payload is missing, client wants to use EAP authentication */
return NOT_FOUND;
}
-
+
auth_method = auth_payload->get_auth_method(auth_payload);
- auth = authenticator_create(this->ike_sa, auth_method);
+ auth = authenticator_create_from_auth_payload(this->ike_sa, auth_payload);
if (auth == NULL)
{
- SIG(IKE_UP_FAILED, "authentication method %N used by %D not "
+ SIG(IKE_UP_FAILED, "authentication method %N used by '%D' not "
"supported", auth_method_names, auth_method,
this->ike_sa->get_other_id(this->ike_sa));
return NOT_SUPPORTED;
@@ -231,9 +288,9 @@ static status_t process_id(private_ike_auth_t *this, message_t *message)
{
id = idr->get_identification(idr);
req = this->ike_sa->get_other_id(this->ike_sa);
- if (!id->matches(id, req, NULL))
+ if (!id->matches(id, req))
{
- SIG(IKE_UP_FAILED, "peer ID %D unacceptable, %D required", id, req);
+ SIG(IKE_UP_FAILED, "peer ID '%D' unacceptable, '%D' required", id, req);
id->destroy(id);
return FAILED;
}
@@ -321,12 +378,12 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
if (!this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D",
+ SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_my_host(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_my_id(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -367,12 +424,12 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
if (this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D",
+ SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_my_host(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_my_id(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -404,7 +461,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
default:
this->eap_payload = NULL;
- SIG(IKE_UP_FAILED, "failed to authenticate against %D using EAP",
+ SIG(IKE_UP_FAILED, "failed to authenticate against '%D' using EAP",
this->ike_sa->get_other_id(this->ike_sa));
return FAILED;
}
@@ -482,7 +539,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
}
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (config->get_auth_method(config) == AUTH_EAP)
+ if (config->get_auth_method(config) == CONF_AUTH_EAP)
{
this->eap_auth = eap_authenticator_create(this->ike_sa);
}
@@ -525,13 +582,13 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
this->eap_auth = eap_authenticator_create(this->ike_sa);
break;
default:
- break;
+ return NEED_MORE;
}
config = charon->backends->get_peer_cfg(charon->backends,
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_other_ca(this->ike_sa));
+ this->ike_sa->get_other_auth(this->ike_sa));
if (config)
{
this->ike_sa->set_peer_cfg(this->ike_sa, config);
@@ -557,10 +614,17 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
return collect_my_init_data(this, message);
}
+ if (!this->peer_authenticated && this->eap_auth == NULL)
+ {
+ /* peer not authenticated, nor does it want to use EAP */
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
+ return FAILED;
+ }
+
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config == NULL)
{
- SIG(IKE_UP_FAILED, "no matching config found for %D...%D",
+ SIG(IKE_UP_FAILED, "no matching config found for '%D'...'%D'",
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -574,26 +638,25 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
return FAILED;
}
+ if (check_uniqueness(this))
+ {
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
+ return FAILED;
+ }
+
/* use "traditional" authentication if we could authenticate peer */
if (this->peer_authenticated)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D",
+ SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_my_host(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_my_id(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
return SUCCESS;
}
- if (this->eap_auth == NULL)
- {
- /* peer not authenticated, nor does it want to use EAP */
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
- }
-
/* initiate EAP authenitcation */
eap_type = config->get_eap_type(config, &eap_vendor);
status = this->eap_auth->initiate(this->eap_auth, eap_type,
@@ -618,6 +681,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
{
iterator_t *iterator;
payload_t *payload;
+ peer_cfg_t *config;
+ auth_info_t *auth;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
@@ -652,8 +717,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
case AUTH_LIFETIME:
/* handled in ike_auth_lifetime task */
break;
- case P2P_ENDPOINT:
- /* handled in ike_p2p task */
+ case ME_ENDPOINT:
+ /* handled in ike_me task */
break;
default:
{
@@ -664,7 +729,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
iterator->destroy(iterator);
return FAILED;
}
- DBG1(DBG_IKE, "received %N notify",
+ DBG2(DBG_IKE, "received %N notify",
notify_type_names, type);
break;
}
@@ -687,13 +752,21 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
return process_eap_i(this, message);
}
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ 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",
+ this->ike_sa->get_other_id(this->ike_sa), config->get_name(config));
+ return FAILED;
+ }
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D",
+ SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H",
this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_my_host(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_my_id(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
return SUCCESS;
}
diff --git a/src/charon/sa/tasks/ike_auth.h b/src/charon/sa/tasks/ike_auth.h
index d7326c988..15f98f312 100644
--- a/src/charon/sa/tasks/ike_auth.h
+++ b/src/charon/sa/tasks/ike_auth.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_auth.h
- *
- * @brief Interface ike_auth_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_auth.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_auth ike_auth
+ * @{ @ingroup tasks
*/
#ifndef IKE_AUTH_H_
@@ -30,7 +30,7 @@ typedef struct ike_auth_t ike_auth_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_auth, authenticates an IKE_SA using authenticators.
+ * Task of type ike_auth, authenticates an IKE_SA using authenticators.
*
* The ike_auth task authenticates the IKE_SA using the IKE_AUTH
* exchange. It processes and build IDi and IDr payloads and also
@@ -38,11 +38,6 @@ typedef struct ike_auth_t ike_auth_t;
* which do the actual authentication process. If the ike_auth task is used
* with EAP authentication, it stays alive over multiple exchanges until
* EAP has completed.
- *
- * @b Constructors:
- * - ike_auth_create()
- *
- * @ingroup tasks
*/
struct ike_auth_t {
@@ -53,7 +48,7 @@ struct ike_auth_t {
};
/**
- * @brief Create a new task of type IKE_AUTHENTICATE.
+ * Create a new task of type IKE_AUTHENTICATE.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if thask is the initator of an exchange
@@ -61,4 +56,4 @@ struct ike_auth_t {
*/
ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_AUTH_H_ */
+#endif /* IKE_AUTH_H_ @} */
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c
index 9d37ec608..2d18c6a1e 100644
--- a/src/charon/sa/tasks/ike_auth_lifetime.c
+++ b/src/charon/sa/tasks/ike_auth_lifetime.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_auth_lifetime.c
- *
- * @brief Implementation of the ike_auth_lifetime task.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: ike_auth_lifetime.c 3589 2008-03-13 14:14:44Z martin $
*/
#include "ike_auth_lifetime.h"
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.h b/src/charon/sa/tasks/ike_auth_lifetime.h
index 500b89d39..21a3bbfdc 100644
--- a/src/charon/sa/tasks/ike_auth_lifetime.h
+++ b/src/charon/sa/tasks/ike_auth_lifetime.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_auth_lifetime.h
- *
- * @brief Interface ike_auth_lifetime_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_auth_lifetime.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_auth_lifetime ike_auth_lifetime
+ * @{ @ingroup tasks
*/
#ifndef IKE_AUTH_LIFETIME_H_
@@ -30,15 +30,10 @@ typedef struct ike_auth_lifetime_t ike_auth_lifetime_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type IKE_AUTH_LIFETIME, implements RFC4478.
+ * Task of type IKE_AUTH_LIFETIME, implements RFC4478.
*
* This task exchanges lifetimes for IKE_AUTH to force a client to
* reauthenticate before the responders lifetime reaches the limit.
- *
- * @b Constructors:
- * - ike_auth_lifetime_create()
- *
- * @ingroup tasks
*/
struct ike_auth_lifetime_t {
@@ -49,7 +44,7 @@ struct ike_auth_lifetime_t {
};
/**
- * @brief Create a new IKE_AUTH_LIFETIME task.
+ * Create a new IKE_AUTH_LIFETIME task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
@@ -57,5 +52,4 @@ struct ike_auth_lifetime_t {
*/
ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_MOBIKE_H_ */
-
+#endif /* IKE_MOBIKE_H_ @} */
diff --git a/src/charon/sa/tasks/ike_cert.c b/src/charon/sa/tasks/ike_cert.c
deleted file mode 100644
index 880ed9c42..000000000
--- a/src/charon/sa/tasks/ike_cert.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- * @file ike_cert.c
- *
- * @brief Implementation of the ike_cert task.
- *
- */
-
-/*
- * Copyright (C) 2006-2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "ike_cert.h"
-
-#include <daemon.h>
-#include <sa/ike_sa.h>
-#include <crypto/hashers/hasher.h>
-#include <encoding/payloads/cert_payload.h>
-#include <encoding/payloads/certreq_payload.h>
-
-
-typedef struct private_ike_cert_t private_ike_cert_t;
-
-/**
- * Private members of a ike_cert_t task.
- */
-struct private_ike_cert_t {
-
- /**
- * Public methods and task_t interface.
- */
- ike_cert_t public;
-
- /**
- * Assigned IKE_SA.
- */
- ike_sa_t *ike_sa;
-
- /**
- * Are we the initiator?
- */
- bool initiator;
-
- /**
- * list of CA cert hashes requested, items point to 20 byte chunk
- */
- linked_list_t *cas;
-
- /**
- * have we seen a certificate request?
- */
- bool certreq_seen;
-};
-
-/**
- * read certificate requests
- */
-static void process_certreqs(private_ike_cert_t *this, message_t *message)
-{
- iterator_t *iterator;
- payload_t *payload;
-
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
- {
- if (payload->get_type(payload) == CERTIFICATE_REQUEST)
- {
- certreq_payload_t *certreq = (certreq_payload_t*)payload;
- cert_encoding_t encoding;
- chunk_t keyids, keyid;
-
- this->certreq_seen = TRUE;
-
- encoding = certreq->get_cert_encoding(certreq);
- if (encoding != CERT_X509_SIGNATURE)
- {
- DBG1(DBG_IKE, "certreq payload %N not supported - ignored",
- cert_encoding_names, encoding);
- continue;
- }
-
- keyids = certreq->get_data(certreq);
-
- while (keyids.len >= HASH_SIZE_SHA1)
- {
- keyid = chunk_create(keyids.ptr, HASH_SIZE_SHA1);
- keyid = chunk_clone(keyid);
- this->cas->insert_last(this->cas, keyid.ptr);
- keyids = chunk_skip(keyids, HASH_SIZE_SHA1);
- }
- }
- }
- iterator->destroy(iterator);
-}
-
-/**
- * import certificates
- */
-static void process_certs(private_ike_cert_t *this, message_t *message)
-{
- iterator_t *iterator;
- payload_t *payload;
-
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
- {
- if (payload->get_type(payload) == CERTIFICATE)
- {
- cert_encoding_t encoding;
- x509_t *cert;
- chunk_t cert_data;
- bool found;
- cert_payload_t *cert_payload = (cert_payload_t*)payload;
-
- encoding = cert_payload->get_cert_encoding(cert_payload);
- if (encoding != CERT_X509_SIGNATURE)
- {
- DBG1(DBG_IKE, "certificate payload %N not supported - ignored",
- cert_encoding_names, encoding);
- continue;
- }
-
- cert_data = cert_payload->get_data_clone(cert_payload);
- cert = x509_create_from_chunk(cert_data, 0);
- if (cert)
- {
- if (charon->credentials->verify(charon->credentials, cert, &found))
- {
- DBG2(DBG_IKE, "received end entity certificate is trusted - "
- "added to store");
- if (found)
- {
- cert->destroy(cert);
- }
- else
- {
- charon->credentials->add_end_certificate(charon->credentials, cert);
- }
- }
- else
- {
- DBG1(DBG_IKE, "received end entity certificate is not trusted - "
- "discarded");
- cert->destroy(cert);
- }
- }
- else
- {
- DBG1(DBG_IKE, "parsing of received certificate failed - discarded");
- chunk_free(&cert_data);
- }
- }
- }
- iterator->destroy(iterator);
-}
-
-/**
- * build certificate requests
- */
-static void build_certreqs(private_ike_cert_t *this, message_t *message)
-{
- ike_cfg_t *ike_cfg;
- peer_cfg_t *peer_cfg;
- identification_t *ca;
- certreq_payload_t *certreq;
-
- ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
-
- if (ike_cfg->send_certreq(ike_cfg) != CERT_NEVER_SEND)
- {
- peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-
- if (peer_cfg)
- {
- ca = peer_cfg->get_other_ca(peer_cfg);
-
- if (ca && ca->get_type(ca) != ID_ANY)
- {
- certreq = certreq_payload_create_from_cacert(ca);
- }
- else
- {
- certreq = certreq_payload_create_from_cacerts();
- }
- }
- else
- {
- certreq = certreq_payload_create_from_cacerts();
- }
-
- if (certreq)
- {
- message->add_payload(message, (payload_t*)certreq);
- }
- }
-}
-
-/**
- * add certificates to message
- */
-static void build_certs(private_ike_cert_t *this, message_t *message)
-{
- peer_cfg_t *peer_cfg;
- x509_t *cert;
- cert_payload_t *payload;
-
- peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-
- if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == AUTH_RSA)
- {
- switch (peer_cfg->get_cert_policy(peer_cfg))
- {
- case CERT_NEVER_SEND:
- break;
- case CERT_SEND_IF_ASKED:
- if (!this->certreq_seen)
- {
- break;
- }
- /* FALL */
- case CERT_ALWAYS_SEND:
- {
- /* TODO: respect CA cert request */
- cert = charon->credentials->get_certificate(charon->credentials,
- peer_cfg->get_my_id(peer_cfg));
- if (cert)
- {
- payload = cert_payload_create_from_x509(cert);
- message->add_payload(message, (payload_t*)payload);
- }
- }
- }
- }
-}
-
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t build_i(private_ike_cert_t *this, message_t *message)
-{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- return NEED_MORE;
- }
-
- build_certreqs(this, message);
- build_certs(this, message);
-
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_ike_cert_t *this, message_t *message)
-{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- return NEED_MORE;
- }
-
- process_certreqs(this, message);
- process_certs(this, message);
-
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_ike_cert_t *this, message_t *message)
-{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- build_certreqs(this, message);
- return NEED_MORE;
- }
-
- build_certs(this, message);
-
- return SUCCESS;
-}
-
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_ike_cert_t *this, message_t *message)
-{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
- process_certreqs(this, message);
- return NEED_MORE;
- }
-
- process_certs(this, message);
- return SUCCESS;
-}
-
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_ike_cert_t *this)
-{
- return IKE_CERT;
-}
-
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_ike_cert_t *this, ike_sa_t *ike_sa)
-{
- this->ike_sa = ike_sa;
-
- this->cas->destroy_function(this->cas, free);
- this->cas = linked_list_create();
- this->certreq_seen = FALSE;
-}
-
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_ike_cert_t *this)
-{
- this->cas->destroy_function(this->cas, free);
- free(this);
-}
-
-/*
- * Described in header.
- */
-ike_cert_t *ike_cert_create(ike_sa_t *ike_sa, bool initiator)
-{
- private_ike_cert_t *this = malloc_thing(private_ike_cert_t);
-
- this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
- this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
- this->public.task.destroy = (void(*)(task_t*))destroy;
-
- if (initiator)
- {
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
- }
- else
- {
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
- }
-
- this->ike_sa = ike_sa;
- this->initiator = initiator;
- this->cas = linked_list_create();
- this->certreq_seen = FALSE;
-
- return &this->public;
-}
diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c
new file mode 100644
index 000000000..184868b28
--- /dev/null
+++ b/src/charon/sa/tasks/ike_cert_post.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2006-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: ike_cert_post.c 4051 2008-06-10 09:08:27Z tobias $
+ */
+
+#include "ike_cert_post.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_ike_cert_post_t private_ike_cert_post_t;
+
+/**
+ * Private members of a ike_cert_post_t task.
+ */
+struct private_ike_cert_post_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_cert_post_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+};
+
+/**
+ * Generates the cert payload, if possible with "Hash and URL"
+ */
+static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certificate_t *cert)
+{
+ cert_payload_t *payload = NULL;
+
+ if (this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
+ {
+ /* ok, our peer sent us a HTTP_CERT_LOOKUP_SUPPORTED Notify */
+ hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher != NULL)
+ {
+ chunk_t hash, encoded = cert->get_encoding(cert);
+ enumerator_t *enumerator;
+ char *url;
+
+ hasher->allocate_hash(hasher, encoded, &hash);
+ identification_t *id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash);
+
+ enumerator = charon->credentials->create_cdp_enumerator(charon->credentials, CERT_X509, id);
+ if (enumerator->enumerate(enumerator, &url))
+ {
+ /* if we have an URL available we send that to our peer */
+ payload = cert_payload_create_from_hash_and_url(hash, url);
+ }
+ enumerator->destroy(enumerator);
+
+ id->destroy(id);
+ chunk_free(&hash);
+ chunk_free(&encoded);
+ hasher->destroy(hasher);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported");
+ }
+ }
+
+ if (!payload)
+ {
+ /* our peer does not support "Hash and URL" or we do not have an URL
+ * to send to our peer, just create a normal cert payload */
+ payload = cert_payload_create_from_cert(cert);
+ }
+
+ return payload;
+}
+
+/**
+ * add certificates to message
+ */
+static void build_certs(private_ike_cert_post_t *this, message_t *message)
+{
+ peer_cfg_t *peer_cfg;
+
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == CONF_AUTH_PUBKEY)
+ {
+ switch (peer_cfg->get_cert_policy(peer_cfg))
+ {
+ case CERT_NEVER_SEND:
+ break;
+ case CERT_SEND_IF_ASKED:
+ if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
+ {
+ break;
+ }
+ /* FALL */
+ case CERT_ALWAYS_SEND:
+ {
+ cert_payload_t *payload;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ auth_info_t *auth;
+ auth_item_t item;
+
+ auth = this->ike_sa->get_my_auth(this->ike_sa);
+ /* get subject cert first, then issuing certificates */
+ if (!auth->get_item(auth, AUTHZ_SUBJECT_CERT, (void**)&cert))
+ {
+ break;
+ }
+ payload = build_cert_payload(this, cert);
+ if (!payload)
+ {
+ break;
+ }
+ DBG1(DBG_IKE, "sending end entity cert \"%D\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+
+ enumerator = auth->create_item_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &item, &cert))
+ {
+ if (item == AUTHZ_IM_CERT)
+ {
+ payload = cert_payload_create_from_cert(cert);
+ if (payload)
+ {
+ DBG1(DBG_IKE, "sending issuer cert \"%D\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ }
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_cert_post_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return NEED_MORE;
+ }
+ build_certs(this, message);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_cert_post_t *this, message_t *message)
+{
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_cert_post_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return NEED_MORE;
+ }
+ build_certs(this, message);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_cert_post_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return NEED_MORE;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_cert_post_t *this)
+{
+ return IKE_CERT_POST;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_cert_post_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+
+ return &this->public;
+}
+
diff --git a/src/charon/sa/tasks/ike_cert_post.h b/src/charon/sa/tasks/ike_cert_post.h
new file mode 100644
index 000000000..78b32d67a
--- /dev/null
+++ b/src/charon/sa/tasks/ike_cert_post.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007-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: ike_cert_post.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_cert_post ike_cert_post
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_CERT_POST_H_
+#define IKE_CERT_POST_H_
+
+typedef struct ike_cert_post_t ike_cert_post_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/tasks/task.h>
+
+/**
+ * Task of type ike_cert_post, certificate processing after authentication.
+ */
+struct ike_cert_post_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new ike_cert_post task.
+ *
+ * The initiator parameter means the original initiator, not the initiator
+ * of the certificate request.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @param initiator TRUE if thask is the original initator
+ * @return ike_cert_post task to handle by the task_manager
+ */
+ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator);
+
+#endif /* IKE_CERT_POST_H_ @} */
diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c
new file mode 100644
index 000000000..3568a214e
--- /dev/null
+++ b/src/charon/sa/tasks/ike_cert_pre.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2006-2007 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: ike_cert_pre.c 3852 2008-04-18 21:27:08Z andreas $
+ */
+
+#include "ike_cert_pre.h"
+
+#include <daemon.h>
+#include <sa/ike_sa.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/certreq_payload.h>
+#include <credentials/certificates/x509.h>
+
+
+typedef struct private_ike_cert_pre_t private_ike_cert_pre_t;
+
+/**
+ * Private members of a ike_cert_pre_t task.
+ */
+struct private_ike_cert_pre_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_cert_pre_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Are we the initiator?
+ */
+ bool initiator;
+
+ /**
+ * Did we send a HTTP_CERT_LOOKUP_SUPPORTED Notify?
+ */
+ bool http_cert_lookup_supported_sent;
+};
+
+/**
+ * read certificate requests
+ */
+static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
+{
+ iterator_t *iterator;
+ payload_t *payload;
+ auth_info_t *auth;
+ bool ca_found = FALSE;
+
+ auth = this->ike_sa->get_my_auth(this->ike_sa);
+
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ switch(payload->get_type(payload))
+ {
+ case CERTIFICATE_REQUEST:
+ {
+ certreq_payload_t *certreq = (certreq_payload_t*)payload;
+ chunk_t keyid;
+ enumerator_t *enumerator;
+
+ this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
+
+ if (certreq->get_cert_type(certreq) != CERT_X509)
+ {
+ DBG1(DBG_IKE, "cert payload %N not supported - ignored",
+ certificate_type_names, certreq->get_cert_type(certreq));
+ break;
+ }
+ enumerator = certreq->create_keyid_enumerator(certreq);
+ while (enumerator->enumerate(enumerator, &keyid))
+ {
+ identification_t *id;
+ certificate_t *cert;
+
+ id = identification_create_from_encoding(
+ ID_PUBKEY_INFO_SHA1, keyid);
+ cert = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, id, TRUE);
+ if (cert)
+ {
+ DBG1(DBG_IKE, "received cert request for \"%D\"",
+ cert->get_subject(cert));
+ auth->add_item(auth, AUTHN_CA_CERT, cert);
+ cert->destroy(cert);
+ ca_found = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received cert request for unknown ca "
+ "with keyid %D", id);
+ auth->add_item(auth, AUTHN_CA_CERT_KEYID, id);
+ }
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+ break;
+ }
+ case NOTIFY:
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ /* we only handle one type of notify here */
+ if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED)
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL);
+ }
+ break;
+ }
+ default:
+ /* ignore other payloads here, these are handled elsewhere */
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * tries to extract a certificate from the cert payload or the credential
+ * manager (based on the hash of a "Hash and URL" encoded cert).
+ * Note: the returned certificate (if any) has to be destroyed
+ */
+static certificate_t *try_get_cert(cert_payload_t *cert_payload)
+{
+ certificate_t *cert = NULL;
+ switch (cert_payload->get_cert_encoding(cert_payload))
+ {
+ case ENC_X509_SIGNATURE:
+ {
+ cert = cert_payload->get_cert(cert_payload);
+ break;
+ }
+ case ENC_X509_HASH_AND_URL:
+ {
+ identification_t *id;
+ chunk_t hash = cert_payload->get_hash(cert_payload);
+ if (!hash.ptr)
+ {
+ /* invalid "Hash and URL" data (logged elsewhere) */
+ break;
+ }
+ id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash);
+ cert = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, id, FALSE);
+ id->destroy(id);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return cert;
+}
+
+/**
+ * import certificates
+ */
+static void process_certs(private_ike_cert_pre_t *this, message_t *message)
+{
+ iterator_t *iterator;
+ payload_t *payload;
+ auth_info_t *auth;
+ bool first = TRUE;
+
+ auth = this->ike_sa->get_other_auth(this->ike_sa);
+
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ if (payload->get_type(payload) == CERTIFICATE)
+ {
+ cert_payload_t *cert_payload = (cert_payload_t*)payload;
+ cert_encoding_t type = cert_payload->get_cert_encoding(cert_payload);
+ switch (type)
+ {
+ case ENC_X509_SIGNATURE:
+ case ENC_X509_HASH_AND_URL:
+ {
+ if (type == ENC_X509_HASH_AND_URL &&
+ !this->http_cert_lookup_supported_sent)
+ {
+ DBG1(DBG_IKE, "received hash-and-url encoded cert, but"
+ " we don't accept them, ignore");
+ break;
+ }
+
+ certificate_t *cert = try_get_cert(cert_payload);
+
+ if (cert)
+ {
+ /* we've got a certificate from the payload or the cache */
+ if (first)
+ { /* the first certificate MUST be an end entity one */
+ DBG1(DBG_IKE, "received end entity cert \"%D\"",
+ cert->get_subject(cert));
+ auth->add_item(auth, AUTHN_SUBJECT_CERT, cert);
+ first = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received issuer cert \"%D\"",
+ cert->get_subject(cert));
+ auth->add_item(auth, AUTHN_IM_CERT, cert);
+ }
+ cert->destroy(cert);
+ }
+ else if (type == ENC_X509_HASH_AND_URL)
+ {
+ /* we received a "Hash and URL" encoded certificate that
+ * we haven't fetched yet, we store the URL and fetch
+ * it later */
+ char *url = cert_payload->get_url(cert_payload);
+ if (!url)
+ {
+ DBG1(DBG_IKE, "received invalid hash-and-url encoded"
+ " cert, ignore");
+ break;
+ }
+
+ if (first)
+ { /* the first certificate MUST be an end entity one */
+ DBG1(DBG_IKE, "received hash-and-url for end"
+ " entity cert \"%s\"", url);
+ auth->add_item(auth, AUTHN_SUBJECT_HASH_URL, url);
+ first = FALSE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "received hash-and-url for issuer"
+ " cert \"%s\"", url);
+ auth->add_item(auth, AUTHN_IM_HASH_URL, url);
+ }
+ }
+ break;
+ }
+ case ENC_PKCS7_WRAPPED_X509:
+ case ENC_PGP:
+ case ENC_DNS_SIGNED_KEY:
+ case ENC_KERBEROS_TOKEN:
+ case ENC_CRL:
+ case ENC_ARL:
+ case ENC_SPKI:
+ case ENC_X509_ATTRIBUTE:
+ case ENC_RAW_RSA_KEY:
+ case ENC_X509_HASH_AND_URL_BUNDLE:
+ case ENC_OCSP_CONTENT:
+ default:
+ DBG1(DBG_ENC, "certificate encoding %N not supported",
+ cert_encoding_names, cert_payload->get_cert_encoding(cert_payload));
+ }
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * add a certificate request to the message, building request payload if required.
+ */
+static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
+ certificate_t *cert)
+{
+ public_key_t *public;
+ certreq_payload_t *req;
+
+ public = cert->get_public_key(cert);
+ if (!public)
+ {
+ return;
+ }
+ switch (cert->get_type(cert))
+ {
+ case CERT_X509:
+ {
+ identification_t *keyid;
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ { /* no CA cert, skip */
+ break;
+ }
+ if (*reqp == NULL)
+ {
+ *reqp = certreq_payload_create_type(CERT_X509);
+ message->add_payload(message, (payload_t*)*reqp);
+ }
+ req = *reqp;
+ keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
+ req->add_keyid(req, keyid->get_encoding(keyid));
+ DBG1(DBG_IKE, "sending cert request for \"%D\"",
+ cert->get_subject(cert));
+ break;
+ }
+ default:
+ break;
+ }
+ public->destroy(public);
+}
+
+/**
+ * build certificate requests
+ */
+static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
+{
+ ike_cfg_t *ike_cfg;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ auth_info_t *auth;
+ bool restricted = FALSE;
+ auth_item_t item;
+ certreq_payload_t *x509_req = NULL;
+
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ if (!ike_cfg->send_certreq(ike_cfg))
+ {
+ return;
+ }
+ auth = this->ike_sa->get_other_auth(this->ike_sa);
+
+ /* check if we require a specific CA for that peer */
+ enumerator = auth->create_item_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &item, &cert))
+ {
+ if (item == AUTHN_CA_CERT)
+ {
+ restricted = TRUE;
+ add_certreq_payload(message, &x509_req, cert);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!restricted)
+ {
+ /* otherwise include all trusted CA certificates */
+ enumerator = charon->credentials->create_cert_enumerator(
+ charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
+ while (enumerator->enumerate(enumerator, &cert, TRUE))
+ {
+ add_certreq_payload(message, &x509_req, cert);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* if we've added at least one certreq, we notify our peer that we support
+ * "Hash and URL" for the requested certificates */
+ if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE) &&
+ message->get_payload(message, CERTIFICATE_REQUEST))
+ {
+ message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, chunk_empty);
+ this->http_cert_lookup_supported_sent = TRUE;
+ }
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return NEED_MORE;
+ }
+ build_certreqs(this, message);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.process for responder
+ */
+static status_t process_r(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ return NEED_MORE;
+ }
+ process_certreqs(this, message);
+ process_certs(this, message);
+ return NEED_MORE;
+}
+
+/**
+ * Implementation of task_t.build for responder
+ */
+static status_t build_r(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ build_certreqs(this, message);
+ return NEED_MORE;
+ }
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.process for initiator
+ */
+static status_t process_i(private_ike_cert_pre_t *this, message_t *message)
+{
+ if (message->get_exchange_type(message) == IKE_SA_INIT)
+ {
+ process_certreqs(this, message);
+ return NEED_MORE;
+ }
+ process_certs(this, message);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of task_t.get_type
+ */
+static task_type_t get_type(private_ike_cert_pre_t *this)
+{
+ return IKE_CERT_PRE;
+}
+
+/**
+ * Implementation of task_t.migrate
+ */
+static void migrate(private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+}
+
+/**
+ * Implementation of task_t.destroy
+ */
+static void destroy(private_ike_cert_pre_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
+{
+ private_ike_cert_pre_t *this = malloc_thing(private_ike_cert_pre_t);
+
+ this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+ this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
+ this->public.task.destroy = (void(*)(task_t*))destroy;
+
+ if (initiator)
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+ }
+ else
+ {
+ this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
+ this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+ }
+
+ this->ike_sa = ike_sa;
+ this->initiator = initiator;
+ this->http_cert_lookup_supported_sent = FALSE;
+
+ return &this->public;
+}
diff --git a/src/charon/sa/tasks/ike_cert.h b/src/charon/sa/tasks/ike_cert_pre.h
index ba0283953..d8793a8e2 100644
--- a/src/charon/sa/tasks/ike_cert.h
+++ b/src/charon/sa/tasks/ike_cert_pre.h
@@ -1,12 +1,5 @@
-/**
- * @file ike_cert.h
- *
- * @brief Interface ike_cert_t.
- *
- */
-
/*
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,27 +11,28 @@
* 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: ike_cert_pre.h 3589 2008-03-13 14:14:44Z martin $
*/
-#ifndef IKE_CERT_H_
-#define IKE_CERT_H_
+/**
+ * @defgroup ike_cert_pre ike_cert_pre
+ * @{ @ingroup tasks
+ */
-typedef struct ike_cert_t ike_cert_t;
+#ifndef IKE_CERT_PRE_H_
+#define IKE_CERT_PRE_H_
+
+typedef struct ike_cert_pre_t ike_cert_pre_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_cert, exchanges certificates and
- * certificate requests.
- *
- * @b Constructors:
- * - ike_cert_create()
- *
- * @ingroup tasks
+ * Task of type ike_cert_post, certificate processing before authentication.
*/
-struct ike_cert_t {
+struct ike_cert_pre_t {
/**
* Implements the task_t interface
@@ -47,15 +41,15 @@ struct ike_cert_t {
};
/**
- * @brief Create a new ike_cert task.
+ * Create a new ike_cert_pre task.
*
* The initiator parameter means the original initiator, not the initiator
* of the certificate request.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if thask is the original initator
- * @return ike_cert task to handle by the task_manager
+ * @return ike_cert_pre task to handle by the task_manager
*/
-ike_cert_t *ike_cert_create(ike_sa_t *ike_sa, bool initiator);
+ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_CERT_H_ */
+#endif /* IKE_CERT_PRE_H_ @} */
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index 3c73395a5..c31e62750 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_config.c
- *
- * @brief Implementation of the ike_config task.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
@@ -19,6 +12,8 @@
* 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: ike_config.c 3800 2008-04-14 07:18:16Z martin $
*/
#include "ike_config.h"
@@ -266,14 +261,14 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
/* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (vip)
+ if (!vip)
{
- this->virtual_ip = vip->clone(vip);
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ vip = config->get_virtual_ip(config);
}
- else
+ if (vip)
{
- config = this->ike_sa->get_peer_cfg(this->ike_sa);
- this->virtual_ip = config->get_my_virtual_ip(config);
+ this->virtual_ip = vip->clone(vip);
}
build_payloads(this, message, CFG_REQUEST);
@@ -307,14 +302,20 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
if (config && this->virtual_ip)
{
- host_t *ip;
+ host_t *ip = NULL;
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
- ip = config->get_other_virtual_ip(config, this->virtual_ip);
- if (ip == NULL || ip->is_anyaddr(ip))
+ if (config->get_pool(config))
+ {
+ ip = charon->attributes->acquire_address(charon->attributes,
+ config->get_pool(config),
+ this->ike_sa->get_other_id(this->ike_sa),
+ this->ike_sa->get_other_auth(this->ike_sa),
+ this->virtual_ip);
+ }
+ if (ip == NULL)
{
DBG1(DBG_IKE, "not assigning a virtual IP to peer");
- DESTROY_IF(ip);
return SUCCESS;
}
DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip);
@@ -323,16 +324,6 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
this->virtual_ip->destroy(this->virtual_ip);
this->virtual_ip = ip;
- /* DNS testing values
- if (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
- {
- ip->destroy(ip);
- ip = host_create_from_string("10.3.0.1", 0);
- this->dns->insert_last(this->dns, ip);
- ip = host_create_from_string("10.3.0.2", 0);
- this->dns->insert_last(this->dns, ip);
- } */
-
build_payloads(this, message, CFG_REPLY);
}
return SUCCESS;
@@ -359,7 +350,11 @@ static status_t process_i(private_ike_config_t *this, message_t *message)
if (this->virtual_ip == NULL)
{ /* force a configured virtual IP, even server didn't return one */
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- this->virtual_ip = config->get_my_virtual_ip(config);
+ this->virtual_ip = config->get_virtual_ip(config);
+ if (this->virtual_ip)
+ {
+ this->virtual_ip = this->virtual_ip->clone(this->virtual_ip);
+ }
}
if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip))
diff --git a/src/charon/sa/tasks/ike_config.h b/src/charon/sa/tasks/ike_config.h
index a7cfddff0..23410a196 100644
--- a/src/charon/sa/tasks/ike_config.h
+++ b/src/charon/sa/tasks/ike_config.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_config.h
- *
- * @brief Interface ike_config_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_config.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_config ike_config
+ * @{ @ingroup tasks
*/
#ifndef IKE_CONFIG_H_
@@ -30,13 +30,8 @@ typedef struct ike_config_t ike_config_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type IKE_CONFIG, sets up a virtual IP and other
+ * Task of type IKE_CONFIG, sets up a virtual IP and other
* configurations for an IKE_SA.
- *
- * @b Constructors:
- * - ike_config_create()
- *
- * @ingroup tasks
*/
struct ike_config_t {
@@ -47,7 +42,7 @@ struct ike_config_t {
};
/**
- * @brief Create a new ike_config task.
+ * Create a new ike_config task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE for initiator
@@ -55,4 +50,4 @@ struct ike_config_t {
*/
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_CONFIG_H_ */
+#endif /* IKE_CONFIG_H_ @} */
diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c
index 1a3656ca6..aa7950ef7 100644
--- a/src/charon/sa/tasks/ike_delete.c
+++ b/src/charon/sa/tasks/ike_delete.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_delete.c
- *
- * @brief Implementation of the ike_delete task.
- *
- */
-
/*
* Copyright (C) 2006-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: ike_delete.c 3802 2008-04-14 08:17:18Z martin $
*/
#include "ike_delete.h"
@@ -87,18 +82,18 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
* come so far without being correct */
switch (this->ike_sa->get_state(this->ike_sa))
{
- case IKE_DELETING:
- this->simultaneous = TRUE;
- break;
case IKE_ESTABLISHED:
DBG1(DBG_IKE, "deleting IKE_SA on request");
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
+ this->ike_sa->reestablish(this->ike_sa);
break;
- case IKE_REKEYING:
- break;
+ case IKE_DELETING:
+ this->simultaneous = TRUE;
+ /* FALL */
default:
+ this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
break;
}
- this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
return NEED_MORE;
}
diff --git a/src/charon/sa/tasks/ike_delete.h b/src/charon/sa/tasks/ike_delete.h
index e8ec5ebbe..6d08d345d 100644
--- a/src/charon/sa/tasks/ike_delete.h
+++ b/src/charon/sa/tasks/ike_delete.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_delete.h
- *
- * @brief Interface ike_delete_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_delete.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_delete ike_delete
+ * @{ @ingroup tasks
*/
#ifndef IKE_DELETE_H_
@@ -30,12 +30,7 @@ typedef struct ike_delete_t ike_delete_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_delete, delete an IKE_SA.
- *
- * @b Constructors:
- * - ike_delete_create()
- *
- * @ingroup tasks
+ * Task of type ike_delete, delete an IKE_SA.
*/
struct ike_delete_t {
@@ -46,7 +41,7 @@ struct ike_delete_t {
};
/**
- * @brief Create a new ike_delete task.
+ * Create a new ike_delete task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if we initiate the delete
@@ -54,4 +49,4 @@ struct ike_delete_t {
*/
ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_DELETE_H_ */
+#endif /* IKE_DELETE_H_ @} */
diff --git a/src/charon/sa/tasks/ike_dpd.c b/src/charon/sa/tasks/ike_dpd.c
index be751766e..9f1d43cbf 100644
--- a/src/charon/sa/tasks/ike_dpd.c
+++ b/src/charon/sa/tasks/ike_dpd.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_dpd.c
- *
- * @brief Implementation of the ike_dpd task.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: ike_dpd.c 3589 2008-03-13 14:14:44Z martin $
*/
#include "ike_dpd.h"
diff --git a/src/charon/sa/tasks/ike_dpd.h b/src/charon/sa/tasks/ike_dpd.h
index 531b0502d..62b8a6a10 100644
--- a/src/charon/sa/tasks/ike_dpd.h
+++ b/src/charon/sa/tasks/ike_dpd.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_dpd.h
- *
- * @brief Interface ike_dpd_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_dpd.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_dpd ike_dpd
+ * @{ @ingroup tasks
*/
#ifndef IKE_DPD_H_
@@ -30,14 +30,9 @@ typedef struct ike_dpd_t ike_dpd_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_dpd, detects dead peers.
+ * Task of type ike_dpd, detects dead peers.
*
* The DPD task actually does nothing, as a DPD has no associated payloads.
- *
- * @b Constructors:
- * - ike_dpd_create()
- *
- * @ingroup tasks
*/
struct ike_dpd_t {
@@ -48,11 +43,11 @@ struct ike_dpd_t {
};
/**
- * @brief Create a new ike_dpd task.
+ * Create a new ike_dpd task.
*
* @param initiator TRUE if thask is the original initator
* @return ike_dpd task to handle by the task_manager
*/
ike_dpd_t *ike_dpd_create(bool initiator);
-#endif /* IKE_DPD_H_ */
+#endif /* IKE_DPD_H_ @} */
diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c
index 42b47a82f..7def3a556 100644
--- a/src/charon/sa/tasks/ike_init.c
+++ b/src/charon/sa/tasks/ike_init.c
@@ -1,11 +1,5 @@
-/**
- * @file ike_init.c
- *
- * @brief Implementation of the ike_init task.
- *
- */
-
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -19,6 +13,8 @@
* 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: ike_init.c 4086 2008-06-22 11:24:33Z andreas $
*/
#include "ike_init.h"
@@ -195,7 +191,7 @@ 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 = diffie_hellman_create(this->dh_group);
+ this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
}
if (this->dh)
{
@@ -222,13 +218,12 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
*/
static status_t build_i(private_ike_init_t *this, message_t *message)
{
- randomizer_t *randomizer;
- status_t status;
+ rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H",
this->ike_sa->get_name(this->ike_sa),
- this->config->get_other_host(this->config));
+ this->ike_sa->get_other_host(this->ike_sa));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
if (this->retry++ >= MAX_RETRIES)
@@ -241,7 +236,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
if (!this->dh)
{
this->dh_group = this->config->get_dh_group(this->config);
- this->dh = diffie_hellman_create(this->dh_group);
+ this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
if (this->dh == NULL)
{
SIG(IKE_UP_FAILED, "configured DH group %N not supported",
@@ -253,15 +248,14 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
/* generate nonce only when we are trying the first time */
if (this->my_nonce.ptr == NULL)
{
- randomizer = randomizer_create();
- status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE,
- &this->my_nonce);
- randomizer->destroy(randomizer);
- if (status != SUCCESS)
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
{
- SIG(IKE_UP_FAILED, "error generating random nonce value");
+ SIG(IKE_UP_FAILED, "error generating nonce");
return FAILED;
}
+ rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
+ rng->destroy(rng);
}
if (this->cookie.ptr)
@@ -270,30 +264,90 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
}
build_payloads(this, message);
-
+
+#ifdef ME
+ {
+ chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
+ if (connect_id.ptr)
+ {
+ message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
+ }
+ }
+#endif /* ME */
return NEED_MORE;
}
/**
- * Implementation of task_t.process for initiator
+ * Implementation of task_t.process for responder
*/
static status_t process_r(private_ike_init_t *this, message_t *message)
{
- randomizer_t *randomizer;
+ rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
- SIG(IKE_UP_FAILED, "%H is initiating an IKE_SA",
+ SIG(IKE_UP_START, "%H is initiating an IKE_SA",
message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
- randomizer = randomizer_create();
- if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE,
- &this->my_nonce) != SUCCESS)
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_IKE, "error generating nonce");
+ return FAILED;
+ }
+ rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
+ rng->destroy(rng);
+
+#ifdef ME
{
- DBG1(DBG_IKE, "error generating random nonce value");
+ chunk_t connect_id = chunk_empty;
+ iterator_t *iterator;
+ payload_t *payload;
+
+ /* check for a ME_CONNECTID 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;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ case ME_CONNECTID:
+ {
+ chunk_free(&connect_id);
+ connect_id = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
+ break;
+ }
+ default:
+ {
+ if (type < 16383)
+ {
+ DBG1(DBG_IKE, "received %N notify error",
+ notify_type_names, type);
+ break;
+ }
+ DBG2(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ break;
+ }
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (connect_id.ptr)
+ {
+ charon->connect_manager->stop_checks(charon->connect_manager,
+ connect_id);
+ chunk_free(&connect_id);
+ }
}
- randomizer->destroy(randomizer);
+#endif /* ME */
process_payloads(this, message);
@@ -321,11 +375,11 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
!this->proposal->has_dh_group(this->proposal, this->dh_group) ||
this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
{
- algorithm_t *algo;
+ u_int16_t group;
+
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
- &algo))
+ &group, NULL))
{
- u_int16_t group = algo->algorithm;
SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N",
diffie_hellman_group_names, this->dh_group,
diffie_hellman_group_names, group);
@@ -370,9 +424,16 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
-
- build_payloads(this, message);
+ /* 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);
+ }
+
+ build_payloads(this, message);
return SUCCESS;
}
@@ -427,7 +488,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
this->cookie = chunk_clone(notify->get_notification_data(notify));
this->ike_sa->reset(this->ike_sa);
iterator->destroy(iterator);
- DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
+ DBG2(DBG_IKE, "received %N notify", notify_type_names, type);
return NEED_MORE;
}
default:
@@ -439,7 +500,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
iterator->destroy(iterator);
return FAILED;
}
- DBG1(DBG_IKE, "received %N notify",
+ DBG2(DBG_IKE, "received %N notify",
notify_type_names, type);
break;
}
@@ -454,7 +515,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG(IKE_UP_FAILED, "peers proposal selection invalid");
+ SIG(IKE_UP_FAILED, "peer's proposal selection invalid");
return FAILED;
}
@@ -462,7 +523,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
!this->proposal->has_dh_group(this->proposal, this->dh_group) ||
this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
{
- SIG(IKE_UP_FAILED, "peers DH group selection invalid");
+ SIG(IKE_UP_FAILED, "peer's DH group selection invalid");
return FAILED;
}
@@ -494,6 +555,15 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
SIG(IKE_UP_FAILED, "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);
+ }
+
return SUCCESS;
}
@@ -532,7 +602,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
this->ike_sa = ike_sa;
this->proposal = NULL;
- this->dh = diffie_hellman_create(this->dh_group);
+ this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
}
/**
diff --git a/src/charon/sa/tasks/ike_init.h b/src/charon/sa/tasks/ike_init.h
index f60c096e8..0e5a913fd 100644
--- a/src/charon/sa/tasks/ike_init.h
+++ b/src/charon/sa/tasks/ike_init.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_init.h
- *
- * @brief Interface ike_init_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_init.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_init ike_init
+ * @{ @ingroup tasks
*/
#ifndef IKE_INIT_H_
@@ -30,14 +30,9 @@ typedef struct ike_init_t ike_init_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type IKE_INIT, creates an IKE_SA without authentication.
+ * Task of type IKE_INIT, creates an IKE_SA without authentication.
*
* The authentication of is handle in the ike_auth task.
- *
- * @b Constructors:
- * - ike_init_create()
- *
- * @ingroup tasks
*/
struct ike_init_t {
@@ -47,16 +42,15 @@ struct ike_init_t {
task_t task;
/**
- * @brief Get the lower of the two nonces, used for rekey collisions.
+ * Get the lower of the two nonces, used for rekey collisions.
*
- * @param this calling object
* @return lower nonce
*/
chunk_t (*get_lower_nonce) (ike_init_t *this);
};
/**
- * @brief Create a new IKE_INIT task.
+ * Create a new IKE_INIT task.
*
* @param ike_sa IKE_SA this task works for (new one when rekeying)
* @param initiator TRUE if thask is the original initator
@@ -65,4 +59,4 @@ struct ike_init_t {
*/
ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa);
-#endif /* IKE_INIT_H_ */
+#endif /* IKE_INIT_H_ @} */
diff --git a/src/charon/sa/tasks/ike_p2p.c b/src/charon/sa/tasks/ike_me.c
index 84b88e16b..2d7c64d70 100644
--- a/src/charon/sa/tasks/ike_p2p.c
+++ b/src/charon/sa/tasks/ike_me.c
@@ -1,12 +1,5 @@
-/**
- * @file ike_p2p.c
- *
- * @brief Implementation of the ike_p2p task.
- *
- */
-
/*
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2008 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,9 +11,11 @@
* 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: ike_me.c 3806 2008-04-15 05:56:35Z martin $
*/
-
-#include "ike_p2p.h"
+
+#include "ike_me.h"
#include <string.h>
@@ -31,27 +26,20 @@
#include <encoding/payloads/endpoint_notify.h>
#include <processing/jobs/mediation_job.h>
-#define P2P_SESSIONID_LEN 8
-#define P2P_SESSIONKEY_LEN 16
+#define ME_CONNECTID_LEN 4
+#define ME_CONNECTKEY_LEN 16
-/* FIXME: proposed values */
-#define P2P_SESSIONID_MIN_LEN 4
-#define P2P_SESSIONID_MAX_LEN 16
-#define P2P_SESSIONKEY_MIN_LEN 8
-#define P2P_SESSIONKEY_MAX_LEN 64
-
-
-typedef struct private_ike_p2p_t private_ike_p2p_t;
+typedef struct private_ike_me_t private_ike_me_t;
/**
- * Private members of a ike_p2p_t task.
+ * Private members of a ike_me_t task.
*/
-struct private_ike_p2p_t {
+struct private_ike_me_t {
/**
* Public methods and task_t interface.
*/
- ike_p2p_t public;
+ ike_me_t public;
/**
* Assigned IKE_SA.
@@ -105,12 +93,12 @@ struct private_ike_p2p_t {
/**
* Received ID used for connectivity checks
*/
- chunk_t session_id;
+ chunk_t connect_id;
/**
* Received key used for connectivity checks
*/
- chunk_t session_key;
+ chunk_t connect_key;
/**
* Peer config of the mediated connection
@@ -138,7 +126,7 @@ static void add_endpoints_to_message(message_t *message, linked_list_t *endpoint
/**
* Gathers endpoints and adds them to the current message
*/
-static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message)
+static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
{
iterator_t *iterator;
host_t *addr, *host;
@@ -176,7 +164,7 @@ static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message
/**
* read notifys from message and evaluate them
*/
-static void process_payloads(private_ike_p2p_t *this, message_t *message)
+static void process_payloads(private_ike_me_t *this, message_t *message)
{
iterator_t *iterator;
payload_t *payload;
@@ -193,55 +181,55 @@ static void process_payloads(private_ike_p2p_t *this, message_t *message)
switch (notify->get_notify_type(notify))
{
- case P2P_CONNECT_FAILED:
+ case ME_CONNECT_FAILED:
{
- DBG2(DBG_IKE, "received P2P_CONNECT_FAILED notify");
+ DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify");
this->failed = TRUE;
break;
}
- case P2P_MEDIATION:
+ case ME_MEDIATION:
{
- DBG2(DBG_IKE, "received P2P_MEDIATION notify");
+ DBG2(DBG_IKE, "received ME_MEDIATION notify");
this->mediation = TRUE;
break;
}
- case P2P_ENDPOINT:
+ case ME_ENDPOINT:
{
endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify);
if (!endpoint)
{
- DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify");
+ DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify");
break;
}
- DBG1(DBG_IKE, "received %N P2P_ENDPOINT %#H", p2p_endpoint_type_names,
+ DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H", me_endpoint_type_names,
endpoint->get_type(endpoint), endpoint->get_host(endpoint));
this->remote_endpoints->insert_last(this->remote_endpoints, endpoint);
break;
}
- case P2P_CALLBACK:
+ case ME_CALLBACK:
{
- DBG2(DBG_IKE, "received P2P_CALLBACK notify");
+ DBG2(DBG_IKE, "received ME_CALLBACK notify");
this->callback = TRUE;
break;
}
- case P2P_SESSIONID:
+ case ME_CONNECTID:
{
- chunk_free(&this->session_id);
- this->session_id = chunk_clone(notify->get_notification_data(notify));
- DBG3(DBG_IKE, "received p2p_sessionid %B", &this->session_id);
+ chunk_free(&this->connect_id);
+ this->connect_id = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id);
break;
}
- case P2P_SESSIONKEY:
+ case ME_CONNECTKEY:
{
- chunk_free(&this->session_key);
- this->session_key = chunk_clone(notify->get_notification_data(notify));
- DBG4(DBG_IKE, "received p2p_sessionkey %B", &this->session_key);
+ chunk_free(&this->connect_key);
+ this->connect_key = chunk_clone(notify->get_notification_data(notify));
+ DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key);
break;
}
- case P2P_RESPONSE:
+ case ME_RESPONSE:
{
- DBG2(DBG_IKE, "received P2P_RESPONSE notify");
+ DBG2(DBG_IKE, "received ME_RESPONSE notify");
this->response = TRUE;
break;
}
@@ -253,9 +241,9 @@ static void process_payloads(private_ike_p2p_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator
+ * Implementation of task_t.build for initiator
*/
-static status_t build_i(private_ike_p2p_t *this, message_t *message)
+static status_t build_i(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -264,8 +252,8 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message)
peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg->is_mediation(peer_cfg))
{
- DBG2(DBG_IKE, "adding P2P_MEDIATION");
- message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
+ DBG2(DBG_IKE, "adding ME_MEDIATION");
+ message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
}
else
{
@@ -283,48 +271,40 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message)
}
break;
}
- case P2P_CONNECT:
+ case ME_CONNECT:
{
id_payload_t *id_payload;
- randomizer_t *rand = randomizer_create();
+ rng_t *rng;
id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
message->add_payload(message, (payload_t*)id_payload);
- if (!this->response)
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng)
{
- /* only the initiator creates a session ID. the responder returns
- * the session ID that it received from the initiator */
- if (rand->allocate_pseudo_random_bytes(rand,
- P2P_SESSIONID_LEN, &this->session_id) != SUCCESS)
- {
- DBG1(DBG_IKE, "unable to generate session ID for P2P_CONNECT");
- rand->destroy(rand);
- return FAILED;
- }
+ DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT");
+ return FAILED;
}
-
- if (rand->allocate_pseudo_random_bytes(rand,
- P2P_SESSIONKEY_LEN, &this->session_key) != SUCCESS)
+ if (!this->response)
{
- DBG1(DBG_IKE, "unable to generate session key for P2P_CONNECT");
- rand->destroy(rand);
- return FAILED;
+ /* only the initiator creates a connect ID. the responder returns
+ * the connect ID that it received from the initiator */
+ rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id);
}
+ rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key);
+ rng->destroy(rng);
- rand->destroy(rand);
-
- message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
- message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
+ message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
+ message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
if (this->response)
{
- message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
+ message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
}
else
{
- /* FIXME: should we make that configurable */
- message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
+ /* FIXME: should we make that configurable? */
+ message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
}
gather_and_add_endpoints(this, message);
@@ -340,17 +320,17 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.process for responder
*/
-static status_t process_r(private_ike_p2p_t *this, message_t *message)
+static status_t process_r(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
- case P2P_CONNECT:
+ case ME_CONNECT:
{
id_payload_t *id_payload;
id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
if (!id_payload)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload, aborting");
break;
}
this->peer_id = id_payload->get_identification(id_payload);
@@ -359,32 +339,32 @@ static status_t process_r(private_ike_p2p_t *this, message_t *message)
if (this->callback)
{
- DBG1(DBG_IKE, "received P2P_CALLBACK for '%D'", this->peer_id);
+ DBG1(DBG_IKE, "received ME_CALLBACK for '%D'", this->peer_id);
break;
}
- if (!this->session_id.ptr)
+ if (!this->connect_id.ptr)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify, aborting");
this->invalid_syntax = TRUE;
break;
}
- if (!this->session_key.ptr)
+ if (!this->connect_key.ptr)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->remote_endpoints->get_count(this->remote_endpoints))
{
- DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT payloads, aborting");
this->invalid_syntax = TRUE;
break;
}
- DBG1(DBG_IKE, "received P2P_CONNECT");
+ DBG1(DBG_IKE, "received ME_CONNECT");
break;
}
default:
@@ -396,11 +376,11 @@ static status_t process_r(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.build for responder
*/
-static status_t build_r(private_ike_p2p_t *this, message_t *message)
+static status_t build_r(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
- case P2P_CONNECT:
+ case ME_CONNECT:
{
if (this->invalid_syntax)
{
@@ -422,7 +402,7 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message)
* as initiator, upon receiving a response from another peer,
* update the checklist and start sending checks */
charon->connect_manager->set_responder_data(charon->connect_manager,
- this->session_id, this->session_key, this->remote_endpoints);
+ this->connect_id, this->connect_key, this->remote_endpoints);
}
else
{
@@ -430,10 +410,10 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message)
* as responder, create a checklist with the initiator's data */
charon->connect_manager->set_initiator_data(charon->connect_manager,
this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
- this->session_id, this->session_key, this->remote_endpoints,
+ this->connect_id, this->connect_key, this->remote_endpoints,
FALSE);
if (this->ike_sa->respond(this->ike_sa, this->peer_id,
- this->session_id) != SUCCESS)
+ this->connect_id) != SUCCESS)
{
return FAILED;
}
@@ -449,7 +429,7 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.process for initiator
*/
-static status_t process_i(private_ike_p2p_t *this, message_t *message)
+static status_t process_i(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
@@ -459,7 +439,7 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message)
if (!this->mediation)
{
- DBG1(DBG_IKE, "server did not return a P2P_MEDIATION, aborting");
+ DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting");
return FAILED;
}
@@ -485,16 +465,14 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message)
break;
}
- case P2P_CONNECT:
+ case ME_CONNECT:
{
process_payloads(this, message);
if (this->failed)
{
DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id);
- /* FIXME: notify the mediated connection (job?)
- * FIXME: probably delete the created checklist, at least as
- * responder */
+ /* FIXME: notify the mediated connection (job?) */
}
else
{
@@ -503,7 +481,7 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message)
/* FIXME: handle result of set_responder_data.
* as responder, we update the checklist and start sending checks */
charon->connect_manager->set_responder_data(charon->connect_manager,
- this->session_id, this->session_key, this->local_endpoints);
+ this->connect_id, this->connect_key, this->local_endpoints);
}
else
{
@@ -511,8 +489,10 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message)
* as initiator, we create a checklist and set the initiator's data */
charon->connect_manager->set_initiator_data(charon->connect_manager,
this->ike_sa->get_my_id(this->ike_sa), this->peer_id,
- this->session_id, this->session_key, this->local_endpoints,
+ this->connect_id, this->connect_key, this->local_endpoints,
TRUE);
+ /* FIXME: also start a timer for the whole transaction (maybe
+ * within the connect_manager?) */
}
}
break;
@@ -524,29 +504,29 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator (mediation server)
+ * Implementation of task_t.build for initiator (mediation server)
*/
-static status_t build_i_ms(private_ike_p2p_t *this, message_t *message)
+static status_t build_i_ms(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
- case P2P_CONNECT:
+ case ME_CONNECT:
{
id_payload_t *id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
message->add_payload(message, (payload_t*)id_payload);
if (this->callback)
{
- message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
+ message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
}
else
{
if (this->response)
{
- message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
+ message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
}
- message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
- message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
+ message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
+ message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
add_endpoints_to_message(message, this->remote_endpoints);
}
@@ -562,27 +542,37 @@ static status_t build_i_ms(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.process for responder (mediation server)
*/
-static status_t process_r_ms(private_ike_p2p_t *this, message_t *message)
+static status_t process_r_ms(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
+ /* FIXME: we should check for SA* and TS* payloads
+ * if any are there send NO_ADDITIONAL_SAS back and delete this SA */
process_payloads(this, message);
return this->mediation ? NEED_MORE : SUCCESS;
}
case IKE_AUTH:
{
+ /* FIXME: we should check whether the current peer_config is configured
+ * as mediation connection */
process_payloads(this, message);
break;
}
- case P2P_CONNECT:
+ case CREATE_CHILD_SA:
+ {
+ /* FIXME: if this is not to rekey the IKE SA we have to return a
+ * NO_ADDITIONAL_SAS and then delete the SA */
+ break;
+ }
+ case ME_CONNECT:
{
id_payload_t *id_payload;
id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
if (!id_payload)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload, aborting");
this->invalid_syntax = TRUE;
break;
}
@@ -591,23 +581,23 @@ static status_t process_r_ms(private_ike_p2p_t *this, message_t *message)
process_payloads(this, message);
- if (!this->session_id.ptr)
+ if (!this->connect_id.ptr)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify, aborting");
this->invalid_syntax = TRUE;
break;
}
- if (!this->session_key.ptr)
+ if (!this->connect_key.ptr)
{
- DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->remote_endpoints->get_count(this->remote_endpoints))
{
- DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
+ DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT payloads, aborting");
this->invalid_syntax = TRUE;
break;
}
@@ -623,13 +613,13 @@ static status_t process_r_ms(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.build for responder (mediation server)
*/
-static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
+static status_t build_r_ms(private_ike_me_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
- message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
+ message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
return NEED_MORE;
}
case IKE_AUTH:
@@ -645,17 +635,17 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, NULL);
message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
+ endpoint->destroy(endpoint);
}
- charon->mediation_manager->update_sa_id(charon->mediation_manager,
- this->ike_sa->get_other_id(this->ike_sa),
- this->ike_sa->get_id(this->ike_sa));
+ /* FIXME: we actually must delete any existing IKE_SAs with the same remote id */
+ this->ike_sa->act_as_mediation_server(this->ike_sa);
SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
break;
}
- case P2P_CONNECT:
+ case ME_CONNECT:
{
if (this->invalid_syntax)
{
@@ -678,13 +668,13 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
if (!peer_sa)
{
/* the peer is not online */
- message->add_notify(message, TRUE, P2P_CONNECT_FAILED, chunk_empty);
+ message->add_notify(message, TRUE, ME_CONNECT_FAILED, chunk_empty);
break;
}
job_t *job = (job_t*)mediation_job_create(this->peer_id,
- this->ike_sa->get_other_id(this->ike_sa), this->session_id,
- this->session_key, this->remote_endpoints, this->response);
+ this->ike_sa->get_other_id(this->ike_sa), this->connect_id,
+ this->connect_key, this->remote_endpoints, this->response);
charon->processor->queue_job(charon->processor, job);
break;
@@ -698,64 +688,71 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
/**
* Implementation of task_t.process for initiator (mediation server)
*/
-static status_t process_i_ms(private_ike_p2p_t *this, message_t *message)
+static status_t process_i_ms(private_ike_me_t *this, message_t *message)
{
+ /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
+ * here if the responding peer is not able to proceed. in this case we shall
+ * notify the initiating peer with a ME_CONNECT request containing only a
+ * ME_CONNECT_FAILED */
return SUCCESS;
}
/**
- * Implementation of ike_p2p.connect
+ * Implementation of ike_me.connect
*/
-static void p2p_connect(private_ike_p2p_t *this, identification_t *peer_id)
+static void me_connect(private_ike_me_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
}
/**
- * Implementation of ike_p2p.respond
+ * Implementation of ike_me.respond
*/
-static void p2p_respond(private_ike_p2p_t *this, identification_t *peer_id,
- chunk_t session_id)
+static void me_respond(private_ike_me_t *this, identification_t *peer_id,
+ chunk_t connect_id)
{
this->peer_id = peer_id->clone(peer_id);
- this->session_id = chunk_clone(session_id);
+ this->connect_id = chunk_clone(connect_id);
this->response = TRUE;
}
/**
- * Implementation of ike_p2p.callback
+ * Implementation of ike_me.callback
*/
-static void p2p_callback(private_ike_p2p_t *this, identification_t *peer_id)
+static void me_callback(private_ike_me_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
this->callback = TRUE;
}
/**
- * Implementation of ike_p2p.relay
+ * Implementation of ike_me.relay
*/
-static void relay(private_ike_p2p_t *this, identification_t *requester, chunk_t session_id,
- chunk_t session_key, linked_list_t *endpoints, bool response)
+static void relay(private_ike_me_t *this, identification_t *requester, chunk_t connect_id,
+ chunk_t connect_key, linked_list_t *endpoints, bool response)
{
this->peer_id = requester->clone(requester);
- this->session_id = chunk_clone(session_id);
- this->session_key = chunk_clone(session_key);
+ this->connect_id = chunk_clone(connect_id);
+ this->connect_key = chunk_clone(connect_key);
+
+ this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy));
this->remote_endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
+
this->response = response;
}
/**
* Implementation of task_t.get_type
*/
-static task_type_t get_type(private_ike_p2p_t *this)
+static task_type_t get_type(private_ike_me_t *this)
{
- return IKE_P2P;
+ return IKE_ME;
}
/**
* Implementation of task_t.migrate
*/
-static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa)
+static void migrate(private_ike_me_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
@@ -763,12 +760,12 @@ static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa)
/**
* Implementation of task_t.destroy
*/
-static void destroy(private_ike_p2p_t *this)
+static void destroy(private_ike_me_t *this)
{
DESTROY_IF(this->peer_id);
- chunk_free(&this->session_id);
- chunk_free(&this->session_key);
+ chunk_free(&this->connect_id);
+ chunk_free(&this->connect_key);
this->local_endpoints->destroy_offset(this->local_endpoints, offsetof(endpoint_notify_t, destroy));
this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy));
@@ -780,16 +777,15 @@ static void destroy(private_ike_p2p_t *this)
/*
* Described in header.
*/
-ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator)
+ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
{
- private_ike_p2p_t *this = malloc_thing(private_ike_p2p_t);
+ private_ike_me_t *this = malloc_thing(private_ike_me_t);
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
- ike_sa_id_t *id = ike_sa->get_id(ike_sa);
- if (id->is_initiator(id))
+ if (ike_sa->is_ike_initiator(ike_sa))
{
if (initiator)
{
@@ -817,17 +813,17 @@ ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator)
}
}
- this->public.connect = (void(*)(ike_p2p_t*,identification_t*))p2p_connect;
- this->public.respond = (void(*)(ike_p2p_t*,identification_t*,chunk_t))p2p_respond;
- this->public.callback = (void(*)(ike_p2p_t*,identification_t*))p2p_callback;
- this->public.relay = (void(*)(ike_p2p_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
+ this->public.connect = (void(*)(ike_me_t*,identification_t*))me_connect;
+ this->public.respond = (void(*)(ike_me_t*,identification_t*,chunk_t))me_respond;
+ this->public.callback = (void(*)(ike_me_t*,identification_t*))me_callback;
+ this->public.relay = (void(*)(ike_me_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
this->ike_sa = ike_sa;
this->initiator = initiator;
this->peer_id = NULL;
- this->session_id = chunk_empty;
- this->session_key = chunk_empty;
+ this->connect_id = chunk_empty;
+ this->connect_key = chunk_empty;
this->local_endpoints = linked_list_create();
this->remote_endpoints = linked_list_create();
this->mediation = FALSE;
diff --git a/src/charon/sa/tasks/ike_p2p.h b/src/charon/sa/tasks/ike_me.h
index 327ac49d8..c9a515c8f 100644
--- a/src/charon/sa/tasks/ike_p2p.h
+++ b/src/charon/sa/tasks/ike_me.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_p2p.h
- *
- * @brief Interface ike_p2p_t.
- *
- */
-
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
@@ -18,35 +11,37 @@
* 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: ike_me.h 3666 2008-03-26 18:40:19Z tobias $
*/
-#ifndef IKE_P2P_H_
-#define IKE_P2P_H_
+/**
+ * @defgroup ike_me ike_me
+ * @{ @ingroup tasks
+ */
+
+#ifndef IKE_ME_H_
+#define IKE_ME_H_
-typedef struct ike_p2p_t ike_p2p_t;
+typedef struct ike_me_t ike_me_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
/**
- * @brief Task of type IKE_P2P, detects and handles P2P-NAT-T extensions.
+ * Task of type IKE_ME, detects and handles IKE-ME extensions.
*
- * This tasks handles the P2P_MEDIATION notify exchange to setup a mediation
- * connection, allows to initiate mediated connections using P2P_CONNECT
+ * This tasks handles the ME_MEDIATION Notify exchange to setup a mediation
+ * connection, allows to initiate mediated connections using ME_CONNECT
* exchanges and to request reflexive addresses from the mediation server using
- * P2P_ENDPOINT notifies.
+ * ME_ENDPOINT notifies.
*
* @note This task has to be activated before the IKE_AUTH task, because that
* task generates the IKE_SA_INIT message so that no more payloads can be added
* to it afterwards.
- *
- * @b Constructors:
- * - ike_p2p_create()
- *
- * @ingroup tasks
*/
-struct ike_p2p_t {
+struct ike_me_t {
/**
* Implements the task_t interface
@@ -54,57 +49,52 @@ struct ike_p2p_t {
task_t task;
/**
- * @brief Initiates a connection with another peer (i.e. sends a P2P_CONNECT
+ * Initiates a connection with another peer (i.e. sends a ME_CONNECT
* to the mediation server)
*
- * @param this object
* @param peer_id ID of the other peer (gets cloned)
*/
- void (*connect)(ike_p2p_t *this, identification_t *peer_id);
+ void (*connect)(ike_me_t *this, identification_t *peer_id);
/**
- * @brief Responds to a P2P_CONNECT from another peer (i.e. sends a P2P_CONNECT
+ * Responds to a ME_CONNECT from another peer (i.e. sends a ME_CONNECT
* to the mediation server)
*
- * @param this object
* @param peer_id ID of the other peer (gets cloned)
- * @param session_id the session ID as provided by the initiator (gets cloned)
+ * @param connect_id the connect ID as provided by the initiator (gets cloned)
*/
- void (*respond)(ike_p2p_t *this, identification_t *peer_id, chunk_t session_id);
+ void (*respond)(ike_me_t *this, identification_t *peer_id, chunk_t connect_id);
/**
- * @brief Sends a P2P_CALLBACK to a peer that previously requested another peer.
+ * Sends a ME_CALLBACK to a peer that previously requested another peer.
*
- * @param this object
* @param peer_id ID of the other peer (gets cloned)
*/
- void (*callback)(ike_p2p_t *this, identification_t *peer_id);
+ void (*callback)(ike_me_t *this, identification_t *peer_id);
/**
- * @brief Relays data to another peer (i.e. sends a P2P_CONNECT to the peer)
+ * Relays data to another peer (i.e. sends a ME_CONNECT to the peer)
*
* Data gets cloned.
*
- * @param this object
* @param requester ID of the requesting peer
- * @param session_id content of the P2P_SESSIONID notify
- * @param session_key content of the P2P_SESSIONKEY notify
+ * @param connect_id content of the ME_CONNECTID notify
+ * @param connect_key content of the ME_CONNECTKEY notify
* @param endpoints endpoints
* @param response TRUE if this is a response
*/
- void (*relay)(ike_p2p_t *this, identification_t *requester, chunk_t session_id,
- chunk_t session_key, linked_list_t *endpoints, bool response);
+ void (*relay)(ike_me_t *this, identification_t *requester, chunk_t connect_id,
+ chunk_t connect_key, linked_list_t *endpoints, bool response);
};
/**
- * @brief Create a new ike_p2p task.
+ * Create a new ike_me task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
- * @return ike_p2p task to handle by the task_manager
+ * @return ike_me task to handle by the task_manager
*/
-ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator);
-
+ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator);
-#endif /*IKE_P2P_H_*/
+#endif /*IKE_ME_H_ @} */
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index a53c243f0..23c68b9e9 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_mobike.c
- *
- * @brief Implementation of the ike_mobike task.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: ike_mobike.c 4006 2008-05-23 15:43:42Z martin $
*/
#include "ike_mobike.h"
@@ -28,6 +23,7 @@
#include <sa/tasks/ike_natd.h>
#include <encoding/payloads/notify_payload.h>
+#define COOKIE2_SIZE 16
typedef struct private_ike_mobike_t private_ike_mobike_t;
@@ -125,6 +121,12 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
break;
}
+ case COOKIE2:
+ {
+ chunk_free(&this->cookie2);
+ this->cookie2 = chunk_clone(notify->get_notification_data(notify));
+ break;
+ }
case ADDITIONAL_IP6_ADDRESS:
{
family = AF_INET6;
@@ -211,6 +213,23 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
}
/**
+ * build a cookie and add it to the message
+ */
+static void build_cookie(private_ike_mobike_t *this, message_t *message)
+{
+ rng_t *rng;
+
+ chunk_free(&this->cookie2);
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (rng)
+ {
+ rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2);
+ rng->destroy(rng);
+ message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ }
+}
+
+/**
* update addresses of associated CHILD_SAs
*/
static void update_children(private_ike_mobike_t *this)
@@ -262,6 +281,11 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet)
charon->kernel_interface, other);
if (me)
{
+ if (me->get_family(me) != other->get_family(other))
+ {
+ me->destroy(me);
+ continue;
+ }
/* reuse port for an active address, 4500 otherwise */
me->set_port(me, me->ip_equals(me, me_old) ?
me_old->get_port(me_old) : IKEV2_NATT_PORT);
@@ -297,6 +321,7 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message)
if (this->update)
{
message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty);
+ build_cookie(this, message);
update_children(this);
}
if (this->address)
@@ -363,6 +388,11 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message)
{
this->natd->task.build(&this->natd->task, message);
}
+ if (this->cookie2.ptr)
+ {
+ message->add_notify(message, FALSE, COOKIE2, this->cookie2);
+ chunk_free(&this->cookie2);
+ }
if (this->update)
{
update_children(this);
@@ -392,7 +422,25 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
/* newer update queued, ignore this one */
return SUCCESS;
}
- process_payloads(this, message);
+ if (this->cookie2.ptr)
+ { /* check cookie if we included none */
+ chunk_t cookie2;
+
+ cookie2 = this->cookie2;
+ this->cookie2 = chunk_empty;
+ process_payloads(this, message);
+ if (!chunk_equals(cookie2, this->cookie2))
+ {
+ chunk_free(&cookie2);
+ DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
+ return FAILED;
+ }
+ chunk_free(&cookie2);
+ }
+ else
+ {
+ process_payloads(this, message);
+ }
if (this->natd)
{
this->natd->task.process(&this->natd->task, message);
diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h
index bb5150723..9dd29970e 100644
--- a/src/charon/sa/tasks/ike_mobike.h
+++ b/src/charon/sa/tasks/ike_mobike.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_mobike.h
- *
- * @brief Interface ike_mobike_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_mobike.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_mobike ike_mobike
+ * @{ @ingroup tasks
*/
#ifndef IKE_MOBIKE_H_
@@ -31,7 +31,7 @@ typedef struct ike_mobike_t ike_mobike_t;
#include <network/packet.h>
/**
- * @brief Task of type ike_mobike, detects and handles MOBIKE extension.
+ * Task of type ike_mobike, detects and handles MOBIKE extension.
*
* The MOBIKE extension is defined in RFC4555. It allows to update IKE
* and IPsec tunnel addresses.
@@ -39,11 +39,6 @@ typedef struct ike_mobike_t ike_mobike_t;
* support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional
* endpoints and handles the UPDATE_SA_ADDRESS notify to finally update
* endpoints.
- *
- * @b Constructors:
- * - ike_mobike_create()
- *
- * @ingroup tasks
*/
struct ike_mobike_t {
@@ -53,36 +48,33 @@ struct ike_mobike_t {
task_t task;
/**
- * @brief Use the task to roam to other addresses.
+ * Use the task to roam to other addresses.
*
- * @param this calling object
* @param address TRUE to include address list update
*/
void (*roam)(ike_mobike_t *this, bool address);
/**
- * @brief Transmision hook, called by task manager.
+ * Transmision hook, called by task manager.
*
* The task manager calls this hook whenever it transmits a packet. It
* allows the mobike task to send the packet on multiple paths to do path
* probing.
*
- * @param this calling object
* @param packet the packet to transmit
*/
void (*transmit)(ike_mobike_t *this, packet_t *packet);
/**
- * @brief Check if this task is probing for routability.
+ * Check if this task is probing for routability.
*
- * @param this calling object
* @return TRUE if task is probing
*/
bool (*is_probing)(ike_mobike_t *this);
};
/**
- * @brief Create a new ike_mobike task.
+ * Create a new ike_mobike task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
@@ -90,5 +82,4 @@ struct ike_mobike_t {
*/
ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_MOBIKE_H_ */
-
+#endif /* IKE_MOBIKE_H_ @} */
diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c
index 4c64ff8ba..69e5bac26 100644
--- a/src/charon/sa/tasks/ike_natd.c
+++ b/src/charon/sa/tasks/ike_natd.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_natd.c
- *
- * @brief Implementation of the ike_natd task.
- *
- */
-
/*
* Copyright (C) 2006-2007 Martin Willi
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
@@ -19,6 +12,8 @@
* 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: ike_natd.c 3806 2008-04-15 05:56:35Z martin $
*/
#include "ike_natd.h"
@@ -118,17 +113,17 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
*/
static chunk_t generate_natd_hash_faked(private_ike_natd_t *this)
{
- randomizer_t *randomizer;
+ rng_t *rng;
chunk_t chunk;
- randomizer = randomizer_create();
- if (randomizer->allocate_pseudo_random_bytes(randomizer, HASH_SIZE_SHA1,
- &chunk) != SUCCESS)
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
{
DBG1(DBG_IKE, "unable to get random bytes for NATD fake");
- chunk = chunk_empty;
+ return chunk_empty;
}
- randomizer->destroy(randomizer);
+ rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk);
+ rng->destroy(rng);
return chunk;
}
@@ -259,7 +254,7 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
{
peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-#ifdef P2P
+#ifdef ME
/* if we are on a mediated connection we have already switched to
* port 4500 and the correct destination port is already configured,
* therefore we must not switch again */
@@ -267,14 +262,14 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
{
return SUCCESS;
}
-#endif /* P2P */
+#endif /* ME */
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) ||
-#ifdef P2P
+#ifdef ME
/* if we are on a mediation connection we swith to port 4500 even
* if no NAT is detected. */
peer_cfg->is_mediation(peer_cfg) ||
-#endif /* P2P */
+#endif /* ME */
/* if peer supports NAT-T, we switch to port 4500 even
* if no NAT is detected. MOBIKE requires this. */
(peer_cfg->use_mobike(peer_cfg) &&
@@ -308,6 +303,12 @@ static status_t build_i(private_ike_natd_t *this, message_t *message)
iterator_t *iterator;
host_t *host;
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
+ return NEED_MORE;
+ }
+
/* destination is always set */
host = message->get_destination(message);
notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
@@ -368,6 +369,12 @@ static status_t build_r(private_ike_natd_t *this, message_t *message)
if (this->src_seen && this->dst_seen)
{
+ if (this->hasher == NULL)
+ {
+ DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
+ return SUCCESS;
+ }
+
/* initiator seems to support NAT detection, add response */
me = message->get_source(message);
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me);
@@ -415,7 +422,7 @@ static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa)
*/
static void destroy(private_ike_natd_t *this)
{
- this->hasher->destroy(this->hasher);
+ DESTROY_IF(this->hasher);
free(this);
}
@@ -443,7 +450,7 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
this->ike_sa = ike_sa;
this->initiator = initiator;
- this->hasher = hasher_create(HASH_SHA1);
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
this->src_seen = FALSE;
this->dst_seen = FALSE;
this->src_matched = FALSE;
diff --git a/src/charon/sa/tasks/ike_natd.h b/src/charon/sa/tasks/ike_natd.h
index 8d0cb58b4..d78c931d9 100644
--- a/src/charon/sa/tasks/ike_natd.h
+++ b/src/charon/sa/tasks/ike_natd.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_natd.h
- *
- * @brief Interface ike_natd_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_natd.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_natd ike_natd
+ * @{ @ingroup tasks
*/
#ifndef IKE_NATD_H_
@@ -30,12 +30,7 @@ typedef struct ike_natd_t ike_natd_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange.
- *
- * @b Constructors:
- * - ike_natd_create()
- *
- * @ingroup tasks
+ * Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange.
*/
struct ike_natd_t {
@@ -46,7 +41,7 @@ struct ike_natd_t {
};
/**
- * @brief Create a new ike_natd task.
+ * Create a new ike_natd task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if thask is the original initator
@@ -54,4 +49,4 @@ struct ike_natd_t {
*/
ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_NATD_H_ */
+#endif /* IKE_NATD_H_ @} */
diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c
index 0e98382a8..854e9359d 100644
--- a/src/charon/sa/tasks/ike_reauth.c
+++ b/src/charon/sa/tasks/ike_reauth.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_reauth.c
- *
- * @brief Implementation of the ike_reauth task.
- *
- */
-
/*
* Copyright (C) 2006-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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: ike_reauth.c 3793 2008-04-11 08:14:48Z martin $
*/
#include "ike_reauth.h"
@@ -66,22 +61,30 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
host_t *host;
iterator_t *iterator;
child_sa_t *child_sa;
+ peer_cfg_t *peer_cfg;
/* process delete response first */
this->ike_delete->task.process(&this->ike_delete->task, message);
- /* reestablish only if we have children */
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+
+ /* reauthenticate only if we have children */
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
- if (iterator->get_count(iterator) == 0)
+ if (iterator->get_count(iterator) == 0
+#ifdef ME
+ /* we allow a peer to reauth a mediation connection (without CHILD_SA) */
+ && !peer_cfg->is_mediation(peer_cfg)
+#endif /* ME */
+ )
{
- DBG1(DBG_IKE, "unable to reestablish IKE_SA, no CHILD_SA to recreate");
+ DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
iterator->destroy(iterator);
return FAILED;
}
new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
- new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
+ new->set_peer_cfg(new, peer_cfg);
host = this->ike_sa->get_other_host(this->ike_sa);
new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa);
@@ -93,6 +96,20 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
new->set_virtual_ip(new, TRUE, host);
}
+#ifdef ME
+ /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ if (new->initiate(new, NULL) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, new);
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+ return FAILED;
+ }
+ }
+#endif /* ME */
+
while (iterator->iterate(iterator, (void**)&child_sa))
{
switch (child_sa->get_state(child_sa))
@@ -114,7 +131,7 @@ 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);
- DBG1(DBG_IKE, "reestablishing IKE_SA failed");
+ DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
break;
diff --git a/src/charon/sa/tasks/ike_reauth.h b/src/charon/sa/tasks/ike_reauth.h
index 3c872e1e1..1076cc7cc 100644
--- a/src/charon/sa/tasks/ike_reauth.h
+++ b/src/charon/sa/tasks/ike_reauth.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_reauth.h
- *
- * @brief Interface ike_reauth_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_reauth.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_reauth ike_reauth
+ * @{ @ingroup tasks
*/
#ifndef IKE_REAUTH_H_
@@ -30,12 +30,7 @@ typedef struct ike_reauth_t ike_reauth_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type ike_reauth, reestablishes an IKE_SA.
- *
- * @b Constructors:
- * - ike_reauth_create()
- *
- * @ingroup tasks
+ * Task of type ike_reauth, reestablishes an IKE_SA.
*/
struct ike_reauth_t {
@@ -46,7 +41,7 @@ struct ike_reauth_t {
};
/**
- * @brief Create a new ike_reauth task.
+ * Create a new ike_reauth task.
*
* This task is initiator only.
*
@@ -55,5 +50,4 @@ struct ike_reauth_t {
*/
ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa);
-#endif /* IKE_REAUTH_H_ */
-
+#endif /* IKE_REAUTH_H_ @} */
diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c
index 827f95156..9c0d1805c 100644
--- a/src/charon/sa/tasks/ike_rekey.c
+++ b/src/charon/sa/tasks/ike_rekey.c
@@ -1,10 +1,3 @@
-/**
- * @file ike_rekey.c
- *
- * @brief Implementation of the ike_rekey task.
- *
- */
-
/*
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,8 @@
* 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: ike_rekey.c 3589 2008-03-13 14:14:44Z martin $
*/
#include "ike_rekey.h"
diff --git a/src/charon/sa/tasks/ike_rekey.h b/src/charon/sa/tasks/ike_rekey.h
index 125422efd..1bfde8a54 100644
--- a/src/charon/sa/tasks/ike_rekey.h
+++ b/src/charon/sa/tasks/ike_rekey.h
@@ -1,10 +1,3 @@
-/**
- * @file ike_rekey.h
- *
- * @brief Interface ike_rekey_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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: ike_rekey.h 3589 2008-03-13 14:14:44Z martin $
+ */
+
+/**
+ * @defgroup ike_rekey ike_rekey
+ * @{ @ingroup tasks
*/
#ifndef IKE_REKEY_H_
@@ -30,12 +30,7 @@ typedef struct ike_rekey_t ike_rekey_t;
#include <sa/tasks/task.h>
/**
- * @brief Task of type IKE_REKEY, rekey an established IKE_SA.
- *
- * @b Constructors:
- * - ike_rekey_create()
- *
- * @ingroup tasks
+ * Task of type IKE_REKEY, rekey an established IKE_SA.
*/
struct ike_rekey_t {
@@ -45,20 +40,19 @@ struct ike_rekey_t {
task_t task;
/**
- * @brief Register a rekeying task which collides with this one.
+ * Register a rekeying task which collides with this one.
*
* If two peers initiate rekeying at the same time, the collision must
* be handled gracefully. The task manager is aware of what exchanges
* are going on and notifies the outgoing task by passing the incoming.
*
- * @param this task initated by us
* @param other incoming task
*/
void (*collide)(ike_rekey_t* this, task_t *other);
};
/**
- * @brief Create a new IKE_REKEY task.
+ * Create a new IKE_REKEY task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE for initiator, FALSE for responder
@@ -66,4 +60,4 @@ struct ike_rekey_t {
*/
ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator);
-#endif /* IKE_REKEY_H_ */
+#endif /* IKE_REKEY_H_ @} */
diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c
index cc20a8861..3192b688a 100644
--- a/src/charon/sa/tasks/task.c
+++ b/src/charon/sa/tasks/task.c
@@ -1,10 +1,3 @@
-/**
- * @file task.c
- *
- * @brief Enum values for task types
- *
- */
-
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2007 Martin Willi
@@ -19,6 +12,8 @@
* 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: task.c 3666 2008-03-26 18:40:19Z tobias $
*/
#include "task.h"
@@ -29,15 +24,16 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_MOBIKE",
"IKE_AUTHENTICATE",
"IKE_AUTH_LIFETIME",
- "IKE_CERT",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
"IKE_CONFIG",
"IKE_REKEY",
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DPD",
-#ifdef P2P
- "IKE_P2P",
-#endif /* P2P */
+#ifdef ME
+ "IKE_ME",
+#endif /* ME */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h
index a59207711..26b4f214e 100644
--- a/src/charon/sa/tasks/task.h
+++ b/src/charon/sa/tasks/task.h
@@ -1,10 +1,3 @@
-/**
- * @file task.h
- *
- * @brief Interface task_t.
- *
- */
-
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2006 Martin Willi
@@ -19,6 +12,13 @@
* 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: task.h 3666 2008-03-26 18:40:19Z tobias $
+ */
+
+/**
+ * @defgroup task task
+ * @{ @ingroup tasks
*/
#ifndef TASK_H_
@@ -32,9 +32,7 @@ typedef struct task_t task_t;
#include <encoding/message.h>
/**
- * @brief Different kinds of tasks.
- *
- * @ingroup tasks
+ * Different kinds of tasks.
*/
enum task_type_t {
/** establish an unauthenticated IKE_SA */
@@ -47,8 +45,10 @@ enum task_type_t {
IKE_AUTHENTICATE,
/** AUTH_LIFETIME negotiation, RFC4478 */
IKE_AUTH_LIFETIME,
- /** exchange certificates and requests */
- IKE_CERT,
+ /** certificate processing before authentication (certreqs, cert parsing) */
+ IKE_CERT_PRE,
+ /** certificate processing after authentication (certs payload generation) */
+ IKE_CERT_POST,
/** Configuration payloads, virtual IP and such */
IKE_CONFIG,
/** rekey an IKE_SA */
@@ -59,10 +59,10 @@ enum task_type_t {
IKE_DELETE,
/** liveness check */
IKE_DPD,
-#ifdef P2P
- /** handle P2P-NAT-T stuff */
- IKE_P2P,
-#endif /* P2P */
+#ifdef ME
+ /** handle ME stuff */
+ IKE_ME,
+#endif /* ME */
/** establish a CHILD_SA within an IKE_SA */
CHILD_CREATE,
/** delete an established CHILD_SA */
@@ -77,7 +77,7 @@ enum task_type_t {
extern enum_name_t *task_type_names;
/**
- * @brief Interface for a task, an operation handled within exchanges.
+ * Interface for a task, an operation handled within exchanges.
*
* A task is an elemantary operation. It may be handled by a single or by
* multiple exchanges. An exchange may even complete multiple tasks.
@@ -94,18 +94,12 @@ extern enum_name_t *task_type_names;
* the task needs further build()/process() calls to complete, the manager
* leaves the taks in the queue. A returned FAILED indicates a critical failure.
* The manager closes the IKE_SA whenever a task returns FAILED.
- *
- * @b Constructors:
- * - None, use implementations specific constructors
- *
- * @ingroup tasks
*/
struct task_t {
/**
- * @brief Build a request or response message for this task.
+ * Build a request or response message for this task.
*
- * @param this calling object
* @param message message to add payloads to
* @return
* - FAILED if a critical error occured
@@ -115,9 +109,8 @@ struct task_t {
status_t (*build) (task_t *this, message_t *message);
/**
- * @brief Process a request or response message for this task.
+ * Process a request or response message for this task.
*
- * @param this calling object
* @param message message to read payloads from
* @return
* - FAILED if a critical error occured
@@ -127,14 +120,12 @@ struct task_t {
status_t (*process) (task_t *this, message_t *message);
/**
- * @brief Get the type of the task implementation.
- *
- * @param this calling object
+ * Get the type of the task implementation.
*/
task_type_t (*get_type) (task_t *this);
/**
- * @brief Migrate a task to a new IKE_SA.
+ * Migrate a task to a new IKE_SA.
*
* After migrating a task, it goes back to a state where it can be
* used again to initate an exchange. This is useful when a task
@@ -144,17 +135,14 @@ struct task_t {
* try.
* The ike_sa is the new IKE_SA this task belongs to and operates on.
*
- * @param this calling object
* @param ike_sa new IKE_SA this task works for
*/
void (*migrate) (task_t *this, ike_sa_t *ike_sa);
/**
- * @brief Destroys a task_t object.
- *
- * @param this calling object
+ * Destroys a task_t object.
*/
void (*destroy) (task_t *this);
};
-#endif /* TASK_H_ */
+#endif /* TASK_H_ @} */