]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3682: smb: handling smb duplicate sessions
authorBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 28 Nov 2022 17:21:09 +0000 (17:21 +0000)
committerBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 28 Nov 2022 17:21:09 +0000 (17:21 +0000)
Merge in SNORT/snort3 from ~BJANDHYA/snort3:pcap_test to master

Squashed commit of the following:

commit 6009316bdbe079c62494b1bcf8a8b9f72e3df393
Author: Bhargava Jandhyala <bjandhya@cisco.com>
Date:   Thu Sep 1 02:24:57 2022 -0400

    smb: handling smb duplicate sessions

16 files changed:
src/file_api/file_flows.cc
src/file_api/file_flows.h
src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb2.h
src/service_inspectors/dce_rpc/dce_smb2_file.cc
src/service_inspectors/dce_rpc/dce_smb2_file.h
src/service_inspectors/dce_rpc/dce_smb2_request.h
src/service_inspectors/dce_rpc/dce_smb2_session.cc
src/service_inspectors/dce_rpc/dce_smb2_session.h
src/service_inspectors/dce_rpc/dce_smb2_session_cache.h
src/service_inspectors/dce_rpc/dce_smb2_tree.cc
src/service_inspectors/dce_rpc/dce_smb2_tree.h
src/service_inspectors/dce_rpc/dce_smb_common.cc
src/service_inspectors/dce_rpc/dce_smb_common.h
src/service_inspectors/dce_rpc/dce_smb_module.cc
src/service_inspectors/dce_rpc/dce_smb_utils.cc

index 068b50f03d160039e385eecfe00cf6a19304870b..42fce79b765a4d3f2cc58e7bfceedd39d90abd6c 100644 (file)
@@ -43,6 +43,7 @@
 #include "file_module.h"
 #include "file_service.h"
 #include "file_stats.h"
+#include <thread>
 
 using namespace snort;
 
@@ -199,6 +200,7 @@ uint64_t FileFlows::get_new_file_instance()
 
 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;
index 6a3387620ec988a3a2b266c443dfed23008e2738..abecb887b32ff7c28476a79bb3c71d4cfb0bdbec 100644 (file)
@@ -56,6 +56,7 @@ public:
 
     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(); }
 
index cabb7a531978552c93942a777e1e0c5dd631750a..47181adb8b1bc1a8ed03950dd8ba7d7b80f1cc0b 100644 (file)
@@ -38,7 +38,8 @@ using namespace snort;
 
 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",
@@ -105,13 +106,14 @@ Dce2Smb2SessionData::Dce2Smb2SessionData(const Packet* p,
 {
     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);
@@ -121,9 +123,10 @@ Dce2Smb2SessionData::~Dce2Smb2SessionData(void)
     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(
@@ -157,23 +160,31 @@ Smb2SessionKey Dce2Smb2SessionData::get_session_key(uint64_t session_id)
 
 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;
     }
 }
 
@@ -181,17 +192,21 @@ Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::find_session(uint64_t session_id)
 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,
@@ -219,7 +234,8 @@ 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) \
@@ -236,7 +252,8 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
         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) \
             { \
@@ -251,9 +268,9 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
     { \
         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); \
@@ -267,9 +284,11 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
         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;
     }
@@ -288,7 +307,8 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
     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
@@ -297,22 +317,25 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
                 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");
                 }
             }
@@ -329,19 +352,15 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
         }
         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++;
@@ -351,11 +370,13 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
             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++;
@@ -382,16 +403,18 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
         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++;
@@ -450,7 +473,7 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
             }
             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++;
@@ -475,7 +498,7 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
             }
             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++;
@@ -530,7 +553,8 @@ void Dce2Smb2SessionData::process()
             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)
@@ -540,9 +564,9 @@ void Dce2Smb2SessionData::process()
             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;
@@ -564,8 +588,8 @@ void Dce2Smb2SessionData::process()
             {
                 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);
@@ -580,8 +604,8 @@ void Dce2Smb2SessionData::process()
             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);
@@ -594,9 +618,11 @@ void Dce2Smb2SessionData::process()
     {
         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;
@@ -604,7 +630,8 @@ void Dce2Smb2SessionData::process()
         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);
@@ -619,7 +646,8 @@ void Dce2Smb2SessionData::process()
         }
         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();
     }
@@ -674,3 +702,4 @@ void Dce2Smb2SessionData::set_reassembled_data(uint8_t* nb_ptr, uint16_t co_len)
         read->length = alignedNtohs(&co_len);
     }
 }
+
index 4c78cc1415e523cf7d4303652a21fde15fc9cb90..231aba48aef44dd7457e39fa93a384f88c0927ae 100644 (file)
@@ -333,11 +333,11 @@ class Dce2Smb2SessionTracker;
 
 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
@@ -485,14 +485,13 @@ public:
     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;
     }
 
@@ -502,21 +501,21 @@ public:
     }
 
     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_ */
 
index 9727a24d4b41c5f1eb5570326568cc51bea51a99..2d04e36cd234ec266e1e161c31b6766ee672cf99 100644 (file)
 #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;
         }
