]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3365: dce_rpc: Handling only named ioctls for smb
authorBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 18 Apr 2022 06:26:33 +0000 (06:26 +0000)
committerBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 18 Apr 2022 06:26:33 +0000 (06:26 +0000)
Merge in SNORT/snort3 from ~BSACHDEV/snort3:dce_ss_crash_2 to master

Squashed commit of the following:

commit 1d77d1119629f9cd241577206b5bb64328b548fd
Author: bsachdev <bsachdev@cisco.com>
Date:   Sun Mar 20 23:51:38 2022 -0400

    dce_rpc: Handling only named ioctls for smb

Signed-off-by: bsachdev <bsachdev@cisco.com>
src/service_inspectors/dce_rpc/dce_smb2.h
src/service_inspectors/dce_rpc/dce_smb2_file.cc
src/service_inspectors/dce_rpc/dce_smb2_tree.cc

index beaf91ceb3d715e8b9df4401d42e701389b1ff2c..b1580de1748108ccbcd14d810cf64bb084868d98 100644 (file)
@@ -69,6 +69,10 @@ extern const char* smb2_command_string[SMB2_COM_MAX];
 #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
+
 struct Smb2Hdr
 {
     uint8_t smb_idf[4];       /* contains 0xFE,’SMB’ */
@@ -251,6 +255,38 @@ struct Smb2TreeConnectResponseHdr
     uint32_t maximal_access;          /* maximal access for the user */
 };
 
+struct Smb2IoctlRequestHdr
+{
+    uint16_t structure_size;          /* This MUST be set to 57 */
+    uint16_t reserved;
+    uint32_t ctl_code;
+    uint64_t fileId_persistent;       /* fileId that is persistent */
+    uint64_t fileId_volatile;
+    uint32_t input_offset;
+    uint32_t input_count;
+    uint32_t max_input_response;
+    uint32_t output_offset;
+    uint32_t output_count;
+    uint32_t max_output_response;
+    uint32_t flags;
+    uint32_t reserved2;
+};
+
+struct Smb2IoctlResponseHdr
+{
+    uint16_t structure_size;           /* This MUST be set to 49 */
+    uint16_t reserved;
+    uint32_t ctl_code;
+    uint64_t fileId_persistent;       /* fileId that is persistent */
+    uint64_t fileId_volatile;
+    uint32_t input_offset;
+    uint32_t input_count;
+    uint32_t output_offset;
+    uint32_t output_count;
+    uint32_t flags;
+    uint32_t reserved2;
+};
+
 #define SMB2_HEADER_LENGTH 64
 
 #define SMB2_ERROR_RESPONSE_STRUC_SIZE 9
index b994613ed59186e32618e21146d4e7fe978a2ad2..1ab85f677d12c81ca9c185c9a2e9ffeb4de03a6b 100644 (file)
@@ -109,18 +109,22 @@ void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint6
     file_size = size_v;
     auto updated_flow = update_processing_flow();
     Flow* flow = updated_flow.second->get_tcp_flow();
-    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)
+        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)
         {
-            if ((file_name_v and name_len_v) or updated_flow.first)
-                file->set_file_name(file_name, file_name_len);
-            file->set_file_size(size_v ? size_v : UNKNOWN_FILE_SIZE);
+            ignore = false;
+            if (file->verdict == FILE_VERDICT_UNKNOWN)
+            {
+                if ((file_name_v and name_len_v) or updated_flow.first)
+                    file->set_file_name(file_name, file_name_len);
+                file->set_file_size(size_v ? size_v : UNKNOWN_FILE_SIZE);
+            }
         }
     }
 }
@@ -135,10 +139,12 @@ bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key)
         file_size = file_offset;
         Dce2Smb2SessionData* processing_flow = update_processing_flow().second;
         Flow* flow = processing_flow->get_tcp_flow();
-        FileContext* file = get_smb_file_context(flow, file_name_hash, file_id, false);
-        if (file)
-            file->set_file_size(file_size);
-        
+        {
+            std::lock_guard<std::mutex> guard(process_file_mutex);
+            FileContext* file = get_smb_file_context(flow, file_name_hash, file_id, false);
+            if (file)
+                file->set_file_size(file_size);
+        }
         Dce2Smb2SessionTrackerPtr ses_ptr = processing_flow->find_session(session_id);
         return (!process_data(current_flow_key, nullptr, 0,ses_ptr));
     }
