uint16_t id, bool host_reporting, AppIdSession& asd, AppidChangeBits& change_bits)
{
int ret;
- const uint8_t* host;
- uint8_t host_len;
- bool host_len_valid;
- uint16_t host_offset;
+ const uint8_t* host = data + *offset;
+ uint8_t host_len = 0;
+ bool host_len_valid = false;
+ uint16_t host_offset = *offset;
- host = data + *offset;
- host_offset = *offset;
ret = dns_validate_label(data, *offset, size, host_len, host_len_valid);
- if (ret == APPID_SUCCESS)
+ if ((ret == APPID_SUCCESS) and (host_reporting))
{
+ if ((*offset > size) || ((size - *offset) < (uint16_t)sizeof(DNSQueryFixed)))
+ return APPID_NOMATCH;
+
const DNSQueryFixed* query = (const DNSQueryFixed*)(data + *offset);
+
*offset += sizeof(DNSQueryFixed);
- if (host_reporting)
- {
- uint16_t record_type = ntohs(query->QType);
+ uint16_t record_type = ntohs(query->QType);
- if ((host_len == 0) || (!host_len_valid))
- {
- host = nullptr;
- host_len = 0;
- host_offset = 0;
- }
- switch (record_type)
- {
- case PATTERN_A_REC:
- case PATTERN_AAAA_REC:
- case PATTERN_CNAME_REC:
- case PATTERN_SRV_REC:
- case PATTERN_TXT_REC:
- case PATTERN_MX_REC:
- case PATTERN_SOA_REC:
- case PATTERN_NS_REC:
- case PATTERN_ANY_REC:
- ret = add_dns_query_info(asd, id, host, host_len, host_offset, record_type, *offset, change_bits);
- break;
- case PATTERN_PTR_REC:
- ret = add_dns_query_info(asd, id, nullptr, 0, 0, record_type, *offset, change_bits);
- break;
- default:
- break;
- }
+ if ((host_len == 0) || (!host_len_valid))
+ {
+ host = nullptr;
+ host_len = 0;
+ host_offset = 0;
+ }
+ switch (record_type)
+ {
+ case PATTERN_A_REC:
+ case PATTERN_AAAA_REC:
+ case PATTERN_CNAME_REC:
+ case PATTERN_SRV_REC:
+ case PATTERN_TXT_REC:
+ case PATTERN_MX_REC:
+ case PATTERN_SOA_REC:
+ case PATTERN_NS_REC:
+ case PATTERN_ANY_REC:
+ ret = add_dns_query_info(asd, id, host, host_len, host_offset, record_type, *offset, change_bits);
+ break;
+ case PATTERN_PTR_REC:
+ ret = add_dns_query_info(asd, id, nullptr, 0, 0, record_type, *offset, change_bits);
+ break;
+ default:
+ break;
}
+
}
return ret;
}
int Pop3ServiceDetector::pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint16_t size,
AppIdSession& asd, int server, AppidChangeBits& change_bits)
-{
+{
ServicePOP3Data* pd = &dd->server;
const uint8_t* begin = nullptr;
// fallthrough
case POP3_STATE_RESPONSE:
- if (!begin && data[0] == '+' && data[1] == ' ')
+ if (!begin && size >= 2 && data[0] == '+' && data[1] == ' ')
{
data += 2;
if (pop3_check_line(&data, end))
if (*args.data == '.')
{
if (len == 0 ||
- args.data[1] == '\n' ||
- (len >= 2 && args.data[1] == '\r' && args.data[2] == '\n'))
+ (len >= 2 && args.data[1] == '\n') ||
+ (len >= 3 && args.data[1] == '\r' && args.data[2] == '\n'))
{
add_app(args.asd, APP_ID_SMTP, APP_ID_SMTP, nullptr, args.change_bits);
goto done;
vendor_len = ver - data;
ver++;
- for (p = ver; *p && p < end; p++)
+ for (p = ver; p < end && *p; p++)
{
if ( *p == '(' )
{
include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
-add_cpputest( detector_smtp_test )
+add_cpputest( detector_smtp_test
+ SOURCES
+ ../../../../utils/util_cstring.cc )
-add_cpputest( http_url_patterns_test )
+add_cpputest( http_url_patterns_test
+ SOURCES
+ ../../../../utils/util_cstring.cc )
-add_cpputest( detector_sip_test )
+add_cpputest( detector_sip_test
+ SOURCES
+ ../../../../utils/util_cstring.cc
+ ../../appid_utils/sf_mlmp.cc )
+
+add_cpputest( detector_pop3_test
+ SOURCES
+ ../../../../utils/util_cstring.cc )
#include "config.h"
#endif
+#include <utils/util_cstring.h>
+#include <framework/module.h>
+#include <appid/service_plugins/service_detector.h>
+#include <appid/client_plugins/client_detector.h>
+#include <appid/appid_inspector.h>
+
#include "log/messages.h"
#include "utils/stats.h"
void show_stats(PegCount*, const PegInfo*, const std::vector<unsigned>&, const char*, FILE*) { }
// LCOV_EXCL_STOP
-#ifndef SIP_UNIT_TEST
-class AppIdInspector : public snort::Inspector
-{
-public:
- AppIdInspector(AppIdModule&) { }
- ~AppIdInspector() override = default;
- bool configure(snort::SnortConfig*) override;
-private:
- AppIdContext* ctxt = nullptr;
-};
-#endif
-
// Stubs for modules, config
AppIdConfig::~AppIdConfig() = default;
AppIdModule::AppIdModule()
return false;
}
-const Command* AppIdModule::get_commands() const
+const snort::Command* AppIdModule::get_commands() const
{
return nullptr;
}
return nullptr;
}
-void AppIdModule::set_trace(const Trace*) const { }
-const TraceOption* AppIdModule::get_trace_options() const { return nullptr; }
+void AppIdModule::set_trace(const snort::Trace*) const { }
+const snort::TraceOption* AppIdModule::get_trace_options() const { return nullptr; }
// LCOV_EXCL_STOP
// Stubs for inspectors
AppIdConfig stub_config;
AppIdContext stub_ctxt(stub_config);
OdpContext stub_odp_ctxt(stub_config, nullptr);
-AppIdSession::AppIdSession(IpProtocol, const SfIp* ip, uint16_t, AppIdInspector& inspector,
+AppIdSession::AppIdSession(IpProtocol, const snort::SfIp* ip, uint16_t, AppIdInspector& inspector,
OdpContext& odpctxt, uint32_t
#ifndef DISABLE_TENANT_ID
,uint32_t
#endif
) : snort::FlowData(inspector_id, (snort::Inspector*)&inspector),
- config(stub_config), api(*(new AppIdSessionApi(this, *ip))), odp_ctxt(odpctxt)
+ config(stub_config), api(*(new snort::AppIdSessionApi(this, *ip))), odp_ctxt(odpctxt)
{
- this->set_session_flags(APPID_SESSION_DISCOVER_APP);
+
}
AppIdSession::~AppIdSession() { delete &api; }
AppIdHttpSession::AppIdHttpSession(AppIdSession& asd, int64_t http2_stream_id)
{ }
THREAD_LOCAL OdpContext* pkt_thread_odp_ctxt = nullptr;
+
+// Stubs for module
+snort::Module::Module(char const*, char const*) {}
+void snort::Module::sum_stats(bool) {}
+void snort::Module::show_interval_stats(std::vector<unsigned>&, FILE*) {}
+void snort::Module::show_stats() {}
+void snort::Module::init_stats(bool) {}
+void snort::Module::reset_stats() {}
+void snort::Module::main_accumulate_stats() {}
+PegCount snort::Module::get_global_count(char const*) const { return 0; }
+
+
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
+AppIdDiscovery::~AppIdDiscovery() = default;
+void ClientDiscovery::initialize(AppIdInspector&) { }
+void ClientDiscovery::reload() { }
+void AppIdDiscovery::register_detector(const string&, AppIdDetector*, IpProtocol) { }
+void AppIdDiscovery::add_pattern_data(AppIdDetector*, snort::SearchTool&, int, unsigned char const*, unsigned int, unsigned int) { }
+void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, unsigned int, int, unsigned int) { }
+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;
+EveCaPatternMatchers::~EveCaPatternMatchers() = default;
+#ifndef SIP_UNIT_TEST
+SipPatternMatchers::~SipPatternMatchers() = default;
+#endif
+HostPatternMatchers::~HostPatternMatchers() = default;
+AlpnPatternMatchers::~AlpnPatternMatchers() = default;
+#ifndef HTTP_PATTERNS_UNIT_TEST
+HttpPatternMatchers::~HttpPatternMatchers() = default;
+#endif
+UserDataMap::~UserDataMap() = default;
+CipPatternMatchers::~CipPatternMatchers() = default;
+bool HostPatternMatchers::scan_url(const uint8_t*, size_t, AppId&, AppId&, bool*){ return true; }
+void AppIdModule::reset_stats() {}
+bool AppIdInspector::configure(snort::SnortConfig*) { return true; }
+void appid_log(const snort::Packet*, unsigned char, char const*, ...) { }
+void HostPatternMatchers::add_host_pattern(unsigned char const*, unsigned long, unsigned char, int, int, HostPatternType, bool, bool) {}
+
+#ifndef SIP_UNIT_TEST
+snort::SearchTool::SearchTool(bool, const char*) { }
+#endif
+
+ServiceDetector::ServiceDetector() {}
+void ServiceDetector::register_appid(AppId appId, unsigned extractsInfo, OdpContext& odp_ctxt) {}
+int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const snort::Packet* pkt,
+ AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
+ AppIdServiceSubtype* subtype, AppidChangeBits& change_bits)
+ { return 0; }
+int ServiceDetector::add_service(AppidChangeBits& change_bits, AppIdSession& asd,
+ const snort::Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor,
+ const char* version, AppIdServiceSubtype* subtype)
+ { return 0; }
+int ServiceDetector::service_inprocess(AppIdSession& asd, const snort::Packet* pkt, AppidSessionDirection dir) { return 0; }
+
+snort::AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&)
+{ }
+
+AppIdInspector::~AppIdInspector() = default;
+
+void ClientDetector::register_appid(int, unsigned int, OdpContext&) { }
+
+void AppIdInspector::eval(snort::Packet*) { }
+void AppIdInspector::show(const snort::SnortConfig*) const { }
+void AppIdInspector::tinit() { }
+void AppIdInspector::tterm() { }
+void AppIdInspector::tear_down(snort::SnortConfig*) { }
+
+ClientDetector::ClientDetector() { }
+
+void AppIdSession::set_client_appid_data(AppId, AppidChangeBits&, char*) { }
+int AppIdSession::add_flow_data_id(uint16_t, ServiceDetector*) { return 0; }
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2025 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.
+//--------------------------------------------------------------------------
+
+// detector_pop3_test.cc author Oleksandr Stepanov <ostepano@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "appid_inspector.h"
+#include "appid_session.h"
+#include "detector_plugins_mock.h"
+
+#include "../detector_pop3.h"
+#include "../detector_pop3.cc"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+using namespace snort;
+
+static ServiceDiscovery test_discovery;
+
+// Stubs for AppIdInspector
+AppIdConfig test_app_config;
+AppIdInspector::AppIdInspector(AppIdModule&) : config(&test_app_config), ctxt(test_app_config) { }
+
+void snort::SearchTool::reload() { }
+int snort::SearchTool::find_all(const char*, unsigned, MpseMatch, bool, void* mp_arg, const snort::SnortConfig*)
+{
+ return 0;
+}
+
+void AppIdDetector::add_user(AppIdSession&, const char*, AppId, bool, AppidChangeBits&){}
+int AppIdDetector::data_add(AppIdSession&, AppIdFlowData*) { return 1; }
+AppIdFlowData* AppIdDetector::data_get(const AppIdSession&)
+{
+ return nullptr;
+}
+
+int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir) { return 1; }
+
+
+TEST_GROUP(detector_pop_tests)
+{
+ Pop3ServiceDetector* test_detector = nullptr;
+ void setup() override
+ {
+ test_detector = new Pop3ServiceDetector(&test_discovery);
+ }
+
+ void teardown() override
+ {
+ delete test_detector;
+ test_detector = nullptr;
+ }
+};
+
+TEST(detector_pop_tests, pop_validate_incorrect_packet_len)
+{
+ OdpContext test_odp_ctxt(test_app_config, nullptr);
+ AppIdModule test_module;
+ AppIdInspector test_inspector(test_module);
+ AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
+ const uint8_t* test_data = (const uint8_t*)".";
+ uint16_t test_data_size = 1;
+ AppidChangeBits cb;
+
+ POP3DetectorData dd;
+ dd.server.state = POP3_STATE_CONNECT;
+
+ auto result = test_detector->pop3_server_validate(&dd, test_data, test_data_size, test_asd, 1, cb);
+ CHECK_EQUAL(-1, result);
+}
+
+int main(int argc, char** argv)
+{
+ int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+ return return_value;
+}
#include "detector_plugins/detector_sip.cc"
#include "detector_plugins/sip_patterns.cc"
-#include "framework/data_bus.h"
-#include "framework/module.cc"
#include "framework/mpse_batch.h"
-#include "main/thread_config.h"
-#include "network_inspectors/appid/appid_utils/sf_mlmp.cc"
-#include "protocols/protocol_ids.h"
#include "service_inspectors/sip/sip_parser.h"
-#include "utils/util_cstring.cc"
#include "appid_inspector.h"
#include "detector_plugins_mock.h"
MpseGroup mpse_group;
static bool prep_patterns = true;
+// Stubs for AppIdInspector
+AppIdConfig test_app_config;
+AppIdInspector::AppIdInspector(AppIdModule&) : config(&test_app_config), ctxt(test_app_config) { }
+
namespace snort
{
AppIdApi appid_api;
-AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&)
-{ }
Flow::~Flow() = default;
AppIdSession* AppIdApi::get_appid_session(snort::Flow const&) { return nullptr; }
unsigned ThreadConfig::get_instance_max() { return 1; }
}
-AppIdInspector::AppIdInspector(AppIdModule&) : config(&s_config), ctxt(s_config)
-{ }
-
-bool AppIdInspector::configure(snort::SnortConfig*)
-{
- return true;
-}
-
-// LCOV_EXCL_START
-void AppIdInspector::eval(Packet*) { }
-void AppIdInspector::show(const SnortConfig*) const { }
-void AppIdInspector::tinit() { }
-void AppIdInspector::tterm() { }
-void AppIdInspector::tear_down(SnortConfig*) { }
-// LCOV_EXCL_STOP
-
-AppIdInspector::~AppIdInspector() = default;
void AppIdContext::create_odp_ctxt()
{
}
void AppIdSession::publish_appid_event(AppidChangeBits&, const Packet&, bool, uint32_t) { }
-AppIdDiscovery::~AppIdDiscovery() = default;
-
-// LCOV_EXCL_START
-void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection,
- AppId, AppidChangeBits&) { }
-void ClientDiscovery::initialize(AppIdInspector&) { }
-void ClientDiscovery::reload() { }
-// LCOV_EXCL_STOP
-
-void AppIdDiscovery::register_detector(const string&, AppIdDetector*, IpProtocol) { }
-
-// LCOV_EXCL_START
-void AppIdDiscovery::add_pattern_data(AppIdDetector*, snort::SearchTool&, int,
- unsigned char const*, unsigned int, unsigned int) { }
-void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, unsigned int,
- int, unsigned int) { }
-void AppIdDiscovery::register_udp_pattern(AppIdDetector*, unsigned char const*, unsigned int,
- int, unsigned int) { }
-int AppIdDiscovery::add_service_port(AppIdDetector*, ServiceDetectorPort const&) { return 0; }
-void AppIdModule::reset_stats() { }
-// LCOV_EXCL_STOP
-
-DnsPatternMatchers::~DnsPatternMatchers() = default;
-EveCaPatternMatchers::~EveCaPatternMatchers() = default;
-HostPatternMatchers::~HostPatternMatchers() = default;
-HttpPatternMatchers::~HttpPatternMatchers() = default;
-AlpnPatternMatchers::~AlpnPatternMatchers() = default;
-CipPatternMatchers::~CipPatternMatchers() = default;
-UserDataMap::~UserDataMap() = default;
-
-ClientDetector::ClientDetector() { }
// LCOV_EXCL_START
-void ClientDetector::register_appid(int, unsigned int, OdpContext&) { }
int AppIdDetector::initialize(AppIdInspector&) { return 1; }
int AppIdDetector::data_add(AppIdSession&, AppIdFlowData*) { return 1; }
void AppIdDetector::add_user(AppIdSession&, char const*, int, bool, AppidChangeBits&) { }
#include "config.h"
#endif
-#if 0
-#include "network_inspectors/appid/detector_plugins/detector_smtp.cc"
+#include "appid_inspector.h"
+#include "appid_session.h"
+#include "detector_plugins_mock.h"
+
+
+#include "../detector_smtp.h"
+#include "../detector_smtp.cc"
+
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
-#include <string>
+using namespace snort;
+#if 0
struct AddAppData
{
AppId client_id = 0;
check_client_version(client_str, APP_ID_THUNDERBIRD, "5.0",
&appid_stats.smtp_thunderbird_clients);
}
-
#endif
-// FIXIT-M Add additional tests for other client types (Outlook, etc).
-int main(int, char**)
+
+static ClientDiscovery test_discovery;
+
+// Stubs for AppIdInspector
+AppIdConfig test_app_config;
+AppIdInspector::AppIdInspector(AppIdModule&) : config(&test_app_config), ctxt(test_app_config) { }
+
+int AppIdDetector::data_add(AppIdSession&, AppIdFlowData*) { return 1; }
+
+SMTPDetectorData* test_data_get = nullptr;
+
+AppIdFlowData* AppIdDetector::data_get(const AppIdSession&)
+{
+ return test_data_get;
+}
+
+int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir) { return 1; }
+
+TEST_GROUP(detector_smtp_tests)
+{
+ SmtpClientDetector *test_detector = nullptr;
+ void setup() override
+ {
+ test_detector = new SmtpClientDetector(&test_discovery);
+ }
+
+ void teardown() override
+ {
+ delete test_detector;
+ test_detector = nullptr;
+ }
+};
+
+TEST(detector_smtp_tests, client_message_wrong_len_1)
+{
+ OdpContext test_odp_ctxt(test_app_config, nullptr);
+ AppIdModule test_module;
+ AppIdInspector test_inspector(test_module);
+ AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
+ const uint8_t* test_data = (const uint8_t*)".";
+ uint16_t test_data_size = 1;
+ AppidChangeBits cb;
+
+ test_data_get = new SMTPDetectorData;
+ test_data_get->client.state = SMTP_CLIENT_STATE_MESSAGE;
+
+ AppIdDiscoveryArgs test_args(test_data, test_data_size, AppidSessionDirection::APP_ID_FROM_INITIATOR, test_asd, nullptr, cb);
+
+ auto result = test_detector->validate(test_args);
+ CHECK_EQUAL(result, APPID_INPROCESS);
+ CHECK_EQUAL(test_asd.is_client_detected(), false);
+
+ delete test_data_get;
+}
+
+TEST(detector_smtp_tests, client_message_wrong_len_2)
+{
+ OdpContext test_odp_ctxt(test_app_config, nullptr);
+ AppIdModule test_module;
+ AppIdInspector test_inspector(test_module);
+ AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
+ const uint8_t* test_data = (const uint8_t*)".\t";
+ uint16_t test_data_size = 2;
+ AppidChangeBits cb;
+
+ test_data_get = new SMTPDetectorData;
+ test_data_get->client.state = SMTP_CLIENT_STATE_MESSAGE;
+
+ AppIdDiscoveryArgs test_args(test_data, test_data_size, AppidSessionDirection::APP_ID_FROM_INITIATOR, test_asd, nullptr, cb);
+
+ auto result = test_detector->validate(test_args);
+ CHECK_EQUAL(result, APPID_INPROCESS);
+ CHECK_EQUAL(test_asd.is_client_detected(), false);
+
+ delete test_data_get;
+}
+
+int main(int argc, char** argv)
{
-#if 0
int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
return return_value;
-#endif
}
-
#include "config.h"
#endif
-#include "network_inspectors/appid/detector_plugins/http_url_patterns.cc"
+#define HTTP_PATTERNS_UNIT_TEST
+
+#include "../http_url_patterns.h"
+#include "../http_url_patterns.cc"
-#include "main/thread_config.h"
-#include "protocols/protocol_ids.h"
-#include "framework/module.cc"
#include "network_inspectors/appid/appid_utils/sf_mlmp.cc"
-#include "utils/util_cstring.cc"
+
#include "detector_plugins_mock.h"
#include <CppUTest/CommandLineTestRunner.h>
static AppId client_id = APP_ID_NONE;
static DetectorHTTPPattern mpattern;
+// Stubs for AppIdInspector
+AppIdConfig test_app_config;
+AppIdInspector::AppIdInspector(AppIdModule&) : config(&test_app_config), ctxt(test_app_config) { }
+
namespace snort
{
-AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&)
-{ }
-SearchTool::SearchTool(bool, const char*) { }
-void SearchTool::reload() { }
static bool test_find_all_done = false;
static bool test_find_all_enabled = false;
static MatchedPatterns* mock_mp = nullptr;
+void SearchTool::reload() { }
int SearchTool::find_all(const char*, unsigned, MpseMatch, bool, void* mp_arg, const SnortConfig*)
{
test_find_all_done = true;
memcpy(mp_arg, &mock_mp, sizeof(MatchedPatterns*));
return 0;
}
-unsigned get_instance_id()
-{ return 0; }
-unsigned ThreadConfig::get_instance_max() { return 1; }
}
-void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
-AppIdDiscovery::~AppIdDiscovery() = default;
-void ClientDiscovery::initialize(AppIdInspector&) { }
-void ClientDiscovery::reload() { }
-void AppIdDiscovery::register_detector(const string&, AppIdDetector*, IpProtocol) { }
-void AppIdDiscovery::add_pattern_data(AppIdDetector*, snort::SearchTool&, int, unsigned char const*, unsigned int, unsigned int) { }
-void AppIdDiscovery::register_tcp_pattern(AppIdDetector*, unsigned char const*, unsigned int, int, unsigned int) { }
-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;
-EveCaPatternMatchers::~EveCaPatternMatchers() = default;
-SipPatternMatchers::~SipPatternMatchers() = default;
-HostPatternMatchers::~HostPatternMatchers() = default;
-AlpnPatternMatchers::~AlpnPatternMatchers() = default;
-UserDataMap::~UserDataMap() = default;
-CipPatternMatchers::~CipPatternMatchers() = default;
-bool HostPatternMatchers::scan_url(const uint8_t*, size_t, AppId&, AppId&, bool*){ return true; }
-void AppIdModule::reset_stats() {}
-bool AppIdInspector::configure(snort::SnortConfig*) { return true; }
-void appid_log(const snort::Packet*, unsigned char, char const*, ...) { }
-void HostPatternMatchers::add_host_pattern(unsigned char const*, unsigned long, unsigned char, int, int, HostPatternType, bool, bool) {}
-
TEST_GROUP(http_url_patterns_tests)
{
void setup() override
test_find_all_enabled = false;
}
+TEST(http_url_patterns_tests, empty_server_vendor_version)
+{
+ char* version = nullptr;
+ char* vendor = nullptr;
+ AppIdServiceSubtype* subtype = nullptr;
+ hm->get_server_vendor_version("test/", 5, &version, &vendor, &subtype);
+
+ CHECK(version);
+ CHECK(version[0] == '\0');
+
+ CHECK(vendor);
+ CHECK_EQUAL(strcmp(vendor, "test"), 0);
+
+ snort_free(version);
+ snort_free(vendor);
+}
+
int main(int argc, char** argv)
{
int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
*data += sizeof(NBNSLabelData);
break;
case 0xC0:
+ if (end - *data < (int)sizeof(NBNSLabelPtr))
+ return -1;
lbl_ptr = (const NBNSLabelPtr*)(*data);
*data += sizeof(NBNSLabelPtr);
if (begin + lbl_ptr->position + sizeof(NBNSLabelData) > end)
*data += sizeof(NBNSLabelData);
break;
case 0xC0:
+ if (end - *data < (int)sizeof(NBNSLabelPtr))
+ return -1;
lbl_ptr = (const NBNSLabelPtr*)(*data);
*data += sizeof(NBNSLabelPtr);
if (begin + lbl_ptr->position + sizeof(NBNSLabelData) > end)
}
else if (*chunk_stream_id == 1)
{
- *chunk_stream_id = data[2] * 256 + data[1] + 64;
if (size < 3)
return 0;
+ *chunk_stream_id = data[2] * 256 + data[1] + 64;
data += 3;
size -= 3;
}
return -1;
if (snmp_ans1_length(data, end, &overall_length))
return -1;
- if (overall_length < 3 || (int)overall_length > end-(*data))
+ if (overall_length < 3 || (*data >= end) || overall_length > static_cast<uint32_t>(end - *data))
return -1;
if (**data != 0x02)
return -1;
add_cpputest( service_rsync_test )
add_cpputest( alpn_patterns_tests )
-
+add_cpputest( service_snmp_test )
+add_cpputest( service_rtmp_test )
+add_cpputest( service_netbios_test )
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 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 Oleksandr Stepanov <ostepano@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../service_netbios.h"
+#include "../service_netbios.cc"
+#include "service_plugin_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+void AppIdSessionApi::set_netbios_name(AppidChangeBits& change_bits, const char* name) { }
+
+TEST_GROUP(netbios_parsing_tests)
+{
+ void setup() override
+ {
+
+ }
+ void teardown() override
+ {
+
+ }
+};
+
+TEST(netbios_parsing_tests, netbios_parse_invalid_len_missing_position)
+{
+ const uint8_t* data = (const uint8_t*)"\xC0"; // Invalid length
+ const uint8_t* original_data = data;
+ const uint8_t* end = data + 1;
+ char name[NBNS_NAME_LEN / 2 + 1] = {0};
+
+ int ret = netbios_validate_name_and_decode(&data, data, end, name);
+ CHECK_EQUAL(-1, ret);
+ CHECK_EQUAL(data, original_data); // Ensure data pointer is unchanged
+}
+
+TEST(netbios_parsing_tests, netbios_parse_invalid_len_wrong_position)
+{
+ const uint8_t* data = (const uint8_t*)"\xC0\xFF"; // Invalid length
+ const uint8_t* original_data = data;
+ const uint8_t* end = data + 2;
+ char name[NBNS_NAME_LEN / 2 + 1] = {0};
+
+ int ret = netbios_validate_name_and_decode(&data, data, end, name);
+ CHECK_EQUAL(-1, ret);
+ CHECK_EQUAL(original_data + sizeof(NBNSLabelPtr), data); // Check that length and flags are parsed
+}
+
+TEST(netbios_parsing_tests, netbios_parse_invalid_len_missing_position_without_decode)
+{
+ const uint8_t* data = (const uint8_t*)"\xC0"; // Invalid length
+ const uint8_t* original_data = data;
+ const uint8_t* end = data + 1;
+ char name[NBNS_NAME_LEN / 2 + 1] = {0};
+
+ int ret = netbios_validate_name(&data, data, end);
+ CHECK_EQUAL(-1, ret);
+ CHECK_EQUAL(data, original_data); // Ensure data pointer is unchanged
+}
+
+TEST(netbios_parsing_tests, netbios_parse_invalid_len_wrong_position_without_decode)
+{
+ const uint8_t* data = (const uint8_t*)"\xC0\xFF"; // Invalid length
+ const uint8_t* original_data = data;
+ const uint8_t* end = data + 2;
+ char name[NBNS_NAME_LEN / 2 + 1] = {0};
+
+ int ret = netbios_validate_name(&data, data, end);
+ CHECK_EQUAL(-1, ret);
+ CHECK_EQUAL(original_data + sizeof(NBNSLabelPtr), data); // Check that length and flags are parsed
+}
+
+int main(int argc, char** argv)
+{
+ int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+ return return_value;
+}
#ifndef SERVICE_PLUGIN_MOCK_H
#define SERVICE_PLUGIN_MOCK_H
-#include "appid_detector.h"
-#include "appid_module.h"
-#include "appid_peg_counts.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <framework/data_bus.h>
+#include <detection/detection_engine.h>
+#include <appid/appid_inspector.h>
+#include <appid/service_plugins/service_discovery.h>
+
+#include "appid_detector.h"
+#include "appid_module.h"
+#include "appid_peg_counts.h"
+
#define APPID_UT_ID 1492
namespace snort
memcpy(p, str, n);
return p;
}
-Module::Module(const char*, const char*) {}
-Module::Module(const char*, const char*, const Parameter*, bool)
-{}
-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){}
-void Module::main_accumulate_stats(){}
-void Module::reset_stats() {}
+void snort::Module::sum_stats(bool) {}
+void snort::Module::show_interval_stats(std::vector<unsigned>&, FILE*) {}
+void snort::Module::show_stats() {}
+void snort::Module::init_stats(bool) {}
+void snort::Module::reset_stats() {}
+void snort::Module::main_accumulate_stats() {}
AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&)
{ }
CipPatternMatchers::~CipPatternMatchers() { }
void ClientDiscovery::initialize(AppIdInspector&) {}
void ClientDiscovery::reload() {}
-FpSMBData* smb_data = nullptr;
int AppIdDetector::initialize(AppIdInspector&){return 0;}
int AppIdDetector::data_add(AppIdSession&, AppIdFlowData*){return 0;}
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*, unsigned) { return 0; }
int dcerpc_validate(const uint8_t*, int){return 0; }
AppIdDiscovery::~AppIdDiscovery() { }
void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
-void show_stats(PegCount*, const PegInfo*, const vector<unsigned>&, const char*, FILE*) { }
AppIdConfig config;
AppIdContext ctxt(config);
-class AppIdInspector : public snort::Inspector
-{
-public:
- bool configure(snort::SnortConfig*) override { return true; }
-};
+ServiceDetector::ServiceDetector() {}
+int ServiceDetector::incompatible_data(AppIdSession& asd, const snort::Packet* pkt, AppidSessionDirection dir) { return 0; }
+int ServiceDetector::fail_service(AppIdSession& asd, const snort::Packet* pkt, AppidSessionDirection dir) { return 0; }
+int ServiceDetector::service_inprocess(AppIdSession& asd, const snort::Packet* pkt, AppidSessionDirection dir) { return 0; }
+int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const snort::Packet* pkt,
+ AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
+ AppIdServiceSubtype* subtype, AppidChangeBits& change_bits)
+ { return 0; }
+int ServiceDetector::add_service(AppidChangeBits& change_bits, AppIdSession& asd,
+ const snort::Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor,
+ const char* version, AppIdServiceSubtype* subtype)
+ { return 0; }
+void ServiceDetector::register_appid(AppId appId, unsigned extractsInfo, OdpContext& odp_ctxt) {}
+
+void AppIdDebug::activate(const snort::Flow*, const AppIdSession*, bool) { active = false; }
+
+AppIdSession* AppIdSession::create_future_session(const snort::Packet* ctrlPkt, const snort::SfIp* cliIp,
+ uint16_t cliPort, const snort::SfIp* srvIp, uint16_t srvPort, IpProtocol proto,
+ SnortProtocolId snort_protocol_id, OdpContext& odp_ctxt, bool swap_app_direction,
+ bool bidirectional, bool expect_persist) { return nullptr; }
+void AppIdSession::initialize_future_session(AppIdSession& expected, uint64_t flags) {}
// Stubs for modules, config
AppIdConfig::~AppIdConfig() = default;
return false;
}
-const Command* AppIdModule::get_commands() const
+const snort::Command* AppIdModule::get_commands() const
{
return nullptr;
}
return nullptr;
}
-void AppIdModule::set_trace(const Trace*) const { }
-const TraceOption* AppIdModule::get_trace_options() const { return nullptr; }
+void AppIdModule::set_trace(const snort::Trace*) const { }
+const snort::TraceOption* AppIdModule::get_trace_options() const { return nullptr; }
// Stubs for inspectors
unsigned AppIdSession::inspector_id = 0;
AppIdContext stub_ctxt(stub_config);
static OdpContext stub_odp_ctxt(stub_config, nullptr);
OdpContext* AppIdContext::odp_ctxt = &stub_odp_ctxt;
-AppIdSession::AppIdSession(IpProtocol, const SfIp* ip, uint16_t, AppIdInspector& inspector,
- OdpContext&
+AppIdSession::AppIdSession(IpProtocol, const snort::SfIp* ip, uint16_t, AppIdInspector& inspector,
+ OdpContext& odpctxt, uint32_t
#ifndef DISABLE_TENANT_ID
- ,uint16_t
+ ,uint32_t
#endif
) : snort::FlowData(inspector_id, (snort::Inspector*)&inspector),
- config(stub_config), api(*(new AppIdSessionApi(this, *ip))), odp_ctxt(stub_odp_ctxt) { }
+ config(stub_config), api(*(new snort::AppIdSessionApi(this, *ip))), odp_ctxt(odpctxt)
+{ }
AppIdSession::~AppIdSession() = default;
DiscoveryFilter::~DiscoveryFilter(){}
void AppIdSession::free_flow_data()
{
- snort_free(smb_data);
+
+}
+AppIdFlowData* AppIdSession::get_flow_data(unsigned) const
+{
+ return nullptr;
}
-void* AppIdSession::get_flow_data(unsigned) const { return smb_data;}
// Stubs for AppIdPegCounts
-void AppIdPegCounts::inc_service_count(AppId, bool) { }
-void AppIdPegCounts::inc_client_count(AppId, bool) { }
-void AppIdPegCounts::inc_payload_count(AppId, bool) { }
+//void AppIdPegCounts::inc_service_count(AppId, bool) { }
+//void AppIdPegCounts::inc_client_count(AppId, bool) { }
+//void AppIdPegCounts::inc_payload_count(AppId, bool) { }
THREAD_LOCAL AppIdStats appid_stats;
void AppIdModule::show_dynamic_stats() { }
{
return true;
}
-ServiceDiscoveryState* AppIdServiceState::add(SfIp const*, IpProtocol,
- unsigned short, int16_t, uint16_t, bool, bool)
-{
- return nullptr;
-}
-void ServiceDiscoveryState::set_service_id_valid(ServiceDetector*) { }
+
+void ServiceDiscovery::initialize(AppIdInspector&) {}
+void ServiceDiscovery::reload() {}
+int ServiceDiscovery::add_service_port(AppIdDetector*, const ServiceDetectorPort&) { return 0; }
OdpContext::OdpContext(const AppIdConfig&, snort::SnortConfig*)
{ }
+void appid_log(const snort::Packet*, unsigned char, char const*, ...) { }
+int AppIdSession::add_flow_data_id(uint16_t, ServiceDetector*) { return 0; }
+AppIdHttpSession* AppIdSession::get_http_session(uint32_t) const { return nullptr; }
+AppIdHttpSession* AppIdSession::create_http_session(int64_t stream_id) { return nullptr; }
+void AppIdHttpSession::set_field(HttpFieldIds id, const std::string* str, AppidChangeBits&) { }
+
+void snort::DataBus::publish(unsigned, unsigned, snort::DataEvent&, snort::Flow*) { }
+void snort::DataBus::publish(unsigned, unsigned, const uint8_t*, unsigned, snort::Flow*) { }
+void snort::DataBus::publish(unsigned, unsigned, snort::Packet*, snort::Flow*) { }
+
+snort::Packet* snort::DetectionEngine::get_current_packet() { return nullptr; }
+
+unsigned AppIdInspector::get_pub_id() { return 0; }
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 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_rtmp_test.cc author Oleksandr Stepanov <ostepano@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../service_rtmp.h"
+#include "../service_rtmp.cc"
+#include "service_plugin_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+TEST_GROUP(rtmp_parsing_tests)
+{
+ void setup() override
+ {
+
+ }
+ void teardown() override
+ {
+
+ }
+};
+
+TEST(rtmp_parsing_tests, rtmp_parse_invalid_len)
+{
+ const uint8_t* data = (const uint8_t*)"\x41\x00";
+ uint16_t size = 2;
+ uint8_t format = 0;
+ uint32_t chunk_stream_id = 0;
+
+ int ret = parse_rtmp_chunk_basic_header(&data, &size, &format, &chunk_stream_id);
+ CHECK_EQUAL(0, ret);
+ CHECK_EQUAL(2, size);
+ CHECK_EQUAL(1, chunk_stream_id);
+}
+
+int main(int argc, char** argv)
+{
+ int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+ return return_value;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 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_snmp_test.cc author Oleksandr Stepanov <ostepano@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <protocols/packet.h>
+#include "../service_detector.h"
+
+#include "../service_snmp.h"
+#include "../service_snmp.cc"
+
+#include "service_plugin_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+THREAD_LOCAL AppIdDebug* appidDebug = nullptr;
+THREAD_LOCAL bool appid_trace_enabled = false;
+
+
+TEST_GROUP(snmp_parsing_tests)
+{
+ void setup() override
+ {
+
+ }
+ void teardown() override
+ {
+
+ }
+};
+
+TEST(snmp_parsing_tests, fail_on_invalid_sequence_tag)
+{
+ const uint8_t* data = (const uint8_t*)"\x31\x02\x01\x00"; /* Invalid tag - should be 0x30 */
+ const uint8_t* end = data + 4;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_insufficient_data)
+{
+ const uint8_t* data = (const uint8_t*)"\x30"; /* Only sequence tag, no length */
+ const uint8_t* end = data + 1;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_invalid_version_tag)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x05\x03\x01\x00\x04\x01"; /* Wrong version tag (0x03 instead of 0x02) */
+ const uint8_t* end = data + 7;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_invalid_version_length)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x05\x02\x02\x00\x04\x01"; /* Version length should be 1, not 2 */
+ const uint8_t* end = data + 7;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, success_snmp_v1_packet)
+{
+ const uint8_t snmp_v1[] = "\x30\x1c\x02\x01\x00\x04\x06public\xa0\x0f\x02\x01\x01\x02\x01\x00\x02\x01\x00\x30\x04\x30\x02\x06\x00";
+ const uint8_t* data = snmp_v1;
+ const uint8_t* end = data + sizeof(snmp_v1) - 1;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, 0);
+ CHECK_EQUAL(version, 0); /* SNMP v1 */
+ CHECK_EQUAL(pdu, 0); /* GET request */
+}
+
+TEST(snmp_parsing_tests, success_snmp_v2c_packet)
+{
+ const uint8_t snmp_v2c[] = "\x30\x1d\x02\x01\x01\x04\x06public\xa0\x10\x02\x01\x01\x02\x01\x00\x02\x01\x00\x30\x05\x30\x03\x06\x01\x00";
+ const uint8_t* data = snmp_v2c;
+ const uint8_t* end = data + sizeof(snmp_v2c) - 1;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, 0);
+ CHECK_EQUAL(version, 1); /* SNMP v2c */
+ CHECK_EQUAL(pdu, 0); /* GET request */
+}
+
+TEST(snmp_parsing_tests, fail_on_invalid_community_string)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x0b\x02\x01\x00\x04\x04\xff\xfe\xfd\xfc\xa0\x00"; /* Non-printable community */
+ const uint8_t* end = data + 13;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_unsupported_version)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x05\x02\x01\x05\x04\x00"; /* Version 5 (unsupported) */
+ const uint8_t* end = data + 7;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_length_overflow)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x82\xff\xff"; /* Length field indicates more data than available */
+ const uint8_t* end = data + 4;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+TEST(snmp_parsing_tests, fail_on_wrong_packet_length)
+{
+ const uint8_t* data = (const uint8_t*)"\x30\x7F"; /* SNMP packet with packet length = 127 */
+ const uint8_t* end = data + 2;
+ uint8_t pdu = 0;
+ uint8_t version = 0;
+
+ int ret = snmp_verify_packet(&data, end, &pdu, &version);
+ CHECK_EQUAL(ret, -1);
+}
+
+int main(int argc, char** argv)
+{
+ int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+ return return_value;
+}
\ No newline at end of file
int common_name_len = 0;
int org_unit_len = 0;
- while (len > 0 and !(common_name and org_unit))
+ while (len > 2 and !(common_name and org_unit))
{
X509* cert = nullptr;
X509_NAME* cert_name = nullptr;
../packet.cc
../packet_manager.cc
)
+
+add_cpputest( ssl_protocol_test )
\ No newline at end of file
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2023-2025 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.
+//--------------------------------------------------------------------------
+// ssl_protocol_test.cc author Oleksandr Stepanov <ostepano@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <cstring>
+#include <openssl/ossl_typ.h>
+
+#include "../ssl.h"
+#include "../ssl.cc"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+using namespace snort;
+
+typedef struct X509_name_entry_st X509_NAME_ENTRY;
+X509_NAME *X509_get_subject_name(const X509 *a) { return nullptr; }
+void X509_free(X509* a) { }
+int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) { return -1; }
+X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) { return nullptr; }
+ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) { return nullptr; }
+const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) { return nullptr; }
+X509* d2i_X509(X509 **a, const unsigned char **in, long len)
+{
+ return nullptr;
+}
+
+namespace snort
+{
+char* snort_strdup(const char* str)
+{
+ return str ? strdup(str) : nullptr;
+}
+
+char* snort_strndup(const char* src, size_t)
+{
+ return snort_strdup(src);
+}
+}
+
+TEST_GROUP(ssl_protocol_tests)
+{
+ void setup() override
+ {
+ }
+
+ void teardown() override
+ {
+ }
+};
+
+TEST(ssl_protocol_tests, cert_data_incomplete_len_2)
+{
+ SSLV3ServerCertData test_data;
+ test_data.certs_data = new uint8_t[2] { 0x01, 0x02 }; // Incomplete length, should be at least 3 bytes
+ test_data.certs_len = 2;
+ auto result = parse_server_certificates(&test_data);
+ CHECK_EQUAL(true, result);
+ CHECK_EQUAL(nullptr, test_data.certs_data);
+ CHECK_EQUAL(0, test_data.certs_len);
+}
+
+int main(int argc, char** argv)
+{
+ return CommandLineTestRunner::RunAllTests(argc, argv);
+}
\ No newline at end of file