#include "file_module.h"
#include "file_service.h"
#include "file_stats.h"
+#include <thread>
using namespace snort;
FileFlows::~FileFlows()
{
+ std::lock_guard<std::mutex> guard(file_flow_context_mutex);
FileCache* file_cache = FileService::get_file_cache();
assert(file_cache);
uint64_t file_id = 0;
FileFlows(Flow* f, FileInspect* inspect) : FlowData(file_flow_data_id, inspect), flow(f) { }
~FileFlows() override;
+ std::mutex file_flow_context_mutex;
static void init()
{ file_flow_data_id = FlowData::create_flow_data_id(); }
Dce2Smb2SessionCache smb2_session_cache(SMB_DEFAULT_MEMCAP);
-const char* smb2_command_string[SMB2_COM_MAX] = {
+const char* smb2_command_string[SMB2_COM_MAX] =
+{
"SMB2_COM_NEGOTIATE",
"SMB2_COM_SESSION_SETUP",
"SMB2_COM_LOGOFF",
{
tcp_file_tracker = nullptr;
flow_key = get_smb2_flow_key(tcp_flow->key);
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, "smb2 session created\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p,
+ "smb2 session created\n");
dce2_smb_stats.total_smb2_sessions++;
+ vlan_id = p->get_flow_vlan_id();
}
Dce2Smb2SessionData::~Dce2Smb2SessionData(void)
{
- session_data_mutex.lock();
for (auto it_session : connected_sessions)
{
it_session.second->detach_flow(flow_key);
if (get_tcp_file_tracker() && !(get_tcp_file_tracker()->get_flow_state_map().empty()))
{
get_tcp_file_tracker()->get_flow_state_map().erase(flow_key);
- tcp_file_tracker = nullptr;
}
- session_data_mutex.unlock();
+ if (tcp_file_tracker and tcp_file_tracker->get_flow_key() == flow_key )
+ tcp_file_tracker->set_flow_key(0);
+ tcp_file_tracker = nullptr;
}
void Dce2Smb2SessionData::reset_matching_tcp_file_tracker(
Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::find_session(uint64_t session_id)
{
- std::lock_guard<std::mutex> guard(session_data_mutex);
+ std::lock_guard<std::recursive_mutex> guard(session_data_mutex);
auto it_session = connected_sessions.find(session_id);
if (it_session != connected_sessions.end())
{
Dce2Smb2SessionTrackerPtr session = it_session->second;
//we already have the session, but call find to update the LRU
- smb2_session_cache.find_session(session->get_key(), this);
+ smb2_session_cache.find_session(session->get_key());
+ if (session->vlan_id != 0 and session->vlan_id !=
+ (DetectionEngine::get_current_packet()->get_flow_vlan_id()))
+ return nullptr;
return session;
}
else
{
Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_session(
- get_session_key(session_id), this);
- if (session)
+ get_session_key(session_id));
+ if (session and session->vlan_id != 0 and
+ session->vlan_id != (DetectionEngine::get_current_packet()->get_flow_vlan_id()))
+ {
connected_sessions.insert(std::make_pair(session_id,session));
- return session;
+ return session;
+ }
+ else
+ return nullptr;
}
}
Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::create_session(uint64_t session_id)
{
Smb2SessionKey session_key = get_session_key(session_id);
- std::lock_guard<std::mutex> guard(session_data_mutex);
- Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_else_create_session(session_key, this);
- connected_sessions.insert(std::make_pair(session_id, session));
+ Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_else_create_session(session_key,
+ this);
+ if (session)
+ {
+ connected_sessions.insert(std::make_pair(session_id, session));
+ session->vlan_id = DetectionEngine::get_current_packet()->get_flow_vlan_id();
+ }
return session;
}
-void Dce2Smb2SessionData::remove_session(uint64_t session_id, bool sync)
+void Dce2Smb2SessionData::remove_session(uint64_t session_id)
{
- if (sync) session_data_mutex.lock();
+ session_data_mutex.lock();
connected_sessions.erase(session_id);
- if (sync) session_data_mutex.unlock();
+ session_data_mutex.unlock();
}
void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
if (smb_data + SMB2_ ## cmd ## _ ## type ## _STRUC_SIZE - 1 > end) \
{ \
dce2_smb_stats.v2_ ## counter ## _hdr_err++; \
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, GET_CURRENT_PACKET, \
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, \
+ GET_CURRENT_PACKET, \
"%s : smb data beyond end detected\n", \
smb2_command_string[command]); \
if (session) \
if (SMB2_COMMAND_TYPE(ERROR, RESPONSE) and Smb2Error(smb_hdr)) \
{ \
dce2_smb_stats.v2_ ## counter ## _err_resp++; \
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET, "%s_RESP: error\n", \
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET, \
+ "%s_RESP: error\n", \
smb2_command_string[command]); \
if (session) \
{ \
{ \
dce2_smb_stats.v2_ ## counter ## _inv_str_sz++; \
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL \
- , GET_CURRENT_PACKET, "%s: invalid struct size\n", \
+ , GET_CURRENT_PACKET, "%s: invalid struct size\n", \
smb2_command_string[command]); \
- if (session) \
+ if (session) \
{ \
session->set_do_not_delete(false); \
session->set_prev_comand(SMB2_COM_MAX); \
flow_key, Smb2Mid(smb_hdr), session_id, Smb2Tid(smb_hdr));
// Handling case of two threads trying to do close same session at a time
- session = find_session(session_id);
+ session = smb2_session_cache.find(get_session_key(session_id));
+ if (session and connected_sessions.size() < 9)
+ connected_sessions.insert(std::make_pair(session_id, session));
if ((command == SMB2_COM_CLOSE or command ==
- SMB2_COM_TREE_DISCONNECT) and (session and session->get_prev_command() != SMB2_COM_MAX))
+ SMB2_COM_TREE_DISCONNECT)and (session and session->get_prev_command() != SMB2_COM_MAX))
{
return;
}
case SMB2_COM_NEGOTIATE:
if (SMB2_COMMAND_TYPE(NEGOTIATE, RESPONSE))
{
- const Smb2NegotiateResponseHdr* neg_resp_hdr = (const Smb2NegotiateResponseHdr*)smb_data;
+ const Smb2NegotiateResponseHdr* neg_resp_hdr = (const
+ Smb2NegotiateResponseHdr*)smb_data;
if (neg_resp_hdr->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)
{
//total multichannel sessions
Dce2SmbFlowData* fd = create_expected_smb_flow_data(p);
if (fd)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+ GET_CURRENT_PACKET,
"Requesting for expected smb flow\n");
int result = Stream::set_snort_protocol_id_expected(p, PktType::TCP,
- IpProtocol::TCP, p->ptrs.ip_api.get_dst() , 0 ,p->ptrs.ip_api.get_src(),
- p->flow->server_port , snort_protocol_id_smb, fd, false, true);
+ IpProtocol::TCP, p->ptrs.ip_api.get_dst(), 0,p->ptrs.ip_api.get_src(),
+ p->flow->server_port, snort_protocol_id_smb, fd, false, true);
if (result < 0)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+ GET_CURRENT_PACKET,
"Failed to create expected smb flow\n");
delete fd;
}
}
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+ GET_CURRENT_PACKET,
"fd is null in negotiate , failed to create pinhole\n");
}
}
}
else if (!SMB2_COMMAND_TYPE(SETUP, REQUEST))
SMB2_HANDLE_INVALID_STRUC_SIZE(setup)
- break;
+ break;
case SMB2_COM_LOGOFF:
dce2_smb_stats.v2_logoff++;
if (SMB2_COMMAND_TYPE(LOGOFF, REQUEST))
- {
- session_data_mutex.lock();
smb2_session_cache.remove(get_session_key(session_id));
- session_data_mutex.unlock();
- }
else
SMB2_HANDLE_INVALID_STRUC_SIZE(logoff)
- break;
+ break;
//commands processed by session
case SMB2_COM_TREE_CONNECT:
dce2_smb_stats.v2_tree_cnct++;
SMB2_HANDLE_HEADER_ERROR(TREE_CONNECT, RESPONSE, tree_cnct_resp)
if (!session)
session = create_session(session_id);
+ if (!session)
+ return;
session->process(command, SMB2_CMD_TYPE_RESPONSE, smb_hdr, end, flow_key);
}
else if (!SMB2_COMMAND_TYPE(TREE_CONNECT,REQUEST))
SMB2_HANDLE_INVALID_STRUC_SIZE(tree_cnct)
- break;
+ break;
case SMB2_COM_TREE_DISCONNECT:
dce2_smb_stats.v2_tree_discn++;
uint8_t command_type = SMB2_GET_COMMAND_TYPE(CREATE);
if (SMB2_CMD_TYPE_INVALID == command_type)
SMB2_HANDLE_INVALID_STRUC_SIZE(crt)
- else if (SMB2_COMMAND_TYPE(CREATE, REQUEST))
- SMB2_HANDLE_HEADER_ERROR(CREATE, REQUEST, crt_req)
- else if (SMB2_COMMAND_TYPE(CREATE, RESPONSE))
- SMB2_HANDLE_HEADER_ERROR(CREATE, RESPONSE, crt_resp)
+ else if (SMB2_COMMAND_TYPE(CREATE, REQUEST))
+ SMB2_HANDLE_HEADER_ERROR(CREATE, REQUEST, crt_req)
+ else if (SMB2_COMMAND_TYPE(CREATE, RESPONSE))
+ SMB2_HANDLE_HEADER_ERROR(CREATE, RESPONSE, crt_resp)
+ if (!session)
+ session = create_session(session_id);
if (!session)
- session = create_session(session_id);
+ return;
session->process(command, command_type, smb_hdr, end, flow_key);
}
- break;
+ break;
case SMB2_COM_CLOSE:
dce2_smb_stats.v2_cls++;
}
else
SMB2_HANDLE_INVALID_STRUC_SIZE(read)
- session->process(command, command_type, smb_hdr, end, flow_key);
+ session->process(command, command_type, smb_hdr, end, flow_key);
}
else
dce2_smb_stats.v2_session_ignored++;
}
else
SMB2_HANDLE_INVALID_STRUC_SIZE(wrt)
- session->process(command, command_type, smb_hdr, end, flow_key);
+ session->process(command, command_type, smb_hdr, end, flow_key);
}
else
dce2_smb_stats.v2_session_ignored++;
return;
}
const Smb2Hdr* smb_hdr = (const Smb2Hdr*)(data_ptr + sizeof(NbssHdr));
- const Smb2TransformHdr* smb_trans_hdr = (const Smb2TransformHdr*)(data_ptr + sizeof(NbssHdr));
+ const Smb2TransformHdr* smb_trans_hdr = (const Smb2TransformHdr*)(data_ptr +
+ sizeof(NbssHdr));
uint32_t smb_proto_id = SmbTransformId(smb_trans_hdr);
uint64_t sid = smb_trans_hdr->session_id;
if (smb_proto_id == DCE2_SMB2_TRANS_ID)
session = find_session(sid);
if (session)
{
- bool flag = session->get_encryption_flag();
- if (!flag)
- session->set_encryption_flag(true);
+ bool flag = session->get_encryption_flag();
+ if (!flag)
+ session->set_encryption_flag(true);
}
}
uint32_t next_command_offset;
{
dce_alert(GID_DCE2, DCE2_SMB_BAD_NEXT_COMMAND_OFFSET,
(dce2CommonStats*)&dce2_smb_stats, sd);
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
- TRACE_ERROR_LEVEL, p, "bad next command offset\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
+ TRACE_ERROR_LEVEL, p, "bad next command offset\n");
dce2_smb_stats.v2_bad_next_cmd_offset++;
if (session)
session->set_do_not_delete(false);
if (compound_request_index > get_smb_max_compound())
{
dce2_smb_stats.v2_cmpnd_req_lt_crossed++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
- TRACE_INFO_LEVEL, p, "compound request limit"
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
+ TRACE_INFO_LEVEL, p, "compound request limit"
" reached %" PRIu8 "\n",compound_request_index);
if (session)
session->set_do_not_delete(false);
{
if ( tcp_file_tracker )
{
- session = find_session (tcp_file_tracker->get_session_id());
+ session = smb2_session_cache.find(get_session_key(tcp_file_tracker->get_session_id()));
if (session)
session->set_do_not_delete(true);
+ else
+ return;
}
else
return;
if ( tcp_file_tracker and tcp_file_tracker.use_count() >
1 and tcp_file_tracker->accepting_raw_data_from(flow_key))
{
- SMB_DEBUG(dce_smb_trace,DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p, "processing raw data for file id %" PRIu64 "\n",
+ SMB_DEBUG(dce_smb_trace,DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
+ "processing raw data for file id %" PRIu64 "\n",
tcp_file_tracker->get_file_id());
tcp_file_tracker->process_data(flow_key, data_ptr, data_len, session);
tcp_file_tracker->stop_accepting_raw_data_from(flow_key);
}
else
{
- SMB_DEBUG(dce_smb_trace,DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p, "not processing raw data\n");
+ SMB_DEBUG(dce_smb_trace,DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
+ "not processing raw data\n");
}
tcp_file_tracker_mutex.unlock();
}
read->length = alignedNtohs(&co_len);
}
}
+
using Dce2Smb2SessionTrackerPtr = std::shared_ptr<Dce2Smb2SessionTracker>;
using Dce2Smb2SessionTrackerMap =
- std::unordered_map<uint64_t, Dce2Smb2SessionTrackerPtr, std::hash<uint64_t> >;
+ std::unordered_map<uint64_t, Dce2Smb2SessionTrackerPtr, std::hash<uint64_t> >;
using Dce2Smb2FileTrackerPtr = std::shared_ptr<Dce2Smb2FileTracker>;
using Dce2Smb2FileTrackerMap =
- std::unordered_map<uint64_t, Dce2Smb2FileTrackerPtr, std::hash<uint64_t> >;
+ std::unordered_map<uint64_t, Dce2Smb2FileTrackerPtr, std::hash<uint64_t> >;
PADDING_GUARD_BEGIN
struct Smb2SessionKey
Dce2Smb2SessionData(const snort::Packet*, const dce2SmbProtoConf* proto);
~Dce2Smb2SessionData() override;
void process() override;
- void remove_session(uint64_t, bool = false);
+ void remove_session(uint64_t);
void handle_retransmit(FilePosition, FileVerdict) override { }
void reset_matching_tcp_file_tracker(Dce2Smb2FileTrackerPtr);
void set_reassembled_data(uint8_t*, uint16_t) override;
uint32_t get_flow_key() { return flow_key; }
void set_tcp_file_tracker(Dce2Smb2FileTrackerPtr file_tracker)
{
- std::lock_guard<std::mutex> guard(session_data_mutex);
tcp_file_tracker = file_tracker;
}
}
Dce2Smb2SessionTrackerPtr find_session(uint64_t);
+ std::recursive_mutex session_data_mutex;
+ uint16_t vlan_id;
private:
void process_command(const Smb2Hdr*, const uint8_t*);
Smb2SessionKey get_session_key(uint64_t);
Dce2Smb2SessionTrackerPtr create_session(uint64_t);
-
Dce2Smb2FileTrackerPtr tcp_file_tracker;
uint32_t flow_key;
Dce2Smb2SessionTrackerMap connected_sessions;
- std::mutex session_data_mutex;
std::mutex tcp_file_tracker_mutex;
};
using Dce2Smb2SessionDataMap =
- std::unordered_map<uint32_t, Dce2Smb2SessionData*, std::hash<uint32_t> >;
+ std::unordered_map<uint32_t, Dce2Smb2SessionData*, std::hash<uint32_t> >;
#endif /* _DCE_SMB2_H_ */
#include "dce_smb2.h"
#include "dce_smb2_session.h"
#include "dce_smb2_tree.h"
+#include "dce_smb2_session_cache.h"
+#include "flow/flow.h"
+#include <thread>
+#include "time/packet_time.h"
#include <mutex>
using namespace snort;
#define UNKNOWN_FILE_SIZE (~0)
-void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow, uint64_t offset, Dce2Smb2FileTrackerPtr file_tracker)
+void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow, uint64_t offset,
+ Dce2Smb2FileTrackerPtr file_tracker)
{
if (flow)
{
+ std::lock_guard<std::recursive_mutex> guard(flow->session_data_mutex);
uint32_t current_flow_key = flow->get_flow_key();
- std::lock_guard<std::mutex> guard(flow_state_mutex);
+ std::lock_guard<std::mutex> guard1(flow_state_mutex);
tcp_flow_state& current_flow_state = flow_state[current_flow_key];
- if ( (current_flow_state.pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA) and
- (current_flow_state.file_offset == current_flow_state.max_offset))
+ if ( (current_flow_state.pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA)and
+ (current_flow_state.file_offset == current_flow_state.max_offset))
{
current_flow_state.file_offset = offset;
}
flow->set_tcp_file_tracker(file_tracker);
}
}
+
void Dce2Smb2FileTracker::stop_accepting_raw_data_from(uint32_t current_flow_key)
{
std::lock_guard<std::mutex> guard(flow_state_mutex);
tcp_flow_state& current_flow_state = flow_state[current_flow_key];
- if(current_flow_state.file_offset == current_flow_state.max_offset)
+ if (current_flow_state.file_offset == current_flow_state.max_offset)
current_flow_state.pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
}
std::pair<bool, Dce2Smb2SessionData*> Dce2Smb2FileTracker::update_processing_flow(
Dce2Smb2SessionData* current_flow,Dce2Smb2SessionTrackerPtr session_tracker)
{
- std::lock_guard<std::mutex> guard(process_file_mutex);
bool switched = false;
- Dce2Smb2SessionData* processing_flow;
- if (session_tracker)
- processing_flow = session_tracker->get_flow(file_flow_key);
- else
- processing_flow = parent_tree->get_parent()->get_flow(file_flow_key);
-
+ Dce2Smb2SessionData* processing_flow = nullptr;
+ std::lock_guard<std::recursive_mutex> guard1(session_tracker->attached_flows_mutex);
+ auto it_flow = session_tracker->attached_flows.find(file_flow_key);
+ if (it_flow != session_tracker->attached_flows.end())
+ processing_flow = (it_flow != session_tracker->attached_flows.end()) ? it_flow->second :
+ nullptr;
+ if (processing_flow)
+ {
+ if (session_tracker->vlan_id != processing_flow->vlan_id)
+ processing_flow = nullptr;
+ else
+ {
+ processing_flow->session_data_mutex.lock();
+ if (processing_flow->get_tcp_flow()->session_state & STREAM_STATE_CLOSED or
+ processing_flow->get_tcp_flow()->session_state & STREAM_STATE_RELEASING)
+ {
+ processing_flow->session_data_mutex.unlock();
+ return std::make_pair(switched, nullptr);
+ }
+ }
+ }
if (!processing_flow)
{
switched = true;
else
{
Flow* flow = DetectionEngine::get_current_packet()->flow;
- Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(Dce2SmbFlowData::inspector_id));
- processing_flow = (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (current_flow_data)
+ processing_flow = (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
+ }
+ if (processing_flow)
+ {
+ file_flow_key = processing_flow->get_flow_key();
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
+ "updating the processing flow key to %u\n", file_flow_key);
}
- file_flow_key = processing_flow->get_flow_key();
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
- "updating the processing flow key to %u\n", file_flow_key);
}
+ if (processing_flow and processing_flow->get_tcp_flow())
+ processing_flow->get_tcp_flow()->last_data_seen = packet_time();
+
+ if (processing_flow and processing_flow->get_tcp_flow())
+ {
+ processing_flow->get_tcp_flow()->last_data_seen = packet_time();
+ }
+ if (processing_flow)
+ processing_flow->session_data_mutex.unlock();
return std::make_pair(switched, processing_flow);
}
file_name_hash = str_to_hash((uint8_t*)file_name, file_name_len);
}
file_size = size_v;
- auto updated_flow = update_processing_flow();
- Flow* flow = updated_flow.second->get_tcp_flow();
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
{
std::lock_guard<std::mutex> guard(process_file_mutex);
FileContext* file = get_smb_file_context(flow, file_name_hash, file_id, true);
ignore = false;
if (file->verdict == FILE_VERDICT_UNKNOWN)
{
- if ((file_name_v and name_len_v) or updated_flow.first)
+ if ((file_name_v and name_len_v))
file->set_file_name(file_name, file_name_len);
file->set_file_size(size_v ? size_v : UNKNOWN_FILE_SIZE);
}
if (!ignore and !file_size and file_offset)
{
file_size = file_offset;
- Dce2Smb2SessionData* processing_flow = update_processing_flow().second;
- Flow* flow = processing_flow->get_tcp_flow();
+ std::lock_guard<std::recursive_mutex> guard1(
+ get_parent()->get_parent()->attached_flows_mutex);
+ Dce2Smb2SessionData* current_flow;
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return false;
+ current_flow = (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
+ Dce2Smb2SessionTracker* sess = parent_tree->get_parent();
+ Dce2Smb2SessionTrackerPtr ses_ptr = smb2_session_cache.find_id(sess->get_key());
+ Dce2Smb2SessionData* processing_flow = update_processing_flow(current_flow,
+ ses_ptr).second;
+ if (!processing_flow)
+ return false;
+ flow = processing_flow->get_tcp_flow();
{
std::lock_guard<std::mutex> guard(process_file_mutex);
FileContext* file = get_smb_file_context(flow, file_name_hash, file_id, false);
if (file)
file->set_file_size(file_size);
}
- Dce2Smb2SessionTrackerPtr ses_ptr = processing_flow->find_session(session_id);
- return (!process_data(current_flow_key, nullptr, 0,ses_ptr));
+ return (!process_data(current_flow_key, nullptr, 0, ses_ptr));
}
return true;
}
current_flow_state.file_offset = offset;
current_flow_state.max_offset = offset + max_offset;
flow_state_mutex.unlock();
+ Dce2Smb2SessionTrackerPtr ses_ptr = nullptr;
Dce2Smb2SessionTracker* sess = parent_tree->get_parent();
+ if (!sess)
+ return false;
+ ses_ptr = smb2_session_cache.find_id(sess->get_key());
+ if (ses_ptr.use_count() < 2)
+ return false;
if (parent_tree->get_share_type() != SMB2_SHARE_TYPE_DISK)
{
Dce2Smb2SessionData* current_flow = nullptr;
- if (sess)
- {
- parent_tree->get_parent()->set_do_not_delete(true);
- current_flow = parent_tree->get_parent()->get_flow(current_flow_key);
- if (!current_flow)
- {
- parent_tree->get_parent()->set_do_not_delete(false);
- return false;
- }
- }
- else
- {
+ if (ses_ptr.use_count() < 2)
+ return false;
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return false;
+ current_flow = (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
+ if (!current_flow)
return false;
- }
-
if (data_size > UINT16_MAX)
{
data_size = UINT16_MAX;
}
- if (parent_tree->get_cotracker())
- {
+ current_flow->session_data_mutex.lock();
+ if (current_flow->get_tcp_flow())
+ current_flow->get_tcp_flow()->last_data_seen = packet_time();
+
+ if (parent_tree->get_cotracker())
+ {
sess->co_tracker_mutex.lock();
DCE2_CoProcess(current_flow->get_dce2_session_data(), parent_tree->get_cotracker(),
file_data, data_size);
- sess->co_tracker_mutex.unlock();
- }
- parent_tree->get_parent()->set_do_not_delete(false);
+ sess->co_tracker_mutex.unlock();
+ }
+ current_flow->session_data_mutex.unlock();
return true;
}
- Dce2Smb2SessionData *current_flow = sess->get_flow(current_flow_key);
- Dce2Smb2SessionTrackerPtr ses_ptr = current_flow->find_session(session_id);
- return process_data(current_flow_key, file_data, data_size,ses_ptr);
+ return process_data(current_flow_key, file_data, data_size, ses_ptr);
}
bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const uint8_t* file_data,
uint32_t data_size,Dce2Smb2SessionTrackerPtr session_tracker)
{
- Dce2Smb2SessionData *current_flow;
- if (session_tracker)
- {
- session_tracker->set_do_not_delete(true);
- current_flow = session_tracker->get_flow(current_flow_key);
- }
- else
- return false;
-
- if (!current_flow)
- {
- session_tracker->set_do_not_delete(false);
- return true;
- }
-
+ if (!session_tracker or session_tracker.use_count() < 2)
+ return false;
+ std::lock_guard<std::recursive_mutex> guard1(session_tracker->attached_flows_mutex);
+ Dce2Smb2SessionData* current_flow;
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return false;
+ current_flow = (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
int64_t file_detection_depth = current_flow->get_smb_file_depth();
int64_t detection_size = 0;
- Packet* p = DetectionEngine::get_current_packet();
+
flow_state_mutex.lock();
uint64_t file_offset = flow_state[current_flow_key].file_offset;
flow_state_mutex.unlock();
if (detection_size)
{
set_file_data(file_data, (detection_size > UINT16_MAX) ?
- UINT16_MAX : (uint16_t)detection_size, file_id);
+ UINT16_MAX : (uint16_t)detection_size);
file_detect();
}
{
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p,
"file name not set , ignored\n");
- session_tracker->set_do_not_delete(false);
return true;
}
if (file_size and file_offset > file_size)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p, "file_process: bad offset\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p,
+ "file_process: bad offset\n");
dce_alert(GID_DCE2, DCE2_SMB_INVALID_FILE_OFFSET, (dce2CommonStats*)
&dce2_smb_stats, *(current_flow->get_dce2_session_data()));
}
+ if (session_tracker.use_count() < 2)
+ return false;
auto updated_flow = update_processing_flow(current_flow, session_tracker);
Dce2Smb2SessionData* processing_flow = updated_flow.second;
-
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,"file_process fid %" PRIu64 " data_size %"
- PRIu32 " offset %" PRIu64 "\n", file_id, data_size, file_offset);
+ if (!processing_flow)
+ return false;
+ if ( !processing_flow->get_tcp_flow())
+ return false;
+ processing_flow->session_data_mutex.lock();
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
+ "file_process fid %" PRIu64 " data_size %" PRIu32 " offset %" PRIu64 "\n", file_id,
+ data_size, file_offset);
{
- std::lock_guard<std::mutex> guard(process_file_mutex);
+ if (processing_flow->get_tcp_flow()->session_state & STREAM_STATE_CLOSED or
+ processing_flow->get_tcp_flow()->session_state & STREAM_STATE_RELEASING)
+ {
+ processing_flow->session_data_mutex.unlock();
+ return true;
+ }
FileFlows* file_flows = FileFlows::get_file_flows(processing_flow->get_tcp_flow());
if (!file_flows)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, p, "file_flows not found\n");
- session_tracker->set_do_not_delete(false);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, p,
+ "file_flows not found\n");
+ processing_flow->session_data_mutex.unlock();
return true;
}
- if (updated_flow.first)
{
- // update the new file context in case of flow switch
- FileContext* file = file_flows->get_file_context(file_name_hash, true, file_id);
- file->set_file_name(file_name, file_name_len);
- file->set_file_size(file_size.load() ? file_size.load() : UNKNOWN_FILE_SIZE);
- }
- FileFlows::get_file_flows(p->flow);
- bool continue_processing = file_flows->file_process(p, file_name_hash, file_data, data_size,
- file_offset, direction, file_id);
-
- if (!continue_processing)
- {
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p, "file_process completed\n");
- session_tracker->set_do_not_delete(false);
- return false;
+ std::lock_guard<std::mutex> guard(file_flows->file_flow_context_mutex);
+
+ if (updated_flow.first)
+ {
+ // update the new file context in case of flow switch
+ FileContext* file = file_flows->get_file_context(file_name_hash, true, file_id);
+ file->set_file_name(file_name, file_name_len);
+ file->set_file_size(file_size.load() ? file_size.load() : UNKNOWN_FILE_SIZE);
+ }
+ FileFlows::get_file_flows(p->flow);
+ bool continue_processing = file_flows->file_process(p, file_name_hash, file_data,
+ data_size,
+ file_offset, direction, file_id);
+
+ if (!continue_processing)
+ {
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
+ "file_process completed\n");
+ processing_flow->session_data_mutex.unlock();
+ return false;
+ }
}
}
flow_state_mutex.lock();
flow_state[current_flow_key].file_offset = file_offset;
flow_state_mutex.unlock();
- session_tracker->set_do_not_delete(false);
+ processing_flow->session_data_mutex.unlock();
return true;
}
file_id(file_idv), file_size(0), file_name_hash(0), file_name(nullptr),
direction(FILE_DOWNLOAD), parent_tree(p_tree), session_id(sid)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
"file tracker %" PRIu64 " created\n", file_id);
}
std::lock_guard<std::mutex> guard(flow_state_mutex);
return (flow_state[current_flow_key].pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA);
}
+
void stop_accepting_raw_data_from(uint32_t);
void set_direction(FileDirection dir) { direction = dir; }
return flow_state;
}
+ uint32_t get_flow_key()
+ {
+ return file_flow_key;
+ }
+
+ void set_flow_key(uint32_t key)
+ {
+ file_flow_key = key;
+ }
+
private:
void file_detect();
std::pair<bool, Dce2Smb2SessionData*> update_processing_flow(Dce2Smb2SessionData* = nullptr,
using Dce2Smb2FileTrackerPtr = std::shared_ptr<Dce2Smb2FileTracker>;
using Dce2Smb2FileTrackerMap =
- std::unordered_map<uint64_t, Dce2Smb2FileTrackerPtr, std::hash<uint64_t> >;
+ std::unordered_map<uint64_t, Dce2Smb2FileTrackerPtr, std::hash<uint64_t> >;
#endif
Dce2Smb2RequestTracker(uint64_t file_id_v, uint64_t offset_v = 0)
: fname(nullptr), fname_len(0), file_id(file_id_v), offset(offset_v)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "request tracker created\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+ "request tracker created\n");
}
Dce2Smb2RequestTracker(char* fname_v, uint16_t fname_len_v)
: fname(fname_v), fname_len(fname_len_v), file_id(0), offset(0)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET, "request tracker created\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+ "request tracker created\n");
}
~Dce2Smb2RequestTracker()
uint64_t offset;
};
+using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
using Dce2Smb2RequestTrackerMap =
- std::unordered_map<Smb2MessageKey, Dce2Smb2RequestTracker*, Smb2KeyHash>;
+ std::unordered_map<Smb2MessageKey, Dce2Smb2RequestTrackerPtr, Smb2KeyHash>;
#endif
#include "file_api/file_flows.h"
+#include <numeric>
+
uint32_t Smb2Tid(const Smb2Hdr* hdr)
{
return snort::alignedNtohl(&(((const Smb2SyncHdr*)hdr)->tree_id));
Dce2Smb2SessionData* Dce2Smb2SessionTracker::get_flow(uint32_t flow_key)
{
- std::lock_guard<std::mutex> guard(attached_flows_mutex);
+ std::lock_guard<std::recursive_mutex> guard(attached_flows_mutex);
auto it_flow = attached_flows.find(flow_key);
return (it_flow != attached_flows.end()) ? it_flow->second : nullptr;
}
std::lock_guard<std::mutex> guard(connected_trees_mutex);
for (auto it_tree : connected_trees)
{
- Dce2Smb2RequestTracker* request = it_tree.second->find_request(message_id, flow_key);
+ Dce2Smb2RequestTrackerPtr request = it_tree.second->find_request(message_id, flow_key);
if (request)
return it_tree.second;
}
return nullptr;
}
+uint32_t Dce2Smb2SessionTracker::fill_map(const uint64_t msg_id, const uint8_t command_type, const
+ uint32_t current_flow_key)
+{
+ std::lock_guard<std::mutex> guard(mid_mutex);
+ auto it = mid_map.find(current_flow_key);
+ msgid_state* mid_ptr;
+ if (it == mid_map.end())
+ {
+ mid_ptr = new msgid_state { 0, 0, { 0 }, { 0 }
+ };
+ mid_map.insert(std::make_pair(current_flow_key, mid_ptr));
+ }
+ else
+ mid_ptr = it->second;
+ if (command_type == SMB2_CMD_TYPE_REQUEST)
+ {
+ if (msg_id > mid_ptr->max_req_msg_id)
+ {
+ const int size = msg_id-(mid_ptr->max_req_msg_id)-1;
+ std::vector<uint64_t> v(size);
+ std::iota(v.begin(), v.end(), mid_ptr->max_req_msg_id+1);
+ mid_ptr->missing_req_msg_ids.insert(v.begin (), v.end ());
+ mid_ptr->max_req_msg_id = msg_id;
+ }
+ else
+ {
+ if (mid_ptr->missing_req_msg_ids.find(msg_id) == mid_ptr->missing_req_msg_ids.end())
+ {
+ return 1;
+ }
+ else
+ {
+ mid_ptr->missing_req_msg_ids.erase(msg_id);
+ }
+ }
+ }
+ if (command_type == SMB2_CMD_TYPE_RESPONSE)
+ {
+ if (msg_id > mid_ptr->max_resp_msg_id)
+ {
+ const int size = msg_id-(mid_ptr->max_resp_msg_id)-1;
+ std::vector<uint64_t> v(size);
+ std::iota(v.begin(), v.end(), mid_ptr->max_resp_msg_id+1);
+ mid_ptr->missing_resp_msg_ids.insert(v.begin (), v.end ());
+ mid_ptr->max_resp_msg_id = msg_id;
+ }
+ else
+ {
+ if (mid_ptr->missing_resp_msg_ids.find(msg_id) == mid_ptr->missing_resp_msg_ids.end())
+ {
+ return 1;
+ }
+ else
+ {
+ mid_ptr->missing_resp_msg_ids.erase(msg_id);
+ }
+ }
+ }
+ return 0;
+}
+
void Dce2Smb2SessionTracker::process(const uint16_t command, uint8_t command_type,
const Smb2Hdr* smb_header, const uint8_t* end, const uint32_t current_flow_key)
{
tree = find_tree_for_message(Smb2Mid(smb_header), current_flow_key);
}
+ if (fill_map(Smb2Mid(smb_header), command_type, current_flow_key))
+ {
+ dce2_smb_stats.ignore_dup_sessions++;
+ return;
+ }
+
switch (command)
{
case SMB2_COM_TREE_CONNECT:
{
uint8_t share_type = ((const Smb2TreeConnectResponseHdr*)
((const uint8_t*)smb_header + SMB2_HEADER_LENGTH))->share_type;
- connect_tree(tree_id, current_flow_key, share_type);
+ connect_tree(tree_id, share_type);
}
break;
case SMB2_COM_TREE_DISCONNECT:
{
- if (!tree)
- dce2_smb_stats.v2_tree_discn_ignored++;
+ if (!tree)
+ dce2_smb_stats.v2_tree_discn_ignored++;
}
break;
case SMB2_COM_CREATE:
if (!tree and SMB2_CMD_TYPE_REQUEST == command_type)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
- TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
+ TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
"%s_REQ: mid-stream session detected\n",
smb2_command_string[command]);
- tree = connect_tree(tree_id, current_flow_key);
+ tree = connect_tree(tree_id);
if (!tree)
{
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
tree->process(command, command_type, smb_header, end, current_flow_key);
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
TRACE_ERROR_LEVEL, GET_CURRENT_PACKET,
"%s: tree tracker missing\n", smb2_command_string[command]);
dce2_smb_stats.v2_tree_ignored++;
}
Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::connect_tree(const uint32_t tree_id,
- const uint32_t current_flow_key, const uint8_t share_type)
+ const uint8_t share_type)
{
- Dce2Smb2SessionData* current_flow = get_flow(current_flow_key);
- if ((SMB2_SHARE_TYPE_DISK == share_type) and current_flow and
- (-1 == current_flow->get_max_file_depth()) and
- (-1 == current_flow->get_smb_file_depth()))
- {
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
- TRACE_INFO_LEVEL, GET_CURRENT_PACKET, "Not inserting TID (%u) "
- "because it's not IPC and not inspecting normal file data.\n", tree_id);
- dce2_smb_stats.v2_tree_cnct_ignored++;
- return nullptr;
- }
Dce2Smb2TreeTrackerPtr tree;
connected_trees_mutex.lock();
auto it_tree = connected_trees.find(tree_id);
return tree;
}
-void Dce2Smb2SessionTracker::clean_file_context_from_flow(uint64_t file_id, uint64_t
- file_name_hash)
-{
- set_do_not_delete(true);
- attached_flows_mutex.lock();
- for (auto it_flow : attached_flows)
- {
- if (get_file_context_cleaned())
- {
- attached_flows_mutex.unlock();
- set_do_not_delete(false);
- return;
- }
- snort::FileFlows* file_flows = snort::FileFlows::get_file_flows(
- it_flow.second->get_tcp_flow(), false);
- if (file_flows)
- file_flows->remove_processed_file_context(file_name_hash, file_id);
- }
- attached_flows_mutex.unlock();
- set_do_not_delete(false);
-}
-
void Dce2Smb2SessionTracker::increase_size(const size_t size)
{
smb2_session_cache.increase_size(size);
smb2_session_cache.decrease_size(size);
}
-void Dce2Smb2SessionTracker::unlink()
-{
- attached_flows_mutex.lock();
- for (auto it_flow : attached_flows)
- it_flow.second->remove_session(session_id, reload_prune.load());
- attached_flows_mutex.unlock();
-}
-
// Session Tracker is created and destroyed only from session cache
Dce2Smb2SessionTracker::~Dce2Smb2SessionTracker(void)
{
fcfs_mutex.unlock();
return;
}
-
- connected_trees_mutex.lock();
- auto it_tree = connected_trees.begin();
- while (it_tree != connected_trees.end())
- {
- auto next_it_tree = std::next(it_tree);
- it_tree->second->close_all_files();
- disconnect_tree(it_tree->second->get_tree_id());
- it_tree = next_it_tree;
- }
- connected_trees_mutex.unlock();
+ disconnect_tree();
+ free_map();
do_not_delete = false;
fcfs_mutex.unlock();
+ std::lock_guard<std::recursive_mutex> guard(attached_flows_mutex);
+ attached_flows.clear();
}
uint32_t Smb2Tid(const Smb2Hdr* hdr);
+typedef struct _msgid_state
+{
+ uint64_t max_req_msg_id;
+ uint64_t max_resp_msg_id;
+ std::unordered_set<uint64_t> missing_req_msg_ids;
+ std::unordered_set<uint64_t> missing_resp_msg_ids;
+} msgid_state;
+
class Dce2Smb2SessionTracker
{
public:
file_context_cleaned = false;
command_prev = SMB2_COM_MAX;
encryption_flag = false;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
"session tracker %" PRIu64 "created\n", session_id);
}
~Dce2Smb2SessionTracker();
- Dce2Smb2TreeTrackerPtr connect_tree(const uint32_t, const uint32_t,
+ Dce2Smb2TreeTrackerPtr connect_tree(const uint32_t,
uint8_t=SMB2_SHARE_TYPE_DISK);
- void disconnect_tree(uint32_t tree_id)
+
+ void disconnect_tree()
{
- connected_trees.erase(tree_id);
- decrease_size(sizeof(Dce2Smb2TreeTracker));
+ std::lock_guard<std::mutex> guard(connected_trees_mutex);
+ auto it_tree = connected_trees.begin();
+ while (it_tree != connected_trees.end())
+ {
+ auto next_it_tree = std::next(it_tree);
+ it_tree->second->close_all_files();
+ connected_trees.erase(it_tree->second->get_tree_id());
+ decrease_size(sizeof(Dce2Smb2TreeTracker));
+ it_tree = next_it_tree;
+ }
}
void attach_flow(uint32_t flow_key, Dce2Smb2SessionData* ssd)
{
- std::lock_guard<std::mutex> guard(attached_flows_mutex);
- attached_flows.insert(std::make_pair(flow_key,ssd));
+ std::lock_guard<std::recursive_mutex> guard(attached_flows_mutex);
+ if (attached_flows.find(flow_key) == attached_flows.end())
+ {
+ attached_flows.insert(std::make_pair(flow_key, ssd));
+ }
}
bool detach_flow(uint32_t flow_key)
{
- std::lock_guard<std::mutex> guard(attached_flows_mutex);
- attached_flows.erase(flow_key);
+ std::lock_guard<std::recursive_mutex> guard(attached_flows_mutex);
+ if (attached_flows.size()<2)
+ attached_flows.clear();
+ else
+ {
+ attached_flows.erase(flow_key);
+ attached_flows[flow_key] = nullptr;
+ }
+ free_one_flow_map(flow_key);
return (0 == attached_flows.size());
}
+ void free_one_flow_map(uint32_t flow_key)
+ {
+ std::lock_guard<std::mutex> guard(mid_mutex);
+ auto it = mid_map.find(flow_key);
+ if (it != mid_map.end())
+ {
+ delete it->second;
+ mid_map.erase(it);
+ }
+ }
+
+ void free_map()
+ {
+ std::lock_guard<std::mutex> guard(mid_mutex);
+ std::vector<msgid_state*> mid_ptrs;
+ auto it_map = mid_map.begin();
+ while (it_map != mid_map.end())
+ {
+ mid_ptrs.push_back(it_map->second);
+ it_map = mid_map.erase(it_map);
+ }
+ for (msgid_state* it_msg_id : mid_ptrs)
+ {
+ delete it_msg_id;
+ }
+ }
+
Smb2SessionKey get_key() { return session_key; }
- void clean_file_context_from_flow(uint64_t, uint64_t);
- void unlink();
Dce2Smb2SessionData* get_flow(uint32_t);
void process(const uint16_t, uint8_t, const Smb2Hdr*, const uint8_t*, const uint32_t);
void increase_size(const size_t size);
void set_prev_comand(uint16_t cmd) { command_prev = cmd; }
uint16_t get_prev_command() { return command_prev; }
std::mutex co_tracker_mutex;
- void set_encryption_flag(bool flag)
- {
- encryption_flag = flag;
- if (flag)
- dce2_smb_stats.total_encrypted_sessions++;
+ void set_encryption_flag(bool flag)
+ {
+ encryption_flag = flag;
+ if (flag)
+ dce2_smb_stats.total_encrypted_sessions++;
}
+
bool get_encryption_flag() { return encryption_flag; }
Dce2Smb2TreeTrackerPtr find_tree_for_tree_id(const uint32_t);
+ uint32_t fill_map(const uint64_t msg_id, const uint8_t command_type, const uint32_t
+ current_flow_key);
+ std::recursive_mutex attached_flows_mutex;
+ uint16_t vlan_id = 0;
+ Dce2Smb2SessionDataMap attached_flows;
+
private:
// do_not_delete is to make sure when we are in processing we should not delete the context
// which is being processed
//to keep the tab of previous command
uint16_t command_prev;
Smb2SessionKey session_key;
- Dce2Smb2SessionDataMap attached_flows;
Dce2Smb2TreeTrackerMap connected_trees;
std::atomic<bool> reload_prune;
std::atomic<bool> encryption_flag;
std::mutex connected_trees_mutex;
- std::mutex attached_flows_mutex;
- // fcfs_mutex is to make sure the mutex is taken at first come first basis if code
+
+ // fcfs_mutex is to make sure the mutex is taken at first come first basis if code
// is being hit by two different paths
std::mutex fcfs_mutex;
+ std::mutex mid_mutex;
+ std::unordered_map<uint32_t, msgid_state*, std::hash<uint32_t> > mid_map;
};
#endif
#include "hash/lru_cache_shared.h"
#include "dce_smb2_session.h"
-
#define SMB_AVG_FILES_PER_SESSION 5
template<typename Key, typename Value, typename Hash, typename Eq = std::equal_to<Key>,
- typename Purgatory = std::vector<std::shared_ptr<Value> > >
+typename Purgatory = std::vector<std::shared_ptr<Value> > >
class Dce2Smb2SharedCache : public LruCacheShared<Key, Value, Hash, Eq, Purgatory>
{
public:
return session;
}
- Data find_session(Key key, Dce2Smb2SessionData* ssd)
+ Data find_session(Key key)
{
Data session = this->find(key);
- if (session)
- session->attach_flow(ssd->get_flow_key(), ssd);
return session;
}
Data find_else_create_session(Key& key, Dce2Smb2SessionData* ssd)
{
Data new_session = Data(new Value(key));
- Data session = this->find_else_insert(key, new_session, nullptr);
- session->attach_flow(ssd->get_flow_key(), ssd);
- return session;
+ Data session = this->find_else_insert(key, new_session, nullptr,false);
+ if (new_session == session)
+ {
+ session->attach_flow(ssd->get_flow_key(), ssd);
+ return session;
+ }
+ return nullptr;
}
size_t mem_size() override
{
assert(current_size >= sizeof(*value_ptr) );
current_size -= sizeof(*value_ptr);
- //This is going down, remove references from flow here
- value_ptr->unlink();
}
}
};
using Dce2Smb2SessionCache =
- Dce2Smb2SharedCache<Smb2SessionKey, Dce2Smb2SessionTracker, Smb2KeyHash>;
+ Dce2Smb2SharedCache<Smb2SessionKey, Dce2Smb2SessionTracker, Smb2KeyHash>;
extern Dce2Smb2SessionCache smb2_session_cache;
auto it_file = opened_files.begin();
while (it_file != opened_files.end())
{
- get_parent()->clean_file_context_from_flow(it_file->second->get_file_id(),
- it_file->second->get_file_name_hash());
it_file = opened_files.erase(it_file);
}
tree_tracker_mutex.unlock();
}
-Dce2Smb2RequestTracker* Dce2Smb2TreeTracker::find_request(const uint64_t message_id,
+Dce2Smb2RequestTrackerPtr Dce2Smb2TreeTracker::find_request(const uint64_t message_id,
const uint32_t current_flow_key)
{
Smb2MessageKey message_key = { message_id, current_flow_key, 0 };
auto request_it = active_requests.find(message_key);
if (request_it != active_requests.end())
{
- delete request_it->second;
return active_requests.erase(message_key);
}
return false;
else
{
dce2_smb_stats.v2_stinf_req_ftrkr_misng++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
GET_CURRENT_PACKET, "%s_REQ: ftracker missing\n",
smb2_command_string[SMB2_COM_SET_INFO]);
}
}
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
GET_CURRENT_PACKET, "%s_REQ: header error\n",
smb2_command_string[SMB2_COM_SET_INFO]);
dce2_smb_stats.v2_stinf_req_hdr_err++;
{
const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
uint64_t file_id = alignedNtohq(&(((const Smb2CloseRequestHdr*)
- smb_data)->fileId_persistent));
+ smb_data)
+ ->fileId_persistent));
do_not_delete_tree = true;
Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
if (!file_tracker)
{
dce2_smb_stats.v2_cls_req_ftrkr_misng++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
- GET_CURRENT_PACKET, "%s_REQ: ftracker missing %" PRIu64 "\n",
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET, "%s_REQ: ftracker missing %" PRIu64 "\n",
smb2_command_string[SMB2_COM_CLOSE], file_id);
do_not_delete_tree = false;
return;
uint32_t data_length = alignedNtohl(&context->data_length);
/* Check for general error condition */
- if (((next & 0x7) != 0) or (next > remaining) or (name_offset != 16) or
- (name_length != 4) or (name_offset + name_length > remaining) or
- ((data_offset & 0x7) != 0) or
- (data_offset and (data_offset < name_offset + name_length)) or
- (data_offset > remaining) or (data_offset + data_length > remaining))
+ if (((next & 0x7) != 0)or (next > remaining) or (name_offset != 16) or
+ (name_length != 4) or (name_offset + name_length > remaining) or
+ ((data_offset & 0x7) != 0) or
+ (data_offset and (data_offset < name_offset + name_length)) or
+ (data_offset > remaining) or (data_offset + data_length > remaining))
{
return 0;
}
if ((strncmp((const char*)context+name_offset,
- SMB2_CREATE_DURABLE_RECONNECT_V2, name_length) == 0) or
- (strncmp((const char*)context+name_offset,
+ SMB2_CREATE_DURABLE_RECONNECT_V2, name_length) == 0)or
+ (strncmp((const char*)context+name_offset,
SMB2_CREATE_DURABLE_RECONNECT, name_length) == 0))
{
return alignedNtohq((const uint64_t*)(((const uint8_t*)context) +
file_size = alignedNtohq((const uint64_t*)(&(create_res_hdr->end_of_file)));
if (create_res_hdr->file_attributes & SMB2_CREATE_RESPONSE_DIRECTORY)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
GET_CURRENT_PACKET, "%s_RESP: not processing for directory\n",
- smb2_command_string[SMB2_COM_CREATE]);
+ smb2_command_string[SMB2_COM_CREATE]);
close_file(file_id, true);
}
else
{
do_not_delete_tree = true;
- Dce2Smb2RequestTracker* create_request = find_request(message_id, current_flow_key);
+ Dce2Smb2RequestTrackerPtr create_request = find_request(message_id, current_flow_key);
if (create_request)
{
Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
}
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, GET_CURRENT_PACKET, "%s_RESP: req tracker missing\n",
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET, "%s_RESP: req tracker missing\n",
smb2_command_string[SMB2_COM_CREATE]);
dce2_smb_stats.v2_crt_rtrkr_misng++;
}
const Smb2CreateRequestHdr* create_req_hdr = (const Smb2CreateRequestHdr*)smb_data;
if (alignedNtohs(&(create_req_hdr->name_offset)) <= SMB2_HEADER_LENGTH)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
GET_CURRENT_PACKET, "%s_REQ: name_offset %" PRIu16 "\n",
- smb2_command_string[SMB2_COM_CREATE], create_req_hdr->name_offset);
+ smb2_command_string[SMB2_COM_CREATE], create_req_hdr->name_offset);
dce2_smb_stats.v2_crt_req_hdr_err++;
return;
}
create_req_hdr->name_offset;
uint16_t file_name_size = alignedNtohs(&(create_req_hdr->name_length));
if (!file_name_size or (file_name_offset >= end) or
- (file_name_offset + file_name_size > end))
+ (file_name_offset + file_name_size > end))
{
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, GET_CURRENT_PACKET,
"%s_REQ: invalid file name data seen with size %" PRIu16 "\n",
uint16_t name_len = 0;
char* file_name = get_smb_file_name(file_name_offset, file_name_size, true, &name_len);
//keep a request tracker with the available info
- Dce2Smb2RequestTracker* create_request = new Dce2Smb2RequestTracker(file_name, name_len);
+ Dce2Smb2RequestTrackerPtr create_request = std::make_shared<Dce2Smb2RequestTracker>(file_name,
+ name_len);
if (!store_request(message_id, current_flow_key, create_request))
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
GET_CURRENT_PACKET, "SMB2_COM_CREATE_REQ: store failed\n");
- delete create_request;
}
//check if file_id is available form a durable reconnect request.
//if present we can create a file tracker right now.
const Smb2ReadResponseHdr* read_resp_hdr = (const Smb2ReadResponseHdr*)smb_data;
uint16_t data_offset = alignedNtohs((const uint16_t*)(&(read_resp_hdr->data_offset)));
- Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return;
+ Dce2Smb2SessionData* current_flow =
+ (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
if (data_offset + (const uint8_t*)smb_header > end)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: bad offset\n");
- if (current_flow)
- dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats,
- *current_flow->get_dce2_session_data());
+ dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats,
+ *current_flow->get_dce2_session_data());
}
do_not_delete_tree = true;
- Dce2Smb2RequestTracker* read_request = find_request(message_id, current_flow_key);
+ Dce2Smb2RequestTrackerPtr read_request = find_request(message_id, current_flow_key);
if (!read_request)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: request tracker missing\n");
dce2_smb_stats.v2_read_rtrkr_misng++;
do_not_delete_tree = false;
}
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
- GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: file tracker missing\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: file tracker missing\n");
}
do_not_delete_tree = false;
}
const Smb2ReadRequestHdr* read_req_hdr = (const Smb2ReadRequestHdr*)smb_data;
uint64_t file_id = alignedNtohq((const uint64_t*)(&(read_req_hdr->fileId_persistent)));
uint64_t offset = alignedNtohq((const uint64_t*)(&(read_req_hdr->offset)));
- Dce2Smb2RequestTracker* read_request = new Dce2Smb2RequestTracker(file_id, offset);
+ Dce2Smb2RequestTrackerPtr read_request = std::make_shared<Dce2Smb2RequestTracker>(file_id,
+ offset);
if (!store_request(message_id, current_flow_key, read_request))
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
- GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: store failed\n");
- delete read_request;
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+ GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: store failed\n");
}
do_not_delete_tree = true;
Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
- Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return;
+ Dce2Smb2SessionData* current_flow =
+ (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
if (file_tracker)
{
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
const Smb2WriteRequestHdr* write_req_hdr = (const Smb2WriteRequestHdr*)smb_data;
uint64_t file_id = alignedNtohq((const uint64_t*)(&(write_req_hdr->fileId_persistent)));
- Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return;
+ Dce2Smb2SessionData* current_flow =
+ (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
if ((alignedNtohs((const uint16_t*)(&(write_req_hdr->data_offset))) +
- (const uint8_t*)smb_header > end) and current_flow)
+ (const uint8_t*)smb_header > end))
{
SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
GET_CURRENT_PACKET, "SMB2_COM_WRITE_REQ: bad offset\n");
*current_flow->get_dce2_session_data());
}
//track this request to clean up opened file in case of error response
- Dce2Smb2RequestTracker* write_request = new Dce2Smb2RequestTracker(file_id);
+ Dce2Smb2RequestTrackerPtr write_request = std::make_shared<Dce2Smb2RequestTracker>(file_id);
if (!store_request(message_id, current_flow_key, write_request))
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
- GET_CURRENT_PACKET, "SMB2_COM_WRITE_REQ: store failed\n");
- delete write_request;
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET, "SMB2_COM_WRITE_REQ: store failed\n");
}
const uint8_t* file_data = (const uint8_t*)write_req_hdr + SMB2_WRITE_REQUEST_STRUC_SIZE - 1;
do_not_delete_tree = true;
}
else
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
- GET_CURRENT_PACKET,"SMB2_COM_WRITE_REQ: file tracker missing\n");
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET,"SMB2_COM_WRITE_REQ: file tracker missing\n");
}
do_not_delete_tree = false;
}
void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
- const uint32_t current_flow_key, const Smb2Hdr* smb_header, const uint8_t* end)
+ const Smb2Hdr* smb_header, const uint8_t* end)
{
const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
const uint8_t structure_size = (command_type == SMB2_CMD_TYPE_REQUEST) ?
if (SMB2_CMD_TYPE_REQUEST == command_type)
{
const Smb2IoctlRequestHdr* ioctl_req = (const Smb2IoctlRequestHdr*)smb_data;
- if ((ioctl_req->ctl_code != FSCTL_PIPE_PEEK) and (ioctl_req->ctl_code !=
+ if ((ioctl_req->ctl_code != FSCTL_PIPE_PEEK)and (ioctl_req->ctl_code !=
FSCTL_PIPE_WAIT) and (ioctl_req->ctl_code != FSCTL_PIPE_TRANSCEIVE))
{
return;
if (SMB2_CMD_TYPE_RESPONSE == command_type)
{
const Smb2IoctlResponseHdr* ioctl_response = (const Smb2IoctlResponseHdr*)smb_data;
- if ((ioctl_response->ctl_code != FSCTL_PIPE_PEEK) and (ioctl_response->ctl_code !=
+ if ((ioctl_response->ctl_code != FSCTL_PIPE_PEEK)and (ioctl_response->ctl_code !=
FSCTL_PIPE_WAIT) and (ioctl_response->ctl_code != FSCTL_PIPE_TRANSCEIVE))
{
return;
}
const uint8_t* file_data = (const uint8_t*)smb_data + structure_size - 1;
int data_size = end - file_data;
- Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
+ Packet* p = DetectionEngine::get_current_packet();
if (data_size > UINT16_MAX)
{
data_size = UINT16_MAX;
if (co_tracker)
{
parent_session->co_tracker_mutex.lock();
- DCE2_CoProcess(current_flow->get_dce2_session_data(), co_tracker, file_data, data_size);
+ DCE2_CoProcess(get_dce2_session_data(p->flow), co_tracker, file_data, data_size);
parent_session->co_tracker_mutex.unlock();
}
}
void Dce2Smb2TreeTracker::process(uint16_t command, uint8_t command_type,
const Smb2Hdr* smb_header, const uint8_t* end, const uint32_t current_flow_key)
{
- Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
tree_tracker_mutex.lock();
size_t pending_requests = active_requests.size();
tree_tracker_mutex.unlock();
+ Packet* p = DetectionEngine::get_current_packet();
+ Flow* flow = p->flow;
+ Dce2SmbFlowData* current_flow_data = (Dce2SmbFlowData*)(flow->get_flow_data(
+ Dce2SmbFlowData::inspector_id));
+ if (!current_flow_data)
+ return;
+ Dce2Smb2SessionData* current_flow =
+ (Dce2Smb2SessionData*)current_flow_data->get_smb_session_data();
if (SMB2_CMD_TYPE_REQUEST == command_type and current_flow and
pending_requests >= current_flow->get_max_outstanding_requests())
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
- GET_CURRENT_PACKET, "%s_REQ: max req exceeded\n", smb2_command_string[command]);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+ GET_CURRENT_PACKET, "%s_REQ: max req exceeded\n", smb2_command_string[command]);
dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
*current_flow->get_dce2_session_data());
return;
if (SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
{
dce2_smb_stats.v2_crt_err_resp++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
- GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+ GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
}
else if (SMB2_CMD_TYPE_REQUEST == command_type)
{
if (SMB2_SHARE_TYPE_DISK != share_type)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
- GET_CURRENT_PACKET, "%s_REQ: processed for ipc share\n", smb2_command_string[command]);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+ GET_CURRENT_PACKET, "%s_REQ: processed for ipc share\n",
+ smb2_command_string[command]);
dce2_smb_stats.v2_crt_req_ipc++;
}
process_create_request(message_id, current_flow_key, smb_header, end);
if (SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
{
dce2_smb_stats.v2_read_err_resp++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
- GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+ GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
do_not_delete_tree = true;
- Dce2Smb2RequestTracker* request = find_request(message_id, current_flow_key);
+ Dce2Smb2RequestTrackerPtr request = find_request(message_id, current_flow_key);
if (request)
close_file(request->get_file_id(), true);
do_not_delete_tree = false;
if (SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
{
dce2_smb_stats.v2_wrt_err_resp++;
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
do_not_delete_tree = true;
- Dce2Smb2RequestTracker* request = find_request(message_id, current_flow_key);
+ Dce2Smb2RequestTrackerPtr request = find_request(message_id, current_flow_key);
if (request)
close_file(request->get_file_id(), true);
do_not_delete_tree = false;
case SMB2_COM_IOCTL:
if (SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
}
else if (SMB2_SHARE_TYPE_DISK != share_type)
{
- process_ioctl_command(command_type, current_flow_key, smb_header, end);
+ process_ioctl_command(command_type, smb_header, end);
}
break;
}
tree_tracker_mutex.lock();
- if (active_requests.size())
- {
- for (auto it_request : active_requests)
- {
- delete it_request.second;
- }
- }
-
for (auto it_file : opened_files)
{
- get_parent()->clean_file_context_from_flow(it_file.second->get_file_id(),
- it_file.second->get_file_name_hash());
it_file.second->get_parent().reset();
parent_session->decrease_size(sizeof(Dce2Smb2FileTracker));
}
tree_tracker_mutex.unlock();
-
}
#include "dce_smb2_file.h"
#include "dce_smb2_request.h"
+using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
+
uint64_t Smb2Mid(const Smb2Hdr* hdr);
class Dce2Smb2SessionTracker;
Dce2Smb2TreeTracker(uint32_t tree_id_v, Dce2Smb2SessionTracker* p_session, uint8_t sharetype)
: tree_id(tree_id_v), share_type(sharetype), parent_session(p_session)
{
- SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
- GET_CURRENT_PACKET, "tree tracker %" PRIu32 " created\n", tree_id);
+ SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+ GET_CURRENT_PACKET, "tree tracker %" PRIu32 " created\n", tree_id);
if (share_type != SMB2_SHARE_TYPE_DISK)
{
co_tracker = (DCE2_CoTracker*)snort_calloc(sizeof(DCE2_CoTracker));
void close_file(uint64_t, bool);
void close_all_files();
Dce2Smb2FileTrackerPtr find_file(uint64_t);
- Dce2Smb2RequestTracker* find_request(const uint64_t, const uint32_t);
+ Dce2Smb2RequestTrackerPtr find_request(const uint64_t, const uint32_t);
void process(uint16_t, uint8_t, const Smb2Hdr*, const uint8_t*, const uint32_t);
Dce2Smb2SessionTracker* get_parent() { return parent_session; }
DCE2_CoTracker* get_cotracker() { return co_tracker; }
void process_write_request(const uint64_t, const uint32_t, const Smb2Hdr*, const uint8_t*);
uint64_t get_durable_file_id(const Smb2CreateRequestHdr*, const uint8_t*);
bool remove_request(const uint64_t, const uint32_t);
- void process_ioctl_command(const uint8_t, const uint32_t, const Smb2Hdr*, const uint8_t*);
+ void process_ioctl_command(const uint8_t, const Smb2Hdr*, const uint8_t*);
bool store_request(const uint64_t message_id, const uint32_t current_flow_key,
- Dce2Smb2RequestTracker* request)
+ Dce2Smb2RequestTrackerPtr request)
{
Smb2MessageKey message_key = { message_id, current_flow_key, 0 };
std::lock_guard<std::mutex> guard(tree_tracker_mutex);
using Dce2Smb2TreeTrackerPtr = std::shared_ptr<Dce2Smb2TreeTracker>;
using Dce2Smb2TreeTrackerMap =
- std::unordered_map<uint32_t, Dce2Smb2TreeTrackerPtr, std::hash<uint32_t> >;
+ std::unordered_map<uint32_t, Dce2Smb2TreeTrackerPtr, std::hash<uint32_t> >;
#endif
inline FileContext* get_smb_file_context(const Packet* p)
{
FileFlows* file_flows = FileFlows::get_file_flows(p->flow);
- return file_flows ? file_flows->get_current_file_context() : nullptr;
+ if (file_flows)
+ {
+ std::lock_guard<std::mutex> guard(file_flows->file_flow_context_mutex);
+ return file_flows->get_current_file_context();
+ }
+ else
+ return nullptr;
}
FileContext* get_smb_file_context(Flow* flow, uint64_t file_id,
uint64_t multi_file_processing_id, bool to_create)
{
+ if (!flow)
+ {
+ dce2_smb_stats.v2_inv_file_ctx_err++;
+ return nullptr;
+ }
FileFlows* file_flows = FileFlows::get_file_flows(flow);
if ( !file_flows )
return nullptr;
}
+ std::lock_guard<std::mutex> guard(file_flows->file_flow_context_mutex);
return file_flows->get_file_context(file_id, to_create, multi_file_processing_id);
}
PegCount total_smb2_sessions;
PegCount total_encrypted_sessions;
PegCount total_mc_sessions;
+ PegCount ignore_dup_sessions;
};
enum DCE2_SmbVersion
{ CountType::SUM, "total_smb2_sessions", "total smb2 sessions" },
{ CountType::SUM, "total_encrypted_sessions", "total encrypted sessions" },
{ CountType::SUM, "total_mc_sessions", "total multichannel sessions" },
+ { CountType::SUM, "ignore_dup_sessions", "total smb req/resp dropped because of dup msg id" },
{ CountType::END, nullptr, nullptr }
};
{
FileFlows* file_flows = FileFlows::get_file_flows(DetectionEngine::get_current_packet()->flow);
if (file_flows)
+ {
return file_flows->get_current_file_context();
+ }
else
return nullptr;
}
return;
FileFlows* file_flows = FileFlows::get_file_flows(p->flow);
+ if (!file_flows)
+ {
+ return;
+ }
bool upload = (ftracker->ff_file_direction == DCE2_SMB_FILE_DIRECTION__UPLOAD);
if (get_file_processed_size(p->flow) != 0)
if ((ftracker->ff_file_size == 0)
&& (ftracker->ff_bytes_processed != 0))
{
- if (file_flows->file_process(p, nullptr, 0, SNORT_FILE_END, upload,
- ftracker->file_name_hash))
+ file_flows->file_flow_context_mutex.lock();
+ bool resault = file_flows->file_process(p, nullptr, 0, SNORT_FILE_END, upload,
+ ftracker->file_name_hash);
+ file_flows->file_flow_context_mutex.unlock();
+ if (resault)
{
if (upload)
{
if (!file_flows)
return DCE2_RET__ERROR;
+ std::lock_guard<std::mutex> guard(file_flows->file_flow_context_mutex);
if (!file_flows->file_process(p, data_ptr, (int)data_len, position, upload,
ftracker->file_name_hash))
{
((ftracker->ff_file_offset == ftracker->ff_bytes_processed) &&
((file_data_depth == 0) || (ftracker->ff_bytes_processed < (uint64_t)file_data_depth))))
{
- set_file_data(data_ptr, (data_len > UINT16_MAX) ? UINT16_MAX : (uint16_t)data_len,
- ftracker->file_key.file_id);
+ set_file_data(data_ptr, (data_len > UINT16_MAX) ? UINT16_MAX : (uint16_t)data_len);
DCE2_FileDetect();
set_file_data(nullptr, 0);
}