@@ -153,25 +159,25 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     current_flow_state.file_offset = offset;
     current_flow_state.max_offset = offset + max_offset;
     flow_state_mutex.unlock();
-    Dce2Smb2SessionTracker *sess = parent_tree->get_parent();
+    Dce2Smb2SessionTrackersess = parent_tree->get_parent();
     if (parent_tree->get_share_type() != SMB2_SHARE_TYPE_DISK)
     {
-        Dce2Smb2SessionData *current_flow = nullptr;
-            if (sess) 
-           {
-                parent_tree->get_parent()->set_do_not_delete(true);
-                current_flow = parent_tree->get_parent()->get_flow(current_flow_key); 
-               if (!current_flow)
-               {
-                   parent_tree->get_parent()->set_do_not_delete(false);
-                   return false;
-               }
-           }
-           else 
-           {
+        Dce2Smb2SessionData* current_flow = nullptr;
+        if (sess)
+        {
+            parent_tree->get_parent()->set_do_not_delete(true);
+            current_flow = parent_tree->get_parent()->get_flow(current_flow_key);
+            if (!current_flow)
+            {
+                parent_tree->get_parent()->set_do_not_delete(false);
                 return false;
-           }
+            }
+        }
+        else
+        {
+            return false;
+        }
+
         if (data_size > UINT16_MAX)
         {
             data_size = UINT16_MAX;
@@ -253,33 +259,34 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
 
     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);
-
-    FileFlows* file_flows = FileFlows::get_file_flows(processing_flow->get_tcp_flow());
-
-    if (!file_flows)
     {
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, p, "file_flows not found\n");
-        session_tracker->set_do_not_delete(false);
-        return true;
-    }
+        std::lock_guard<std::mutex> guard(process_file_mutex);
+        FileFlows* file_flows = FileFlows::get_file_flows(processing_flow->get_tcp_flow());
 
-    if (updated_flow.first)
-    {
-        // update the new file context in case of flow switch
-        FileContext* file = file_flows->get_file_context(file_name_hash, true, file_id);
-        file->set_file_name(file_name, file_name_len);
-        file->set_file_size(file_size.load() ? file_size.load() : UNKNOWN_FILE_SIZE);
-    }
+        if (!file_flows)
+        {
+            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, p, "file_flows not found\n");
+            session_tracker->set_do_not_delete(false);
+            return true;
+        }
 
-    process_file_mutex.lock();
-    bool continue_processing = file_flows->file_process(p, file_name_hash, file_data, data_size,
-        file_offset, direction, file_id);
-    process_file_mutex.unlock();
-    if (!continue_processing)
-    {
-           SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p, "file_process completed\n");
-        session_tracker->set_do_not_delete(false);
-        return false;
+        if (updated_flow.first)
+        {
+            // update the new file context in case of flow switch
+            FileContext* file = file_flows->get_file_context(file_name_hash, true, file_id);
+            file->set_file_name(file_name, file_name_len);
+            file->set_file_size(file_size.load() ? file_size.load() : UNKNOWN_FILE_SIZE);
+        }
+
+        bool continue_processing = file_flows->file_process(p, file_name_hash, file_data, data_size,
+           file_offset, direction, file_id);
+    
+        if (!continue_processing)
+        {
+               SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL, p, "file_process completed\n");
+            session_tracker->set_do_not_delete(false);
+            return false;
+        }
     }
 
     file_offset += data_size;
index 154ad4813199c97a486db462cfd823d4c04d7994..2a7bb73e43fadff824e28bc736395b307e4c2821 100644 (file)
@@ -157,12 +157,7 @@ void Dce2Smb2TreeTracker::process_close_request(const Smb2Hdr* smb_header,
 
     if (share_type != SMB2_SHARE_TYPE_DISK)
     {
-        if (co_tracker != nullptr)
-        {
-            DCE2_CoCleanTracker(co_tracker);
-            snort_free((void*)co_tracker);
-            co_tracker = nullptr;
-        }
+        DCE2_CoCleanTracker(co_tracker);
     }
 }
 
@@ -453,7 +448,25 @@ void Dce2Smb2TreeTracker::process_ioctl_command(const uint8_t command_type,
     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;
     Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);