]> git.ipfire.org Git - thirdparty/strongswan.git/blobdiff - src/libcharon/sa/ikev2/task_manager_v2.c
ikev2: Only set STAT_INBOUND for valid and expected messages
[thirdparty/strongswan.git] / src / libcharon / sa / ikev2 / task_manager_v2.c
index 5c0ec49f04dcfad804598b473654469fe0601a81..09447b7e8e0b2fe6fe4b190b3e65d90228c9e924 100644 (file)
@@ -109,7 +109,7 @@ struct private_task_manager_t {
                array_t *packets;
 
                /**
-                * type of the initated exchange
+                * type of the initiated exchange
                 */
                exchange_type_t type;
 
@@ -1458,6 +1458,59 @@ static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg,
        return found && !other;
 }
 
+/**
+ * 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);
@@ -1517,24 +1568,14 @@ METHOD(task_manager_t, process_message, status_t,
                /* add a timeout if peer does not establish it completely */
                schedule_delete_job = TRUE;
        }
-       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
-                                                               time_monotonic(NULL));
 
        mid = msg->get_message_id(msg);
        if (msg->get_request(msg))
        {
                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))
@@ -1544,6 +1585,11 @@ METHOD(task_manager_t, process_message, status_t,
                        status = handle_fragment(this, &this->responding.defrag, msg);
                        if (status != SUCCESS)
                        {
+                               if (status == NEED_MORE)
+                               {
+                                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                                               time_monotonic(NULL));
+                               }
                                return status;
                        }
                        charon->bus->message(charon->bus, msg, TRUE, TRUE);
@@ -1554,6 +1600,8 @@ METHOD(task_manager_t, process_message, status_t,
                        switch (process_request(this, msg))
                        {
                                case SUCCESS:
+                                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                                               time_monotonic(NULL));
                                        this->responding.mid++;
                                        break;
                                case NEED_MORE:
@@ -1570,10 +1618,17 @@ METHOD(task_manager_t, process_message, status_t,
                        status = handle_fragment(this, &this->responding.defrag, msg);
                        if (status != SUCCESS)
                        {
+                               if (status == NEED_MORE)
+                               {
+                                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                                               time_monotonic(NULL));
+                               }
                                return status;
                        }
                        DBG1(DBG_IKE, "received retransmit of request with ID %d, "
                                 "retransmitting response", mid);
+                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                               time_monotonic(NULL));
                        charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
                        send_packets(this, this->responding.packets,
                                                 msg->get_destination(msg), msg->get_source(msg));
@@ -1603,6 +1658,11 @@ METHOD(task_manager_t, process_message, status_t,
                        status = handle_fragment(this, &this->initiating.defrag, msg);
                        if (status != SUCCESS)
                        {
+                               if (status == NEED_MORE)
+                               {
+                                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                                               time_monotonic(NULL));
+                               }
                                return status;
                        }
                        charon->bus->message(charon->bus, msg, TRUE, TRUE);
@@ -1615,6 +1675,8 @@ METHOD(task_manager_t, process_message, status_t,
                                flush(this);
                                return DESTROY_ME;
                        }
+                       this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
+                                                                               time_monotonic(NULL));
                }
                else
                {
@@ -1794,9 +1856,25 @@ static void trigger_mbb_reauth(private_task_manager_t *this)
        enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
        while (enumerator->enumerate(enumerator, &child_sa))
        {
+               child_create_t *child_create;
+
+               switch (child_sa->get_state(child_sa))
+               {
+                       case CHILD_REKEYED:
+                       case CHILD_DELETED:
+                               /* ignore CHILD_SAs in these states */
+                               continue;
+                       default:
+                               break;
+               }
                cfg = child_sa->get_config(child_sa);
-               new->queue_task(new, &child_create_create(new, cfg->get_ref(cfg),
-                                                                                                 FALSE, NULL, NULL)->task);
+               child_create = child_create_create(new, cfg->get_ref(cfg),
+                                                                                  FALSE, NULL, NULL);
+               child_create->use_reqid(child_create, child_sa->get_reqid(child_sa));
+               child_create->use_marks(child_create,
+                                                               child_sa->get_mark(child_sa, TRUE).value,
+                                                               child_sa->get_mark(child_sa, FALSE).value);
+               new->queue_task(new, &child_create->task);
                children = TRUE;
        }
        enumerator->destroy(enumerator);
@@ -1930,8 +2008,7 @@ METHOD(task_manager_t, queue_dpd, void,
 {
        ike_mobike_t *mobike;
 
-       if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE) &&
-               this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
+       if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
        {
 #ifdef ME
                peer_cfg_t *cfg = this->ike_sa->get_peer_cfg(this->ike_sa);