@@ -54,11 +60,12 @@ void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow, uint64
         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;
 }
 
@@ -71,14 +78,28 @@ inline void Dce2Smb2FileTracker::file_detect()
 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;
@@ -87,13 +108,27 @@ std::pair<bool, Dce2Smb2SessionData*> Dce2Smb2FileTracker::update_processing_flo
         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);
 }
 
@@ -107,8 +142,8 @@ void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint6
         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);
@@ -121,7 +156,7 @@ void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint6
             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);
             }
@@ -137,16 +172,30 @@ bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key)
     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;
 }
@@ -159,65 +208,65 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     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();
@@ -235,7 +284,7 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     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();
     }
 
@@ -243,49 +292,68 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     {
         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;
+            }
         }
     }
 
@@ -293,7 +361,7 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     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;
 }
 
index efb26aff84dd5f8a213c43df179f273f119eaadc..7665ad52b366c6df7d869bc4a11bf20b44a162e1 100644 (file)
@@ -50,7 +50,7 @@ public:
         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);
     }
 
@@ -65,6 +65,7 @@ public:
         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; }
@@ -78,6 +79,16 @@ public:
         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,
@@ -99,7 +110,7 @@ private:
 
 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
 
index 1ea75309fc0e01fd7cdf5b63f663c25520c13279..e9e6f96e19ff4f1f9dbb07dd5790f05360cc8b00 100644 (file)
@@ -37,13 +37,15 @@ public:
     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()
@@ -64,8 +66,9 @@ private:
     uint64_t offset;
 };
 
+using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
 using Dce2Smb2RequestTrackerMap =
-    std::unordered_map<Smb2MessageKey, Dce2Smb2RequestTracker*, Smb2KeyHash>;
+        std::unordered_map<Smb2MessageKey, Dce2Smb2RequestTrackerPtr, Smb2KeyHash>;
 
 #endif
 
index d2d2c6786134a37fe9574c2f0de1c04927550e3f..4284a05877aaede6af0833a37570c0bd66ca4408 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "file_api/file_flows.h"
 
+#include <numeric>
+
 uint32_t Smb2Tid(const Smb2Hdr* hdr)
 {
     return snort::alignedNtohl(&(((const Smb2SyncHdr*)hdr)->tree_id));
@@ -35,7 +37,7 @@ uint32_t Smb2Tid(const Smb2Hdr* hdr)
 
 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;
 }
@@ -46,7 +48,7 @@ Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::find_tree_for_message(
     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;
     }
@@ -63,6 +65,67 @@ Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::find_tree_for_tree_id(
     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)
 {
@@ -83,19 +146,25 @@ void Dce2Smb2SessionTracker::process(const uint16_t command, uint8_t command_typ
         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;
 
@@ -103,11 +172,11 @@ void Dce2Smb2SessionTracker::process(const uint16_t command, uint8_t command_typ
     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,
@@ -122,7 +191,7 @@ void Dce2Smb2SessionTracker::process(const uint16_t command, uint8_t command_typ
             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++;
@@ -132,19 +201,8 @@ void Dce2Smb2SessionTracker::process(const uint16_t command, uint8_t command_typ
 }
 
 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);
@@ -162,28 +220,6 @@ Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::connect_tree(const uint32_t tree_
     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);
@@ -194,14 +230,6 @@ void Dce2Smb2SessionTracker::decrease_size(const size_t 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)
 {
@@ -215,19 +243,12 @@ 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();
 }
 
index aa7c4ae44c760c90cccbbaafa02537d7e12b1dab..e99fc432232f90bb12c51ea92017b9792842f2ad 100644 (file)
 
 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:
@@ -40,35 +48,79 @@ 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);
@@ -82,14 +134,21 @@ public:
     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
@@ -100,15 +159,16 @@ private:
     //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
index fca5d3159bf6e18ab5e7a94579a0da4dbe7a6672..61267cf5673d93c1908c9ef3785a5c7fb107774b 100644 (file)
 #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:
@@ -48,20 +47,22 @@ 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
@@ -131,14 +132,12 @@ private:
         {
             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;
 
index 4d5c451600385737e3b93c8525b6d1c9f98efbe9..ee84650253028c135741761735272a23e42017e8 100644 (file)
@@ -85,14 +85,12 @@ void Dce2Smb2TreeTracker::close_all_files()
     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 };
@@ -109,7 +107,6 @@ bool Dce2Smb2TreeTracker::remove_request(const uint64_t message_id,
     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;
@@ -133,7 +130,7 @@ void Dce2Smb2TreeTracker::process_set_info_request(const Smb2Hdr* smb_header)
         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]);
         }
@@ -141,7 +138,7 @@ void Dce2Smb2TreeTracker::process_set_info_request(const Smb2Hdr* smb_header)
     }
     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++;
