]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2075 in SNORT/snort3 from ~KAMURTHI/snort3:smb_appid to master
authorShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Mon, 16 Mar 2020 14:17:30 +0000 (14:17 +0000)
committerShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Mon, 16 Mar 2020 14:17:30 +0000 (14:17 +0000)
Squashed commit of the following:

commit 158a37aa6275e82dc1504f26f83617463336700f
Author: Kanimozhi Murthi <kamurthi@cisco.com>
Date:   Wed Mar 11 14:40:01 2020 -0400

    appid: Fix SMB session data memory leak.

src/network_inspectors/appid/service_plugins/service_netbios.cc
src/network_inspectors/appid/service_plugins/test/CMakeLists.txt
src/network_inspectors/appid/service_plugins/test/service_netbios_test.cc [new file with mode: 0644]
src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h [new file with mode: 0644]

index 1f7a07ea4baca8765bec6fe0a534be9d3e8cc998..812b8a77fe9859b39a52f0811c510eeb0ba4e51f 100644 (file)
@@ -1168,7 +1168,8 @@ void NbdgmServiceDetector::add_smb_info(AppIdSession& asd, unsigned major, unsig
 
     if ( flags & FINGERPRINT_UDP_FLAGS_XENIX )
         return;
-
+    if ( asd.get_session_flags(APPID_SESSION_HAS_SMB_INFO) )
+        return;
     sd = (FpSMBData*)snort_calloc(sizeof(FpSMBData));
 
     if ( asd.add_flow_data(sd, APPID_SESSION_DATA_SMB_DATA, (AppIdFreeFCN)AppIdFreeSMBData) )
index d221dfda36fa2e1ac06799902aed674b878ec245..85ef7522f441602214d9f55d03760585cbb5043b 100644 (file)
@@ -2,4 +2,5 @@
 include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
 
 add_cpputest( service_rsync_test )
+add_cpputest( service_netbios_test )
 
diff --git a/src/network_inspectors/appid/service_plugins/test/service_netbios_test.cc b/src/network_inspectors/appid/service_plugins/test/service_netbios_test.cc
new file mode 100644 (file)
index 0000000..319a298
--- /dev/null
@@ -0,0 +1,93 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// service_netbios_test.cc author Kani Murthi<kamurthi@cisco.com>
+// unit test for service_netbios
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "network_inspectors/appid/service_plugins/service_detector.cc"
+#include "network_inspectors/appid/service_plugins/service_netbios.cc"
+#include "protocols/packet.h"
+#include "service_plugin_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+void ServiceDiscovery::initialize() {}
+void ServiceDiscovery::finalize_service_patterns() {}
+void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {}
+void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {}
+void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&)
+{}
+int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
+int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; }
+bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
+int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection,
+    ServiceDetector*) { return 0; }
+int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection,
+    ServiceDetector*, ServiceDiscoveryState*) { return 0; }
+int ServiceDiscovery::add_service_port(AppIdDetector*,
+    const ServiceDetectorPort&) { return APPID_EINVALID; }
+
+TEST_GROUP(service_netbios_test){};
+
+TEST(service_netbios_test, check_add_smb_info_pointer )
+{
+    const uint8_t data[] = { 0x11, 0x02, 0x45, 0x63, 0xac, 0x1f, 0x13, 0x49, 0x00, 0x8a, 0x00, 0xd7,
+        0x00, 0x00, 0x20, 0x45, 0x50, 0x45, 0x4c, 0x45, 0x4a, 0x43, 0x4e, 0x44, 0x42, 0x44, 0x46,
+        0x45, 0x46, 0x44, 0x47, 0x45, 0x43, 0x45, 0x44, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
+        0x41, 0x43, 0x41, 0x41, 0x41, 0x00, 0x20, 0x46, 0x48, 0x45, 0x50, 0x46, 0x43, 0x45, 0x4c,
+        0x45, 0x48, 0x46, 0x43, 0x45, 0x50, 0x46, 0x46, 0x46, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
+        0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x42, 0x4e, 0x00, 0xff, 0x53, 0x4d, 0x42, 0x25,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00,
+        0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x56, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x02, 0x00, 0x40, 0x00, 0x5c, 0x4d, 0x41, 0x49, 0x4c, 0x53, 0x4c, 0x4f, 0x54, 0x5c, 0x42,
+        0x52, 0x4f, 0x57, 0x53, 0x45, 0x00, 0x01, 0x00, 0x60, 0xea, 0x00, 0x00, 0x4f, 0x4b, 0x49,
+        0x2d, 0x31, 0x35, 0x45, 0x36, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+        0x03, 0x22, 0x41, 0x00, 0x0f, 0x01, 0x55, 0xaa, 0x43, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61,
+        0x27, 0x73, 0x20, 0x63, 0x75, 0x62, 0x65, 0x01};
+    uint16_t size =215;
+    AppidSessionDirection dir = APP_ID_FROM_INITIATOR;
+    AppIdInspector ins;
+    snort::Packet pkt;
+    AppidChangeBits cb;
+    AppIdSession asd(IpProtocol::TCP, nullptr, 21, ins);
+    AppIdDiscoveryArgs args(data, size, dir, asd, &pkt,cb);
+    ServiceDiscovery& s_discovery_manager = asd.ctxt.get_odp_ctxt().get_service_disco_mgr();
+    args.pkt->ptrs.sp = args.pkt->ptrs.dp = 138;
+    NbdgmServiceDetector nsd(&s_discovery_manager);
+    nsd.validate(args);
+    FpSMBData *smb_ptr1 = (FpSMBData*)(asd.get_flow_data(APPID_SESSION_DATA_SMB_DATA));
+    nsd.validate(args);
+    FpSMBData *smb_ptr2 = (FpSMBData*)(asd.get_flow_data(APPID_SESSION_DATA_SMB_DATA));
+    CHECK(smb_ptr1 == smb_ptr2);
+    asd.free_flow_data();
+}
+
+int main(int argc, char** argv)
+{
+    int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+    return return_value;
+}
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
new file mode 100644 (file)
index 0000000..214b33a
--- /dev/null
@@ -0,0 +1,199 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+// service_plugins_mock.h author Kani Murthi <kamurthi@cisco.com>
+
+#ifndef SERVICE_PLUGIN_MOCK_H
+#define SERVICE_PLUGIN_MOCK_H
+
+namespace snort
+{
+// Stubs for messages
+void ParseWarning(WarningGroup, const char*, ...) { }
+
+// Stubs for appid sessions
+FlowData::FlowData(unsigned, Inspector*) { }
+FlowData::~FlowData() = default;
+
+// Stubs for packet
+Packet::Packet(bool) { }
+Packet::~Packet() = default;
+
+Inspector::Inspector() = default;
+Inspector::~Inspector() = default;
+bool Inspector::likes(Packet*) { return true; }
+bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return true; }
+class StreamSplitter* Inspector::get_splitter(bool) { return nullptr; }
+
+// Stubs for search_tool.cc
+SearchTool::SearchTool(const char*, bool) { }
+SearchTool::~SearchTool() = default;
+
+// Stubs for util.cc
+char* snort_strndup(const char* , size_t dst_size)
+{
+    char* dup = (char*)snort_calloc(dst_size + 1);
+    return dup;
+}
+
+char* snort_strdup(const char* str)
+{
+    assert(str);
+    size_t n = strlen(str) + 1;
+    char* p = (char*)snort_alloc(n);
+    memcpy(p, str, n);
+    return p;
+}
+class InspectorManager
+{
+public:
+SO_PUBLIC static Inspector* get_inspector(const char*, bool, SnortConfig*) {return nullptr;}
+};
+Module::Module(const char*, const char*) {}
+Module::Module(const char*, const char*, const Parameter*, bool, Trace*, const Parameter*, TraceMask*)
+{}
+PegCount Module::get_global_count(char const*) const { return 0; }
+void Module::show_interval_stats(std::vector<unsigned int, std::allocator<unsigned int> >&, FILE*) {}
+void Module::show_stats(){}
+void Module::sum_stats(bool ){}
+bool Module::set(const char*, Value&, SnortConfig*){ return false;}
+void Module::reset_stats() {}
+}
+
+SslPatternMatchers::~SslPatternMatchers() { }
+SipPatternMatchers::~SipPatternMatchers() { }
+HttpPatternMatchers::~HttpPatternMatchers() { }
+DnsPatternMatchers::~DnsPatternMatchers() { }
+void ClientDiscovery::initialize() {}
+FpSMBData* smb_data = nullptr;
+
+int AppIdDetector::initialize(){return 0;}
+int AppIdDetector::data_add(AppIdSession&, void*, AppIdFreeFCN){return 0;}
+void* AppIdDetector::data_get(AppIdSession&) {return nullptr;}
+void AppIdDetector::add_info(AppIdSession&, const char*, AppidChangeBits&){}
+void AppIdDetector::add_user(AppIdSession&, const char*, AppId, bool){}
+void AppIdDetector::add_payload(AppIdSession&, AppId){}
+void AppIdDetector::add_app(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppId, const char*, AppidChangeBits&){}
+void AppIdDiscovery::add_pattern_data(AppIdDetector*, snort::SearchTool*, int,
+        const uint8_t* const, unsigned, unsigned){}
+void AppIdDiscovery::register_detector(const std::string&, AppIdDetector*,  IpProtocol){}
+void add_pattern_data(AppIdDetector*, snort::SearchTool*, int,
+    const uint8_t* const, unsigned, unsigned) {}
+void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, const uint8_t* const, unsigned,
+    int, unsigned){}
+void AppIdDiscovery::register_udp_pattern(AppIdDetector*, const uint8_t* const, unsigned,
+    int, unsigned){}
+int AppIdDiscovery::add_service_port(AppIdDetector*, const ServiceDetectorPort&){return 0;}
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&){}
+int AppIdSession::add_flow_data(void* data, unsigned type, AppIdFreeFCN)
+{
+    if ( type == APPID_SESSION_DATA_SMB_DATA )
+    {
+        smb_data = (FpSMBData*)data;
+        set_session_flags(APPID_SESSION_HAS_SMB_INFO);
+    }
+    return 0;
+}
+int dcerpc_validate(const uint8_t*, int){return 0; }
+AppIdDiscovery::AppIdDiscovery() { }
+AppIdDiscovery::~AppIdDiscovery() { }
+void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
+void show_stats(PegCount*, const PegInfo*, const IndexVec&, const char*, FILE*) { }
+AppIdConfig config;
+AppIdContext ctxt(config);
+class AppIdInspector : public snort::Inspector
+{
+public:
+    void eval(Packet*) override { }
+    bool configure(snort::SnortConfig*) override { return true; }
+};
+
+// Stubs for modules, config
+AppIdConfig::~AppIdConfig() = default;
+bool AppIdModule::begin(const char*, int, snort::SnortConfig*)
+{
+    return false;
+}
+
+bool AppIdModule::set(const char*, snort::Value&, snort::SnortConfig*)
+{
+    return false;
+}
+
+bool AppIdModule::end(const char*, int, snort::SnortConfig*)
+{
+    return false;
+}
+
+const Command* AppIdModule::get_commands() const
+{
+    return nullptr;
+}
+
+const PegInfo* AppIdModule::get_pegs() const
+{
+    return nullptr;
+}
+
+PegCount* AppIdModule::get_counts() const
+{
+    return nullptr;
+}
+
+// Stubs for inspectors
+unsigned AppIdSession::inspector_id = 0;
+AppIdConfig stub_config;
+AppIdContext stub_ctxt(stub_config);
+AppIdSession::AppIdSession(IpProtocol, const SfIp*, uint16_t, AppIdInspector& inspector)
+    : snort::FlowData(inspector_id, (snort::Inspector*)&inspector), ctxt(stub_ctxt) { }
+AppIdSession::~AppIdSession() = default;
+void AppIdSession::free_flow_data()
+{
+    snort_free(smb_data);
+}
+void* AppIdSession::get_flow_data(unsigned){ return smb_data;}
+
+// Stubs for AppIdPegCounts
+void AppIdPegCounts::inc_service_count(AppId) { }
+void AppIdPegCounts::inc_client_count(AppId) { }
+void AppIdPegCounts::inc_payload_count(AppId) { }
+
+THREAD_LOCAL AppIdStats appid_stats;
+void AppIdModule::show_dynamic_stats() { }
+
+// Stubs for app_info_table.cc
+AppInfoTableEntry* AppInfoManager::get_app_info_entry(int)
+{
+    return nullptr;
+}
+
+bool AppInfoManager::configured()
+{
+    return true;
+}
+ServiceDiscoveryState* AppIdServiceState::add(SfIp const*, IpProtocol, unsigned short, bool, bool)
+{
+  return nullptr;
+}
+void ServiceDiscoveryState::set_service_id_valid(ServiceDetector*) { }
+static OdpContext stub_odp_ctxt(stub_config, nullptr);
+OdpContext* AppIdContext::odp_ctxt = &stub_odp_ctxt;
+
+OdpContext::OdpContext(AppIdConfig&, snort::SnortConfig*)
+{ }
+
+#endif