ikev2: Reject IKE_INTERMEDIATE requests after IKE_AUTH

We currently only support these exchanges for additional key exchanges,
so once we have the final keys derived and the ike-init task is removed,
we don't expect any more of them.
This commit is contained in:
Tobias Brunner
2024-08-07 16:20:18 +02:00
parent 25f2cdfc56
commit aedf73f7cf
+59 -33
View File
@@ -244,6 +244,49 @@ METHOD(task_manager_t, flush, void,
flush_queue(this, TASK_QUEUE_ACTIVE); flush_queue(this, TASK_QUEUE_ACTIVE);
} }
/**
* Check if a given task has been queued already
*/
static bool has_queued(private_task_manager_t *this, task_queue_t queue,
task_type_t type)
{
enumerator_t *enumerator;
array_t *array;
task_t *task;
bool found = FALSE;
switch (queue)
{
case TASK_QUEUE_ACTIVE:
array = this->active_tasks;
break;
case TASK_QUEUE_PASSIVE:
array = this->passive_tasks;
break;
case TASK_QUEUE_QUEUED:
array = this->queued_tasks;
break;
default:
return FALSE;
}
enumerator = array_create_enumerator(array);
while (enumerator->enumerate(enumerator, &task))
{
if (queue == TASK_QUEUE_QUEUED)
{
task = ((queued_task_t*)task)->task;
}
if (task->get_type(task) == type)
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
/** /**
* Move a task of a specific type from the queue to the active list, if it is * Move a task of a specific type from the queue to the active list, if it is
* not delayed. * not delayed.
@@ -1676,6 +1719,11 @@ static inline bool reject_request(private_task_manager_t *this,
case IKE_SA_INIT: case IKE_SA_INIT:
reject = state != IKE_CREATED; reject = state != IKE_CREATED;
break; break;
case IKE_INTERMEDIATE:
/* only accept this if we have not yet completed the KEs */
reject = state != IKE_CONNECTING ||
!has_queued(this, TASK_QUEUE_PASSIVE, TASK_IKE_INIT);
break;
case IKE_AUTH: case IKE_AUTH:
reject = state != IKE_CONNECTING; reject = state != IKE_CONNECTING;
break; break;
@@ -2029,64 +2077,42 @@ METHOD(task_manager_t, queue_task, void,
queue_task_delayed(this, task, 0); queue_task_delayed(this, task, 0);
} }
/**
* Check if a given task has been queued already
*/
static bool has_queued(private_task_manager_t *this, task_type_t type)
{
enumerator_t *enumerator;
bool found = FALSE;
queued_task_t *queued;
enumerator = array_create_enumerator(this->queued_tasks);
while (enumerator->enumerate(enumerator, &queued))
{
if (queued->task->get_type(queued->task) == type)
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
METHOD(task_manager_t, queue_ike, void, METHOD(task_manager_t, queue_ike, void,
private_task_manager_t *this) private_task_manager_t *this)
{ {
if (!has_queued(this, TASK_IKE_VENDOR)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_VENDOR))
{ {
queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_INIT)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_INIT))
{ {
queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL)); queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL));
} }
if (!has_queued(this, TASK_IKE_NATD)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_NATD))
{ {
queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_CERT_PRE)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_CERT_PRE))
{ {
queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_AUTH)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_AUTH))
{ {
queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_CERT_POST)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_CERT_POST))
{ {
queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_CONFIG)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_CONFIG))
{ {
queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_AUTH_LIFETIME)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_AUTH_LIFETIME))
{ {
queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE));
} }
if (!has_queued(this, TASK_IKE_MOBIKE)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_MOBIKE))
{ {
peer_cfg_t *peer_cfg; peer_cfg_t *peer_cfg;
@@ -2096,12 +2122,12 @@ METHOD(task_manager_t, queue_ike, void,
queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE));
} }
} }
if (!has_queued(this, TASK_IKE_ESTABLISH)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_ESTABLISH))
{ {
queue_task(this, (task_t*)ike_establish_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_establish_create(this->ike_sa, TRUE));
} }
#ifdef ME #ifdef ME
if (!has_queued(this, TASK_IKE_ME)) if (!has_queued(this, TASK_QUEUE_QUEUED, TASK_IKE_ME))
{ {
queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE)); queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE));
} }