]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Move critical bit checking to ike_sa, notify payload includes unsupported payload...
authorMartin Willi <martin@revosec.ch>
Wed, 10 Nov 2010 15:47:56 +0000 (16:47 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:45:44 +0000 (16:45 +0100)
src/libcharon/encoding/message.c
src/libcharon/encoding/message.h
src/libcharon/sa/ike_sa.c
src/libcharon/sa/task_manager.c
src/libcharon/sa/task_manager.h

index 913b57c62ebdc90fb4f7e085c120215ce6ef81b0..41f0edeafa64e9e4919ff19aad1f58786604b524 100644 (file)
@@ -1313,21 +1313,9 @@ static status_t verify(private_message_t *this)
                while (enumerator->enumerate(enumerator, &payload))
                {
                        payload_type_t type;
-                       unknown_payload_t *unknown;
 
                        type = payload->get_type(payload);
-                       if (!payload_is_known(type))
-                       {
-                               unknown = (unknown_payload_t*)payload;
-                               if (unknown->is_critical(unknown))
-                               {
-                                       DBG1(DBG_ENC, "payload type %N is not supported, "
-                                                "but its critical!", payload_type_names, type);
-                                       enumerator->destroy(enumerator);
-                                       return NOT_SUPPORTED;
-                               }
-                       }
-                       else if (type == rule->type)
+                       if (type == rule->type)
                        {
                                found++;
                                DBG2(DBG_ENC, "found payload of type %N",
index 899ced24a0e713480068851f4cae22ff7d87aed4..7db9e015436cac6ec7f0e16fe030da544c2878d5 100644 (file)
@@ -211,8 +211,6 @@ struct message_t {
         * @param aead          aead transform to verify/decrypt message
         * @return
         *                                      - SUCCESS if parsing successful
-        *                                      - NOT_SUPPORTED if ciritcal unknown payloads found
-        *                                      - NOT_SUPPORTED if message type is not supported!
         *                                      - PARSE_ERROR if message parsing failed
         *                                      - VERIFY_ERROR if message verification failed (bad syntax)
         *                                      - FAILED if integrity check failed
index 04e3d9ebd26977f8a6aa6585bcf1115cce09448f..b012c3d391e4bfd4ba2190ed33fa9a5aea056963 100644 (file)
@@ -50,6 +50,7 @@
 #include <processing/jobs/send_dpd_job.h>
 #include <processing/jobs/send_keepalive_job.h>
 #include <processing/jobs/rekey_ike_sa_job.h>
+#include <encoding/payloads/unknown_payload.h>
 
 #ifdef ME
 #include <sa/tasks/ike_me.h>
@@ -901,7 +902,7 @@ METHOD(ike_sa_t, generate_message, status_t,
  * send a notify back to the sender
  */
 static void send_notify_response(private_ike_sa_t *this, message_t *request,
-                                                                notify_type_t type)
+                                                                notify_type_t type, chunk_t data)
 {
        message_t *response;
        packet_t *packet;
@@ -910,7 +911,7 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
        response->set_exchange_type(response, request->get_exchange_type(request));
        response->set_request(response, FALSE);
        response->set_message_id(response, request->get_message_id(request));
-       response->add_notify(response, FALSE, type, chunk_empty);
+       response->add_notify(response, FALSE, type, data);
        if (this->my_host->is_anyaddr(this->my_host))
        {
                this->my_host->destroy(this->my_host);
@@ -1175,6 +1176,7 @@ METHOD(ike_sa_t, process_message, status_t,
 {
        status_t status;
        bool is_request;
+       u_int8_t type = 0;
 
        if (this->state == IKE_PASSIVE)
        {       /* do not handle messages in passive state */
@@ -1185,9 +1187,29 @@ METHOD(ike_sa_t, process_message, status_t,
 
        status = message->parse_body(message,
                                                                 this->keymat->get_aead(this->keymat, TRUE));
+       if (status == SUCCESS)
+       {       /* check for unsupported critical payloads */
+               enumerator_t *enumerator;
+               unknown_payload_t *unknown;
+               payload_t *payload;
+
+               enumerator = message->create_payload_enumerator(message);
+               while (enumerator->enumerate(enumerator, &payload))
+               {
+                       unknown = (unknown_payload_t*)payload;
+                       type = payload->get_type(payload);
+                       if (!payload_is_known(type) &&
+                               unknown->is_critical(unknown))
+                       {
+                               DBG1(DBG_ENC, "payload type %N is not supported, "
+                                        "but its critical!", payload_type_names, type);
+                               status = NOT_SUPPORTED;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
        if (status != SUCCESS)
        {
-
                if (is_request)
                {
                        switch (status)
@@ -1196,21 +1218,28 @@ METHOD(ike_sa_t, process_message, status_t,
                                        DBG1(DBG_IKE, "critical unknown payloads found");
                                        if (is_request)
                                        {
-                                               send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD);
+                                               send_notify_response(this, message,
+                                                                                        UNSUPPORTED_CRITICAL_PAYLOAD,
+                                                                                        chunk_from_thing(type));
+                                               this->task_manager->incr_mid(this->task_manager, FALSE);
                                        }
                                        break;
                                case PARSE_ERROR:
                                        DBG1(DBG_IKE, "message parsing failed");
                                        if (is_request)
                                        {
-                                               send_notify_response(this, message, INVALID_SYNTAX);
+                                               send_notify_response(this, message,
+                                                                                        INVALID_SYNTAX, chunk_empty);
+                                               this->task_manager->incr_mid(this->task_manager, FALSE);
                                        }
                                        break;
                                case VERIFY_ERROR:
                                        DBG1(DBG_IKE, "message verification failed");
                                        if (is_request)
                                        {
-                                               send_notify_response(this, message, INVALID_SYNTAX);
+                                               send_notify_response(this, message,
+                                                                                        INVALID_SYNTAX, chunk_empty);
+                                               this->task_manager->incr_mid(this->task_manager, FALSE);
                                        }
                                        break;
                                case FAILED:
@@ -1219,10 +1248,6 @@ METHOD(ike_sa_t, process_message, status_t,
                                        break;
                                case INVALID_STATE:
                                        DBG1(DBG_IKE, "found encrypted message, but no keys available");
-                                       if (is_request)
-                                       {
-                                               send_notify_response(this, message, INVALID_SYNTAX);
-                                       }
                                default:
                                        break;
                        }
@@ -1252,7 +1277,8 @@ METHOD(ike_sa_t, process_message, status_t,
                                /* no config found for these hosts, destroy */
                                DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
                                         me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
-                               send_notify_response(this, message, NO_PROPOSAL_CHOSEN);
+                               send_notify_response(this, message,
+                                                                        NO_PROPOSAL_CHOSEN, chunk_empty);
                                return DESTROY_ME;
                        }
                        /* add a timeout if peer does not establish it completely */
index 6dda6d27a083a805d3ba2a744dd8acbdf064c31d..8e41774093377c514415227d3f123f58ae668553 100644 (file)
@@ -1008,6 +1008,19 @@ METHOD(task_manager_t, busy, bool,
        return (this->active_tasks->get_count(this->active_tasks) > 0);
 }
 
+METHOD(task_manager_t, incr_mid, void,
+       private_task_manager_t *this, bool initiate)
+{
+       if (initiate)
+       {
+               this->initiating.mid++;
+       }
+       else
+       {
+               this->responding.mid++;
+       }
+}
+
 METHOD(task_manager_t, reset, void,
        private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
 {
@@ -1091,6 +1104,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa)
                        .queue_task = _queue_task,
                        .initiate = _initiate,
                        .retransmit = _retransmit,
+                       .incr_mid = _incr_mid,
                        .reset = _reset,
                        .adopt_tasks = _adopt_tasks,
                        .busy = _busy,
index 14fccd5f9f214ea2bc653b0cb2780c8ef32ef3b5..5bc6c80c44315bbe55a2adb9e976ffd8b14dc43a 100644 (file)
@@ -148,6 +148,16 @@ struct task_manager_t {
         */
        void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
 
+       /**
+        * Increment a message ID counter, in- or outbound.
+        *
+        * If a message is processed outside of the manager, this call increments
+        * the message ID counters of the task manager.
+        *
+        * @param inititate             TRUE to increment the initiating ID
+        */
+       void (*incr_mid)(task_manager_t *this, bool initiate);
+
        /**
         * Reset message ID counters of the task manager.
         *