From 1b8c92c60640356cd5507253a1fa70bb3a4e4e06 Mon Sep 17 00:00:00 2001 From: "Shravan Rangarajuvenkata (shrarang)" Date: Mon, 16 Mar 2020 14:17:30 +0000 Subject: [PATCH] Merge pull request #2075 in SNORT/snort3 from ~KAMURTHI/snort3:smb_appid to master Squashed commit of the following: commit 158a37aa6275e82dc1504f26f83617463336700f Author: Kanimozhi Murthi Date: Wed Mar 11 14:40:01 2020 -0400 appid: Fix SMB session data memory leak. --- .../appid/service_plugins/service_netbios.cc | 3 +- .../appid/service_plugins/test/CMakeLists.txt | 1 + .../test/service_netbios_test.cc | 93 ++++++++ .../test/service_plugin_mock.h | 199 ++++++++++++++++++ 4 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 src/network_inspectors/appid/service_plugins/test/service_netbios_test.cc create mode 100644 src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h diff --git a/src/network_inspectors/appid/service_plugins/service_netbios.cc b/src/network_inspectors/appid/service_plugins/service_netbios.cc index 1f7a07ea4..812b8a77f 100644 --- a/src/network_inspectors/appid/service_plugins/service_netbios.cc +++ b/src/network_inspectors/appid/service_plugins/service_netbios.cc @@ -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) ) diff --git a/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt b/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt index d221dfda3..85ef7522f 100644 --- a/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt +++ b/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt @@ -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 index 000000000..319a29823 --- /dev/null +++ b/src/network_inspectors/appid/service_plugins/test/service_netbios_test.cc @@ -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 +// 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 +#include +#include + +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 index 000000000..214b33ae2 --- /dev/null +++ b/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h @@ -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 + +#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 >&, 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 -- 2.47.3