From: Shravan Rangarajuvenkata (shrarang) Date: Thu, 23 Sep 2021 09:08:40 +0000 (+0000) Subject: Merge pull request #3042 in SNORT/snort3 from ~CLJUDGE/snort3:snort3_mercury_process_... X-Git-Tag: 3.1.14.0~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b79c2370c0f028e3b4e3530ea0b16c27adfed43;p=thirdparty%2Fsnort3.git Merge pull request #3042 in SNORT/snort3 from ~CLJUDGE/snort3:snort3_mercury_process_clientapp_mapping to master Squashed commit of the following: commit e0711099931cf59733dbfe1a95c2e2b927df5acb Author: cljudge Date: Thu Jun 17 10:15:02 2021 -0400 appid: provide api for Lua detectors to map process name to client app --- diff --git a/src/network_inspectors/appid/CMakeLists.txt b/src/network_inspectors/appid/CMakeLists.txt index d940998b4..fac670bb4 100644 --- a/src/network_inspectors/appid/CMakeLists.txt +++ b/src/network_inspectors/appid/CMakeLists.txt @@ -37,6 +37,8 @@ set ( CP_APPID_SOURCES client_plugins/client_detector.h client_plugins/client_discovery.cc client_plugins/client_discovery.h + client_plugins/efp_ca_patterns.cc + client_plugins/efp_ca_patterns.h ) set ( SP_APPID_SOURCES @@ -152,6 +154,8 @@ set ( APPID_SOURCES appid_discovery.cc appid_discovery.h appid_dns_session.h + appid_efp_process_event_handler.cc + appid_efp_process_event_handler.h appid_ha.cc appid_ha.h appid_http_session.cc @@ -218,6 +222,7 @@ target_include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} ) add_subdirectory(service_plugins/test) add_subdirectory(detector_plugins/test) +add_subdirectory(client_plugins/test) add_subdirectory(test) install (FILES ${APPID_INCLUDES} diff --git a/src/network_inspectors/appid/appid_app_descriptor.h b/src/network_inspectors/appid/appid_app_descriptor.h index d4c4f5470..d7f85d3e3 100644 --- a/src/network_inspectors/appid/appid_app_descriptor.h +++ b/src/network_inspectors/appid/appid_app_descriptor.h @@ -254,9 +254,20 @@ public: void update_stats(AppId id, bool increment = true) override; + void set_efp_client_app_id(AppId id) + { + efp_client_app_id = id; + } + + AppId get_efp_client_app_id() const + { + return efp_client_app_id; + } + private: std::string my_username; AppId my_user_id = APP_ID_NONE; + AppId efp_client_app_id = APP_ID_NONE; }; class PayloadAppDescriptor : public ApplicationDescriptor diff --git a/src/network_inspectors/appid/appid_config.cc b/src/network_inspectors/appid/appid_config.cc index 4dde961aa..4ba519d42 100644 --- a/src/network_inspectors/appid/appid_config.cc +++ b/src/network_inspectors/appid/appid_config.cc @@ -167,6 +167,7 @@ void OdpContext::initialize(AppIdInspector& inspector) service_disco_mgr.finalize_service_patterns(); client_disco_mgr.finalize_client_patterns(); http_matchers.finalize_patterns(); + efp_ca_matchers.finalize_patterns(); // sip patterns need to be finalized after http patterns because they // are dependent on http patterns sip_matchers.finalize_patterns(*this); @@ -183,6 +184,7 @@ void OdpContext::reload() client_pattern_detector->reload_client_port_patterns(); service_disco_mgr.reload_service_patterns(); client_disco_mgr.reload_client_patterns(); + efp_ca_matchers.reload_patterns(); http_matchers.reload_patterns(); sip_matchers.reload_patterns(); ssl_matchers.reload_patterns(); diff --git a/src/network_inspectors/appid/appid_config.h b/src/network_inspectors/appid/appid_config.h index c5f823e26..10bcae24a 100644 --- a/src/network_inspectors/appid/appid_config.h +++ b/src/network_inspectors/appid/appid_config.h @@ -30,6 +30,7 @@ #include "app_info_table.h" #include "client_plugins/client_discovery.h" +#include "client_plugins/efp_ca_patterns.h" #include "detector_plugins/dns_patterns.h" #include "detector_plugins/http_url_patterns.h" #include "detector_plugins/sip_patterns.h" @@ -177,6 +178,11 @@ public: return http_matchers; } + EfpCaPatternMatchers& get_efp_ca_matchers() + { + return efp_ca_matchers; + } + SipPatternMatchers& get_sip_matchers() { return sip_matchers; @@ -214,6 +220,7 @@ private: LengthCache length_cache; DnsPatternMatchers dns_matchers; HttpPatternMatchers http_matchers; + EfpCaPatternMatchers efp_ca_matchers; ServiceDiscovery service_disco_mgr; SipPatternMatchers sip_matchers; SslPatternMatchers ssl_matchers; diff --git a/src/network_inspectors/appid/appid_efp_process_event_handler.cc b/src/network_inspectors/appid/appid_efp_process_event_handler.cc new file mode 100644 index 000000000..669cb7811 --- /dev/null +++ b/src/network_inspectors/appid/appid_efp_process_event_handler.cc @@ -0,0 +1,59 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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_efp_process_event_handler.cc author Cliff Judge + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "appid_efp_process_event_handler.h" + +#include "appid_debug.h" +#include "appid_inspector.h" +#include "appid_session.h" + +using namespace snort; + +void AppIdEfpProcessEventHandler::handle(DataEvent& event, Flow* flow) +{ + assert(flow); + AppIdSession* asd = appid_api.get_appid_session(*flow); + if (!asd or + !asd->get_session_flags(APPID_SESSION_DISCOVER_APP | APPID_SESSION_SPECIAL_MONITORED)) + return; + + if (!pkt_thread_odp_ctxt or + (pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version())) + return; + + const EfpProcessEvent &efp_process_event = static_cast(event); + + const std::string& name = efp_process_event.get_process_name(); + uint8_t conf = efp_process_event.get_process_confidence(); + + AppId app_id = asd->get_odp_ctxt().get_efp_ca_matchers().match_efp_ca_pattern(name, + conf); + + if (appidDebug->is_active()) + LogMessage("AppIdDbg %s encrypted client app %d process name '%s', " + "confidence: %d\n", appidDebug->get_debug_session(), app_id, name.c_str(), conf); + + asd->set_efp_client_app_id(app_id); +} + diff --git a/src/network_inspectors/appid/appid_efp_process_event_handler.h b/src/network_inspectors/appid/appid_efp_process_event_handler.h new file mode 100644 index 000000000..e5fbe28ea --- /dev/null +++ b/src/network_inspectors/appid/appid_efp_process_event_handler.h @@ -0,0 +1,35 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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_efp_process_event_handler.h author Cliff Judge + +#ifndef APPID_EFP_PROCESS_EVENT_HANDLER_H +#define APPID_EFP_PROCESS_EVENT_HANDLER_H + +#include "pub_sub/efp_process_event.h" +#include "appid_module.h" + +class AppIdEfpProcessEventHandler : public snort::DataHandler +{ +public: + AppIdEfpProcessEventHandler() : DataHandler(MOD_NAME) { } + + void handle(snort::DataEvent& event, snort::Flow* flow) override; +}; + +#endif diff --git a/src/network_inspectors/appid/appid_inspector.cc b/src/network_inspectors/appid/appid_inspector.cc index fe8c7fdf0..074057d3f 100644 --- a/src/network_inspectors/appid/appid_inspector.cc +++ b/src/network_inspectors/appid/appid_inspector.cc @@ -38,6 +38,7 @@ #include "appid_dcerpc_event_handler.h" #include "appid_debug.h" #include "appid_discovery.h" +#include "appid_efp_process_event_handler.h" #include "appid_ha.h" #include "appid_http_event_handler.h" #include "appid_http2_req_body_event_handler.h" @@ -149,6 +150,8 @@ bool AppIdInspector::configure(SnortConfig* sc) DataBus::subscribe_global(OPPORTUNISTIC_TLS_EVENT, new AppIdOpportunisticTlsEventHandler(), sc); + DataBus::subscribe_global(EFP_PROCESS_EVENT, new AppIdEfpProcessEventHandler(), sc); + return true; } diff --git a/src/network_inspectors/appid/appid_session.cc b/src/network_inspectors/appid/appid_session.cc index 41ee0b4ce..756a7c650 100644 --- a/src/network_inspectors/appid/appid_session.cc +++ b/src/network_inspectors/appid/appid_session.cc @@ -849,6 +849,11 @@ AppId AppIdSession::pick_ss_client_app_id() const if (tmp_id > APP_ID_NONE) return tmp_id; + if (api.client.get_efp_client_app_id() > APP_ID_NONE and + (api.client.get_id() == APP_ID_SSL_CLIENT or + api.client.get_id() <= APP_ID_NONE)) + return api.client.get_efp_client_app_id(); + if (api.client.get_id() > APP_ID_NONE) return api.client.get_id(); diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index 513ffc0d1..eca17b2b3 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -515,6 +515,16 @@ public: api.client.update_user(id, username, change_bits); } + void set_efp_client_app_id(AppId id) + { + api.client.set_efp_client_app_id(id); + } + + AppId get_efp_client_app_id() const + { + return api.client.get_efp_client_app_id(); + } + AppId get_payload_id() const { return api.payload.get_id(); diff --git a/src/network_inspectors/appid/client_plugins/efp_ca_patterns.cc b/src/network_inspectors/appid/client_plugins/efp_ca_patterns.cc new file mode 100644 index 000000000..fab0bfe8c --- /dev/null +++ b/src/network_inspectors/appid/client_plugins/efp_ca_patterns.cc @@ -0,0 +1,102 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- + +// efp_ca_patterns.cc author Cliff Judge + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "efp_ca_patterns.h" + +#include "log/messages.h" +#include "utils/util.h" +#include "appid_debug.h" + +using namespace snort; + +void EfpCaPatternMatchers::add_efp_ca_pattern(AppId app_id, const std::string& pattern_str, + uint8_t confidence) +{ + EfpCaPattern* new_efp_ca_pattern = new EfpCaPattern(app_id, pattern_str, confidence); + efp_ca_load_list.push_back(new_efp_ca_pattern); +} + +static int efp_ca_pattern_match(void* id, void*, int, void* data, void*) +{ + EfpCaPatternList* efp_ca_match_list = (EfpCaPatternList *)data; + efp_ca_match_list->push_back((EfpCaPattern *)id); + return 0; +} + +AppId EfpCaPatternMatchers::match_efp_ca_pattern(const std::string& pattern, + uint8_t reported_confidence) +{ + EfpCaPatternList* efp_ca_match_list = new EfpCaPatternList(); + EfpCaPattern* best_match = nullptr; + + efp_ca_pattern_matcher.find_all(pattern.data(), pattern.size(), efp_ca_pattern_match, + false, efp_ca_match_list); + + for (auto &mp : *efp_ca_match_list) + { + if (reported_confidence >= mp->confidence) + { + if (!best_match or (mp->pattern.size() > best_match->pattern.size() or + (mp->pattern.size() == best_match->pattern.size() and + mp->confidence > best_match->confidence))) + { + best_match = mp; + } + } + } + AppId ret_app_id = APP_ID_NONE; + if (best_match) + ret_app_id = best_match->app_id; + + delete efp_ca_match_list; + + return ret_app_id; +} + +EfpCaPatternMatchers::~EfpCaPatternMatchers() +{ + for (auto& p : efp_ca_load_list) + delete p; + efp_ca_load_list.clear(); +} + +void EfpCaPatternMatchers::finalize_patterns() +{ + for (auto& p : efp_ca_load_list) + { + efp_ca_pattern_matcher.add(p->pattern.data(), p->pattern.size(), p, true); + + #ifdef REG_TEST + LogMessage("Adding EFP Client App pattern %d %s %d\n", + p->app_id, p->pattern.c_str(), p->confidence); + #endif + } + efp_ca_pattern_matcher.prep(); +} + +void EfpCaPatternMatchers::reload_patterns() +{ + efp_ca_pattern_matcher.reload(); +} + diff --git a/src/network_inspectors/appid/client_plugins/efp_ca_patterns.h b/src/network_inspectors/appid/client_plugins/efp_ca_patterns.h new file mode 100644 index 000000000..53cded9f9 --- /dev/null +++ b/src/network_inspectors/appid/client_plugins/efp_ca_patterns.h @@ -0,0 +1,58 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- + +// efp_ca_patterns.h author Cliff Judge + +#ifndef EFP_CA_PATTERNS_H +#define EFP_CA_PATTERNS_H + +#include + +#include "search_engines/search_tool.h" +#include "application_ids.h" + +struct EfpCaPattern +{ + const AppId app_id; + const std::string pattern; + const uint8_t confidence; + + EfpCaPattern(AppId id, const std::string& name, uint8_t conf) : app_id(id), pattern(name), + confidence(conf) {} + + ~EfpCaPattern() {} +}; + +typedef std::vector EfpCaPatternList; + +class EfpCaPatternMatchers +{ +public: + ~EfpCaPatternMatchers(); + AppId match_efp_ca_pattern(const std::string&, uint8_t); + void add_efp_ca_pattern(AppId, const std::string&, uint8_t); + void finalize_patterns(); + void reload_patterns(); + +private: + snort::SearchTool efp_ca_pattern_matcher = snort::SearchTool(); + EfpCaPatternList efp_ca_load_list; +}; + +#endif + diff --git a/src/network_inspectors/appid/client_plugins/test/CMakeLists.txt b/src/network_inspectors/appid/client_plugins/test/CMakeLists.txt new file mode 100644 index 000000000..9dcc7c489 --- /dev/null +++ b/src/network_inspectors/appid/client_plugins/test/CMakeLists.txt @@ -0,0 +1,5 @@ + +include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} ) + +add_cpputest( efp_ca_patterns_test ) + diff --git a/src/network_inspectors/appid/client_plugins/test/client_plugins_mock.h b/src/network_inspectors/appid/client_plugins/test/client_plugins_mock.h new file mode 100644 index 000000000..d696eaece --- /dev/null +++ b/src/network_inspectors/appid/client_plugins/test/client_plugins_mock.h @@ -0,0 +1,41 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- +// client_plugins_mock.h author author Sreeja Athirkandathil Narayanan + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define APPID_UT_ID 1492 + +namespace snort +{ +// Stubs for messages +void LogMessage(const char*,...) { } + +// Stubs for search_tool.cc +SearchTool::SearchTool(char const*, bool) { } +SearchTool::~SearchTool() = default; +void SearchTool::add(const char*, unsigned, int, bool) { } +void SearchTool::add(const char*, unsigned, void*, bool) { } +void SearchTool::add(const uint8_t*, unsigned, int, bool) { } +void SearchTool::add(const uint8_t*, unsigned, void*, bool) { } +void SearchTool::prep() { } +void SearchTool::reload() { } +} + diff --git a/src/network_inspectors/appid/client_plugins/test/efp_ca_patterns_test.cc b/src/network_inspectors/appid/client_plugins/test/efp_ca_patterns_test.cc new file mode 100644 index 000000000..add4f1aa3 --- /dev/null +++ b/src/network_inspectors/appid/client_plugins/test/efp_ca_patterns_test.cc @@ -0,0 +1,98 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- +// +// efp_ca_patterns_test.cc author Sreeja Athirkandathil Narayanan + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "client_plugins/efp_ca_patterns.cc" +#include "client_plugins_mock.h" + +#include +#include +#include + +static EfpCaPatternMatchers* efp_matcher = nullptr; +EfpCaPattern efp_ca(APPID_UT_ID, "firefox", 90); + +namespace snort +{ +int SearchTool::find_all(const char* pattern, unsigned, MpseMatch, bool, void* data) +{ + if (strcmp(pattern, "firefox") == 0) + efp_ca_pattern_match(&efp_ca, nullptr, 0, data, nullptr); + return 0; +} +} + +TEST_GROUP(efp_ca_patterns_tests) +{ + void setup() override + { + efp_matcher = new EfpCaPatternMatchers(); + } + void teardown() override + { + delete efp_matcher; + } +}; + + +TEST(efp_ca_patterns_tests, efp_ca_pattern_match) +{ + EfpCaPatternList data; + EfpCaPattern efp1(APPID_UT_ID + 1, "firefox", 80); + efp_ca_pattern_match(&efp1, nullptr, 0, &data, nullptr); + EfpCaPattern* efp = data.back(); + CHECK(efp->app_id == efp1.app_id); + CHECK(efp->pattern == efp1.pattern); + CHECK(efp->confidence == efp1.confidence); + + EfpCaPattern efp2(APPID_UT_ID + 2, "chrome", 95); + efp_ca_pattern_match(&efp2, nullptr, 0, &data, nullptr); + efp = data.back(); + CHECK(efp->app_id == efp2.app_id); + CHECK(efp->pattern == efp2.pattern); + CHECK(efp->confidence == efp2.confidence); + CHECK(data.size() == 2); +} + + +TEST(efp_ca_patterns_tests, match_efp_ca_pattern) +{ + // 1. pattern not present in pattern matcher list + CHECK(efp_matcher->match_efp_ca_pattern("chrome", 95) == 0); + + // 2. pattern matches, confidence doesn't match + CHECK(efp_matcher->match_efp_ca_pattern("firefox", 60) == 0); + + // 3. pattern and confidence matches + CHECK(efp_matcher->match_efp_ca_pattern("firefox", 90) == APPID_UT_ID); + + // 4. pattern matches, reported confidence > existing value + CHECK(efp_matcher->match_efp_ca_pattern("firefox", 92) == APPID_UT_ID); +} + +int main(int argc, char** argv) +{ + int return_value = CommandLineTestRunner::RunAllTests(argc, argv); + return return_value; +} + 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 655acdcfa..f8ce42d74 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 @@ -141,6 +141,7 @@ void AppIdDiscovery::register_udp_pattern(AppIdDetector*, unsigned char const*, int AppIdDiscovery::add_service_port(AppIdDetector*, ServiceDetectorPort const&) { return 0; } void AppIdModule::reset_stats() {} DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; 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 488b3d7fe..cc18cbdc6 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 @@ -87,6 +87,7 @@ void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, void AppIdDiscovery::register_udp_pattern(AppIdDetector*, unsigned char const*, unsigned int, int, unsigned int) { } int AppIdDiscovery::add_service_port(AppIdDetector*, ServiceDetectorPort const&) { return 0; } DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; void AppIdModule::reset_stats() {} diff --git a/src/network_inspectors/appid/lua_detector_api.cc b/src/network_inspectors/appid/lua_detector_api.cc index 5bd5966e6..18b09e9a0 100644 --- a/src/network_inspectors/appid/lua_detector_api.cc +++ b/src/network_inspectors/appid/lua_detector_api.cc @@ -114,7 +114,7 @@ static inline int convert_string_to_address(const char* string, SfIp* address) static inline bool lua_params_validator(LuaDetectorParameters& ldp, bool packet_context) { - if ( packet_context ) + if (packet_context) { assert(ldp.asd); assert(ldp.pkt); @@ -231,7 +231,7 @@ static int service_register_pattern(lua_State* L) size_t size = lua_tonumber(L, ++index); unsigned int position = lua_tonumber(L, ++index); - if ( protocol == IpProtocol::TCP) + if (protocol == IpProtocol::TCP) ud->get_odp_ctxt().get_service_disco_mgr().register_tcp_pattern(ud->sd, (const uint8_t*)pattern, size, position, 0); else @@ -254,7 +254,7 @@ static int common_register_application_id(lua_State* L) int index = 1; AppId appId = lua_tonumber(L, ++index); - if ( ad->is_client() ) + if (ad->is_client()) ad->register_appid(appId, APPINFO_FLAG_CLIENT_ADDITIONAL, ud->get_odp_ctxt()); else ad->register_appid(appId, APPINFO_FLAG_SERVICE_ADDITIONAL, ud->get_odp_ctxt()); @@ -300,7 +300,7 @@ static int detector_log_message(lua_State* L) unsigned int level = lua_tonumber(L, 2); const char* message = lua_tostring(L, 3); - switch ( level ) + switch (level) { case LUA_LOG_CRITICAL: FatalError("%s:%s\n", name.c_str(), message); @@ -392,13 +392,13 @@ static int service_add_ports(lua_State* L) pp.port = lua_tonumber(L, 3); pp.reversed_validation = lua_tonumber(L, 5); - if ( ((pp.proto != IpProtocol::UDP) && (pp.proto != IpProtocol::TCP)) || !pp.port ) + if (((pp.proto != IpProtocol::UDP) and (pp.proto != IpProtocol::TCP)) or !pp.port) { lua_pushnumber(L, -1); return 1; } - if ( ud->sd->get_handler().add_service_port(ud->sd, pp) ) + if (ud->sd->get_handler().add_service_port(ud->sd, pp)) { lua_pushnumber(L, -1); return 1; @@ -690,7 +690,7 @@ static int detector_get_pcre_groups(lua_State* L) ovector, // output vector for substring information OVECCOUNT); // number of elements in the output vector - if ( rc >= 0 ) + if (rc >= 0) { if (rc == 0) { @@ -714,7 +714,7 @@ static int detector_get_pcre_groups(lua_State* L) else { // log errors except no matches - if ( rc != PCRE_ERROR_NOMATCH) + if (rc != PCRE_ERROR_NOMATCH) WarningMessage("PCRE regular expression group match failed. rc: %d\n", rc); rc = 0; } @@ -760,14 +760,14 @@ static int detector_get_protocol_type(lua_State* L) // Verify detector user data and that we are in packet context LuaStateDescriptor* lsd = ud->validate_lua_state(true); - if ( !lsd->ldp.pkt->has_ip() ) + if (!lsd->ldp.pkt->has_ip()) { lua_pushnumber(L, 0); return 1; } // FIXIT-M is this conversion to double valid? - lua_pushnumber(L, (double)lsd->ldp.pkt->get_ip_proto_next() ); + lua_pushnumber(L, (double)lsd->ldp.pkt->get_ip_proto_next()); return 1; } @@ -884,7 +884,7 @@ static int client_register_pattern(lua_State* L) /*mpse library does not hold reference to pattern therefore we don't need to allocate it. */ - if ( protocol == IpProtocol::TCP) + if (protocol == IpProtocol::TCP) ud->get_odp_ctxt().get_client_disco_mgr().register_tcp_pattern(ud->cd, (const uint8_t*)pattern, size, position, 0); else @@ -922,7 +922,7 @@ static int service_add_client(lua_State* L) AppId service_id = lua_tonumber(L, 3); const char* version = lua_tostring(L, 4); - if ( !version ) + if (!version) { lua_pushnumber(L, -1); return 1; @@ -986,6 +986,40 @@ static int client_add_payload(lua_State* L) return 1; } +/** Add a fp process to client app mapping. + * @param Lua_State* - Lua state variable. + * @param appid/stack - the AppId to map the fp data to + * @param process_name/stack - encrypted fingerprint process name + * @param process_score - encrypted fingerprint process_score + */ +static int client_add_fingerprint_process(lua_State* L) +{ + 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; + int index = 1; + + uint32_t appid = lua_tointeger(L, ++index); + + // Verify that process_name is a valid string + const char* tmp_string = lua_tostring(L, ++index); + if (!tmp_string) + { + ErrorMessage("appid: Invalid efp process_name string: appid %u.\n", appid); + return 0; + } + const std::string process_name(tmp_string); + uint8_t process_score = lua_tointeger(L, ++index); + + ud->get_odp_ctxt().get_efp_ca_matchers().add_efp_ca_pattern(appid, process_name, + process_score); + + ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(appid); + + return 0; +} + /**Get flow object from a detector object. The flow object is then used with flowApi. * A new copy of flow object is provided with every call. This can be optimized by maintaining * a single copy. @@ -1024,7 +1058,7 @@ static int detector_add_http_pattern(lua_State* L) int index = 1; enum httpPatternType pat_type = (enum httpPatternType)lua_tointeger(L, ++index); - if (pat_type < HTTP_PAYLOAD || pat_type > HTTP_URL) + if (pat_type < HTTP_PAYLOAD or pat_type > HTTP_URL) { ErrorMessage("Invalid HTTP pattern type."); return 0; @@ -1042,8 +1076,8 @@ static int detector_add_http_pattern(lua_State* L) const uint8_t* pattern_str = (const uint8_t*)lua_tolstring(L, ++index, &pattern_size); uint32_t app_id = lua_tointeger(L, ++index); DetectorHTTPPattern pattern; - if ( pattern.init(pattern_str, pattern_size, seq, service_id, client_id, - payload_id, app_id) ) + if (pattern.init(pattern_str, pattern_size, seq, service_id, client_id, + payload_id, app_id)) { ud->get_odp_ctxt().get_http_matchers().insert_http_pattern(pat_type, pattern); aim.set_app_info_active(service_id); @@ -1069,7 +1103,7 @@ static int detector_add_ssl_cert_pattern(lua_State* L) AppId app_id = (AppId)lua_tointeger(L, ++index); size_t pattern_size = 0; const char* tmp_string = lua_tolstring(L, ++index, &pattern_size); - if (!tmp_string || !pattern_size) + if (!tmp_string or !pattern_size) { ErrorMessage("Invalid SSL Host pattern string"); return 0; @@ -1097,7 +1131,7 @@ static int detector_add_dns_host_pattern(lua_State* L) size_t pattern_size = 0; const char* tmp_string = lua_tolstring(L, ++index, &pattern_size); - if (!tmp_string || !pattern_size) + if (!tmp_string or !pattern_size) { ErrorMessage("LuaDetectorApi:Invalid DNS Host pattern string"); return 0; @@ -1123,7 +1157,7 @@ static int detector_add_ssl_cname_pattern(lua_State* L) size_t pattern_size = 0; const char* tmp_string = lua_tolstring(L, ++index, &pattern_size); - if (!tmp_string || !pattern_size) + if (!tmp_string or !pattern_size) { ErrorMessage("Invalid SSL Host pattern string"); return 0; @@ -1150,7 +1184,7 @@ static int detector_add_host_port_application(lua_State* L) AppId app_id = (AppId)lua_tointeger(L, ++index); size_t ipaddr_size = 0; const char* ip_str= lua_tolstring(L, ++index, &ipaddr_size); - if (!ip_str || !ipaddr_size || !convert_string_to_address(ip_str, &ip_address)) + if (!ip_str or !ipaddr_size or !convert_string_to_address(ip_str, &ip_address)) { ErrorMessage("%s: Invalid IP address: %s\n",__func__, ip_str); return 0; @@ -1187,7 +1221,7 @@ static int detector_add_host_port_dynamic(lua_State* L) AppId appid = (AppId)lua_tointeger(L, ++index); size_t ipaddr_size = 0; const char* ip_str = lua_tolstring(L, ++index, &ipaddr_size); - if (!ip_str || !ipaddr_size || !convert_string_to_address(ip_str, &ip_address)) + if (!ip_str or !ipaddr_size or !convert_string_to_address(ip_str, &ip_address)) return 0; unsigned port = lua_tointeger(L, ++index); @@ -1222,7 +1256,7 @@ static int detector_add_content_type_pattern(lua_State* L) int index = 1; const char* tmp_string = lua_tolstring(L, ++index, &stringSize); - if (!tmp_string || !stringSize) + if (!tmp_string or !stringSize) { ErrorMessage("Invalid HTTP Header string"); return 0; @@ -1468,7 +1502,7 @@ static inline int get_chp_key_pattern_boolean(lua_State* L, int index) static inline int get_chp_pattern_type(lua_State* L, int index, HttpFieldIds* pattern_type) { *pattern_type = (HttpFieldIds)lua_tointeger(L, index); - if ( *pattern_type >= NUM_HTTP_FIELDS ) + if (*pattern_type >= NUM_HTTP_FIELDS) { ErrorMessage("LuaDetectorApi:Invalid CHP Action pattern type."); return -1; @@ -1484,7 +1518,7 @@ static inline int get_chp_pattern_data_and_size(lua_State* L, int index, char** *pattern_data = nullptr; tmp_string = lua_tolstring(L, index, pattern_size); // non-empty pattern required - if (!tmp_string || !*pattern_size) + if (!tmp_string or !*pattern_size) { ErrorMessage("LuaDetectorApi:Invalid CHP Action PATTERN string."); return -1; @@ -1496,7 +1530,7 @@ static inline int get_chp_pattern_data_and_size(lua_State* L, int index, char** static inline int get_chp_action_type(lua_State* L, int index, ActionType& action_type) { action_type = (ActionType)lua_tointeger(L, index); - if (action_type < NO_ACTION || action_type > MAX_ACTION_TYPE) + if (action_type < NO_ACTION or action_type > MAX_ACTION_TYPE) { WarningMessage( "LuaDetectorApi:Unsupported CHP Action type: %d, possible version mismatch.", @@ -1563,7 +1597,7 @@ static int add_chp_pattern_action(AppId appIdInstance, int isKeyPattern, HttpFie unsigned precedence = chpapp->ptype_scan_counts[patternType]++; // at runtime we'll want to know how many of each type of pattern we are looking for. - if (actionType != ALTERNATE_APPID && actionType != DEFER_TO_SIMPLE_DETECT) + if (actionType != ALTERNATE_APPID and actionType != DEFER_TO_SIMPLE_DETECT) chpapp->ptype_req_counts[patternType]++; CHPListElement* chpa = (CHPListElement*)snort_calloc(sizeof(CHPListElement)); @@ -1578,7 +1612,7 @@ static int add_chp_pattern_action(AppId appIdInstance, int isKeyPattern, HttpFie chpa->chp_action.chpapp = chpapp; // link this struct to the Glossary entry odp_ctxt.get_http_matchers().insert_chp_pattern(chpa); - if (actionType == DEFER_TO_SIMPLE_DETECT && strcmp(patternData,"") == 0) + if (actionType == DEFER_TO_SIMPLE_DETECT and strcmp(patternData,"") == 0) odp_ctxt.get_http_matchers().remove_http_patterns_for_id(appIdInstance); return 0; @@ -1646,7 +1680,7 @@ static int detector_create_chp_multi_application(lua_State* L) unsigned app_type_flags = lua_tointeger(L, ++index); int num_matches = lua_tointeger(L, ++index); - for (instance=0; instance < CHP_APPID_INSTANCE_MAX; instance++ ) + for (instance=0; instance < CHP_APPID_INSTANCE_MAX; instance++) { appIdInstance = (appId << CHP_APPID_BITS_FOR_INSTANCE) + instance; if (CHP_glossary->find(appIdInstance) != CHP_glossary->end()) @@ -1668,7 +1702,7 @@ static int detector_create_chp_multi_application(lua_State* L) return 0; } - if ( create_chp_application(appIdInstance, app_type_flags, num_matches) ) + if (create_chp_application(appIdInstance, app_type_flags, num_matches)) return 0; lua_pushnumber(L, appIdInstance); @@ -1784,9 +1818,9 @@ static int detector_add_length_app_cache(lua_State* L) uint8_t sequence_cnt = lua_tonumber(L, ++index); const char* sequence_str = lua_tostring(L, ++index); - if (((proto != IpProtocol::TCP) && (proto != IpProtocol::UDP)) - || ((sequence_cnt == 0) || (sequence_cnt > LENGTH_SEQUENCE_CNT_MAX)) - || ((sequence_str == nullptr) || (strlen(sequence_str) == 0))) + if (((proto != IpProtocol::TCP) and (proto != IpProtocol::UDP)) + or ((sequence_cnt == 0) or (sequence_cnt > LENGTH_SEQUENCE_CNT_MAX)) + or ((sequence_str == nullptr) or (strlen(sequence_str) == 0))) { ErrorMessage("LuaDetectorApi:Invalid input (%d,%u,%u,\"%s\")!", appId, (unsigned)proto, (unsigned)sequence_cnt, sequence_str ? sequence_str : ""); @@ -1839,14 +1873,14 @@ static int detector_add_length_app_cache(lua_State* L) } length_sequence.sequence[i].length = length; - while ((*str_ptr != ',') && (*str_ptr != 0)) + while ((*str_ptr != ',') and (*str_ptr != 0)) { str_ptr++; } last_one = (i == (sequence_cnt - 1)); - if ( (!last_one && (*str_ptr != ',')) - || (last_one && (*str_ptr != 0))) + if ((!last_one and (*str_ptr != ',')) + or (last_one and (*str_ptr != 0))) { ErrorMessage("LuaDetectorApi:Invalid sequence string (\"%s\")!", sequence_str); @@ -1856,7 +1890,7 @@ static int detector_add_length_app_cache(lua_State* L) str_ptr++; } - if ( !ud->get_odp_ctxt().length_cache_add(length_sequence, appId) ) + if (!ud->get_odp_ctxt().length_cache_add(length_sequence, appId)) { ErrorMessage("LuaDetectorApi:Could not add entry to cache!"); lua_pushnumber(L, -1); @@ -1886,7 +1920,7 @@ static int detector_add_url_application(lua_State* L) size_t host_pattern_size = 0; uint8_t* host_pattern = nullptr; const char* tmp_string = lua_tolstring(L, ++index, &host_pattern_size); - if (!tmp_string || !host_pattern_size) + if (!tmp_string or !host_pattern_size) { ErrorMessage( "appid: Invalid host pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -1900,7 +1934,7 @@ static int detector_add_url_application(lua_State* L) size_t path_pattern_size = 0; uint8_t* path_pattern = nullptr; tmp_string = lua_tolstring(L, ++index, &path_pattern_size); - if (!tmp_string || !path_pattern_size ) + if (!tmp_string or !path_pattern_size) { ErrorMessage( "appid: Invalid path pattern string: service_id %u; client_id %u; payload %u.\n", @@ -1915,7 +1949,7 @@ static int detector_add_url_application(lua_State* L) size_t schemePatternSize; uint8_t* schemePattern = nullptr; tmp_string = lua_tolstring(L, ++index, &schemePatternSize); - if (!tmp_string || !schemePatternSize ) + if (!tmp_string or !schemePatternSize) { ErrorMessage( "appid: Invalid scheme pattern string: service_id %u; client_id %u; payload %u.\n", @@ -1931,7 +1965,7 @@ static int detector_add_url_application(lua_State* L) size_t query_pattern_size; uint8_t* query_pattern = nullptr; tmp_string = lua_tolstring(L, ++index, &query_pattern_size); - if (tmp_string && query_pattern_size) + if (tmp_string and query_pattern_size) query_pattern = (uint8_t*)snort_strdup(tmp_string); uint32_t appId = lua_tointeger(L, ++index); @@ -1978,7 +2012,7 @@ static int detector_add_rtmp_url(lua_State* L) /* Verify that host pattern is a valid string */ size_t host_pattern_size = 0; const char* tmp_string = lua_tolstring(L, ++index, &host_pattern_size); - if (!tmp_string || !host_pattern_size) + if (!tmp_string or !host_pattern_size) { ErrorMessage( "appid: Invalid RTMP host pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -1990,7 +2024,7 @@ static int detector_add_rtmp_url(lua_State* L) /* Verify that path pattern is a valid string */ size_t path_pattern_size = 0; tmp_string = lua_tolstring(L, ++index, &path_pattern_size); - if (!tmp_string || !path_pattern_size) + if (!tmp_string or !path_pattern_size) { ErrorMessage( "appid: Invalid RTMP path pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -2003,7 +2037,7 @@ static int detector_add_rtmp_url(lua_State* L) /* Verify that scheme pattern is a valid string */ size_t schemePatternSize; tmp_string = lua_tolstring(L, ++index, &schemePatternSize); - if (!tmp_string || !schemePatternSize) + if (!tmp_string or !schemePatternSize) { ErrorMessage( "appid: Invalid RTMP scheme pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -2018,7 +2052,7 @@ static int detector_add_rtmp_url(lua_State* L) size_t query_pattern_size; uint8_t* query_pattern = nullptr; tmp_string = lua_tolstring(L, ++index, &query_pattern_size); - if (tmp_string && query_pattern_size) + if (tmp_string and query_pattern_size) query_pattern = (uint8_t*)snort_strdup(tmp_string); uint32_t appId = lua_tointeger(L, ++index); @@ -2064,7 +2098,7 @@ static int detector_add_sip_user_agent(lua_State* L) uint32_t client_app = lua_tointeger(L, ++index); const char* client_version = lua_tostring(L, ++index); - if (!client_version ) + if (!client_version) { ErrorMessage("Invalid sip client version string."); return 0; @@ -2098,7 +2132,7 @@ static int create_custom_application(lua_State* L) /* Verify that host pattern is a valid string */ size_t appNameLen = 0; const char* tmp_string = lua_tolstring(L, ++index, &appNameLen); - if (!tmp_string || !appNameLen) + if (!tmp_string or !appNameLen) { ErrorMessage("Invalid appName string."); lua_pushnumber(L, APP_ID_NONE); @@ -2183,7 +2217,7 @@ static int add_http_pattern(lua_State* L) /* Verify valid pattern type */ enum httpPatternType pat_type = (enum httpPatternType)lua_tointeger(L, ++index); - if (pat_type < HTTP_PAYLOAD || pat_type > HTTP_URL) + if (pat_type < HTTP_PAYLOAD or pat_type > HTTP_URL) { ErrorMessage("Invalid HTTP pattern type."); return 0; @@ -2198,8 +2232,8 @@ static int add_http_pattern(lua_State* L) size_t pattern_size = 0; const uint8_t* pattern_str = (const uint8_t*)lua_tolstring(L, ++index, &pattern_size); DetectorHTTPPattern pattern; - if ( pattern.init(pattern_str, pattern_size, seq, service_id, client_id, - payload_id, APP_ID_NONE) ) + if (pattern.init(pattern_str, pattern_size, seq, service_id, client_id, + payload_id, APP_ID_NONE)) { ud->get_odp_ctxt().get_http_matchers().insert_http_pattern(pat_type, pattern); AppInfoManager& app_info_manager = ud->get_odp_ctxt().get_app_info_mgr(); @@ -2228,20 +2262,20 @@ static int add_url_pattern(lua_State* L) size_t host_pattern_size = 0; uint8_t* host_pattern = nullptr; const char* tmp_string = lua_tolstring(L, ++index, &host_pattern_size); - if ( !tmp_string || !host_pattern_size ) + if (!tmp_string or !host_pattern_size) { ErrorMessage( "appid: Invalid host pattern string: service_id %u; client_id %u; payload_id %u.\n", service_id, client_id, payload_id); return 0; } - host_pattern = (uint8_t* )snort_strdup(tmp_string); + host_pattern = (uint8_t*)snort_strdup(tmp_string); /* Verify that path pattern is a valid string */ size_t path_pattern_size = 0; uint8_t* path_pattern = nullptr; tmp_string = lua_tolstring(L, ++index, &path_pattern_size); - if ( !tmp_string || !path_pattern_size ) + if (!tmp_string or !path_pattern_size) { ErrorMessage( "appid: Invalid path pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -2255,7 +2289,7 @@ static int add_url_pattern(lua_State* L) size_t schemePatternSize; uint8_t* schemePattern = nullptr; tmp_string = lua_tolstring(L, ++index, &schemePatternSize); - if (!tmp_string || !schemePatternSize) + if (!tmp_string or !schemePatternSize) { ErrorMessage( "appid: Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u.\n", @@ -2322,8 +2356,8 @@ static int add_port_pattern_client(lua_State* L) const char* pattern = lua_tolstring(L, ++index, &patternSize); unsigned position = lua_tonumber(L, ++index); AppId appId = lua_tointeger(L, ++index); - if (appId <= APP_ID_NONE || !pattern || !patternSize || - (protocol != IpProtocol::TCP && protocol != IpProtocol::UDP)) + if (appId <= APP_ID_NONE or !pattern or !patternSize or + (protocol != IpProtocol::TCP and protocol != IpProtocol::UDP)) { ErrorMessage("addPortPatternClient(): Invalid input in %s\n", ud->get_detector()->get_name().c_str()); return 0; @@ -2404,7 +2438,7 @@ static int detector_add_sip_server(lua_State* L) uint32_t client_app = lua_tointeger(L, ++index); const char* client_version = lua_tostring(L, ++index); - if (!client_version ) + if (!client_version) { ErrorMessage("Invalid sip client version string."); return 0; @@ -2537,7 +2571,7 @@ static int is_http_tunnel(lua_State* L) if (hsession) { - if (hsession->payload.get_id() == APP_ID_HTTP_TUNNEL || + if (hsession->payload.get_id() == APP_ID_HTTP_TUNNEL or hsession->payload.get_id() == APP_ID_HTTP_SSL_TUNNEL) lua_pushboolean(L, 1); else @@ -2684,6 +2718,9 @@ static const luaL_Reg detector_methods[] = { "client_addUser", client_add_user }, { "client_addPayload", client_add_payload }, + /* add client mapping for process name derived by fingerprinting */ + { "client_addFingerprintProcess", client_add_fingerprint_process }, + //HTTP Multi Pattern engine { "CHPCreateApp", detector_chp_create_application }, { "CHPAddAction", detector_add_chp_action }, @@ -2800,7 +2837,7 @@ int LuaStateDescriptor::lua_validate(AppIdDiscoveryArgs& args) ldp.pkt = args.pkt; const char* validateFn = package_info.validateFunctionName.c_str(); - if ( (!validateFn) || (validateFn[0] == '\0')) + if ((!validateFn) or (validateFn[0] == '\0')) { ldp.pkt = nullptr; lua_settop(my_lua_state, 0); @@ -2809,7 +2846,7 @@ int LuaStateDescriptor::lua_validate(AppIdDiscoveryArgs& args) lua_getfield(my_lua_state, -1, validateFn); // get the function we want to call - if ( lua_pcall(my_lua_state, 0, 1, 0) ) + if (lua_pcall(my_lua_state, 0, 1, 0)) { // Runtime Lua errors are suppressed in production code since detectors are written for // efficiency and with defensive minimum checks. Errors are dealt as exceptions @@ -2827,7 +2864,7 @@ int LuaStateDescriptor::lua_validate(AppIdDiscoveryArgs& args) lua_detector_mgr.free_detector_flow(); /* retrieve result */ - if ( !lua_isnumber(my_lua_state, -1) ) + if (!lua_isnumber(my_lua_state, -1)) { ErrorMessage("lua detector %s: returned non-numeric value\n", package_info.name.c_str()); ldp.pkt = 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 60f7ebb63..79ba62993 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 @@ -80,6 +80,7 @@ AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&) : StashGenericObject(STASH_GENERIC_OBJECT_APPID) {} } +EfpCaPatternMatchers::~EfpCaPatternMatchers() { } SslPatternMatchers::~SslPatternMatchers() { } SipPatternMatchers::~SipPatternMatchers() { } HttpPatternMatchers::~HttpPatternMatchers() { } diff --git a/src/network_inspectors/appid/test/CMakeLists.txt b/src/network_inspectors/appid/test/CMakeLists.txt index 35a260a6e..c5dca9c25 100644 --- a/src/network_inspectors/appid/test/CMakeLists.txt +++ b/src/network_inspectors/appid/test/CMakeLists.txt @@ -41,6 +41,10 @@ add_cpputest( appid_http_session_test SOURCES $ ) +add_cpputest( appid_efp_process_event_handler_test + SOURCES $ +) + add_cpputest( tp_lib_handler_test SOURCES tp_lib_handler_test.cc diff --git a/src/network_inspectors/appid/test/appid_discovery_test.cc b/src/network_inspectors/appid/test/appid_discovery_test.cc index 3d246704f..82cc38109 100644 --- a/src/network_inspectors/appid/test/appid_discovery_test.cc +++ b/src/network_inspectors/appid/test/appid_discovery_test.cc @@ -129,6 +129,7 @@ void DataBus::publish(const char*, DataEvent& event, Flow*) // Stubs for matchers static HttpPatternMatchers* http_matchers; DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; diff --git a/src/network_inspectors/appid/test/appid_efp_process_event_handler_test.cc b/src/network_inspectors/appid/test/appid_efp_process_event_handler_test.cc new file mode 100644 index 000000000..f0efac840 --- /dev/null +++ b/src/network_inspectors/appid/test/appid_efp_process_event_handler_test.cc @@ -0,0 +1,105 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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_efp_process_event_handler_test.cc author Sreeja Athirkandathil Narayanan + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "appid_efp_process_event_handler.cc" + +#include + +#include "framework/data_bus.h" +#include "protocols/protocol_ids.h" + +#include "appid_mock_definitions.h" +#include "appid_mock_session.h" +#include "appid_mock_inspector.h" + +#include +#include +#include + +AppIdSession *session = nullptr; +THREAD_LOCAL AppIdDebug* appidDebug; + +using namespace snort; +using namespace std; + +namespace snort +{ +AppIdApi appid_api; +AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&) : + StashGenericObject(STASH_GENERIC_OBJECT_APPID) { } +AppIdSession* AppIdApi::get_appid_session(Flow const&) { return session; } + +Packet::Packet(bool) { } +Packet::~Packet() = default; +} + +void memory::MemoryCap::update_allocations(unsigned long) { } +void memory::MemoryCap::update_deallocations(size_t) { } + +void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, + AppId, AppidChangeBits&) { } +void AppIdModule::reset_stats() { } +void AppIdDebug::activate(snort::Flow const*, AppIdSession const*, bool) { } + +AppId EfpCaPatternMatchers::match_efp_ca_pattern(const string&, uint8_t) +{ + return APPID_UT_ID; +} + +TEST_GROUP(appid_efp_process_event_handler_tests) +{ + void setup() override + { + SfIp ip; + session = new AppIdSession(IpProtocol::TCP, &ip, 0, dummy_appid_inspector, stub_odp_ctxt); + pkt_thread_odp_ctxt = &stub_odp_ctxt; + appidDebug = new AppIdDebug(); + appidDebug->activate(nullptr, nullptr, false); + } + + void teardown() override + { + delete &session->get_api(); + delete session; + delete appidDebug; + } +}; + +TEST(appid_efp_process_event_handler_tests, efp_process_event_handler) +{ + Packet p; + EfpProcessEvent event(p, "firefox", 90); + AppIdEfpProcessEventHandler event_handler; + Flow* flow = new Flow(); + event_handler.handle(event, flow); + CHECK(session->get_efp_client_app_id() == APPID_UT_ID); + delete flow; +} + +int main(int argc, char** argv) +{ + int return_value = CommandLineTestRunner::RunAllTests(argc, argv); + return return_value; +} + diff --git a/src/network_inspectors/appid/test/appid_mock_definitions.h b/src/network_inspectors/appid/test/appid_mock_definitions.h index 427a2231f..f0e918bfb 100644 --- a/src/network_inspectors/appid/test/appid_mock_definitions.h +++ b/src/network_inspectors/appid/test/appid_mock_definitions.h @@ -83,6 +83,7 @@ void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, void AppIdDiscovery::register_udp_pattern(AppIdDetector*, unsigned char const*, unsigned int, int, unsigned int) { } int AppIdDiscovery::add_service_port(AppIdDetector*, ServiceDetectorPort const&) { return 0; } DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; diff --git a/src/network_inspectors/appid/test/appid_mock_session.h b/src/network_inspectors/appid/test/appid_mock_session.h index 31bb7d978..7f50b82c8 100644 --- a/src/network_inspectors/appid/test/appid_mock_session.h +++ b/src/network_inspectors/appid/test/appid_mock_session.h @@ -84,6 +84,7 @@ AppIdSession::AppIdSession(IpProtocol proto, const SfIp* ip, uint16_t, AppIdInsp OdpContext&, uint16_t) : FlowData(inspector_id, &inspector), config(stub_config), protocol(proto), api(*(new AppIdSessionApi(this, *ip))), odp_ctxt(stub_odp_ctxt) { + this->set_session_flags(APPID_SESSION_DISCOVER_APP | APPID_SESSION_SPECIAL_MONITORED); odp_ctxt_version = odp_ctxt.get_version(); set_service_port(APPID_UT_SERVICE_PORT); AppidChangeBits change_bits; diff --git a/src/network_inspectors/appid/test/service_state_test.cc b/src/network_inspectors/appid/test/service_state_test.cc index 7b9051ea7..e1d9ce23a 100644 --- a/src/network_inspectors/appid/test/service_state_test.cc +++ b/src/network_inspectors/appid/test/service_state_test.cc @@ -127,6 +127,7 @@ int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDir int ServiceDiscovery::add_service_port(AppIdDetector*, const ServiceDetectorPort&) { return APPID_EINVALID; } DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = 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 16026ef92..af4ac1195 100644 --- a/src/network_inspectors/appid/test/tp_lib_handler_test.cc +++ b/src/network_inspectors/appid/test/tp_lib_handler_test.cc @@ -56,6 +56,7 @@ void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, void AppIdDiscovery::register_udp_pattern(AppIdDetector*, unsigned char const*, unsigned int, int, unsigned int) { } int AppIdDiscovery::add_service_port(AppIdDetector*, ServiceDetectorPort const&) { return 0; } DnsPatternMatchers::~DnsPatternMatchers() = default; +EfpCaPatternMatchers::~EfpCaPatternMatchers() = default; HttpPatternMatchers::~HttpPatternMatchers() = default; SipPatternMatchers::~SipPatternMatchers() = default; SslPatternMatchers::~SslPatternMatchers() = default; diff --git a/src/pub_sub/CMakeLists.txt b/src/pub_sub/CMakeLists.txt index 40b0e9e8b..d825fc45c 100644 --- a/src/pub_sub/CMakeLists.txt +++ b/src/pub_sub/CMakeLists.txt @@ -6,6 +6,7 @@ set (PUB_SUB_INCLUDES daq_message_event.h dcerpc_events.h dhcp_events.h + efp_process_event.h expect_events.h finalize_packet_event.h http_events.h diff --git a/src/pub_sub/efp_process_event.h b/src/pub_sub/efp_process_event.h new file mode 100644 index 000000000..1c0e44daf --- /dev/null +++ b/src/pub_sub/efp_process_event.h @@ -0,0 +1,52 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- +// efp_process_event.h author Cliff Judge + +#ifndef EFP_PROCESS_EVENT_H +#define EFP_PROCESS_EVENT_H + +#include +#include "framework/data_bus.h" + +#define EFP_PROCESS_EVENT "efp_process_event" + +class EfpProcessEvent : public snort::DataEvent +{ +public: + EfpProcessEvent(const snort::Packet& p, const char* process, uint8_t process_conf) : + p(p), process_name(process), process_confidence(process_conf) { } + + const snort::Packet* get_packet() override { return &p; } + + const std::string& get_process_name() const + { + return process_name; + } + + uint8_t get_process_confidence() const + { + return process_confidence; + } + +private: + const snort::Packet &p; + std::string process_name; + uint8_t process_confidence = 0; +}; + +#endif diff --git a/src/pub_sub/test/CMakeLists.txt b/src/pub_sub/test/CMakeLists.txt index d2c5642b9..75b7740b5 100644 --- a/src/pub_sub/test/CMakeLists.txt +++ b/src/pub_sub/test/CMakeLists.txt @@ -7,3 +7,7 @@ add_cpputest( pub_sub_http_request_body_event_test ../http_request_body_event.cc ../../service_inspectors/http_inspect/http_msg_body_cl.cc ) +add_cpputest( pub_sub_efp_process_event_test + SOURCES + ../efp_process_event.h +) diff --git a/src/pub_sub/test/pub_sub_efp_process_event_test.cc b/src/pub_sub/test/pub_sub_efp_process_event_test.cc new file mode 100644 index 000000000..697362ea2 --- /dev/null +++ b/src/pub_sub/test/pub_sub_efp_process_event_test.cc @@ -0,0 +1,57 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2021-2021 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. +//-------------------------------------------------------------------------- +// pub_sub_efp_process_event_test.cc author Cliff Judge + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pub_sub/efp_process_event.h" +#include "protocols/packet.h" + +#include +#include +#include + +using namespace snort; + +Packet::Packet(bool) { } +Packet::~Packet() = default; + +TEST_GROUP(pub_sub_efp_process_event_test) +{ + void teardown() override + { + mock().clear(); + } +}; + +TEST(pub_sub_efp_process_event_test, efp_process_event) +{ + Packet p; + EfpProcessEvent event(p, "process", 10); + CHECK(event.get_process_name() == "process"); + CHECK(event.get_process_confidence() == 10); + CHECK(event.get_packet() == &p); +} + +int main(int argc, char** argv) +{ + return CommandLineTestRunner::RunAllTests(argc, argv); +} +