]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #3042 in SNORT/snort3 from ~CLJUDGE/snort3:snort3_mercury_process_...
authorShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Thu, 23 Sep 2021 09:08:40 +0000 (09:08 +0000)
committerShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Thu, 23 Sep 2021 09:08:40 +0000 (09:08 +0000)
Squashed commit of the following:

commit e0711099931cf59733dbfe1a95c2e2b927df5acb
Author: cljudge <cljudge@cisco.com>
Date:   Thu Jun 17 10:15:02 2021 -0400

    appid: provide api for Lua detectors to map process name to client app

29 files changed:
src/network_inspectors/appid/CMakeLists.txt
src/network_inspectors/appid/appid_app_descriptor.h
src/network_inspectors/appid/appid_config.cc
src/network_inspectors/appid/appid_config.h
src/network_inspectors/appid/appid_efp_process_event_handler.cc [new file with mode: 0644]
src/network_inspectors/appid/appid_efp_process_event_handler.h [new file with mode: 0644]
src/network_inspectors/appid/appid_inspector.cc
src/network_inspectors/appid/appid_session.cc
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/client_plugins/efp_ca_patterns.cc [new file with mode: 0644]
src/network_inspectors/appid/client_plugins/efp_ca_patterns.h [new file with mode: 0644]
src/network_inspectors/appid/client_plugins/test/CMakeLists.txt [new file with mode: 0644]
src/network_inspectors/appid/client_plugins/test/client_plugins_mock.h [new file with mode: 0644]
src/network_inspectors/appid/client_plugins/test/efp_ca_patterns_test.cc [new file with mode: 0644]
src/network_inspectors/appid/detector_plugins/test/detector_sip_test.cc
src/network_inspectors/appid/detector_plugins/test/http_url_patterns_test.cc
src/network_inspectors/appid/lua_detector_api.cc
src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h
src/network_inspectors/appid/test/CMakeLists.txt
src/network_inspectors/appid/test/appid_discovery_test.cc
src/network_inspectors/appid/test/appid_efp_process_event_handler_test.cc [new file with mode: 0644]
src/network_inspectors/appid/test/appid_mock_definitions.h
src/network_inspectors/appid/test/appid_mock_session.h
src/network_inspectors/appid/test/service_state_test.cc
src/network_inspectors/appid/test/tp_lib_handler_test.cc
src/pub_sub/CMakeLists.txt
src/pub_sub/efp_process_event.h [new file with mode: 0644]
src/pub_sub/test/CMakeLists.txt
src/pub_sub/test/pub_sub_efp_process_event_test.cc [new file with mode: 0644]

index d940998b480aad25a546456edb836395e5bacdaa..fac670bb47367e6d794ccbc7a6e3755dff890e59 100644 (file)
@@ -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}
index d4c4f5470b8872f06774a9716b19a385219a6ad9..d7f85d3e317e95e6a9321553fc4fd89e8e55b39a 100644 (file)
@@ -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
index 4dde961aa5dcfd7254c7f372719632b7e041f2d2..4ba519d42166916d65a7713f55621a544552eeed 100644 (file)
@@ -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();
index c5f823e267a1d5d0628bb059e22365c991b6e01c..10bcae24acc35040af1e8bfdfd3851f85dc71c60 100644 (file)
@@ -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 (file)
index 0000000..669cb78
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#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<EfpProcessEvent&>(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 (file)
index 0000000..e5fbe28
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#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
index fe8c7fdf0f37aad0030afb6b582ee3ff7f631dd7..074057d3fa5182f559f04fb9170d2fccb9cf1792 100644 (file)
@@ -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;
 }
 
index 41ee0b4ce5cea6ab3dcfe577a1221bd0bad122b5..756a7c6500d32c096c80ae9be043cf65fd4eb593 100644 (file)
@@ -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();
 
