summaryrefslogtreecommitdiff
path: root/src/charon/sa/tasks/child_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/tasks/child_create.c')
-rw-r--r--src/charon/sa/tasks/child_create.c147
1 files changed, 126 insertions, 21 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;