]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3927: appid, cip: parsing cip safety segments
authorUmang Sharma (umasharm) <umasharm@cisco.com>
Tue, 1 Aug 2023 20:14:14 +0000 (20:14 +0000)
committerChris Sherwin (chsherwi) <chsherwi@cisco.com>
Tue, 1 Aug 2023 20:14:14 +0000 (20:14 +0000)
Merge in SNORT/snort3 from ~UMASHARM/snort3:cip to master

Squashed commit of the following:

commit a8174147e5aff828a79dffe6e252b4bea69de8d7
Author: Umang Sharma <umasharm@cisco.com>
Date:   Mon Jul 24 12:07:57 2023 -0400

    appid, cip: parsing cip safety segments

src/network_inspectors/appid/appid_cip_event_handler.cc
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/appid_session_api.cc
src/network_inspectors/appid/application_ids.h
src/network_inspectors/appid/detector_plugins/cip_patterns.cc
src/service_inspectors/cip/cip.h
src/service_inspectors/cip/cip_definitions.h
src/service_inspectors/cip/cip_parsing.cc

index f4d8a6336f2cbb8a255fa0fb2dcba66401463cda..446bd5561069c2c5dc04b02ffc9d5adb7c0380e8 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "appid_cip_event_handler.h"
 #include "detector_plugins/cip_patterns.h"
-#include "service_inspectors/cip/cip.h"
 #include "appid_debug.h"
 
 using namespace snort;
@@ -91,7 +90,6 @@ void CipEventHandler::handle(DataEvent& event, Flow* flow)
     AppId payload_id = asd->get_odp_ctxt().get_cip_matchers().get_cip_payload_id(event_data);
     asd->set_payload_id(payload_id);
     asd->set_ss_application_ids(APP_ID_CIP, APP_ID_CIP, payload_id, APP_ID_NONE, APP_ID_NONE, change_bits);
-    asd->set_cip_msp(event_data->multipayload);
 
     if (change_bits[APPID_PAYLOAD_BIT] and appidDebug->is_enabled())
     {
index 65051b9d9d92701f3671a07e5baa2d921d14a682..520b90c081ab1d2fa8d65ff1dca829f172258f85 100644 (file)
@@ -703,16 +703,6 @@ public:
         return client_info_unpublished;
     }
 
-    void set_cip_msp(bool multipayload)
-    {
-        cip_msp = multipayload;
-    }
-
-    bool is_cip_msp() const
-    {
-        return cip_msp;
-    }
-
     inline bool is_encrypted_oportunistic_tls_session()
     {
         return get_session_flags(APPID_SESSION_OPPORTUNISTIC_TLS) and !flow->flags.data_decrypted;
@@ -741,7 +731,6 @@ private:
     bool no_service_candidate = false;
     bool no_service_inspector = false;
     bool client_info_unpublished = false;
-    bool cip_msp = false;
 };
 
 #endif
index c38fba1d51fcdc326155bfc128b3c311e6231690..8c80649f15763b23b77e4f0c9406ca3f165cc551 100644 (file)
@@ -239,7 +239,7 @@ bool AppIdSessionApi::is_appid_inspecting_session() const
         return true;
     }
 
-    if ( get_service_app_id() == APP_ID_CIP and asd->is_cip_msp())
+    if ( get_service_app_id() == APP_ID_CIP)
     {
          return true;
     }
index 1766214e4130fa4181aabc0c1acc84b9dcf912d1..e393bbc4aa6282e4bbdebf6592facdd029c71cc4 100644 (file)
@@ -1021,6 +1021,7 @@ enum ApplicationIds : AppId
     APP_ID_CIP                            = 5002,
     APP_ID_CIP_UNKNOWN                    = 5003,
     APP_ID_CIP_MALFORMED                  = 5005,
+    APP_ID_CIP_SAFETY                     = 7430,
 #ifdef REG_TEST
     APP_ID_DNS_OVER_TLS                   = 4615,
     APP_ID_REGTEST                        = 10000,