index 513ffc0d114bf0e2345ba36a79f5563ac75aaf4c..eca17b2b3cd23f2df0912076413cffe3da87ac84 100644 (file)
@@ -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 (file)
index 0000000..fab0bfe
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#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 (file)
index 0000000..53cded9
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#ifndef EFP_CA_PATTERNS_H
+#define EFP_CA_PATTERNS_H
+
+#include <vector>
+
+#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<EfpCaPattern*> 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 (file)
index 0000000..9dcc7c4
--- /dev/null
@@ -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 (file)
index 0000000..d696eae
--- /dev/null
@@ -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 <sathirka@cisco.com>
+
+#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 (file)
index 0000000..add4f1a
--- /dev/null
@@ -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 <sathirka@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "client_plugins/efp_ca_patterns.cc"
+#include "client_plugins_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+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;
+}
+
index 655acdcfa6e1155862d434b43de95ee3ad2b5fa0..f8ce42d74ff406313fc08c621a5252d2c00f3de8 100644 (file)
@@ -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;
 
index 488b3d7fe1eb99670e3121c0297ce62eee24dc0c..cc18cbdc6c6ed0060207d78959dc2774ca087538 100644 (file)
@@ -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() {}
index 5bd5966e6376ab7f56f38d3d7df6c3c1604fdffc..18b09e9a0086904835c68a3aa3551db2b6f626cf 100644 (file)
@@ -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<LuaObject>::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,"<ignore-all-patterns>") == 0)
+    if (actionType == DEFER_TO_SIMPLE_DETECT and strcmp(patternData,"<ignore-all-patterns>") == 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;
index 60f7ebb6398534f897f9d48827ef274e6a9d52ac..79ba62993b166b13826ad6cc4cfc2a4b8f247141 100644 (file)
@@ -80,6 +80,7 @@ AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&) :
     StashGenericObject(STASH_GENERIC_OBJECT_APPID) {}
 }
 
+EfpCaPatternMatchers::~EfpCaPatternMatchers() { }
 SslPatternMatchers::~SslPatternMatchers() { }
 SipPatternMatchers::~SipPatternMatchers() { }
 HttpPatternMatchers::~HttpPatternMatchers() { }
index 35a260a6e3adf88b8889bc304df5bcee9a0ca010..c5dca9c250385065d8fe08a98baad898eee50bf7 100644 (file)
@@ -41,6 +41,10 @@ add_cpputest( appid_http_session_test
     SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
 )
 
+add_cpputest( appid_efp_process_event_handler_test
+    SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
+)
+
 add_cpputest( tp_lib_handler_test
     SOURCES
         tp_lib_handler_test.cc
index 3d246704faff8359b54d142464fb0893e89b2a08..82cc381097bbc0e2a2ed8dc4441f8ab04d881b3b 100644 (file)
@@ -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 (file)
index 0000000..f0efac8
--- /dev/null
@@ -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 <sathirka@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "appid_efp_process_event_handler.cc"
+
+#include <string>
+
+#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 <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+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;
+}
+
index 427a2231f541866b601e66a6c65e11201972beec..f0e918bfb5276f3c00cf9f3184b0e1ad4b5d27f8 100644 (file)
@@ -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;
index 31bb7d978eeb9fc55e98e369774da2b97ddbdd78..7f50b82c863ef86d8a7c8a6527d71c1a23e39a2c 100644 (file)
@@ -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;
index 7b9051ea73f8f153793e18029a792d7ca09422c6..e1d9ce23af2be9d4bbbfdb5340969ca47e5d492a 100644 (file)
@@ -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;
index 16026ef9294a788b3d4a6590261cceb81892c68d..af4ac1195847df559fc0cf3abb9c82e833199664 100644 (file)
@@ -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;
index 40b0e9e8b7813ccd75feaacfbe1de4564618236f..d825fc45c78d7d1165d71a7e1788312f5523553a 100644 (file)
@@ -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 (file)
index 0000000..1c0e44d
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#ifndef EFP_PROCESS_EVENT_H
+#define EFP_PROCESS_EVENT_H
+
+#include <string>
+#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
index d2c5642b9e65da77db2d733ead1246a78c084ddc..75b7740b54ef19bf51e8158f07b2dc8c831b3e90 100644 (file)
@@ -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 (file)
index 0000000..697362e
--- /dev/null
@@ -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 <cljudge@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pub_sub/efp_process_event.h"
+#include "protocols/packet.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+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);
+}
+