ikev2: Clear fragments of a retransmitted message if we receive the next one
authorTobias Brunner <tobias@strongswan.org>
Wed, 28 Oct 2020 14:50:59 +0000 (15:50 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 29 Oct 2020 13:06:19 +0000 (14:06 +0100)
The message_t object used for defragmentation was only cleared after
all fragments have been received and the message was delivered.  So
if we received only some fragments of a retransmitted message, the
fragments of the next message were not processed (message_t returns
INVALID_ARG if the message ID does not match causing the message to
get ignored).  This rendered the IKE_SA unusable as the client
obviously never retransmitted the fragments of that previous message
after it received our response.

src/libcharon/sa/ikev2/task_manager_v2.c

index 781d6b2..64d95f5 100644 (file)
@@ -1281,7 +1281,7 @@ METHOD(task_manager_t, get_mid, uint32_t,
  * Handle the given IKE fragment, if it is one.
  *
  * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was
- * handled properly.  Error states are  returned if the fragment was invalid or
+ * handled properly.  Error states are returned if the fragment was invalid or
  * the reassembled message could not have been processed properly.
  */
 static status_t handle_fragment(private_task_manager_t *this,
@@ -1290,6 +1290,12 @@ static status_t handle_fragment(private_task_manager_t *this,
        message_t *reassembled;
        status_t status;
 
+       if (*defrag && (*defrag)->get_message_id(*defrag) < msg->get_message_id(msg))
+       {
+               /* clear fragments of an incompletely received retransmitted message */
+               (*defrag)->destroy(*defrag);
+               *defrag = NULL;
+       }
        if (!msg->get_payload(msg, PLV2_FRAGMENT))
        {
                return SUCCESS;