aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-05-21 14:56:01 +0200
committerTobias Brunner <tobias@strongswan.org>2016-03-04 16:03:00 +0100
commit47701e1178a91da363a61bd0478932352bfde2af (patch)
treec7694752dd55cc98f921f42d2492679633b10644 /src
parentfb7cc16d67e867191335bf05ed5c9fc7e3599a14 (diff)
downloadstrongswan-47701e1178a91da363a61bd0478932352bfde2af.tar.bz2
strongswan-47701e1178a91da363a61bd0478932352bfde2af.tar.xz
ike-init: Verify REDIRECT notify before processing IKE_SA_INIT message
An attacker could blindly send a message with invalid nonce data (or none at all) to DoS an initiator if we just destroy the SA. To prevent this we ignore the message and wait for the one by the correct responder.
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 572c997cb..5cfb51807 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -693,6 +693,54 @@ static void raise_alerts(private_ike_init_t *this, notify_type_t type)
}
}
+METHOD(task_t, pre_process_i, status_t,
+ private_ike_init_t *this, message_t *message)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+
+ /* check for erroneous notifies */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == PLV2_NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ case REDIRECT:
+ {
+ identification_t *gateway;
+ chunk_t data, nonce = chunk_empty;
+ status_t status = SUCCESS;
+
+ if (this->old_sa)
+ {
+ break;
+ }
+ data = notify->get_notification_data(notify);
+ gateway = redirect_data_parse(data, &nonce);
+ if (!gateway || !chunk_equals(nonce, this->my_nonce))
+ {
+ DBG1(DBG_IKE, "received invalid REDIRECT notify");
+ status = FAILED;
+ }
+ DESTROY_IF(gateway);
+ chunk_free(&nonce);
+ enumerator->destroy(enumerator);
+ return status;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ return SUCCESS;
+}
+
METHOD(task_t, process_i, status_t,
private_ike_init_t *this, message_t *message)
{
@@ -762,18 +810,13 @@ METHOD(task_t, process_i, status_t,
}
data = notify->get_notification_data(notify);
gateway = redirect_data_parse(data, &nonce);
- enumerator->destroy(enumerator);
- if (!gateway || !chunk_equals(nonce, this->my_nonce))
- {
- DBG1(DBG_IKE, "received invalid REDIRECT notify");
- }
- else if (this->ike_sa->handle_redirect(this->ike_sa,
- gateway))
+ if (this->ike_sa->handle_redirect(this->ike_sa, gateway))
{
status = NEED_MORE;
}
DESTROY_IF(gateway);
chunk_free(&nonce);
+ enumerator->destroy(enumerator);
return status;
}
default:
@@ -909,6 +952,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
{
this->public.task.build = _build_i;
this->public.task.process = _process_i;
+ this->public.task.pre_process = _pre_process_i;
}
else
{