From: Umang Sharma (umasharm) Date: Tue, 1 Aug 2023 20:14:14 +0000 (+0000) Subject: Pull request #3927: appid, cip: parsing cip safety segments X-Git-Tag: 3.1.69.0~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21f9e68c6e1ee2c476262c2e3902a1b89d7fd438;p=thirdparty%2Fsnort3.git Pull request #3927: appid, cip: parsing cip safety segments Merge in SNORT/snort3 from ~UMASHARM/snort3:cip to master Squashed commit of the following: commit a8174147e5aff828a79dffe6e252b4bea69de8d7 Author: Umang Sharma Date: Mon Jul 24 12:07:57 2023 -0400 appid, cip: parsing cip safety segments --- diff --git a/src/network_inspectors/appid/appid_cip_event_handler.cc b/src/network_inspectors/appid/appid_cip_event_handler.cc index f4d8a6336..446bd5561 100644 --- a/src/network_inspectors/appid/appid_cip_event_handler.cc +++ b/src/network_inspectors/appid/appid_cip_event_handler.cc @@ -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()) { diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index 65051b9d9..520b90c08 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -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 diff --git a/src/network_inspectors/appid/appid_session_api.cc b/src/network_inspectors/appid/appid_session_api.cc index c38fba1d5..8c80649f1 100644 --- a/src/network_inspectors/appid/appid_session_api.cc +++ b/src/network_inspectors/appid/appid_session_api.cc @@ -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; } diff --git a/src/network_inspectors/appid/application_ids.h b/src/network_inspectors/appid/application_ids.h index 1766214e4..e393bbc4a 100644 --- a/src/network_inspectors/appid/application_ids.h +++ b/src/network_inspectors/appid/application_ids.h @@ -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, diff --git a/src/network_inspectors/appid/detector_plugins/cip_patterns.cc b/src/network_inspectors/appid/detector_plugins/cip_patterns.cc index 1a5c486b7..ae36ae291 100644 --- a/src/network_inspectors/appid/detector_plugins/cip_patterns.cc +++ b/src/network_inspectors/appid/detector_plugins/cip_patterns.cc @@ -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); diff --git a/src/service_inspectors/cip/cip.h b/src/service_inspectors/cip/cip.h index 6499ea53e..59ccf366e 100644 --- a/src/service_inspectors/cip/cip.h +++ b/src/service_inspectors/cip/cip.h @@ -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. diff --git a/src/service_inspectors/cip/cip_definitions.h b/src/service_inspectors/cip/cip_definitions.h index 2560ce26f..7b2826f1f 100644 --- a/src/service_inspectors/cip/cip_definitions.h +++ b/src/service_inspectors/cip/cip_definitions.h @@ -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; diff --git a/src/service_inspectors/cip/cip_parsing.cc b/src/service_inspectors/cip/cip_parsing.cc index 9f2f07400..033a69356 100644 --- a/src/service_inspectors/cip/cip_parsing.cc +++ b/src/service_inspectors/cip/cip_parsing.cc @@ -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.