ikev1: Fix handling of overlapping Quick Mode exchanges
In some cases the third message of a Quick Mode exchange might arrive after the first message of a subsequent Quick Mode exchange. Previously these messages were handled incorrectly and the second Quick Mode exchange failed. Some implementations might even try to establish multiple Quick Modes simultaneously, which is explicitly allowed in RFC 2409. We don't fully support that, though, in particular in case of retransmits. Fixes #1076.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2014 Tobias Brunner
|
||||
* Copyright (C) 2007-2015 Tobias Brunner
|
||||
* Copyright (C) 2007-2011 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -900,6 +900,34 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we already have a quick mode task queued for the exchange with the
|
||||
* given message ID
|
||||
*/
|
||||
static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
quick_mode_t *qm;
|
||||
task_t *task;
|
||||
bool found = FALSE;
|
||||
|
||||
enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
{
|
||||
if (task->get_type(task) == TASK_QUICK_MODE)
|
||||
{
|
||||
qm = (quick_mode_t*)task;
|
||||
if (qm->get_mid(qm) == mid)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle an incoming request message
|
||||
*/
|
||||
@@ -911,6 +939,7 @@ static status_t process_request(private_task_manager_t *this,
|
||||
bool send_response = FALSE, dpd = FALSE;
|
||||
|
||||
if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
|
||||
message->get_exchange_type(message) == QUICK_MODE ||
|
||||
this->passive_tasks->get_count(this->passive_tasks) == 0)
|
||||
{ /* create tasks depending on request type, if not already some queued */
|
||||
switch (message->get_exchange_type(message))
|
||||
@@ -946,6 +975,10 @@ static status_t process_request(private_task_manager_t *this,
|
||||
"unestablished IKE_SA, ignored");
|
||||
return FAILED;
|
||||
}
|
||||
if (have_quick_mode_task(this, message->get_message_id(message)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
task = (task_t *)quick_mode_create(this->ike_sa, NULL,
|
||||
NULL, NULL);
|
||||
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||
|
||||
Reference in New Issue
Block a user