index 1a5c486b70fab9d2f29af51b2fe4abb6925d9b42..ae36ae291b0edab8defbb7cfb3f74ba4760f813f 100644 (file)
@@ -255,6 +255,9 @@ AppId CipPatternMatchers::get_cip_payload_id(const CipEventData* event_data)
         }
         break;
 
+    case CIP_DATA_TYPE_CONNECTION_SAFETY:
+        found_app_id = APP_ID_CIP_SAFETY;
+        break;
     case CIP_DATA_TYPE_CONNECTION:
     case CIP_DATA_TYPE_IMPLICIT:
         found_app_id = match_cip_connection(connection_list, event_data);
index 6499ea53e9937dd3d9f9cb8a6f03c44c3254dad1..59ccf366e57c789786035a1ca794910c82cebd57 100644 (file)
@@ -44,7 +44,8 @@ enum CipDataType
     CIP_DATA_TYPE_IMPLICIT,
     CIP_DATA_TYPE_OTHER,
     CIP_DATA_TYPE_ENIP_COMMAND,
-    CIP_DATA_TYPE_MALFORMED
+    CIP_DATA_TYPE_MALFORMED,
+    CIP_DATA_TYPE_CONNECTION_SAFETY
 };
 
 struct CipEventData
@@ -62,9 +63,6 @@ struct CipEventData
     //  CIP_DATA_TYPE_SET_ATTRIBUTE
     uint8_t service_id;
 
-    // Set when the packet is a multiple service packet
-    bool multipayload;
-
     // Used for:
     //  CIP_DATA_TYPE_PATH_CLASS: This represents the Request Path Class.
     //  CIP_DATA_TYPE_SET_ATTRIBUTE: This represents the Request Path Class.
index 2560ce26fe46e9fd8945cb61f894156ba277760a..7b2826f1f23930a377db0d2ba195b62f5c977360 100644 (file)
@@ -140,6 +140,7 @@ enum CipSegmentType
     CipSegment_Type_LOGICAL_SERVICE_ID,
 
     CipSegment_Type_NETWORK,
+    CipSegment_Type_NETWORK_SAFETY,
 
     CipSegment_Type_SYMBOLIC,
 
@@ -367,7 +368,7 @@ struct CipRequest
 
     // True if this request was a Forward Open Request.
     bool is_forward_open_request;
-
+    bool is_cip_safety;
     // Class ID in the Forward Open Request Connection Path.
     // Used only when is_forward_open_request is true.
     uint32_t connection_path_class_id;
