--- /dev/null
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+// appid_dcerpc_event_handler.h author Eduard Burmai <eburmai@cisco.com>
+
+#ifndef APPID_DCERPC_EVENT_HANDLER_H
+#define APPID_DCERPC_EVENT_HANDLER_H
+
+#include "pub_sub/dcerpc_events.h"
+
+#include "appid_session.h"
+#include "service_plugins/service_detector.h"
+
+class DceExpSsnEventHandler : public snort::DataHandler
+{
+public:
+ DceExpSsnEventHandler() : DataHandler(MOD_NAME) { }
+
+ void handle(snort::DataEvent& event, snort::Flow* flow) override
+ {
+ assert(flow);
+
+ AppIdSession* asd = snort::appid_api.get_appid_session(*flow);
+ if (!asd)
+ return; // appid disabled
+
+ DceExpectedSessionEvent& map_resp_event = static_cast<DceExpectedSessionEvent&>(event);
+
+ const snort::Packet* pkt = map_resp_event.get_packet();
+ const snort::SfIp* src_ip = map_resp_event.get_src_ip();
+ const snort::SfIp* dst_ip = map_resp_event.get_dst_ip();
+ uint16_t src_port = map_resp_event.get_src_port();
+ uint16_t dst_port = map_resp_event.get_dst_port();
+ IpProtocol proto = map_resp_event.get_ip_proto();
+ SnortProtocolId protocol_id = map_resp_event.get_proto_id();
+
+ AppIdSession* fp = AppIdSession::create_future_session(pkt, src_ip, src_port,
+ dst_ip, dst_port, proto, protocol_id);
+
+ if (fp) // initialize data session
+ {
+ fp->service.set_id(APP_ID_DCE_RPC, asd->ctxt.get_odp_ctxt());
+ asd->initialize_future_session(*fp, APPID_SESSION_IGNORE_ID_FLAGS,
+ APP_ID_FROM_RESPONDER);
+ }
+ }
+};
+
+#endif // APPID_DCERPC_EVENT_HANDLER_H
#include "app_forecast.h"
#include "appid_data_decrypt_event_handler.h"
+#include "appid_dcerpc_event_handler.h"
#include "appid_debug.h"
#include "appid_discovery.h"
#include "appid_http_event_handler.h"
DataBus::subscribe_global(DATA_DECRYPT_EVENT, new DataDecryptEventHandler(), sc);
+ DataBus::subscribe_global(DCERPC_EXP_SESSION_EVENT_KEY, new DceExpSsnEventHandler(), sc);
+
return true;
}
AppIdSession* AppIdSession::create_future_session(const Packet* ctrlPkt, const SfIp* cliIp,
uint16_t cliPort, const SfIp* srvIp, uint16_t srvPort, IpProtocol proto,
- SnortProtocolId snort_protocol_id, int /*flags*/)
+ SnortProtocolId snort_protocol_id)
{
char src_ip[INET6_ADDRSTRLEN];
char dst_ip[INET6_ADDRSTRLEN];
return asd;
}
+void AppIdSession::initialize_future_session(AppIdSession& expected, uint64_t flags,
+ AppidSessionDirection dir)
+{
+ if (dir == APP_ID_FROM_INITIATOR)
+ {
+ expected.set_session_flags(flags |
+ get_session_flags(
+ APPID_SESSION_INITIATOR_CHECKED |
+ APPID_SESSION_INITIATOR_MONITORED |
+ APPID_SESSION_RESPONDER_CHECKED |
+ APPID_SESSION_RESPONDER_MONITORED));
+ }
+ else if (dir == APP_ID_FROM_RESPONDER)
+ {
+ if (get_session_flags(APPID_SESSION_INITIATOR_CHECKED))
+ flags |= APPID_SESSION_RESPONDER_CHECKED;
+
+ if (get_session_flags(APPID_SESSION_INITIATOR_MONITORED))
+ flags |= APPID_SESSION_RESPONDER_MONITORED;
+
+ if (get_session_flags(APPID_SESSION_RESPONDER_CHECKED))
+ flags |= APPID_SESSION_INITIATOR_CHECKED;
+
+ if (get_session_flags(APPID_SESSION_RESPONDER_MONITORED))
+ flags |= APPID_SESSION_INITIATOR_MONITORED;
+ }
+
+ expected.set_session_flags(flags |
+ get_session_flags(
+ APPID_SESSION_SPECIAL_MONITORED |
+ APPID_SESSION_DISCOVER_APP |
+ APPID_SESSION_DISCOVER_USER));
+
+ expected.service_disco_state = APPID_DISCO_STATE_FINISHED;
+ expected.client_disco_state = APPID_DISCO_STATE_FINISHED;
+}
void AppIdSession::reinit_session_data(AppidChangeBits& change_bits)
{
misc_app_id = APP_ID_NONE;
static AppIdSession* allocate_session(const snort::Packet*, IpProtocol,
AppidSessionDirection, AppIdInspector*);
static AppIdSession* create_future_session(const snort::Packet*, const snort::SfIp*, uint16_t,
- const snort::SfIp*,
- uint16_t, IpProtocol, SnortProtocolId, int);
+ const snort::SfIp*, uint16_t, IpProtocol, SnortProtocolId);
+ void initialize_future_session(AppIdSession&, uint64_t, AppidSessionDirection);
size_t size_of() override
{ return sizeof(*this); }
// snort_protocol_id.
AppIdSession* fp = AppIdSession::create_future_session(
- pkt, cliIp, cliPort, srvIp, srvPort, protocol, app_id,
- APPID_EARLY_SESSION_FLAG_FW_RULE);
+ pkt, cliIp, cliPort, srvIp, srvPort, protocol, app_id);
if ( fp )
{
// FIXIT-M : snort 2.9.x updated the flag to APPID_SESSION_EXPECTED_EVALUATE.
// Check if it is needed here as well.
- //initialize_expected_session(asd, fp, APPID_SESSION_EXPECTED_EVALUATE);
+ // asd.initialize_future_session(*fp, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
- initialize_expected_session(
- asd, *fp, APPID_SESSION_IGNORE_ID_FLAGS, APP_ID_APPID_SESSION_DIRECTION_MAX);
+ asd.initialize_future_session(*fp, APPID_SESSION_IGNORE_ID_FLAGS,
+ APP_ID_APPID_SESSION_DIRECTION_MAX);
}
// create an RTCP flow as well
AppIdSession* fp2 = AppIdSession::create_future_session(
- pkt, cliIp, cliPort + 1, srvIp, srvPort + 1, protocol, app_id,
- APPID_EARLY_SESSION_FLAG_FW_RULE);
+ pkt, cliIp, cliPort + 1, srvIp, srvPort + 1, protocol, app_id);
if ( fp2 )
{
fp2->service.set_id(APP_ID_RTCP, asd.ctxt.get_odp_ctxt());
// FIXIT-M : same comment as above
- //initialize_expected_session(asd, fp2, APPID_SESSION_EXPECTED_EVALUATE);
+ // asd.initialize_future_session(*fp2, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
- initialize_expected_session(
- asd, *fp2, APPID_SESSION_IGNORE_ID_FLAGS, APP_ID_APPID_SESSION_DIRECTION_MAX);
+ asd.initialize_future_session(*fp2, APPID_SESSION_IGNORE_ID_FLAGS,
+ APP_ID_APPID_SESSION_DIRECTION_MAX);
}
}
}
AppIdSession* fp = AppIdSession::create_future_session(lsd->ldp.pkt, &client_addr,
- client_port, &server_addr, server_port, proto, snort_protocol_id,
- APPID_EARLY_SESSION_FLAG_FW_RULE);
+ client_port, &server_addr, server_port, proto, snort_protocol_id);
if (fp)
{
fp->service.set_id(service_id, ud->get_odp_ctxt());
LuaDetectorManager::add_detector_flow(detector_flow);
detector_flow->asd = AppIdSession::create_future_session(lsd->ldp.pkt, &saddr, sport,
- &daddr, dport, proto, 0, 0);
+ &daddr, dport, proto, 0);
if (!detector_flow->asd)
{
{
return static_cast<ServiceDiscovery*>(handler)->fail_service(asd, pkt, dir, this);
}
-
-void ServiceDetector::initialize_expected_session(const AppIdSession& parent, AppIdSession& expected,
- uint64_t flags, AppidSessionDirection dir)
-{
- if (dir == APP_ID_FROM_INITIATOR)
- {
- expected.set_session_flags(flags |
- parent.get_session_flags(
- APPID_SESSION_INITIATOR_CHECKED |
- APPID_SESSION_INITIATOR_MONITORED |
- APPID_SESSION_RESPONDER_CHECKED |
- APPID_SESSION_RESPONDER_MONITORED));
- }
- else if (dir == APP_ID_FROM_RESPONDER)
- {
- if (parent.get_session_flags(APPID_SESSION_INITIATOR_CHECKED))
- flags |= APPID_SESSION_RESPONDER_CHECKED;
-
- if (parent.get_session_flags(APPID_SESSION_INITIATOR_MONITORED))
- flags |= APPID_SESSION_RESPONDER_MONITORED;
-
- if (parent.get_session_flags(APPID_SESSION_RESPONDER_CHECKED))
- flags |= APPID_SESSION_INITIATOR_CHECKED;
-
- if (parent.get_session_flags(APPID_SESSION_RESPONDER_MONITORED))
- flags |= APPID_SESSION_INITIATOR_MONITORED;
- }
-
- expected.set_session_flags(flags |
- parent.get_session_flags(
- APPID_SESSION_SPECIAL_MONITORED |
- APPID_SESSION_DISCOVER_APP |
- APPID_SESSION_DISCOVER_USER));
-
- expected.service_disco_state = APPID_DISCO_STATE_FINISHED;
- expected.client_disco_state = APPID_DISCO_STATE_FINISHED;
-}
#include "appid_detector.h"
#include "service_discovery.h"
-#define APPID_EARLY_SESSION_FLAG_FW_RULE 1
-
class ServiceDetector : public AppIdDetector
{
public:
asd.misc_app_id = miscId;
}
- void initialize_expected_session(const AppIdSession&, AppIdSession&, uint64_t flags, AppidSessionDirection dir);
-
private:
int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
const char* vendor, const char* version, AppidChangeBits& change_bits);
}
void FtpServiceDetector::create_expected_session(AppIdSession& asd, const Packet* pkt, const SfIp* cliIp,
- uint16_t cliPort, const SfIp* srvIp, uint16_t srvPort, IpProtocol protocol,
- int flags, AppidSessionDirection dir)
+ uint16_t cliPort, const SfIp* srvIp, uint16_t srvPort, IpProtocol protocol, AppidSessionDirection dir)
{
// FIXIT-M - Avoid thread locals
static THREAD_LOCAL SnortProtocolId ftp_data_snort_protocol_id = UNKNOWN_PROTOCOL_ID;
ftp_data_snort_protocol_id = pkt->context->conf->proto_ref->find("ftp-data");
AppIdSession* fp = AppIdSession::create_future_session(pkt, cliIp, cliPort, srvIp, srvPort,
- protocol, ftp_data_snort_protocol_id, flags);
+ protocol, ftp_data_snort_protocol_id);
if (fp) // initialize data session
{
fp->service.set_id(APP_ID_FTP_DATA, asd.ctxt.get_odp_ctxt());
}
- initialize_expected_session(asd, *fp, APPID_SESSION_IGNORE_ID_FLAGS | encrypted_flags, dir);
+ asd.initialize_future_session(*fp, APPID_SESSION_IGNORE_ID_FLAGS | encrypted_flags, dir);
}
}
&fd->address, &fd->port) == 0)
{
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
- create_expected_session(args.asd, args.pkt, dip, 0, &fd->address, fd->port, args.asd.protocol,
- APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_RESPONDER);
+ create_expected_session(args.asd, args.pkt, dip, 0, &fd->address, fd->port,
+ args.asd.protocol, APP_ID_FROM_RESPONDER);
WatchForCommandResult(fd, args.asd, FTP_CMD_PORT_EPRT);
}
}
&fd->address, &fd->port) == 0)
{
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
- create_expected_session(args.asd, args.pkt, dip, 0, &fd->address, fd->port, args.asd.protocol,
- APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_RESPONDER);
+ create_expected_session(args.asd, args.pkt, dip, 0, &fd->address, fd->port,
+ args.asd.protocol, APP_ID_FROM_RESPONDER);
WatchForCommandResult(fd, args.asd, FTP_CMD_PORT_EPRT);
}
}
addr = htonl(address);
ip.set(&addr, AF_INET);
create_expected_session(args.asd, args.pkt, dip, 0, &ip, port,
- args.asd.protocol, APPID_EARLY_SESSION_FLAG_FW_RULE,
- APP_ID_FROM_INITIATOR);
+ args.asd.protocol, APP_ID_FROM_INITIATOR);
if (!ip.fast_eq6(*sip))
{
create_expected_session(args.asd, args.pkt, dip, 0, sip, port,
- args.asd.protocol, APPID_EARLY_SESSION_FLAG_FW_RULE,
- APP_ID_FROM_INITIATOR);
+ args.asd.protocol, APP_ID_FROM_INITIATOR);
}
add_payload(args.asd, APP_ID_FTP_PASSIVE);
}
{
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
const SfIp* sip = args.pkt->ptrs.ip_api.get_src();
- create_expected_session(args.asd, args.pkt, dip, 0, sip, port, args.asd.protocol,
- APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_INITIATOR);
+ create_expected_session(args.asd, args.pkt, dip, 0, sip, port,
+ args.asd.protocol, APP_ID_FROM_INITIATOR);
add_payload(args.asd, APP_ID_FTP_PASSIVE);
}
private:
void create_expected_session(AppIdSession&, const snort::Packet*,
const snort::SfIp* cliIp, uint16_t cliPort, const snort::SfIp* srvIp,
- uint16_t srvPort, IpProtocol, int flags, AppidSessionDirection);
+ uint16_t srvPort, IpProtocol, AppidSessionDirection);
};
#endif
dip = args.pkt->ptrs.ip_api.get_dst();
sip = args.pkt->ptrs.ip_api.get_src();
AppIdSession* pf = AppIdSession::create_future_session(args.pkt, dip, 0, sip, (uint16_t)port,
- IpProtocol::TCP, rexec_snort_protocol_id, APPID_EARLY_SESSION_FLAG_FW_RULE);
+ IpProtocol::TCP, rexec_snort_protocol_id);
if (pf)
{
ServiceREXECData* tmp_rd = (ServiceREXECData*)snort_calloc(
}
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
- initialize_expected_session(args.asd, *pf, REXEC_EXPECTED_SESSION_FLAGS, APP_ID_FROM_RESPONDER);
+ args.asd.initialize_future_session(*pf, REXEC_EXPECTED_SESSION_FLAGS, APP_ID_FROM_RESPONDER);
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
rd->child = tmp_rd;
rd->state = REXEC_STATE_SERVER_CONNECT;
AppIdSession* pf = AppIdSession::create_future_session(
pkt, dip, 0, sip, (uint16_t)tmp,
- (IpProtocol)ntohl((uint32_t)rd->proto), sunrpc_snort_protocol_id, 0);
+ (IpProtocol)ntohl((uint32_t)rd->proto), sunrpc_snort_protocol_id);
if (pf)
{
pf->add_flow_data_id((uint16_t)tmp, this);
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
const SfIp* sip = args.pkt->ptrs.ip_api.get_src();
AppIdSession* pf = AppIdSession::create_future_session(args.pkt, dip, 0, sip,
- (uint16_t)port, IpProtocol::TCP, rsh_error_snort_protocol_id, APPID_EARLY_SESSION_FLAG_FW_RULE);
+ (uint16_t)port, IpProtocol::TCP, rsh_error_snort_protocol_id);
if (pf)
{
ServiceRSHELLData* tmp_rd = (ServiceRSHELLData*)snort_calloc(
return APPID_ENOMEM;
}
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
- initialize_expected_session(args.asd, *pf,
- APPID_SESSION_CONTINUE | APPID_SESSION_REXEC_STDERR | APPID_SESSION_NO_TPI |
+ args.asd.initialize_future_session(*pf, APPID_SESSION_CONTINUE | APPID_SESSION_REXEC_STDERR | APPID_SESSION_NO_TPI |
APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_PORT_SERVICE_DONE,
APP_ID_FROM_RESPONDER);
+
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
rd->child = tmp_rd;
rd->state = RSHELL_STATE_SERVER_CONNECT;
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
const SfIp* sip = args.pkt->ptrs.ip_api.get_src();
AppIdSession* pf = AppIdSession::create_future_session(args.pkt, dip, 0, sip,
- args.pkt->ptrs.sp, args.asd.protocol, snmp_snort_protocol_id, 0);
+ args.pkt->ptrs.sp, args.asd.protocol, snmp_snort_protocol_id);
if (pf)
{
tmp_sd = (ServiceSNMPData*)snort_calloc(sizeof(ServiceSNMPData));
tmp_sd->state = SNMP_STATE_ERROR;
return APPID_ENULL;
}
- initialize_expected_session(args.asd, *pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
+ args.asd.initialize_future_session(*pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
pf->common.initiator_ip = *sip;
dip = args.pkt->ptrs.ip_api.get_dst();
sip = args.pkt->ptrs.ip_api.get_src();
pf = AppIdSession::create_future_session(args.pkt, dip, 0, sip,
- args.pkt->ptrs.sp, args.asd.protocol, tftp_snort_protocol_id, APPID_EARLY_SESSION_FLAG_FW_RULE);
+ args.pkt->ptrs.sp, args.asd.protocol, tftp_snort_protocol_id);
if (pf)
{
data_add(*pf, tmp_td, &snort_free);
tmp_td->state = TFTP_STATE_ERROR;
return APPID_ENOMEM;
}
- initialize_expected_session(args.asd, *pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_FROM_RESPONDER);
+ args.asd.initialize_future_session(*pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_FROM_RESPONDER);
pf->common.initiator_ip = *sip;
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
)
-add_cpputest( appid_expected_flags_test
- SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
-)
-
add_cpputest( appid_http_event_test
SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
)
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2017-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.
-//--------------------------------------------------------------------------
-
-// appid_expected_flags_test.cc author maya dagon <mdagon@cisco.com>
-
-#include "network_inspectors/appid/appid_detector.cc"
-#include "network_inspectors/appid/service_plugins/service_detector.cc"
-
-#include "appid_mock_definitions.h"
-#include "appid_mock_inspector.h"
-#include "appid_mock_session.h"
-
-#include <CppUTest/CommandLineTestRunner.h>
-#include <CppUTest/TestHarness.h>
-
-snort::Inspector* snort::InspectorManager::get_inspector(
- char const*, bool, const snort::SnortConfig*) { return nullptr; }
-
-void ApplicationDescriptor::set_id(
- const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
-
-void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
-
-class MockServiceDetector : public ServiceDetector
-{
-public:
- int validate(AppIdDiscoveryArgs&) override { return 0; }
-};
-
-AppIdSession* parent = nullptr;
-AppIdSession* expected = nullptr;
-MockServiceDetector test_detector;
-
-uint64_t allFlags = APPID_SESSION_RESPONDER_MONITORED | APPID_SESSION_INITIATOR_MONITORED |
- APPID_SESSION_SPECIAL_MONITORED | APPID_SESSION_RESPONDER_CHECKED |
- APPID_SESSION_INITIATOR_CHECKED | APPID_SESSION_DISCOVER_APP |
- APPID_SESSION_DISCOVER_USER;
-
-static inline void cleanup()
-{
- parent->clear_session_flags(allFlags);
- expected->clear_session_flags(allFlags);
-}
-
-TEST_GROUP(appid_expected_flags)
-{
- void setup() override
- {
- MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
- parent = new AppIdSession(IpProtocol::TCP, nullptr, 1492, dummy_appid_inspector);
- expected = new AppIdSession(IpProtocol::TCP, nullptr, 1492, dummy_appid_inspector);
- }
-
- void teardown() override
- {
- delete parent;
- delete expected;
- MemoryLeakWarningPlugin::turnOnNewDeleteOverloads();
- }
-};
-
-TEST(appid_expected_flags, test1)
-{
- // Test 1 - expected flow same direction as parent, initiator monitored
- parent->set_session_flags(APPID_SESSION_INITIATOR_CHECKED | APPID_SESSION_INITIATOR_MONITORED);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_INITIATOR);
-
- CHECK(expected->get_session_flags(allFlags) ==
- (APPID_SESSION_INITIATOR_CHECKED | APPID_SESSION_INITIATOR_MONITORED));
-
- cleanup();
-}
-
-TEST(appid_expected_flags, test2)
-{
- // Test 2 - expected flow same direction as parent, responder monitored
- parent->set_session_flags(APPID_SESSION_RESPONDER_CHECKED | APPID_SESSION_RESPONDER_MONITORED);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_INITIATOR);
-
- CHECK(expected->get_session_flags(allFlags) ==
- (APPID_SESSION_RESPONDER_CHECKED | APPID_SESSION_RESPONDER_MONITORED));
-
- cleanup();
-}
-
-TEST(appid_expected_flags, test3)
-{
- // Test 3 - expected flow same direction as parent, all flags set
- parent->set_session_flags(allFlags);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_INITIATOR);
-
- CHECK(expected->get_session_flags(allFlags) == allFlags);
-
- cleanup();
-}
-
-TEST(appid_expected_flags, test4)
-{
- // Test 4 - expected flow opposite direction as parent, initiator monitored
- parent->set_session_flags(APPID_SESSION_INITIATOR_CHECKED | APPID_SESSION_INITIATOR_MONITORED);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_RESPONDER);
-
- CHECK(expected->get_session_flags(allFlags) ==
- (APPID_SESSION_RESPONDER_CHECKED | APPID_SESSION_RESPONDER_MONITORED));
-
- cleanup();
-}
-
-TEST(appid_expected_flags, test5)
-{
- // Test 5 - expected flow opposite direction as parent, responder monitored
- parent->set_session_flags(APPID_SESSION_RESPONDER_CHECKED | APPID_SESSION_RESPONDER_MONITORED);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_RESPONDER);
-
- CHECK(expected->get_session_flags(allFlags) ==
- (APPID_SESSION_INITIATOR_CHECKED | APPID_SESSION_INITIATOR_MONITORED));
-
- cleanup();
-}
-
-TEST(appid_expected_flags, test6)
-{
- // Test 6 - expected flow opposite direction as parent, all flags set
- parent->set_session_flags(allFlags);
- test_detector.initialize_expected_session(*parent, *expected, 0, APP_ID_FROM_RESPONDER);
-
- CHECK(expected->get_session_flags(allFlags) == allFlags);
-
- cleanup();
-}
-
-int main(int argc, char** argv)
-{
- mock_init_appid_pegs();
- int rc = CommandLineTestRunner::RunAllTests(argc, argv);
- mock_cleanup_appid_pegs();
- return rc;
-}
-
cip_events.h
data_decrypt_event.h
daq_message_event.h
+ dcerpc_events.h
expect_events.h
finalize_packet_event.h
http_events.h
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
+//--------------------------------------------------------------------------
+
+#ifndef DCERPC_EVENTS_H
+#define DCERPC_EVENTS_H
+
+#include "framework/data_bus.h"
+
+#define DCERPC_EXP_SESSION_EVENT_KEY "dcerpc_expected_session_event"
+
+namespace snort
+{
+struct SfIp;
+}
+
+class DceExpectedSessionEvent : public snort::DataEvent
+{
+public:
+
+ DceExpectedSessionEvent(snort::Packet* p,
+ const snort::SfIp* src_ip, const uint16_t src_port,
+ const snort::SfIp* dst_ip, const uint16_t dst_port,
+ IpProtocol proto, SnortProtocolId protocol_id) :
+ p(p), src_ip(src_ip), src_port(src_port),
+ dst_ip(dst_ip), dst_port(dst_port),
+ proto(proto), protocol_id(protocol_id) { }
+
+ const snort::Packet* get_packet() override
+ { return p; }
+
+ const snort::SfIp* get_src_ip() const
+ { return src_ip; }
+
+ const snort::SfIp* get_dst_ip() const
+ { return dst_ip; }
+
+ uint16_t get_src_port() const
+ { return src_port; }
+
+ uint16_t get_dst_port() const
+ { return dst_port; }
+
+ SnortProtocolId get_proto_id() const
+ { return protocol_id; }
+
+ IpProtocol get_ip_proto() const
+ { return proto; }
+
+private:
+ const snort::Packet* p;
+
+ const snort::SfIp* src_ip;
+ uint16_t src_port;
+
+ const snort::SfIp* dst_ip;
+ uint16_t dst_port;
+
+ IpProtocol proto;
+ SnortProtocolId protocol_id;
+};
+
+#endif // DCERPC_EVENTS_H
dce_common.h
dce_context_data.cc
dce_context_data.h
+ dce_expected_session.cc
+ dce_expected_session.h
dce_http_proxy.cc
dce_http_proxy_module.cc
dce_http_proxy_module.h
#include "utils/util.h"
+#include "dce_expected_session.h"
#include "dce_smb.h"
#include "dce_smb_module.h"
#include "dce_smb_utils.h"
#include "dce_tcp.h"
-#include "dce_tcp_module.h"
using namespace snort;
static THREAD_LOCAL int co_reassembled = 0;
+/* [MS-RPCE] 2.2.5 - 64-Bit Network Data Representation */
+static const Uuid uuid_ndr64 = { 0x71710533, 0xbeba, 0x4937, 0x83, 0x19,
+ { 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36 } };
+
+/********************************************************************
+ * Function: DCE2_CoEptMapResponse()
+ *
+ * Handles the processing of EPT_MAP response.
+ * The response consists of a tower array that embeds tower pointers.
+ * Pointers, in turn, consist of floors. Our target is 4 & 5 floors,
+ * which contain info about future sessions.
+ *
+ ********************************************************************/
+static void DCE2_CoEptMapResponse(const DCE2_CoTracker* cot, const DceRpcCoHdr* co_hdr,
+ const uint8_t* stub_data, uint16_t dlen)
+{
+ DCE2_CoCtxIdNode* ctx_id_node;
+ uint64_t actual_count;
+ uint64_t tptr_length; /* Tower pointer length */
+ unsigned int i;
+ int ndr_flen = 4; /* 4-bytes fields in default NDR */
+ int offset = 0;
+ int floor3_start;
+ int proto_offset;
+ int port_offset;
+ int ip_addr_offset;
+ uint16_t ept_port;
+ SfIp ept_ip_addr;
+ DceRpcBoFlag byte_order;
+
+ if (stub_data == nullptr || dlen == 0)
+ return;
+
+ ctx_id_node = (DCE2_CoCtxIdNode*)DCE2_ListFind(cot->ctx_ids,
+ (void*)(uintptr_t)cot->ctx_id);
+
+ if (ctx_id_node == nullptr)
+ return;
+
+ if (ctx_id_node->transport == DCE2_CO_CTX_TRANS_SYNTAX_NDR64)
+ ndr_flen = 8; /* 8-bytes fields in NDR64 */
+
+ /* 20 4
+ * +---------------------------------------+--------+
+ * | Handle | N Twrs |
+ * +---------------------------------------+--------+
+ * Length of the next fields depends on transport
+ * (NDR/NDR64, 4/8 bytes). Conformant & Varying Arr hdrs.
+ * +---------------+---------------+----------------+
+ * | Max Count | Offset | Actual Count |
+ * +---------------+---------------+----------------+ */
+ offset += DCE2_CO_MAP_HANDLE_OFS + DCE2_CO_MAP_NUM_TOWERS_OFS + 2 * ndr_flen;
+
+ /* Get the actual count of pointers in tower array */
+ byte_order = DceRpcCoByteOrder(co_hdr);
+ offset += DCE2_GetNdrUint3264(stub_data + offset, actual_count,
+ offset, byte_order, ctx_id_node->transport);
+
+ /* Skipping Referent IDs and moving to deferred pointers representation */
+ offset += actual_count * ndr_flen;
+ dce2_move(stub_data, dlen, offset);
+
+ for (i = 0; i < actual_count; i++)
+ {
+ int fc_offset;
+ uint16_t floor_count;
+ /* 4/8 4
+ * +---------------+--------+
+ * | Length | Length |
+ * +---------------+--------+
+ * The first len field seems to be a conformant array header,
+ * the second one tower length field.
+ * 2
+ * +-------------+---------+---------+---------+---------+
+ * | floor count | floor 1 | floor 2 | ... | floor n |
+ * +-------------+---------+---------+---------+---------+
+ * The target is 4th & 5th floors */
+
+ /* Get tower length and determine the floor count offset */
+ fc_offset = DCE2_GetNdrUint3264(stub_data, tptr_length,
+ offset, byte_order, ctx_id_node->transport) + DCE2_CO_MAP_TWR_LEN_OFS;
+ if (dlen < tptr_length)
+ return;
+
+ floor_count = DceRpcNtohs((const uint16_t*)(stub_data + fc_offset),
+ DceRpcCoByteOrder(co_hdr));
+
+ offset += fc_offset;
+ dce2_move(stub_data, dlen, fc_offset);
+
+ /* No needed data for the pinhole creation */
+ if (floor_count < 5)
+ continue;
+
+ floor3_start = 2 * DCE2_CO_MAP_TWR_FLOOR12_OFS +
+ DCE2_CO_MAP_FLR_COUNT_OFS;
+
+ /* Skipping 1st & 2nd floors up to 3rd floor protocol id */
+ proto_offset = floor3_start +
+ DCE2_CO_MAP_FLR_LHS_RHS_OFS;
+
+ /* Check protocol, expected to be connection-oriented */
+ if (*(stub_data + proto_offset) != DCE2_CO_PROTO_ID_CO)
+ return;
+
+ port_offset = floor3_start + DCE2_CO_MAP_TWR_FLOOR34_OFS +
+ 2 * DCE2_CO_MAP_FLR_LHS_RHS_OFS + DCE2_CO_MAP_FLR_PROTO_ID_OFS;
+
+ ip_addr_offset = port_offset +
+ DCE2_CO_MAP_TWR_FLOOR34_OFS;
+
+ ept_port = DceRpcNtohs((const uint16_t*)(stub_data + port_offset),
+ DCERPC_BO_FLAG__BIG_ENDIAN);
+
+ /* According to DCE RPC 1.1, host address is 4 octets, big-endian order */
+ ept_ip_addr.set(stub_data + ip_addr_offset, AF_INET);
+
+ DceExpSsnManager::create_expected_session(&ept_ip_addr, ept_port, DCE2_TCP_NAME);
+
+ offset += tptr_length;
+ dce2_move(stub_data, dlen, tptr_length);
+ }
+}
+
/********************************************************************
* Function: DCE2_CoInitTracker()
*
ctx_node->iface_vers_maj = if_vers_maj;
ctx_node->iface_vers_min = if_vers_min;
ctx_node->state = DCE2_CO_CTX_STATE__PENDING;
+ ctx_node->transport = DCE2_CO_CTX_TRANS_SYNTAX_NDR_DEF;
return ctx_node;
}
}
static void dce_co_process_ctx_result(DCE2_SsnData*, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr,DCE2_Policy policy, uint16_t result)
+ const DceRpcCoHdr* co_hdr, DCE2_Policy policy, uint16_t result,
+ const Uuid* transport)
{
DCE2_CoCtxIdNode* ctx_node, * existing_ctx_node;
DCE2_Ret status;
ctx_node->state = DCE2_CO_CTX_STATE__ACCEPTED;
if (DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK)
cot->got_bind = 1;
+
+ /* Need to check accepted transfer syntax
+ * for further EPT_MAP response parsing */
+ if (!DCE2_UuidCompare(transport, &uuid_ndr64))
+ {
+ ctx_node->transport = DCE2_CO_CTX_TRANS_SYNTAX_NDR64;
+ }
}
else
{
for (i = 0; i < num_ctx_results; i++)
{
const DceRpcCoContResult* ctx_result;
+ const Uuid* transport;
uint16_t result;
if (ctx_len < sizeof(DceRpcCoContResult))
return;
}
ctx_result = (const DceRpcCoContResult*)ctx_data;
+ transport = DceRpcCoContResTransport(ctx_result);
result = DceRpcCoContRes(co_hdr, ctx_result);
dce2_move(ctx_data, ctx_len, sizeof(DceRpcCoContResult));
if (DCE2_QueueIsEmpty(cot->pending_ctx_ids))
return;
- dce_co_process_ctx_result(sd,cot,co_hdr,policy,result);
+ dce_co_process_ctx_result(sd,cot,co_hdr,policy,result,transport);
}
}
(uint16_t)(frag_len - (uint16_t)auth_len));
}
}
+
+ /* If this is the last fragment, we can proceed with stub data processing */
+ if (DceRpcCoLastFrag(co_hdr))
+ {
+ const uint8_t* stub_data;
+ uint16_t stub_data_len;
+ if (DCE2_BufferIsEmpty(cot->frag_tracker.srv_stub_buf))
+ {
+ /* Data reassembled from multiple TSDUs */
+ stub_data = frag_ptr;
+ stub_data_len = frag_len;
+ }
+ else
+ {
+ /* Data received from single TSDU */
+ stub_data = cot->frag_tracker.srv_stub_buf->data;
+ stub_data_len = cot->frag_tracker.srv_stub_buf->len;
+ }
+
+ if (cot->opnum == DCE2_CO_EPT_MAP)
+ {
+ DCE2_CoEptMapResponse(cot, co_hdr, stub_data, stub_data_len);
+ }
+ }
}
/********************************************************************
#define DCE2_CO_FRAG_DIFF_OPNUM 38
#define DCE2_CO_FRAG_DIFF_CTX_ID 39
+/* Map response fields offsets */
+#define DCE2_CO_MAP_HANDLE_OFS 20
+#define DCE2_CO_MAP_NUM_TOWERS_OFS 4
+#define DCE2_CO_MAP_TWR_FLOOR12_OFS 25
+#define DCE2_CO_MAP_TWR_FLOOR34_OFS 7
+#define DCE2_CO_MAP_TWR_LEN_OFS 4
+#define DCE2_CO_MAP_FLR_COUNT_OFS 2
+#define DCE2_CO_MAP_FLR_LHS_RHS_OFS 2
+#define DCE2_CO_MAP_FLR_PROTO_ID_OFS 1
+
+/* Protocol IDs. Not a full list.
+ * Refer to DCE RPC 1.1 Appendix I */
+#define DCE2_CO_PROTO_DOD_TCP 0x07
+#define DCE2_CO_PROTO_ID_CO 0x0b
+
#define DCE2_CO_BAD_MAJOR_VERSION_STR "connection oriented DCE/RPC - invalid major version"
#define DCE2_CO_BAD_MINOR_VERSION_STR "connection oriented DCE/RPC - invalid minor version"
#define DCE2_CO_BAD_PDU_TYPE_STR "connection-oriented DCE/RPC - invalid PDU type"
DCE2_CO_CTX_STATE__PENDING
};
+enum DCE2_CoCtxTransport
+{
+ /* Default 32-Bit NDR defined in DCE RPC 1.1 */
+ DCE2_CO_CTX_TRANS_SYNTAX_NDR_DEF,
+ /* 64-Bit NDR defined in [MS-RPCE] */
+ DCE2_CO_CTX_TRANS_SYNTAX_NDR64
+};
+
+enum DCE2_CoEpmOpnum {
+ DCE2_CO_EPT_NONE = -1,
+ DCE2_CO_EPT_INSERT = 0,
+ DCE2_CO_EPT_DELETE,
+ DCE2_CO_EPT_LOOKUP,
+ DCE2_CO_EPT_MAP,
+ DCE2_CO_EPT_LKUP_HANDLE_FREE,
+ DCE2_CO_EPT_INQ_OBJECT,
+ DCE2_CO_EPT_MGMT_DELETE
+};
+
struct DCE2_CoCtxIdNode
{
uint16_t ctx_id; /* The context id */
/* Whether or not the server accepted or rejected the client bind/alter context
* request. Initially set to pending until server response */
DCE2_CoCtxState state;
+ DCE2_CoCtxTransport transport;
};
enum DceRpcCoAuthLevelType
return DceRpcNtohs(&cocr->result, DceRpcCoByteOrder(co));
}
+inline const Uuid* DceRpcCoContResTransport(const DceRpcCoContResult* cocr)
+{
+ return &cocr->transfer_syntax.if_uuid;
+}
+
inline int DceRpcCoObjectFlag(const DceRpcCoHdr* co)
{
return co->pfc_flags & DCERPC_CO_PFC_FLAGS__OBJECT_UUID;
return DceRpcNtohs(&cor->context_id, DceRpcCoByteOrder(co));
}
+inline int DCE2_GetNdrUint32(const uint8_t* data_ptr, uint32_t& data,
+ int offset, DceRpcBoFlag bo_flag)
+{
+ const uint32_t* ptr;
+ int align_offset = 0;
+
+ /* Alignment */
+ if (offset % 4)
+ {
+ align_offset = 4 - (offset % 4);
+ }
+
+ ptr = (const uint32_t*)(data_ptr + align_offset);
+ data = DceRpcNtohl(ptr, bo_flag);
+
+ return align_offset + 4;
+}
+
+inline int DCE2_GetNdrUint64(const uint8_t* data_ptr, uint64_t& data,
+ int offset, DceRpcBoFlag bo_flag)
+{
+ const uint64_t* ptr;
+ int align_offset = 0;
+
+ /* Alignment */
+ if (offset % 8)
+ {
+ align_offset = 8 - (offset % 8);
+ }
+
+ ptr = (const uint64_t*)(data_ptr + align_offset);
+ data = DceRpcNtohl64(ptr, bo_flag);
+
+ return align_offset + 8;
+}
+
+inline int DCE2_GetNdrUint3264(const uint8_t* data_ptr, uint64_t& data,
+ int offset, DceRpcBoFlag bo_flag, DCE2_CoCtxTransport transport)
+{
+ if (transport == DCE2_CO_CTX_TRANS_SYNTAX_NDR64)
+ return DCE2_GetNdrUint64(data_ptr, data, offset, bo_flag);
+
+ uint32_t val = 0;
+ offset = DCE2_GetNdrUint32(data_ptr, val, offset, bo_flag);
+ data = val;
+ return offset;
+}
+
void DCE2_CoInitTracker(DCE2_CoTracker*);
void DCE2_CoProcess(DCE2_SsnData*, DCE2_CoTracker*,
const uint8_t*, uint16_t);
--- /dev/null
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+//dce_expected_session.cc author Eduard Burmai <eburmai@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dce_expected_session.h"
+
+#include "managers/inspector_manager.h"
+#include "pub_sub/dcerpc_events.h"
+#include "stream/stream.h"
+
+#include "dce_tcp.h"
+
+using namespace snort;
+
+DceExpSsnManager::DceExpSsnManager(const char* protocol,
+ IpProtocol proto, PktType type): proto(proto), type(type)
+{
+ protocol_id = SnortConfig::get_conf()->proto_ref->add(protocol);
+}
+
+void DceExpSsnManager::create_expected_session(const SfIp* ept_ip,
+ uint16_t ept_port, const char* mod_name)
+{
+ Packet* pkt = DetectionEngine::get_current_packet();
+ Dce2Tcp* inspector = (Dce2Tcp*)InspectorManager::get_inspector(mod_name, true);
+ DceExpSsnManager& esm = inspector->get_esm();
+
+ const SfIp* src_ip = pkt->ptrs.ip_api.get_dst();
+ PktType type = esm.get_pkt_type();
+ IpProtocol proto = esm.get_ip_proto();
+ SnortProtocolId protocol_id = esm.get_proto_id();
+
+ if (esm.create_expected_session_impl(pkt, src_ip, 0,
+ ept_ip, ept_port, type, proto, protocol_id))
+ return;
+
+ dce2_tcp_stats.tcp_expected_sessions++;
+
+ DceExpectedSessionEvent map_resp_event(pkt, src_ip, 0,
+ ept_ip, ept_port, proto, protocol_id);
+ DataBus::publish(DCERPC_EXP_SESSION_EVENT_KEY, map_resp_event, pkt->flow);
+}
+
+DceTcpExpSsnManager::DceTcpExpSsnManager(dce2TcpProtoConf& config) :
+ DceExpSsnManager("dce-tcp", IpProtocol::TCP, PktType::TCP),
+ pc(config) { }
+
+int DceTcpExpSsnManager::create_expected_session_impl(Packet* pkt,
+ const snort::SfIp* src_ip, uint16_t src_port,
+ const snort::SfIp* dst_ip, uint16_t dst_port,
+ PktType type, IpProtocol proto, SnortProtocolId protocol_id)
+{
+ Dce2TcpFlowData* fd = new Dce2TcpFlowData;
+
+ fd->state = DCE2_TCP_FLOW__EXPECTED;
+ memset(&fd->dce2_tcp_session, 0, sizeof(DCE2_TcpSsnData));
+ DCE2_CoInitTracker(&fd->dce2_tcp_session.co_tracker);
+ DCE2_ResetRopts(&fd->dce2_tcp_session.sd, pkt);
+
+ fd->dce2_tcp_session.sd.trans = DCE2_TRANS_TYPE__TCP;
+ fd->dce2_tcp_session.sd.server_policy = pc.common.policy;
+ fd->dce2_tcp_session.sd.client_policy = DCE2_POLICY__WINXP;
+ fd->dce2_tcp_session.sd.config = (void*)&pc;
+
+ if (Stream::set_snort_protocol_id_expected(pkt, type,
+ proto, src_ip, src_port, dst_ip, dst_port, protocol_id, fd))
+ {
+ delete fd;
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+//dce_expected_session.h author Eduard Burmai <eburmai@cisco.com>
+
+#ifndef DCE_EXPECTED_SESSION_H
+#define DCE_EXPECTED_SESSION_H
+
+#include "framework/decode_data.h"
+#include "target_based/snort_protocols.h"
+
+namespace snort
+{
+struct Packet;
+struct SfIp;
+}
+
+struct dce2TcpProtoConf;
+
+// Expected Session Manager
+class DceExpSsnManager
+{
+public:
+ DceExpSsnManager(const char*, IpProtocol, PktType);
+ virtual ~DceExpSsnManager() = default;
+
+ SnortProtocolId get_proto_id() const
+ { return protocol_id; }
+
+ IpProtocol get_ip_proto() const
+ { return proto; }
+
+ PktType get_pkt_type() const
+ { return type; }
+
+ static void create_expected_session(const snort::SfIp*, uint16_t, const char*);
+
+private:
+ virtual int create_expected_session_impl(snort::Packet*,
+ const snort::SfIp*, uint16_t, const snort::SfIp*, uint16_t,
+ PktType, IpProtocol, SnortProtocolId) = 0;
+
+private:
+ SnortProtocolId protocol_id;
+ IpProtocol proto;
+ PktType type;
+};
+
+class DceTcpExpSsnManager : public DceExpSsnManager
+{
+public:
+ DceTcpExpSsnManager() = delete;
+ DceTcpExpSsnManager(dce2TcpProtoConf&);
+ DceTcpExpSsnManager(const DceTcpExpSsnManager&) = delete;
+ DceTcpExpSsnManager& operator=(const DceTcpExpSsnManager&) =delete;
+
+private:
+ int create_expected_session_impl(snort::Packet*,
+ const snort::SfIp*, uint16_t, const snort::SfIp*, uint16_t,
+ PktType, IpProtocol, SnortProtocolId) override;
+
+private:
+ const dce2TcpProtoConf& pc;
+};
+
+#endif // DCE_EXPECTED_SESSION_H
#include "dce_context_data.h"
#include "dce_common.h"
-#include "dce_tcp_module.h"
-#include "dce_tcp_paf.h"
using namespace snort;
DCE2_TcpSsnData* get_dce2_tcp_session_data(Flow* flow)
{
Dce2TcpFlowData* fd = (Dce2TcpFlowData*)flow->get_flow_data(Dce2TcpFlowData::inspector_id);
+
+ // check whether this session was expected and mark it as realized
+ if (fd && fd->state == DCE2_TCP_FLOW__EXPECTED)
+ {
+ fd->state = DCE2_TCP_FLOW__REALIZED;
+ dce2_tcp_stats.tcp_expected_realized_sessions++;
+ }
return fd ? &fd->dce2_tcp_session : nullptr;
}
{
Dce2TcpFlowData* fd = new Dce2TcpFlowData;
+ fd->state = DCE2_TCP_FLOW__COMMON;
memset(&fd->dce2_tcp_session,0,sizeof(DCE2_TcpSsnData));
p->flow->set_flow_data(fd);
return(&fd->dce2_tcp_session);
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
-
-class Dce2Tcp : public Inspector
-{
-public:
- Dce2Tcp(const dce2TcpProtoConf&);
-
- void show(const SnortConfig*) const override;
- void eval(Packet*) override;
- void clear(Packet*) override;
- StreamSplitter* get_splitter(bool c2s) override
- {
- return new Dce2TcpSplitter(c2s);
- }
-
-private:
- dce2TcpProtoConf config;
-};
-
-Dce2Tcp::Dce2Tcp(const dce2TcpProtoConf& pc)
-{
- config = pc;
-}
+Dce2Tcp::Dce2Tcp(const dce2TcpProtoConf& pc) :
+ config(pc), esm(config) { }
void Dce2Tcp::show(const SnortConfig*) const
{
#ifndef DCE_TCP_H
#define DCE_TCP_H
+#include "framework/inspector.h"
#include "profiler/profiler_defs.h"
#include "dce_co.h"
+#include "dce_expected_session.h"
+#include "dce_tcp_module.h"
+#include "dce_tcp_paf.h"
#define DCE2_TCP_NAME "dce_tcp"
#define DCE2_TCP_HELP "dce over tcp inspection"
/*DCE TCP specific*/
PegCount tcp_sessions;
+ PegCount tcp_expected_sessions;
+ PegCount tcp_expected_realized_sessions;
PegCount tcp_pkts;
PegCount concurrent_sessions;
PegCount max_concurrent_sessions;
DCE2_CoTracker co_tracker;
};
+enum DCE2_TcpFlowState
+{
+ DCE2_TCP_FLOW__COMMON,
+ DCE2_TCP_FLOW__EXPECTED,
+ DCE2_TCP_FLOW__REALIZED
+};
+
class Dce2TcpFlowData : public snort::FlowData
{
public:
public:
static unsigned inspector_id;
DCE2_TcpSsnData dce2_tcp_session;
+ DCE2_TcpFlowState state;
+};
+
+class Dce2Tcp : public snort::Inspector
+{
+public:
+ Dce2Tcp(const dce2TcpProtoConf&);
+
+ void show(const snort::SnortConfig*) const override;
+ void eval(snort::Packet*) override;
+ void clear(snort::Packet*) override;
+
+ DceTcpExpSsnManager& get_esm()
+ { return esm; }
+
+ snort::StreamSplitter* get_splitter(bool c2s) override
+ { return new Dce2TcpSplitter(c2s); }
+
+private:
+ dce2TcpProtoConf config;
+ DceTcpExpSsnManager esm;
};
DCE2_TcpSsnData* get_dce2_tcp_session_data(snort::Flow*);
{ CountType::SUM, "server_frags_reassembled",
"total connection-oriented server fragments reassembled" },
{ CountType::SUM, "tcp_sessions", "total tcp sessions" },
+ { CountType::SUM, "tcp_expected_sessions", "total tcp dynamic endpoint expected sessions" },
+ { CountType::SUM, "tcp_expected_realized", "total tcp dynamic endpoint expected realized sessions" },
{ CountType::SUM, "tcp_packets", "total tcp packets" },
{ CountType::NOW, "concurrent_sessions", "total concurrent sessions" },
{ CountType::MAX, "max_concurrent_sessions", "maximum concurrent sessions" },
return DceRpcNtohl(ptr, bo_flag);
}
+inline uint64_t DceRpcNtohl64(const uint64_t* ptr, const DceRpcBoFlag bo_flag)
+{
+ uint64_t value;
+
+ if (ptr == nullptr)
+ return 0;
+
+ value = *ptr;
+
+ if (bo_flag == DCERPC_BO_FLAG__NONE)
+ return value;
+
+#ifdef WORDS_BIGENDIAN
+ if (bo_flag == DCERPC_BO_FLAG__BIG_ENDIAN)
+#else
+ if (bo_flag == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+#endif /* WORDS_BIGENDIAN */
+ return value;
+
+ return ((value & 0xff00000000000000) >> 56) | ((value & 0x00ff000000000000) >> 40) |
+ ((value & 0x0000ff0000000000) >> 24) | ((value & 0x000000ff00000000) >> 8) |
+ ((value & 0x00000000000000ff) << 56) | ((value & 0x000000000000ff00) << 40) |
+ ((value & 0x0000000000ff0000) << 24) | ((value & 0x00000000ff000000) << 8);
+}
+
+inline uint64_t DceRpcHtonl64(const uint64_t* ptr, const DceRpcBoFlag bo_flag)
+{
+ return DceRpcNtohl64(ptr, bo_flag);
+}
+
inline void DCE2_CopyUuid(Uuid* dst_uuid, const Uuid* pkt_uuid, const DceRpcBoFlag byte_order)
{
dst_uuid->time_low = DceRpcNtohl(&pkt_uuid->time_low, byte_order);
}
#endif
-