]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4061: Porting into 760(snort3) for SMB Multichannel Redesigning (First...
authorSumit Kumar (sumikum7) <sumikum7@cisco.com>
Fri, 27 Oct 2023 18:07:41 +0000 (18:07 +0000)
committerBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Fri, 27 Oct 2023 18:07:41 +0000 (18:07 +0000)
Merge in SNORT/snort3 from ~SUMIKUM7/snort3:porting_760 to master

Squashed commit of the following:

commit 6fc8604a2a7448163b8226ffaf77799c2965f4c1
Author: Sumit Kumar <sumikum7@cisco.com>
Date:   Fri Oct 13 15:45:05 2023 +0530

    dce_rpc: Added SMB Redsigned Multichannel enabled code

74 files changed:
src/detection/CMakeLists.txt
src/detection/pattern_match_data.h
src/file_api/file_flows.cc
src/file_api/file_segment.cc
src/file_api/file_segment.h
src/hash/lru_cache_local.h
src/ips_options/CMakeLists.txt
src/protocols/packet.h
src/service_inspectors/dce_rpc/CMakeLists.txt
src/service_inspectors/dce_rpc/dce_co.cc
src/service_inspectors/dce_rpc/dce_co.h
src/service_inspectors/dce_rpc/dce_common.cc
src/service_inspectors/dce_rpc/dce_common.h
src/service_inspectors/dce_rpc/dce_context_data.cc
src/service_inspectors/dce_rpc/dce_db.h [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_expected_session.cc
src/service_inspectors/dce_rpc/dce_expected_session.h
src/service_inspectors/dce_rpc/dce_http_proxy_module.cc
src/service_inspectors/dce_rpc/dce_http_proxy_splitter.cc
src/service_inspectors/dce_rpc/dce_http_server_module.cc
src/service_inspectors/dce_rpc/dce_http_server_splitter.cc
src/service_inspectors/dce_rpc/dce_list.cc
src/service_inspectors/dce_rpc/dce_smb.cc [moved from src/service_inspectors/dce_rpc/dce_smb1.cc with 68% similarity]
src/service_inspectors/dce_rpc/dce_smb.h [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_smb1.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb2.h
src/service_inspectors/dce_rpc/dce_smb2_commands.cc [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_smb2_commands.h [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_smb2_file.cc [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_file.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_request.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_session.cc [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_session.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_session_cache.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_tree.cc [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_tree.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb2_utils.cc [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_smb2_utils.h [new file with mode: 0644]
src/service_inspectors/dce_rpc/dce_smb_commands.cc
src/service_inspectors/dce_rpc/dce_smb_commands.h
src/service_inspectors/dce_rpc/dce_smb_common.cc [deleted file]
src/service_inspectors/dce_rpc/dce_smb_common.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb_inspector.cc [deleted file]
src/service_inspectors/dce_rpc/dce_smb_inspector.h [deleted file]
src/service_inspectors/dce_rpc/dce_smb_module.cc
src/service_inspectors/dce_rpc/dce_smb_module.h
src/service_inspectors/dce_rpc/dce_smb_paf.cc
src/service_inspectors/dce_rpc/dce_smb_paf.h
src/service_inspectors/dce_rpc/dce_smb_transaction.cc
src/service_inspectors/dce_rpc/dce_smb_transaction_utils.cc
src/service_inspectors/dce_rpc/dce_smb_transaction_utils.h
src/service_inspectors/dce_rpc/dce_smb_utils.cc
src/service_inspectors/dce_rpc/dce_smb_utils.h
src/service_inspectors/dce_rpc/dce_tcp.cc
src/service_inspectors/dce_rpc/dce_tcp.h
src/service_inspectors/dce_rpc/dce_tcp_module.cc
src/service_inspectors/dce_rpc/dce_tcp_module.h
src/service_inspectors/dce_rpc/dce_tcp_paf.cc
src/service_inspectors/dce_rpc/dce_tcp_paf.h
src/service_inspectors/dce_rpc/dce_udp.cc
src/service_inspectors/dce_rpc/dce_udp.h
src/service_inspectors/dce_rpc/dce_udp_module.cc
src/service_inspectors/dce_rpc/dce_udp_module.h
src/service_inspectors/dce_rpc/dce_udp_processing.cc
src/service_inspectors/dce_rpc/dce_utils.cc
src/service_inspectors/dce_rpc/dce_utils.h
src/service_inspectors/dce_rpc/dev_notes.txt
src/service_inspectors/dce_rpc/ips_dce_iface.cc
src/service_inspectors/dce_rpc/ips_dce_opnum.cc
src/service_inspectors/dce_rpc/ips_dce_stub_data.cc
src/service_inspectors/dce_rpc/smb_common.h
src/service_inspectors/dce_rpc/smb_message.cc
src/service_inspectors/dce_rpc/smb_message.h

index 064c53e3220cb9c9a997366bfdc34001e0b45949..757c0260f28b1b7a362a718d4e6466f7deaad2bb 100644 (file)
@@ -13,6 +13,7 @@ set (DETECTION_INCLUDES
     rules.h
     signature.h
     treenodes.h
+    pattern_match_data.h
 )
 
 add_library (detection OBJECT
@@ -38,7 +39,6 @@ add_library (detection OBJECT
     ips_context.cc
     ips_context_chain.cc
     ips_context_data.cc
-    pattern_match_data.h
     pcrm.cc
     pcrm.h
     regex_offload.cc
index 5dc3e106896e1877a3625308b8c02fb27dbd7e4f..5b08e70631d372ebe5d449d279d5a663ebe9f7fb 100644 (file)
@@ -69,7 +69,7 @@ struct PatternMatchData
         NO_FP    = 0x20,
     };
 
-    uint16_t flags;          // from above enum
+    uint16_t flags = 0;          // from above enum
     uint16_t mpse_flags;     // passed through to mpse
 
     uint16_t fp_offset;
index 1d1d41feeb8175021f525096a5ca3d2d0b0dd806..e76a591a5eef8037ef45e5fe88bcf5302a847cfb 100644 (file)
@@ -206,7 +206,6 @@ 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;
@@ -496,10 +495,11 @@ bool FileFlows::file_process(Packet* p, const uint8_t* file_data, int data_size,
 bool FileFlows::set_file_name(const uint8_t* fname, uint32_t name_size, uint64_t file_id,
     uint64_t multi_file_processing_id, const uint8_t* url, uint32_t url_size)
 {
-    bool is_new_context = false;
     FileContext* context;
-    if (file_id)
+    if (file_id) {
+        bool is_new_context = false;
         context = get_file_context(file_id, false, is_new_context, multi_file_processing_id);
+    }
     else
         context = get_current_file_context();
     if ( !context )
index 9af6556e277de74abce4590252c26c141b9024ed..c2cfe1c54e5cd4ee0bd2713a30fb0b96b08e1f68 100644 (file)
@@ -110,6 +110,7 @@ void FileSegments::add(const uint8_t* file_data, int64_t data_size, uint64_t off
             data_size = end -offset;
             file_data = file_data + offset - start;
         }
+        insert_segment(file_data, data_size, offset, find_left, &left);
     }
     // New segment should be at the start of link list
     else if (!left)
@@ -119,29 +120,41 @@ void FileSegments::add(const uint8_t* file_data, int64_t data_size, uint64_t off
             /* Overlap, trim off extra data from end */
             data_size = head->offset - offset;
         }
+        insert_segment(file_data, data_size, offset, find_left, &left);
     }
     else
     {
         //Left Overlap
-        if ( (left->offset + left->data->size() > start)  )
+        while(left and (left->offset + left->data->size() <= end))
         {
-            offset = left->offset + left->data->size();
-            data_size = end - offset;
-            file_data = file_data + offset - start;
-        }
-        //Right Overlap
-        if ( (left->next->offset < end) )
-        {
-            data_size = left->next->offset - offset;
-        }
 
+            const uint8_t *cur_file_data = file_data;
+            if ( (left->offset + left->data->size() > start)  )
+            {
+                offset = left->offset + left->data->size();
+                data_size = end - offset;
+                cur_file_data = cur_file_data + offset - start;
+            }
+            //Right Overlap
+            if ( left->next and (left->next->offset < end) )
+            {
+                data_size = left->next->offset - offset;
+            }
+
+            insert_segment(cur_file_data, data_size, offset, find_left, &left);
+            left = left->next;
+        }
     }
+}
 
+void FileSegments::insert_segment(const uint8_t* file_data, int64_t data_size, uint64_t offset, bool find_left,  FileSegment** left)
+{
     // ignore overlap case
     if (data_size <= 0)
     {
         FILE_DEBUG(file_trace , DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            GET_CURRENT_PACKET, "Complete overlap while adding segments\n");
+            GET_CURRENT_PACKET, "Complete overlap while adding segments  offset : %lu data_size : %lu\n",
+            offset, data_size);
         return;
     }
 
@@ -150,22 +163,22 @@ void FileSegments::add(const uint8_t* file_data, int64_t data_size, uint64_t off
     new_segment->data = new std::string((const char*)file_data, data_size);
 
     FILE_DEBUG(file_trace , DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
-        GET_CURRENT_PACKET, "Adding offset : %u data_size : %lu\n", new_segment->offset,
+        GET_CURRENT_PACKET, "Adding offset : %lu data_size : %lu\n", offset,
         data_size);
-    if (!find_left)
-    {
-        previous->next = new_segment;
-
-    }
-    else if (!left)
+    if (!*left)
     {
         new_segment->next = head;
         head = new_segment;
     }
+    else if (!find_left)
+    {
+        (*left)->next = new_segment;
+    }
     else
     {
-        new_segment->next = left->next;
-        left->next = new_segment;
+        new_segment->next = (*left)->next;
+        (*left)->next = new_segment;
+        *left = (*left)->next;
     }
 }
 
@@ -179,7 +192,7 @@ FilePosition FileSegments::get_file_position(uint64_t data_size, uint64_t file_s
             return SNORT_FILE_START;
     }
 
-    if (file_size <= data_size + current_offset)
+    if (file_size and (file_size <= data_size + current_offset))
         return SNORT_FILE_END;
 
     return SNORT_FILE_MIDDLE;
index 7badb4df128b8936ae3f0ad6cc8eb6072863ddcd..0785bff9ac07ca01617a83498c8fe4af4f0a67e5 100644 (file)
@@ -63,6 +63,7 @@ private:
     snort::FileContext* context = nullptr;
 
     void add(const uint8_t* file_data, int64_t data_size, uint64_t offset);
+    void insert_segment(const uint8_t* file_data, int64_t data_size, uint64_t offset, bool find_left,  FileSegment** left);
     FilePosition get_file_position(uint64_t data_size, uint64_t file_size);
     int process_one(snort::Packet*, const uint8_t* file_data, int data_size, snort::FilePolicyBase*,
         FilePosition position=SNORT_FILE_POSITION_UNKNOWN);
index 1f549233599db1394812715464dc4a96392a08da..4cc87f1e2a15a43428c074e356568abd69274ecd 100644 (file)
@@ -35,7 +35,8 @@
     { CountType::SUM, "cache_misses", module " cache did not find entry" }, \
     { CountType::SUM, "cache_replaces", module " cache found entry and replaced its value" }, \
     { CountType::SUM, "cache_max", module " cache's maximum byte usage"}, \
-    { CountType::SUM, "cache_prunes", module " cache pruned entry to make space for new entry" }
+    { CountType::SUM, "cache_prunes", module " cache pruned entry to make space for new entry" }, \
+    { CountType::SUM, "cache_removes", module " cache removed existing entry"}
 
 struct LruCacheLocalStats
 {
@@ -45,6 +46,7 @@ struct LruCacheLocalStats
     PegCount cache_replaces;
     PegCount cache_max;
     PegCount cache_prunes;
+    PegCount cache_removes;
 };
 
 template<typename Key, typename Value, typename Hash>
@@ -66,6 +68,10 @@ public:
     // else return false replacing the existing value if asked
     bool add(const Key&, const Value&, bool replace = false);
 
+    // If key does not exist, return false;
+    // else remove the entry associated with key
+    bool remove(const Key&);
+
     // Copy all key-value pairs from the cache
     void get_all_values(std::vector<std::pair<Key, Value>>&);
 
@@ -159,6 +165,21 @@ bool LruCacheLocal<Key, Value, Hash>::add(const Key& key, const Value& value, bo
     return false;
 }
 
+template<typename Key, typename Value, typename Hash>
+bool LruCacheLocal<Key, Value, Hash>::remove(const Key& key)
+{
+    LruMapIter it = map.find(key);
+    if (it == map.end())
+    {
+        return false;
+    }
+    list.erase(it->second);
+    map.erase(it);
+    current_size -= entry_size;
+    stats.cache_removes++;
+    return true;
+}
+
 template<typename Key, typename Value, typename Hash>
 void LruCacheLocal<Key, Value, Hash>::get_all_values(std::vector<std::pair<Key, Value>>& kv)
 {
index d81ed4bb461ad54035c41db92ac07b751d2fca49..4ae54c65e0496376fc16dd8906f1f35fafcd9ee4 100644 (file)
@@ -1,3 +1,6 @@
+set(IPS_INCLUDES
+    extract.h
+)
 
 SET( PLUGIN_LIST
     ips_ack.cc
@@ -45,8 +48,8 @@ SET( PLUGIN_LIST
 
 
 set (IPS_SOURCES
+    ${IPS_INCLUDES}
     extract.cc
-    extract.h
     ips_classtype.cc
     ips_content.cc
     ips_detection_filter.cc
@@ -141,3 +144,7 @@ endif ( HAVE_HYPERSCAN )
 endif (STATIC_IPS_OPTIONS)
 
 add_subdirectory(test)
+
+install(FILES ${IPS_INCLUDES}
+    DESTINATION "${INCLUDE_INSTALL_PATH}/ips_options/"
+)
index 245e9f5bc3b640a4a60cf6e389a134d39e401aad..38d3e2b5eefd478747cb87039188d8f9edca5a69 100644 (file)
@@ -229,7 +229,7 @@ struct SO_PUBLIC Packet
     { return (proto_bits & PROTO_BIT__UDP) and data and dsize; }
 
     bool has_udp_quic_data() const
-    { return (pseudo_type == PSEUDO_PKT_UDP_QUIC) and data and dsize; }
+    { return (is_cooked() and pseudo_type == PSEUDO_PKT_UDP_QUIC) and data and dsize; }
 
     /* Get general, non-boolean information */
     PktType type() const
index 3f4ca4b094e3948bdd8518b5092fcfe51b790708..a8b19ad043b47e18da80ea08fb42068eb1649d7e 100644 (file)
@@ -6,6 +6,7 @@ set( FILE_LIST
     dce_common.h
     dce_context_data.cc
     dce_context_data.h
+    dce_db.h
     dce_expected_session.cc
     dce_expected_session.h
     dce_http_proxy.cc
@@ -18,25 +19,18 @@ set( FILE_LIST
     dce_http_server_module.h
     dce_http_server_splitter.cc
     dce_http_server_splitter.h
-    dce_list.cc
     dce_list.h
-    dce_smb1.cc
-    dce_smb1.h
+    dce_list.cc
+    dce_smb.cc
+    dce_smb.h
     dce_smb2.cc
     dce_smb2.h
-    dce_smb2_file.cc
-    dce_smb2_file.h
-    dce_smb2_request.h
-    dce_smb2_session.cc
-    dce_smb2_session.h
-    dce_smb2_tree.cc
-    dce_smb2_tree.h
+    dce_smb2_commands.cc
+    dce_smb2_commands.h
+    dce_smb2_utils.cc
+    dce_smb2_utils.h
     dce_smb_commands.cc
     dce_smb_commands.h
-    dce_smb_common.cc
-    dce_smb_common.h
-    dce_smb_inspector.cc
-    dce_smb_inspector.h
     dce_smb_module.cc
     dce_smb_module.h
     dce_smb_paf.cc
index a5810ea25808531558e845ae6a60ffd98040df68..e3f39ef60ec1e3f91adb127dc608535d7dda5dfb 100644 (file)
@@ -28,8 +28,7 @@
 #include "utils/util.h"
 
 #include "dce_expected_session.h"
-#include "dce_smb1.h"
-#include "dce_smb_common.h"
+#include "dce_smb.h"
 #include "dce_smb_module.h"
 #include "dce_smb_utils.h"
 #include "dce_tcp.h"
@@ -40,11 +39,13 @@ static THREAD_LOCAL int co_reassembled = 0;
 
 /* [MS-RPCE] 2.2.5 - 64-Bit Network Data Representation */
 static const Uuid uuid_ndr64 = { 0x71710533, 0xbeba, 0x4937, 0x83, 0x19,
-    { 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36 } };
+                                 { 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36 }
+};
 
 /* Endpoint mapper UUID */
 static const Uuid uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, 0x91, 0xa4,
-    { 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
+                               { 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa }
+};
 
 static inline dce2CommonStats* dce_get_proto_stats_ptr(const DCE2_SsnData* sd)
 {
@@ -54,7 +55,9 @@ static inline dce2CommonStats* dce_get_proto_stats_ptr(const DCE2_SsnData* sd)
     }
     else
     {
-        return((dce2CommonStats*)&dce2_smb_stats);
+        /* Since dce2_smb_stats derives from LruCacheLocalStats,
+        force return the pointer to first peg of the derived class */
+        return((dce2CommonStats*)&(dce2_smb_stats.events));
     }
     // FIXIT-M add HTTP, UDP cases when these are ported
 }
@@ -387,6 +390,7 @@ static inline DCE2_CoSeg* DCE2_CoGetSegPtr(DCE2_CoTracker* cot)
     Packet* p = DetectionEngine::get_current_packet();
     if (p == nullptr)
         return nullptr;
+
     if ( p->is_from_server() )
         return &cot->srv_seg;
 
@@ -818,7 +822,6 @@ static void dce_co_process_ctx_result(DCE2_SsnData*, DCE2_CoTracker* cot,
     const Uuid* transport)
 {
     DCE2_CoCtxIdNode* ctx_node, * existing_ctx_node;
-
     /* Dequeue context item in pending queue - this will get put in the permanent
      * context id list or freed */
     ctx_node = (DCE2_CoCtxIdNode*)DCE2_QueueDequeue(cot->pending_ctx_ids);
@@ -1361,6 +1364,7 @@ static Packet* dce_co_reassemble(DCE2_SsnData* sd, DCE2_CoTracker* cot,
     Packet* p = DetectionEngine::get_current_packet();
     if (p == nullptr)
         return nullptr;
+
     bool from_client = p->is_from_client();
 
     int co_hdr_len = from_client ? DCE2_MOCK_HDR_LEN__CO_CLI : DCE2_MOCK_HDR_LEN__CO_SRV;
@@ -1378,7 +1382,8 @@ static Packet* dce_co_reassemble(DCE2_SsnData* sd, DCE2_CoTracker* cot,
     {
     case DCE2_RPKT_TYPE__SMB_CO_FRAG:
     case DCE2_RPKT_TYPE__SMB_CO_SEG:
-        set_smb_reassembled_data(wrdata, (uint16_t)(rpkt->dsize - smb_hdr_len));
+        set_smb_reassembled_data(wrdata,
+            (uint16_t)(rpkt->dsize - smb_hdr_len));
 
         if (rpkt_type == DCE2_RPKT_TYPE__SMB_CO_FRAG)
         {
@@ -1418,7 +1423,7 @@ static Packet* dce_co_reassemble(DCE2_SsnData* sd, DCE2_CoTracker* cot,
             if ( from_client )
                 dce_common_stats->co_cli_seg_reassembled++;
             else
-                dce_common_stats->co_srv_seg_reassembled++;
+                dce_common_stats->co_srv_frag_reassembled++;
         }
 
         *co_hdr = (const DceRpcCoHdr*)rpkt->data;
@@ -2163,7 +2168,6 @@ static void DCE2_CoEarlyReassemble(DCE2_SsnData* sd, DCE2_CoTracker* cot)
 {
     DCE2_Buffer* frag_buf = DCE2_CoGetFragBuf(&cot->frag_tracker);
     Packet* p = DetectionEngine::get_current_packet();
-
     if ( (p == nullptr) || p->is_from_server() )
         return;
 
@@ -2234,16 +2238,16 @@ static Packet* DCE2_CoGetSegRpkt(DCE2_SsnData* sd,
     Packet* p = DetectionEngine::get_current_packet();
     if (p == nullptr)
         return nullptr;
+
     Packet* rpkt = nullptr;
-    int smb_hdr_len = p->is_from_client() ? DCE2_MOCK_HDR_LEN__SMB_CLI :
-        DCE2_MOCK_HDR_LEN__SMB_SRV;
+    int smb_hdr_len = p->is_from_client() ? DCE2_MOCK_HDR_LEN__SMB_CLI : DCE2_MOCK_HDR_LEN__SMB_SRV;
 
     switch (sd->trans)
     {
     case DCE2_TRANS_TYPE__SMB:
         rpkt = DCE2_GetRpkt(p, DCE2_RPKT_TYPE__SMB_CO_SEG, data_ptr, data_len);
 
-        if ( !rpkt  || !rpkt->data )
+        if ( !rpkt || !rpkt->data )
             return nullptr;
 
         set_smb_reassembled_data(const_cast<uint8_t*>(rpkt->data),
@@ -2293,7 +2297,6 @@ static void DCE2_CoSegDecode(DCE2_SsnData* sd, DCE2_CoTracker* cot, DCE2_CoSeg*
         dce_common_stats->co_srv_seg_reassembled++;
     }
 
-
     Packet* rpkt = DCE2_CoGetSegRpkt(sd, DCE2_BufferData(seg->buf), DCE2_BufferLength(seg->buf));
 
     // FIXIT-M don't toss data until success response to
index bc8dea3d01991e926f4f9f870c2941c7b9237b69..4f3e5b3176c6e1d95a7ac7fbbb1a3447867af147 100644 (file)
@@ -265,7 +265,8 @@ enum DCE2_CoCtxTransport
     DCE2_CO_CTX_TRANS_SYNTAX_NDR64
 };
 
-enum DCE2_CoEpmOpnum {
+enum DCE2_CoEpmOpnum
+{
     DCE2_CO_EPT_NONE = -1,
     DCE2_CO_EPT_INSERT = 0,
     DCE2_CO_EPT_DELETE,
index e0ded056c505c232b3562dd072509aa76efa2f35..7682ddf012b575207a7d017530d37c3b3f739c1b 100644 (file)
@@ -32,8 +32,6 @@
 #include "dce_context_data.h"
 #include "dce_http_proxy_module.h"
 #include "dce_http_server_module.h"
-#include "dce_smb1.h"
-#include "dce_smb_common.h"
 #include "dce_smb_utils.h"
 #include "dce_tcp.h"
 #include "dce_udp.h"
index 7cc7eb89a6ae86468965037ee5e48449f2e2ed93..3f1ba8362670e46bc19ea894a4c8ce80d09a16be 100644 (file)
@@ -186,7 +186,7 @@ struct DCE2_Roptions
     int opnum;    /* Set to sentinel if not applicable */
 
     /* dce_stub_data */
-    const uint8_t* stub_data;  /* Set to null if not applicable */
+    const uint8_t* stub_data;  /* Set to null  if not applicable */
 };
 
 enum DCE2_SsnFlag
index 0539d2c55d3d190b517975013debaa41b71e11d7..3e9697fbe13dca7b18d750aed0df3764577c1c69 100644 (file)
@@ -41,35 +41,35 @@ void DceContextData::init(DCE2_TransType trans)
 
 unsigned DceContextData::get_ips_id(DCE2_TransType trans)
 {
-    switch(trans)
+    switch (trans)
     {
-        case DCE2_TRANS_TYPE__SMB:
-            return DceContextData::smb_ips_id;
-        case DCE2_TRANS_TYPE__TCP:
-            return DceContextData::tcp_ips_id;
-        case DCE2_TRANS_TYPE__UDP:
-            return DceContextData::udp_ips_id;
-        default:
-            break;
+    case DCE2_TRANS_TYPE__SMB:
+        return DceContextData::smb_ips_id;
+    case DCE2_TRANS_TYPE__TCP:
+        return DceContextData::tcp_ips_id;
+    case DCE2_TRANS_TYPE__UDP:
+        return DceContextData::udp_ips_id;
+    default:
+        break;
     }
     return 0;
 }
 
 void DceContextData::set_ips_id(DCE2_TransType trans, unsigned id)
 {
-    switch(trans)
+    switch (trans)
     {
-        case DCE2_TRANS_TYPE__SMB:
-            DceContextData::smb_ips_id = id;
-            break;
-        case DCE2_TRANS_TYPE__TCP:
-            DceContextData::tcp_ips_id = id;
-            break;
-        case DCE2_TRANS_TYPE__UDP:
-            DceContextData::udp_ips_id = id;
-            break;
-        default:
-            break;
+    case DCE2_TRANS_TYPE__SMB:
+        DceContextData::smb_ips_id = id;
+        break;
+    case DCE2_TRANS_TYPE__TCP:
+        DceContextData::tcp_ips_id = id;
+        break;
+    case DCE2_TRANS_TYPE__UDP:
+        DceContextData::udp_ips_id = id;
+        break;
+    default:
+        break;
     }
     return;
 }
@@ -145,9 +145,8 @@ void DceContextData::clear_current_ropts(IpsContext* context, DCE2_TransType tra
     {
         dcd->clear();
     }
-
-    return;
 }
+
 void DceContextData::clear_current_ropts(const Packet* p, DCE2_TransType trans)
 {
     IpsContext* context = p ? p->context : nullptr;
diff --git a/src/service_inspectors/dce_rpc/dce_db.h b/src/service_inspectors/dce_rpc/dce_db.h
new file mode 100644 (file)
index 0000000..47e5812
--- /dev/null
@@ -0,0 +1,116 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// dce_db.h author Neha Sharma <nehash4@cisco.com>
+
+// This implementation provides interface that can be extended for map, list, etc.
+// Currently only map has been implemented to handle multiple smb sessions
+// in single tcp connection. This database will modify/change to handle
+// single smb session spread across multiple tcp connections.
+
+#ifndef DCE_DB_H
+#define DCE_DB_H
+
+#include <unordered_map>
+#include <vector>
+#include "dce_utils.h"
+
+#include "main/snort_types.h"
+
+template<typename Key, typename Value, typename Hash>
+class DCE2_Db
+{
+public:
+
+    virtual bool Insert(const Key& key, Value data) = 0;
+    virtual Value Find(const Key& key) = 0;
+    virtual void Remove(const Key& key) = 0;
+    virtual int GetSize() = 0;
+    virtual std::vector< std::pair<Key, Value> > get_all_entry() = 0;
+};
+
+template<typename Key, typename Value, typename Hash>
+class DCE2_DbMap : public DCE2_Db<Key, Value, Hash>
+{
+public:
+
+    DCE2_DbMap(bool gc = true) :   garbage_collection(gc) { }
+
+    ~DCE2_DbMap()
+    {
+        auto it = Map.cbegin();
+        while (it != Map.cend())
+        {
+            if (garbage_collection)
+                delete it->second;
+            it = Map.erase(it);
+        }
+    }
+
+    bool Insert(const Key& key, Value data) override;
+    Value Find(const Key& key) override;
+    void Remove(const Key& key) override;
+    int GetSize() override
+    {
+        return Map.size();
+    }
+
+    std::vector< std::pair<Key, Value> > get_all_entry() override;
+
+private:
+    std::unordered_map<Key, Value, Hash> Map;
+    bool garbage_collection = true;
+};
+
+template<typename Key, typename Value, typename Hash>
+bool DCE2_DbMap<Key, Value, Hash>::Insert(const Key& key, Value data)
+{
+    return Map.insert(std::make_pair(key,data)).second;
+}
+
+template<typename Key, typename Value, typename Hash>
+Value DCE2_DbMap<Key, Value, Hash>::Find(const Key& key)
+{
+    auto elem = Map.find(key);
+    if (elem != Map.end())
+        return elem->second;
+    return nullptr;
+}
+
+template<typename Key, typename Value, typename Hash>
+void DCE2_DbMap<Key, Value, Hash>::Remove(const Key& key)
+{
+    auto elem = Map.find(key);
+    if (elem != Map.end())
+    {
+        if (garbage_collection)
+            delete elem->second;
+
+        Map.erase(elem->first);
+    }
+}
+
+template<typename Key, typename Value, typename Hash>
+std::vector< std::pair<Key, Value> >DCE2_DbMap<Key, Value, Hash>::get_all_entry()
+{
+    std::vector<std::pair<Key, Value> > vec;
+    std::copy(Map.begin(), Map.end(), std::back_inserter(vec));
+    return vec;
+}
+
+#endif
+
index 38f672ae03613f16c4132026b783d8909c957f30..c260b991b7d9507911f530b80212c2351fcfdad3 100644 (file)
@@ -56,7 +56,7 @@ void DceExpSsnManager::create_expected_session(const SfIp* ept_ip,
 }
 
 DceTcpExpSsnManager::DceTcpExpSsnManager(const dce2TcpProtoConf& config) :
-    DceExpSsnManager(IpProtocol::TCP, PktType::TCP), pc(config) {}
+    DceExpSsnManager(IpProtocol::TCP, PktType::TCP), pc(config) { }
 
 int DceTcpExpSsnManager::create_expected_session_impl(Packet* pkt,
     const snort::SfIp* src_ip, uint16_t src_port,
@@ -84,3 +84,4 @@ int DceTcpExpSsnManager::create_expected_session_impl(Packet* pkt,
 
     return 0;
 }
+
index 26082c1866a1b1c89bcb03fcd1a1bc2894fdc3e5..6bdb3202e51c1a17489a458ef967333c85052b88 100644 (file)
@@ -37,7 +37,7 @@ class DceExpSsnManager
 {
 public:
     DceExpSsnManager(IpProtocol p, PktType t) :
-        proto(p), type(t) {}
+        proto(p), type(t) { }
 
     virtual ~DceExpSsnManager() = default;
 
@@ -70,9 +70,9 @@ class DceTcpExpSsnManager : public DceExpSsnManager
 {
 public:
     DceTcpExpSsnManager() = delete;
-    DceTcpExpSsnManager(const dce2TcpProtoConf&);
+    explicit DceTcpExpSsnManager(const dce2TcpProtoConf&);
     DceTcpExpSsnManager(const DceTcpExpSsnManager&) = delete;
-    DceTcpExpSsnManager& operator=(const DceTcpExpSsnManager&) =delete;
+    DceTcpExpSsnManager& operator=(const DceTcpExpSsnManager&) = delete;
 
 private:
     int create_expected_session_impl(snort::Packet*,
@@ -84,3 +84,4 @@ private:
 };
 
 #endif // DCE_EXPECTED_SESSION_H
+
index 75d13cbb70059bef5f2e0ec8ab6b238bd777ea55..aff67d328fb66e54fe99e3414b32fb4b03718777 100644 (file)
@@ -31,7 +31,7 @@ static const PegInfo dce_http_proxy_pegs[] =
     { CountType::END, nullptr, nullptr }
 };
 
-DceHttpProxyModule::DceHttpProxyModule() : Module(DCE_HTTP_PROXY_NAME, DCE_HTTP_PROXY_HELP)
+DceHttpProxyModule::DceHttpProxyModule() :   Module(DCE_HTTP_PROXY_NAME, DCE_HTTP_PROXY_HELP)
 {
 }
 
@@ -44,3 +44,4 @@ PegCount* DceHttpProxyModule::get_counts() const
 {
     return (PegCount*)&dce_http_proxy_stats;
 }
+
index 2e24b674e1f9918cb18aa8c850d0273d90b47635..86222d7cc2a37402087dd8fb4ec511e9c2e4d2bb 100644 (file)
@@ -54,9 +54,9 @@ StreamSplitter::Status DceHttpProxySplitter::scan(
     StreamSplitter::Status status;
 
     if ( (flags & PKT_FROM_CLIENT) != 0 )
-        status =  match_request_head( data, len );
+        status =  match_request_head(data, len);
     else if ( (flags & PKT_FROM_SERVER) != 0 )
-        status = match_response( data, len );
+        status = match_response(data, len);
     else
         return StreamSplitter::ABORT;
 
@@ -68,8 +68,7 @@ StreamSplitter::Status DceHttpProxySplitter::scan(
 }
 
 /* match_request_head() is only used by the c2s splitter instance. */
-StreamSplitter::Status
-    DceHttpProxySplitter::match_request_head(const uint8_t* data, uint32_t& len)
+StreamSplitter::Status DceHttpProxySplitter::match_request_head(const uint8_t* data, uint32_t& len)
 {
     if ( match_index == (unsigned int)strlen(HTTP_PROXY_REQUEST) )
     {
@@ -80,7 +79,7 @@ StreamSplitter::Status
     len = (len > strlen(HTTP_PROXY_REQUEST)) ? strlen(HTTP_PROXY_REQUEST) : len;
 
     if ( ((len+match_index) > strlen(HTTP_PROXY_REQUEST)) ||
-        memcmp( (const void*)data, (const void*)(&HTTP_PROXY_REQUEST[match_index]), len ) != 0 )
+        memcmp( (const void*)data, (const void*)(&HTTP_PROXY_REQUEST[match_index]), len) != 0 )
         return StreamSplitter::ABORT;
     else
     {
@@ -101,19 +100,18 @@ StreamSplitter::Status DceHttpProxySplitter::match_response_head(const uint8_t*
 
     len = (len > strlen(HTTP_PROXY_RESPONSE)) ? strlen(HTTP_PROXY_RESPONSE) : len;
 
-    if ( memcmp( (const void*)data, (const void*)(&HTTP_PROXY_RESPONSE[match_index]), len ) != 0 )
+    if ( memcmp( (const void*)data, (const void*)(&HTTP_PROXY_RESPONSE[match_index]), len) != 0 )
         return StreamSplitter::ABORT;
     else
     {
         match_index += len;
         return match_index == (unsigned int)strlen(HTTP_PROXY_RESPONSE) ?
-            StreamSplitter::FLUSH : StreamSplitter::SEARCH;
+               StreamSplitter::FLUSH : StreamSplitter::SEARCH;
     }
 }
 
 /* match_request() is only used by the s2c splitter instance. */
-StreamSplitter::Status
-    DceHttpProxySplitter::match_response(const uint8_t* data, const uint32_t& len)
+StreamSplitter::Status DceHttpProxySplitter::match_response(const uint8_t* data, const uint32_t& len)
 {
     uint32_t starting_index = 0;
 
@@ -148,7 +146,7 @@ StreamSplitter::Status
     return StreamSplitter::SEARCH;
 }
 
-DceHttpProxySplitter::DceHttpProxySplitter(bool c2s) : StreamSplitter(c2s)
+DceHttpProxySplitter::DceHttpProxySplitter(bool c2s) :   StreamSplitter(c2s)
 {
     cutover = false;
     match_index = 0;
@@ -358,3 +356,4 @@ TEST_CASE("DceHttpProxySplitter-scan - bad_3_proxy_response", "[http_proxy_split
 }
 
 #endif
+
index 1117dcd714acc0c473492da68386074b93bbc1f4..97324a4130c0cf908e500b7a96cee50c3a79e7b6 100644 (file)
@@ -31,7 +31,7 @@ static const PegInfo dce_http_server_pegs[] =
     { CountType::END, nullptr, nullptr }
 };
 
-DceHttpServerModule::DceHttpServerModule() : Module(DCE_HTTP_SERVER_NAME, DCE_HTTP_SERVER_HELP)
+DceHttpServerModule::DceHttpServerModule() :   Module(DCE_HTTP_SERVER_NAME, DCE_HTTP_SERVER_HELP)
 {
 }
 
@@ -44,3 +44,4 @@ PegCount* DceHttpServerModule::get_counts() const
 {
     return (PegCount*)&dce_http_server_stats;
 }
+
index afa589a5ac44fc3a94ae63d76a410334cea8f8e0..28736d7122becc698213a71a76a845a66674ad8b 100644 (file)
@@ -55,17 +55,17 @@ StreamSplitter::Status DceHttpServerSplitter::match(const uint8_t* data, uint32_
     len = (len > strlen(HTTP_SERVER_MARKER)) ? strlen(HTTP_SERVER_MARKER) : len;
 
     if ( ((len+match_index) > strlen(HTTP_SERVER_MARKER)) ||
-        memcmp( (const void*)data, (const void*)(&HTTP_SERVER_MARKER[match_index]), len ) != 0 )
+        memcmp( (const void*)data, (const void*)(&HTTP_SERVER_MARKER[match_index]), len) != 0 )
         return StreamSplitter::ABORT;
     else
     {
         match_index += len;
         return match_index == (unsigned int)strlen(HTTP_SERVER_MARKER) ?
-            StreamSplitter::FLUSH : StreamSplitter::SEARCH;
+               StreamSplitter::FLUSH : StreamSplitter::SEARCH;
     }
 }
 
-DceHttpServerSplitter::DceHttpServerSplitter(bool c2s) : StreamSplitter(c2s)
+DceHttpServerSplitter::DceHttpServerSplitter(bool c2s) :   StreamSplitter(c2s)
 {
     match_index = 0;
     cutover = false;
@@ -180,3 +180,4 @@ TEST_CASE("DceHttpServerSplitter-scan - extra_server", "[http_server_splitter]")
 }
 
 #endif
+
index 854ad8b9676f4b8e12838d9afd058c83a678f66b..606d7c8209cc9cac63e71c16f99ff43470a8ccda 100644 (file)
@@ -53,11 +53,11 @@ static void DCE2_ListInsertBefore(DCE2_List*, DCE2_ListNode*, DCE2_ListNode*);
  *      for inserting, finding, etc.
  *  DCE2_ListDataFree
  *      An optional function to call to free data in the list.
- *      If null is passed in, the user will have to manually free
+ *      If null  is passed in, the user will have to manually free
  *      the data.
  *  DCE2_ListKeyFree
  *      An optional function to call to free keys used in the list.
- *      If null is passed in, the user will have to manually free
+ *      If null  is passed in, the user will have to manually free
  *      the keys.
  *  int
  *      Flags that affect processing of the list.
@@ -66,7 +66,7 @@ static void DCE2_ListInsertBefore(DCE2_List*, DCE2_ListNode*, DCE2_ListNode*);
  * Returns:
  *  DCE2_List *
  *      Pointer to a valid list object.
- *      Null if an error occurs.
+ *      null  if an error occurs.
  *
  ********************************************************************/
 DCE2_List* DCE2_ListNew(DCE2_ListType type, DCE2_ListKeyCompare kc,
@@ -109,7 +109,6 @@ static void DCE2_ListInsertTail(DCE2_List* list, DCE2_ListNode* n)
     if ((list == nullptr) || (n == nullptr))
         return;
 
-
     if (list->tail == nullptr)
     {
         list->tail = list->head = n;
@@ -221,7 +220,7 @@ static void DCE2_ListInsertBefore(DCE2_List* list, DCE2_ListNode* insert, DCE2_L
  *          in the list and no duplicates are allowed.
  *      DCE2_RET__SUCCESS if a new node with key and data is
  *          successfully inserted into the list.
- *      DCE2_RET__ERROR if a null list object was passed in.
+ *      DCE2_RET__ERROR if a null  list object was passed in.
  *
  ********************************************************************/
 DCE2_Ret DCE2_ListInsert(DCE2_List* list, void* key, void* data)
@@ -309,7 +308,7 @@ DCE2_Ret DCE2_ListInsert(DCE2_List* list, void* key, void* data)
  * Returns:
  *  void *
  *      The data in the first node in the list.
- *      Null if the list object passed in is null, or there are
+ *      null  if the list object passed in is NULL, or there are
  *          no items in the list.
  *
  ********************************************************************/
@@ -342,7 +341,7 @@ void* DCE2_ListFirst(DCE2_List* list)
  * Returns:
  *  void *
  *      The data in the next node in the list.
- *      Null if the list object passed in is null, or we are at
+ *      null  if the list object passed in is NULL, or we are at
  *          the end of the list and there are no next nodes.
  *
  ********************************************************************/
@@ -372,7 +371,7 @@ void* DCE2_ListNext(DCE2_List* list)
  *
  * Removes all of the nodes in a list.  Does not delete the list
  * object itself.  Calls data free and key free functions for
- * data and key if they are not null.
+ * data and key if they are not NULL.
  *
  * Arguments:
  *  DCE2_List *
@@ -446,7 +445,7 @@ void DCE2_ListDestroy(DCE2_List* list)
  *  void *
  *      If the key is found, the data associated with the node
  *          is returned.
- *      Null is returned if the item cannot be found given the key.
+ *      null  is returned if the item cannot be found given the key.
  *
  ********************************************************************/
 void* DCE2_ListFind(DCE2_List* list, void* key)
@@ -579,7 +578,7 @@ DCE2_Ret DCE2_ListFindKey(DCE2_List* list, void* key)
  * Returns:
  *  DCE2_Ret
  *      DCE2_RET__ERROR if a node in the list with the specified
- *          key cannot be found or the list object passed in is null.
+ *          key cannot be found or the list object passed in is NULL.
  *      DCE2_RET__SUCCESS if the node is successfully removed from
  *          the list.
  *
@@ -688,7 +687,7 @@ void DCE2_ListRemoveCurrent(DCE2_List* list)
  * Arguments:
  *  DCE2_QueueDataFree
  *      An optional free function for the data inserted into
- *      the queue.  If null is passed in, the user will be
+ *      the queue.  If null  is passed in, the user will be
  *      responsible for freeing data left in the queue.
  *
  * Returns:
@@ -719,7 +718,7 @@ DCE2_Queue* DCE2_QueueNew(DCE2_QueueDataFree df)
  *
  * Returns:
  *  DCE2_Ret
- *      DCE2_RET__ERROR if the queue object passed in is null.
+ *      DCE2_RET__ERROR if the queue object passed in is NULL.
  *      DCE2_RET__SUCCESS if the data is successfully added to
  *          the queue.
  *
@@ -766,8 +765,8 @@ DCE2_Ret DCE2_QueueEnqueue(DCE2_Queue* queue, void* data)
  * Returns:
  *  void *
  *      The data in the first node in the queue.
- *      Null if there are no items in the queue or the queue object
- *          passed in is null.
+ *      null  if there are no items in the queue or the queue object
+ *          passed in is NULL.
  *
  ********************************************************************/
 void* DCE2_QueueDequeue(DCE2_Queue* queue)
@@ -808,7 +807,7 @@ void* DCE2_QueueDequeue(DCE2_Queue* queue)
  *
  * Removes all of the nodes in a queue.  Does not delete the queue
  * object itself.  Calls data free function for data if it is
- * not null.
+ * not NULL.
  *
  * Arguments:
  *  DCE2_Queue *
@@ -876,7 +875,7 @@ void DCE2_QueueDestroy(DCE2_Queue* queue)
  * Returns:
  *  void *
  *      The data in the first node in the queue.
- *      Null if the queue object passed in is null, or there are
+ *      null  if the queue object passed in is NULL, or there are
  *          no items in the queue.
  *
  ********************************************************************/
@@ -909,7 +908,7 @@ void* DCE2_QueueFirst(DCE2_Queue* queue)
  * Returns:
  *  void *
  *      The data in the next node in the queue.
- *      Null if the queue object passed in is null, or we are at
+ *      null  if the queue object passed in is NULL, or we are at
  *          the end of the queue and there are no next nodes.
  *
  ********************************************************************/
@@ -994,7 +993,7 @@ void DCE2_QueueRemoveCurrent(DCE2_Queue* queue)
  * Returns:
  *  void *
  *      The data in the last node in the queue.
- *      Null if the queue object passed in is null, or there are
+ *      null  if the queue object passed in is NULL, or there are
  *          no items in the queue.
  *
  ********************************************************************/
similarity index 68%
rename from src/service_inspectors/dce_rpc/dce_smb1.cc
rename to src/service_inspectors/dce_rpc/dce_smb.cc
index c6d72f394b7753948a24060e01ed87b932761b2a..d8cefaae9c42d0b1dd507285951168023c8c0ccc 100644 (file)
@@ -1,6 +1,5 @@
 //--------------------------------------------------------------------------
 // Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
 // by the Free Software Foundation.  You may not use, modify or distribute
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// dce_smb1.cc author Bhargava Jandhyala <bjandhya@cisco.com>
+// dce_smb.cc author Rashmi Pitre <rrp@cisco.com>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include "dce_smb1.h"
+#include "dce_smb.h"
+
+#include "detection/detection_engine.h"
+#include "file_api/file_service.h"
+#include "managers/inspector_manager.h"
+#include "protocols/packet.h"
 
-#include "dce_smb_utils.h"
+#include "dce_context_data.h"
+#include "dce_smb_commands.h"
+#include "dce_smb_module.h"
+#include "dce_smb_paf.h"
+#include "dce_smb_transaction.h"
+#include "dce_smb2.h"
+#include "dce_smb2_utils.h"
 
 using namespace snort;
 
+THREAD_LOCAL dce2SmbStats dce2_smb_stats;
+THREAD_LOCAL ProfileStats dce2_smb_pstat_main;
+
 //-------------------------------------------------------------------------
 // debug stuff
 //-------------------------------------------------------------------------
@@ -295,38 +308,215 @@ static const char* smb_com_strings[SMB_MAX_NUM_COMS] =
 const char* get_smb_com_string(uint8_t b)
 { return smb_com_strings[b]; }
 
-Dce2Smb1SessionData::Dce2Smb1SessionData(const Packet* p,
-    const dce2SmbProtoConf* proto) : Dce2SmbSessionData(p, proto)
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+class Dce2SmbInspector : public Inspector
+{
+public:
+    explicit Dce2SmbInspector(const dce2SmbProtoConf&);
+    ~Dce2SmbInspector() override;
+
+    void tinit() override;
+    void tterm() override;
+
+    void show(const SnortConfig*) const override;
+    void eval(Packet*) override;
+    void clear(Packet*) override;
+
+    StreamSplitter* get_splitter(bool c2s) override
+    { return new Dce2SmbSplitter(c2s); }
+
+    bool can_carve_files() const override
+    { return true; }
+
+private:
+    dce2SmbProtoConf config;
+};
+
+Dce2SmbInspector::Dce2SmbInspector(const dce2SmbProtoConf& pc) : config(pc)
 {
-    ssd = { };
-    ssd.max_outstanding_requests = 10;  // Until Negotiate/SessionSetupAndX
-    ssd.cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-    ssd.srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-    ssd.pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
-    ssd.uid = DCE2_SENTINEL;
-    ssd.tid = DCE2_SENTINEL;
-    ssd.ftracker.fid_v1 = DCE2_SENTINEL;
-    ssd.rtracker.mid = DCE2_SENTINEL;
-    ssd.dialect_index = dialect_index;
-    ssd.max_file_depth = max_file_depth;
-    ssd.sd = sd;
-    ssd.policy = policy;
-    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p, "smb1 session created\n");
-    dce2_smb_stats.total_smb1_sessions++;
 }
 
-Dce2Smb1SessionData::~Dce2Smb1SessionData()
+Dce2SmbInspector::~Dce2SmbInspector()
 {
-    DCE2_SmbDataFree(&ssd);
+    if (config.smb_invalid_shares)
+    {
+        DCE2_ListDestroy(config.smb_invalid_shares);
+    }
+}
+
+void Dce2SmbInspector::show(const SnortConfig*) const
+{
+    print_dce2_smb_conf(config);
+}
+
+void Dce2SmbInspector::eval(Packet* p)
+{
+    DCE2_SmbSsnData* dce2_smb_sess = nullptr;
+    DCE2_Smb2SsnData* dce2_smb2_sess = nullptr;
+    DCE2_SmbVersion smb_version = DCE2_SMB_VERSION_NULL;
+    Profile profile(dce2_smb_pstat_main);
+
+    if (p == nullptr)
+        return;
+
+    assert(p->has_tcp_data());
+    assert(p->flow);
+
+    reset_using_rpkt();
+
+    Dce2SmbFlowData* smb_flowdata = (Dce2SmbFlowData*)p->flow->get_flow_data(Dce2SmbFlowData::inspector_id);
+    if (smb_flowdata and smb_flowdata->dce2_smb_session_data)
+    {
+        smb_version = smb_flowdata->smb_version;
+        if (DCE2_SMB_VERSION_1 == smb_version)
+            dce2_smb_sess = (DCE2_SmbSsnData*)smb_flowdata->dce2_smb_session_data;
+        else
+            dce2_smb2_sess = (DCE2_Smb2SsnData*)smb_flowdata->dce2_smb_session_data;
+    }
+    else
+    {
+        smb_version = DCE2_Smb2Version(p);
+
+        if (DCE2_SMB_VERSION_1 == smb_version)
+        {
+            //1st packet of flow in smb1 session, create smb1 session and flowdata
+            dce2_smb_sess = dce2_create_new_smb_session(p, &config);
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL
+                , p, "smb1 session created\n");
+        }
+        else if (DCE2_SMB_VERSION_2 == smb_version)
+        {
+            //1st packet of flow in smb2 session, create smb2 session and flowdata
+            dce2_smb2_sess = dce2_create_new_smb2_session(p, &config);
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL
+                , p, "smb2 session created\n");
+        }
+        else
+        {
+            //smb_version is DCE2_SMB_VERSION_NULL
+            //This means there is no flow data and this is not an SMB packet
+            //if it is a TCP packet for smb data, the flow must have been
+            //already identified with version.
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL
+                , p, "non-smb packet detected\n");
+            return;
+        }
+    }
+
+    //  By this time we must know the smb version, have correct smb session data and created
+    // flowdata
+    p->packet_flags |= PKT_ALLOW_MULTIPLE_DETECT;
+    dce2_detected = 0;
+    p->endianness = new DceEndianness();
+
+    if (DCE2_SMB_VERSION_1 == smb_version)
+    {
+        DCE2_Smb1Process(dce2_smb_sess);
+        if (!dce2_detected)
+            DCE2_Detect(&dce2_smb_sess->sd);
+    }
+    else
+    {
+        DCE2_Smb2Process(dce2_smb2_sess);
+        if (!dce2_detected)
+            DCE2_Detect(&dce2_smb2_sess->sd);
+    }
+
+    delete(p->endianness);
+    p->endianness = nullptr;
 }
 
-void Dce2Smb1SessionData::process()
+void Dce2SmbInspector::clear(Packet* p)
 {
-    DCE2_Smb1Process(&ssd);
+    DCE2_SsnData* sd = get_dce2_session_data(p->flow);
+    if ( sd )
+        DCE2_ResetRopts(sd, p);
 }
 
-void Dce2Smb1SessionData::set_reassembled_data(uint8_t* nb_ptr,uint16_t co_len)
+void Dce2SmbInspector::tinit()
 {
-    DCE2_SmbSetRdata(&ssd, nb_ptr, co_len);
+    delete smb2_session_cache;
+    size_t smb_memcap = DCE2_ScSmbMemcap(&config);
+    DCE2_SmbSessionCacheInit(smb_memcap);
 }
 
+void Dce2SmbInspector::tterm()
+{
+    delete smb2_session_cache;
+    smb2_session_cache = nullptr;
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{
+    return new Dce2SmbModule;
+}
+
+static void mod_dtor(Module* m)
+{
+    delete m;
+}
+
+static void dce2_smb_init()
+{
+    Dce2SmbFlowData::init();
+    DCE2_SmbInitGlobals();
+    DCE2_SmbInitDeletePdu();
+    DceContextData::init(DCE2_TRANS_TYPE__SMB);
+}
+
+static Inspector* dce2_smb_ctor(Module* m)
+{
+    Dce2SmbModule* mod = (Dce2SmbModule*)m;
+    dce2SmbProtoConf config;
+    mod->get_data(config);
+    return new Dce2SmbInspector(config);
+}
+
+static void dce2_smb_dtor(Inspector* p)
+{
+    delete p;
+}
+
+static const char* dce2_bufs[] =
+{
+    "dce_iface",
+    "dce_stub_data",
+    "file_data",
+    nullptr
+};
+
+const InspectApi dce2_smb_api =
+{
+    {
+        PT_INSPECTOR,
+        sizeof(InspectApi),
+        INSAPI_VERSION,
+        0,
+        API_RESERVED,
+        API_OPTIONS,
+        DCE2_SMB_NAME,
+        DCE2_SMB_HELP,
+        mod_ctor,
+        mod_dtor
+    },
+    IT_SERVICE,
+    PROTO_BIT__PDU,
+    dce2_bufs,
+    "netbios-ssn",
+    dce2_smb_init,
+    nullptr, // pterm
+    nullptr, // tinit
+    nullptr, // tterm
+    dce2_smb_ctor,
+    dce2_smb_dtor,
+    nullptr, // ssn
+    nullptr  // reset
+};
+
diff --git a/src/service_inspectors/dce_rpc/dce_smb.h b/src/service_inspectors/dce_rpc/dce_smb.h
new file mode 100644 (file)
index 0000000..9baf3cf
--- /dev/null
@@ -0,0 +1,532 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2020 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// dce_smb.h author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#ifndef DCE_SMB_H
+#define DCE_SMB_H
+
+#include "dce_co.h"
+#include "hash/lru_cache_local.h"
+#include "protocols/packet.h"
+#include "profiler/profiler_defs.h"
+#include "smb_common.h"
+#include "smb_message.h"
+
+#include "trace/trace_api.h"
+#define SMB_DEBUG(module_name, module_id, log_level, p, ...) \
+    trace_logf(log_level, module_name, module_id, p, __VA_ARGS__)
+
+#define DCE2_SMB_NAME "dce_smb"
+#define DCE2_SMB_HELP "dce over smb inspection"
+#define DCE2_SMB_RPKT_TYPE_MAX 4
+#define DCE2_SMB_RPKT_TYPE_START 1
+
+#define DCE2_SMB_BAD_NBSS_TYPE 2
+#define DCE2_SMB_BAD_TYPE 3
+#define DCE2_SMB_BAD_ID 4
+#define DCE2_SMB_BAD_WCT 5
+#define DCE2_SMB_BAD_BCC 6
+#define DCE2_SMB_BAD_FORM 7
+#define DCE2_SMB_BAD_OFF 8
+#define DCE2_SMB_TDCNT_ZE 9
+#define DCE2_SMB_NB_LT_SMBHDR 10
+#define DCE2_SMB_NB_LT_COM 11
+#define DCE2_SMB_NB_LT_BCC 12
+#define DCE2_SMB_NB_LT_DSIZE 13
+#define DCE2_SMB_TDCNT_LT_DSIZE 14
+#define DCE2_SMB_DSENT_GT_TDCNT 15
+#define DCE2_SMB_BCC_LT_DSIZE 16
+#define DCE2_SMB_INVALID_DSIZE 17
+#define DCE2_SMB_EXCESSIVE_TREE_CONNECTS 18
+#define DCE2_SMB_EXCESSIVE_READS 19
+#define DCE2_SMB_EXCESSIVE_CHAINING 20
+#define DCE2_SMB_MULT_CHAIN_SS 21
+#define DCE2_SMB_MULT_CHAIN_TC 22
+#define DCE2_SMB_CHAIN_SS_LOGOFF 23
+#define DCE2_SMB_CHAIN_TC_TDIS 24
+#define DCE2_SMB_CHAIN_OPEN_CLOSE 25
+#define DCE2_SMB_INVALID_SHARE 26
+
+#define DCE2_SMB_V1 44
+#define DCE2_SMB_V2 45
+#define DCE2_SMB_INVALID_BINDING 46
+#define DCE2_SMB2_EXCESSIVE_COMPOUNDING 47
+#define DCE2_SMB_DCNT_ZERO 48
+#define DCE2_SMB_DCNT_MISMATCH 49
+#define DCE2_SMB_MAX_REQS_EXCEEDED 50
+#define DCE2_SMB_REQS_SAME_MID 51
+#define DCE2_SMB_DEPR_DIALECT_NEGOTIATED 52
+#define DCE2_SMB_DEPR_COMMAND_USED 53
+#define DCE2_SMB_UNUSUAL_COMMAND_USED 54
+#define DCE2_SMB_INVALID_SETUP_COUNT 55
+#define DCE2_SMB_MULTIPLE_NEGOTIATIONS 56
+#define DCE2_SMB_EVASIVE_FILE_ATTRS 57
+#define DCE2_SMB_INVALID_FILE_OFFSET 58
+#define DCE2_SMB_BAD_NEXT_COMMAND_OFFSET 59
+
+#define DCE2_SMB_BAD_NBSS_TYPE_STR "SMB - bad NetBIOS session service session type"
+#define DCE2_SMB_BAD_TYPE_STR  "SMB - bad SMB message type"
+#define DCE2_SMB_BAD_ID_STR "SMB - bad SMB Id (not \\xffSMB for SMB1 or not \\xfeSMB for SMB2)"
+#define DCE2_SMB_BAD_WCT_STR "SMB - bad word count or structure size"
+#define DCE2_SMB_BAD_BCC_STR  "SMB - bad byte count"
+#define DCE2_SMB_BAD_FORM_STR  "SMB - bad format type"
+#define DCE2_SMB_BAD_OFF_STR  "SMB - bad offset"
+#define DCE2_SMB_TDCNT_ZE_STR  "SMB - zero total data count"
+#define DCE2_SMB_NB_LT_SMBHDR_STR "SMB - NetBIOS data length less than SMB header length"
+#define DCE2_SMB_NB_LT_COM_STR   "SMB - remaining NetBIOS data length less than command length"
+#define DCE2_SMB_NB_LT_BCC_STR  "SMB - remaining NetBIOS data length less than command byte count"
+#define DCE2_SMB_NB_LT_DSIZE_STR \
+    "SMB - remaining NetBIOS data length less than command data size"
+#define DCE2_SMB_TDCNT_LT_DSIZE_STR \
+    "SMB - remaining total data count less than this command data size"
+#define DCE2_SMB_DSENT_GT_TDCNT_STR \
+    "SMB - total data sent (STDu64) greater than command total data expected"
+#define DCE2_SMB_BCC_LT_DSIZE_STR   "SMB - byte count less than command data size (STDu64)"
+#define DCE2_SMB_INVALID_DSIZE_STR  "SMB - invalid command data size for byte count"
+#define DCE2_SMB_EXCESSIVE_TREE_CONNECTS_STR \
+    "SMB - excessive tree connect requests with pending tree connect responses"
+#define DCE2_SMB_EXCESSIVE_READS_STR  "SMB - excessive read requests with pending read responses"
+#define DCE2_SMB_EXCESSIVE_CHAINING_STR  "SMB - excessive command chaining"
+#define DCE2_SMB_MULT_CHAIN_SS_STR   "SMB - multiple chained tree connect requests"
+#define DCE2_SMB_MULT_CHAIN_TC_STR   "SMB - multiple chained tree connect requests"
+#define DCE2_SMB_CHAIN_SS_LOGOFF_STR   "SMB - chained/compounded login followed by logoff"
+#define DCE2_SMB_CHAIN_TC_TDIS_STR \
+    "SMB - chained/compounded tree connect followed by tree disconnect"
+#define DCE2_SMB_CHAIN_OPEN_CLOSE_STR \
+    "SMB - chained/compounded open pipe followed by close pipe"
+#define DCE2_SMB_INVALID_SHARE_STR   "SMB - invalid share access"
+
+#define DCE2_SMB_V1_STR  "SMB - invalid SMB version 1 seen"
+#define DCE2_SMB_V2_STR  "SMB - invalid SMB version 2 seen"
+#define DCE2_SMB_INVALID_BINDING_STR "SMB - invalid user, tree connect, file binding"
+#define DCE2_SMB2_EXCESSIVE_COMPOUNDING_STR  "SMB - excessive command compounding"
+#define DCE2_SMB_DCNT_ZERO_STR   "SMB - zero data count"
+#define DCE2_SMB_DCNT_MISMATCH_STR "SMB - data count mismatch in command and format"
+#define DCE2_SMB_MAX_REQS_EXCEEDED_STR  "SMB - maximum number of outstanding requests exceeded"
+#define DCE2_SMB_REQS_SAME_MID_STR "SMB - outstanding requests with same MID"
+#define DCE2_SMB_DEPR_DIALECT_NEGOTIATED_STR  "SMB - deprecated dialect negotiated"
+#define DCE2_SMB_DEPR_COMMAND_USED_STR   "SMB - deprecated command used"
+#define DCE2_SMB_UNUSUAL_COMMAND_USED_STR "SMB - unusual command used"
+#define DCE2_SMB_INVALID_SETUP_COUNT_STR  "SMB - invalid setup count for command"
+#define DCE2_SMB_MULTIPLE_NEGOTIATIONS_STR \
+    "SMB - client attempted multiple dialect negotiations on session"
+#define DCE2_SMB_EVASIVE_FILE_ATTRS_STR \
+    "SMB - client attempted to create or set a file's attributes to readonly/hidden/system"
+#define DCE2_SMB_INVALID_FILE_OFFSET_STR \
+    "SMB - file offset provided is greater than file size specified"
+#define DCE2_SMB_BAD_NEXT_COMMAND_OFFSET_STR \
+    "SMB - next command specified in SMB2 header is beyond payload boundary"
+
+struct dce2SmbStats : public LruCacheLocalStats
+{
+    PegCount events;
+
+    PegCount co_pdus;
+    PegCount co_bind;
+    PegCount co_bind_ack;
+    PegCount co_alter_ctx;
+    PegCount co_alter_ctx_resp;
+    PegCount co_bind_nack;
+    PegCount co_request;
+    PegCount co_response;
+    PegCount co_cancel;
+    PegCount co_orphaned;
+    PegCount co_fault;
+    PegCount co_auth3;
+    PegCount co_shutdown;
+    PegCount co_reject;
+    PegCount co_ms_pdu;
+    PegCount co_other_req;
+    PegCount co_other_resp;
+    PegCount co_req_fragments;
+    PegCount co_resp_fragments;
+    PegCount co_cli_max_frag_size;
+    PegCount co_cli_min_frag_size;
+    PegCount co_cli_seg_reassembled;
+    PegCount co_cli_frag_reassembled;
+    PegCount co_srv_max_frag_size;
+    PegCount co_srv_min_frag_size;
+    PegCount co_srv_seg_reassembled;
+    PegCount co_srv_frag_reassembled;
+
+    PegCount smb_sessions;
+    PegCount smb_pkts;
+    PegCount smb_ignored_bytes;
+    PegCount smb_cli_seg_reassembled;
+    PegCount smb_srv_seg_reassembled;
+    PegCount smb_max_outstanding_requests;
+    //  FIXIT-M more peg count foo
+    /*uint64_t smb_com_stats[2][SMB_MAX_NUM_COMS];
+    uint64_t smb_chained_stats[2][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
+    // The +1 is for codes beyond the range of the highest valid subcommand code
+    // Indicates a bogus subcommand
+    uint64_t smb_trans_subcom_stats[2][TRANS_SUBCOM_MAX+1];
+    uint64_t smb_trans2_subcom_stats[2][TRANS2_SUBCOM_MAX+1];
+    uint64_t smb_nt_transact_subcom_stats[2][NT_TRANSACT_SUBCOM_MAX+1];
+    */
+    PegCount smb_files_processed;
+    /* SMB2 stats */
+    PegCount v2_setup;
+    PegCount v2_setup_err_resp;
+    PegCount v2_setup_inv_str_sz;
+    PegCount v2_setup_resp_hdr_err;
+    PegCount v2_tree_cnct;
+    PegCount v2_tree_cnct_err_resp;
+    PegCount v2_tree_cnct_ignored;
+    PegCount v2_tree_cnct_inv_str_sz;
+    PegCount v2_tree_cnct_resp_hdr_err;
+    PegCount v2_crt;
+    PegCount v2_crt_err_resp;
+    PegCount v2_crt_inv_file_data;
+    PegCount v2_crt_inv_str_sz;
+    PegCount v2_crt_resp_hdr_err;
+    PegCount v2_crt_req_hdr_err;
+    PegCount v2_crt_rtrkr_misng;
+    PegCount v2_crt_req_ipc;
+    PegCount v2_crt_tree_trkr_misng;
+    PegCount v2_wrt;
+    PegCount v2_wrt_err_resp;
+    PegCount v2_wrt_ignored;
+    PegCount v2_wrt_inv_str_sz;
+    PegCount v2_wrt_req_hdr_err;
+    PegCount v2_read;
+    PegCount v2_read_err_resp;
+    PegCount v2_read_ignored;
+    PegCount v2_read_inv_str_sz;
+    PegCount v2_read_rtrkr_misng;
+    PegCount v2_read_resp_hdr_err;
+    PegCount v2_read_req_hdr_err;
+    PegCount v2_setinfo;
+    PegCount v2_stinf_err_resp;
+    PegCount v2_stinf_ignored;
+    PegCount v2_stinf_inv_str_sz;
+    PegCount v2_stinf_req_ftrkr_misng;
+    PegCount v2_stinf_req_hdr_err;
+    PegCount v2_cls;
+    PegCount v2_cls_err_resp;
+    PegCount v2_cls_ignored;
+    PegCount v2_cls_inv_str_sz;
+    PegCount v2_cls_req_ftrkr_misng;
+    PegCount v2_cls_req_hdr_err;
+    PegCount v2_tree_discn;
+    PegCount v2_tree_discn_ignored;
+    PegCount v2_tree_discn_inv_str_sz;
+    PegCount v2_tree_discn_req_hdr_err;
+    PegCount v2_logoff;
+    PegCount v2_logoff_inv_str_sz;
+    PegCount v2_hdr_err;
+    PegCount v2_bad_next_cmd_offset;
+    PegCount v2_extra_file_data_err;
+    PegCount v2_inv_file_ctx_err;
+    PegCount v2_msgs_uninspected;
+    PegCount v2_cmpnd_req_lt_crossed;
+    PegCount concurrent_sessions;
+    PegCount max_concurrent_sessions;
+    PegCount total_smb1_sessions;
+    PegCount total_smb2_sessions;
+    PegCount total_encrypted_sessions;
+    PegCount total_mc_sessions;
+    PegCount v2_total_session_trackers;
+    PegCount v2_total_tree_trackers;
+    PegCount v2_total_file_trackers;
+    PegCount v2_updated_file_flows;
+    PegCount v2_ignored_file_processing;
+    PegCount v2_mc_file_transfers;
+    PegCount v2_ioctl;
+    PegCount v2_ioctl_err_resp;
+    PegCount v2_ioctl_inv_str_sz;
+    PegCount v2_ioctl_ignored;
+    PegCount total_sessions; // not used
+};
+
+extern THREAD_LOCAL dce2SmbStats dce2_smb_stats;
+extern THREAD_LOCAL snort::ProfileStats dce2_smb_pstat_main;
+
+enum DCE2_SmbSsnState
+{
+    DCE2_SMB_SSN_STATE__START         = 0x00,
+    DCE2_SMB_SSN_STATE__NEGOTIATED    = 0x01,
+    DCE2_SMB_SSN_STATE__FP_CLIENT     = 0x02,  // Fingerprinted client
+    DCE2_SMB_SSN_STATE__FP_SERVER     = 0x04   // Fingerprinted server
+};
+
+enum DCE2_SmbDataState
+{
+    DCE2_SMB_DATA_STATE__NETBIOS_HEADER,
+    DCE2_SMB_DATA_STATE__SMB_HEADER,
+    DCE2_SMB_DATA_STATE__NETBIOS_PDU
+};
+
+enum DCE2_SmbPduState
+{
+    DCE2_SMB_PDU_STATE__COMMAND,
+    DCE2_SMB_PDU_STATE__RAW_DATA
+};
+
+enum DCE2_SmbFileDirection
+{
+    DCE2_SMB_FILE_DIRECTION__UNKNOWN = 0,
+    DCE2_SMB_FILE_DIRECTION__UPLOAD,
+    DCE2_SMB_FILE_DIRECTION__DOWNLOAD
+};
+
+enum SmbAndXCom
+{
+    SMB_ANDX_COM__NONE,
+    SMB_ANDX_COM__OPEN_ANDX,
+    SMB_ANDX_COM__READ_ANDX,
+    SMB_ANDX_COM__WRITE_ANDX,
+    SMB_ANDX_COM__TREE_CONNECT_ANDX,
+    SMB_ANDX_COM__SESSION_SETUP_ANDX,
+    SMB_ANDX_COM__LOGOFF_ANDX,
+    SMB_ANDX_COM__NT_CREATE_ANDX,
+    SMB_ANDX_COM__MAX
+};
+
+struct DCE2_SmbWriteAndXRaw
+{
+    int remaining;  // A signed integer so it can be negative
+    DCE2_Buffer* buf;
+};
+
+struct DCE2_SmbFileChunk
+{
+    uint64_t offset;
+    uint32_t length;
+    uint8_t* data;
+};
+
+enum DCE2_SmbVersion
+{
+    DCE2_SMB_VERSION_NULL,
+    DCE2_SMB_VERSION_1,
+    DCE2_SMB_VERSION_2
+};
+
+struct DCE2_SmbFileTracker
+{
+    struct
+    {
+        int file_id;   // A signed integer so it can be set to sentinel
+        uint16_t u_id;
+        uint16_t tree_id;
+    } file_key;
+
+    bool is_ipc;
+    bool is_smb2;
+    char* file_name;
+    uint16_t file_name_size;
+    uint64_t file_name_hash;
+
+    union
+    {
+        struct
+        {
+            // If pipe has been set to byte mode via TRANS_SET_NMPIPE_STATE
+            bool byte_mode;
+
+            // For Windows 2000
+            bool used;
+
+            // For WriteAndX requests that use raw mode flag
+            // Windows only
+            DCE2_SmbWriteAndXRaw* writex_raw;
+
+            // Connection-oriented DCE/RPC tracker
+            DCE2_CoTracker* co_tracker;
+        } nmpipe;
+
+        struct
+        {
+            uint64_t file_size;
+            uint64_t file_offset;
+            uint64_t bytes_processed;
+            DCE2_List* file_chunks;
+            uint32_t bytes_queued;
+            DCE2_SmbFileDirection file_direction;
+            bool sequential_only;
+        } file;
+    } tracker;
+
+    DCE2_SmbPduState smb2_pdu_state;
+
+#define fid_v1                file_key.file_id
+#define uid_v1                file_key.u_id
+#define tid_v1                file_key.tree_id
+#define fp_byte_mode   tracker.nmpipe.byte_mode
+#define fp_used        tracker.nmpipe.used
+#define fp_writex_raw  tracker.nmpipe.writex_raw
+#define fp_co_tracker  tracker.nmpipe.co_tracker
+#define ff_file_size          tracker.file.file_size
+#define ff_file_offset        tracker.file.file_offset
+#define ff_bytes_processed    tracker.file.bytes_processed
+#define ff_file_direction     tracker.file.file_direction
+#define ff_file_chunks        tracker.file.file_chunks
+#define ff_bytes_queued       tracker.file.bytes_queued
+#define ff_sequential_only    tracker.file.sequential_only
+};
+
+struct Smb2Request
+{
+    uint64_t message_id;   /* identifies a message uniquely on connection */
+    uint64_t offset;       /* data offset */
+    uint64_t file_id;      /* file id */
+    struct Smb2Request* next;
+    struct Smb2Request* previous;
+};
+
+struct DCE2_SmbTransactionTracker
+{
+    int smb_type;
+    uint8_t subcom;
+    bool one_way;
+    bool disconnect_tid;
+    bool pipe_byte_mode;
+    uint32_t tdcnt;
+    uint32_t dsent;
+    DCE2_Buffer* dbuf;
+    uint32_t tpcnt;
+    uint32_t psent;
+    DCE2_Buffer* pbuf;
+    // For Transaction2/Query File Information
+    uint16_t info_level;
+};
+
+struct DCE2_SmbRequestTracker
+{
+    int smb_com;
+
+    int mid;   // A signed integer so it can be set to sentinel
+    uint16_t uid;
+    uint16_t tid;
+    uint16_t pid;
+
+    // For WriteRaw
+    bool writeraw_writethrough;
+    uint32_t writeraw_remaining;
+
+    // For Transaction/Transaction2/NtTransact
+    DCE2_SmbTransactionTracker ttracker;
+
+    // Client can chain a write to an open.  Need to write data, but also
+    // need to associate tracker with fid returned from server
+    DCE2_Queue* ft_queue;
+
+    // This is a reference to an existing file tracker
+    DCE2_SmbFileTracker* ftracker;
+
+    // Used for requests to cache data that will ultimately end up in
+    // the file tracker upon response.
+    char* file_name;
+    uint16_t file_name_size;
+    uint64_t file_size;
+    uint64_t file_offset;
+    bool sequential_only;
+
+    // For TreeConnect to know whether it's to IPC
+    bool is_ipc;
+};
+
+struct DCE2_SmbSsnData
+{
+    DCE2_SsnData sd;  // This member must be first
+    DCE2_Policy policy;
+
+    int dialect_index;
+    int ssn_state_flags;
+
+    DCE2_SmbDataState cli_data_state;
+    DCE2_SmbDataState srv_data_state;
+
+    DCE2_SmbPduState pdu_state;
+
+    int uid;   // A signed integer so it can be set to sentinel
+    int tid;   // A signed integer so it can be set to sentinel
+    DCE2_List* uids;
+    DCE2_List* tids;
+
+    // For tracking files and named pipes
+    DCE2_SmbFileTracker ftracker;
+    DCE2_List* ftrackers;  // List of DCE2_SmbFileTracker
+
+    // For tracking requests / responses
+    DCE2_SmbRequestTracker rtracker;
+    DCE2_Queue* rtrackers;
+    uint16_t max_outstanding_requests;
+    uint16_t outstanding_requests;
+
+    // The current pid/mid node for this request/response
+    DCE2_SmbRequestTracker* cur_rtracker;
+
+    // Used for TCP segmentation to get full PDU
+    DCE2_Buffer* cli_seg;
+    DCE2_Buffer* srv_seg;
+
+    // These are used for commands we don't need to process
+    uint32_t cli_ignore_bytes;
+    uint32_t srv_ignore_bytes;
+
+    // The file API supports one concurrent upload/download per session.
+    // This is a reference to a file tracker so shouldn't be freed.
+    DCE2_SmbFileTracker* fapi_ftracker;
+
+    DCE2_SmbFileTracker* fb_ftracker;
+    bool block_pdus;
+
+    // Maximum file depth as returned from file API
+    int64_t max_file_depth;
+};
+
+struct DCE2_SmbFsm
+{
+    char input;
+    int next_state;
+    int fail_state;
+};
+
+class Dce2SmbFlowData : public snort::FlowData
+{
+public:
+    Dce2SmbFlowData();
+    ~Dce2SmbFlowData() override;
+
+    static void init()
+    { inspector_id = snort::FlowData::create_flow_data_id(); }
+
+    size_t size_of() override
+    { return sizeof(*this); }
+
+public:
+    static unsigned inspector_id;
+    DCE2_SmbVersion smb_version;
+    void* dce2_smb_session_data;
+};
+
+// Used for reassembled packets
+#define DCE2_MOCK_HDR_LEN__SMB_CLI \
+    ((unsigned)(sizeof(NbssHdr) + sizeof(SmbNtHdr) + sizeof(SmbWriteAndXReq)))
+#define DCE2_MOCK_HDR_LEN__SMB_SRV \
+    ((unsigned)(sizeof(NbssHdr) + sizeof(SmbNtHdr) + sizeof(SmbReadAndXResp)))
+
+DCE2_SsnData* get_dce2_session_data(snort::Flow*);
+
+const char* get_smb_com_string(uint8_t);
+#endif
+
diff --git a/src/service_inspectors/dce_rpc/dce_smb1.h b/src/service_inspectors/dce_rpc/dce_smb1.h
deleted file mode 100644 (file)
index 958b9c3..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb1.h author Bhargava Jandhyala <bjandhya@cisco.com>
-
-#ifndef DCE_SMB1_H
-#define DCE_SMB1_H
-
-// This provides smb session data and SMBv1 specific trackers
-
-#include "protocols/packet.h"
-#include "profiler/profiler_defs.h"
-
-#include "dce_co.h"
-#include "dce_smb_common.h"
-#include "dce_smb_module.h"
-#include "smb_message.h"
-
-enum DCE2_SmbSsnState
-{
-    DCE2_SMB_SSN_STATE__START         = 0x00,
-    DCE2_SMB_SSN_STATE__NEGOTIATED    = 0x01,
-    DCE2_SMB_SSN_STATE__FP_CLIENT     = 0x02,  // Fingerprinted client
-    DCE2_SMB_SSN_STATE__FP_SERVER     = 0x04   // Fingerprinted server
-};
-
-enum DCE2_SmbDataState
-{
-    DCE2_SMB_DATA_STATE__NETBIOS_HEADER,
-    DCE2_SMB_DATA_STATE__SMB_HEADER,
-    DCE2_SMB_DATA_STATE__NETBIOS_PDU
-};
-
-enum DCE2_SmbFileDirection
-{
-    DCE2_SMB_FILE_DIRECTION__UNKNOWN = 0,
-    DCE2_SMB_FILE_DIRECTION__UPLOAD,
-    DCE2_SMB_FILE_DIRECTION__DOWNLOAD
-};
-
-enum SmbAndXCom
-{
-    SMB_ANDX_COM__NONE,
-    SMB_ANDX_COM__OPEN_ANDX,
-    SMB_ANDX_COM__READ_ANDX,
-    SMB_ANDX_COM__WRITE_ANDX,
-    SMB_ANDX_COM__TREE_CONNECT_ANDX,
-    SMB_ANDX_COM__SESSION_SETUP_ANDX,
-    SMB_ANDX_COM__LOGOFF_ANDX,
-    SMB_ANDX_COM__NT_CREATE_ANDX,
-    SMB_ANDX_COM__MAX
-};
-
-struct DCE2_SmbWriteAndXRaw
-{
-    int remaining;  // A signed integer so it can be negative
-    DCE2_Buffer* buf;
-};
-
-struct DCE2_SmbFileChunk
-{
-    uint64_t offset;
-    uint32_t length;
-    uint8_t* data;
-};
-
-struct DCE2_SmbFileTracker
-{
-    struct
-    {
-        int file_id;   // A signed integer so it can be set to sentinel
-        uint16_t u_id;
-        uint16_t tree_id;
-    } file_key;
-
-    bool is_ipc;
-    bool is_smb2;
-    char* file_name;
-    uint16_t file_name_size;
-    uint64_t file_name_hash;
-
-    union
-    {
-        struct
-        {
-            // If pipe has been set to byte mode via TRANS_SET_NMPIPE_STATE
-            bool byte_mode;
-
-            // For Windows 2000
-            bool used;
-
-            // For WriteAndX requests that use raw mode flag
-            // Windows only
-            DCE2_SmbWriteAndXRaw* writex_raw;
-
-            // Connection-oriented DCE/RPC tracker
-            DCE2_CoTracker* co_tracker;
-        } nmpipe;
-
-        struct
-        {
-            uint64_t file_size;
-            uint64_t file_offset;
-            uint64_t bytes_processed;
-            DCE2_List* file_chunks;
-            uint32_t bytes_queued;
-            DCE2_SmbFileDirection file_direction;
-            bool sequential_only;
-        } file;
-    } tracker;
-
-#define fid_v1                file_key.file_id
-#define uid_v1                file_key.u_id
-#define tid_v1                file_key.tree_id
-#define fp_byte_mode   tracker.nmpipe.byte_mode
-#define fp_used        tracker.nmpipe.used
-#define fp_writex_raw  tracker.nmpipe.writex_raw
-#define fp_co_tracker  tracker.nmpipe.co_tracker
-#define ff_file_size          tracker.file.file_size
-#define ff_file_offset        tracker.file.file_offset
-#define ff_bytes_processed    tracker.file.bytes_processed
-#define ff_file_direction     tracker.file.file_direction
-#define ff_file_chunks        tracker.file.file_chunks
-#define ff_bytes_queued       tracker.file.bytes_queued
-#define ff_sequential_only    tracker.file.sequential_only
-};
-
-struct Smb2Request
-{
-    uint64_t message_id;   /* identifies a message uniquely on connection */
-    uint64_t offset;       /* data offset */
-    uint64_t file_id;      /* file id */
-    struct Smb2Request* next;
-    struct Smb2Request* previous;
-};
-
-struct DCE2_SmbTransactionTracker
-{
-    int smb_type;
-    uint8_t subcom;
-    bool one_way;
-    bool disconnect_tid;
-    bool pipe_byte_mode;
-    uint32_t tdcnt;
-    uint32_t dsent;
-    DCE2_Buffer* dbuf;
-    uint32_t tpcnt;
-    uint32_t psent;
-    DCE2_Buffer* pbuf;
-    // For Transaction2/Query File Information
-    uint16_t info_level;
-};
-
-struct DCE2_SmbRequestTracker
-{
-    int smb_com;
-
-    int mid;   // A signed integer so it can be set to sentinel
-    uint16_t uid;
-    uint16_t tid;
-    uint16_t pid;
-
-    // For WriteRaw
-    bool writeraw_writethrough;
-    uint32_t writeraw_remaining;
-
-    // For Transaction/Transaction2/NtTransact
-    DCE2_SmbTransactionTracker ttracker;
-
-    // Client can chain a write to an open.  Need to write data, but also
-    // need to associate tracker with fid returned from server
-    DCE2_Queue* ft_queue;
-
-    // This is a reference to an existing file tracker
-    DCE2_SmbFileTracker* ftracker;
-
-    // Used for requests to cache data that will ultimately end up in
-    // the file tracker upon response.
-    char* file_name;
-    uint16_t file_name_size;
-    uint64_t file_size;
-    uint64_t file_offset;
-    bool sequential_only;
-
-    // For TreeConnect to know whether it's to IPC
-    bool is_ipc;
-};
-
-struct DCE2_SmbSsnData
-{
-    DCE2_SsnData sd;  // This member must be first
-    DCE2_Policy policy;
-
-    int dialect_index;
-    int ssn_state_flags;
-
-    DCE2_SmbDataState cli_data_state;
-    DCE2_SmbDataState srv_data_state;
-
-    Dce2SmbPduState pdu_state;
-
-    int uid;   // A signed integer so it can be set to sentinel
-    int tid;   // A signed integer so it can be set to sentinel
-    DCE2_List* uids;
-    DCE2_List* tids;
-
-    // For tracking files and named pipes
-    DCE2_SmbFileTracker ftracker;
-    DCE2_List* ftrackers;  // List of DCE2_SmbFileTracker
-
-    // For tracking requests / responses
-    DCE2_SmbRequestTracker rtracker;
-    DCE2_Queue* rtrackers;
-    uint16_t max_outstanding_requests;
-    uint16_t outstanding_requests;
-
-    // The current pid/mid node for this request/response
-    DCE2_SmbRequestTracker* cur_rtracker;
-
-    // Used for TCP segmentation to get full PDU
-    DCE2_Buffer* cli_seg;
-    DCE2_Buffer* srv_seg;
-
-    // These are used for commands we don't need to process
-    uint32_t cli_ignore_bytes;
-    uint32_t srv_ignore_bytes;
-
-    // The file API supports one concurrent upload/download per session.
-    // This is a reference to a file tracker so shouldn't be freed.
-    DCE2_SmbFileTracker* fapi_ftracker;
-
-    DCE2_SmbFileTracker* fb_ftracker;
-    bool block_pdus;
-
-    // Maximum file depth as returned from file API
-    int64_t max_file_depth;
-};
-
-struct DCE2_SmbFsm
-{
-    char input;
-    int next_state;
-    int fail_state;
-};
-
-// Used for reassembled packets
-#define DCE2_MOCK_HDR_LEN__SMB_CLI \
-    ((unsigned)(sizeof(NbssHdr) + sizeof(SmbNtHdr) + sizeof(SmbWriteAndXReq)))
-#define DCE2_MOCK_HDR_LEN__SMB_SRV \
-    ((unsigned)(sizeof(NbssHdr) + sizeof(SmbNtHdr) + sizeof(SmbReadAndXResp)))
-
-DCE2_SsnData* get_dce2_session_data(snort::Flow*);
-
-const char* get_smb_com_string(uint8_t);
-
-class Dce2Smb1SessionData : public Dce2SmbSessionData
-{
-public:
-    Dce2Smb1SessionData() = delete;
-    Dce2Smb1SessionData(const snort::Packet*, const dce2SmbProtoConf* proto);
-    ~Dce2Smb1SessionData() override;
-    void process() override;
-    void handle_retransmit(FilePosition, FileVerdict) override { }
-    void set_reassembled_data(uint8_t*, uint16_t) override;
-
-private:
-    DCE2_SmbSsnData ssd;
-};
-
-#endif
-
index 53bf47e4cdebe683cceaed74f16480bf94998664..e1f3bbdf226150ded2eaaa7226a7810422342089 100644 (file)
 #endif
 
 #include "dce_smb2.h"
-
+#include "dce_smb2_commands.h"
 #include "detection/detection_util.h"
-#include "flow/flow_key.h"
 #include "stream/stream.h"
 
-#include "dce_smb2_file.h"
-#include "dce_smb2_session.h"
-#include "dce_smb2_session_cache.h"
-#include "dce_smb2_tree.h"
-
 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",
@@ -58,254 +49,268 @@ const char* smb2_command_string[SMB2_COM_MAX] =
     "SMB2_COM_CHANGE_NOTIFY",
     "SMB2_COM_QUERY_INFO",
     "SMB2_COM_SET_INFO",
-    "SMB2_COM_OPLOCK_BREAK"
-};
+    "SMB2_COM_OPLOCK_BREAK" };
 
-static inline uint64_t Smb2Sid(const Smb2Hdr* hdr)
+DCE2_Smb2RequestTracker::DCE2_Smb2RequestTracker(uint64_t file_id_v,
+    uint64_t offset_v) :   file_id(file_id_v), offset(offset_v)
 {
-    return alignedNtohq(&(hdr->session_id));
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        GET_CURRENT_PACKET, "Request tracker created with file_id = 0x%" PRIx64 " offset = %" PRIu64 "\n", file_id,
+        offset);
 }
 
-static inline bool Smb2Error(const Smb2Hdr* hdr)
+DCE2_Smb2RequestTracker::DCE2_Smb2RequestTracker(char* fname_v,
+    uint16_t fname_len_v) :   fname(fname_v), fname_len(fname_len_v)
 {
-    return (SMB_NT_STATUS_SEVERITY__ERROR == (uint8_t)(hdr->status >> 30));
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        GET_CURRENT_PACKET, "Request tracker created\n");
 }
 
-uint32_t get_smb2_flow_key(const FlowKey* flow_key)
+DCE2_Smb2RequestTracker::~DCE2_Smb2RequestTracker()
 {
-    Smb2FlowKey key;
-
-    key.ip_l[0] = flow_key->ip_l[0];
-    key.ip_l[1] = flow_key->ip_l[1];
-    key.ip_l[2] = flow_key->ip_l[2];
-    key.ip_l[3] = flow_key->ip_l[3];
-    key.ip_h[0] = flow_key->ip_h[0];
-    key.ip_h[1] = flow_key->ip_h[1];
-    key.ip_h[2] = flow_key->ip_h[2];
-    key.ip_h[3] = flow_key->ip_h[3];
-    key.mplsLabel = flow_key->mplsLabel;
-    key.port_l = flow_key->port_l;
-    key.port_h = flow_key->port_h;
-    key.group_l = flow_key->group_l;
-    key.group_h = flow_key->group_h;
-    key.vlan_tag = flow_key->vlan_tag;
-    key.addressSpaceId = flow_key->addressSpaceId;
-    key.ip_protocol = flow_key->ip_protocol;
-    key.pkt_type = (uint8_t)flow_key->pkt_type;
-    key.version = flow_key->version;
-    key.padding = key.padding16 = 0;
-
-    Smb2KeyHash hasher;
-    return hasher(key);
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        nullptr, "Request tracker terminating\n");
+    if (fname)
+        snort_free(fname);
 }
 
-//Dce2Smb2SessionData member functions
-
-Dce2Smb2SessionData::Dce2Smb2SessionData(const Packet* p,
-    const dce2SmbProtoConf* proto) : Dce2SmbSessionData(p, proto)
+DCE2_Smb2FileTracker::DCE2_Smb2FileTracker(uint64_t file_id_v, DCE2_Smb2TreeTracker* ttr_v,
+    DCE2_Smb2SessionTracker* str_v, Flow* flow_v) :   file_id(file_id_v), ttr(ttr_v),
+    str(str_v), parent_flow(flow_v), ignore(false), upload(false), multi_channel_file(false)
 {
-    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");
-    dce2_smb_stats.total_smb2_sessions++;
-    vlan_id = p->get_flow_vlan_id();
+    dce2_smb_stats.v2_total_file_trackers++;
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        GET_CURRENT_PACKET, "File tracker 0x%" PRIx64 " created\n", file_id);
+    str->update_cache_size(sizeof(DCE2_Smb2FileTracker));
 }
 
-Dce2Smb2SessionData::~Dce2Smb2SessionData(void)
+DCE2_Smb2FileTracker::~DCE2_Smb2FileTracker(void)
 {
-    for (auto it_session : connected_sessions)
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        nullptr, "File tracker with file id: 0x%" PRIx64 " tracker terminating\n", file_id);
+    auto all_conn_trackers = str->conn_trackers.get_all_entry();
+    for ( auto& h : all_conn_trackers )
     {
-        it_session.second->detach_flow(flow_key);
-        it_session.second->set_file_context_cleaned(true);
+        if (h.second->ftracker_tcp)
+        {
+            if (h.second->ftracker_tcp == this)
+            {
+                h.second->ftracker_tcp = nullptr;
+                h.second->ftracker_local = nullptr;
+            }
+        }
     }
-
-    if (get_tcp_file_tracker() && !(get_tcp_file_tracker()->get_flow_state_map().empty()))
+    if (multi_channel_file)
+        dce2_smb_stats.v2_mc_file_transfers++;
+    if (co_tracker != nullptr)
     {
-        get_tcp_file_tracker()->get_flow_state_map().erase(flow_key);
+        DCE2_CoCleanTracker(co_tracker);
+        snort_free((void*)co_tracker);
     }
-    if (tcp_file_tracker and tcp_file_tracker->get_flow_key() == flow_key )
-        tcp_file_tracker->set_flow_key(0);
-    tcp_file_tracker = nullptr;
+    str->update_cache_size(-(int)sizeof(DCE2_Smb2FileTracker));
 }
 
-void Dce2Smb2SessionData::reset_matching_tcp_file_tracker(
-    Dce2Smb2FileTrackerPtr file_tracker)
+DCE2_Smb2TreeTracker::DCE2_Smb2TreeTracker (uint32_t tid_v, uint8_t share_type_v) :
+    share_type(share_type_v), tid(tid_v)
 {
-    std::lock_guard<std::mutex> guard(tcp_file_tracker_mutex);
-    if (tcp_file_tracker == file_tracker)
-    {
-        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;
-        }
-        else
-            return;
-    }
+    dce2_smb_stats.v2_total_tree_trackers++;
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        GET_CURRENT_PACKET, "Tree tracker %" PRIu32 " created\n", tid);
 }
 
-Smb2SessionKey Dce2Smb2SessionData::get_session_key(uint64_t session_id)
+DCE2_Smb2TreeTracker::~DCE2_Smb2TreeTracker(void)
 {
-    Smb2SessionKey key;
-    Flow* flow = DetectionEngine::get_current_packet()->flow;
-    memcpy(key.cip, flow->client_ip.get_ip6_ptr(), 4*sizeof(uint32_t));
-    memcpy(key.sip, flow->server_ip.get_ip6_ptr(), 4*sizeof(uint32_t));
-    key.sid = session_id;
-    key.cgroup = flow->client_group;
-    key.sgroup = flow->server_group;
-    key.asid = flow->key->addressSpaceId;
-    return key;
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        nullptr, "Tree tracker %" PRIu32 " terminating\n", tid);
 }
 
-Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::find_session(uint64_t session_id)
+DCE2_Smb2SessionTracker::DCE2_Smb2SessionTracker(uint64_t sid) :   conn_trackers(false), session_id(sid),
+    encryption_flag(0)
 {
-    std::lock_guard<std::recursive_mutex> guard(session_data_mutex);
-    auto it_session = connected_sessions.find(session_id);
+    update_cache_size((int)sizeof(DCE2_Smb2SessionTracker));
+    dce2_smb_stats.v2_total_session_trackers++;
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        GET_CURRENT_PACKET, "Session tracker 0x%" PRIx64 " created\n", session_id);
+}
 
-    if (it_session != connected_sessions.end())
+DCE2_Smb2SessionTracker::~DCE2_Smb2SessionTracker(void)
+{
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+        nullptr, "Session tracker 0x%" PRIx64 " terminating\n", session_id);
+    removeSessionFromAllConnection();
+    auto all_tree_trackers = tree_trackers.get_all_entry();
+    for ( auto& h : all_tree_trackers )
     {
-        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());
-        if (session->vlan_id != 0 and session->vlan_id !=
-            (DetectionEngine::get_current_packet()->get_flow_vlan_id()))
-            return nullptr;
-        return session;
+        removeTtracker(h.first);
     }
-    else
+    update_cache_size(-(int)sizeof(DCE2_Smb2SessionTracker));
+}
+
+void DCE2_Smb2SessionTracker::removeSessionFromAllConnection()
+{
+    auto all_conn_trackers = conn_trackers.get_all_entry();
+    auto all_tree_trackers = tree_trackers.get_all_entry();
+    for ( auto& h : all_conn_trackers )
     {
-        Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_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()))
+        if (h.second->ftracker_tcp)
         {
-            connected_sessions.insert(std::make_pair(session_id,session));
-            return session;
+            for (auto& t : all_tree_trackers)
+            {
+                DCE2_Smb2FileTracker* ftr = t.second->findFtracker(
+                    h.second->ftracker_tcp->file_id);
+                if (ftr and ftr == h.second->ftracker_tcp)
+                {
+                    h.second->ftracker_tcp = nullptr;
+                    h.second->ftracker_local = nullptr;
+                    break;
+                }
+            }
         }
-        else
-            return nullptr;
+        DCE2_Smb2RemoveSidInSsd(h.second, session_id);
     }
 }
 
-// Caller must ensure that the session is not already present in flow
-Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::create_session(uint64_t session_id)
+void DCE2_Smb2SessionTracker::update_cache_size(int size)
 {
-    Smb2SessionKey session_key = get_session_key(session_id);
-    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;
+    DCE2_SmbSessionCacheUpdateSize(size);
 }
 
-void Dce2Smb2SessionData::remove_session(uint64_t session_id)
+DCE2_Smb2SsnData::DCE2_Smb2SsnData()
 {
-    session_data_mutex.lock();
-    connected_sessions.erase(session_id);
-    session_data_mutex.unlock();
+    Packet* p = DetectionEngine::get_current_packet();
+    memset(&sd, 0, sizeof(DCE2_SsnData));
+    memset(&policy, 0, sizeof(DCE2_Policy));
+    dialect_index = 0;
+    ssn_state_flags = 0;
+    ftracker_tcp = nullptr;
+    smb_id = 0;
+    max_file_depth = FileService::get_max_file_depth();
+    max_outstanding_requests = 10;  // Until Negotiate
+    flow = p->flow;
+    SmbKeyHash hasher;
+    flow_key = hasher(*flow->key);
 }
 
-void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
-    const uint8_t* end)
+DCE2_Smb2SsnData::~DCE2_Smb2SsnData()
 {
-    const uint8_t* smb_data = (const uint8_t*)smb_hdr + SMB2_HEADER_LENGTH;
-    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
-    uint16_t command = alignedNtohs(&(smb_hdr->command));
-    uint64_t session_id = Smb2Sid(smb_hdr);
-    Dce2Smb2SessionTrackerPtr session;
-
-// Macro and shorthand to save some repetitive code
-// Should only be used in this function
-#define SMB2_COMMAND_TYPE(cmd, type) \
-    (structure_size == SMB2_ ## cmd ## _ ## type ## _STRUC_SIZE)
-
-#define SMB2_GET_COMMAND_TYPE(cmd) \
-    (SMB2_COMMAND_TYPE(ERROR,RESPONSE) and Smb2Error(smb_hdr)) ? \
-    SMB2_CMD_TYPE_ERROR_RESPONSE : (SMB2_COMMAND_TYPE(cmd, REQUEST) ? \
-    SMB2_CMD_TYPE_REQUEST : (SMB2_COMMAND_TYPE(cmd, RESPONSE) ? \
-    SMB2_CMD_TYPE_RESPONSE : SMB2_CMD_TYPE_INVALID))
-
-#define SMB2_HANDLE_HEADER_ERROR(cmd, type, counter) \
-    { \
-        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, \
-                "%s : smb data beyond end detected\n", \
-                smb2_command_string[command]); \
-            if (session) \
-            { \
-                session->set_do_not_delete(false); \
-                session->set_prev_comand(SMB2_COM_MAX); \
-            } \
-            return; \
-        } \
+    for (auto it = session_trackers.cbegin(), next_it = it; it != session_trackers.cend(); it = next_it)
+    {
+        ++next_it;
+        auto sptr = it->second.lock();
+        if (sptr)
+        {
+            if (flow_key)
+                sptr->removeConnectionTracker(flow_key); // remove tcp connection from session
+                                                         // tracker
+            auto ttrs = sptr->tree_trackers.get_all_entry();
+            for (const auto& titer: ttrs)
+            {
+                DCE2_Smb2TreeTracker* ttr = titer.second;
+                auto ftrs = ttr->file_trackers.get_all_entry();
+                for (const auto& fiter: ftrs)
+                {
+                    DCE2_Smb2FileTracker* ftr = fiter.second;
+                    if (flow == ftr->parent_flow)
+                        ftr->parent_flow = nullptr;
+                }
+            }
+        }
     }
+}
 
-#define SMB2_HANDLE_ERROR_RESPONSE(counter) \
-    { \
-        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", \
-                smb2_command_string[command]); \
-            if (session) \
-            { \
-                session->set_do_not_delete(false); \
-                session->set_prev_comand(SMB2_COM_MAX); \
-            } \
-            return; \
-        } \
-    }
+void DCE2_Smb2SsnData::set_reassembled_data(uint8_t* nb_ptr, uint16_t co_len)
+{
+    NbssHdr* nb_hdr = (NbssHdr*)nb_ptr;
+    SmbNtHdr* smb_hdr = (SmbNtHdr*)((uint8_t*)nb_hdr + sizeof(NbssHdr));
 
-#define SMB2_HANDLE_INVALID_STRUC_SIZE(counter) \
-    { \
-        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", \
-            smb2_command_string[command]); \
-        if (session) \
-        { \
-            session->set_do_not_delete(false); \
-            session->set_prev_comand(SMB2_COM_MAX); \
-        } \
-        return; \
-    }
+    uint32_t tid = (ftracker_tcp) ? ftracker_tcp->ttr->get_tid() : 0;
+    smb_hdr->smb_tid = alignedNtohl((const uint32_t*)&tid);
+
+    if (DetectionEngine::get_current_packet()->is_from_client())
+    {
+        Smb2WriteRequestHdr* write = (Smb2WriteRequestHdr*)((uint8_t*)smb_hdr + sizeof(SmbNtHdr));
+        uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(Smb2WriteRequestHdr) + co_len;
 
-    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
-        "%s : flow %" PRIu32 " mid %" PRIu64 " sid %" PRIu64 " tid %" PRIu32 "\n",
-        (command < SMB2_COM_MAX ? smb2_command_string[command] : "unknown"),
-        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 = 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))
+        if (nb_len > UINT16_MAX)
+            nb_len = UINT16_MAX;
+        write->structure_size = SMB2_WRITE_REQUEST_STRUC_SIZE;
+        nb_hdr->length = htons((uint16_t)nb_len);
+        if (ftracker_tcp)
+        {
+            uint64_t fid = ftracker_tcp->file_id;
+            write->fileId_persistent = alignedNtohq(&fid);
+            write->fileId_volatile = alignedNtohq(&fid);
+        }
+        else
+            write->fileId_persistent = write->fileId_volatile = 0;
+        write->length = alignedNtohs(&co_len);
+    }
+    else
     {
-        return;
+        Smb2ReadResponseHdr* read = (Smb2ReadResponseHdr*)((uint8_t*)smb_hdr + sizeof(SmbNtHdr));
+        uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(Smb2ReadResponseHdr) + co_len;
+
+        if (nb_len > UINT16_MAX)
+            nb_len = UINT16_MAX;
+
+        nb_hdr->length = htons((uint16_t)nb_len);
+        read->structure_size = SMB2_READ_RESPONSE_STRUC_SIZE;
+        read->length = alignedNtohs(&co_len);
     }
+}
 
-    if (session)
+static inline bool DCE2_Smb2FindSidTid(DCE2_Smb2SsnData* ssd, const uint64_t sid,
+    const uint32_t tid, const uint32_t mid, DCE2_Smb2SessionTracker** str, DCE2_Smb2TreeTracker** ttr, bool
+    lookup_cache = false)
+{
+    *str = DCE2_Smb2FindSidInSsd(ssd, sid).get();
+    if (!*str)
     {
-        session->set_do_not_delete(true);
-        session->set_prev_comand(command);
+        if (lookup_cache)
+            *str = DCE2_Smb2FindElseCreateSid(ssd, sid, false);
     }
+    if (!*str)
+        return false;
 
-    // Try to find the session.
-    // The case when session is not available will be handled per command.
+    if (!tid)
+        *ttr = ssd->GetTreeTrackerFromMessage(mid);
+    else
+        *ttr = (*str)->findTtracker(tid);
+
+    if (!*ttr)
+        return false;
+
+    return true;
+}
+
+// FIXIT-L port fileCache related code along with
+// DCE2_Smb2Init, DCE2_Smb2Close and DCE2_Smb2UpdateStats
+
+static void DCE2_Smb2Inspect(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* end)
+{
+    const uint8_t* smb_data = (const uint8_t*)smb_hdr + SMB2_HEADER_LENGTH;
+    uint16_t command = alignedNtohs(&(smb_hdr->command));
+    int16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+    DCE2_Smb2SessionTracker* str = nullptr;
+    DCE2_Smb2TreeTracker* ttr = nullptr;
+    uint32_t tid = 0;
+
+    uint64_t mid = Smb2Mid(smb_hdr);
+    uint64_t sid = Smb2Sid(smb_hdr);
+    /* Still process async commands*/
+    if (!(alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND))
+        tid = Smb2Tid(smb_hdr);
+
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+        DetectionEngine::get_current_packet(),
+        "%s : mid %" PRIu64 " sid 0x%" PRIx64 " tid %" PRIu32 "\n",
+        (command <= SMB2_COM_OPLOCK_BREAK ? smb2_command_string[command] : "unknown"),
+        mid, sid, tid);
     switch (command)
     {
-    //commands processed by flow
     case SMB2_COM_NEGOTIATE:
-        if (SMB2_COMMAND_TYPE(NEGOTIATE, RESPONSE))
+        if (structure_size == SMB2_NEGOTIATE_RESPONSE_STRUC_SIZE)
         {
             const Smb2NegotiateResponseHdr* neg_resp_hdr = (const
                 Smb2NegotiateResponseHdr*)smb_data;
@@ -313,243 +318,159 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
             {
                 //total multichannel sessions
                 dce2_smb_stats.total_mc_sessions++;
-                Packet* p = DetectionEngine::get_current_packet();
-                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,
-                        "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);
-
-                    if (result < 0)
-                    {
-                        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,
-                        "fd is null in negotiate , failed to create pinhole\n");
-                }
             }
         }
         break;
-    case SMB2_COM_SESSION_SETUP:
-        dce2_smb_stats.v2_setup++;
-        SMB2_HANDLE_ERROR_RESPONSE(setup)
-        if (SMB2_COMMAND_TYPE(SETUP, RESPONSE))
+    case SMB2_COM_CREATE:
+        if (!tid)
         {
-            SMB2_HANDLE_HEADER_ERROR(SETUP, RESPONSE, setup_resp)
-            if (!session)
-                create_session(session_id);
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
         }
-        else if (!SMB2_COMMAND_TYPE(SETUP, REQUEST))
-            SMB2_HANDLE_INVALID_STRUC_SIZE(setup)
-            break;
-
-    case SMB2_COM_LOGOFF:
-        dce2_smb_stats.v2_logoff++;
-        if (SMB2_COMMAND_TYPE(LOGOFF, REQUEST))
-            smb2_session_cache.remove(get_session_key(session_id));
-        else
-            SMB2_HANDLE_INVALID_STRUC_SIZE(logoff)
-            break;
-    //commands processed by session
-    case SMB2_COM_TREE_CONNECT:
-        dce2_smb_stats.v2_tree_cnct++;
-        SMB2_HANDLE_ERROR_RESPONSE(tree_cnct)
-        if (SMB2_COMMAND_TYPE(TREE_CONNECT, RESPONSE))
+        dce2_smb_stats.v2_crt++;
+        DCE2_Smb2Create(ssd, smb_hdr, smb_data, end, mid, sid, tid);
+        break;
+    case SMB2_COM_READ:
+        if (!tid)
         {
-            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);
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
+        }
+        dce2_smb_stats.v2_read++;
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr, true))
+        {
+            dce2_smb_stats.v2_read_ignored++;
+            return;
         }
-        else if (!SMB2_COMMAND_TYPE(TREE_CONNECT,REQUEST))
-            SMB2_HANDLE_INVALID_STRUC_SIZE(tree_cnct)
-            break;
-
-    case SMB2_COM_TREE_DISCONNECT:
-        dce2_smb_stats.v2_tree_discn++;
 
-        if (session)
+        DCE2_Smb2Read(ssd, smb_hdr, smb_data, end, str, ttr, mid);
+        break;
+    case SMB2_COM_WRITE:
+        if (!tid)
         {
-            if (SMB2_COMMAND_TYPE(TREE_DISCONNECT, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(TREE_DISCONNECT, REQUEST, tree_discn_req)
-                session->process(command, SMB2_CMD_TYPE_REQUEST, smb_hdr, end, flow_key);
-            }
-            else
-            {
-                SMB2_HANDLE_INVALID_STRUC_SIZE(tree_discn)
-            }
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
         }
-        else
-            dce2_smb_stats.v2_session_ignored++;
+        dce2_smb_stats.v2_wrt++;
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr, true))
+        {
+            dce2_smb_stats.v2_wrt_ignored++;
+            return;
+        }
+
+        DCE2_Smb2Write(ssd, smb_hdr, smb_data, end, str, ttr, mid);
         break;
-    //commands processed by tree
-    case SMB2_COM_CREATE:
-    {
-        dce2_smb_stats.v2_crt++;
-        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)
-
-                    if (!session)
-                        session = create_session(session_id);
-        if (!session)
+    case SMB2_COM_SET_INFO:
+        if (!tid)
+        {
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
+        }
+        dce2_smb_stats.v2_setinfo++;
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr))
+        {
+            dce2_smb_stats.v2_stinf_ignored++;
             return;
-        session->process(command, command_type, smb_hdr, end, flow_key);
-    }
-    break;
+        }
 
+        DCE2_Smb2SetInfo(ssd, smb_hdr, smb_data, end, ttr);
+        break;
     case SMB2_COM_CLOSE:
+        if (!tid)
+        {
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
+        }
         dce2_smb_stats.v2_cls++;
-        SMB2_HANDLE_ERROR_RESPONSE(cls)
-        if (session)
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr))
         {
-            if (SMB2_COMMAND_TYPE(CLOSE, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(CLOSE, REQUEST, cls_req)
-                session->process(command, SMB2_CMD_TYPE_REQUEST, smb_hdr, end, flow_key);
-            }
-            else if (!SMB2_COMMAND_TYPE(CLOSE, RESPONSE))
-            {
-                SMB2_HANDLE_INVALID_STRUC_SIZE(cls)
-            }
+            dce2_smb_stats.v2_cls_ignored++;
+            return;
         }
-        else
-            dce2_smb_stats.v2_session_ignored++;
-        break;
 
-    case SMB2_COM_SET_INFO:
-        dce2_smb_stats.v2_setinfo++;
-        SMB2_HANDLE_ERROR_RESPONSE(stinf)
-        if (session)
+        DCE2_Smb2CloseCmd(ssd, smb_hdr, smb_data, end, ttr, str, mid);
+        break;
+    case SMB2_COM_TREE_CONNECT:
+        dce2_smb_stats.v2_tree_cnct++;
+        // This will always return session tracker
+        str = DCE2_Smb2FindElseCreateSid(ssd, sid);
+        if (str)
         {
-            if (SMB2_COMMAND_TYPE(SET_INFO, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(SET_INFO, REQUEST, stinf_req)
-                session->process(command, SMB2_CMD_TYPE_REQUEST, smb_hdr, end, flow_key);
-            }
-            else if (!SMB2_COMMAND_TYPE(SET_INFO, RESPONSE))
-            {
-                SMB2_HANDLE_INVALID_STRUC_SIZE(stinf)
-            }
+            DCE2_Smb2TreeConnect(ssd, smb_hdr, smb_data, end, str, tid);
         }
-        else
-            dce2_smb_stats.v2_session_ignored++;
         break;
-
-    case SMB2_COM_READ:
-        dce2_smb_stats.v2_read++;
-        if (session)
+    case SMB2_COM_TREE_DISCONNECT:
+        dce2_smb_stats.v2_tree_discn++;
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr))
         {
-            uint8_t command_type;
-            if (SMB2_COMMAND_TYPE(ERROR, RESPONSE) and Smb2Error(smb_hdr))
-                command_type = SMB2_CMD_TYPE_ERROR_RESPONSE;
-            else if (SMB2_COMMAND_TYPE(READ, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(READ, REQUEST, read_req)
-                command_type = SMB2_CMD_TYPE_REQUEST;
-            }
-            else if (SMB2_COMMAND_TYPE(READ, RESPONSE))
-            {
-                SMB2_HANDLE_HEADER_ERROR(READ, RESPONSE, read_resp)
-                command_type = SMB2_CMD_TYPE_RESPONSE;
-            }
-            else
-                SMB2_HANDLE_INVALID_STRUC_SIZE(read)
-                session->process(command, command_type, smb_hdr, end, flow_key);
+            dce2_smb_stats.v2_tree_discn_ignored++;
+            return;
         }
-        else
-            dce2_smb_stats.v2_session_ignored++;
+        DCE2_Smb2TreeDisconnect(ssd, smb_data, end);
         break;
-
-    case SMB2_COM_WRITE:
-        dce2_smb_stats.v2_wrt++;
-        if (session)
+    case SMB2_COM_SESSION_SETUP:
+        dce2_smb_stats.v2_setup++;
+        DCE2_Smb2Setup(ssd, smb_hdr, sid, smb_data, end);
+        break;
+    case SMB2_COM_LOGOFF:
+        dce2_smb_stats.v2_logoff++;
+        DCE2_Smb2Logoff(ssd, smb_data, sid);
+        break;
+    case SMB2_COM_IOCTL:
+        if (!tid)
         {
-            uint8_t command_type;
-            if (SMB2_COMMAND_TYPE(ERROR, RESPONSE) and Smb2Error(smb_hdr))
-                command_type = SMB2_CMD_TYPE_ERROR_RESPONSE;
-            else if (SMB2_COMMAND_TYPE(WRITE, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(WRITE, REQUEST, wrt_req)
-                command_type = SMB2_CMD_TYPE_REQUEST;
-            }
-            else if (SMB2_COMMAND_TYPE(WRITE, RESPONSE))
-            {
-                SMB2_HANDLE_HEADER_ERROR(WRITE, RESPONSE, wrt_resp)
-                command_type = SMB2_CMD_TYPE_RESPONSE;
-            }
-            else
-                SMB2_HANDLE_INVALID_STRUC_SIZE(wrt)
-                session->process(command, command_type, smb_hdr, end, flow_key);
+            //Check request tracker for tid in Async case.
+            auto rtracker = ssd->findRtracker(mid);
+            if (rtracker)
+                tid = rtracker->get_tree_id();
+        }
+        if (!DCE2_Smb2FindSidTid(ssd, sid, tid, mid, &str, &ttr))
+        {
+            dce2_smb_stats.v2_ioctl_ignored++;
+            return;
+        }
+        else if (SMB2_SHARE_TYPE_DISK != ttr->get_share_type())
+        {
+            dce2_smb_stats.v2_ioctl++;
+            DCE2_Smb2IoctlCommand(ssd, smb_hdr, smb_data, end, str, ttr, mid);
         }
         else
-            dce2_smb_stats.v2_session_ignored++;
-        break;
-    case SMB2_COM_IOCTL:
-        if (session)
         {
-            if (SMB2_COMMAND_TYPE(IOCTL, REQUEST))
-            {
-                SMB2_HANDLE_HEADER_ERROR(IOCTL, REQUEST, ioctl_req)
-                session->process(command, SMB2_CMD_TYPE_REQUEST, smb_hdr, end, flow_key);
-            }
-            else if ( SMB2_COMMAND_TYPE(IOCTL, RESPONSE))
-            {
-                SMB2_HANDLE_HEADER_ERROR(IOCTL, RESPONSE, ioctl_resp)
-                session->process(command, SMB2_CMD_TYPE_RESPONSE, smb_hdr, end, flow_key);
-            }
-            else
-            {
-                SMB2_HANDLE_INVALID_STRUC_SIZE(ioctl)
-            }
+            dce2_smb_stats.v2_ioctl_ignored++;
+            return;
         }
         break;
     default:
         dce2_smb_stats.v2_msgs_uninspected++;
         break;
     }
-    if (session)
-    {
-        session->set_prev_comand(SMB2_COM_MAX);
-        session->set_do_not_delete(false);
-    }
 }
 
 // This is the main entry point for SMB2 processing.
-void Dce2Smb2SessionData::process()
+void DCE2_Smb2Process(DCE2_Smb2SsnData* ssd)
 {
     Packet* p = DetectionEngine::get_current_packet();
     const uint8_t* data_ptr = p->data;
     uint16_t data_len = p->dsize;
-    Dce2Smb2SessionTrackerPtr session = nullptr;
-
     // Process the header
     if (p->is_pdu_start())
     {
         // Check header length
         if (data_len < sizeof(NbssHdr) + SMB2_HEADER_LENGTH)
         {
-            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
-                p, "Header error with data length %d\n",data_len);
             dce2_smb_stats.v2_hdr_err++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p,
+                "Header error with data length %d\n",data_len);
             return;
         }
         const Smb2Hdr* smb_hdr = (const Smb2Hdr*)(data_ptr + sizeof(NbssHdr));
@@ -559,14 +480,12 @@ void Dce2Smb2SessionData::process()
         uint64_t sid = smb_trans_hdr->session_id;
         if (smb_proto_id == DCE2_SMB2_TRANS_ID)
         {
-            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
                 p, "Encrypted header is received \n");
-            session = find_session(sid);
+            DCE2_Smb2SessionTracker* session = DCE2_Smb2FindElseCreateSid(ssd, sid);
             if (session)
             {
-                bool flag = session->get_encryption_flag();
-                if (!flag)
-                    session->set_encryption_flag(true);
+                session->set_encryption_flag(true);
             }
         }
         uint32_t next_command_offset;
@@ -581,18 +500,16 @@ void Dce2Smb2SessionData::process()
         // multiple requests up to the maximum size<88> that is supported by the transport."
         do
         {
-            process_command(smb_hdr, data_ptr +  data_len);
+            DCE2_Smb2Inspect(ssd, smb_hdr, data_ptr +  data_len);
             // In case of message compounding, find the offset of the next smb command
             next_command_offset = alignedNtohl(&(smb_hdr->next_command));
             if (next_command_offset + (const uint8_t*)smb_hdr > (data_ptr + data_len))
             {
                 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");
+                    (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
+                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);
                 return;
             }
             if (next_command_offset)
@@ -601,105 +518,46 @@ void Dce2Smb2SessionData::process()
                 compound_request_index++;
             }
 
-            if (compound_request_index > get_smb_max_compound())
+            if (compound_request_index > DCE2_ScSmbMaxCompound((dce2SmbProtoConf*)ssd->sd.config))
             {
                 dce2_smb_stats.v2_cmpnd_req_lt_crossed++;
-                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);
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                    p, "compound req limit reached %" PRIu8 "\n",
+                    compound_request_index);
                 return;
             }
         }
         while (next_command_offset and smb_hdr);
     }
-    else
+    else if ( ssd->ftracker_tcp and ssd->ftracker_local and (ssd->ftracker_local->smb2_pdu_state ==
+        DCE2_SMB_PDU_STATE__RAW_DATA))
     {
-        if ( tcp_file_tracker )
-        {
-            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
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            p, "raw data file_name_hash %" PRIu64 " fid 0x%" PRIx64 " dir %s\n",
+            ssd->ftracker_tcp->file_name_hash, ssd->ftracker_tcp->file_id,
+            ssd->ftracker_tcp->upload ? "upload" : "download");
+
+        if (!DCE2_Smb2ProcessFileData(ssd, data_ptr, data_len))
             return;
-        tcp_file_tracker_mutex.lock();
-        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",
-                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 if (tcp_file_tracker and tcp_file_tracker.use_count() == 1)
-        {
-            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;
-            }
-        }
-        else
-        {
-            SMB_DEBUG(dce_smb_trace,DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
-                "not processing raw data\n");
-        }
-        tcp_file_tracker_mutex.unlock();
     }
-    if (session)
-        session->set_do_not_delete(false);
 }
 
-void Dce2Smb2SessionData::set_reassembled_data(uint8_t* nb_ptr, uint16_t co_len)
+// Check whether the packet is smb2
+DCE2_SmbVersion DCE2_Smb2Version(const Packet* p)
 {
-    NbssHdr* nb_hdr = (NbssHdr*)nb_ptr;
-    SmbNtHdr* smb_hdr = (SmbNtHdr*)((uint8_t*)nb_hdr + sizeof(NbssHdr));
-
-    tcp_file_tracker_mutex.lock();
-    uint32_t tid = (tcp_file_tracker) ? tcp_file_tracker->get_parent()->get_tree_id() : 0;
-    tcp_file_tracker_mutex.unlock();
-
-    smb_hdr->smb_tid = alignedNtohl((const uint32_t*)&tid);
-
-    if (DetectionEngine::get_current_packet()->is_from_client())
+    // Only check reassembled SMB2 packet
+    if ( p->has_paf_payload() and
+        (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE) )     // DCE2_SMB_ID is u32
     {
-        Smb2WriteRequestHdr* write = (Smb2WriteRequestHdr*)((uint8_t*)smb_hdr + sizeof(SmbNtHdr));
-        uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(Smb2WriteRequestHdr) + co_len;
-
-        if (nb_len > UINT16_MAX)
-            nb_len = UINT16_MAX;
-        write->structure_size = SMB2_WRITE_REQUEST_STRUC_SIZE;
-        nb_hdr->length = htons((uint16_t)nb_len);
-
-        tcp_file_tracker_mutex.lock();
-        if (tcp_file_tracker)
-        {
-            uint64_t fid = tcp_file_tracker->get_file_id();
-            write->fileId_persistent = alignedNtohq(&fid);
-            write->fileId_volatile = alignedNtohq(&fid);
-        }
-        else
-            write->fileId_persistent = write->fileId_volatile = 0;
-        tcp_file_tracker_mutex.unlock();
+        const Smb2Hdr* smb_hdr = (const Smb2Hdr*)(p->data + sizeof(NbssHdr));
+        uint32_t smb_version_id = SmbId((const SmbNtHdr*)smb_hdr);
 
-        write->length = alignedNtohs(&co_len);
+        if (smb_version_id == DCE2_SMB_ID)
+            return DCE2_SMB_VERSION_1;
+        else if (smb_version_id == DCE2_SMB2_ID)
+            return DCE2_SMB_VERSION_2;
     }
-    else
-    {
-        Smb2ReadResponseHdr* read = (Smb2ReadResponseHdr*)((uint8_t*)smb_hdr + sizeof(SmbNtHdr));
-        uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(Smb2ReadResponseHdr) + co_len;
 
-        if (nb_len > UINT16_MAX)
-            nb_len = UINT16_MAX;
-
-        nb_hdr->length = htons((uint16_t)nb_len);
-        read->structure_size = SMB2_READ_RESPONSE_STRUC_SIZE;
-        read->length = alignedNtohs(&co_len);
-    }
+    return DCE2_SMB_VERSION_NULL;
 }
 
index 26eb8cb83e43b2fecad0aa8621bb9fea9cefb3a8..91b931d9fd35d5cbd4099c3e308a086f124a679b 100644 (file)
 #ifndef DCE_SMB2_H
 #define DCE_SMB2_H
 
-// This implements smb session data for SMBv2
-// Also provides SMBv2 related header structures
-
-#include <mutex>
-
+#include "dce_db.h"
+#include "dce_smb.h"
+#include "hash/lru_cache_shared.h"
+#include "flow/flow_key.h"
 #include "main/thread_config.h"
 #include "utils/util.h"
 
-#include "dce_smb_common.h"
-
-/* SMB2 command codes */
-#define SMB2_COM_NEGOTIATE        0x00
-#define SMB2_COM_SESSION_SETUP    0x01
-#define SMB2_COM_LOGOFF           0x02
-#define SMB2_COM_TREE_CONNECT     0x03
-#define SMB2_COM_TREE_DISCONNECT  0x04
-#define SMB2_COM_CREATE           0x05
-#define SMB2_COM_CLOSE            0x06
-#define SMB2_COM_FLUSH            0x07
-#define SMB2_COM_READ             0x08
-#define SMB2_COM_WRITE            0x09
-#define SMB2_COM_LOCK             0x0A
-#define SMB2_COM_IOCTL            0x0B
-#define SMB2_COM_CANCEL           0x0C
-#define SMB2_COM_ECHO             0x0D
-#define SMB2_COM_QUERY_DIRECTORY  0x0E
-#define SMB2_COM_CHANGE_NOTIFY    0x0F
-#define SMB2_COM_QUERY_INFO       0x10
-#define SMB2_COM_SET_INFO         0x11
-#define SMB2_COM_OPLOCK_BREAK     0x12
-#define SMB2_COM_MAX              0x13
-
-extern const char* smb2_command_string[SMB2_COM_MAX];
-
-// file attribute for create response
-#define SMB2_CREATE_RESPONSE_DIRECTORY 0x10
-#define SMB_AVG_FILES_PER_SESSION 5
-
-#define SMB2_SHARE_TYPE_DISK  0x01
-#define SMB2_SHARE_TYPE_PIPE  0x02
-#define SMB2_SHARE_TYPE_PRINT 0x03
-
-#define SMB2_CMD_TYPE_ERROR_RESPONSE 0
-#define SMB2_CMD_TYPE_REQUEST        1
-#define SMB2_CMD_TYPE_RESPONSE       2
-#define SMB2_CMD_TYPE_INVALID        3
-
-#define FSCTL_PIPE_WAIT 0x00110018
-#define FSCTL_PIPE_TRANSCEIVE 0x0011C017
-#define FSCTL_PIPE_PEEK 0x0011400C
+#define GET_CURRENT_PACKET snort::DetectionEngine::get_current_packet()
 
 struct Smb2Hdr
 {
@@ -84,7 +42,24 @@ struct Smb2Hdr
     uint32_t flags;           /* flags */
     uint32_t next_command;    /* used for compounded request */
     uint64_t message_id;      /* identifies a message uniquely on connection */
-    uint64_t async_sync;      /* used for async and sync differently */
+    uint32_t process_id;      /* Reserved */
+    uint32_t tree_id;         /* Tree id*/
+    uint64_t session_id;      /* identifies the established session for the command*/
+    uint8_t signature[16];    /* signature of the message */
+};
+
+struct Smb2ASyncHdr
+{
+    uint8_t smb_idf[4];       /* contains 0xFE,’SMB’ */
+    uint16_t structure_size;  /* This MUST be set to 64 */
+    uint16_t credit_charge;   /* # of credits that this request consumes */
+    uint32_t status;          /* depends */
+    uint16_t command;         /* command code  */
+    uint16_t credit;          /* # of credits requesting/granted */
+    uint32_t flags;           /* flags */
+    uint32_t next_command;    /* used for compounded request */
+    uint64_t message_id;      /* identifies a message uniquely on connection */
+    uint64_t async_id;        /* handle operations asynchronously */
     uint64_t session_id;      /* identifies the established session for the command*/
     uint8_t signature[16];    /* signature of the message */
 };
@@ -106,6 +81,413 @@ struct Smb2SyncHdr
     uint8_t signature[16];    /* signature of the message */
 };
 
+struct Smb2ErrorResponseHdr
+{
+    uint16_t structure_size;  /* This MUST be set to 9 */
+    uint16_t reserved;        /* reserved */
+    uint32_t byte_count;      /* The number of bytes of error_data */
+    uint8_t error_data[1];    /* If byte_count is 0, this MUST be 0*/
+};
+
+class DCE2_Smb2TreeTracker;
+
+class DCE2_Smb2RequestTracker
+{
+public:
+
+    DCE2_Smb2RequestTracker() = delete;
+    DCE2_Smb2RequestTracker(const DCE2_Smb2RequestTracker& arg) = delete;
+    DCE2_Smb2RequestTracker& operator=(const DCE2_Smb2RequestTracker& arg) = delete;
+
+    explicit DCE2_Smb2RequestTracker(uint64_t file_id_v, uint64_t offset_v = 0);
+    DCE2_Smb2RequestTracker(char* fname_v, uint16_t fname_len_v);
+    ~DCE2_Smb2RequestTracker();
+
+    uint64_t get_offset()
+    {
+        return offset;
+    }
+
+    uint64_t get_file_id()
+    {
+        return file_id;
+    }
+
+    void set_file_id(uint64_t fid)
+    {
+        file_id = fid;
+    }
+
+    void set_tree_id(uint32_t l_tree_id)
+    {
+        tree_id = l_tree_id;
+    }
+
+    uint32_t get_tree_id()
+    {
+        return tree_id;
+    }
+
+    void set_session_id(uint32_t l_session_id)
+    {
+        session_id = l_session_id;
+    }
+
+    uint32_t get_session_id()
+    {
+        return session_id;
+    }
+
+    char* fname = nullptr;
+    uint16_t fname_len = 0;
+    uint64_t file_id = 0;
+    uint64_t offset = 0;
+    uint32_t tree_id = 0;
+    uint64_t session_id = 0;
+};
+
+struct DCE2_Smb2SsnData;
+class DCE2_Smb2SessionTracker;
+
+class DCE2_Smb2FileTracker
+{
+public:
+
+    DCE2_Smb2FileTracker() = delete;
+    DCE2_Smb2FileTracker(const DCE2_Smb2FileTracker& arg) = delete;
+    DCE2_Smb2FileTracker& operator=(const DCE2_Smb2FileTracker& arg) = delete;
+
+    DCE2_Smb2FileTracker(uint64_t file_id_v, DCE2_Smb2TreeTracker* ttr_v,
+        DCE2_Smb2SessionTracker* str_v, snort::Flow* flow_v);
+    ~DCE2_Smb2FileTracker();
+    uint64_t max_offset = 0;
+    uint64_t file_id = 0;
+    uint64_t file_size = 0;
+    uint64_t file_name_hash = 0;
+    DCE2_Smb2TreeTracker* ttr = nullptr;
+    DCE2_Smb2SessionTracker* str = nullptr;
+    snort::Flow* parent_flow = nullptr;
+    DCE2_CoTracker* co_tracker = nullptr;
+    bool ignore : 1;
+    bool upload : 1;
+    bool multi_channel_file : 1;
+};
+
+class DCE2_Smb2LocalFileTracker
+{
+public:
+    uint64_t file_offset = 0;
+    DCE2_SmbPduState smb2_pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+};
+typedef DCE2_DbMap<uint64_t, DCE2_Smb2FileTracker*, std::hash<uint64_t> > DCE2_DbMapFtracker;
+typedef DCE2_DbMap<uint64_t, DCE2_Smb2RequestTracker*, std::hash<uint64_t> > DCE2_DbMapRtracker;
+class DCE2_Smb2TreeTracker
+{
+public:
+
+    DCE2_Smb2TreeTracker() = delete;
+    DCE2_Smb2TreeTracker(const DCE2_Smb2TreeTracker& arg) = delete;
+    DCE2_Smb2TreeTracker& operator=(const DCE2_Smb2TreeTracker& arg) = delete;
+
+    DCE2_Smb2TreeTracker (uint32_t tid_v, uint8_t share_type_v);
+    ~DCE2_Smb2TreeTracker();
+
+    // File Tracker
+    DCE2_Smb2FileTracker* findFtracker(uint64_t file_id)
+    {
+        return file_trackers.Find(file_id);
+    }
+
+    bool insertFtracker(uint64_t file_id, DCE2_Smb2FileTracker* ftracker)
+    {
+        return file_trackers.Insert(file_id, ftracker);
+    }
+
+    void removeFtracker(uint64_t file_id)
+    {
+        file_trackers.Remove(file_id);
+    }
+
+    // common methods
+    uint8_t get_share_type()
+    {
+        return share_type;
+    }
+
+    uint32_t get_tid()
+    {
+        return tid;
+    }
+
+    uint8_t share_type = 0;
+    uint32_t tid = 0;
+    DCE2_DbMapFtracker file_trackers;
+};
+
+PADDING_GUARD_BEGIN
+
+struct Smb2SidHashKey
+{
+    uint32_t cip[4] = {};
+    uint32_t sip[4] = {};
+    uint32_t mplsLabel = 0;
+    int16_t cgroup = 0;
+    int16_t sgroup = 0;
+    uint32_t addressSpaceId = 0;
+    uint16_t vlan_tag = 0;
+    uint16_t padding = 0;
+    uint64_t sid = 0;
+
+    bool operator==(const Smb2SidHashKey& other) const
+    {
+        return( cip[0] == other.cip[0] and
+               cip[1] == other.cip[1] and
+               cip[2] == other.cip[2] and
+               cip[3] == other.cip[3] and
+               sip[0] == other.sip[0] and
+               sip[1] == other.sip[1] and
+               sip[2] == other.sip[2] and
+               sip[3] == other.sip[3] and
+               mplsLabel == other.mplsLabel and
+               cgroup == other.cgroup and
+               sgroup == other.sgroup and
+               addressSpaceId == other.addressSpaceId and
+               vlan_tag == other.vlan_tag and
+               sid == other.sid);
+    }
+};
+PADDING_GUARD_END
+
+//The below value is taken from Hash Key class static hash hardener
+#define SMB_KEY_HASH_HARDENER 133824503
+
+struct SmbKeyHash
+{
+    size_t operator()(const Smb2SidHashKey& key) const
+    {
+        return do_hash((const uint32_t*)&key);
+    }
+
+    size_t operator()(const snort::FlowKey& key) const
+    {
+        return do_hash_flow_key((const uint32_t*)&key);
+    }
+
+private:
+    size_t do_hash(const uint32_t* d) const
+    {
+        uint32_t a, b, c;
+        a = b = c = SMB_KEY_HASH_HARDENER;
+        a += d[0]; b += d[1];  c += d[2];  mix(a, b, c);
+        a += d[3]; b += d[4];  c += d[5];  mix(a, b, c);
+        a += d[6]; b += d[7];  c += d[8];  mix(a, b, c);
+        a += d[9]; b += d[10]; c += d[11]; mix(a, b, c);
+        a += d[12]; b += d[13]; finalize(a, b, c);
+        return c;
+    }
+
+    size_t do_hash_flow_key(const uint32_t* d) const
+    {
+        uint32_t a, b, c;
+        a = b = c = SMB_KEY_HASH_HARDENER;
+
+        a += d[0];   // IPv6 lo[0]
+        b += d[1];   // IPv6 lo[1]
+        c += d[2];   // IPv6 lo[2]
+
+        mix(a, b, c);
+
+        a += d[3];   // IPv6 lo[3]
+        b += d[4];   // IPv6 hi[0]
+        c += d[5];   // IPv6 hi[1]
+
+        mix(a, b, c);
+
+        a += d[6];   // IPv6 hi[2]
+        b += d[7];   // IPv6 hi[3]
+        c += d[8];   // mpls label
+
+        mix(a, b, c);
+
+        a += d[9];   // addressSpaceId
+        b += d[10];  // port lo & port hi
+        c += d[11];  // group lo & group hi
+
+        mix(a, b, c);
+
+        a += d[12];  // vlan & pad
+        b += d[13];  // ip_proto, pkt_type, version, flags
+
+        finalize(a, b, c);
+
+        return c;
+    }
+};
+
+typedef DCE2_DbMap<uint32_t, DCE2_Smb2TreeTracker*, std::hash<uint32_t> > DCE2_DbMapTtracker;
+typedef DCE2_DbMap<uint32_t, DCE2_Smb2SsnData*, std::hash<uint32_t> > DCE2_DbMapConntracker;
+class DCE2_Smb2SessionTracker
+{
+public:
+
+    DCE2_Smb2SessionTracker() = delete;
+    DCE2_Smb2SessionTracker(uint64_t sid);
+    ~DCE2_Smb2SessionTracker();
+
+    void removeSessionFromAllConnection();
+    void update_cache_size(int size);
+
+    // tree tracker
+    bool insertTtracker(uint32_t tree_id, DCE2_Smb2TreeTracker* ttr)
+    {
+        update_cache_size(sizeof(DCE2_Smb2TreeTracker));
+        return tree_trackers.Insert(tree_id, ttr);
+    }
+
+    DCE2_Smb2TreeTracker* findTtracker(uint32_t tree_id)
+    {
+        return tree_trackers.Find(tree_id);
+    }
+
+    void removeTtracker(uint32_t tree_id)
+    {
+        update_cache_size(-(int)sizeof(DCE2_Smb2TreeTracker));
+        tree_trackers.Remove(tree_id);
+    }
+
+    // ssd tracker
+    bool insertConnectionTracker(const uint32_t key, DCE2_Smb2SsnData* ssd)
+    {
+        return conn_trackers.Insert(key, ssd);
+    }
+
+    DCE2_Smb2SsnData* findConnectionTracker(const uint32_t key)
+    {
+        return conn_trackers.Find(key);
+    }
+
+    void removeConnectionTracker(const uint32_t key)
+    {
+        conn_trackers.Remove(key);
+    }
+
+    int getConnTrackerSize()
+    {
+        return conn_trackers.GetSize();
+    }
+
+    void set_encryption_flag(bool flag)
+    {
+        if (flag)
+            encryption_flag++;
+        if (encryption_flag == 1)
+            dce2_smb_stats.total_encrypted_sessions++;
+    }
+
+    bool get_encryption_flag() { return static_cast<bool>(encryption_flag); }
+
+    DCE2_DbMapConntracker conn_trackers;
+    DCE2_DbMapTtracker tree_trackers;
+    uint64_t session_id = 0;
+    uint8_t encryption_flag = 0;
+};
+struct DCE2_Smb2SsnData
+{
+    DCE2_SsnData sd;  // This member must be first
+    uint8_t smb_id;
+    DCE2_Policy policy;
+    int dialect_index;
+    int ssn_state_flags;
+    int64_t max_file_depth; // Maximum file depth as returned from file API
+    int16_t max_outstanding_requests; // Maximum number of request that can stay pending
+    std::unordered_map<uint64_t, std::weak_ptr<DCE2_Smb2SessionTracker>, std::hash<uint64_t> > session_trackers;
+    DCE2_Smb2FileTracker* ftracker_tcp; //To keep tab of current file being transferred over TCP
+    std::unique_ptr<DCE2_Smb2LocalFileTracker> ftracker_local;
+    DCE2_DbMapRtracker req_trackers;
+    uint32_t flow_key;
+    snort::Flow* flow = nullptr;
+    DCE2_Smb2SsnData();
+    ~DCE2_Smb2SsnData();
+    void set_reassembled_data(uint8_t* nb_ptr, uint16_t co_len);
+
+    std::shared_ptr<DCE2_Smb2SessionTracker> find_session_tracker(uint64_t session_id)
+    {
+        auto session_iter = session_trackers.find(session_id);
+        if (session_iter != session_trackers.end())
+        {
+            return session_iter->second.lock();
+        }
+        return nullptr;
+    }
+
+    void remove_session_tracker(uint64_t session_id)
+    {
+        session_trackers.erase(session_id);
+    }
+
+    bool insert_session_tracker(uint64_t session_id, std::shared_ptr<DCE2_Smb2SessionTracker> sptr)
+    {
+        return session_trackers.insert(std::make_pair(session_id, sptr)).second;
+    }
+
+    // Request Tracker
+    DCE2_Smb2RequestTracker* findRtracker(uint64_t mid)
+    {
+        return req_trackers.Find(mid);
+    }
+
+    bool insertRtracker(uint64_t message_id, DCE2_Smb2RequestTracker* rtracker)
+    {
+        return req_trackers.Insert(message_id, rtracker);
+    }
+
+    void removeRtracker(uint64_t message_id)
+    {
+        req_trackers.Remove(message_id);
+    }
+
+    int getTotalRequestsPending()
+    {
+        return req_trackers.GetSize();
+    }
+
+    DCE2_Smb2TreeTracker* GetTreeTrackerFromMessage(uint64_t mid)
+    {
+        DCE2_Smb2RequestTracker* request_tracker = findRtracker(mid);
+        if (request_tracker)
+        {
+            auto session_tracker = find_session_tracker(request_tracker->get_session_id());
+            if (session_tracker)
+            {
+                return session_tracker->findTtracker(request_tracker->get_tree_id());
+            }
+        }
+        return nullptr;
+    }
+};
+
+/* SMB2 command codes */
+#define SMB2_COM_NEGOTIATE        0x00
+#define SMB2_COM_SESSION_SETUP    0x01
+#define SMB2_COM_LOGOFF           0x02
+#define SMB2_COM_TREE_CONNECT     0x03
+#define SMB2_COM_TREE_DISCONNECT  0x04
+#define SMB2_COM_CREATE           0x05
+#define SMB2_COM_CLOSE            0x06
+#define SMB2_COM_FLUSH            0x07
+#define SMB2_COM_READ             0x08
+#define SMB2_COM_WRITE            0x09
+#define SMB2_COM_LOCK             0x0A
+#define SMB2_COM_IOCTL            0x0B
+#define SMB2_COM_CANCEL           0x0C
+#define SMB2_COM_ECHO             0x0D
+#define SMB2_COM_QUERY_DIRECTORY  0x0E
+#define SMB2_COM_CHANGE_NOTIFY    0x0F
+#define SMB2_COM_QUERY_INFO       0x10
+#define SMB2_COM_SET_INFO         0x11
+#define SMB2_COM_OPLOCK_BREAK     0x12
+#define SMB2_COM_MAX              0x13
+
 struct Smb2NegotiateResponseHdr
 {
     uint16_t structure_size;
@@ -206,6 +588,9 @@ struct Smb2CreateRequestHdr
     uint32_t create_contexts_length;  /* length of contexts */
 };
 
+// file attribute for create response
+#define SMB2_CREATE_RESPONSE_DIRECTORY 0x10
+
 struct Smb2CreateResponseHdr
 {
     uint16_t structure_size;          /* This MUST be set to 89 */
@@ -226,16 +611,6 @@ struct Smb2CreateResponseHdr
     uint32_t create_contexts_length;  /*  */
 };
 
-struct Smb2CreateContextHdr
-{
-    uint32_t next;            /* next context header*/
-    uint16_t name_offset;     /* name offset */
-    uint16_t name_length;     /* name length */
-    uint16_t reserved;        /* reserved */
-    uint16_t data_offset;     /* data offset */
-    uint32_t data_length;     /* data length */
-};
-
 struct Smb2CloseRequestHdr
 {
     uint16_t structure_size;          /* This MUST be set to 24 */
@@ -245,6 +620,10 @@ struct Smb2CloseRequestHdr
     uint64_t fileId_volatile;         /* fileId that is volatile */
 };
 
+#define SMB2_SHARE_TYPE_DISK  0x01
+#define SMB2_SHARE_TYPE_PIPE  0x02
+#define SMB2_SHARE_TYPE_PRINT 0x03
+
 struct Smb2TreeConnectResponseHdr
 {
     uint16_t structure_size;          /* This MUST be set to 16 */
@@ -255,6 +634,42 @@ struct Smb2TreeConnectResponseHdr
     uint32_t maximal_access;          /* maximal access for the user */
 };
 
+struct Smb2TreeDisConnectHdr
+{
+    uint16_t structure_size;          /* This MUST be set to 4 */
+    uint16_t reserved;                 /* reserved */
+};
+
+struct  Smb2SetupRequestHdr
+{
+    uint16_t structure_size;            /* This MUST be set to 25 (0x19) bytes */
+    uint8_t flags;
+    uint8_t security_mode;
+    uint32_t capabilities;
+    uint32_t channel;
+    uint16_t secblob_ofs;
+    uint16_t secblob_size;
+    uint64_t previous_sessionid;
+};
+
+struct Smb2SetupResponseHdr
+{
+    uint16_t structure_size;            /* This MUST be set to 9 (0x09) bytes */
+    uint16_t session_flags;
+    uint16_t secblob_ofs;
+    uint16_t secblob_size;
+};
+
+struct Smb2CreateContextHdr
+{
+    uint32_t next;            /* next context header*/
+    uint16_t name_offset;     /* name offset */
+    uint16_t name_length;     /* name length */
+    uint16_t reserved;        /* reserved */
+    uint16_t data_offset;     /* data offset */
+    uint32_t data_length;     /* data length */
+};
+
 struct Smb2IoctlRequestHdr
 {
     uint16_t structure_size;          /* This MUST be set to 57 */
@@ -288,14 +703,14 @@ struct Smb2IoctlResponseHdr
 };
 
 #define SMB2_HEADER_LENGTH 64
+#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x08
 
 #define SMB2_ERROR_RESPONSE_STRUC_SIZE 9
-
-#define SMB2_NEGOTIATE_REQUEST_STRUC_SIZE 36
 #define SMB2_NEGOTIATE_RESPONSE_STRUC_SIZE 65
 
 #define SMB2_CREATE_REQUEST_STRUC_SIZE 57
 #define SMB2_CREATE_RESPONSE_STRUC_SIZE 89
+#define SMB2_CREATE_REQUEST_DATA_OFFSET 120
 
 #define SMB2_CLOSE_REQUEST_STRUC_SIZE 24
 #define SMB2_CLOSE_RESPONSE_STRUC_SIZE 60
@@ -312,210 +727,35 @@ struct Smb2IoctlResponseHdr
 #define SMB2_TREE_CONNECT_REQUEST_STRUC_SIZE 9
 #define SMB2_TREE_CONNECT_RESPONSE_STRUC_SIZE 16
 #define SMB2_TREE_DISCONNECT_REQUEST_STRUC_SIZE 4
-#define SMB2_TREE_DISCONNECT_RESPONSE_STRUC_SIZE 4
+
+#define SMB2_FILE_ALLOCATION_INFO 0x13
+#define SMB2_FILE_ENDOFFILE_INFO 0x14
 
 #define SMB2_SETUP_REQUEST_STRUC_SIZE 25
 #define SMB2_SETUP_RESPONSE_STRUC_SIZE 9
 
-#define SMB2_LOGOFF_REQUEST_STRUC_SIZE 4
-#define SMB2_LOGOFF_RESPONSE_STRUC_SIZE 4
-
 #define SMB2_IOCTL_REQUEST_STRUC_SIZE 57
 #define SMB2_IOCTL_RESPONSE_STRUC_SIZE 49
 
-#define SMB2_FILE_ENDOFFILE_INFO 0x14
-#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x08
-
-#define GET_CURRENT_PACKET snort::DetectionEngine::get_current_packet()
-
-class Dce2Smb2FileTracker;
-class Dce2Smb2SessionTracker;
-
-using Dce2Smb2SessionTrackerPtr = std::shared_ptr<Dce2Smb2SessionTracker>;
-using Dce2Smb2SessionTrackerMap =
-        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> >;
-
-PADDING_GUARD_BEGIN
-struct Smb2SessionKey
-{
-    uint32_t cip[4];
-    uint32_t sip[4];
-    uint64_t sid;
-    uint32_t asid;
-    int16_t cgroup;
-    int16_t sgroup;
-
-    bool operator==(const Smb2SessionKey& other) const
-    {
-        return( sid == other.sid and
-               cip[0] == other.cip[0] and
-               cip[1] == other.cip[1] and
-               cip[2] == other.cip[2] and
-               cip[3] == other.cip[3] and
-               sip[0] == other.sip[0] and
-               sip[1] == other.sip[1] and
-               sip[2] == other.sip[2] and
-               sip[3] == other.sip[3] and
-               cgroup == other.cgroup and
-               sgroup == other.sgroup and
-               asid == other.asid );
-    }
-};
-
-struct Smb2FlowKey
-{
-    uint32_t ip_l[4];   // Low IP
-    uint32_t ip_h[4];   // High IP
-    uint32_t mplsLabel;
-    uint32_t addressSpaceId;
-    uint16_t port_l;    // Low Port - 0 if ICMP
-    uint16_t port_h;    // High Port - 0 if ICMP
-    int16_t group_l;
-    int16_t group_h;
-    uint16_t vlan_tag;
-    uint16_t padding16;
-    uint8_t ip_protocol;
-    uint8_t pkt_type;
-    uint8_t version;
-    uint8_t padding;
-};
-
-struct Smb2MessageKey
-{
-    uint64_t mid;
-    uint32_t flow_key;
-    uint32_t padding;
-
-    bool operator==(const Smb2MessageKey& other) const
-    {
-        return (mid == other.mid and
-               flow_key == other.flow_key);
-    }
-};
-PADDING_GUARD_END
-
-//The below value is taken from Hash Key class static hash hardener
-#define SMB_KEY_HASH_HARDENER 133824503
-
-struct Smb2KeyHash
-{
-    size_t operator()(const Smb2FlowKey& key) const
-    {
-        return do_hash_flow_key((const uint32_t*)&key);
-    }
-
-    size_t operator()(const Smb2SessionKey& key) const
-    {
-        return do_hash_session_key((const uint32_t*)&key);
-    }
-
-    size_t operator()(const Smb2MessageKey& key) const
-    {
-        return do_hash_message_key((const uint32_t*)&key);
-    }
-
-private:
-    size_t do_hash_flow_key(const uint32_t* d) const
-    {
-        uint32_t a, b, c;
-        a = b = c = SMB_KEY_HASH_HARDENER;
-        a += d[0]; b += d[1];  c += d[2];  mix(a, b, c);
-        a += d[3]; b += d[4];  c += d[5];  mix(a, b, c);
-        a += d[6]; b += d[7];  c += d[8];  mix(a, b, c);
-        a += d[9]; b += d[10]; c += d[11]; mix(a, b, c);
-        a += d[12]; b += d[13]; finalize(a, b, c);
-        return c;
-    }
-
-    size_t do_hash_session_key(const uint32_t* d) const
-    {
-        uint32_t a, b, c;
-        a = b = c = SMB_KEY_HASH_HARDENER;
-        a += d[0]; b += d[1];  c += d[2];  mix(a, b, c);
-        a += d[3]; b += d[4];  c += d[5];  mix(a, b, c);
-        a += d[6]; b += d[7];  c += d[8];  mix(a, b, c);
-        a += d[9]; b += d[10]; c += d[11]; finalize(a, b, c);
-        return c;
-    }
-
-    size_t do_hash_message_key(const uint32_t* d) const
-    {
-        uint32_t a, b, c;
-        a = b = c = SMB_KEY_HASH_HARDENER;
-        a += d[0]; b += d[1]; c += d[2]; mix(a, b, c);
-        finalize(a, b, c);
-        return c;
-    }
-
-    inline uint32_t rot(uint32_t x, unsigned k) const
-    { return (x << k) | (x >> (32 - k)); }
-
-    inline void mix(uint32_t& a, uint32_t& b, uint32_t& c) const
-    {
-        a -= c; a ^= rot(c, 4); c += b;
-        b -= a; b ^= rot(a, 6); a += c;
-        c -= b; c ^= rot(b, 8); b += a;
-        a -= c; a ^= rot(c,16); c += b;
-        b -= a; b ^= rot(a,19); a += c;
-        c -= b; c ^= rot(b, 4); b += a;
-    }
+#define SMB2_LOGOFF_REQUEST_STRUC_SIZE 4
 
-    inline void finalize(uint32_t& a, uint32_t& b, uint32_t& c) const
-    {
-        c ^= b; c -= rot(b,14);
-        a ^= c; a -= rot(c,11);
-        b ^= a; b -= rot(a,25);
-        c ^= b; c -= rot(b,16);
-        a ^= c; a -= rot(c,4);
-        b ^= a; b -= rot(a,14);
-        c ^= b; c -= rot(b,24);
-    }
-};
+#define SMB2_FLAGS_ASYNC_COMMAND  0x00000002
 
-uint32_t get_smb2_flow_key(const snort::FlowKey*);
+#define SMB2_STATUS_PENDING  0x00000103
 
-class Dce2Smb2SessionData : public Dce2SmbSessionData
-{
-public:
-    Dce2Smb2SessionData() = delete;
-    Dce2Smb2SessionData(const snort::Packet*, const dce2SmbProtoConf* proto);
-    ~Dce2Smb2SessionData() override;
-    void process() override;
-    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)
-    {
-        tcp_file_tracker = file_tracker;
-    }
-
-    Dce2Smb2FileTrackerPtr get_tcp_file_tracker()
-    {
-        return tcp_file_tracker;
-    }
+#define FSCTL_PIPE_WAIT 0x00110018
+#define FSCTL_PIPE_TRANSCEIVE 0x0011C017
+#define FSCTL_PIPE_PEEK 0x0011400C
 
-    Dce2Smb2SessionTrackerPtr find_session(uint64_t);
-    std::recursive_mutex session_data_mutex;
-    uint16_t vlan_id;
+#define SMB2_CREATE_DURABLE_RECONNECT "DHnC"
+#define SMB2_CREATE_DURABLE_RECONNECT_V2 "DH2C"
 
-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 tcp_file_tracker_mutex;
-};
+extern const char* smb2_command_string[SMB2_COM_MAX];
+/* Process smb2 message */
+void DCE2_Smb2Process(DCE2_Smb2SsnData* ssd);
 
-using Dce2Smb2SessionDataMap =
-        std::unordered_map<uint32_t, Dce2Smb2SessionData*, std::hash<uint32_t> >;
+/* Check smb version based on smb header */
+DCE2_SmbVersion DCE2_Smb2Version(const snort::Packet* p);
 
 #endif  /* _DCE_SMB2_H_ */
 
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_commands.cc b/src/service_inspectors/dce_rpc/dce_smb2_commands.cc
new file mode 100644 (file)
index 0000000..43e2d5b
--- /dev/null
@@ -0,0 +1,1204 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2023 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// dce_smb2_commands.cc author Bhargava Jandhyala <bjandhya@cisco.com>
+// based on work by Todd Wease
+
+// Smb commands processing
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dce_smb2_commands.h"
+#include "hash/hash_key_operations.h"
+#include "log/messages.h"
+#include "packet_io/active.h"
+#include "protocols/packet.h"
+
+using namespace snort;
+#define UNKNOWN_FILE_SIZE (~0)
+
+#define SMB2_CHECK_HDR_ERROR(smb_data, end, strcuture_size, counter, cmd) \
+    { \
+        if ((smb_data + (strcuture_size)) > end) \
+        { \
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, DetectionEngine::get_current_packet(), \
+    "%s : smb truncated data detected\n", smb2_command_string[cmd]); \
+            counter++; \
+            return; \
+        } \
+    }
+
+inline FileFlows* DCE2_Smb2GetFileFlow(DCE2_Smb2FileTracker* ftracker)
+{
+    Packet* p = DetectionEngine::get_current_packet();
+    if (p->flow != ftracker->parent_flow)
+        ftracker->multi_channel_file = true;
+    if (!ftracker->parent_flow)
+    {
+        //Parent flow is deleted, upgrade the current flow as parent flow
+        ftracker->parent_flow = p->flow;
+        dce2_smb_stats.v2_updated_file_flows++;
+    }
+    return FileFlows::get_file_flows(ftracker->parent_flow);
+}
+
+inline FileFlows* DCE2_Smb2GetCurrentFileFlow()
+{
+    Packet* p = DetectionEngine::get_current_packet();
+    return FileFlows::get_file_flows(p->flow);
+}
+
+static inline FileContext* DCE2_Smb2GetFileContext(DCE2_Smb2SsnData*, DCE2_Smb2FileTracker* ftracker, bool
+    to_create = false)
+{
+    FileFlows* file_flows = DCE2_Smb2GetFileFlow(ftracker);
+    if ( !file_flows )
+    {
+        dce2_smb_stats.v2_inv_file_ctx_err++;
+        return nullptr;
+    }
+    bool is_new_context = false;
+    if (ftracker->file_name_hash)
+            return file_flows->get_file_context(ftracker->file_name_hash, to_create, is_new_context, ftracker->file_id);
+    return file_flows->get_file_context(ftracker->file_id, to_create, is_new_context);
+}
+
+inline void DCE2_Smb2UpdateMaxOffset(DCE2_Smb2FileTracker* ftracker, uint64_t offset)
+{
+    if (ftracker->max_offset < offset)
+        ftracker->max_offset = offset;
+}
+
+bool DCE2_Smb2ProcessFileData(DCE2_Smb2SsnData* ssd, const uint8_t* file_data,
+    uint32_t data_size)
+{
+    if (ssd->ftracker_tcp->co_tracker)
+    {
+        DCE2_CoProcess(&ssd->sd, ssd->ftracker_tcp->co_tracker,
+            file_data, data_size);
+        return true;
+    }
+    int64_t file_detection_depth = DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config);
+    int64_t detection_size = 0;
+
+    if (file_detection_depth == 0)
+        detection_size = data_size;
+    else if ( ssd->ftracker_local->file_offset < (uint64_t)file_detection_depth)
+    {
+        if ( file_detection_depth - ssd->ftracker_local->file_offset < data_size )
+            detection_size = file_detection_depth - ssd->ftracker_local->file_offset;
+        else
+            detection_size = data_size;
+    }
+
+    if (detection_size)
+    {
+        set_file_data(file_data,
+            (detection_size > UINT16_MAX) ? UINT16_MAX : (uint16_t)detection_size);
+
+        DCE2_FileDetect();
+    }
+    Packet* p = DetectionEngine::get_current_packet();
+    FileDirection dir = ssd->ftracker_tcp->upload ? FILE_UPLOAD : FILE_DOWNLOAD;
+
+    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p,
+        "file_process fid 0x%" PRIx64 " data_size %" PRIu32 " offset %"
+        PRIu64  "\n", ssd->ftracker_tcp->file_id, data_size,
+        ssd->ftracker_local->file_offset);
+
+    if (!ssd->ftracker_tcp->ignore)
+    {
+        // Do not process data beyond file size if file size is known.
+        if (ssd->ftracker_tcp->file_size)
+        {
+            if (ssd->ftracker_local->file_offset > ssd->ftracker_tcp->file_size)
+            {
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
+                    TRACE_ERROR_LEVEL, DetectionEngine::get_current_packet(),
+                    "file_process: bad offset\n");
+                return false;
+            }
+            else if (ssd->ftracker_local->file_offset + data_size > ssd->ftracker_tcp->file_size)
+            {
+                //Trim padded data
+                data_size = ssd->ftracker_tcp->file_size - ssd->ftracker_local->file_offset;
+            }
+        }
+
+        FileFlows* file_flows = DCE2_Smb2GetFileFlow(ssd->ftracker_tcp);
+        if (!file_flows)
+        {
+            dce2_smb_stats.v2_extra_file_data_err++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                p, "No file flow \n");
+
+            DCE2_Smb2TreeTracker* ttr = ssd->ftracker_tcp->ttr;
+            ttr->removeFtracker(ssd->ftracker_tcp->file_id);
+            return false;
+        }
+
+        // A hack to force to create a file flow for this connection
+        // Required for file type detection based on IPS rules.
+        if (ssd->flow != ssd->ftracker_tcp->parent_flow)
+            DCE2_Smb2GetCurrentFileFlow();
+
+        bool continue_processing = true;
+        if (ssd->ftracker_tcp->file_name_hash)
+            continue_processing = file_flows->file_process(p, ssd->ftracker_tcp->file_name_hash, file_data, data_size,
+                ssd->ftracker_local->file_offset, dir, ssd->ftracker_tcp->file_id);
+        else
+            continue_processing = file_flows->file_process(p, ssd->ftracker_tcp->file_id, file_data, data_size,
+                ssd->ftracker_local->file_offset, dir);
+        if (!continue_processing)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                p, "file_process completed\n");
+        }
+    }
+    ssd->ftracker_local->file_offset += data_size;
+    return true;
+}
+
+//-------------------------------------------------------------------------
+// Process session setup response to find/create session tracker
+//-------------------------------------------------------------------------
+void DCE2_Smb2Setup(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr, const uint64_t sid,
+    const uint8_t* smb_data, const uint8_t* end)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_SESSION_SETUP]);
+        dce2_smb_stats.v2_setup_err_resp++;
+    }
+    else if (structure_size == SMB2_SETUP_RESPONSE_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_SETUP_RESPONSE_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_setup_resp_hdr_err, SMB2_COM_SESSION_SETUP)
+        DCE2_Smb2FindElseCreateSid(ssd, sid);
+    }
+    else if (structure_size != SMB2_SETUP_REQUEST_STRUC_SIZE)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_SESSION_SETUP]);
+        dce2_smb_stats.v2_setup_inv_str_sz++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process tree connect response to find/create tree tracker
+//-------------------------------------------------------------------------
+void DCE2_Smb2TreeConnect(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str, uint32_t tid)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        dce2_smb_stats.v2_tree_cnct_err_resp++;
+    }
+    else if (structure_size == SMB2_TREE_CONNECT_RESPONSE_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_TREE_CONNECT_RESPONSE_STRUC_SIZE,
+            dce2_smb_stats.v2_tree_cnct_resp_hdr_err, SMB2_COM_TREE_CONNECT)
+
+        if (!DCE2_Smb2InsertTid(ssd, tid,
+            ((const Smb2TreeConnectResponseHdr*)smb_data)->share_type, str))
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                DetectionEngine::get_current_packet(), "%s: ignored %d\n",
+                smb2_command_string[SMB2_COM_TREE_CONNECT], tid);
+            dce2_smb_stats.v2_tree_cnct_ignored++;
+        }
+    }
+    else if (structure_size != SMB2_TREE_CONNECT_REQUEST_STRUC_SIZE)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_TREE_CONNECT]);
+        dce2_smb_stats.v2_tree_cnct_inv_str_sz++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process tree disconnect request to cleanup tree tracker and its
+// corresponding request trackers and file trackers
+//-------------------------------------------------------------------------
+void DCE2_Smb2TreeDisconnect(DCE2_Smb2SsnData*, const uint8_t* smb_data,
+    const uint8_t* end)
+{
+    if (SMB2_TREE_DISCONNECT_REQUEST_STRUC_SIZE == alignedNtohs((const uint16_t*)smb_data))
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_TREE_DISCONNECT_REQUEST_STRUC_SIZE,
+            dce2_smb_stats.v2_tree_discn_req_hdr_err, SMB2_COM_TREE_DISCONNECT)
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_TREE_DISCONNECT]);
+        dce2_smb_stats.v2_tree_discn_inv_str_sz++;
+    }
+}
+
+bool DCE2_IsSmb2DurableReconnect(const Smb2CreateRequestHdr* smb_create_hdr, const uint8_t* end, uint64_t& file_id)
+{
+    const uint8_t* data = (const uint8_t*)smb_create_hdr + alignedNtohl(&smb_create_hdr->create_contexts_offset) -
+        SMB2_HEADER_LENGTH;
+    uint32_t remaining = alignedNtohl(&smb_create_hdr->create_contexts_length);
+
+    while (remaining > sizeof(Smb2CreateRequestHdr) && data < end)
+    {
+        const Smb2CreateContextHdr* context = (const Smb2CreateContextHdr*)data;
+        uint32_t next = alignedNtohl(&context->next);
+        uint16_t name_offset = alignedNtohs(&context->name_offset);
+        uint16_t name_length = alignedNtohs(&context->name_length);
+        uint16_t data_offset = alignedNtohs(&context->data_offset);
+        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))
+        {
+            return false;
+        }
+
+        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, name_length) == 0))
+        {
+            file_id = alignedNtohq((const uint64_t*)(((const uint8_t*)context) + data_offset));
+            return true;
+        }
+
+        if (!next)
+            break;
+
+        data += next;
+        remaining -= next;
+    }
+    return false;
+}
+
+//-------------------------------------------------------------------------
+// Process create request to get file name and save it in request tracker
+//-------------------------------------------------------------------------
+static void DCE2_Smb2CreateRequest(DCE2_Smb2SsnData* ssd,
+    const Smb2CreateRequestHdr* smb_create_hdr, const uint8_t* end,
+    DCE2_Smb2SessionTracker* str, DCE2_Smb2TreeTracker* ttr, uint64_t mid)
+{
+    uint16_t name_offset = alignedNtohs(&(smb_create_hdr->name_offset));
+
+    if (name_offset > SMB2_HEADER_LENGTH)
+    {
+        uint16_t name_len  = 0;
+
+        const uint8_t* file_data =  (const uint8_t*)smb_create_hdr + smb_create_hdr->name_offset -
+            SMB2_HEADER_LENGTH;
+        if (file_data >= end)
+        {
+            dce2_smb_stats.v2_crt_inv_file_data++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_REQ: invalid "
+                "file data seen\n", smb2_command_string[SMB2_COM_CREATE]);
+            return;
+        }
+
+        uint16_t size = alignedNtohs(&(smb_create_hdr->name_length));
+        if (!size or (file_data + size > end))
+        {
+            dce2_smb_stats.v2_crt_inv_file_data++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_REQ: invalid file data seen with size %" PRIu16 "\n",
+                smb2_command_string[SMB2_COM_CREATE], size);
+            return;
+        }
+
+        if (ssd->max_outstanding_requests > ssd->getTotalRequestsPending())
+        {
+            char* file_name = DCE2_SmbGetFileName(file_data, size, true, &name_len);
+            auto rtracker = new DCE2_Smb2RequestTracker(file_name, name_len);
+            rtracker->set_session_id(str->session_id);
+            rtracker->set_tree_id(ttr->get_tid());
+            ssd->insertRtracker(mid, rtracker);
+            uint64_t file_id = 0;
+            if (DCE2_IsSmb2DurableReconnect(smb_create_hdr, end, file_id))
+            {
+                //Create a ftracker here to handle compound write case
+                auto ftracker = new DCE2_Smb2FileTracker(file_id, ttr, str,
+                    DetectionEngine::get_current_packet()->flow);
+                if (file_name and name_len)
+                {
+                    ftracker->file_name_hash = str_to_hash(
+                        (const uint8_t*)file_name, name_len);
+                }
+                else
+                {
+                    ftracker->ignore = true;
+                    dce2_smb_stats.v2_ignored_file_processing++;
+                }
+                ttr->insertFtracker(file_id, ftracker);
+                if (SMB2_SHARE_TYPE_DISK == ttr->get_share_type())
+                {
+                    FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker, true);
+                    if (file)
+                        file->set_file_name(file_name, name_len);
+                    else
+                    {
+                        //Ignore the file processing.
+                        ftracker->ignore = true;
+                        dce2_smb_stats.v2_ignored_file_processing++;
+                    }
+                }
+                else
+                {
+                    ftracker->co_tracker = (DCE2_CoTracker*)snort_calloc(sizeof(DCE2_CoTracker));
+                    DCE2_CoInitTracker(ftracker->co_tracker);
+                }
+            }
+        }
+        else
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_REQ: max req exceeded\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+            dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
+                ssd->sd);
+        }
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_REQ: name_offset %"
+            PRIu16 "\n", smb2_command_string[SMB2_COM_CREATE], name_offset);
+        dce2_smb_stats.v2_crt_req_hdr_err++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process create response to create file tracker with file id and file
+// size. Request tracker is cleaned after updating file name in file tracker
+//-------------------------------------------------------------------------
+static void DCE2_Smb2CreateResponse(DCE2_Smb2SsnData* ssd,
+    const Smb2CreateResponseHdr* smb_create_hdr, DCE2_Smb2RequestTracker* rtracker,
+    DCE2_Smb2TreeTracker* ttr, DCE2_Smb2SessionTracker* str, uint64_t fileId_persistent)
+{
+    uint64_t file_size = 0;
+
+    if (smb_create_hdr->end_of_file)
+    {
+        file_size = alignedNtohq((const uint64_t*)(&(smb_create_hdr->end_of_file)));
+    }
+
+    DCE2_Smb2FileTracker* ftracker = ttr->findFtracker(fileId_persistent);
+    if (!ftracker)
+    {
+        ftracker = new DCE2_Smb2FileTracker(fileId_persistent, ttr, str, DetectionEngine::get_current_packet()->flow);
+        ttr->insertFtracker(fileId_persistent, ftracker);
+    }
+
+    ftracker->file_size = file_size;
+    if (SMB2_SHARE_TYPE_DISK == ttr->get_share_type())
+    {
+        if (rtracker->fname and rtracker->fname_len)
+        {
+            if (!ftracker->file_name_hash)
+                ftracker->file_name_hash = str_to_hash(
+                    (const uint8_t*)rtracker->fname, rtracker->fname_len);
+
+            FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker, true);
+
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_RESP: file size %"
+                PRIu64 " fid 0x%" PRIx64 " file_name_hash %" PRIu64 " file context %s\n",
+                smb2_command_string[SMB2_COM_CREATE], file_size,
+                fileId_persistent, ftracker->file_name_hash, (file ? "found" : "not found"));
+
+            if (file)
+            {
+                if (file->verdict == FILE_VERDICT_UNKNOWN)
+                {
+                    file->set_file_size(!file_size ? UNKNOWN_FILE_SIZE : file_size);
+                    file->set_file_name(rtracker->fname, rtracker->fname_len);
+                }
+            }
+            else
+            {
+                // could not create file context, hence this file transfer
+                // cant be inspected
+                ftracker->ignore = true;
+                dce2_smb_stats.v2_ignored_file_processing++;
+            }
+        }
+        else
+        {
+            ftracker->ignore = true; // file can not be inspected as file name is not present
+            dce2_smb_stats.v2_ignored_file_processing++;
+        }
+    }
+    else
+    {
+        ftracker->co_tracker = (DCE2_CoTracker*)snort_calloc(sizeof(DCE2_CoTracker));
+        DCE2_CoInitTracker(ftracker->co_tracker);
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process create request to handle mid stream sessions by adding tree
+// tracker if not already present. Process create response for only disk
+// share type.
+//-------------------------------------------------------------------------
+void DCE2_Smb2Create(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, uint64_t mid, uint64_t sid, uint32_t tid)
+{
+    DCE2_Smb2SessionTracker* str = DCE2_Smb2FindElseCreateSid(ssd, sid);
+    DCE2_Smb2TreeTracker* ttr = nullptr;
+    if (tid)
+        ttr = str->findTtracker(tid);
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        ssd->removeRtracker(mid);
+
+        dce2_smb_stats.v2_crt_err_resp++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_CREATE]);
+    }
+    // Using structure size to decide whether it is response or request
+    else if (structure_size == SMB2_CREATE_REQUEST_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_CREATE_REQUEST_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_crt_req_hdr_err, SMB2_COM_CREATE)
+
+        if (!ttr)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_REQ: mid stream session detected\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+            ttr = DCE2_Smb2InsertTid(ssd, tid, SMB2_SHARE_TYPE_DISK, str);
+            if (!ttr)
+            {
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                    DetectionEngine::get_current_packet(),
+                    "%s_REQ: insert tree tracker failed\n",
+                    smb2_command_string[SMB2_COM_CREATE]);
+                return;
+            }
+        }
+        else if (SMB2_SHARE_TYPE_DISK != ttr->get_share_type())
+        {
+            dce2_smb_stats.v2_crt_req_ipc++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                "%s_REQ: processed for ipc share\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+        }
+        DCE2_Smb2CreateRequest(ssd, (const Smb2CreateRequestHdr*)smb_data, end, str, ttr, mid);
+    }
+    else if (structure_size == SMB2_CREATE_RESPONSE_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_CREATE_RESPONSE_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_crt_resp_hdr_err, SMB2_COM_CREATE)
+        if (!ttr)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_RESP: tree tracker missing\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+            dce2_smb_stats.v2_crt_tree_trkr_misng++;
+            return;
+        }
+
+        DCE2_Smb2RequestTracker* rtr = ssd->findRtracker(mid);
+        if (!rtr)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_RESP: req tracker missing\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+            dce2_smb_stats.v2_crt_rtrkr_misng++;
+            return;
+        }
+
+        uint64_t fileId_persistent = alignedNtohq((const uint64_t*)(
+                &(((const Smb2CreateResponseHdr*)smb_data)->fileId_persistent)));
+
+        if (((const Smb2CreateResponseHdr*)smb_data)->file_attributes &
+            SMB2_CREATE_RESPONSE_DIRECTORY)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_RESP: not processing for directory\n",
+                smb2_command_string[SMB2_COM_CREATE]);
+            ssd->removeRtracker(mid);
+            return;
+        }
+
+        DCE2_Smb2CreateResponse(ssd, (const Smb2CreateResponseHdr*)smb_data, rtr, ttr,
+            str, fileId_persistent);
+        ssd->removeRtracker(mid);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_CREATE]);
+        dce2_smb_stats.v2_crt_inv_str_sz++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process close command request to do file processing for an upload or
+// download request with unknown size.
+//-------------------------------------------------------------------------
+void DCE2_Smb2CloseCmd(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2TreeTracker* ttr,
+    DCE2_Smb2SessionTracker* str, uint64_t mid)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_CLOSE]);
+        dce2_smb_stats.v2_cls_err_resp++;
+    }
+    // Using structure size to decide whether it is response or request
+    else if (structure_size == SMB2_CLOSE_REQUEST_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_CLOSE_REQUEST_STRUC_SIZE,
+            dce2_smb_stats.v2_cls_req_hdr_err, SMB2_COM_CLOSE)
+
+        uint64_t fileId_persistent = alignedNtohq(&(((const
+            Smb2CloseRequestHdr*)smb_data)->fileId_persistent));
+        DCE2_Smb2FileTracker* ftracker =  ttr->findFtracker(fileId_persistent);
+        if (!ftracker)
+        {
+            dce2_smb_stats.v2_cls_req_ftrkr_misng++;
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_REQ: ftracker missing 0x%"
+                PRIx64 "\n", smb2_command_string[SMB2_COM_CLOSE], fileId_persistent);
+            return;
+        }
+
+        if (ssd->max_outstanding_requests > ssd->getTotalRequestsPending())
+        {
+            auto rtracker = new DCE2_Smb2RequestTracker(fileId_persistent);
+            rtracker->set_session_id(str->session_id);
+            rtracker->set_tree_id(ttr->get_tid());
+            ssd->insertRtracker(mid, rtracker);
+        }
+
+        if (SMB2_SHARE_TYPE_DISK == ttr->get_share_type() and !ftracker->ignore
+            and !ftracker->file_size and ftracker->max_offset)
+        {
+            ftracker->file_size = ftracker->max_offset;
+            FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker);
+            if (file)
+            {
+                file->set_file_size(ftracker->file_size);
+            }
+
+            ssd->ftracker_tcp = ftracker;
+            ssd->ftracker_local = std::unique_ptr<DCE2_Smb2LocalFileTracker>(new DCE2_Smb2LocalFileTracker());
+            ssd->ftracker_local->file_offset = ftracker->max_offset;
+            // In case of upload/download of file with UNKNOWN size, we will not be able to
+            // detect malicious file during write request or read response. Once the close
+            // command request comes, we will go for file inspection and block an subsequent
+            // upload/download request for this file even with unknown size
+            DCE2_Smb2ProcessFileData(ssd, nullptr, 0);
+        }
+    }
+    else if (structure_size == SMB2_CLOSE_RESPONSE_STRUC_SIZE)
+    {
+        DCE2_Smb2RequestTracker* rtr = ssd->findRtracker(mid);
+        if (!rtr)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(),
+                "%s_RESP: req tracker missing\n",
+                smb2_command_string[SMB2_COM_CLOSE]);
+            return;
+        }
+        auto fileId_persistent = rtr->get_file_id();
+        ttr->removeFtracker(fileId_persistent);
+        ssd->removeRtracker(mid);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_CLOSE]);
+        dce2_smb_stats.v2_cls_inv_str_sz++;
+        DCE2_Smb2RequestTracker* rtr = ssd->findRtracker(mid);
+        if (rtr)
+        {
+            auto fileId_persistent = rtr->get_file_id();
+            ttr->removeFtracker(fileId_persistent);
+            ssd->removeRtracker(mid);
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process set info request to update file size
+//-------------------------------------------------------------------------
+void DCE2_Smb2SetInfo(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2TreeTracker* ttr)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    // Using structure size to decide whether it is response or request
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: error resp\n",
+            smb2_command_string[SMB2_COM_SET_INFO]);
+        dce2_smb_stats.v2_stinf_err_resp++;
+    }
+    else if (structure_size == SMB2_SET_INFO_REQUEST_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_SET_INFO_REQUEST_STRUC_SIZE,
+            dce2_smb_stats.v2_stinf_req_hdr_err, SMB2_COM_SET_INFO)
+
+        const Smb2SetInfoRequestHdr* smb_set_info_hdr = (const Smb2SetInfoRequestHdr*)smb_data;
+        const uint8_t* file_data = (const uint8_t*)smb_set_info_hdr +
+            SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1;
+
+        if (smb_set_info_hdr->file_info_class == SMB2_FILE_ENDOFFILE_INFO or
+            smb_set_info_hdr->file_info_class == SMB2_FILE_ALLOCATION_INFO)
+        {
+            uint64_t file_size = alignedNtohq((const uint64_t*)file_data);
+            uint64_t fileId_persistent = alignedNtohq(&(smb_set_info_hdr->fileId_persistent));
+            DCE2_Smb2FileTracker* ftracker = ttr->findFtracker(fileId_persistent);
+            if (ftracker and !ftracker->ignore)
+            {
+                if (smb_set_info_hdr->file_info_class == SMB2_FILE_ALLOCATION_INFO)
+                {
+                    if(ftracker->file_size < file_size)
+                    {
+                        //Then possible ZIP upload in which case we dont know the actual size of the file
+                        ftracker->file_size = 0;
+                    }
+                }
+                else
+                    ftracker->file_size = file_size;
+
+                FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker);
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                    DetectionEngine::get_current_packet(),
+                    "%s_REQ: set file size %" PRIu64 " fid 0x%" PRIx64 " file context %s\n",
+                    smb2_command_string[SMB2_COM_SET_INFO], file_size, fileId_persistent,
+                    file ? "found" : "not found");
+                if (file)
+                {
+                    file->set_file_size(ftracker->file_size);
+                }
+            }
+            else
+            {
+                dce2_smb_stats.v2_stinf_req_ftrkr_misng++;
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+                    DetectionEngine::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_ERROR_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_REQ: header error\n",
+                smb2_command_string[SMB2_COM_SET_INFO]);
+
+            dce2_smb_stats.v2_stinf_req_hdr_err++;
+        }
+    }
+    else if (structure_size != SMB2_SET_INFO_RESPONSE_STRUC_SIZE)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_SET_INFO]);
+        dce2_smb_stats.v2_stinf_inv_str_sz++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process read request to create read request trackers to get file offset
+//-------------------------------------------------------------------------
+static void DCE2_Smb2ReadRequest(DCE2_Smb2SsnData* ssd,
+    const Smb2ReadRequestHdr* smb_read_hdr, const uint8_t*, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t message_id)
+{
+    uint64_t offset = alignedNtohq((const uint64_t*)(&(smb_read_hdr->offset)));
+    uint64_t fileId_persistent = alignedNtohq((const
+        uint64_t*)(&(smb_read_hdr->fileId_persistent)));
+
+    if (ssd->max_outstanding_requests > ssd->getTotalRequestsPending())
+    {
+        DCE2_Smb2RequestTracker* readtracker = ssd->findRtracker(message_id);
+        if (!readtracker)
+            readtracker = new DCE2_Smb2RequestTracker(fileId_persistent, offset);
+        readtracker->set_session_id(str->session_id);
+        readtracker->set_tree_id(ttr->get_tid());
+        readtracker->set_file_id(fileId_persistent);
+        ssd->insertRtracker(message_id, readtracker);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_REQ: max req exceeded\n",
+            smb2_command_string[SMB2_COM_READ]);
+        dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
+            ssd->sd);
+        return;
+    }
+
+    DCE2_Smb2FileTracker* ftracker =  ttr->findFtracker(fileId_persistent);
+    if (!ftracker and ttr->get_share_type() == SMB2_SHARE_TYPE_DISK)
+    {
+        //At times read is sent after the close, in case of malware block
+        // Create a file tracker here
+        ftracker = new DCE2_Smb2FileTracker(fileId_persistent, ttr, str, DetectionEngine::get_current_packet()->flow);
+        ttr->insertFtracker(fileId_persistent, ftracker);
+    }
+    if (!ftracker)
+    {
+        dce2_smb_stats.v2_read_rtrkr_misng++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_REQ: ftracker missing 0x%"
+            PRIx64 "\n", smb2_command_string[SMB2_COM_READ], fileId_persistent);
+        return;
+    }
+
+    if (ftracker->file_size and (offset > ftracker->file_size))
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(),
+            "%s_REQ: invalid file offset\n", smb2_command_string[SMB2_COM_READ]);
+        dce_alert(GID_DCE2, DCE2_SMB_INVALID_FILE_OFFSET, (dce2CommonStats*)&dce2_smb_stats,
+            ssd->sd);
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process read response to send file data for inspection. read request
+// trackers is cleaned after updating file offset in file tracker
+//-------------------------------------------------------------------------
+static void DCE2_Smb2ReadResponse(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const Smb2ReadResponseHdr* smb_read_hdr, const uint8_t* end, DCE2_Smb2TreeTracker* ttr,
+    uint64_t message_id)
+{
+    const uint8_t* file_data =  (const uint8_t*)smb_read_hdr + SMB2_READ_RESPONSE_STRUC_SIZE - 1;
+    int data_size = end - file_data;
+    uint16_t data_offset;
+    DCE2_Smb2RequestTracker* request = ssd->findRtracker(message_id);
+
+    if (!request)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(),
+            "%s_RESP: request tracker missing\n", smb2_command_string[SMB2_COM_READ]);
+        dce2_smb_stats.v2_read_rtrkr_misng++;
+        return;
+    }
+    data_offset = alignedNtohs((const uint16_t*)(&(smb_read_hdr->data_offset)));
+    if (data_offset + (const uint8_t*)smb_hdr > end)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: bad offset\n",
+            smb2_command_string[SMB2_COM_READ]);
+        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
+    }
+
+    DCE2_Smb2FileTracker* ftracker =  ttr->findFtracker(request->get_file_id());
+    if ( ftracker and !ftracker->ignore )
+    {
+        ftracker->upload = false;
+        ssd->ftracker_local = std::unique_ptr<DCE2_Smb2LocalFileTracker>(new DCE2_Smb2LocalFileTracker());
+        ssd->ftracker_local->file_offset = request->get_offset();
+        ssd->ftracker_tcp = ftracker;
+        if (!ssd->ftracker_local->file_offset and SMB2_SHARE_TYPE_DISK == ttr->get_share_type())
+        {
+            FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker, true);
+            if (file)
+                file->set_file_size(!ftracker->file_size ? UNKNOWN_FILE_SIZE : ftracker->file_size);
+        }
+        if (!DCE2_Smb2ProcessFileData(ssd, file_data, data_size))
+        {
+            ssd->removeRtracker(message_id);
+            return;
+        }
+
+        uint32_t total_data_length = alignedNtohl((const uint32_t*)&(smb_read_hdr->length));
+        DCE2_Smb2UpdateMaxOffset(ftracker, request->get_offset() + total_data_length);
+        if (total_data_length > (uint32_t)data_size)
+        {
+            ssd->ftracker_local->smb2_pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
+        }
+    }
+    ssd->removeRtracker(message_id);
+}
+
+//-------------------------------------------------------------------------
+// Process read message
+//-------------------------------------------------------------------------
+void DCE2_Smb2Read(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        DCE2_Smb2RequestTracker* rtr = ssd->findRtracker(mid);
+        if (rtr and rtr->get_file_id())
+        {
+            DCE2_Smb2FileTracker* ftracker = ttr->findFtracker(rtr->get_file_id());
+            if (ftracker)
+            {
+                ttr->removeFtracker(rtr->get_file_id());
+            }
+        }
+        ssd->removeRtracker(mid);
+        dce2_smb_stats.v2_read_err_resp++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+    }
+    // Using structure size to decide whether it is response or request
+    else if (structure_size == SMB2_READ_REQUEST_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_READ_REQUEST_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_read_req_hdr_err, SMB2_COM_READ)
+        DCE2_Smb2ReadRequest(ssd, (const Smb2ReadRequestHdr*)smb_data, end, str, ttr, mid);
+    }
+    else if (structure_size == SMB2_READ_RESPONSE_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_READ_RESPONSE_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_read_resp_hdr_err, SMB2_COM_READ)
+
+        DCE2_Smb2ReadResponse(ssd, smb_hdr, (const Smb2ReadResponseHdr*)smb_data, end, ttr, mid);
+    }
+    else
+    {
+        dce2_smb_stats.v2_read_inv_str_sz++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(),"%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process write request to create write trackers (to enforce credits limit)
+// and to send file data for inspection.
+//-------------------------------------------------------------------------
+static void DCE2_Smb2WriteRequest(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const Smb2WriteRequestHdr* smb_write_hdr, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid)
+{
+    const uint8_t* file_data =  (const uint8_t*)smb_write_hdr + SMB2_WRITE_REQUEST_STRUC_SIZE - 1;
+    int data_size = end - file_data;
+    uint64_t fileId_persistent, offset;
+    uint16_t data_offset;
+
+    fileId_persistent = alignedNtohq((const uint64_t*)(&(smb_write_hdr->fileId_persistent)));
+
+    if (ssd->max_outstanding_requests > ssd->getTotalRequestsPending())
+    {
+        DCE2_Smb2RequestTracker* writetracker = ssd->findRtracker(mid);
+        if (!writetracker)
+            writetracker = new DCE2_Smb2RequestTracker(fileId_persistent);
+        writetracker->set_session_id(str->session_id);
+        writetracker->set_tree_id(ttr->get_tid());
+        writetracker->set_file_id(fileId_persistent);
+        ssd->insertRtracker(mid, writetracker);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_REQ: max req exceeded\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+        dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
+            ssd->sd);
+        return;
+    }
+
+    data_offset = alignedNtohs((const uint16_t*)(&(smb_write_hdr->data_offset)));
+    if (data_offset + (const uint8_t*)smb_hdr > end)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_REQ: bad offset\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
+    }
+
+    offset = alignedNtohq((const uint64_t*)(&(smb_write_hdr->offset)));
+    DCE2_Smb2FileTracker* ftracker = ttr->findFtracker(fileId_persistent);
+
+    if (!ftracker and ttr->get_share_type() == SMB2_SHARE_TYPE_DISK)
+    {
+        ftracker = new DCE2_Smb2FileTracker(fileId_persistent, ttr, str, DetectionEngine::get_current_packet()->flow);
+        ttr->insertFtracker(fileId_persistent, ftracker);
+    }
+    if (!ftracker)
+    {
+        dce2_smb_stats.v2_read_rtrkr_misng++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(),
+            "%s_REQ: ftracker missing 0x%" PRIx64 "\n",
+            smb2_command_string[SMB2_COM_WRITE], fileId_persistent);
+        return;
+    }
+
+    if (!ftracker->ignore) // file tracker can not be nullptr here
+    {
+        if (ftracker->file_size and (offset > ftracker->file_size))
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_INVALID_FILE_OFFSET, (dce2CommonStats*)&dce2_smb_stats,
+                ssd->sd);
+        }
+
+        ftracker->upload = true;
+        ssd->ftracker_local = std::unique_ptr<DCE2_Smb2LocalFileTracker>(new DCE2_Smb2LocalFileTracker());
+        ssd->ftracker_local->file_offset = offset;
+        ssd->ftracker_tcp = ftracker;
+        if (!ssd->ftracker_local->file_offset and SMB2_SHARE_TYPE_DISK == ttr->get_share_type())
+        {
+            FileContext* file = DCE2_Smb2GetFileContext(ssd, ftracker, true);
+            if (file)
+                file->set_file_size(!ftracker->file_size ? UNKNOWN_FILE_SIZE : ftracker->file_size);
+        }
+        if (!DCE2_Smb2ProcessFileData(ssd, file_data, data_size))
+            return;
+
+        uint32_t total_data_length = alignedNtohl((const uint32_t*)&(smb_write_hdr->length));
+        DCE2_Smb2UpdateMaxOffset(ftracker, offset + total_data_length);
+        if (total_data_length > (uint32_t)data_size)
+        {
+            ssd->ftracker_local->smb2_pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process write message
+//-------------------------------------------------------------------------
+void DCE2_Smb2Write(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        DCE2_Smb2RequestTracker* wtr = ssd->findRtracker(mid);
+        if (wtr and wtr->get_file_id())
+        {
+            DCE2_Smb2FileTracker* ftracker = ttr->findFtracker(wtr->get_file_id());
+            if (ftracker)
+            {
+                ttr->removeFtracker(wtr->get_file_id());
+            }
+        }
+        ssd->removeRtracker(mid);
+        dce2_smb_stats.v2_wrt_err_resp++;
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+    }
+    // Using structure size to decide whether it is response or request
+    else if (structure_size == SMB2_WRITE_REQUEST_STRUC_SIZE)
+    {
+        SMB2_CHECK_HDR_ERROR(
+            smb_data, end, SMB2_WRITE_REQUEST_STRUC_SIZE - 1,
+            dce2_smb_stats.v2_wrt_req_hdr_err, SMB2_COM_WRITE)
+        DCE2_Smb2WriteRequest(ssd, smb_hdr, (const Smb2WriteRequestHdr*)smb_data, end, str, ttr,
+            mid);
+    }
+    else if (structure_size == SMB2_WRITE_RESPONSE_STRUC_SIZE)
+    {
+        ssd->removeRtracker(mid);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_WRITE]);
+        dce2_smb_stats.v2_wrt_inv_str_sz++;
+    }
+}
+
+//-------------------------------------------------------------------------
+// Process logoff to cleanup session tracker and their corresponding tree
+// trackers and their corresponding file trackers
+//-------------------------------------------------------------------------
+void DCE2_Smb2Logoff(DCE2_Smb2SsnData* ssd, const uint8_t* smb_data,
+    const uint64_t sid)
+{
+    if (alignedNtohs((const uint16_t*)smb_data) == SMB2_LOGOFF_REQUEST_STRUC_SIZE)
+    {
+        auto str = DCE2_Smb2FindSidInSsd(ssd, sid);
+        if (str)
+        {
+            auto session_key = get_key(sid);
+            DCE2_SmbSessionCacheRemove(session_key);
+        }
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            DetectionEngine::get_current_packet(), "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_LOGOFF]);
+        dce2_smb_stats.v2_logoff_inv_str_sz++;
+    }
+}
+
+void DCE2_Smb2IoctlCommand(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid)
+{
+    uint16_t structure_size = alignedNtohs((const uint16_t*)smb_data);
+    const uint8_t* file_data = (const uint8_t*)smb_data + structure_size - 1;
+    int data_size = end - file_data;
+    uint64_t fileId_persistent = 0;
+    Packet* p = DetectionEngine::get_current_packet();
+    if (data_size > UINT16_MAX)
+    {
+        data_size = UINT16_MAX;
+    }
+    if (structure_size == SMB2_ERROR_RESPONSE_STRUC_SIZE and Smb2Error(smb_hdr))
+    {
+        if ((alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) &&
+            (alignedNtohl(&(smb_hdr->status)) == SMB2_STATUS_PENDING))
+            return;
+
+        dce2_smb_stats.v2_ioctl_err_resp++;
+        ssd->removeRtracker(mid);
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            p, "%s_RESP: error\n",
+            smb2_command_string[SMB2_COM_IOCTL]);
+    }
+    // Using structure size to decide whether it is response or request
+    else if (structure_size == SMB2_IOCTL_REQUEST_STRUC_SIZE)
+    {
+        const Smb2IoctlRequestHdr* ioctl_request = (const Smb2IoctlRequestHdr*)smb_data;
+        if ((ioctl_request->ctl_code != FSCTL_PIPE_PEEK) and (ioctl_request->ctl_code !=
+            FSCTL_PIPE_WAIT) and (ioctl_request->ctl_code != FSCTL_PIPE_TRANSCEIVE))
+        {
+            return;
+        }
+        fileId_persistent = ioctl_request->fileId_persistent;
+        if (ssd->max_outstanding_requests > ssd->getTotalRequestsPending())
+        {
+            DCE2_Smb2RequestTracker* readtracker = ssd->findRtracker(mid);
+            if (!readtracker)
+                readtracker = new DCE2_Smb2RequestTracker(fileId_persistent, 0);
+            readtracker->set_session_id(str->session_id);
+            readtracker->set_tree_id(ttr->get_tid());
+            readtracker->set_file_id(fileId_persistent);
+            ssd->insertRtracker(mid, readtracker);
+        }
+        else
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL,
+                DetectionEngine::get_current_packet(), "%s_REQ: max req exceeded\n",
+                smb2_command_string[SMB2_COM_READ]);
+            dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
+                ssd->sd);
+            return;
+        }
+    }
+    else if (structure_size == SMB2_IOCTL_RESPONSE_STRUC_SIZE)
+    {
+        const Smb2IoctlResponseHdr* ioctl_response = (const Smb2IoctlResponseHdr*)smb_data;
+        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;
+        }
+        fileId_persistent = ioctl_response->fileId_persistent;
+        ssd->removeRtracker(mid);
+    }
+    else
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            p, "%s: invalid struct size\n",
+            smb2_command_string[SMB2_COM_IOCTL]);
+        dce2_smb_stats.v2_ioctl_inv_str_sz++;
+        return;
+    }
+    DCE2_Smb2FileTracker* ftracker =  ttr->findFtracker(fileId_persistent);
+    if (ftracker and ftracker->co_tracker)
+    {
+        DCE2_CoProcess(&ssd->sd, ftracker->co_tracker, file_data, data_size);
+    }
+}
+
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_commands.h b/src/service_inspectors/dce_rpc/dce_smb2_commands.h
new file mode 100644 (file)
index 0000000..1c054a6
--- /dev/null
@@ -0,0 +1,74 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2023 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// dce_smb2_commands.h author Bhargava Jandhyala <bjandhya@cisco.com>
+// based on work by Todd Wease
+
+#ifndef DCE_SMB2_COMMANDS_H
+#define DCE_SMB2_COMMANDS_H
+
+#include "dce_smb_module.h"
+#include "dce_smb_utils.h"
+#include "dce_smb2_utils.h"
+#include "detection/detection_util.h"
+#include "file_api/file_flows.h"
+#include "file_api/file_service.h"
+
+void DCE2_Smb2Setup(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint64_t sid, const uint8_t* smb_data, const uint8_t* end);
+
+void DCE2_Smb2TreeConnect(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str, uint32_t tid);
+
+void DCE2_Smb2TreeDisconnect(DCE2_Smb2SsnData*, const uint8_t* smb_data,
+    const uint8_t* end);
+
+void DCE2_Smb2Create(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, uint64_t mid, uint64_t sid, uint32_t tid);
+
+void DCE2_Smb2Read(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid);
+
+void DCE2_Smb2Write(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2SessionTracker* str,
+    DCE2_Smb2TreeTracker* ttr, uint64_t mid);
+
+void DCE2_Smb2SetInfo(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2TreeTracker* ttr);
+
+bool DCE2_Smb2ProcessFileData(DCE2_Smb2SsnData*, const uint8_t* file_data,
+    uint32_t data_size);
+
+void DCE2_Smb2CloseCmd(DCE2_Smb2SsnData*, const Smb2Hdr*,
+    const uint8_t* smb_data, const uint8_t* end, DCE2_Smb2TreeTracker* ttr,
+    DCE2_Smb2SessionTracker* str, uint64_t mid);
+
+void DCE2_Smb2Logoff(DCE2_Smb2SsnData*, const uint8_t* smb_data,
+    const uint64_t sid);
+
+DCE2_Smb2TreeTracker*find_tree_for_message(DCE2_Smb2SsnData*, const uint64_t);
+
+bool DCE2_IsSmb2DurableReconnect(const Smb2CreateRequestHdr* smb_create_hdr, const uint8_t* end, uint64_t& file_id);
+
+void DCE2_Smb2IoctlCommand(DCE2_Smb2SsnData* ssd, const Smb2Hdr* smb_hdr,
+    const uint8_t* smb_data, const uint8_t* end,
+    DCE2_Smb2SessionTracker* str, DCE2_Smb2TreeTracker* ttr, uint64_t mid);
+
+#endif
+
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_file.cc b/src/service_inspectors/dce_rpc/dce_smb2_file.cc
deleted file mode 100644 (file)
index cd50843..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_file.cc author Dipta Pandit <dipandit@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "dce_smb2_file.h"
-
-#include "file_api/file_flows.h"
-#include "hash/hash_key_operations.h"
-
-#include "dce_co.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)
-{
-    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> 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))
-        {
-            current_flow_state.file_offset = offset;
-        }
-
-        current_flow_state.pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
-        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)
-        current_flow_state.pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
-}
-
-inline void Dce2Smb2FileTracker::file_detect()
-{
-    DetectionEngine::detect(DetectionEngine::get_current_packet());
-    dce2_detected = 1;
-}
-
-std::pair<bool, Dce2Smb2SessionData*> Dce2Smb2FileTracker::update_processing_flow(
-    Dce2Smb2SessionData* current_flow,Dce2Smb2SessionTrackerPtr session_tracker)
-{
-    bool switched = false;
-    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;
-        if (current_flow)
-            processing_flow = current_flow;
-        else
-        {
-            Flow* flow = DetectionEngine::get_current_packet()->flow;
-            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);
-        }
-    }
-    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);
-}
-
-void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint64_t size_v)
-{
-    if (file_name_v and name_len_v and !file_name)
-    {
-        file_name = (char*)snort_alloc(name_len_v + 1);
-        memcpy(file_name, file_name_v, name_len_v);
-        file_name_len = name_len_v;
-        file_name_hash = str_to_hash((uint8_t*)file_name, file_name_len);
-    }
-    file_size = size_v;
-    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);
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
-            "set file info: file size %"
-            PRIu64 " fid %" PRIu64 " file_name_hash %" PRIu64 " file context "
-            "%sfound\n", size_v, file_id, file_name_hash, (file ? "" : "not "));
-        if (file)
-        {
-            ignore = false;
-            if (file->verdict == FILE_VERDICT_UNKNOWN)
-            {
-                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);
-            }
-        }
-    }
-}
-
-bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key)
-{
-    flow_state_mutex.lock();
-    uint64_t file_offset = flow_state[current_flow_key].file_offset;
-    flow_state_mutex.unlock();
-    if (!ignore and !file_size and file_offset)
-    {
-        file_size = file_offset;
-        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);
-        }
-        return (!process_data(current_flow_key, nullptr, 0, ses_ptr));
-    }
-    return true;
-}
-
-bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const uint8_t* file_data,
-    uint32_t data_size, const uint64_t offset, uint64_t max_offset)
-{
-    flow_state_mutex.lock();
-    tcp_flow_state& current_flow_state = flow_state[current_flow_key];
-    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 (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;
-        }
-        current_flow->session_data_mutex.lock();
-        if (current_flow->get_tcp_flow())
-            current_flow->get_tcp_flow()->last_data_seen = packet_time();
-        sess->co_tracker_mutex.lock();
-        if (parent_tree->get_cotracker())
-        {
-            DCE2_CoProcess(current_flow->get_dce2_session_data(), parent_tree->get_cotracker(),
-                file_data, data_size);
-        }
-        sess->co_tracker_mutex.unlock();
-        current_flow->session_data_mutex.unlock();
-        return true;
-    }
-    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)
-{
-    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;
-
-    flow_state_mutex.lock();
-    uint64_t file_offset = flow_state[current_flow_key].file_offset;
-    flow_state_mutex.unlock();
-
-    if (file_detection_depth == 0)
-        detection_size = data_size;
-    else if ( file_offset < (uint64_t)file_detection_depth)
-    {
-        if ( file_detection_depth - file_offset < data_size )
-            detection_size = file_detection_depth - file_offset;
-        else
-            detection_size = data_size;
-    }
-
-    if (detection_size)
-    {
-        set_file_data(file_data, (detection_size > UINT16_MAX) ?
-            UINT16_MAX : (uint16_t)detection_size);
-        file_detect();
-    }
-
-    if (ignore)
-    {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL, p,
-            "file name not set , ignored\n");
-        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");
-        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;
-    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);
-    {
-        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");
-            processing_flow->session_data_mutex.unlock();
-            return true;
-        }
-
-        {
-            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
-                bool is_new_context = false;
-                FileContext* file = file_flows->get_file_context(file_name_hash, true, is_new_context, 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;
-            }
-        }
-    }
-
-    file_offset += data_size;
-    flow_state_mutex.lock();
-    flow_state[current_flow_key].file_offset = file_offset;
-    flow_state_mutex.unlock();
-    processing_flow->session_data_mutex.unlock();
-    return true;
-}
-
-Dce2Smb2FileTracker::~Dce2Smb2FileTracker(void)
-{
-    if (file_name)
-        snort_free((void*)file_name);
-
-    file_name = nullptr;
-    parent_tree.reset();
-}
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_file.h b/src/service_inspectors/dce_rpc/dce_smb2_file.h
deleted file mode 100644 (file)
index 8159110..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_file.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifndef DCE_SMB2_FILE_H
-#define DCE_SMB2_FILE_H
-
-// This provides file tracker for SMBv2
-
-#include "dce_smb2.h"
-#include <atomic>
-
-class Dce2Smb2TreeTracker;
-using Dce2Smb2TreeTrackerPtr = std::shared_ptr<Dce2Smb2TreeTracker>;
-
-typedef struct _tcp_flow_state
-{
-    Dce2SmbPduState pdu_state;
-    uint64_t file_offset;
-    uint64_t max_offset;
-} tcp_flow_state;
-
-class Dce2Smb2FileTracker
-{
-public:
-
-    Dce2Smb2FileTracker() = delete;
-    Dce2Smb2FileTracker(const Dce2Smb2FileTracker& arg) = delete;
-    Dce2Smb2FileTracker& operator=(const Dce2Smb2FileTracker& arg) = delete;
-
-    Dce2Smb2FileTracker(uint64_t file_idv, const uint32_t flow_key, Dce2Smb2TreeTrackerPtr p_tree,
-        uint64_t sid) :
-        ignore(true), file_name_len(0), file_flow_key(flow_key),
-        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,
-            "file tracker %" PRIu64 " created\n", file_id);
-    }
-
-    ~Dce2Smb2FileTracker();
-    bool process_data(const uint32_t, const uint8_t*, uint32_t, const uint64_t, uint64_t);
-    bool process_data(const uint32_t, const uint8_t*, uint32_t, Dce2Smb2SessionTrackerPtr);
-    bool close(const uint32_t);
-    void set_info(char*, uint16_t, uint64_t);
-    void accept_raw_data_from(Dce2Smb2SessionData*, uint64_t, Dce2Smb2FileTrackerPtr);
-    bool accepting_raw_data_from(uint32_t current_flow_key)
-    {
-        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; }
-    Dce2Smb2TreeTrackerPtr get_parent() { return parent_tree; }
-    void set_parent(Dce2Smb2TreeTrackerPtr pt) { parent_tree = pt; }
-    uint64_t get_file_id() { return file_id; }
-    uint64_t get_file_name_hash() { return file_name_hash; }
-    uint64_t get_session_id() { return session_id; }
-    std::unordered_map<uint32_t, tcp_flow_state, std::hash<uint32_t> > get_flow_state_map()
-    {
-        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,
-        Dce2Smb2SessionTrackerPtr session_tracker = nullptr);
-    bool ignore;
-    uint16_t file_name_len;
-    uint32_t file_flow_key;
-    uint64_t file_id;
-    std::atomic<uint64_t> file_size;
-    uint64_t file_name_hash;
-    char* file_name;
-    FileDirection direction;
-    Dce2Smb2TreeTrackerPtr parent_tree;
-    std::unordered_map<uint32_t, tcp_flow_state, std::hash<uint32_t> > flow_state;
-    uint64_t session_id;
-    std::mutex process_file_mutex;
-    std::mutex flow_state_mutex;
-};
-
-using Dce2Smb2FileTrackerPtr = std::shared_ptr<Dce2Smb2FileTracker>;
-using Dce2Smb2FileTrackerMap =
-        std::unordered_map<uint64_t, Dce2Smb2FileTrackerPtr, std::hash<uint64_t> >;
-
-#endif
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_request.h b/src/service_inspectors/dce_rpc/dce_smb2_request.h
deleted file mode 100644 (file)
index 1454baa..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_request.h author Bhargava Jandhyala <bjandhya@cisco.com>
-
-#ifndef DCE_SMB2_REQUEST_H
-#define DCE_SMB2_REQUEST_H
-
-// This provides request trackers for SMBv2.
-// Request trackers are used to track CREATE, READ and WRITE requests
-
-#include "dce_smb2.h"
-
-class Dce2Smb2RequestTracker
-{
-public:
-
-    Dce2Smb2RequestTracker() = delete;
-    Dce2Smb2RequestTracker(const Dce2Smb2RequestTracker& arg) = delete;
-    Dce2Smb2RequestTracker& operator=(const Dce2Smb2RequestTracker& arg) = delete;
-
-    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");
-    }
-
-    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");
-    }
-
-    ~Dce2Smb2RequestTracker()
-    {
-        if (fname)
-            snort_free(fname);
-    }
-
-    uint64_t get_offset() { return offset; }
-    uint64_t get_file_id() { return file_id; }
-    char* get_file_name() { return fname; }
-    uint16_t get_file_name_size() { return fname_len; }
-
-private:
-    char* fname;
-    uint16_t fname_len;
-    uint64_t file_id;
-    uint64_t offset;
-};
-
-using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
-using Dce2Smb2RequestTrackerMap =
-        std::unordered_map<Smb2MessageKey, Dce2Smb2RequestTrackerPtr, Smb2KeyHash>;
-
-#endif
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session.cc b/src/service_inspectors/dce_rpc/dce_smb2_session.cc
deleted file mode 100644 (file)
index 5bd0dd8..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_session.cc author Dipta Pandit <dipandit@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "dce_smb2_session.h"
-
-#include "dce_smb2_session_cache.h"
-
-#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::recursive_mutex> guard(attached_flows_mutex);
-    auto it_flow = attached_flows.find(flow_key);
-    return (it_flow != attached_flows.end()) ? it_flow->second : nullptr;
-}
-
-Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::find_tree_for_message(
-    const uint64_t message_id, const uint32_t flow_key)
-{
-    std::lock_guard<std::mutex> guard(connected_trees_mutex);
-    for (auto it_tree : connected_trees)
-    {
-        Dce2Smb2RequestTrackerPtr request = it_tree.second->find_request(message_id, flow_key);
-        if (request)
-            return it_tree.second;
-    }
-    return nullptr;
-}
-
-Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::find_tree_for_tree_id(
-    const uint32_t tree_id)
-{
-    std::lock_guard<std::mutex> guard(connected_trees_mutex);
-    auto it_tree = connected_trees.find(tree_id);
-    if (it_tree != connected_trees.end())
-        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;
-        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)
-{
-    Dce2Smb2TreeTrackerPtr tree;
-    uint32_t tree_id = Smb2Tid(smb_header);
-
-    if (tree_id)
-    {
-        connected_trees_mutex.lock();
-        auto it_tree = connected_trees.find(tree_id);
-        if (it_tree != connected_trees.end())
-            tree = it_tree->second;
-        connected_trees_mutex.unlock();
-    }
-    else
-    {
-        //async response case
-        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, share_type);
-    }
-    break;
-    case SMB2_COM_TREE_DISCONNECT:
-    {
-        if (!tree)
-            dce2_smb_stats.v2_tree_discn_ignored++;
-    }
-    break;
-
-    //for all other cases, tree tracker should handle the command
-    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,
-                "%s_REQ: mid-stream session detected\n",
-                smb2_command_string[command]);
-            tree = connect_tree(tree_id);
-            if (!tree)
-            {
-                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID,
-                    TRACE_INFO_LEVEL, GET_CURRENT_PACKET,
-                    "%s_REQ: insert tree tracker failed\n",
-                    smb2_command_string[command]);
-            }
-        }
-    // fallthrough
-    default:
-        if (tree)
-            tree->process(command, command_type, smb_header, end, current_flow_key);
-        else
-        {
-            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++;
-        }
-        break;
-    }
-}
-
-Dce2Smb2TreeTrackerPtr Dce2Smb2SessionTracker::connect_tree(const uint32_t tree_id,
-    const uint8_t share_type)
-{
-    Dce2Smb2TreeTrackerPtr tree;
-    connected_trees_mutex.lock();
-    auto it_tree = connected_trees.find(tree_id);
-    if (it_tree != connected_trees.end())
-        tree = it_tree->second;
-    connected_trees_mutex.unlock();
-    if (!tree)
-    {
-        tree = std::make_shared<Dce2Smb2TreeTracker>(tree_id, this, share_type);
-        connected_trees_mutex.lock();
-        connected_trees.insert(std::make_pair(tree_id, tree));
-        connected_trees_mutex.unlock();
-        increase_size(sizeof(Dce2Smb2TreeTracker));
-    }
-    return tree;
-}
-
-void Dce2Smb2SessionTracker::increase_size(const size_t size)
-{
-    smb2_session_cache.increase_size(size);
-}
-
-void Dce2Smb2SessionTracker::decrease_size(const size_t size)
-{
-    smb2_session_cache.decrease_size(size);
-}
-
-// Session Tracker is created and destroyed only from session cache
-Dce2Smb2SessionTracker::~Dce2Smb2SessionTracker(void)
-{
-    if (!(fcfs_mutex.try_lock()))
-        return;
-
-    if (do_not_delete )
-    {
-        // Dont prune the session in LRU Cache
-        smb2_session_cache.find_id(get_key());
-        fcfs_mutex.unlock();
-        return;
-    }
-    disconnect_tree();
-    free_map();
-
-    do_not_delete = false;
-    fcfs_mutex.unlock();
-    std::lock_guard<std::recursive_mutex> guard(attached_flows_mutex);
-    attached_flows.clear();
-}
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session.h b/src/service_inspectors/dce_rpc/dce_smb2_session.h
deleted file mode 100644 (file)
index f8bc618..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_session.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifndef DCE_SMB2_SESSION_H
-#define DCE_SMB2_SESSION_H
-
-// This provides session tracker for SMBv2
-
-#include "dce_smb2.h"
-#include "dce_smb2_tree.h"
-
-uint32_t Smb2Tid(const Smb2Hdr* hdr);
-
-typedef struct _msgid_state
-{
-    uint64_t max_req_msg_id = 0;
-    uint64_t max_resp_msg_id = 0;
-    std::unordered_set<uint64_t> missing_req_msg_ids;
-    std::unordered_set<uint64_t> missing_resp_msg_ids;
-} msgid_state;
-
-class Dce2Smb2SessionTracker
-{
-public:
-    Dce2Smb2SessionTracker(const Smb2SessionKey& key)
-    {
-        session_id = key.sid;
-        session_key = key;
-        reload_prune = false;
-        do_not_delete = false;
-        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,
-            "session tracker %" PRIu64 "created\n", session_id);
-    }
-
-    ~Dce2Smb2SessionTracker();
-    Dce2Smb2TreeTrackerPtr connect_tree(const uint32_t,
-        uint8_t=SMB2_SHARE_TYPE_DISK);
-
-    void disconnect_tree()
-    {
-        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::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::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; }
-    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 decrease_size(const size_t size);
-    void set_reload_prune(bool flag) { reload_prune = flag; }
-    uint64_t get_session_id() { return session_id; }
-    void set_do_not_delete(bool flag) { do_not_delete = flag; }
-    bool get_do_not_delete() { return do_not_delete; }
-    void set_file_context_cleaned(bool flag) { file_context_cleaned = flag; }
-    bool get_file_context_cleaned() { return file_context_cleaned; }
-    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++;
-    }
-
-    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
-    bool do_not_delete;
-    bool file_context_cleaned;
-    Dce2Smb2TreeTrackerPtr find_tree_for_message(const uint64_t, const uint32_t);
-    uint64_t session_id;
-    //to keep the tab of previous command
-    uint16_t command_prev;
-    Smb2SessionKey session_key;
-    Dce2Smb2TreeTrackerMap connected_trees;
-    std::atomic<bool> reload_prune;
-    std::atomic<bool> encryption_flag;
-    std::mutex connected_trees_mutex;
-
-    // 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
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h b/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h
deleted file mode 100644 (file)
index 7713826..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_session_cache.h author Bhargava Jandhyala <bjandhya@cisco.com>
-
-#ifndef DCE_SMB2_SESSION_CACHE_H
-#define DCE_SMB2_SESSION_CACHE_H
-
-// This provides a wrapper over LRU cache shared for SMBv2 Session trackers
-
-#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> > >
-class Dce2Smb2SharedCache : public LruCacheShared<Key, Value, Hash, Eq, Purgatory>
-{
-public:
-    Dce2Smb2SharedCache() = delete;
-    Dce2Smb2SharedCache(const Dce2Smb2SharedCache& arg) = delete;
-    Dce2Smb2SharedCache& operator=(const Dce2Smb2SharedCache& arg) = delete;
-    Dce2Smb2SharedCache(const size_t initial_size) :
-        LruCacheShared<Key, Value, Hash, Eq, Purgatory>(initial_size) { }
-
-    using Data = std::shared_ptr<Value>;
-
-    Data find_id(const Key& key)
-    {
-        Data session = this->find(key);
-        return session;
-    }
-
-    Data find_session(const Key& key)
-    {
-        Data session = this->find(key);
-        return session;
-    }
-
-    Data find_else_create_session(const Key& key, Dce2Smb2SessionData* ssd)
-    {
-        Data new_session = Data(new Value(key));
-        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
-    {
-        return current_size;
-    }
-
-    void increase_size(size_t size)
-    {
-        current_size += size;
-    }
-
-    void decrease_size(size_t size)
-    {
-        assert(current_size >= size);
-        current_size -= size;
-    }
-
-    // Since decrease_size() does not account for associated objects in smb2_session_cache,
-    // we will over-prune when we reach the new_size here, as more space will be freed up
-    // when actual objects are destroyed. We might need to do gradual pruning like how
-    // host cache does. For now over pruning is ok.
-    void reload_prune(size_t new_size)
-    {
-        Purgatory data;
-        std::lock_guard<std::mutex> cache_lock(cache_mutex);
-        max_size = new_size;
-        while (current_size > max_size && !list.empty())
-        {
-            LruListIter list_iter = --list.end();
-            data.emplace_back(list_iter->second); // increase reference count
-            // This instructs the session_tracker to take a lock before detaching
-            // from ssd, when it is getting destroyed.
-            if (!list_iter->second->get_do_not_delete())
-            {
-                list_iter->second->set_reload_prune(true);
-                decrease_size(list_iter->second.get());
-                map.erase(list_iter->first);
-                list.erase(list_iter);
-                ++stats.reload_prunes;
-            }
-            else
-            {
-                // Move entry to front of LruList
-                list.splice(list.begin(), list, list_iter);
-            }
-        }
-    }
-
-private:
-    using LruBase = LruCacheShared<Key, Value, Hash, Eq, Purgatory>;
-    using LruBase::cache_mutex;
-    using LruBase::current_size;
-    using LruBase::list;
-    using LruBase::map;
-    using LruBase::max_size;
-    using LruBase::stats;
-    using LruListIter = typename LruBase::LruListIter;
-    void increase_size(Value* value_ptr=nullptr) override
-    {
-        if (value_ptr) current_size += sizeof(*value_ptr);
-    }
-
-    void decrease_size(Value* value_ptr=nullptr) override
-    {
-        if (value_ptr)
-        {
-            assert(current_size >= sizeof(*value_ptr) );
-            current_size -= sizeof(*value_ptr);
-        }
-    }
-};
-
-using Dce2Smb2SessionCache =
-        Dce2Smb2SharedCache<Smb2SessionKey, Dce2Smb2SessionTracker, Smb2KeyHash>;
-
-extern Dce2Smb2SessionCache smb2_session_cache;
-
-#endif
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_tree.cc b/src/service_inspectors/dce_rpc/dce_smb2_tree.cc
deleted file mode 100644 (file)
index 7884702..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_tree.cc author Dipta Pandit <dipandit@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "dce_smb2_tree.h"
-
-#include "dce_smb2_session.h"
-#include <memory>
-
-using namespace snort;
-
-#define SMB2_CREATE_DURABLE_RECONNECT "DHnC"
-#define SMB2_CREATE_DURABLE_RECONNECT_V2 "DH2C"
-
-uint64_t Smb2Mid(const Smb2Hdr* hdr)
-{
-    return alignedNtohq(&(hdr->message_id));
-}
-
-Dce2Smb2FileTrackerPtr Dce2Smb2TreeTracker::open_file(const uint64_t file_id,
-    const uint32_t current_flow_key)
-{
-    Dce2Smb2TreeTrackerPtr tree_ptr = parent_session->find_tree_for_tree_id(tree_id);
-    if (!tree_ptr)
-        return nullptr;
-    std::shared_ptr<Dce2Smb2FileTracker> ftracker =  std::make_shared<Dce2Smb2FileTracker> (
-        file_id, current_flow_key, tree_ptr, this->get_parent()->get_session_id());
-    tree_tracker_mutex.lock();
-    opened_files.insert(std::make_pair(file_id, ftracker));
-    tree_tracker_mutex.unlock();
-    parent_session->increase_size(sizeof(Dce2Smb2FileTracker));
-    return ftracker;
-}
-
-Dce2Smb2FileTrackerPtr Dce2Smb2TreeTracker::find_file(uint64_t file_id)
-{
-    std::lock_guard<std::mutex> guard(tree_tracker_mutex);
-    auto it_file = opened_files.find(file_id);
-    if (it_file != opened_files.end())
-        return it_file->second;
-    return nullptr;
-}
-
-void Dce2Smb2TreeTracker::close_file(uint64_t file_id, bool destroy)
-{
-    tree_tracker_mutex.lock();
-    auto it_file = opened_files.find(file_id);
-    if (it_file != opened_files.end())
-    {
-        Dce2Smb2FileTrackerPtr file = it_file->second;
-        it_file->second->get_parent().reset();
-        if (opened_files.erase(file_id) and destroy)
-        {
-            parent_session->decrease_size(sizeof(Dce2Smb2FileTracker));
-            tree_tracker_mutex.unlock();
-            return;
-        }
-    }
-    tree_tracker_mutex.unlock();
-}
-
-void Dce2Smb2TreeTracker::close_all_files()
-{
-    tree_tracker_mutex.lock();
-    auto it_file = opened_files.begin();
-    while (it_file != opened_files.end())
-    {
-        it_file = opened_files.erase(it_file);
-    }
-    tree_tracker_mutex.unlock();
-}
-
-Dce2Smb2RequestTrackerPtr Dce2Smb2TreeTracker::find_request(const uint64_t message_id,
-    const uint32_t current_flow_key)
-{
-    Smb2MessageKey message_key = { message_id, current_flow_key, 0 };
-    std::lock_guard<std::mutex> guard(tree_tracker_mutex);
-    auto request_it = active_requests.find(message_key);
-    return (request_it == active_requests.end()) ? nullptr : request_it->second;
-}
-
-bool Dce2Smb2TreeTracker::remove_request(const uint64_t message_id,
-    const uint32_t current_flow_key)
-{
-    Smb2MessageKey message_key = { message_id, current_flow_key, 0 };
-    std::lock_guard<std::mutex> guard(tree_tracker_mutex);
-    auto request_it = active_requests.find(message_key);
-    if (request_it != active_requests.end())
-    {
-        return active_requests.erase(message_key);
-    }
-    return false;
-}
-
-void Dce2Smb2TreeTracker::process_set_info_request(const Smb2Hdr* smb_header)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    const Smb2SetInfoRequestHdr* set_info_hdr = (const Smb2SetInfoRequestHdr*)smb_data;
-
-    if (set_info_hdr->file_info_class == SMB2_FILE_ENDOFFILE_INFO)
-    {
-        uint64_t file_size = alignedNtohq((const uint64_t*)((const uint8_t*)
-            set_info_hdr + SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1));
-        uint64_t file_id = alignedNtohq(&(set_info_hdr->fileId_persistent));
-
-        do_not_delete_tree = true;
-        Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
-        if (file_tracker)
-            file_tracker->set_info(nullptr, 0, file_size);
-        else
-        {
-            dce2_smb_stats.v2_stinf_req_ftrkr_misng++;
-            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]);
-        }
-        do_not_delete_tree = false;
-    }
-    else
-    {
-        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++;
-    }
-}
-
-void Dce2Smb2TreeTracker::process_close_request(const Smb2Hdr* smb_header,
-    const uint32_t current_flow_key)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    uint64_t file_id = alignedNtohq(&(((const Smb2CloseRequestHdr*)
-        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",
-            smb2_command_string[SMB2_COM_CLOSE], file_id);
-        do_not_delete_tree = false;
-        return;
-    }
-    if (file_tracker->close(current_flow_key))
-        close_file(file_id, true);
-
-    do_not_delete_tree = false;
-
-    if (share_type != SMB2_SHARE_TYPE_DISK)
-    {
-        parent_session->co_tracker_mutex.lock();
-        DCE2_CoCleanTracker(co_tracker);
-        parent_session->co_tracker_mutex.unlock();
-
-    }
-}
-
-uint64_t Dce2Smb2TreeTracker::get_durable_file_id(
-    const Smb2CreateRequestHdr* smb_create_hdr, const uint8_t* end)
-{
-    const uint8_t* data = (const uint8_t*)smb_create_hdr +
-        alignedNtohl(&smb_create_hdr->create_contexts_offset) - SMB2_HEADER_LENGTH;
-    uint32_t remaining = alignedNtohl(&smb_create_hdr->create_contexts_length);
-
-    while (remaining > sizeof(Smb2CreateContextHdr) and data < end)
-    {
-        const Smb2CreateContextHdr* context = (const Smb2CreateContextHdr*)data;
-        uint32_t next = alignedNtohl(&context->next);
-        uint16_t name_offset = alignedNtohs(&context->name_offset);
-        uint16_t name_length = alignedNtohs(&context->name_length);
-        uint16_t data_offset = alignedNtohs(&context->data_offset);
-        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))
-        {
-            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, name_length) == 0))
-        {
-            return alignedNtohq((const uint64_t*)(((const uint8_t*)context) +
-                data_offset));
-        }
-
-        if (!next)
-            break;
-
-        data += next;
-        remaining -= next;
-    }
-    return 0;
-}
-
-void Dce2Smb2TreeTracker::process_create_response(const uint64_t message_id,
-    const uint32_t current_flow_key, const Smb2Hdr* smb_header)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    const Smb2CreateResponseHdr* create_res_hdr = (const Smb2CreateResponseHdr*)smb_data;
-    uint64_t file_size = 0;
-    uint64_t file_id = alignedNtohq((const uint64_t*)(&(create_res_hdr->fileId_persistent)));
-    if (create_res_hdr->end_of_file)
-        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,
-            GET_CURRENT_PACKET, "%s_RESP: not processing for directory\n",
-            smb2_command_string[SMB2_COM_CREATE]);
-        close_file(file_id, true);
-    }
-    else
-    {
-        do_not_delete_tree = true;
-        Dce2Smb2RequestTrackerPtr create_request = find_request(message_id, current_flow_key);
-        if (create_request)
-        {
-            Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
-            if (!file_tracker)
-                file_tracker = open_file(file_id, current_flow_key);
-
-            if (share_type == SMB2_SHARE_TYPE_DISK)
-            {
-                file_tracker->set_info(create_request->get_file_name(),
-                    create_request->get_file_name_size(), file_size);
-            }
-        }
-        else
-        {
-            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++;
-        }
-        do_not_delete_tree = false;
-    }
-}
-
-void Dce2Smb2TreeTracker::process_create_request(const uint64_t message_id,
-    const uint32_t current_flow_key, const Smb2Hdr* smb_header, const uint8_t* end)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    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,
-            GET_CURRENT_PACKET, "%s_REQ: name_offset %" PRIu16 "\n",
-            smb2_command_string[SMB2_COM_CREATE], create_req_hdr->name_offset);
-        dce2_smb_stats.v2_crt_req_hdr_err++;
-        return;
-    }
-    const uint8_t* file_name_offset = (const uint8_t*)smb_header +
-        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))
-    {
-        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",
-            smb2_command_string[SMB2_COM_CREATE], file_name_size);
-        dce2_smb_stats.v2_crt_inv_file_data++;
-        return;
-    }
-
-    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
-    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,
-            GET_CURRENT_PACKET, "SMB2_COM_CREATE_REQ: store failed\n");
-    }
-    //check if file_id is available form a durable reconnect request.
-    //if present we can create a file tracker right now.
-    //mostly this is the case for compound request.
-    uint64_t file_id = get_durable_file_id(create_req_hdr, end);
-    if (file_id)
-    {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-            GET_CURRENT_PACKET, "requested file_id %lu\n", file_id);
-        do_not_delete_tree = true;
-        Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
-        if (!file_tracker)
-        {
-            file_tracker = open_file(file_id, current_flow_key);
-            if (share_type == SMB2_SHARE_TYPE_DISK)
-            {
-                file_tracker->set_info(file_name, name_len, 0);
-            }
-        }
-        do_not_delete_tree = false;
-    }
-}
-
-void Dce2Smb2TreeTracker::process_read_response(const uint64_t message_id,
-    const uint32_t current_flow_key, const Smb2Hdr* smb_header, const uint8_t* end)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    const Smb2ReadResponseHdr* read_resp_hdr = (const Smb2ReadResponseHdr*)smb_data;
-
-    uint16_t data_offset = alignedNtohs((const uint16_t*)(&(read_resp_hdr->data_offset)));
-    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,
-            GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: bad offset\n");
-        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats,
-            *current_flow->get_dce2_session_data());
-    }
-
-    do_not_delete_tree = true;
-
-    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,
-            GET_CURRENT_PACKET, "SMB2_COM_READ_RESP: request tracker missing\n");
-        dce2_smb_stats.v2_read_rtrkr_misng++;
-        do_not_delete_tree = false;
-        return;
-    }
-
-    Dce2Smb2FileTrackerPtr file_tracker = find_file(read_request->get_file_id());
-    if (file_tracker)
-    {
-        const uint8_t* file_data =  (const uint8_t*)read_resp_hdr +
-            SMB2_READ_RESPONSE_STRUC_SIZE - 1;
-        // we may not have enough data in some case, use best effort to process file for whatever
-        // data we have till now.
-        int data_size = (read_resp_hdr->length > (end - file_data)) ?
-            (end - file_data) : read_resp_hdr->length;
-        if (file_tracker->process_data(current_flow_key, file_data, data_size,
-            read_request->get_offset(), read_resp_hdr->length))
-        {
-            if ((uint32_t)data_size < alignedNtohl((const uint32_t*)&(read_resp_hdr->length)))
-            {
-                file_tracker->accept_raw_data_from(current_flow, 0, file_tracker);
-            }
-        }
-    }
-    else
-    {
-        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;
-}
-
-void Dce2Smb2TreeTracker::process_read_request(const uint64_t message_id,
-    const uint32_t current_flow_key, const Smb2Hdr* smb_header)
-{
-    const uint8_t* smb_data = (const uint8_t*)smb_header + SMB2_HEADER_LENGTH;
-    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)));
-    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");
-    }
-    do_not_delete_tree = true;
-    Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
-    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,
-            GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: start accepting Raw Data\n");
-        file_tracker->accept_raw_data_from(current_flow,offset, file_tracker);
-    }
-    else
-    {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: file tracker missing\n");
-    }
-    do_not_delete_tree = false;
-}
-
-void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
-    const uint32_t current_flow_key, const Smb2Hdr* smb_header, const uint8_t* end)
-{
-    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)));
-    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))
-    {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            GET_CURRENT_PACKET, "SMB2_COM_WRITE_REQ: bad offset\n");
-        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats,
-            *current_flow->get_dce2_session_data());
-    }
-    //track this request to clean up opened file in case of error response
-    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");
-    }
-    const uint8_t* file_data = (const uint8_t*)write_req_hdr + SMB2_WRITE_REQUEST_STRUC_SIZE - 1;
-    do_not_delete_tree = true;
-    Dce2Smb2FileTrackerPtr file_tracker = find_file(file_id);
-    if (file_tracker)
-    {
-        file_tracker->set_direction(FILE_UPLOAD);
-        // we may not have enough data in some case, use best effort to process file for whatever
-        // data we have till now.
-        int data_size = (write_req_hdr->length > (end - file_data)) ?
-            (end - file_data) : write_req_hdr->length;
-        uint64_t offset = alignedNtohq((const uint64_t*)(&(write_req_hdr->offset)));
-        if (file_tracker->process_data(current_flow_key, file_data, data_size, offset,
-            write_req_hdr->length))
-        {
-            if ((uint32_t)data_size < alignedNtohl((const uint32_t*)&(write_req_hdr->length)))
-            {
-                file_tracker->accept_raw_data_from(current_flow, 0, file_tracker);
-            }
-        }
-    }
-    else
-    {
-        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 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) ?
-        SMB2_IOCTL_REQUEST_STRUC_SIZE : SMB2_IOCTL_RESPONSE_STRUC_SIZE;
-    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 !=
-            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 !=
-            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;
-    Packet* p = DetectionEngine::get_current_packet();
-    if (data_size > UINT16_MAX)
-    {
-        data_size = UINT16_MAX;
-    }
-    parent_session->co_tracker_mutex.lock();
-    if (co_tracker)
-    {
-        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)
-{
-    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]);
-        dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
-            *current_flow->get_dce2_session_data());
-        return;
-    }
-
-    uint64_t message_id = Smb2Mid(smb_header);
-
-    switch (command)
-    {
-    case SMB2_COM_CREATE:
-        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]);
-        }
-        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]);
-                dce2_smb_stats.v2_crt_req_ipc++;
-            }
-            process_create_request(message_id, current_flow_key, smb_header, end);
-        }
-        else if (SMB2_CMD_TYPE_RESPONSE == command_type)
-            process_create_response(message_id, current_flow_key, smb_header);
-        break;
-    case SMB2_COM_CLOSE:
-        process_close_request(smb_header, current_flow_key);
-        break;
-    case SMB2_COM_SET_INFO:
-        process_set_info_request(smb_header);
-        break;
-    case SMB2_COM_READ:
-        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]);
-            do_not_delete_tree = true;
-            Dce2Smb2RequestTrackerPtr request = find_request(message_id, current_flow_key);
-            if (request)
-                close_file(request->get_file_id(), true);
-            do_not_delete_tree = false;
-        }
-        else if (SMB2_CMD_TYPE_REQUEST == command_type)
-            process_read_request(message_id, current_flow_key, smb_header);
-        else if (SMB2_CMD_TYPE_RESPONSE == command_type)
-            process_read_response(message_id, current_flow_key, smb_header, end);
-        break;
-    case SMB2_COM_WRITE:
-        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,
-                GET_CURRENT_PACKET, "%s_RESP: error\n", smb2_command_string[command]);
-            do_not_delete_tree = true;
-            Dce2Smb2RequestTrackerPtr request = find_request(message_id, current_flow_key);
-            if (request)
-                close_file(request->get_file_id(), true);
-            do_not_delete_tree = false;
-        }
-        else if (SMB2_CMD_TYPE_REQUEST == command_type)
-            process_write_request(message_id, current_flow_key, smb_header, end);
-        break;
-    case SMB2_COM_IOCTL:
-        if (SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
-        {
-            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, smb_header, end);
-        }
-        break;
-    }
-    if (SMB2_CMD_TYPE_RESPONSE == command_type or SMB2_CMD_TYPE_ERROR_RESPONSE == command_type)
-        remove_request(message_id, current_flow_key);
-}
-
-Dce2Smb2TreeTracker::~Dce2Smb2TreeTracker(void)
-{
-    if (do_not_delete_tree == true)
-        return;
-
-    if (co_tracker != nullptr)
-    {
-        DCE2_CoCleanTracker(co_tracker);
-        snort_free((void*)co_tracker);
-        co_tracker = nullptr;
-    }
-
-    tree_tracker_mutex.lock();
-
-    for (auto it_file : opened_files)
-    {
-        it_file.second->get_parent().reset();
-        parent_session->decrease_size(sizeof(Dce2Smb2FileTracker));
-    }
-
-    tree_tracker_mutex.unlock();
-}
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_tree.h b/src/service_inspectors/dce_rpc/dce_smb2_tree.h
deleted file mode 100644 (file)
index 315254c..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb2_tree.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifndef DCE_SMB2_TREE_H
-#define DCE_SMB2_TREE_H
-
-// This provides tree trackers for SMBv2.
-// Tree trackers are used to identify and track an opened share
-
-#include "dce_co.h"
-#include "dce_smb2.h"
-#include "dce_smb2_file.h"
-#include "dce_smb2_request.h"
-
-using Dce2Smb2RequestTrackerPtr = std::shared_ptr<Dce2Smb2RequestTracker>;
-
-uint64_t Smb2Mid(const Smb2Hdr* hdr);
-
-class Dce2Smb2SessionTracker;
-
-class Dce2Smb2TreeTracker
-{
-public:
-    Dce2Smb2TreeTracker() = delete;
-    Dce2Smb2TreeTracker(const Dce2Smb2TreeTracker&) = delete;
-    Dce2Smb2TreeTracker& operator=(const Dce2Smb2TreeTracker&) = delete;
-
-    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);
-        if (share_type != SMB2_SHARE_TYPE_DISK)
-        {
-            co_tracker = (DCE2_CoTracker*)snort_calloc(sizeof(DCE2_CoTracker));
-            DCE2_CoInitTracker(co_tracker);
-        }
-        else
-        {
-            co_tracker = nullptr;
-        }
-    }
-
-    ~Dce2Smb2TreeTracker();
-
-    Dce2Smb2FileTrackerPtr open_file(const uint64_t, const uint32_t);
-    void close_file(uint64_t, bool);
-    void close_all_files();
-    Dce2Smb2FileTrackerPtr find_file(uint64_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; }
-    uint32_t get_tree_id() { return tree_id; }
-    uint8_t get_share_type() { return share_type; }
-    std::atomic<bool> do_not_delete_tree { false };
-    void set_parent(Dce2Smb2SessionTracker* session_tracker) { parent_session = session_tracker; }
-
-private:
-    void process_set_info_request(const Smb2Hdr*);
-    void process_close_request(const Smb2Hdr*, const uint32_t);
-    void process_create_response(const uint64_t, const uint32_t, const Smb2Hdr*);
-    void process_create_request(const uint64_t, const uint32_t, const Smb2Hdr*, const uint8_t*);
-    void process_read_response(const uint64_t, const uint32_t, const Smb2Hdr*, const uint8_t*);
-    void process_read_request(const uint64_t, const uint32_t, const Smb2Hdr*);
-    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 Smb2Hdr*, const uint8_t*);
-    bool store_request(const uint64_t message_id, const uint32_t current_flow_key,
-        Dce2Smb2RequestTrackerPtr request)
-    {
-        Smb2MessageKey message_key = { message_id, current_flow_key, 0 };
-        std::lock_guard<std::mutex> guard(tree_tracker_mutex);
-        return active_requests.insert(std::make_pair(message_key, request)).second;
-    }
-
-    uint32_t tree_id;
-    uint8_t share_type;
-    DCE2_CoTracker* co_tracker; // Connection-oriented DCE/RPC tracker
-    Dce2Smb2FileTrackerMap opened_files;
-    Dce2Smb2RequestTrackerMap active_requests;
-    Dce2Smb2SessionTracker* parent_session;
-    std::mutex tree_tracker_mutex;
-};
-
-using Dce2Smb2TreeTrackerPtr = std::shared_ptr<Dce2Smb2TreeTracker>;
-using Dce2Smb2TreeTrackerMap =
-        std::unordered_map<uint32_t, Dce2Smb2TreeTrackerPtr, std::hash<uint32_t> >;
-
-#endif
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_utils.cc b/src/service_inspectors/dce_rpc/dce_smb2_utils.cc
new file mode 100644 (file)
index 0000000..6751133
--- /dev/null
@@ -0,0 +1,99 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2023 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// SMB2 utils processing
+// dce_smb2_utils.cc author Bhargava Jandhyala <bjandhya@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dce_smb_module.h"
+#include "dce_smb_utils.h"
+#include "dce_smb2_utils.h"
+#include "detection/detection_util.h"
+#include "flow/flow_key.h"
+
+using namespace snort;
+
+size_t session_cache_size;
+THREAD_LOCAL SmbSessionCache* smb2_session_cache;
+
+Smb2SidHashKey get_key(uint64_t sid)
+{
+    Smb2SidHashKey key = { };
+    Flow* flow = DetectionEngine::get_current_packet()->flow;
+    if (flow)
+    {
+        memcpy(key.cip, flow->client_ip.get_ip6_ptr(), 4 * sizeof(uint32_t));
+        memcpy(key.sip, flow->server_ip.get_ip6_ptr(), 4 * sizeof(uint32_t));
+        key.sid = sid;
+        key.cgroup = flow->client_group;
+        key.sgroup = flow->server_group;
+        key.vlan_tag = flow->key->vlan_tag;
+        key.mplsLabel = flow->key->mplsLabel;
+        key.addressSpaceId = flow->key->addressSpaceId;
+        key.padding = 0;
+    }
+    return key;
+}
+
+DCE2_Smb2SessionTracker* DCE2_Smb2FindElseCreateSid(DCE2_Smb2SsnData* ssd, const
+    uint64_t sid, bool force_cache_update)
+{
+    // Local MAP search
+    auto stracker = DCE2_Smb2FindSidInSsd(ssd, sid);
+    if (!stracker)
+    {
+        // Global Hash Search
+        stracker = DCE2_SmbSessionCacheFindElseCreate(sid);
+        DCE2_Smb2InsertSidInSsd(ssd, sid, stracker);
+    }
+    else if (force_cache_update)
+    {
+        //find on cache to force update LRU.
+        auto key = get_key(sid);
+        smb2_session_cache->find(key);
+    }
+    return stracker.get();
+}
+
+DCE2_Smb2TreeTracker* DCE2_Smb2InsertTid(DCE2_Smb2SsnData* ssd, const uint32_t tid, uint8_t
+    share_type,
+    DCE2_Smb2SessionTracker* str)
+{
+    if (share_type == SMB2_SHARE_TYPE_DISK and
+        ssd->max_file_depth == -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1)
+    {
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            DetectionEngine::get_current_packet(),
+            "Not inserting TID (%u) because it's not IPC and not "
+            " inspecting normal file data.\n", tid);
+        return nullptr;
+    }
+
+    DCE2_Smb2TreeTracker* ttracker = str->findTtracker(tid);
+    if (!ttracker)
+    {
+        ttracker = new DCE2_Smb2TreeTracker(tid, share_type);
+        str->insertTtracker(tid, ttracker);
+    }
+
+    return ttracker;
+}
+
diff --git a/src/service_inspectors/dce_rpc/dce_smb2_utils.h b/src/service_inspectors/dce_rpc/dce_smb2_utils.h
new file mode 100644 (file)
index 0000000..1cda450
--- /dev/null
@@ -0,0 +1,153 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2023 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// dce_smb2_utils.h author Bhargava Jandhyala <bjandhya@cisco.com>
+// based on work by Todd Wease
+
+#ifndef DCE_SMB2_UTILS_H
+#define DCE_SMB2_UTILS_H
+
+#include "dce_smb.h"
+#include "dce_smb2.h"
+#include "file_api/file_flows.h"
+
+Smb2SidHashKey get_key(uint64_t sid);
+
+template<typename Key, typename Value, typename Hash>
+class LruCacheLocalSmbMultiChannel : public LruCacheLocal <Key, Value, Hash>
+{
+public:
+    using LruLocal = LruCacheLocal<Key, Value, Hash>;
+    using LruLocal::current_size;
+    using LruLocal::max_size;
+    using LruLocal::list;
+    using LruLocal::map;
+    using LruLocal::stats;
+    using LruMapIter = typename LruLocal::LruMapIter;
+
+    LruCacheLocalSmbMultiChannel(const size_t sz, struct LruCacheLocalStats& st) :   LruLocal(sz, st) { }
+
+    void update(int size)
+    {
+        if ( size < 0 )
+            assert(current_size >= (size_t)-size);
+        current_size += size;
+        if ( size > 0)
+        {
+            // Checking 1+ size prevents crash if max_size is too low to hold even a single entry
+            if ( current_size > max_size and list.size() > 1 )
+                LruLocal::prune();
+            if ( stats.cache_max < current_size )
+                stats.cache_max = current_size;
+        }
+    }
+
+    Value find(Key& key)
+    {
+        LruMapIter it = map.find(key);
+        if (it == map.end())
+            return nullptr;
+        //Move entry to front of LruList
+        list.splice(list.begin(), list, it->second);
+        return list.begin()->second;
+    }
+};
+
+typedef LruCacheLocalSmbMultiChannel<Smb2SidHashKey, std::shared_ptr<DCE2_Smb2SessionTracker>,
+    SmbKeyHash> SmbSessionCache;
+
+extern THREAD_LOCAL SmbSessionCache* smb2_session_cache;
+
+// SMB2 Session cache manipulation functions
+inline void DCE2_SmbSessionCacheInit(const size_t cache_size)
+{
+    smb2_session_cache = new SmbSessionCache(cache_size, dce2_smb_stats);
+}
+
+inline void DCE2_SmbSessionCacheUpdateSize(int size)
+{
+    smb2_session_cache->update(size);
+}
+
+inline std::shared_ptr<DCE2_Smb2SessionTracker> DCE2_SmbSessionCacheFindElseCreate(uint64_t sid)
+{
+    bool is_new = false;
+    auto& session_ptr =  smb2_session_cache->find_else_create(get_key(sid), &is_new);
+    if (is_new)
+    {
+        session_ptr.reset(new DCE2_Smb2SessionTracker(sid));
+    }
+    return session_ptr;
+}
+
+inline bool DCE2_SmbSessionCacheRemove(Smb2SidHashKey& key)
+{
+    return smb2_session_cache->remove(key);
+}
+
+// SMB2 functions for fetching sid, tid, request type and so on.
+inline uint64_t Smb2Sid(const Smb2Hdr* hdr)
+{
+    return snort::alignedNtohq(&(((const Smb2SyncHdr*)hdr)->session_id));
+}
+
+inline uint32_t Smb2Tid(const Smb2Hdr* hdr)
+{
+    return snort::alignedNtohl(&(((const Smb2SyncHdr*)hdr)->tree_id));
+}
+
+inline uint64_t Smb2Mid(const Smb2Hdr* hdr)
+{
+    return snort::alignedNtohq(&(((const Smb2SyncHdr*)hdr)->message_id));
+}
+
+inline bool Smb2Error(const Smb2Hdr* hdr)
+{
+    return (hdr->status != SMB_NT_STATUS__SUCCESS);
+}
+
+inline std::shared_ptr<DCE2_Smb2SessionTracker> DCE2_Smb2FindSidInSsd(DCE2_Smb2SsnData* ssd, const
+    uint64_t sid)
+{
+    return ssd->find_session_tracker(sid);
+}
+
+inline void DCE2_Smb2InsertSidInSsd(DCE2_Smb2SsnData* ssd, const uint64_t sid,
+    std::shared_ptr<DCE2_Smb2SessionTracker> stracker)
+{
+    // add ssd in session tracker's tcp trackers database
+    if (ssd->flow_key)
+    {
+        stracker->insertConnectionTracker(ssd->flow_key, ssd);
+    }
+    ssd->insert_session_tracker(sid, stracker);
+}
+
+inline void DCE2_Smb2RemoveSidInSsd(DCE2_Smb2SsnData* ssd, const uint64_t sid)
+{
+    ssd->remove_session_tracker(sid);
+}
+
+DCE2_Smb2TreeTracker* DCE2_Smb2InsertTid(DCE2_Smb2SsnData*, const uint32_t tid, uint8_t share_type,
+    DCE2_Smb2SessionTracker*);
+
+DCE2_Smb2SessionTracker* DCE2_Smb2FindElseCreateSid(DCE2_Smb2SsnData*, const uint64_t sid, bool
+    force_cache_update = true);
+
+#endif
+
index 2092a063df877cfb417935c987d7b5de20b7400c..01f9c39c2e16c8adc8cd1a8f85f22e35a9d57564 100644 (file)
@@ -1,6 +1,5 @@
 //--------------------------------------------------------------------------
 // Copyright (C) 2016-2023 Cisco and/or its affiliates. All rights reserved.
-//
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
 // by the Free Software Foundation.  You may not use, modify or distribute
@@ -567,7 +566,7 @@ DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         dce2_move(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            get_smb_file_name(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
             &ssd->cur_rtracker->file_name_size);
     }
 
@@ -625,7 +624,7 @@ DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         dce2_move(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            get_smb_file_name(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
             &ssd->cur_rtracker->file_name_size);
     }
 
@@ -856,7 +855,7 @@ DCE2_Ret DCE2_SmbCreateNew(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         dce2_move(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            get_smb_file_name(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
             &ssd->cur_rtracker->file_name_size);
     }
 
@@ -1069,7 +1068,7 @@ DCE2_Ret DCE2_SmbOpenAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ssd->cur_rtracker->file_name == nullptr)
         {
             ssd->cur_rtracker->file_name =
-                get_smb_file_name(nb_ptr, nb_len, unicode, &ssd->cur_rtracker->file_name_size);
+                DCE2_SmbGetFileName(nb_ptr, nb_len, unicode, &ssd->cur_rtracker->file_name_size);
         }
     }
 
@@ -1491,13 +1490,13 @@ DCE2_Ret DCE2_SmbSessionSetupAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
                 uint8_t r2 = 0;  // Release version second digit
 
                 // Get Major version
-                for (i = 0; (i < nb_len) && (*nb_ptr != '\0'); i += increment)
+                for (i = 0; (i < nb_len); i += increment)
                 {
                     if (isdigit((int)nb_ptr[i]))
                         break;
                 }
 
-                if ((i == nb_len) || (*nb_ptr == '\0'))
+                if (i == nb_len)
                 {
                     return DCE2_RET__SUCCESS;
                 }
@@ -1930,7 +1929,7 @@ DCE2_Ret DCE2_SmbNtCreateAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ssd->cur_rtracker->file_name == nullptr)
         {
             ssd->cur_rtracker->file_name =
-                get_smb_file_name(nb_ptr, file_name_length, unicode,
+                DCE2_SmbGetFileName(nb_ptr, file_name_length, unicode,
                 &ssd->cur_rtracker->file_name_size);
         }
 
@@ -2167,3 +2166,4 @@ DCE2_Ret DCE2_SmbWriteAndClose(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
 
     return DCE2_RET__SUCCESS;
 }
+
index 74a77ec221e1a6763e9aa8beaed84c9aeb39759b..429dd84f4a0bf44edbfd56371ab11f40ea81a568 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "dce_smb_utils.h"
 
+#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x08
+
 DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData*, const SmbNtHdr*,
     const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
 DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData*, const SmbNtHdr*,
diff --git a/src/service_inspectors/dce_rpc/dce_smb_common.cc b/src/service_inspectors/dce_rpc/dce_smb_common.cc
deleted file mode 100644 (file)
index 5b01567..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb_common.cc author Dipta Pandit <dipandit@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "dce_smb_common.h"
-
-#include "file_api/file_flows.h"
-#include "file_api/file_service.h"
-
-#include "dce_smb1.h"
-#include "dce_smb2.h"
-
-using namespace snort;
-
-THREAD_LOCAL dce2SmbStats dce2_smb_stats;
-THREAD_LOCAL ProfileStats dce2_smb_pstat_main;
-
-//Dce2SmbFlowData members
-
-unsigned Dce2SmbFlowData::inspector_id = 0;
-
-Dce2SmbFlowData::Dce2SmbFlowData(Dce2SmbSessionData* ssd_v) : FlowData(inspector_id)
-{
-    dce2_smb_stats.concurrent_sessions++;
-    if (dce2_smb_stats.max_concurrent_sessions < dce2_smb_stats.concurrent_sessions)
-        dce2_smb_stats.max_concurrent_sessions = dce2_smb_stats.concurrent_sessions;
-    ssd = ssd_v;
-}
-
-Dce2SmbSessionData* Dce2SmbFlowData::upgrade(const Packet* p)
-{
-    dce2SmbProtoConf* config =
-        (dce2SmbProtoConf*)ssd->get_dce2_session_data()->config;
-    delete ssd;
-    ssd = new Dce2Smb2SessionData(p, config);
-    return ssd;
-}
-
-void Dce2SmbFlowData::handle_retransmit(Packet* p)
-{
-    FilePosition position = get_file_position(p);
-    if (!(SNORT_FILE_FULL == position or SNORT_FILE_END == position))
-        return;
-    FileContext* context = get_smb_file_context(p);
-    FileVerdict verdict = context ? context->verdict : FILE_VERDICT_UNKNOWN;
-    ssd->handle_retransmit(position, verdict);
-}
-
-Dce2SmbFlowData::~Dce2SmbFlowData()
-{
-    if (ssd)
-        delete ssd;
-    assert(dce2_smb_stats.concurrent_sessions > 0);
-    dce2_smb_stats.concurrent_sessions--;
-}
-
-//Dce2SmbSessionData members
-
-Dce2SmbSessionData::Dce2SmbSessionData(const Packet* p,
-    const dce2SmbProtoConf* config)
-{
-    sd = { };
-    policy = { };
-    tcp_flow = p->flow;
-    DCE2_ResetRopts(&sd, p);
-    sd.trans = DCE2_TRANS_TYPE__SMB;
-    sd.server_policy = config->common.policy;
-    sd.client_policy = DCE2_POLICY__WINXP;
-    sd.config = (void*)config;
-    dialect_index = DCE2_SENTINEL;
-    max_file_depth = FileService::get_max_file_depth();
-    dce2_smb_stats.smb_sessions++;
-}
-
-//Helper functions
-
-static inline DCE2_SmbVersion get_smb_version(const Packet* p)
-{
-    // Only check reassembled SMB2 packet
-    if ( p->has_paf_payload() and (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE))
-    {
-        const SmbNtHdr* smb_hdr = (const SmbNtHdr*)(p->data + sizeof(NbssHdr));
-        uint32_t smb_version_id = SmbId(smb_hdr);
-
-        if (smb_version_id == DCE2_SMB_ID)
-            return DCE2_SMB_VERSION_1;
-        else if (smb_version_id == DCE2_SMB2_ID)
-            return DCE2_SMB_VERSION_2;
-    }
-
-    return DCE2_SMB_VERSION_NULL;
-}
-
-Dce2SmbFlowData* create_expected_smb_flow_data(const Packet* p)
-{
-    DCE2_SmbVersion smb_version = get_smb_version(p);
-    if (DCE2_SMB_VERSION_2 == smb_version)
-    {
-        return new Dce2SmbFlowData();
-    }
-    return nullptr;
-}
-
-Dce2SmbSessionData* create_smb_session_data(Dce2SmbFlowData* flow_data, const Packet* p,
-    dce2SmbProtoConf* config)
-{
-    DCE2_SmbVersion smb_version = get_smb_version(p);
-    if (DCE2_SMB_VERSION_2 != smb_version)
-        return nullptr;
-    Dce2SmbSessionData* ssd = (Dce2SmbSessionData*)new Dce2Smb2SessionData(p, config);
-    flow_data->update_smb_session_data(ssd);
-    return ssd;
-}
-
-Dce2SmbSessionData* create_new_smb_session(const Packet* p,
-    dce2SmbProtoConf* config)
-{
-    DCE2_SmbVersion smb_version = get_smb_version(p);
-
-    if (DCE2_SMB_VERSION_NULL == smb_version)
-        return nullptr;
-
-    Dce2SmbSessionData* ssd = (DCE2_SMB_VERSION_1 == smb_version) ?
-        (Dce2SmbSessionData*)new Dce2Smb1SessionData(p, config) :
-        (Dce2SmbSessionData*)new Dce2Smb2SessionData(p, config);
-
-    Dce2SmbFlowData* flow_data = new Dce2SmbFlowData(ssd);
-    p->flow->set_flow_data(flow_data);
-
-    return ssd;
-}
-
-DCE2_SsnData* get_dce2_session_data(snort::Flow* flow)
-{
-    Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(Dce2SmbFlowData::inspector_id);
-    return fd ? fd->get_smb_session_data() ? fd->get_smb_session_data()->get_dce2_session_data() :
-        nullptr : nullptr;
-}
-
-inline FileContext* get_smb_file_context(const Packet* p)
-{
-    FileFlows* file_flows = FileFlows::get_file_flows(p->flow);
-    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 )
-    {
-        dce2_smb_stats.v2_inv_file_ctx_err++;
-        return nullptr;
-    }
-
-    bool is_new_context = false;
-    std::lock_guard<std::mutex> guard(file_flows->file_flow_context_mutex);
-    return file_flows->get_file_context(file_id, to_create, is_new_context, multi_file_processing_id);
-}
-
-char* get_smb_file_name(const uint8_t* data, uint32_t data_len, bool unicode,
-    uint16_t* file_name_len)
-{
-    const uint8_t inc = unicode ? 2 : 1;
-    if (data_len < inc)
-        return nullptr;
-
-    const uint32_t max_len =  unicode ? data_len - 1 : data_len;
-    // Move forward.  Don't know if the end of data is actually
-    // the end of the string.
-    uint32_t i;
-    for (i = 0; i < max_len; i += inc)
-    {
-        uint16_t uchar = unicode ? extract_16bits(data + i) : data[i];
-        if (uchar == 0)
-            break;
-    }
-
-    char* fname = nullptr;
-    const uint32_t real_len = i;
-
-    if (unicode)
-    {
-        fname = (char*)snort_calloc(real_len + UTF_16_LE_BOM_LEN + 2);
-        memcpy(fname, UTF_16_LE_BOM, UTF_16_LE_BOM_LEN);//Prepend with BOM
-        memcpy(fname + UTF_16_LE_BOM_LEN, data, real_len);
-        *file_name_len = real_len + UTF_16_LE_BOM_LEN;
-    }
-    else
-    {
-        fname = (char*)snort_alloc(real_len + 1);
-        memcpy(fname, data, real_len);
-        fname[real_len] = 0;
-        *file_name_len = real_len;
-    }
-    return fname;
-}
-
-void set_smb_reassembled_data(uint8_t* nb_ptr, uint16_t co_len)
-{
-    snort::Flow* flow = DetectionEngine::get_current_packet()->flow;
-    if (flow)
-    {
-        Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(
-            Dce2SmbFlowData::inspector_id);
-        if (fd)
-        {
-            Dce2SmbSessionData* smb_ssn_data = fd->get_smb_session_data();
-            smb_ssn_data->set_reassembled_data(nb_ptr, co_len);
-        }
-    }
-}
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb_common.h b/src/service_inspectors/dce_rpc/dce_smb_common.h
deleted file mode 100644 (file)
index b03adf8..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb_common.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifndef DCE_SMB_COMMON_H
-#define DCE_SMB_COMMON_H
-
-// This provides SMB flow data and base class for SMB session data
-// Also provides common functions used by both versions
-
-#include "file_api/file_api.h"
-#include "protocols/packet.h"
-#include "profiler/profiler_defs.h"
-#include "trace/trace_api.h"
-
-#include "dce_common.h"
-#include "dce_smb_module.h"
-#include "smb_common.h"
-
-#define DCE2_SMB_NAME "dce_smb"
-#define DCE2_SMB_HELP "dce over smb inspection"
-
-#define SMB_DEBUG(module_name, module_id, log_level, p, ...) \
-    trace_logf(log_level, module_name , module_id, p, __VA_ARGS__)
-
-#define DCE2_SMB_ID   0xff534d42  /* \xffSMB */
-#define DCE2_SMB2_ID  0xfe534d42  /* \xfeSMB */
-#define DCE2_SMB_ID_SIZE 4
-
-#define SMB_DEFAULT_MAX_CREDIT        8192
-#define SMB_DEFAULT_MEMCAP            8388608
-#define SMB_DEFAULT_MAX_COMPOUND_REQ  3
-
-#define DCE2_SMB_RPKT_TYPE_MAX 4
-#define DCE2_SMB_RPKT_TYPE_START 1
-
-#define DCE2_SMB_BAD_NBSS_TYPE 2
-#define DCE2_SMB_BAD_TYPE 3
-#define DCE2_SMB_BAD_ID 4
-#define DCE2_SMB_BAD_WCT 5
-#define DCE2_SMB_BAD_BCC 6
-#define DCE2_SMB_BAD_FORM 7
-#define DCE2_SMB_BAD_OFF 8
-#define DCE2_SMB_TDCNT_ZE 9
-#define DCE2_SMB_NB_LT_SMBHDR 10
-#define DCE2_SMB_NB_LT_COM 11
-#define DCE2_SMB_NB_LT_BCC 12
-#define DCE2_SMB_NB_LT_DSIZE 13
-#define DCE2_SMB_TDCNT_LT_DSIZE 14
-#define DCE2_SMB_DSENT_GT_TDCNT 15
-#define DCE2_SMB_BCC_LT_DSIZE 16
-#define DCE2_SMB_INVALID_DSIZE 17
-#define DCE2_SMB_EXCESSIVE_TREE_CONNECTS 18
-#define DCE2_SMB_EXCESSIVE_READS 19
-#define DCE2_SMB_EXCESSIVE_CHAINING 20
-#define DCE2_SMB_MULT_CHAIN_SS 21
-#define DCE2_SMB_MULT_CHAIN_TC 22
-#define DCE2_SMB_CHAIN_SS_LOGOFF 23
-#define DCE2_SMB_CHAIN_TC_TDIS 24
-#define DCE2_SMB_CHAIN_OPEN_CLOSE 25
-#define DCE2_SMB_INVALID_SHARE 26
-
-#define DCE2_SMB_V1 44
-#define DCE2_SMB_V2 45
-#define DCE2_SMB_INVALID_BINDING 46
-#define DCE2_SMB2_EXCESSIVE_COMPOUNDING 47
-#define DCE2_SMB_DCNT_ZERO 48
-#define DCE2_SMB_DCNT_MISMATCH 49
-#define DCE2_SMB_MAX_REQS_EXCEEDED 50
-#define DCE2_SMB_REQS_SAME_MID 51
-#define DCE2_SMB_DEPR_DIALECT_NEGOTIATED 52
-#define DCE2_SMB_DEPR_COMMAND_USED 53
-#define DCE2_SMB_UNUSUAL_COMMAND_USED 54
-#define DCE2_SMB_INVALID_SETUP_COUNT 55
-#define DCE2_SMB_MULTIPLE_NEGOTIATIONS 56
-#define DCE2_SMB_EVASIVE_FILE_ATTRS 57
-#define DCE2_SMB_INVALID_FILE_OFFSET 58
-#define DCE2_SMB_BAD_NEXT_COMMAND_OFFSET 59
-
-struct dce2SmbStats
-{
-    PegCount events;
-
-    PegCount co_pdus;
-    PegCount co_bind;
-    PegCount co_bind_ack;
-    PegCount co_alter_ctx;
-    PegCount co_alter_ctx_resp;
-    PegCount co_bind_nack;
-    PegCount co_request;
-    PegCount co_response;
-    PegCount co_cancel;
-    PegCount co_orphaned;
-    PegCount co_fault;
-    PegCount co_auth3;
-    PegCount co_shutdown;
-    PegCount co_reject;
-    PegCount co_ms_pdu;
-    PegCount co_other_req;
-    PegCount co_other_resp;
-    PegCount co_req_fragments;
-    PegCount co_resp_fragments;
-    PegCount co_cli_max_frag_size;
-    PegCount co_cli_min_frag_size;
-    PegCount co_cli_seg_reassembled;
-    PegCount co_cli_frag_reassembled;
-    PegCount co_srv_max_frag_size;
-    PegCount co_srv_min_frag_size;
-    PegCount co_srv_seg_reassembled;
-    PegCount co_srv_frag_reassembled;
-
-    PegCount smb_sessions;
-    PegCount smb_pkts;
-    PegCount smb_ignored_bytes;
-    PegCount smb_cli_seg_reassembled;
-    PegCount smb_srv_seg_reassembled;
-    PegCount smb_max_outstanding_requests;
-    //  FIXIT-M more peg count foo
-    /*uint64_t smb_com_stats[2][SMB_MAX_NUM_COMS];
-    uint64_t smb_chained_stats[2][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
-    // The +1 is for codes beyond the range of the highest valid subcommand code
-    // Indicates a bogus subcommand
-    uint64_t smb_trans_subcom_stats[2][TRANS_SUBCOM_MAX+1];
-    uint64_t smb_trans2_subcom_stats[2][TRANS2_SUBCOM_MAX+1];
-    uint64_t smb_nt_transact_subcom_stats[2][NT_TRANSACT_SUBCOM_MAX+1];
-    */
-    PegCount smb_files_processed;
-    /* SMB2 stats */
-    PegCount v2_setup;
-    PegCount v2_setup_err_resp;
-    PegCount v2_setup_inv_str_sz;
-    PegCount v2_setup_resp_hdr_err;
-    PegCount v2_tree_cnct;
-    PegCount v2_tree_cnct_err_resp;
-    PegCount v2_tree_cnct_ignored;
-    PegCount v2_tree_cnct_inv_str_sz;
-    PegCount v2_tree_cnct_resp_hdr_err;
-    PegCount v2_crt;
-    PegCount v2_crt_err_resp;
-    PegCount v2_crt_inv_file_data;
-    PegCount v2_crt_inv_str_sz;
-    PegCount v2_crt_resp_hdr_err;
-    PegCount v2_crt_req_hdr_err;
-    PegCount v2_crt_rtrkr_misng;
-    PegCount v2_crt_req_ipc;
-    PegCount v2_crt_tree_trkr_misng;
-    PegCount v2_wrt;
-    PegCount v2_wrt_err_resp;
-    PegCount v2_wrt_inv_str_sz;
-    PegCount v2_wrt_req_hdr_err;
-    PegCount v2_wrt_resp_hdr_err;
-    PegCount v2_read;
-    PegCount v2_read_err_resp;
-    PegCount v2_read_inv_str_sz;
-    PegCount v2_read_rtrkr_misng;
-    PegCount v2_read_resp_hdr_err;
-    PegCount v2_read_req_hdr_err;
-    PegCount v2_setinfo;
-    PegCount v2_stinf_err_resp;
-    PegCount v2_stinf_inv_str_sz;
-    PegCount v2_stinf_req_ftrkr_misng;
-    PegCount v2_stinf_req_hdr_err;
-    PegCount v2_cls;
-    PegCount v2_cls_err_resp;
-    PegCount v2_cls_inv_str_sz;
-    PegCount v2_cls_req_ftrkr_misng;
-    PegCount v2_cls_req_hdr_err;
-    PegCount v2_tree_discn;
-    PegCount v2_tree_discn_ignored;
-    PegCount v2_tree_discn_inv_str_sz;
-    PegCount v2_tree_discn_req_hdr_err;
-    PegCount v2_logoff;
-    PegCount v2_logoff_inv_str_sz;
-    PegCount v2_hdr_err;
-    PegCount v2_bad_next_cmd_offset;
-    PegCount v2_inv_file_ctx_err;
-    PegCount v2_msgs_uninspected;
-    PegCount v2_cmpnd_req_lt_crossed;
-    PegCount v2_tree_ignored;
-    PegCount v2_session_ignored;
-    PegCount v2_ioctl;
-    PegCount v2_ioctl_err_resp;
-    PegCount v2_ioctl_inv_str_sz;
-    PegCount v2_ioctl_req_hdr_err;
-    PegCount v2_ioctl_resp_hdr_err;
-    PegCount concurrent_sessions;
-    PegCount max_concurrent_sessions;
-    PegCount total_smb1_sessions;
-    PegCount total_smb2_sessions;
-    PegCount total_encrypted_sessions;
-    PegCount total_mc_sessions;
-    PegCount ignore_dup_sessions;
-};
-
-enum DCE2_SmbVersion
-{
-    DCE2_SMB_VERSION_NULL,
-    DCE2_SMB_VERSION_1,
-    DCE2_SMB_VERSION_2
-};
-
-enum Dce2SmbPduState
-{
-    DCE2_SMB_PDU_STATE__COMMAND,
-    DCE2_SMB_PDU_STATE__RAW_DATA
-};
-
-extern THREAD_LOCAL dce2SmbStats dce2_smb_stats;
-extern THREAD_LOCAL snort::ProfileStats dce2_smb_pstat_main;
-extern bool smb_module_is_up;
-extern SnortProtocolId snort_protocol_id_smb;
-
-class Dce2SmbSessionData
-{
-public:
-    Dce2SmbSessionData() = delete;
-    Dce2SmbSessionData(const snort::Packet*, const dce2SmbProtoConf*);
-    virtual ~Dce2SmbSessionData() { }
-
-    virtual void process() = 0;
-    virtual void handle_retransmit(FilePosition, FileVerdict) = 0;
-    virtual void set_reassembled_data(uint8_t*, uint16_t) = 0;
-
-    DCE2_SsnData* get_dce2_session_data()
-    { return &sd; }
-
-    snort::Flow* get_tcp_flow()
-    { return tcp_flow; }
-
-    int64_t get_max_file_depth()
-    { return max_file_depth; }
-
-    uint16_t get_max_outstanding_requests()
-    {
-        return sd.config ? ((dce2SmbProtoConf*)sd.config)->smb_max_credit :
-               SMB_DEFAULT_MAX_CREDIT;
-    }
-
-    int64_t get_smb_file_depth()
-    {
-        return ((dce2SmbProtoConf*)sd.config)->smb_file_depth;
-    }
-
-    uint16_t get_smb_max_compound()
-    {
-        return sd.config ? ((dce2SmbProtoConf*)sd.config)->smb_max_compound :
-               SMB_DEFAULT_MAX_COMPOUND_REQ;
-    }
-
-protected:
-    DCE2_SsnData sd;
-    DCE2_Policy policy;
-    int64_t max_file_depth;
-    int dialect_index;
-    snort::Flow* tcp_flow;
-};
-
-class Dce2SmbFlowData : public snort::FlowData
-{
-public:
-    Dce2SmbFlowData(Dce2SmbSessionData*);
-    Dce2SmbFlowData() : snort::FlowData(inspector_id)
-    {
-        dce2_smb_stats.concurrent_sessions++;
-        if (dce2_smb_stats.max_concurrent_sessions < dce2_smb_stats.concurrent_sessions)
-            dce2_smb_stats.max_concurrent_sessions = dce2_smb_stats.concurrent_sessions;
-        ssd = nullptr;
-    }
-
-    ~Dce2SmbFlowData() override;
-
-    static void init()
-    { inspector_id = snort::FlowData::create_flow_data_id(); }
-
-    Dce2SmbSessionData* get_smb_session_data()
-    { return ssd; }
-
-    Dce2SmbSessionData* upgrade(const snort::Packet*);
-    void update_smb_session_data(Dce2SmbSessionData* ssd_v)
-    {
-        if (ssd) delete ssd;
-        ssd = ssd_v;
-    }
-    void handle_retransmit(snort::Packet*) override;
-
-public:
-    static unsigned inspector_id;
-
-private:
-    Dce2SmbSessionData* ssd;
-};
-
-Dce2SmbFlowData* create_expected_smb_flow_data(const snort::Packet*);
-Dce2SmbSessionData* create_new_smb_session(const snort::Packet*, dce2SmbProtoConf*);
-Dce2SmbSessionData* create_smb_session_data(Dce2SmbFlowData*, const snort::Packet*,
-    dce2SmbProtoConf*);
-DCE2_SsnData* get_dce2_session_data(snort::Flow*);
-snort::FileContext* get_smb_file_context(const snort::Packet*);
-snort::FileContext* get_smb_file_context(snort::Flow*, uint64_t, uint64_t, bool);
-char* get_smb_file_name(const uint8_t*, uint32_t, bool, uint16_t*);
-void set_smb_reassembled_data(uint8_t*, uint16_t);
-
-#endif
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb_inspector.cc b/src/service_inspectors/dce_rpc/dce_smb_inspector.cc
deleted file mode 100644 (file)
index 69474cf..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb_inspector.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "dce_smb_inspector.h"
-
-#include "dce_smb_common.h"
-#include "dce_smb_module.h"
-#include "dce_smb_utils.h"
-#include "dce_smb2_session_cache.h"
-#include "main/thread_config.h"
-
-#define DCE_SMB_PROTOCOL_ID "netbios-ssn"
-
-using namespace snort;
-
-bool smb_module_is_up = false;
-SnortProtocolId snort_protocol_id_smb = UNKNOWN_PROTOCOL_ID;
-
-Dce2Smb::Dce2Smb(const dce2SmbProtoConf& pc) :
-    config(pc) { }
-
-Dce2Smb::~Dce2Smb()
-{
-    if (config.smb_invalid_shares)
-    {
-        DCE2_ListDestroy(config.smb_invalid_shares);
-    }
-}
-
-bool Dce2Smb::configure(SnortConfig* sc)
-{
-    snort_protocol_id_smb = sc->proto_ref->add(DCE_SMB_PROTOCOL_ID);
-    return true;
-}
-
-void Dce2Smb::show(const SnortConfig*) const
-{
-    print_dce2_smb_conf(config);
-}
-
-void Dce2Smb::eval(Packet* p)
-{
-    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
-        p, "smb packet detected with dsize as %u\n", p->dsize);
-
-    Profile profile(dce2_smb_pstat_main);
-
-    assert(p->has_tcp_data() || p->has_udp_quic_data());
-    assert(p->flow);
-
-    reset_using_rpkt();
-
-    Dce2SmbFlowData* smb_flowdata =
-        (Dce2SmbFlowData*)p->flow->get_flow_data(Dce2SmbFlowData::inspector_id);
-
-    Dce2SmbSessionData* smb_session_data;
-    if (smb_flowdata)
-    {
-        smb_session_data = smb_flowdata->get_smb_session_data();
-        // if flow data present but session data is not, it is an expected session
-        // try to update the session data, will only do for SMBv2. Ideally it should
-        // be done in handle_expected, but we dont have access to the config there.
-        if (!smb_session_data)
-            smb_session_data = create_smb_session_data(smb_flowdata, p, &config);
-    }
-    else
-        smb_session_data = create_new_smb_session(p, &config);
-
-    if (smb_session_data)
-    {
-        dce2_detected = 0;
-        p->packet_flags |= PKT_ALLOW_MULTIPLE_DETECT;
-        p->endianness = new DceEndianness();
-
-        smb_session_data->process();
-        //smb_session_data may not be valid anymore in case of upgrade
-        //but flow will always have updated session
-        if (!dce2_detected)
-            DCE2_Detect(get_dce2_session_data(p->flow));
-        delete(p->endianness);
-        p->endianness = nullptr;
-    }
-    else
-    {
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
-               p, "non-smb packet detected with dsize as %u\n", p->dsize);
-    }
-}
-
-void Dce2Smb::clear(Packet* p)
-{
-    DCE2_SsnData* sd = get_dce2_session_data(p->flow);
-    if (sd)
-        DCE2_ResetRopts(sd, p);
-}
-
-//-------------------------------------------------------------------------
-// api stuff
-//-------------------------------------------------------------------------
-
-static Module* mod_ctor()
-{
-    return new Dce2SmbModule;
-}
-
-static void mod_dtor(Module* m)
-{
-    delete m;
-}
-
-static void dce2_smb_init()
-{
-    Dce2SmbFlowData::init();
-    DCE2_SmbInitGlobals();
-    DCE2_SmbInitDeletePdu();
-    DceContextData::init(DCE2_TRANS_TYPE__SMB);
-}
-
-static Inspector* dce2_smb_ctor(Module* m)
-{
-    Dce2SmbModule* mod = (Dce2SmbModule*)m;
-    dce2SmbProtoConf config;
-    mod->get_data(config);
-    size_t max_smb_mem = DCE2_ScSmbMemcap(&config);
-    uint16_t num_threads = ThreadConfig::get_instance_max();
-    smb_module_is_up = true;
-    smb2_session_cache.reload_prune(max_smb_mem*num_threads);
-    return new Dce2Smb(config);
-}
-
-static void dce2_smb_dtor(Inspector* p)
-{
-    smb_module_is_up = false;
-    delete p;
-}
-
-static const char* dce2_bufs[] =
-{
-    "dce_iface",
-    "dce_stub_data",
-    "file_data",
-    nullptr
-};
-
-const InspectApi dce2_smb_api =
-{
-    {
-        PT_INSPECTOR,
-        sizeof(InspectApi),
-        INSAPI_VERSION,
-        0,
-        API_RESERVED,
-        API_OPTIONS,
-        DCE2_SMB_NAME,
-        DCE2_SMB_HELP,
-        mod_ctor,
-        mod_dtor
-    },
-    IT_SERVICE,
-    PROTO_BIT__PDU,
-    dce2_bufs,
-    DCE_SMB_PROTOCOL_ID,
-    dce2_smb_init,
-    nullptr,
-    nullptr, // tinit
-    nullptr, // tterm
-    dce2_smb_ctor,
-    dce2_smb_dtor,
-    nullptr, // ssn
-    nullptr  // reset
-};
-
diff --git a/src/service_inspectors/dce_rpc/dce_smb_inspector.h b/src/service_inspectors/dce_rpc/dce_smb_inspector.h
deleted file mode 100644 (file)
index df9d831..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2023 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// dce_smb_inspector.h author Dipta Pandit <dipandit@cisco.com>
-
-#ifndef DCE_SMB_INSPECTOR_H
-#define DCE_SMB_INSPECTOR_H
-
-#include "managers/inspector_manager.h"
-
-#include "dce_smb_module.h"
-#include "dce_smb_paf.h"
-
-class Dce2Smb : public snort::Inspector
-{
-public:
-    Dce2Smb(const dce2SmbProtoConf&);
-    ~Dce2Smb() override;
-
-    bool configure(snort::SnortConfig*) override;
-    void show(const snort::SnortConfig*) const override;
-    void eval(snort::Packet*) override;
-    void clear(snort::Packet*) override;
-
-    snort::StreamSplitter* get_splitter(bool c2s) override
-    { return new Dce2SmbSplitter(c2s); }
-
-    bool can_carve_files() const override
-    { return true; }
-
-private:
-    dce2SmbProtoConf config;
-};
-
-#endif
-
index 2183f6af6200316808e464b50169e94be12b4965..d21dacf29d81484d83cd503a4fd27a6cdfdaf569 100644 (file)
@@ -29,7 +29,7 @@
 #include "trace/trace.h"
 #include "utils/util.h"
 
-#include "dce_smb_common.h"
+#include "dce_smb.h"
 
 using namespace snort;
 using namespace std;
@@ -38,13 +38,14 @@ THREAD_LOCAL const Trace* dce_smb_trace = nullptr;
 
 static const PegInfo dce2_smb_pegs[] =
 {
+    LRU_CACHE_LOCAL_PEGS("smbv2"),
     { CountType::SUM, "events", "total events" },
     { CountType::SUM, "pdus", "total connection-oriented PDUs" },
     { CountType::SUM, "binds", "total connection-oriented binds" },
     { CountType::SUM, "bind_acks", "total connection-oriented binds acks" },
     { CountType::SUM, "alter_contexts", "total connection-oriented alter contexts" },
     { CountType::SUM, "alter_context_responses",
-        "total connection-oriented alter context responses" },
+      "total connection-oriented alter context responses" },
     { CountType::SUM, "bind_naks", "total connection-oriented bind naks" },
     { CountType::SUM, "requests", "total connection-oriented requests" },
     { CountType::SUM, "responses", "total connection-oriented responses" },
@@ -55,27 +56,27 @@ static const PegInfo dce2_smb_pegs[] =
     { CountType::SUM, "shutdowns", "total connection-oriented shutdowns" },
     { CountType::SUM, "rejects", "total connection-oriented rejects" },
     { CountType::SUM, "ms_rpc_http_pdus",
-        "total connection-oriented MS requests to send RPC over HTTP" },
+      "total connection-oriented MS requests to send RPC over HTTP" },
     { CountType::SUM, "other_requests", "total connection-oriented other requests" },
     { CountType::SUM, "other_responses", "total connection-oriented other responses" },
     { CountType::SUM, "request_fragments", "total connection-oriented request fragments" },
     { CountType::SUM, "response_fragments", "total connection-oriented response fragments" },
     { CountType::SUM, "client_max_fragment_size",
-        "connection-oriented client maximum fragment size" },
+      "connection-oriented client maximum fragment size" },
     { CountType::SUM, "client_min_fragment_size",
-        "connection-oriented client minimum fragment size" },
+      "connection-oriented client minimum fragment size" },
     { CountType::SUM, "client_segs_reassembled",
-        "total connection-oriented client segments reassembled" },
+      "total connection-oriented client segments reassembled" },
     { CountType::SUM, "client_frags_reassembled",
-        "total connection-oriented client fragments reassembled" },
+      "total connection-oriented client fragments reassembled" },
     { CountType::SUM, "server_max_fragment_size",
-        "connection-oriented server maximum fragment size" },
+      "connection-oriented server maximum fragment size" },
     { CountType::SUM, "server_min_fragment_size",
-        "connection-oriented server minimum fragment size" },
+      "connection-oriented server minimum fragment size" },
     { CountType::SUM, "server_segs_reassembled",
-        "total connection-oriented server segments reassembled" },
+      "total connection-oriented server segments reassembled" },
     { CountType::SUM, "server_frags_reassembled",
-        "total connection-oriented server fragments reassembled" },
+      "total connection-oriented server fragments reassembled" },
     { CountType::SUM, "sessions", "total smb sessions" },
     { CountType::SUM, "packets", "total smb packets" },
     { CountType::SUM, "ignored_bytes", "total ignored bytes" },
@@ -84,117 +85,115 @@ static const PegInfo dce2_smb_pegs[] =
     { CountType::MAX, "max_outstanding_requests", "maximum outstanding requests" },
     { CountType::SUM, "files_processed", "total smb files processed" },
     { CountType::SUM, "v2_setup", "total number of SMBv2 setup packets seen" },
-    { CountType::SUM, "v2_setup_err_resp",
-        "total number of SMBv2 setup error response packets seen" },
+    { CountType::SUM, "v2_setup_err_resp", "total number of SMBv2 setup error response packets seen" },
     { CountType::SUM, "v2_setup_inv_str_sz",
-        "total number of SMBv2 setup packets seen with invalid structure size" },
+      "total number of SMBv2 setup packets seen with invalid structure size" },
     { CountType::SUM, "v2_setup_resp_hdr_err",
-        "total number of SMBv2 setup response packets ignored due to corrupted header" },
+      "total number of SMBv2 setup response packets ignored due to corrupted header" },
     { CountType::SUM, "v2_tree_cnct", "total number of SMBv2 tree connect packets seen" },
     { CountType::SUM, "v2_tree_cnct_err_resp",
-        "total number of SMBv2 tree connect error response packets seen" },
+      "total number of SMBv2 tree connect error response packets seen" },
     { CountType::SUM, "v2_tree_cnct_ignored",
-        "total number of SMBv2 setup response packets ignored due to failure in creating tree tracker" },
+      "total number of SMBv2 setup response packets ignored due to failure in creating tree tracker" },
     { CountType::SUM, "v2_tree_cnct_inv_str_sz",
-        "total number of SMBv2 tree connect packets seen with invalid structure size" },
+      "total number of SMBv2 tree connect packets seen with invalid structure size" },
     { CountType::SUM, "v2_tree_cnct_resp_hdr_err",
-        "total number of SMBv2 tree connect response packets ignored due to corrupted header" },
+      "total number of SMBv2 tree connect response packets ignored due to corrupted header" },
     { CountType::SUM, "v2_crt", "total number of SMBv2 create packets seen" },
-    { CountType::SUM, "v2_crt_err_resp",
-        "total number of SMBv2 create error response packets seen" },
+    { CountType::SUM, "v2_crt_err_resp", "total number of SMBv2 create error response packets seen" },
     { CountType::SUM, "v2_crt_inv_file_data",
-        "total number of SMBv2 create request packets ignored due to error in getting file name" },
+      "total number of SMBv2 create request packets ignored due to error in getting file name" },
     { CountType::SUM, "v2_crt_inv_str_sz",
-        "total number of SMBv2 create packets seen with invalid structure size" },
+      "total number of SMBv2 create packets seen with invalid structure size" },
     { CountType::SUM, "v2_crt_resp_hdr_err",
-         "total number of SMBv2 create response packets ignored due to corrupted header" },
+      "total number of SMBv2 create response packets ignored due to corrupted header" },
     { CountType::SUM, "v2_crt_req_hdr_err",
-         "total number of SMBv2 create request packets ignored due to corrupted header" },
+      "total number of SMBv2 create request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_crt_rtrkr_misng",
-        "total number of SMBv2 create response packets ignored due to missing create request tracker" },
+      "total number of SMBv2 create response packets ignored due to missing create request tracker" },
     { CountType::SUM, "v2_crt_req_ipc",
-        "total number of SMBv2 create request packets ignored as share type is IPC" },
+      "total number of SMBv2 create request packets ignored as share type is IPC" },
     { CountType::SUM, "v2_crt_tree_trkr_misng",
-        "total number of SMBv2 create response packets ignored due to missing tree tracker" },
+      "total number of SMBv2 create response packets ignored due to missing tree tracker" },
     { CountType::SUM, "v2_wrt", "total number of SMBv2 write packets seen" },
-    { CountType::SUM, "v2_wrt_err_resp",
-        "total number of SMBv2 write error response packets seen" },
+    { CountType::SUM, "v2_wrt_err_resp", "total number of SMBv2 write error response packets seen" },
+    { CountType::SUM, "v2_wrt_ignored",
+      "total number of SMBv2 write packets ignored due to missing trackers or invalid share type" },
     { CountType::SUM, "v2_wrt_inv_str_sz",
-        "total number of SMBv2 write packets seen with invalid structure size" },
+      "total number of SMBv2 write packets seen with invalid structure size" },
     { CountType::SUM, "v2_wrt_req_hdr_err",
-        "total number of SMBv2 write request packets ignored due to corrupted header" },
-    { CountType::SUM, "v2_wrt_resp_hdr_err",
-        "total number of SMBv2 write response packets ignored due to corrupted header" },
+      "total number of SMBv2 write request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_read", "total number of SMBv2 read packets seen" },
-    { CountType::SUM, "v2_read_err_resp",
-        "total number of SMBv2 read error response packets seen" },
+    { CountType::SUM, "v2_read_err_resp", "total number of SMBv2 read error response packets seen" },
+    { CountType::SUM, "v2_read_ignored",
+      "total number of SMBv2 write packets ignored due to missing trackers or invalid share type" },
     { CountType::SUM, "v2_read_inv_str_sz",
-        "total number of SMBv2 read packets seen with invalid structure size" },
+      "total number of SMBv2 read packets seen with invalid structure size" },
     { CountType::SUM, "v2_read_rtrkr_misng",
-        "total number of SMBv2 read response packets ignored due to missing read request tracker" },
+      "total number of SMBv2 read response packets ignored due to missing read request tracker" },
     { CountType::SUM, "v2_read_resp_hdr_err",
-        "total number of SMBv2 read response packets ignored due to corrupted header" },
+      "total number of SMBv2 read response packets ignored due to corrupted header" },
     { CountType::SUM, "v2_read_req_hdr_err",
-        "total number of SMBv2 read request packets ignored due to corrupted header" },
+      "total number of SMBv2 read request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_setinfo", "total number of SMBv2 set info packets seen" },
-    { CountType::SUM, "v2_stinf_err_resp",
-        "total number of SMBv2 set info error response packets seen" },
+    { CountType::SUM, "v2_stinf_err_resp", "total number of SMBv2 set info error response packets seen" },
+    { CountType::SUM, "v2_stinf_ignored",
+      "total number of SMBv2 set info packets ignored due to missing trackers or invalid share type" },
     { CountType::SUM, "v2_stinf_inv_str_sz",
-        "total number of SMBv2 set info packets seen with invalid structure size" },
+      "total number of SMBv2 set info packets seen with invalid structure size" },
     { CountType::SUM, "v2_stinf_req_ftrkr_misng",
-        "total number of SMBv2 set info request packets ignored due to missing file tracker" },
+      "total number of SMBv2 set info request packets ignored due to missing file tracker" },
     { CountType::SUM, "v2_stinf_req_hdr_err",
-        "total number of SMBv2 set info request packets ignored due to corrupted header" },
+      "total number of SMBv2 set info request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_cls", "total number of SMBv2 close packets seen" },
-    { CountType::SUM, "v2_cls_err_resp",
-        "total number of SMBv2 close error response packets seen" },
+    { CountType::SUM, "v2_cls_err_resp", "total number of SMBv2 close error response packets seen" },
+    { CountType::SUM, "v2_cls_ignored",
+      "total number of SMBv2 close packets ignored due to missing trackers or invalid share type" },
     { CountType::SUM, "v2_cls_inv_str_sz",
-        "total number of SMBv2 close packets seen with invalid structure size" },
+      "total number of SMBv2 close packets seen with invalid structure size" },
     { CountType::SUM, "v2_cls_req_ftrkr_misng",
-        "total number of SMBv2 close request packets ignored due to missing file tracker" },
+      "total number of SMBv2 close request packets ignored due to missing file tracker" },
     { CountType::SUM, "v2_cls_req_hdr_err",
-        "total number of SMBv2 close request packets ignored due to corrupted header" },
+      "total number of SMBv2 close request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_tree_discn",
-        "total number of SMBv2 tree disconnect packets seen" },
+      "total number of SMBv2 tree disconnect packets seen" },
     { CountType::SUM, "v2_tree_discn_ignored",
-        "total number of SMBv2 tree disconnect packets ignored due to missing trackers or invalid share type" },
+      "total number of SMBv2 tree disconnect packets ignored due to missing trackers or invalid share type" },
     { CountType::SUM, "v2_tree_discn_inv_str_sz",
-        "total number of SMBv2 tree disconnect packets seen with invalid structure size" },
+      "total number of SMBv2 tree disconnect packets seen with invalid structure size" },
     { CountType::SUM, "v2_tree_discn_req_hdr_err",
-        "total number of SMBv2 tree disconnect request packets ignored due to corrupted header" },
+      "total number of SMBv2 tree disconnect request packets ignored due to corrupted header" },
     { CountType::SUM, "v2_logoff", "total number of SMBv2 logoff" },
     { CountType::SUM, "v2_logoff_inv_str_sz",
-        "total number of SMBv2 logoff packets seen with invalid structure size" },
+      "total number of SMBv2 logoff packets seen with invalid structure size" },
     { CountType::SUM, "v2_hdr_err", "total number of SMBv2 packets seen with corrupted hdr" },
     { CountType::SUM, "v2_bad_next_cmd_offset",
-        "total number of SMBv2 packets seen with invalid next command offset" },
+      "total number of SMBv2 packets seen with invalid next command offset" },
+    { CountType::SUM, "v2_extra_file_data_err",
+      "total number of SMBv2 packets seen with where file data beyond file size is observed" },
     { CountType::SUM, "v2_inv_file_ctx_err",
-        "total number of times null file context are seen resulting in not being able to set file size" },
+      "total number of times null file context are seen resulting in not being able to set file size" },
     { CountType::SUM, "v2_msgs_uninspected",
-        "total number of SMBv2 packets seen where command is not being inspected" },
+      "total number of SMBv2 packets seen where command is not being inspected" },
     { CountType::SUM, "v2_cmpnd_req_lt_crossed",
-        "total number of SMBv2 packets seen where compound requests exceed the smb_max_compound limit" },
-    { CountType::SUM, "v2_tree_ignored",
-        "total number of packets ignored due to missing tree tracker" },
-    { CountType::SUM, "v2_session_ignored",
-        "total number of packets ignored due to missing session tracker" },
-    { CountType::SUM, "v2_ioctl",
-        "total number of ioctl calls" },
-    { CountType::SUM, "v2_ioctl_err_resp",
-        "total number of ioctl errors responses" },
-    { CountType::SUM, "v2_ioctl_inv_str_sz",
-        "total number of ioctl invalid structure size" },
-    { CountType::SUM, "v2_ioctl_req_hdr_err",
-        "total number of ioctl request header errors" },
-    { CountType::SUM, "v2_ioctl_resp_hdr_err",
-        "total number of ioctl response header errors" },
+      "total number of SMBv2 packets seen where compound requests exceed the smb_max_compound limit" },
     { CountType::NOW, "concurrent_sessions", "total concurrent sessions" },
     { CountType::MAX, "max_concurrent_sessions", "maximum concurrent sessions" },
     { CountType::SUM, "total_smb1_sessions", "total smb1 sessions" },
     { 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::SUM, "v2_total_session_trackers", "total number of session trackers" },
+    { CountType::SUM, "v2_total_tree_trackers", "total number of tree trackers" },
+    { CountType::SUM, "v2_total_file_trackers", "total number of file trackers" },
+    { CountType::SUM, "v2_updated_file_flows", "total number of updated file flows due to parent flow cleanup" },
+    { CountType::SUM, "v2_ignored_file_processing", "total number of file processing ignored" },
+    { CountType::SUM, "v2_mc_file_transfers", "total multichannel files transferred" },
+    { CountType::SUM, "v2_ioctl", "total number of ioctl calls" },
+    { CountType::SUM, "v2_ioctl_err_resp", "total number of ioctl errors responses" },
+    { CountType::SUM, "v2_ioctl_inv_str_sz", "total number of ioctl invalid structure size" },
+    { CountType::SUM, "v2_ioctl_ignored", "total number of SMBv2 IOCTL packets ignored due to missing trackers or invalid share type" },
+    { CountType::SUM, "total_sessions", "total smb sessions" },/* not used */
     { CountType::END, nullptr, nullptr }
 };
 
@@ -248,7 +247,7 @@ static const Parameter s_params[] =
       "Maximum number of outstanding request" },
 
     { "memcap", Parameter::PT_INT, "512:maxSZ", "8388608",
-      "Memory utilization limit on smb" },
+      "Memory utilization limit on SMBv2 cache" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -322,7 +321,7 @@ static std::string get_shares(DCE2_List* shares)
     return cmds;
 }
 
-Dce2SmbModule::Dce2SmbModule() : Module(DCE2_SMB_NAME, DCE2_SMB_HELP, s_params)
+Dce2SmbModule::Dce2SmbModule() :   Module(DCE2_SMB_NAME, DCE2_SMB_HELP, s_params)
 {
     memset(&config, 0, sizeof(config));
 }
@@ -534,7 +533,7 @@ bool Dce2SmbModule::set(const char*, Value& v, SnortConfig*)
 
 void Dce2SmbModule::get_data(dce2SmbProtoConf& dce2_smb_config)
 {
-    dce2_smb_config = config; // includes pointer copy so set to null
+    dce2_smb_config = config; // includes pointer copy so set to NULL
     config.smb_invalid_shares = nullptr;
 }
 
index be10a0c3f089e3700a0dc9eb0552a279c39bd509..905d9674db82bfef1e63e3b6b5cdb0f9f3611ecb 100644 (file)
@@ -21,9 +21,8 @@
 #ifndef DCE_SMB_MODULE_H
 #define DCE_SMB_MODULE_H
 
-#include "framework/module.h"
-
 #include "dce_common.h"
+#include "framework/module.h"
 #include "dce_list.h"
 
 namespace snort
@@ -37,59 +36,6 @@ extern THREAD_LOCAL const snort::Trace* dce_smb_trace;
 #define DCE2_VALID_SMB_VERSION_FLAG_V1 1
 #define DCE2_VALID_SMB_VERSION_FLAG_V2 2
 
-#define DCE2_SMB_BAD_NBSS_TYPE_STR "SMB - bad NetBIOS session service session type"
-#define DCE2_SMB_BAD_TYPE_STR  "SMB - bad SMB message type"
-#define DCE2_SMB_BAD_ID_STR "SMB - bad SMB Id (not \\xffSMB for SMB1 or not \\xfeSMB for SMB2)"
-#define DCE2_SMB_BAD_WCT_STR "SMB - bad word count or structure size"
-#define DCE2_SMB_BAD_BCC_STR  "SMB - bad byte count"
-#define DCE2_SMB_BAD_FORM_STR  "SMB - bad format type"
-#define DCE2_SMB_BAD_OFF_STR  "SMB - bad offset"
-#define DCE2_SMB_TDCNT_ZE_STR  "SMB - zero total data count"
-#define DCE2_SMB_NB_LT_SMBHDR_STR "SMB - NetBIOS data length less than SMB header length"
-#define DCE2_SMB_NB_LT_COM_STR   "SMB - remaining NetBIOS data length less than command length"
-#define DCE2_SMB_NB_LT_BCC_STR  "SMB - remaining NetBIOS data length less than command byte count"
-#define DCE2_SMB_NB_LT_DSIZE_STR \
-    "SMB - remaining NetBIOS data length less than command data size"
-#define DCE2_SMB_TDCNT_LT_DSIZE_STR \
-    "SMB - remaining total data count less than this command data size"
-#define DCE2_SMB_DSENT_GT_TDCNT_STR \
-    "SMB - total data sent (STDu64) greater than command total data expected"
-#define DCE2_SMB_BCC_LT_DSIZE_STR   "SMB - byte count less than command data size (STDu64)"
-#define DCE2_SMB_INVALID_DSIZE_STR  "SMB - invalid command data size for byte count"
-#define DCE2_SMB_EXCESSIVE_TREE_CONNECTS_STR \
-    "SMB - excessive tree connect requests with pending tree connect responses"
-#define DCE2_SMB_EXCESSIVE_READS_STR  "SMB - excessive read requests with pending read responses"
-#define DCE2_SMB_EXCESSIVE_CHAINING_STR  "SMB - excessive command chaining"
-#define DCE2_SMB_MULT_CHAIN_SS_STR   "SMB - Multiple chained login requests"
-#define DCE2_SMB_MULT_CHAIN_TC_STR   "SMB - Multiple chained tree connect requests"
-#define DCE2_SMB_CHAIN_SS_LOGOFF_STR   "SMB - chained/compounded login followed by logoff"
-#define DCE2_SMB_CHAIN_TC_TDIS_STR \
-    "SMB - chained/compounded tree connect followed by tree disconnect"
-#define DCE2_SMB_CHAIN_OPEN_CLOSE_STR \
-    "SMB - chained/compounded open pipe followed by close pipe"
-#define DCE2_SMB_INVALID_SHARE_STR   "SMB - invalid share access"
-
-#define DCE2_SMB_V1_STR  "SMB - invalid SMB version 1 seen"
-#define DCE2_SMB_V2_STR  "SMB - invalid SMB version 2 seen"
-#define DCE2_SMB_INVALID_BINDING_STR "SMB - invalid user, tree connect, file binding"
-#define DCE2_SMB2_EXCESSIVE_COMPOUNDING_STR  "SMB - excessive command compounding"
-#define DCE2_SMB_DCNT_ZERO_STR   "SMB - zero data count"
-#define DCE2_SMB_DCNT_MISMATCH_STR "SMB - data count mismatch in command and format"
-#define DCE2_SMB_MAX_REQS_EXCEEDED_STR  "SMB - maximum number of outstanding requests exceeded"
-#define DCE2_SMB_REQS_SAME_MID_STR "SMB - outstanding requests with same MID"
-#define DCE2_SMB_DEPR_DIALECT_NEGOTIATED_STR  "SMB - deprecated dialect negotiated"
-#define DCE2_SMB_DEPR_COMMAND_USED_STR   "SMB - deprecated command used"
-#define DCE2_SMB_UNUSUAL_COMMAND_USED_STR "SMB - unusual command used"
-#define DCE2_SMB_INVALID_SETUP_COUNT_STR  "SMB - invalid setup count for command"
-#define DCE2_SMB_MULTIPLE_NEGOTIATIONS_STR \
-    "SMB - client attempted multiple dialect negotiations on session"
-#define DCE2_SMB_EVASIVE_FILE_ATTRS_STR \
-    "SMB - client attempted to create or set a file's attributes to readonly/hidden/system"
-#define DCE2_SMB_INVALID_FILE_OFFSET_STR \
-    "SMB - file offset provided is greater than file size specified"
-#define DCE2_SMB_BAD_NEXT_COMMAND_OFFSET_STR \
-    "SMB - next command specified in SMB2 header is beyond payload boundary"
-
 enum dce2SmbFingerprintPolicy
 {
     DCE2_SMB_FINGERPRINT_POLICY_NONE = 0,
index 3c31a215907e8581f65abc565a6429888465ca22..977ee4b15a94117742db8276fe711db19a290f79 100644 (file)
 #include "config.h"
 #endif
 
+#include "dce_smb_module.h"
 #include "dce_smb_paf.h"
-
-#include "dce_smb_common.h"
+#include "dce_smb.h"
+#include "trace/trace_api.h"
+#include "utils/util.h"
 
 namespace
 {
@@ -45,8 +47,8 @@ using namespace snort;
  *          junk states, header type must be Session Message.
  *
  *********************************************************************/
-static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk,
-    const SmbNtHdr* nt_hdr, uint32_t* nb_len)
+static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, const SmbNtHdr* nt_hdr,
+    uint32_t* nb_len)
 {
     uint8_t type = (uint8_t)(nb_hdr >> 24);
     uint8_t bit = (uint8_t)((nb_hdr & 0x00ff0000) >> 16);
@@ -106,8 +108,8 @@ static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk,
  *          state 7 until this is the case.
  *
  *********************************************************************/
-static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow,
-    const uint8_t* data, uint32_t len, uint32_t, uint32_t* fp)
+static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, const uint8_t* data,
+    uint32_t len, uint32_t, uint32_t* fp)
 {
     uint32_t n = 0;
     StreamSplitter::Status ps = StreamSplitter::SEARCH;
@@ -179,7 +181,7 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow,
     return ps;
 }
 
-Dce2SmbSplitter::Dce2SmbSplitter(bool c2s) : StreamSplitter(c2s)
+Dce2SmbSplitter::Dce2SmbSplitter(bool c2s) :   StreamSplitter(c2s)
 {
     state.paf_state = DCE2_PAF_SMB_STATES__0;
     state.nb_hdr = 0;
@@ -190,9 +192,9 @@ StreamSplitter::Status Dce2SmbSplitter::scan(
     uint32_t flags, uint32_t* fp)
 {
     DCE2_PafSmbData* pfdata = &state;
-    StreamSplitter::Status ps =  dce2_smb_paf(pfdata, pkt->flow, data, len, flags, fp);
+    StreamSplitter::Status ps = dce2_smb_paf(pfdata, pkt->flow, data, len, flags, fp);
     SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, pkt,
-        "Dce2SmbSplitter scan with length %u and status %d\n", len, ps);
+        "Dce2SmbSplitter scan with length %u, status %d and fp %u\n", len, ps, *fp);
     return ps;
 }
 
index bd6844e299a6e0318b2ba324e8569a1e24e1c396..455fbd1c4bbf3f678107d0402894f6baeb0dc601 100644 (file)
@@ -48,7 +48,7 @@ struct DCE2_PafSmbData
 class Dce2SmbSplitter : public snort::StreamSplitter
 {
 public:
-    Dce2SmbSplitter(bool c2s);
+    explicit Dce2SmbSplitter(bool c2s);
 
     Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
         uint32_t flags, uint32_t* fp) override;
index 2349b30f601458167a628369c2c25aa1cf9d1b22..2aba031ffea19c098ecaeed3ad564d7ff4c567cc 100644 (file)
@@ -290,7 +290,7 @@ static DCE2_Ret DCE2_SmbNtTransactCreateReq(DCE2_SmbSsnData* ssd,
     dce2_move(param_ptr, param_len, pad);
 
     ssd->cur_rtracker->file_name =
-      get_smb_file_name(param_ptr, file_name_length, unicode, &ssd->cur_rtracker->file_name_size);
+        DCE2_SmbGetFileName(param_ptr, file_name_length, unicode, &ssd->cur_rtracker->file_name_size);
 
     return DCE2_RET__SUCCESS;
 }
@@ -528,8 +528,7 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
             if (DCE2_SsnIsWindowsPolicy(&ssd->sd)
                 && ssd->cur_rtracker->ftracker->fp_byte_mode)
             {
-                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-                    DetectionEngine::get_current_packet(),
+                debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
                     "Pipe is in byte mode - TRANS_TRANSACT_NMPIPE won't work\n");
                 return DCE2_RET__ERROR;
             }
@@ -554,14 +553,14 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
         // Not implemented according to MS-CIFS
         case TRANS_RAW_READ_NMPIPE:
 
-        // Can only write 2 null bytes and subsequent writes return pipe disconnected
+        // Can only write 2 NULL bytes and subsequent writes return pipe disconnected
         case TRANS_RAW_WRITE_NMPIPE:
 
         // Can at most do a DCE/RPC bind
         case TRANS_CALL_NMPIPE:
             dce_alert(GID_DCE2, DCE2_SMB_DEPR_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats,
                 ssd->sd);
-            // fallthrough
+        // fallthrough
 
         // Aren't looking at these or the three above
         case TRANS_QUERY_NMPIPE_STATE:
@@ -588,10 +587,9 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
         // And Samba uses the ByteCount to validate
         if (DCE2_SsnIsSambaPolicy(&ssd->sd)
             && (DCE2_SmbTransactionGetName(nb_ptr, nb_len,
-            byte_count, SmbUnicode(smb_hdr)) != DCE2_RET__SUCCESS))
+                byte_count, SmbUnicode(smb_hdr)) != DCE2_RET__SUCCESS))
         {
-            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-                DetectionEngine::get_current_packet(),
+            debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
                 "Failed to validate pipe name for Samba.\n");
             return DCE2_RET__ERROR;
         }
@@ -720,7 +718,7 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
         // If all of the data and parameters weren't sent, buffer what was sent
         if (((dcnt != tdcnt) || (pcnt != tpcnt)) && (dcnt != 0)
             && (DCE2_SmbBufferTransactionData(ttracker,
-            nb_ptr, dcnt, 0) != DCE2_RET__SUCCESS))
+                nb_ptr, dcnt, 0) != DCE2_RET__SUCCESS))
         {
             return DCE2_RET__ERROR;
         }
@@ -737,7 +735,7 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
         // If all of the data and parameters weren't sent, buffer what was sent
         if (((pcnt != tpcnt) || (dcnt != tdcnt)) && (pcnt != 0)
             && (DCE2_SmbBufferTransactionParameters(ttracker,
-            nb_ptr, pcnt, 0) != DCE2_RET__SUCCESS))
+                nb_ptr, pcnt, 0) != DCE2_RET__SUCCESS))
         {
             return DCE2_RET__ERROR;
         }
@@ -960,7 +958,7 @@ static DCE2_Ret DCE2_SmbTrans2Open2Req(DCE2_SmbSsnData* ssd,
     dce2_move(param_ptr, param_len, sizeof(SmbTrans2Open2ReqParams));
 
     ssd->cur_rtracker->file_name =
-      get_smb_file_name(param_ptr, param_len, unicode, &ssd->cur_rtracker->file_name_size);
+        DCE2_SmbGetFileName(param_ptr, param_len, unicode, &ssd->cur_rtracker->file_name_size);
 
     return DCE2_RET__SUCCESS;
 }
@@ -1075,8 +1073,8 @@ DCE2_Ret DCE2_SmbTransaction(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
     if (DCE2_ComInfoIsRequest(com_info)
         && !DCE2_SmbIsTransactionComplete(ttracker))
     {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            DetectionEngine::get_current_packet(), "Got new transaction request "
+        debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
+            "Got new transaction request "
             "that matches an in progress transaction - not inspecting.\n");
         return DCE2_RET__ERROR;
     }
@@ -1085,8 +1083,7 @@ DCE2_Ret DCE2_SmbTransaction(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
     if (DCE2_ComInfoIsRequest(com_info)
         && (DCE2_ComInfoWordCount(com_info) != 16))
     {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            DetectionEngine::get_current_packet(),
+        debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
             "\\PIPE\\LANMAN request - not inspecting\n");
         return DCE2_RET__IGNORE;
     }
@@ -1199,9 +1196,9 @@ DCE2_Ret DCE2_SmbTransaction2(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
     if (DCE2_ComInfoIsRequest(com_info)
         && !DCE2_SmbIsTransactionComplete(ttracker))
     {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-             DetectionEngine::get_current_packet(), "Got new transaction request "
-             "that matches an in progress transaction - not inspecting.\n");
+        debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
+            "Got new transaction request "
+            "that matches an in progress transaction - not inspecting.\n");
         return DCE2_RET__ERROR;
     }
 
@@ -1294,9 +1291,9 @@ DCE2_Ret DCE2_SmbTransaction2(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
 
             if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid)
                 && (SmbFileAttrsDirectory(SmbTrans2Open2RespFileAttrs(
-                (const SmbTrans2Open2RespParams*)ptr))
+                    (const SmbTrans2Open2RespParams*)ptr))
                 || !SmbResourceTypeDisk(SmbTrans2Open2RespResourceType(
-                (const SmbTrans2Open2RespParams*)ptr))))
+                    (const SmbTrans2Open2RespParams*)ptr))))
             {
                 return DCE2_RET__SUCCESS;
             }
@@ -1458,8 +1455,8 @@ DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
     if (DCE2_ComInfoIsRequest(com_info)
         && !DCE2_SmbIsTransactionComplete(ttracker))
     {
-        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-            DetectionEngine::get_current_packet(), "Got new transaction request "
+        debug_log(dce_smb_trace, DetectionEngine::get_current_packet(),
+            "Got new transaction request "
             "that matches an in progress transaction - not inspecting.\n");
         return DCE2_RET__ERROR;
     }
index a22e996a6c76280c12439a3bf78332349fe45adf..f92fefcf3c88a8a85d3c3225608a46f191acafb2 100644 (file)
@@ -402,3 +402,4 @@ DCE2_Ret DCE2_SmbBufferTransactionParameters(DCE2_SmbTransactionTracker* ttracke
 
     return DCE2_RET__SUCCESS;
 }
+
index dd39cb489ac99e0f9fe46009eb866b6e7c879133..a81319d18c0114ce374a0419ba71f9623ac86cf6 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef DCE_SMB_TRANSACTION_UTILS_H
 #define DCE_SMB_TRANSACTION_UTILS_H
 
-#include "dce_smb1.h"
+#include "dce_smb.h"
 
 DCE2_Ret DCE2_SmbTransactionGetName(const uint8_t* nb_ptr,
     uint32_t nb_len, uint16_t bcc, bool unicode);
index f92ab9ebee1eeaa9912122a71a5de08bab78e35e..b2c3f7cf2ee59f0e70476b614eba73ae4140e51b 100644 (file)
@@ -94,6 +94,47 @@ bool DCE2_SmbIsTidIPC(DCE2_SmbSsnData* ssd, const uint16_t tid)
     return false;
 }
 
+// Extract file name from data. Supports ASCII and UTF-16LE.
+// Returns byte stream (ASCII or UTF-16LE with BOM)
+char* DCE2_SmbGetFileName(const uint8_t* data, uint32_t data_len, bool unicode,
+    uint16_t* file_name_len)
+{
+    const uint8_t inc = unicode ? 2 : 1;
+    if (data_len < inc)
+        return nullptr;
+
+    const uint32_t max_len =  unicode ? data_len - 1 : data_len;
+    // Move forward.  Don't know if the end of data is actually
+    // the end of the string.
+    uint32_t i;
+    for (i = 0; i < max_len; i += inc)
+    {
+        uint16_t uchar = unicode ? extract_16bits(data + i) : data[i];
+        if (uchar == 0)
+            break;
+    }
+
+    char* fname = nullptr;
+    const uint32_t real_len = i;
+
+    if (unicode)
+    {
+        fname = (char*)snort_calloc(real_len + UTF_16_LE_BOM_LEN + 2);
+        memcpy(fname, UTF_16_LE_BOM, UTF_16_LE_BOM_LEN);//Prepend with BOM
+        memcpy(fname + UTF_16_LE_BOM_LEN, data, real_len);
+        *file_name_len = real_len + UTF_16_LE_BOM_LEN;
+    }
+    else
+    {
+        fname = (char*)snort_alloc(real_len + 1);
+        memcpy(fname, data, real_len);
+        fname[real_len] = 0;
+        *file_name_len = real_len;
+    }
+
+    return fname;
+}
+
 int DCE2_SmbUidTidFidCompare(const void* a, const void* b)
 {
     int x = (int)(uintptr_t)a;
@@ -137,7 +178,7 @@ void DCE2_SmbInsertUid(DCE2_SmbSsnData* ssd, const uint16_t uid)
             }
         }
 
-        DCE2_ListInsert(ssd->uids, (void*)(uintptr_t)uid, (void*)(uintptr_t)uid);
+        (void)DCE2_ListInsert(ssd->uids, (void*)(uintptr_t)uid, (void*)(uintptr_t)uid);
     }
 }
 
@@ -439,7 +480,7 @@ DCE2_SmbFileTracker* DCE2_SmbFindFileTracker(DCE2_SmbSsnData* ssd,
 
             break;
         }
-        // fallthrough
+    // fallthrough
 
     case DCE2_POLICY__WIN2003:
     case DCE2_POLICY__WINXP:
@@ -663,7 +704,7 @@ void DCE2_SmbRemoveFileTrackerFromRequestTrackers(DCE2_SmbSsnData* ssd,
     if (ftracker == nullptr)
         return;
 
-    // null out file trackers of any outstanding requests
+    // NULL out file trackers of any outstanding requests
     // that reference this file tracker
     if (ssd->rtracker.ftracker == ftracker)
         ssd->rtracker.ftracker = nullptr;
@@ -794,8 +835,8 @@ void DCE2_SmbInsertTid(DCE2_SmbSsnData* ssd,
     if ( !is_ipc and
         ssd->max_file_depth == -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1 )
     {
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-               DetectionEngine::get_current_packet(), "Not inserting TID (%hu) "
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            DetectionEngine::get_current_packet(), "Not inserting TID (%hu) "
             "because it's not IPC and not inspecting normal file data.\n", tid);
         return;
     }
@@ -822,7 +863,7 @@ void DCE2_SmbInsertTid(DCE2_SmbSsnData* ssd,
             }
         }
 
-        DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)insert_tid);
+        (void)DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)insert_tid);
     }
 }
 
@@ -951,8 +992,7 @@ DCE2_Ret DCE2_SmbProcessRequestData(DCE2_SmbSsnData* ssd,
         if (data_len > UINT16_MAX)
             data_len = UINT16_MAX;
 
-        if (ftracker->fp_co_tracker)
-            DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, data_ptr, (uint16_t)data_len);
+        DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, data_ptr, (uint16_t)data_len);
 
         if (!ftracker->fp_used)
             ftracker->fp_used = true;
@@ -1303,9 +1343,7 @@ 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;
 }
@@ -1423,9 +1461,7 @@ static void DCE2_SmbFinishFileAPI(DCE2_SmbSsnData* ssd)
 
     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)
@@ -1435,11 +1471,8 @@ static void DCE2_SmbFinishFileAPI(DCE2_SmbSsnData* ssd)
         if ((ftracker->ff_file_size == 0)
             && (ftracker->ff_bytes_processed != 0))
         {
-            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 (file_flows->file_process(p, nullptr, 0, SNORT_FILE_END, upload,
+                ftracker->file_name_hash))
             {
                 if (upload)
                 {
@@ -1511,13 +1544,12 @@ 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))
     {
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
-               p, "File API returned FAILURE for (0x%02X) %s\n",
-               ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_ERROR_LEVEL,
+            p, "File API returned FAILURE for (0x%02X) %s\n",
+            ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
 
         // Failure.  Abort tracking this file under file API
         return DCE2_RET__ERROR;
@@ -1657,7 +1689,7 @@ static DCE2_Ret DCE2_SmbHandleOutOfOrderFileData(DCE2_SmbSsnData* ssd,
 
         DCE2_Ret ret;
         if ((ret = DCE2_ListInsert(ftracker->ff_file_chunks,
-                (void*)file_chunk, (void*)file_chunk)) != DCE2_RET__SUCCESS)
+            (void*)file_chunk, (void*)file_chunk)) != DCE2_RET__SUCCESS)
         {
             snort_free((void*)file_chunk->data);
             snort_free((void*)file_chunk);
@@ -1769,10 +1801,10 @@ void DCE2_SmbProcessFileData(DCE2_SmbSsnData* ssd,
             }
             else if (ftracker->ff_file_offset < ftracker->ff_bytes_processed)
             {
-                       SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-                       DetectionEngine::get_current_packet(), "File offset %" PRIu64 " is less than bytes processed %"
-                           PRIu64 " - aborting.\n", ftracker->ff_file_offset,
-                           ftracker->ff_bytes_processed);
+                SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+                    DetectionEngine::get_current_packet(), "File offset %" PRIu64 " is less than bytes processed %"
+                    PRIu64 " - aborting.\n", ftracker->ff_file_offset,
+                    ftracker->ff_bytes_processed);
 
                 DCE2_SmbAbortFileAPI(ssd);
                 DCE2_SmbSetNewFileAPIFileTracker(ssd);
index 0a2fdb4326ddc146b20e3518dc858d7e23fe8625..a86ccb73ef4d8982772c0b946906dc5db1af1798 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef DCE_SMB_UTILS_H
 #define DCE_SMB_UTILS_H
 
-#include "dce_smb1.h"
+#include "dce_smb.h"
 #include "file_api/file_flows.h"
 
 /********************************************************************
@@ -125,6 +125,7 @@ inline bool DCE2_ComInfoCanProcessCommand(const DCE2_SmbComInfo* com_info)
  * Function prototypes
  ********************************************************************/
 bool DCE2_SmbIsTidIPC(DCE2_SmbSsnData*, const uint16_t);
+char* DCE2_SmbGetFileName(const uint8_t* data, uint32_t data_len, bool unicode, uint16_t* file_name_len);
 int DCE2_SmbUidTidFidCompare(const void*, const void*);
 DCE2_Ret DCE2_SmbFindUid(DCE2_SmbSsnData*, const uint16_t);
 void DCE2_SmbInsertUid(DCE2_SmbSsnData*, const uint16_t);
@@ -177,7 +178,6 @@ void DCE2_SmbProcessFileData(DCE2_SmbSsnData* ssd,
     uint32_t data_len, bool upload);
 void DCE2_FileDetect();
 FileVerdict DCE2_get_file_verdict();
-void DCE2_SmbInitGlobals();
 void DCE2_SmbInitDeletePdu();
 void DCE2_Update_Ftracker_from_ReqTracker(DCE2_SmbFileTracker*, DCE2_SmbRequestTracker*);
 
index 3b6f58a7bc4a34eec96345f32fd69eeb76005bc5..8dd658ee15caa3075ef4b7a969713b901ec8272a 100644 (file)
 
 using namespace snort;
 
-Dce2TcpFlowData::Dce2TcpFlowData() : FlowData(inspector_id)
+Dce2TcpFlowData::Dce2TcpFlowData() :   FlowData(inspector_id)
 {
     dce2_tcp_stats.concurrent_sessions++;
-    if(dce2_tcp_stats.max_concurrent_sessions < dce2_tcp_stats.concurrent_sessions)
+    if (dce2_tcp_stats.max_concurrent_sessions < dce2_tcp_stats.concurrent_sessions)
         dce2_tcp_stats.max_concurrent_sessions = dce2_tcp_stats.concurrent_sessions;
 }
 
@@ -113,7 +113,7 @@ static DCE2_TcpSsnData* dce2_handle_tcp_session(Packet* p, dce2TcpProtoConf* con
 // class stuff
 //-------------------------------------------------------------------------
 Dce2Tcp::Dce2Tcp(const dce2TcpProtoConf& pc) :
-    config(pc), esm(config) {}
+    config(pc), esm(config) { }
 
 bool Dce2Tcp::configure(snort::SnortConfig* sc)
 {
@@ -167,7 +167,6 @@ void Dce2Tcp::clear(Packet* p)
     {
         DCE2_ResetRopts(&dce2_tcp_sess->sd, p);
     }
-
 }
 
 //-------------------------------------------------------------------------
index 44d86b9180a38c324a06dbfbc0b9ebaedb8a77ff..7723a292455f7b02a544e11f6f2fcaed2c60a9f3 100644 (file)
@@ -128,14 +128,14 @@ public:
 
 public:
     static unsigned inspector_id;
-    DCE2_TcpSsnData dce2_tcp_session;
-    DCE2_TcpFlowState state;
+    DCE2_TcpSsnData dce2_tcp_session = {};
+    DCE2_TcpFlowState state = DCE2_TCP_FLOW__COMMON;
 };
 
 class Dce2Tcp : public snort::Inspector
 {
 public:
-    Dce2Tcp(const dce2TcpProtoConf&);
+    explicit Dce2Tcp(const dce2TcpProtoConf&);
 
     bool configure(snort::SnortConfig*) override;
     void show(const snort::SnortConfig*) const override;
index 1e8d1fd418eb9f9c77c5a0bd24e316aa5181e573..335ff0fcccf636446c6cd5b53248507556c2e1ec 100644 (file)
@@ -79,7 +79,7 @@ static const PegInfo dce2_tcp_pegs[] =
     { CountType::SUM, "bind_acks", "total connection-oriented binds acks" },
     { CountType::SUM, "alter_contexts", "total connection-oriented alter contexts" },
     { CountType::SUM, "alter_context_responses",
-        "total connection-oriented alter context responses" },
+      "total connection-oriented alter context responses" },
     { CountType::SUM, "bind_naks", "total connection-oriented bind naks" },
     { CountType::SUM, "requests", "total connection-oriented requests" },
     { CountType::SUM, "responses", "total connection-oriented responses" },
@@ -90,27 +90,27 @@ static const PegInfo dce2_tcp_pegs[] =
     { CountType::SUM, "shutdowns", "total connection-oriented shutdowns" },
     { CountType::SUM, "rejects", "total connection-oriented rejects" },
     { CountType::SUM, "ms_rpc_http_pdus",
-        "total connection-oriented MS requests to send RPC over HTTP" },
+      "total connection-oriented MS requests to send RPC over HTTP" },
     { CountType::SUM, "other_requests", "total connection-oriented other requests" },
     { CountType::SUM, "other_responses", "total connection-oriented other responses" },
     { CountType::SUM, "request_fragments", "total connection-oriented request fragments" },
     { CountType::SUM, "response_fragments", "total connection-oriented response fragments" },
     { CountType::SUM, "client_max_fragment_size",
-        "connection-oriented client maximum fragment size" },
+      "connection-oriented client maximum fragment size" },
     { CountType::SUM, "client_min_fragment_size",
-        "connection-oriented client minimum fragment size" },
+      "connection-oriented client minimum fragment size" },
     { CountType::SUM, "client_segs_reassembled",
-        "total connection-oriented client segments reassembled" },
+      "total connection-oriented client segments reassembled" },
     { CountType::SUM, "client_frags_reassembled",
-        "total connection-oriented client fragments reassembled" },
+      "total connection-oriented client fragments reassembled" },
     { CountType::SUM, "server_max_fragment_size",
-        "connection-oriented server maximum fragment size" },
+      "connection-oriented server maximum fragment size" },
     { CountType::SUM, "server_min_fragment_size",
-        "connection-oriented server minimum fragment size" },
+      "connection-oriented server minimum fragment size" },
     { CountType::SUM, "server_segs_reassembled",
-        "total connection-oriented server segments reassembled" },
+      "total connection-oriented server segments reassembled" },
     { CountType::SUM, "server_frags_reassembled",
-        "total connection-oriented server fragments reassembled" },
+      "total connection-oriented server fragments reassembled" },
     { CountType::SUM, "tcp_sessions", "total tcp sessions" },
     { CountType::SUM, "tcp_expected_sessions", "total tcp dynamic endpoint expected sessions" },
     { CountType::SUM, "tcp_expected_realized", "total tcp dynamic endpoint expected realized sessions" },
@@ -120,7 +120,7 @@ static const PegInfo dce2_tcp_pegs[] =
     { CountType::END, nullptr, nullptr }
 };
 
-Dce2TcpModule::Dce2TcpModule() : Module(DCE2_TCP_NAME, DCE2_TCP_HELP, s_params)
+Dce2TcpModule::Dce2TcpModule() :   Module(DCE2_TCP_NAME, DCE2_TCP_HELP, s_params)
 {
 }
 
index 74021805ab34250ba3480f92d64ebec9ecef7336..dee0440e4a445e75ff2c693abe2579bb588a7828 100644 (file)
@@ -31,7 +31,7 @@ struct SnortConfig;
 
 struct dce2TcpProtoConf
 {
-    dce2CoProtoConf common;
+    dce2CoProtoConf common = {};
 };
 
 class Dce2TcpModule : public snort::Module
index 1c3384d77b850b79d5dd34d8a67a23f05bac99ca..aaecd9dbac6604eaa35c3cdb85404313fa4f1eb7 100644 (file)
@@ -30,7 +30,7 @@
 
 using namespace snort;
 
-Dce2TcpSplitter::Dce2TcpSplitter(bool c2s) : StreamSplitter(c2s)
+Dce2TcpSplitter::Dce2TcpSplitter(bool c2s) :   StreamSplitter(c2s)
 {
     state.paf_state = DCE2_PAF_TCP_STATES__0;
     state.byte_order = DCERPC_BO_FLAG__NONE;
@@ -53,12 +53,12 @@ StreamSplitter::Status Dce2TcpSplitter::scan(
 {
     DCE2_TcpSsnData* sd = get_dce2_tcp_session_data(pkt->flow);
 
-    if (dce2_paf_abort((DCE2_SsnData*) sd))
+    if (dce2_paf_abort((DCE2_SsnData*)sd))
         return StreamSplitter::ABORT;
 
     uint32_t n = 0;
     uint32_t new_fp = 0;
-    int start_state = (uint8_t) state.paf_state;
+    int start_state = (uint8_t)state.paf_state;
     int num_requests = 0;
 
     while (n < len)
@@ -108,7 +108,8 @@ StreamSplitter::Status Dce2TcpSplitter::scan(
             if (state.frag_len < sizeof(DceRpcCoHdr))
             {
                 if (sd)
-                    dce_alert(GID_DCE2, DCE2_CO_FRAG_LEN_LT_HDR, (dce2CommonStats*)&dce2_tcp_stats, *(DCE2_SsnData*)sd);
+                    dce_alert(GID_DCE2, DCE2_CO_FRAG_LEN_LT_HDR, (dce2CommonStats*)&dce2_tcp_stats,
+                        *(DCE2_SsnData*)sd);
                 return StreamSplitter::ABORT;
             }
 
@@ -117,7 +118,7 @@ StreamSplitter::Status Dce2TcpSplitter::scan(
                 state.autodetected = true;
 
             /* Increment n here so we can continue */
-            n += state.frag_len - (uint8_t) state.paf_state;
+            n += state.frag_len - (uint8_t)state.paf_state;
             num_requests++;
             /* Might have multiple PDUs in one segment.  If the last PDU is partial,
              * flush just before it */
@@ -142,3 +143,4 @@ StreamSplitter::Status Dce2TcpSplitter::scan(
 
     return StreamSplitter::SEARCH;
 }
+
index a1c470f75ac75c709ebe7d304ef9f80a814ad893..82ab251fce8557a0ccc33033eee8a93484f1342b 100644 (file)
@@ -51,7 +51,7 @@ struct DCE2_PafTcpData
 class Dce2TcpSplitter : public snort::StreamSplitter
 {
 public:
-    Dce2TcpSplitter(bool c2s);
+    explicit Dce2TcpSplitter(bool c2s);
 
     Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
         uint32_t flags, uint32_t* fp) override;
index e6315389f7032cfcdef18b34ed727905ae090d27..a3b60631984fdfafb280f1240e869602b1089fc4 100644 (file)
@@ -50,10 +50,10 @@ static void DCE2_ClCleanTracker(DCE2_ClTracker* clt)
 //-------------------------------------------------------------------------
 // class stuff
 //-------------------------------------------------------------------------
-Dce2UdpFlowData::Dce2UdpFlowData() : FlowData(inspector_id)
+Dce2UdpFlowData::Dce2UdpFlowData() :   FlowData(inspector_id)
 {
     dce2_udp_stats.concurrent_sessions++;
-    if(dce2_udp_stats.max_concurrent_sessions < dce2_udp_stats.concurrent_sessions)
+    if (dce2_udp_stats.max_concurrent_sessions < dce2_udp_stats.concurrent_sessions)
         dce2_udp_stats.max_concurrent_sessions = dce2_udp_stats.concurrent_sessions;
 }
 
@@ -108,7 +108,7 @@ static DCE2_UdpSsnData* dce2_handle_udp_session(Packet* p, dce2UdpProtoConf* con
 class Dce2Udp : public Inspector
 {
 public:
-    Dce2Udp(const dce2UdpProtoConf&);
+    explicit Dce2Udp(const dce2UdpProtoConf&);
     void show(const SnortConfig*) const override;
     void eval(Packet*) override;
     void clear(Packet*) override;
@@ -117,9 +117,8 @@ private:
     dce2UdpProtoConf config;
 };
 
-Dce2Udp::Dce2Udp(const dce2UdpProtoConf& pc)
+Dce2Udp::Dce2Udp(const dce2UdpProtoConf& pc) : config(pc)
 {
-    config = pc;
 }
 
 void Dce2Udp::show(const SnortConfig*) const
@@ -163,7 +162,6 @@ void Dce2Udp::clear(Packet* p)
     {
         DCE2_ResetRopts(&dce2_udp_sess->sd, p);
     }
-
 }
 
 //-------------------------------------------------------------------------
index eca90f7d194869bfd59e6362e6bd5fd3f88c5a44..c491afa7ed80e15369c4917d52b3f281b986b11c 100644 (file)
@@ -196,7 +196,7 @@ public:
     { inspector_id = snort::FlowData::create_flow_data_id(); }
 
     static unsigned inspector_id;
-    DCE2_UdpSsnData dce2_udp_session;
+    DCE2_UdpSsnData dce2_udp_session = {};
 };
 
 DCE2_UdpSsnData* get_dce2_udp_session_data(snort::Flow*);
index b3c17c39ad66771c8d41fb7d820bc950c76304d5..c4990cf5436702e1539e94d50ef87dfe4cc4547e 100644 (file)
@@ -85,7 +85,7 @@ static const PegInfo dce2_udp_pegs[] =
     { CountType::END, nullptr, nullptr }
 };
 
-Dce2UdpModule::Dce2UdpModule() : Module(DCE2_UDP_NAME, DCE2_UDP_HELP, s_params)
+Dce2UdpModule::Dce2UdpModule() :   Module(DCE2_UDP_NAME, DCE2_UDP_HELP, s_params), config {}
 { }
 
 void Dce2UdpModule::set_trace(const Trace* trace) const
index 170f485e4c8600620d146a8f0604e8a8e0d90088..3c53050b89015526799abf8a4ac0a625b2c254b6 100644 (file)
@@ -44,7 +44,7 @@ extern THREAD_LOCAL const snort::Trace* dce_udp_trace;
 
 struct dce2UdpProtoConf
 {
-    dce2CommonProtoConf common;
+    dce2CommonProtoConf common = {};
 };
 
 class Dce2UdpModule : public snort::Module
index 3c6643a1aba3f241d611f7a22e114edadac5058b..735421bec91e7267cc77ab80fe2569bdd6f3962b 100644 (file)
@@ -1,6 +1,5 @@
 //--------------------------------------------------------------------------
 // Copyright (C) 2014-2023 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2008-2013 Sourcefire, Inc.
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
@@ -538,10 +537,10 @@ static int DCE2_ClFragCompare(const void* a, const void* b)
 static void DCE2_ClFragReassemble(
     DCE2_SsnData* sd, DCE2_ClActTracker* at, const DceRpcClHdr* cl_hdr)
 {
-    uint8_t dce2_cl_rbuf[IP_MAXPACKET];
+    auto dce2_cl_rbuf = std::make_unique<uint8_t[]>(IP_MAXPACKET);
     DCE2_ClFragTracker* ft = &at->frag_tracker;
-    const uint8_t* rdata = dce2_cl_rbuf;
-    uint16_t rlen = sizeof(dce2_cl_rbuf);
+    const uint8_t* rdata = dce2_cl_rbuf.get();
+    uint16_t rlen = IP_MAXPACKET;
     DCE2_ClFragNode* fnode;
     uint32_t stub_len = 0;
 
@@ -558,7 +557,7 @@ static void DCE2_ClFragReassemble(
     }
 
     Packet* rpkt = DCE2_GetRpkt(DetectionEngine::get_current_packet(),
-        DCE2_RPKT_TYPE__UDP_CL_FRAG, dce2_cl_rbuf, stub_len);
+        DCE2_RPKT_TYPE__UDP_CL_FRAG, dce2_cl_rbuf.get(), stub_len);
 
     if ( !rpkt )
         return;
index cfd7bfc8e095f462957722def44979e29057f417..ffa787c271fbd96500b19caafcc2205e1604a3e0 100644 (file)
@@ -182,7 +182,6 @@ const char* DCE2_UuidToStr(
     return uuid_buf;
 }
 
-
 DCE2_Buffer* DCE2_BufferNew(uint32_t initial_size, uint32_t min_add_size)
 {
     DCE2_Buffer* buf = (DCE2_Buffer*)snort_calloc(sizeof(DCE2_Buffer));
index 64c3de039feb0a63f6c3a4fd3ace6c31a49b69f2..c3ce017ab5dec1799a49ce4f5e030ee21f2fc0a2 100644 (file)
@@ -1,6 +1,5 @@
-//--------------------------------------------------------------------------
+//-------------------------------------------------------------------------/
 // Copyright (C) 2014-2023 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2008-2013 Sourcefire, Inc.
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
@@ -136,11 +135,10 @@ void DCE2_BufferDestroy(DCE2_Buffer* buf);
 
 #define DCE2_UUID_BUF_SIZE 50
 const char* DCE2_UuidToStr(
-    const Uuid*, DceRpcBoFlag, char (&buf)[DCE2_UUID_BUF_SIZE]);
+    const Uuid*, DceRpcBoFlag, char (& buf)[DCE2_UUID_BUF_SIZE]);
 
 // Determines if the character passed in is a character that
 // the inspector considers a to be a space character.
-
 inline bool DCE2_IsSpaceChar(const char c)
 {
     if (isspace((int)c))
@@ -151,7 +149,6 @@ inline bool DCE2_IsSpaceChar(const char c)
 // Determines if the character passed in is a character that
 // the inspector considers a to be an end of configuration
 // character.
-
 inline bool DCE2_IsConfigEndChar(const char c)
 {
     if (c == DCE2_CFG_TOK__END)
@@ -161,7 +158,6 @@ inline bool DCE2_IsConfigEndChar(const char c)
 
 // Prunes whitespace surrounding string.
 // String must be 0 terminated.
-
 inline char* DCE2_PruneWhiteSpace(char* str)
 {
     char* end;
@@ -186,7 +182,6 @@ inline char* DCE2_PruneWhiteSpace(char* str)
 
 // Checks if string is null, empty or just spaces.
 // String must be 0 terminated.
-
 inline bool DCE2_IsEmptyStr(char* str)
 {
     char* end;
@@ -386,3 +381,4 @@ inline void dce2_move(const uint8_t*& data_ptr, int64_t& data_len, int amount)
 }
 
 #endif
+
index 6942429e4b4d8db3a38413810050af119fef4c83..da0d1d8cedc7543b429274bb23642369bf36e0f3 100644 (file)
@@ -2,7 +2,7 @@ This directory contains all the files related to DCE-RPC protocol
 processing.
 
 DCE is supported over TCP/IP, UDP, SMB and HTTP v1 Proxy and Server.
-The DCE-RPC preprocessor is split into four inspectors - one for each
+The DCE-RPC inspector is split into four inspectors - one for each
 transport. This includes the configuration as well as the inspector
 modules.
 
@@ -25,18 +25,13 @@ inspectors.  These inspectors only serve to locate the 'tunnel' setup
 content.  If/when the setup content is located, the session is transferred
 to the DCE TCP inspector.
 
-The SMB inspector supports version 1 and version 2 of the protocol. 
-It processes relevant messages and inspects file transferred over this transport. 
+The SMB inspector supports version 1 and version 2 of the protocol.
+It processes relevant messages and inspects file transferred over this transport.
 For SMBv2, it supports TCP as transport and it also supports multiple File transfer
-on single SMB2 connection.
-The SMB inspector implements base class for smb flow data,
-which all versions now inherits and implements. SMBv1 and SMBv2 code is completely
-segregated, maintaining common code in separate file to reduce redundancy.
-The common functionality used by both versions are in dce_smb_common files.
-SMBv2 specific trackers are in there own file now.
+on single SMB2 connection or multiple SMB2 connection from the same source IP.
 
 The inspector eval function checks for the presence of SMB flow data in the flow,
 if not present, it creates an SMB flow data according to detected version, otherwise
 calls the respective process function.
 The process functions processes the commands according to respective versions and when
-file transfer is detected, it calls file_flow process().
\ No newline at end of file
+file transfer is detected, it calls file_flow process().
index a681a4137883a0c3bc1c77f7838654865a1e2476..cf891dc8392bfbb2f4323f7d96a0058c0f2aebc9 100644 (file)
@@ -231,8 +231,8 @@ public:
 
 private:
     const RangeCheck version;
-    const bool any_frag;
-    const Uuid uuid;
+    const bool any_frag = false;
+    const Uuid uuid = {};
     PatternMatchData pmd;
     PatternMatchData alt_pmd;
 };
@@ -249,7 +249,7 @@ Dce2IfaceOption::~Dce2IfaceOption()
     }
 }
 
-static char* make_pattern_buffer( const Uuid &uuid, DceRpcBoFlag type )
+static char* make_pattern_buffer(const Uuid& uuid, DceRpcBoFlag type)
 {
     int index = 0;
     char* pattern_buf = (char*)snort_alloc(sizeof(Uuid));
@@ -314,9 +314,9 @@ PatternMatchData* Dce2IfaceOption::get_pattern(SnortProtocolId snort_protocol_id
     }
     else if (snort_protocol_id == SNORT_PROTO_UDP)
     {
-        pmd.pattern_buf = make_pattern_buffer( uuid, DCERPC_BO_FLAG__LITTLE_ENDIAN );
+        pmd.pattern_buf = make_pattern_buffer(uuid, DCERPC_BO_FLAG__LITTLE_ENDIAN);
         pmd.pattern_size = sizeof(Uuid);
-        alt_pmd.pattern_buf = make_pattern_buffer( uuid, DCERPC_BO_FLAG__BIG_ENDIAN );
+        alt_pmd.pattern_buf = make_pattern_buffer(uuid, DCERPC_BO_FLAG__BIG_ENDIAN);
         alt_pmd.pattern_size = sizeof(Uuid);
 
         return &pmd;
@@ -454,7 +454,7 @@ static const Parameter s_params[] =
 class Dce2IfaceModule : public Module
 {
 public:
-    Dce2IfaceModule() : Module(s_name, s_help, s_params) { }
+    Dce2IfaceModule() :   Module(s_name, s_help, s_params) { }
 
     bool begin(const char*, int, SnortConfig*) override;
     bool set(const char*, Value&, SnortConfig*) override;
index 31c264ac63ef2becfc289aa1774e72adb567ade0..5a7b318c3684dfe06ac20981d93bd61f832ce06c 100644 (file)
@@ -342,8 +342,8 @@ static DCE2_Ret DCE2_OpnumParse(char* args, DCE2_Opnum* opnum)
 class Dce2OpnumOption : public IpsOption
 {
 public:
-    Dce2OpnumOption(const DCE2_Opnum& src_opnum) : IpsOption(s_name)
-    { opnum = src_opnum; }
+    explicit Dce2OpnumOption(const DCE2_Opnum& src_opnum) :   IpsOption(s_name), opnum(src_opnum)
+    { }
     uint32_t hash() const override;
     bool operator==(const IpsOption&) const override;
     EvalStatus eval(Cursor&, Packet*) override;
@@ -462,7 +462,7 @@ static const Parameter s_params[] =
 class Dce2OpnumModule : public Module
 {
 public:
-    Dce2OpnumModule() : Module(s_name, s_help, s_params)
+    Dce2OpnumModule() :   Module(s_name, s_help, s_params)
     { memset(&opnum, 0, sizeof(opnum)); }
 
     bool begin(const char*, int, SnortConfig*) override;
@@ -489,7 +489,8 @@ bool Dce2OpnumModule::begin(const char*, int, SnortConfig*)
 
 bool Dce2OpnumModule::set(const char*, Value& v, SnortConfig*)
 {
-    assert(v.is("~"));
+    if ( !v.is("~") )
+        return false;
     std::string tok = v.get_unquoted_string();
     char* s = snort_strdup(tok.c_str());
     DCE2_Ret status = DCE2_OpnumParse(s, &opnum);
index eba1dcba9dae337b39c4769d19b47fc1881c3778..2c0269de21081a078480edd57b37f7a557708bfa 100644 (file)
@@ -46,7 +46,7 @@ static THREAD_LOCAL ProfileStats dce2_stub_data_perf_stats;
 class Dce2StubDataOption : public IpsOption
 {
 public:
-    Dce2StubDataOption() : IpsOption(s_name) { }
+    Dce2StubDataOption() :   IpsOption(s_name) { }
 
     uint32_t hash() const override;
     bool operator==(const IpsOption&) const override;
@@ -109,7 +109,7 @@ IpsOption::EvalStatus Dce2StubDataOption::eval(Cursor& c, Packet* p)
 class Dce2StubDataModule : public Module
 {
 public:
-    Dce2StubDataModule() : Module(s_name, s_help) { }
+    Dce2StubDataModule() :   Module(s_name, s_help) { }
     ProfileStats* get_profile() const override;
 
     Usage get_usage() const override
index 1975b818433d555505144d5361d307d1678f522c..3331160a3aa57fdffbd2512d31c0ff6f18164402 100644 (file)
@@ -397,7 +397,7 @@ inline uint32_t NbssLen(const NbssHdr* nb)
 }
 
 // NbssLen2 should be used by SMB2/SMB3
-inline uint32_t NbssLen2(const NbssHdr *nb)
+inline uint32_t NbssLen2(const NbssHdrnb)
 {
     // The Length is 3 bytes. [MS-SMB2] 2.1 Transport
     // The left operand of '<<' is a garbage value
index 419677881b84962e66da4b6d72a341f6341c1334..e2b273adf8b0a6a06fc3765fb4eb6e6e0cf1766d 100644 (file)
 
 #include "smb_message.h"
 
+#include "dce_smb.h"
 #include "dce_smb_commands.h"
 #include "dce_smb_module.h"
 #include "dce_smb_paf.h"
 #include "dce_smb_transaction.h"
+#include "dce_smb2_utils.h"
 #include "detection/detect.h"
 #include "file_api/file_service.h"
+#include "memory/memory_cap.h"
 #include "packet_io/active.h"
 #include "protocols/packet.h"
 #include "trace/trace_api.h"
@@ -803,9 +806,9 @@ static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr
         com_info.cmd_size = 0;
         com_info.byte_count = 0;
         DCE2_SmbCheckCommand(ssd, smb_hdr, smb_com, nb_ptr, nb_len, com_info);
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-               DetectionEngine::get_current_packet(),
-               "Processing command: %s (0x%02X)\n", get_smb_com_string(smb_com), smb_com);
+        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
+            DetectionEngine::get_current_packet(),
+            "Processing command: %s (0x%02X)\n", get_smb_com_string(smb_com), smb_com);
 
         // Note that even if the command shouldn't be processed, some of
         // the command functions need to know and do cleanup or some other
@@ -830,8 +833,8 @@ static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr
             break;
 
         SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
-           DetectionEngine::get_current_packet(),
-           "Chained SMB command: %s\n", get_smb_com_string(smb_com2));
+            DetectionEngine::get_current_packet(),
+            "Chained SMB command: %s\n", get_smb_com_string(smb_com2));
 
         num_chained++;
         if (DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config) &&
@@ -1012,7 +1015,7 @@ static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr
  * Function: DCE2_SmbInspect()
  *
  * Purpose:
- *  Determines whether the SMB command is something the inspector
+ *  Determines whether the SMB command is something the preprocessor
  *  needs to inspect.
  *  This function returns a DCE2_SmbRequestTracker which tracks command
  *  requests / responses.
@@ -1294,6 +1297,71 @@ void DCE2_SmbDataFree(DCE2_SmbSsnData* ssd)
     }
 }
 
+Dce2SmbFlowData::Dce2SmbFlowData() :   FlowData(inspector_id)
+{
+    dce2_smb_stats.concurrent_sessions++;
+    if (dce2_smb_stats.max_concurrent_sessions < dce2_smb_stats.concurrent_sessions)
+        dce2_smb_stats.max_concurrent_sessions = dce2_smb_stats.concurrent_sessions;
+    smb_version = DCE2_SMB_VERSION_NULL;
+    dce2_smb_session_data = nullptr;
+}
+
+Dce2SmbFlowData::~Dce2SmbFlowData()
+{
+    if (DCE2_SMB_VERSION_1 == smb_version)
+    {
+        DCE2_SmbDataFree((DCE2_SmbSsnData*)dce2_smb_session_data);
+        delete (DCE2_SmbSsnData*)dce2_smb_session_data;
+    }
+    else
+    {
+        delete (DCE2_Smb2SsnData*)dce2_smb_session_data;
+    }
+    assert(dce2_smb_stats.concurrent_sessions > 0);
+    dce2_smb_stats.concurrent_sessions--;
+}
+
+unsigned Dce2SmbFlowData::inspector_id = 0;
+
+static inline DCE2_SmbSsnData* set_new_dce2_smb_session(Packet* p)
+{
+    Dce2SmbFlowData* fd = new Dce2SmbFlowData;
+    fd->smb_version = DCE2_SMB_VERSION_1;
+    fd->dce2_smb_session_data = new DCE2_SmbSsnData();
+    p->flow->set_flow_data(fd);
+    return (DCE2_SmbSsnData*)(fd->dce2_smb_session_data);
+}
+
+DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf* config)
+{
+    DCE2_SmbSsnData* dce2_smb_sess = set_new_dce2_smb_session(p);
+    if ( dce2_smb_sess )
+    {
+        dce2_smb_sess->dialect_index = DCE2_SENTINEL;
+        dce2_smb_sess->max_outstanding_requests = 10;  // Until Negotiate/SessionSetupAndX
+        dce2_smb_sess->cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+        dce2_smb_sess->srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+        dce2_smb_sess->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+        dce2_smb_sess->uid = DCE2_SENTINEL;
+        dce2_smb_sess->tid = DCE2_SENTINEL;
+        dce2_smb_sess->ftracker.fid_v1 = DCE2_SENTINEL;
+        dce2_smb_sess->rtracker.mid = DCE2_SENTINEL;
+        dce2_smb_sess->max_file_depth = FileService::get_max_file_depth();
+
+        DCE2_ResetRopts(&dce2_smb_sess->sd, p);
+
+        dce2_smb_stats.smb_sessions++;
+        dce2_smb_stats.total_smb1_sessions++;
+
+        dce2_smb_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
+        dce2_smb_sess->sd.server_policy = config->common.policy;
+        dce2_smb_sess->sd.client_policy = DCE2_POLICY__WINXP;
+        dce2_smb_sess->sd.config = (void*)config;
+    }
+
+    return dce2_smb_sess;
+}
+
 /********************************************************************
  * Function: DCE2_NbssHdrChecks()
  *
@@ -1554,15 +1622,15 @@ void DCE2_Smb1Process(DCE2_SmbSsnData* ssd)
                 if (!DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
                 {
                     // Upgrade connection to SMBv2
-                           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-                               p, "upgrading to smb2 session\n");
+                    debug_log(dce_smb_trace, p, "upgrading to smb2 session\n");
+                    dce2SmbProtoConf* config = (dce2SmbProtoConf*)ssd->sd.config;
                     Dce2SmbFlowData* fd = (Dce2SmbFlowData*)p->flow->get_flow_data(
                         Dce2SmbFlowData::inspector_id);
-                    if (fd)
-                    {
-                        Dce2SmbSessionData* dce2_smb2_sess = fd->upgrade(p);
-                        dce2_smb2_sess->process();
-                    }
+                    p->flow->free_flow_data(fd);
+                    DCE2_Smb2SsnData* dce2_smb2_sess = dce2_create_new_smb2_session(p, config);
+                    DCE2_Smb2Process(dce2_smb2_sess);
+                    if (!dce2_detected)
+                        DCE2_Detect(&dce2_smb2_sess->sd);
                 }
                 else
                     ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
@@ -1573,8 +1641,7 @@ void DCE2_Smb1Process(DCE2_SmbSsnData* ssd)
             rtracker = DCE2_SmbInspect(ssd, smb_hdr);
             if (rtracker == nullptr)
             {
-                       SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
-                           p, "Not inspecting SMB packet.\n");
+                debug_log(dce_smb_trace, p, "Not inspecting SMB packet.\n");
 
                 if (DCE2_BufferIsEmpty(*seg_buf))
                 {
@@ -2489,3 +2556,63 @@ void DCE2_SmbInitGlobals()
     }
 }
 
+/* smb2 Functions */
+
+static inline DCE2_Smb2SsnData* set_new_dce2_smb2_session(Packet* p)
+{
+    Dce2SmbFlowData* fd = new Dce2SmbFlowData;
+    fd->smb_version = DCE2_SMB_VERSION_2;
+    fd->dce2_smb_session_data = new DCE2_Smb2SsnData();
+
+    p->flow->set_flow_data(fd);
+    return((DCE2_Smb2SsnData*)fd->dce2_smb_session_data);
+}
+
+DCE2_Smb2SsnData* dce2_create_new_smb2_session(Packet* p, dce2SmbProtoConf* config)
+{
+    DCE2_Smb2SsnData* dce2_smb2_sess = set_new_dce2_smb2_session(p);
+    if ( dce2_smb2_sess )
+    {
+        dce2_smb2_sess->sd.flags |= DCE2_SSN_FLAG__SMB2;
+        dce2_smb2_sess->dialect_index = DCE2_SENTINEL;
+
+        DCE2_ResetRopts(&dce2_smb2_sess->sd, p);
+
+        dce2_smb_stats.smb_sessions++;
+        dce2_smb_stats.total_smb2_sessions++;
+
+        dce2_smb2_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
+        dce2_smb2_sess->sd.server_policy = config->common.policy;
+        dce2_smb2_sess->sd.client_policy = DCE2_POLICY__WINXP;
+        dce2_smb2_sess->sd.config = (void*)config;
+        dce2_smb2_sess->max_outstanding_requests = DCE2_ScSmbMaxCredit(config);
+    }
+
+    return dce2_smb2_sess;
+}
+
+DCE2_SsnData* get_dce2_session_data(snort::Flow* flow)
+{
+    Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(Dce2SmbFlowData::inspector_id);
+    if (fd and fd->dce2_smb_session_data)
+        return (fd->smb_version == DCE2_SMB_VERSION_1) ?
+               (DCE2_SsnData*)(&((DCE2_SmbSsnData*)fd->dce2_smb_session_data)->sd) :
+               (DCE2_SsnData*)(&((DCE2_Smb2SsnData*)fd->dce2_smb_session_data)->sd);
+    else
+        return nullptr;
+}
+
+void set_smb_reassembled_data(uint8_t* nb_ptr, uint16_t co_len)
+{
+    snort::Flow* flow = DetectionEngine::get_current_packet()->flow;
+    if (flow)
+    {
+        Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(
+            Dce2SmbFlowData::inspector_id);
+        if (fd and fd->dce2_smb_session_data)
+            return (fd->smb_version == DCE2_SMB_VERSION_1) ?
+                   DCE2_SmbSetRdata((DCE2_SmbSsnData*)fd->dce2_smb_session_data, nb_ptr, co_len):
+                   (((DCE2_Smb2SsnData*)fd->dce2_smb_session_data)->set_reassembled_data(nb_ptr, co_len));
+    }
+}
+
index 3b786b6a8cd4a1d40fe05c0e6b77c27a6cc9028d..2f6e9f9bde6dc0c25885e871c414141dc04b367f 100644 (file)
@@ -152,7 +152,7 @@ inline uint16_t SmbCloseReqFid(const SmbCloseReq* req)
  ********************************************************************/
 struct SmbDeleteReq  /* smb_wct = 1 */
 {
-    uint8_t  smb_wct;
+    uint8_t smb_wct;
     uint16_t smb_search_attrs;
     uint16_t smb_bcc;
 };
@@ -489,7 +489,7 @@ inline uint64_t SmbReadAndXReqOffset(const SmbReadAndXExtReq* req)
         return (uint64_t)snort::alignedNtohl(&req->smb_offset);
 
     return (uint64_t)snort::alignedNtohl(&req->smb_off_high) << 32
-                    | (uint64_t)snort::alignedNtohl(&req->smb_offset);
+           | (uint64_t)snort::alignedNtohl(&req->smb_offset);
 }
 
 inline uint16_t SmbReadAndXRespDataOff(const SmbReadAndXResp* req)
@@ -500,7 +500,7 @@ inline uint16_t SmbReadAndXRespDataOff(const SmbReadAndXResp* req)
 inline uint32_t SmbReadAndXRespDataCnt(const SmbReadAndXResp* resp)
 {
     return (uint32_t)snort::alignedNtohs(&resp->smb_dsize_high) << 16
-                    | (uint32_t)snort::alignedNtohs(&resp->smb_dsize);
+           | (uint32_t)snort::alignedNtohs(&resp->smb_dsize);
 }
 
 /********************************************************************
@@ -583,13 +583,13 @@ inline uint64_t SmbWriteAndXReqOffset(const SmbWriteAndXExtReq* req)
         return (uint64_t)snort::alignedNtohl(&req->smb_offset);
 
     return (uint64_t)snort::alignedNtohl(&req->smb_off_high) << 32
-                    | (uint64_t)snort::alignedNtohl(&req->smb_offset);
+           | (uint64_t)snort::alignedNtohl(&req->smb_offset);
 }
 
 inline uint32_t SmbWriteAndXReqDataCnt(const SmbWriteAndXReq* req)
 {
     return (uint32_t)snort::alignedNtohs(&req->smb_dsize_high) << 16
-                    | (uint32_t)snort::alignedNtohs(&req->smb_dsize);
+           | (uint32_t)snort::alignedNtohs(&req->smb_dsize);
 }
 
 inline uint16_t SmbWriteAndXReqWriteMode(const SmbWriteAndXReq* req)
@@ -2033,7 +2033,7 @@ inline uint64_t SmbReadRawReqOffset(const SmbReadRawExtReq* req)
         return (uint64_t)snort::alignedNtohl(&req->smb_offset);
 
     return (uint64_t)snort::alignedNtohl(&req->smb_off_high) << 32
-                    | (uint64_t)snort::alignedNtohl(&req->smb_offset);
+           | (uint64_t)snort::alignedNtohl(&req->smb_offset);
 }
 
 /********************************************************************
@@ -2112,7 +2112,7 @@ inline uint64_t SmbWriteRawReqOffset(const SmbWriteRawExtReq* req)
         return (uint64_t)snort::alignedNtohl(&req->smb_offset);
 
     return (uint64_t)snort::alignedNtohl(&req->smb_off_high) << 32 |
-                    (uint64_t)snort::alignedNtohl(&req->smb_offset);
+           (uint64_t)snort::alignedNtohl(&req->smb_offset);
 }
 
 inline uint16_t SmbWriteRawInterimRespRemaining(const SmbWriteRawInterimResp* resp)
@@ -2190,8 +2190,12 @@ inline uint16_t SmbWriteAndCloseRespCount(const SmbWriteAndCloseResp* resp)
 
 #pragma pack()
 
+void DCE2_SmbInitGlobals();
 void DCE2_Smb1Process(struct DCE2_SmbSsnData*);
+struct DCE2_SmbSsnData* dce2_create_new_smb_session(snort::Packet*, struct dce2SmbProtoConf*);
+struct DCE2_Smb2SsnData* dce2_create_new_smb2_session(snort::Packet*, struct dce2SmbProtoConf*);
 void DCE2_SmbDataFree(DCE2_SmbSsnData*);
+void set_smb_reassembled_data(uint8_t* nb_ptr, uint16_t co_len);
 
 #endif