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.c136
1 files changed, 75 insertions, 61 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index f6043979f..f51443738 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -13,8 +13,6 @@
* 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 4860 2009-02-11 13:09:52Z martin $
*/
#include "child_create.h"
@@ -87,6 +85,16 @@ struct private_child_create_t {
linked_list_t *tsr;
/**
+ * source of triggering packet
+ */
+ traffic_selector_t *packet_tsi;
+
+ /**
+ * destination of triggering packet
+ */
+ traffic_selector_t *packet_tsr;
+
+ /**
* optional diffie hellman exchange
*/
diffie_hellman_t *dh;
@@ -570,7 +578,7 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
*/
static void process_payloads(private_child_create_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
sa_payload_t *sa_payload;
ke_payload_t *ke_payload;
@@ -579,8 +587,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
/* defaults to TUNNEL mode */
this->mode = MODE_TUNNEL;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch (payload->get_type(payload))
{
@@ -616,7 +624,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -643,9 +651,9 @@ static status_t build_i(private_child_create_t *this, message_t *message)
}
break;
case IKE_AUTH:
- if (!message->get_payload(message, ID_INITIATOR))
+ if (message->get_message_id(message) != 1)
{
- /* send only in the first request, not in subsequent EAP */
+ /* send only in the first request, not in subsequent rounds */
return NEED_MORE;
}
break;
@@ -694,7 +702,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
}
this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
NULL, other);
-
+
+ if (this->packet_tsi)
+ {
+ this->tsi->insert_first(this->tsi,
+ this->packet_tsi->clone(this->packet_tsi));
+ }
+ if (this->packet_tsr)
+ {
+ this->tsr->insert_first(this->tsr,
+ this->packet_tsr->clone(this->packet_tsr));
+ }
this->proposals = this->config->get_proposals(this->config,
this->dh_group == MODP_NONE);
this->mode = this->config->get_mode(this->config);
@@ -737,8 +755,6 @@ static status_t build_i(private_child_create_t *this, message_t *message)
*/
static status_t process_r(private_child_create_t *this, message_t *message)
{
- peer_cfg_t *peer_cfg;
-
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@@ -747,42 +763,17 @@ static status_t process_r(private_child_create_t *this, message_t *message)
get_nonce(message, &this->other_nonce);
break;
case IKE_AUTH:
- if (message->get_payload(message, ID_INITIATOR) == NULL)
+ if (message->get_message_id(message) != 1)
{
- /* wait until extensible authentication completed, if used */
+ /* only handle first AUTH payload, not additional rounds */
return NEED_MORE;
}
default:
break;
}
-
+
process_payloads(this, message);
- if (this->tsi == NULL || this->tsr == NULL)
- {
- DBG1(DBG_IKE, "TS payload missing in message");
- return NEED_MORE;
- }
-
- peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg)
- {
- host_t *me, *other;
-
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
-
- this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
- this->tsi, me, other);
- }
return NEED_MORE;
}
@@ -799,7 +790,7 @@ static void handle_child_sa_failure(private_child_create_t *this,
/* we delay the delete for 100ms, as the IKE_AUTH response must arrive
* first */
DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
- charon->scheduler->schedule_job(charon->scheduler, (job_t*)
+ charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
100);
}
@@ -810,10 +801,11 @@ static void handle_child_sa_failure(private_child_create_t *this,
*/
static status_t build_r(private_child_create_t *this, message_t *message)
{
+ peer_cfg_t *peer_cfg;
payload_t *payload;
- iterator_t *iterator;
+ enumerator_t *enumerator;
bool no_dh = TRUE;
-
+
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@@ -828,9 +820,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
no_dh = FALSE;
break;
case IKE_AUTH:
- if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- {
- /* wait until extensible authentication completed, if used */
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
return NEED_MORE;
}
default:
@@ -844,6 +835,25 @@ static status_t build_r(private_child_create_t *this, message_t *message)
return SUCCESS;
}
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg && this->tsi && this->tsr)
+ {
+ host_t *me, *other;
+
+ me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (me == NULL)
+ {
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ }
+ other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
+ if (other == NULL)
+ {
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
+ this->tsi, me, other);
+ }
+
if (this->config == NULL)
{
DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
@@ -854,8 +864,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
/* check if ike_config_t included non-critical error notifies */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -868,7 +878,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
{
DBG1(DBG_IKE,"configuration payload negotation "
"failed, no CHILD_SA built");
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
handle_child_sa_failure(this, message);
return SUCCESS;
}
@@ -877,7 +887,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
@@ -938,7 +948,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
*/
static status_t process_i(private_child_create_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
bool no_dh = TRUE;
@@ -951,9 +961,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
no_dh = FALSE;
break;
case IKE_AUTH:
- if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- {
- /* wait until extensible authentication completed, if used */
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
return NEED_MORE;
}
default:
@@ -961,8 +970,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
}
/* check for erronous notifies */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -982,7 +991,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{
DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
notify_type_names, type);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
handle_child_sa_failure(this, message);
/* an error in CHILD_SA creation is not critical */
return SUCCESS;
@@ -1000,7 +1009,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
bad_group, diffie_hellman_group_names, this->dh_group);
this->public.task.migrate(&this->public.task, this->ike_sa);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return NEED_MORE;
}
default:
@@ -1008,7 +1017,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
process_payloads(this, message);
@@ -1137,11 +1146,11 @@ static void destroy(private_child_create_t *this)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
- if (this->tsi)
+ if (this->tsr)
{
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
}
- if (this->tsr)
+ if (this->tsi)
{
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
}
@@ -1149,6 +1158,8 @@ static void destroy(private_child_create_t *this)
{
DESTROY_IF(this->child_sa);
}
+ DESTROY_IF(this->packet_tsi);
+ DESTROY_IF(this->packet_tsr);
DESTROY_IF(this->proposal);
DESTROY_IF(this->dh);
if (this->proposals)
@@ -1163,7 +1174,8 @@ static void destroy(private_child_create_t *this)
/*
* Described in header.
*/
-child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
+child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
{
private_child_create_t *this = malloc_thing(private_child_create_t);
@@ -1195,6 +1207,8 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
this->proposal = NULL;
this->tsi = NULL;
this->tsr = NULL;
+ this->packet_tsi = tsi ? tsi->clone(tsi) : NULL;
+ this->packet_tsr = tsr ? tsr->clone(tsr) : NULL;
this->dh = NULL;
this->dh_group = MODP_NONE;
this->keymat = ike_sa->get_keymat(ike_sa);