]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
ike-init: Verify REDIRECT notify before processing IKE_SA_INIT message
authorTobias Brunner <tobias@strongswan.org>
Thu, 21 May 2015 12:56:01 +0000 (14:56 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 4 Mar 2016 15:03:00 +0000 (16:03 +0100)
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.

src/libcharon/sa/ikev2/tasks/ike_init.c

index 572c997cb648adddb1bb02fcce724ce2386459fa..5cfb5180783eac70e6df02b6b7e67af9dd821088 100644 (file)
@@ -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
        {