task-manager-v2: Reject requests for incomplete IKE_SAs as initiator
authorTobias Brunner <tobias@strongswan.org>
Fri, 26 Oct 2018 09:21:38 +0000 (11:21 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 26 Oct 2018 09:22:08 +0000 (11:22 +0200)
Based on a patch by Thomas Egerer.

src/libcharon/sa/ikev2/task_manager_v2.c

index 910c77a..be180a4 100644 (file)
@@ -1459,6 +1459,59 @@ static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg,
 }
 
 /**
+ * Check whether we should reject the given request message
+ */
+static inline bool reject_request(private_task_manager_t *this,
+                                                                 message_t *msg)
+{
+       ike_sa_state_t state;
+       exchange_type_t type;
+       ike_sa_id_t *ike_sa_id;
+       bool reject = FALSE;
+
+       state = this->ike_sa->get_state(this->ike_sa);
+       type = msg->get_exchange_type(msg);
+
+       /* reject initial messages if not received in specific states */
+       switch (type)
+       {
+               case IKE_SA_INIT:
+                       reject = state != IKE_CREATED;
+                       break;
+               case IKE_AUTH:
+                       reject = state != IKE_CONNECTING;
+                       break;
+               default:
+                       break;
+       }
+
+       if (!reject)
+       {
+               switch (state)
+               {
+                       /* after rekeying we only expect a DELETE in an INFORMATIONAL */
+                       case IKE_REKEYED:
+                               reject = type != INFORMATIONAL;
+                               break;
+                       /* also reject requests for half-open IKE_SAs as initiator */
+                       case IKE_CREATED:
+                       case IKE_CONNECTING:
+                               ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+                               reject = ike_sa_id->is_initiator(ike_sa_id);
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       if (reject)
+       {
+               DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N", exchange_type_names,
+                        type, ike_sa_state_names, state);
+       }
+       return reject;
+}
+/**
  * Check if a message with message ID 0 looks like it is used to synchronize
  * the message IDs and we are prepared to process it.
  *
@@ -1483,8 +1536,6 @@ METHOD(task_manager_t, process_message, status_t,
        status_t status;
        uint32_t mid;
        bool schedule_delete_job = FALSE;
-       ike_sa_state_t state;
-       exchange_type_t type;
 
        charon->bus->message(charon->bus, msg, TRUE, FALSE);
        status = parse_message(this, msg);
@@ -1525,16 +1576,8 @@ METHOD(task_manager_t, process_message, status_t,
        {
                if (mid == this->responding.mid || (mid == 0 && is_mid_sync(this, msg)))
                {
-                       /* reject initial messages if not received in specific states,
-                        * after rekeying we only expect a DELETE in an INFORMATIONAL */
-                       type = msg->get_exchange_type(msg);
-                       state = this->ike_sa->get_state(this->ike_sa);
-                       if ((type == IKE_SA_INIT && state != IKE_CREATED) ||
-                               (type == IKE_AUTH && state != IKE_CONNECTING) ||
-                               (state == IKE_REKEYED && type != INFORMATIONAL))
+                       if (reject_request(this, msg))
                        {
-                               DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N",
-                                        exchange_type_names, type, ike_sa_state_names, state);
                                return FAILED;
                        }
                        if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))