@@ -153,15 +150,16 @@ void Dce2Smb2TreeTracker::process_close_request(const Smb2Hdr* smb_header,
 {
     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;
@@ -194,18 +192,18 @@ uint64_t Dce2Smb2TreeTracker::get_durable_file_id(
         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) +
@@ -232,15 +230,15 @@ void Dce2Smb2TreeTracker::process_create_response(const uint64_t message_id,
         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);
@@ -255,7 +253,8 @@ void Dce2Smb2TreeTracker::process_create_response(const uint64_t message_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++;
         }
@@ -270,9 +269,9 @@ void Dce2Smb2TreeTracker::process_create_request(const uint64_t message_id,
     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;
     }
@@ -280,7 +279,7 @@ void Dce2Smb2TreeTracker::process_create_request(const uint64_t message_id,
         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",
@@ -292,12 +291,12 @@ void Dce2Smb2TreeTracker::process_create_request(const uint64_t message_id,
     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.
@@ -328,22 +327,28 @@ void Dce2Smb2TreeTracker::process_read_response(const uint64_t message_id,
     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;
@@ -370,8 +375,8 @@ void Dce2Smb2TreeTracker::process_read_response(const uint64_t message_id,
     }
     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;
 }
@@ -383,16 +388,23 @@ void Dce2Smb2TreeTracker::process_read_request(const uint64_t message_id,
     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,
@@ -413,9 +425,16 @@ void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
     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");
@@ -423,12 +442,11 @@ void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
             *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;
@@ -452,14 +470,14 @@ void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
     }
     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) ?
@@ -467,7 +485,7 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
     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;
@@ -477,7 +495,7 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
     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;
@@ -485,7 +503,7 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
     }
     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;
@@ -493,7 +511,7 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
     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();
     }
 }
@@ -501,15 +519,22 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
 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;
@@ -523,15 +548,16 @@ void Dce2Smb2TreeTracker::process(uint16_t command, uint8_t command_type,
         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);
@@ -549,10 +575,10 @@ void Dce2Smb2TreeTracker::process(uint16_t command, uint8_t command_type,
         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;
@@ -566,10 +592,10 @@ void Dce2Smb2TreeTracker::process(uint16_t command, uint8_t command_type,
         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;
@@ -580,12 +606,12 @@ void Dce2Smb2TreeTracker::process(uint16_t command, uint8_t command_type,
     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;
     }
@@ -607,23 +633,12 @@ Dce2Smb2TreeTracker::~Dce2Smb2TreeTracker(void)
 
     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();
-
 }
 
index 0df0b3f4b73cc6124acb3180b5d571e51c5a5f8c..cec38f8071c59534cf76d0b79fea6b99c8c20a47 100644 (file)
@@ -29,6 +29,8 @@
 #include "dce_smb2_file.h"
 #include "dce_smb2_request.h"
 
+using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
+
 uint64_t Smb2Mid(const Smb2Hdr* hdr);
 
 class Dce2Smb2SessionTracker;
@@ -43,8 +45,8 @@ public:
     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));
@@ -62,7 +64,7 @@ public:
     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; }
@@ -81,9 +83,9 @@ private:
     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);
@@ -101,7 +103,7 @@ private:
 
 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
 
index 59023c1ffc5a96355898b10125bbb0faeaa6947f..3b9d082722d30334d3e948ba569173b03f3eeac3 100644 (file)
@@ -161,12 +161,23 @@ DCE2_SsnData* get_dce2_session_data(snort::Flow* flow)
 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 )
@@ -175,6 +186,7 @@ FileContext* get_smb_file_context(Flow* flow, uint64_t file_id,
         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);
 }
 
index 1d579318d088b3b2abcd3c77a72a7e0d57efbb74..f171ca00181fd202622d4621d226117529f1b5f7 100644 (file)
@@ -205,6 +205,7 @@ struct dce2SmbStats
     PegCount total_smb2_sessions;
     PegCount total_encrypted_sessions;
     PegCount total_mc_sessions;
+    PegCount ignore_dup_sessions;
 };
 
 enum DCE2_SmbVersion
index 54801f26af99d587c2fe89b5f9ed37199457c479..c96770d6653cb96fd7803a509795ebe7f8cf8179 100644 (file)
@@ -194,6 +194,7 @@ static const PegInfo dce2_smb_pegs[] =
     { 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 }
 };
 
index 81c36bc6e3d941f920e618bcf2cd73c4bd68a12d..047f730987481428abffb2c66cde307cdb8d9f23 100644 (file)
@@ -1303,7 +1303,9 @@ static FileContext* DCE2_get_main_file_context()
 {
     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;
 }
@@ -1420,6 +1422,10 @@ static void DCE2_SmbFinishFileAPI(DCE2_SmbSsnData* ssd)
         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)
@@ -1429,8 +1435,11 @@ static void DCE2_SmbFinishFileAPI(DCE2_SmbSsnData* ssd)
         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)
                 {
@@ -1502,6 +1511,7 @@ static DCE2_Ret DCE2_SmbFileAPIProcess(DCE2_SmbSsnData* ssd,
     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))
     {
@@ -1720,8 +1730,7 @@ void DCE2_SmbProcessFileData(DCE2_SmbSsnData* ssd,
         ((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);
     }