From: Sreeja Athirkandathil Narayanan (sathirka) Date: Tue, 10 Jan 2023 15:27:09 +0000 (+0000) Subject: Pull request #3683: Cip appid support on snort3 X-Git-Tag: 3.1.51.0~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5abd4bf24d5b002fe134b8828562949fcd571b25;p=thirdparty%2Fsnort3.git Pull request #3683: Cip appid support on snort3 Merge in SNORT/snort3 from ~SUBALU/snort3:Cip_Appid to master Squashed commit of the following: commit 4de25c9be46823b572bc9a40365966eb587ad4a4 Author: suriya Date: Mon Dec 19 17:51:22 2022 +0530 appid: add support for cip service, client and payload detection --- diff --git a/src/network_inspectors/appid/CMakeLists.txt b/src/network_inspectors/appid/CMakeLists.txt index 894aa910a..6d2afd949 100644 --- a/src/network_inspectors/appid/CMakeLists.txt +++ b/src/network_inspectors/appid/CMakeLists.txt @@ -105,6 +105,8 @@ set ( SP_APPID_SOURCES ) set ( DP_APPID_SOURCES + detector_plugins/cip_patterns.cc + detector_plugins/cip_patterns.h detector_plugins/detector_dns.cc detector_plugins/detector_dns.h detector_plugins/detector_imap.cc @@ -144,6 +146,8 @@ set ( APPID_SOURCES appid_app_descriptor.h appid_config.cc appid_config.h + appid_cip_event_handler.cc + appid_cip_event_handler.h appid_data_decrypt_event_handler.h appid_debug.cc appid_debug.h diff --git a/src/network_inspectors/appid/appid_api.cc b/src/network_inspectors/appid/appid_api.cc index 9e6a367ad..f06316261 100644 --- a/src/network_inspectors/appid/appid_api.cc +++ b/src/network_inspectors/appid/appid_api.cc @@ -261,7 +261,8 @@ bool AppIdApi::is_inspection_needed(const Inspector& inspector) const SnortProtocolId id = inspector.get_service(); const AppIdConfig& config = appid_inspector->get_ctxt().config; - if (id == config.snort_proto_ids[PROTO_INDEX_HTTP2] or id == config.snort_proto_ids[PROTO_INDEX_SSH]) + if (id == config.snort_proto_ids[PROTO_INDEX_HTTP2] or id == config.snort_proto_ids[PROTO_INDEX_SSH] + or id == config.snort_proto_ids[PROTO_INDEX_CIP]) return true; return false; diff --git a/src/network_inspectors/appid/appid_cip_event_handler.cc b/src/network_inspectors/appid/appid_cip_event_handler.cc new file mode 100644 index 000000000..9ef7c546a --- /dev/null +++ b/src/network_inspectors/appid/appid_cip_event_handler.cc @@ -0,0 +1,107 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2023-2023 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License Version 2 as +// published by the Free Software Foundation. You may not use, modify or +// distribute this program under any other version of the GNU General +// Public License. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// -------------------------------------------------------------------------------- +// appid_cip_event_handler.cc author Suriya Balu + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "appid_cip_event_handler.h" +#include "detector_plugins/cip_patterns.h" +#include "appid_debug.h" + +using namespace snort; + +void CipEventHandler::client_handler(AppIdSession& asd) +{ + asd.set_client_id(APP_ID_CIP); + asd.set_client_detected(); + asd.client_inferred_service_id = APP_ID_CIP; +} + +void CipEventHandler::service_handler(const Packet& p, AppIdSession& asd) +{ + int16_t group; + uint16_t port; + const SfIp* ip; + + if (p.is_from_client()) + { + ip = p.ptrs.ip_api.get_dst(); + port = p.ptrs.dp; + group = p.get_egress_group(); + } + else + { + ip = p.ptrs.ip_api.get_src(); + port = p.ptrs.sp; + group = p.get_ingress_group(); + } + + asd.set_server_info(*ip, port, group); + asd.set_service_id(APP_ID_CIP, asd.get_odp_ctxt()); + asd.set_service_detected(); +} + +void CipEventHandler::handle(DataEvent& event, Flow* flow) +{ + if (!flow) + return; + + AppIdSession* asd = appid_api.get_appid_session(*flow); + + if (!asd) + return; + + if (!pkt_thread_odp_ctxt or (asd->get_odp_ctxt_version() != pkt_thread_odp_ctxt->get_version())) + return; + + if (!asd->get_session_flags(APPID_SESSION_DISCOVER_APP | APPID_SESSION_SPECIAL_MONITORED)) + return; + + CipEvent& cip_event = (CipEvent&)event; + const CipEventData* event_data = cip_event.get_event_data(); + + if (!event_data) + return; + + const Packet* p = cip_event.get_packet(); + assert(p); + + AppidChangeBits change_bits; + client_handler(*asd); + service_handler(*p, *asd); + 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); + + if (change_bits[APPID_PAYLOAD_BIT] and appidDebug->is_enabled()) + { + appidDebug->activate(flow, asd, inspector.get_ctxt().config.log_all_sessions); + if (appidDebug->is_active()) + { + const char* app_name_service = asd->get_odp_ctxt().get_app_info_mgr().get_app_name(APP_ID_CIP); + const char* app_name_payload = asd->get_odp_ctxt().get_app_info_mgr().get_app_name(payload_id); + LogMessage("AppIdDbg %s CIP event handler service %s (%d) and payload %s (%d) are detected\n", + appidDebug->get_debug_session(), app_name_service, APP_ID_CIP, app_name_payload, payload_id); + } + } + + asd->publish_appid_event(change_bits, *p); +} diff --git a/src/network_inspectors/appid/appid_cip_event_handler.h b/src/network_inspectors/appid/appid_cip_event_handler.h new file mode 100644 index 000000000..5e21199ce --- /dev/null +++ b/src/network_inspectors/appid/appid_cip_event_handler.h @@ -0,0 +1,44 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2023-2023 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License Version 2 as +// published by the Free Software Foundation. You may not use, modify or +// distribute this program under any other version of the GNU General +// Public License. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// -------------------------------------------------------------------------------- +// appid_cip_event_handler.h author Suriya Balu + +#ifndef APPID_CIP_EVENT_HANDLER_H +#define APPID_CIP_EVENT_HANDLER_H + +#include "pub_sub/cip_events.h" +#include "appid_detector.h" +#include "appid_inspector.h" + +class CipEventHandler : public snort::DataHandler +{ +public: + CipEventHandler(AppIdInspector& inspector) : + DataHandler(MOD_NAME), inspector(inspector) + { } + + void handle(snort::DataEvent&, snort::Flow*) override; + +private: + void client_handler(AppIdSession&); + void service_handler(const snort::Packet&, AppIdSession&); + + AppIdInspector& inspector; +}; + +#endif //APPID_CIP_EVENT_HANDLER_H diff --git a/src/network_inspectors/appid/appid_config.cc b/src/network_inspectors/appid/appid_config.cc index 7af81f52b..f51ee69b5 100644 --- a/src/network_inspectors/appid/appid_config.cc +++ b/src/network_inspectors/appid/appid_config.cc @@ -63,6 +63,7 @@ static void map_app_names_to_snort_ids(SnortConfig* sc, AppIdConfig& config) config.snort_proto_ids[PROTO_INDEX_TFTP] = sc->proto_ref->add("tftp"); config.snort_proto_ids[PROTO_INDEX_SIP] = sc->proto_ref->add("sip"); config.snort_proto_ids[PROTO_INDEX_SSH] = sc->proto_ref->add("ssh"); + config.snort_proto_ids[PROTO_INDEX_CIP] = sc->proto_ref->add("cip"); } AppIdConfig::~AppIdConfig() diff --git a/src/network_inspectors/appid/appid_config.h b/src/network_inspectors/appid/appid_config.h index a0ec848fc..ddd8539a4 100644 --- a/src/network_inspectors/appid/appid_config.h +++ b/src/network_inspectors/appid/appid_config.h @@ -31,6 +31,7 @@ #include "app_info_table.h" #include "client_plugins/client_discovery.h" #include "client_plugins/eve_ca_patterns.h" +#include "detector_plugins/cip_patterns.h" #include "detector_plugins/dns_patterns.h" #include "detector_plugins/http_url_patterns.h" #include "detector_plugins/sip_patterns.h" @@ -63,6 +64,7 @@ enum SnortProtoIdIndex PROTO_INDEX_TFTP, PROTO_INDEX_SIP, PROTO_INDEX_SSH, + PROTO_INDEX_CIP, PROTO_INDEX_MAX }; @@ -188,6 +190,11 @@ public: return length_cache.add(key, val); } + CipPatternMatchers& get_cip_matchers() + { + return cip_matchers; + } + DnsPatternMatchers& get_dns_matchers() { return dns_matchers; @@ -244,6 +251,7 @@ private: HostPortCache host_port_cache; HostPortCache first_pkt_cache; LengthCache length_cache; + CipPatternMatchers cip_matchers; DnsPatternMatchers dns_matchers; HttpPatternMatchers http_matchers; EveCaPatternMatchers eve_ca_matchers; diff --git a/src/network_inspectors/appid/appid_inspector.cc b/src/network_inspectors/appid/appid_inspector.cc index ba24f89f9..df5cd3372 100644 --- a/src/network_inspectors/appid/appid_inspector.cc +++ b/src/network_inspectors/appid/appid_inspector.cc @@ -36,6 +36,7 @@ #include "pub_sub/appid_event_ids.h" #include "pub_sub/intrinsic_event_ids.h" +#include "appid_cip_event_handler.h" #include "appid_data_decrypt_event_handler.h" #include "appid_dcerpc_event_handler.h" #include "appid_debug.h" @@ -128,6 +129,7 @@ bool AppIdInspector::configure(SnortConfig* sc) DataBus::subscribe_global(sip_pub_key, SipEventIds::DIALOG, new SipEventHandler(*this), *sc); DataBus::subscribe_global(dce_tcp_pub_key, DceTcpEventIds::EXP_SESSION, new DceExpSsnEventHandler(), *sc); DataBus::subscribe_global(ssh_pub_key, SshEventIds::STATE_CHANGE, new SshEventHandler(), *sc); + DataBus::subscribe_global(cip_pub_key, CipEventIds::DATA, new CipEventHandler(*this), *sc); DataBus::subscribe_global(external_pub_key, ExternalEventIds::DATA_DECRYPT, new DataDecryptEventHandler(), *sc); DataBus::subscribe_global(external_pub_key, ExternalEventIds::EVE_PROCESS, diff --git a/src/network_inspectors/appid/application_ids.h b/src/network_inspectors/appid/application_ids.h index c9223a05a..d77b71215 100644 --- a/src/network_inspectors/appid/application_ids.h +++ b/src/network_inspectors/appid/application_ids.h @@ -1017,6 +1017,10 @@ enum ApplicationIds : AppId APP_ID_SMB_VERSION_3 = 4647, APP_ID_HTTP3 = 4667, APP_ID_SMB_OVER_QUIC = 4668, + APP_ID_ENIP = 5001, + APP_ID_CIP = 5002, + APP_ID_CIP_UNKNOWN = 5003, + APP_ID_CIP_MALFORMED = 5005, #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 new file mode 100644 index 000000000..26e9862a0 --- /dev/null +++ b/src/network_inspectors/appid/detector_plugins/cip_patterns.cc @@ -0,0 +1,356 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2023-2023 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License Version 2 as +// published by the Free Software Foundation. You may not use, modify or +// distribute this program under any other version of the GNU General +// Public License. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// -------------------------------------------------------------------------------- +// cip_patterns.cc author Suriya Balu + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "cip_patterns.h" +#include "service_inspectors/cip/cip.h" +#include "utils/util.h" + +using namespace snort; + +void CipPatternMatchers::cip_add_enip_command(AppId app_id, uint16_t command_id) +{ + EnipCommandList* pattern = (EnipCommandList*)snort_calloc(sizeof(EnipCommandList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.command_id = command_id; + + pattern->next = enip_command_list; + enip_command_list = pattern; +} + +void CipPatternMatchers::cip_add_path(AppId app_id, uint32_t class_id, uint8_t service_id) +{ + CipPathList* pattern = (CipPathList*)snort_calloc(sizeof(CipPathList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.class_id = class_id; + pattern->data.service_id = service_id; + + pattern->next = path_list; + path_list = pattern; +} + +void CipPatternMatchers::cip_add_set_attribute(AppId app_id, uint32_t class_id, bool is_class_instance, + uint32_t attribute_id) +{ + CipSetAttributeList* pattern = (CipSetAttributeList*)snort_calloc(sizeof(CipSetAttributeList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.class_id = class_id; + pattern->data.is_class_instance = is_class_instance; + pattern->data.attribute_id = attribute_id; + + pattern->next = set_attribute_list; + set_attribute_list = pattern; +} + +void CipPatternMatchers::cip_add_connection_class(AppId app_id, uint32_t class_id) +{ + CipConnectionClassList* pattern = (CipConnectionClassList*)snort_calloc(sizeof(CipConnectionClassList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.class_id = class_id; + + pattern->next = connection_list; + connection_list = pattern; +} + +void CipPatternMatchers::cip_add_extended_symbol_service(AppId app_id, uint8_t service_id) +{ + CipServiceList* pattern = (CipServiceList*)snort_calloc(sizeof(CipServiceList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.service_id = service_id; + + pattern->next = symbol_list; + symbol_list = pattern; +} + +void CipPatternMatchers::cip_add_service(AppId app_id, uint8_t service_id) +{ + CipServiceList* pattern = (CipServiceList*)snort_calloc(sizeof(CipServiceList)); + if (!pattern) + { + return; + } + + pattern->data.app_id = app_id; + pattern->data.service_id = service_id; + + pattern->next = service_list; + service_list = pattern; +} + +static AppId match_enip_command(const EnipCommandList* enip_command_list, const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_ENIP; + + while (enip_command_list) + { + if (event_data->enip_command_id == enip_command_list->data.command_id) + { + found_app_id = enip_command_list->data.app_id; + break; + } + + enip_command_list = enip_command_list->next; + } + + return found_app_id; +} + +static AppId match_cip_service(const CipServiceList* service_list, const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_CIP_UNKNOWN; + + while (service_list) + { + if (event_data->service_id == service_list->data.service_id) + { + found_app_id = service_list->data.app_id; + break; + } + + service_list = service_list->next; + } + + return found_app_id; +} + +static AppId match_cip_path(const CipPathList* path_list, const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_CIP_UNKNOWN; + + while (path_list) + { + if ((event_data->class_id == path_list->data.class_id) + and (event_data->service_id == path_list->data.service_id)) + { + found_app_id = path_list->data.app_id; + break; + } + + path_list = path_list->next; + } + + return found_app_id; +} + +static AppId match_cip_set_attribute(const CipSetAttributeList* set_attribute_list, const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_CIP_UNKNOWN; + + bool is_class_instance = (event_data->instance_id == 0); + + while (set_attribute_list) + { + if ((event_data->class_id == set_attribute_list->data.class_id) + and (is_class_instance == set_attribute_list->data.is_class_instance) + and (event_data->attribute_id == set_attribute_list->data.attribute_id)) + { + found_app_id = set_attribute_list->data.app_id; + break; + } + + set_attribute_list = set_attribute_list->next; + } + + return found_app_id; +} + +static AppId match_cip_connection(const CipConnectionClassList* connection_list, const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_CIP_UNKNOWN; + + while (connection_list) + { + if (event_data->class_id == connection_list->data.class_id) + { + found_app_id = connection_list->data.app_id; + break; + } + + connection_list = connection_list->next; + } + + return found_app_id; +} + +AppId CipPatternMatchers::get_cip_payload_id(const CipEventData* event_data) +{ + AppId found_app_id = APP_ID_CIP_UNKNOWN; + + switch (event_data->type) + { + case CIP_DATA_TYPE_PATH_CLASS: + found_app_id = match_cip_path(path_list, event_data); + + if (found_app_id == APP_ID_CIP_UNKNOWN) + { + found_app_id = match_cip_service(service_list, event_data); + } + break; + + case CIP_DATA_TYPE_PATH_EXT_SYMBOL: + found_app_id = match_cip_service(symbol_list, event_data); + + if (found_app_id == APP_ID_CIP_UNKNOWN) + { + found_app_id = match_cip_service(service_list, event_data); + } + break; + + case CIP_DATA_TYPE_SET_ATTRIBUTE: + found_app_id = match_cip_set_attribute(set_attribute_list, event_data); + + if (found_app_id == APP_ID_CIP_UNKNOWN) + { + found_app_id = match_cip_service(symbol_list, event_data); + + if (found_app_id == APP_ID_CIP_UNKNOWN) + { + found_app_id = match_cip_service(service_list, event_data); + } + } + break; + + case CIP_DATA_TYPE_CONNECTION: + case CIP_DATA_TYPE_IMPLICIT: + found_app_id = match_cip_connection(connection_list, event_data); + break; + + case CIP_DATA_TYPE_MALFORMED: + found_app_id = APP_ID_CIP_MALFORMED; + break; + + case CIP_DATA_TYPE_ENIP_COMMAND: + found_app_id = match_enip_command(enip_command_list, event_data); + break; + + default: + break; + } + return found_app_id; +} + +static void free_enip_command_list(EnipCommandList* enip_command_list) +{ + EnipCommandList* node; + for (node = enip_command_list; node != nullptr; node = enip_command_list) + { + enip_command_list = node->next; + snort_free(node); + } +} + +static void free_cip_path_list(CipPathList* path_list) +{ + CipPathList* node; + for (node = path_list; node != nullptr; node = path_list) + { + path_list = node->next; + snort_free(node); + } +} + +static void free_cip_set_attribute_list( CipSetAttributeList* set_attribute_list) +{ + CipSetAttributeList* node; + for (node = set_attribute_list; node != nullptr; node = set_attribute_list) + { + set_attribute_list = node->next; + snort_free(node); + } +} + +static void free_cip_connection_class_list(CipConnectionClassList* connection_list) +{ + CipConnectionClassList* node; + for (node = connection_list; node != nullptr; node = connection_list) + { + connection_list = node->next; + snort_free(node); + } +} + +static void free_cip_extended_symbol_service_list(CipServiceList* symbol_list) +{ + CipServiceList* node; + for (node = symbol_list; node != nullptr; node = symbol_list) + { + symbol_list = node->next; + snort_free(node); + } +} + +static void free_cip_service_list(CipServiceList* service_list) +{ + CipServiceList* node; + for (node = service_list; node != nullptr; node = service_list) + { + service_list = node->next; + snort_free(node); + } +} + +CipPatternMatchers::~CipPatternMatchers() +{ + free_enip_command_list(enip_command_list); + enip_command_list = nullptr; + + free_cip_path_list(path_list); + path_list = nullptr; + + free_cip_set_attribute_list(set_attribute_list); + set_attribute_list = nullptr; + + free_cip_connection_class_list(connection_list); + connection_list = nullptr; + + free_cip_extended_symbol_service_list(symbol_list); + symbol_list = nullptr; + + free_cip_service_list(service_list); + service_list = nullptr; +} diff --git a/src/network_inspectors/appid/detector_plugins/cip_patterns.h b/src/network_inspectors/appid/detector_plugins/cip_patterns.h new file mode 100644 index 000000000..c3f4d22f9 --- /dev/null +++ b/src/network_inspectors/appid/detector_plugins/cip_patterns.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2023-2023 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License Version 2 as +// published by the Free Software Foundation. You may not use, modify or +// distribute this program under any other version of the GNU General +// Public License. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// -------------------------------------------------------------------------------- +// cip_patterns.h author Suriya Balu + +#ifndef CIP_PATTERN_H +#define CIP_PATTERN_H + +#include "pub_sub/cip_events.h" +#include "application_ids.h" + +struct EnipCommandData +{ + AppId app_id; + uint16_t command_id; +} ; + +struct EnipCommandList +{ + EnipCommandData data; + struct EnipCommandList* next; +} ; + +struct CipPathData +{ + AppId app_id; + uint32_t class_id; + uint8_t service_id; +} ; + +struct CipPathList +{ + CipPathData data; + struct CipPathList* next; +} ; + +struct CipSetAttributeData +{ + AppId app_id; + uint32_t class_id; + bool is_class_instance; + uint32_t attribute_id; +} ; + +struct CipSetAttributeList +{ + CipSetAttributeData data; + struct CipSetAttributeList* next; +} ; + +struct CipConnectionClassData +{ + AppId app_id; + uint32_t class_id; +} ; + +struct CipConnectionClassList +{ + CipConnectionClassData data; + struct CipConnectionClassList* next; +} ; + +struct CipServiceData +{ + AppId app_id; + uint8_t service_id; +} ; + +struct CipServiceList +{ + CipServiceData data; + struct CipServiceList* next; +} ; + +class CipPatternMatchers +{ +public: + ~CipPatternMatchers(); + void cip_add_enip_command(AppId app_id, uint16_t command_id); + void cip_add_path(AppId app_id, uint32_t class_id, uint8_t service_id); + void cip_add_set_attribute(AppId app_id, uint32_t class_id, bool is_class_instance, uint32_t attribute_id); + void cip_add_extended_symbol_service(AppId app_id, uint8_t service_id); + void cip_add_service(AppId app_id, uint8_t service_id); + void cip_add_connection_class(AppId app_id, uint32_t class_id); + AppId get_cip_payload_id(const CipEventData* event_data); + +private: + EnipCommandList* enip_command_list = nullptr; + CipPathList* path_list = nullptr; + CipSetAttributeList* set_attribute_list = nullptr; + CipConnectionClassList* connection_list = nullptr; + CipServiceList* symbol_list = nullptr; + CipServiceList* service_list = nullptr; +} ; + +#endif // CIP_PATTERN_H diff --git a/src/network_inspectors/appid/detector_plugins/test/detector_sip_test.cc b/src/network_inspectors/appid/detector_plugins/test/detector_sip_test.cc index c1f38cfe8..e6b7c6d00 100644 --- a/src/network_inspectors/appid/detector_plugins/test/detector_sip_test.cc +++ b/src/network_inspectors/appid/detector_plugins/test/detector_sip_test.cc @@ -157,6 +157,7 @@ EveCaPatternMatchers::~EveCaPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; ClientDetector::ClientDetector() { } diff --git a/src/network_inspectors/appid/detector_plugins/test/http_url_patterns_test.cc b/src/network_inspectors/appid/detector_plugins/test/http_url_patterns_test.cc index 303b9224b..f4ffa9a0c 100644 --- a/src/network_inspectors/appid/detector_plugins/test/http_url_patterns_test.cc +++ b/src/network_inspectors/appid/detector_plugins/test/http_url_patterns_test.cc @@ -88,6 +88,7 @@ EveCaPatternMatchers::~EveCaPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; void AppIdModule::reset_stats() {} bool AppIdInspector::configure(snort::SnortConfig*) { return true; } diff --git a/src/network_inspectors/appid/lua_detector_api.cc b/src/network_inspectors/appid/lua_detector_api.cc index 0ef36d2d5..c55bb33c9 100644 --- a/src/network_inspectors/appid/lua_detector_api.cc +++ b/src/network_inspectors/appid/lua_detector_api.cc @@ -41,6 +41,7 @@ #include "appid_inspector.h" #include "appid_peg_counts.h" #include "client_plugins/client_discovery.h" +#include "detector_plugins/cip_patterns.h" #include "detector_plugins/detector_dns.h" #include "detector_plugins/detector_pattern.h" #include "detector_plugins/detector_sip.h" @@ -2186,7 +2187,7 @@ static int detector_add_rtmp_url(lua_State* L) return 0; } -/*Lua should inject patterns in format. */ +/*Lua should inject patterns in format. */ static int detector_add_sip_user_agent(lua_State* L) { auto& ud = *UserData::check(L, DETECTOR, 1); @@ -2547,7 +2548,7 @@ static int add_port_pattern_service(lua_State* L) return 0; } -/*Lua should inject patterns in format. */ +/*Lua should inject patterns in format. */ static int detector_add_sip_server(lua_State* L) { auto& ud = *UserData::check(L, DETECTOR, 1); @@ -2765,6 +2766,129 @@ static int get_http_tunneled_port(lua_State* L) return 1; } +/*Lua should inject patterns in format. */ +static int detector_add_cip_connection_class(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint32_t class_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_connection_class(app_id, class_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + +/*Lua should inject patterns in format. */ +static int detector_add_cip_path(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint32_t class_id = lua_tointeger(L, ++index); + uint8_t service_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_path(app_id, class_id, service_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + +/*Lua should inject patterns in format. */ +static int detector_add_cip_set_attribute(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint32_t class_id = lua_tointeger(L, ++index); + bool is_class_instance = lua_toboolean(L, ++index); + uint32_t attribute_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_set_attribute(app_id, class_id, is_class_instance, attribute_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + +/*Lua should inject patterns in format. */ +static int detector_add_cip_extended_symbol_service(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint8_t service_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_extended_symbol_service(app_id, service_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + +/*Lua should inject patterns in format. */ +static int detector_add_cip_service(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint8_t service_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_service(app_id, service_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + +/*Lua should inject patterns in format. */ +static int detector_add_enip_command(lua_State *L) +{ + int index = 1; + + auto& ud = *UserData::check(L, DETECTOR, 1); + // Verify detector user data and that we are NOT in packet context + ud->validate_lua_state(false); + if (!init(L)) + return 0; + + uint32_t app_id = lua_tointeger(L, ++index); + uint16_t command_id = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_cip_matchers().cip_add_enip_command(app_id, command_id); + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id); + + return 0; +} + static const luaL_Reg detector_methods[] = { /* Obsolete API names. No longer use these! They are here for backward @@ -2878,6 +3002,14 @@ static const luaL_Reg detector_methods[] = { "getHttpTunneledIp", get_http_tunneled_ip }, { "getHttpTunneledPort", get_http_tunneled_port }, + /* CIP registration */ + {"addCipConnectionClass", detector_add_cip_connection_class}, + {"addCipPath", detector_add_cip_path}, + {"addCipSetAttribute", detector_add_cip_set_attribute}, + {"addCipExtendedSymbolService", detector_add_cip_extended_symbol_service}, + {"addCipService", detector_add_cip_service}, + {"addEnipCommand", detector_add_enip_command}, + { nullptr, nullptr } }; diff --git a/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h b/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h index 2e6729c15..f06915726 100644 --- a/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h +++ b/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h @@ -88,6 +88,7 @@ SslPatternMatchers::~SslPatternMatchers() { } SipPatternMatchers::~SipPatternMatchers() { } HttpPatternMatchers::~HttpPatternMatchers() { } DnsPatternMatchers::~DnsPatternMatchers() { } +CipPatternMatchers::~CipPatternMatchers() { } void ClientDiscovery::initialize(AppIdInspector&) {} void ClientDiscovery::reload() {} FpSMBData* smb_data = nullptr; diff --git a/src/network_inspectors/appid/test/appid_discovery_test.cc b/src/network_inspectors/appid/test/appid_discovery_test.cc index d7edeea7e..e0a014146 100644 --- a/src/network_inspectors/appid/test/appid_discovery_test.cc +++ b/src/network_inspectors/appid/test/appid_discovery_test.cc @@ -148,6 +148,7 @@ HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { } void ApplicationDescriptor::set_id(AppId app_id){my_id = app_id;} diff --git a/src/network_inspectors/appid/test/appid_mock_definitions.h b/src/network_inspectors/appid/test/appid_mock_definitions.h index 6f046045e..4726813ee 100644 --- a/src/network_inspectors/appid/test/appid_mock_definitions.h +++ b/src/network_inspectors/appid/test/appid_mock_definitions.h @@ -87,6 +87,7 @@ HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; void Field::set(int32_t length, const uint8_t* start, bool own_the_buffer_) { diff --git a/src/network_inspectors/appid/test/service_state_test.cc b/src/network_inspectors/appid/test/service_state_test.cc index b204bd2e6..4e4e3315d 100644 --- a/src/network_inspectors/appid/test/service_state_test.cc +++ b/src/network_inspectors/appid/test/service_state_test.cc @@ -128,6 +128,7 @@ HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; snort::SearchTool::SearchTool(bool) { } snort::SearchTool::~SearchTool() = default; diff --git a/src/network_inspectors/appid/test/tp_lib_handler_test.cc b/src/network_inspectors/appid/test/tp_lib_handler_test.cc index 6045ac200..34d3b28cb 100644 --- a/src/network_inspectors/appid/test/tp_lib_handler_test.cc +++ b/src/network_inspectors/appid/test/tp_lib_handler_test.cc @@ -61,6 +61,7 @@ HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; AlpnPatternMatchers::~AlpnPatternMatchers() = default; +CipPatternMatchers::~CipPatternMatchers() = default; AppIdConfig::~AppIdConfig() = default; OdpContext::OdpContext(const AppIdConfig&, snort::SnortConfig*) { } void ServiceDiscovery::initialize(AppIdInspector&) { } diff --git a/src/pub_sub/cip_events.cc b/src/pub_sub/cip_events.cc index 57e5e1fd5..37c0016b8 100644 --- a/src/pub_sub/cip_events.cc +++ b/src/pub_sub/cip_events.cc @@ -28,9 +28,9 @@ using namespace snort; using namespace std; -CipEvent::CipEvent(const Packet* p, const CipEventData* EventData) +CipEvent::CipEvent(const Packet* p, const CipEventData* event_data) { this->p = p; - this->EventData = EventData; + this->event_data = event_data; } diff --git a/src/pub_sub/cip_events.h b/src/pub_sub/cip_events.h index 6e0fd852c..3ab445ff9 100644 --- a/src/pub_sub/cip_events.h +++ b/src/pub_sub/cip_events.h @@ -47,9 +47,11 @@ public: const snort::Packet* get_packet() const override { return p; } + const CipEventData* get_event_data() + { return event_data; } private: const snort::Packet* p; - const CipEventData* EventData; + const CipEventData* event_data; }; #endif