index 9f2f074003708293dedf0e59ea4d5c7f8b883ef3..033a69356ad5636065eb47d518d59e1abf40f0f9 100644 (file)
@@ -690,7 +690,7 @@ static bool parse_segment_network(const uint8_t* data,
 {
     #define CIP_PATH_NETWORK_FORMAT_MASK 0xF0
     #define CIP_PATH_NETWORK_ONE_BYTE 0x40
-
+    #define CIP_PATH_NETWORK_SAFETY_SEGMENT 0x50
     size_t segment_size_bytes = 0;
 
     uint8_t segment_type = data[CIP_PATH_TYPE_OFFSET];
@@ -708,8 +708,11 @@ static bool parse_segment_network(const uint8_t* data,
             return false;
         }
     }
+    if (segment_type == CIP_PATH_NETWORK_SAFETY_SEGMENT)
+       segment->type = CipSegment_Type_NETWORK_SAFETY;
+    else
+       segment->type = CipSegment_Type_NETWORK;
 
-    segment->type = CipSegment_Type_NETWORK;
     segment->size = segment_size_bytes;
 
     return true;
@@ -1015,33 +1018,47 @@ static bool parse_cip_segments(const uint8_t* data,
             break;
         }
 
-        // Save off key data in this segment for later use.
-        if (segment.type == CipSegment_Type_LOGICAL_CLASS)
+        switch (segment.type)
         {
-            path->has_class_id = true;
-            path->class_id = segment.logical_value;
+        // Save off key data in this segment for later use.
+            case CipSegment_Type_LOGICAL_CLASS:
 
-            path->primary_segment_type = CipSegment_Type_LOGICAL_CLASS;
-        }
-        else if (segment.type == CipSegment_Type_DATA_EXT_SYMBOL)
-        {
-            path->primary_segment_type = CipSegment_Type_DATA_EXT_SYMBOL;
-        }
-        else if (segment.type == CipSegment_Type_LOGICAL_INSTANCE)
-        {
-            path->has_instance_id = true;
-            path->instance_id = segment.logical_value;
-        }
-        else if (segment.type == CipSegment_Type_LOGICAL_ATTRIBUTE)
-        {
-            path->has_attribute_id = true;
-            path->attribute_id = segment.logical_value;
-        }
-        else if (segment.type == CipSegment_Type_UNKNOWN)
-        {
-            path->has_unknown_segment = true;
-        }
+                path->has_class_id = true;
+                path->class_id = segment.logical_value;
+
+                path->primary_segment_type = CipSegment_Type_LOGICAL_CLASS;
+                break;
+
+            case CipSegment_Type_DATA_EXT_SYMBOL:
+
+                path->primary_segment_type = CipSegment_Type_DATA_EXT_SYMBOL;
+                break;
+
+            case CipSegment_Type_LOGICAL_INSTANCE:
 
+                path->has_instance_id = true;
+                path->instance_id = segment.logical_value;
+                break;
+
+            case CipSegment_Type_LOGICAL_ATTRIBUTE:
+
+                path->has_attribute_id = true;
+                path->attribute_id = segment.logical_value;
+                break;
+
+            case CipSegment_Type_NETWORK_SAFETY:
+
+                path->primary_segment_type = CipSegment_Type_NETWORK_SAFETY;
+                break;
+
+            case CipSegment_Type_UNKNOWN:
+
+                path->has_unknown_segment = true;
+                break;
+
+            default:
+                break;
+        }
         // Move to the next segment.
         data_length -= segment.size;
         data += segment.size;
@@ -1538,11 +1555,6 @@ static bool parse_multiple_service_packet(const uint8_t* data,
 
         pack_cip_request_event(&embedded_request, &cip_event_data);
 
-        if (i != number_services)
-            cip_event_data.multipayload = true;
-        else
-            cip_event_data.multipayload = false;
-
         DataBus::publish(CipEventData::pub_id, CipEventIds::DATA, cip_event, global_data->snort_packet->flow);
     }
 
@@ -1658,6 +1670,8 @@ static bool parse_cip_command_specific_data_request(const uint8_t* data,
             cip_request->connection_path_class_id = forward_open_request.connection_path.class_id;
             cip_request->timeout_ms = forward_open_request.timeout_ms;
             cip_request->has_timeout = true;
+            if (forward_open_request.connection_path.primary_segment_type == CipSegment_Type_NETWORK_SAFETY)
+                cip_request->is_cip_safety = true;
         }
 
         cip_request->request_type = CipRequestTypeForwardOpen;
@@ -2078,9 +2092,17 @@ void pack_cip_request_event(const CipRequest* request, CipEventData* cip_event_d
 
     if (request->is_forward_open_request)
     {
-        cip_event_data->type = CIP_DATA_TYPE_CONNECTION;
+        if (request->is_cip_safety)
+        {
+            cip_event_data->type = CIP_DATA_TYPE_CONNECTION_SAFETY;
+        }
+        else
+        {
+            cip_event_data->type = CIP_DATA_TYPE_CONNECTION;
+        }
         cip_event_data->class_id = request->connection_path_class_id;
     }
+
     else if (request->request_path.primary_segment_type == CipSegment_Type_LOGICAL_CLASS)
     {
         // Publish Set Attribute Single services separately than other requests.