]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
ike-delete: Continue break-before-make reauth if server concurrently deletes SA
authorTobias Brunner <tobias@strongswan.org>
Mon, 14 Oct 2019 15:24:15 +0000 (17:24 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 15 Oct 2019 15:25:37 +0000 (17:25 +0200)
There seem to be servers around that, upon receiving a delete from the
client, instead of responding with an empty INFORMATIONAL, send a delete
themselves.

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

index fd36b144a29dd556fde13de257fcf3026f2c746d..49cd663708b089b2ba2ed87e1f3155b42b8ab566 100644 (file)
@@ -168,6 +168,33 @@ METHOD(task_t, process_r, status_t,
        return NEED_MORE;
 }
 
+/**
+ * Check if we are currently deleting this IKE_SA in a break-before-make reauth.
+ */
+static bool is_reauthenticating(private_ike_delete_t *this)
+{
+       enumerator_t *tasks;
+       task_t *task;
+
+       if (!this->ike_sa->has_condition(this->ike_sa, COND_REAUTHENTICATING))
+       {
+               return FALSE;
+       }
+
+       tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
+                                                                                                TASK_QUEUE_ACTIVE);
+       while (tasks->enumerate(tasks, &task))
+       {
+               if (task->get_type(task) == TASK_IKE_REAUTH)
+               {
+                       tasks->destroy(tasks);
+                       return TRUE;
+               }
+       }
+       tasks->destroy(tasks);
+       return FALSE;
+}
+
 METHOD(task_t, build_r, status_t,
        private_ike_delete_t *this, message_t *message)
 {
@@ -177,6 +204,18 @@ METHOD(task_t, build_r, status_t,
        {       /* invoke ike_down() hook if SA has not been rekeyed */
                charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
        }
+
+       /* if we are currently deleting this IKE_SA due to a break-before-make
+        * reauthentication, make sure to not just silently destroy the SA if
+        * the peer concurrently deletes it */
+       if (is_reauthenticating(this))
+       {
+               if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS)
+               {
+                       DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+               }
+       }
+
        /* completed, delete IKE_SA by returning DESTROY_ME */
        return DESTROY_ME;
 }