]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2966 in SNORT/snort3 from ~VKAMBALA/snort3:eicar to master
authorBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 5 Jul 2021 06:47:23 +0000 (06:47 +0000)
committerBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Mon, 5 Jul 2021 06:47:23 +0000 (06:47 +0000)
Squashed commit of the following:

commit bd1c2d1e18fa3ec4e1efac72f0ea924a9b252407
Author: krishnakanth <vkambala@cisco.com>
Date:   Thu Jul 1 05:06:31 2021 -0400

    dce_rpc: Handling raw packets

src/file_api/file_lib.cc
src/file_api/file_segment.cc
src/file_api/file_segment.h
src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb2_file.cc
src/service_inspectors/dce_rpc/dce_smb2_file.h
src/service_inspectors/dce_rpc/dce_smb2_tree.cc

index 54d58ee02fe4255a357d8da7b4a9f16bf3cfa7a9..425b4cab49b2225ab0a0a4148ee47db28d834dc1 100644 (file)
@@ -450,6 +450,10 @@ bool FileContext::process(Packet* p, const uint8_t* file_data, int data_size,
                 PacketTracer::log("File: Type-%s found\n",
                     file_type_name(get_file_type()).c_str());
             config_file_type(false);
+
+            if (PacketTracer::is_active() and (!(is_file_signature_enabled())))
+                PacketTracer::log("File: signature config is disabled\n");
+
             file_stats->files_processed[get_file_type()][get_file_direction()]++;
             //Check file type based on file policy
             FileVerdict v = policy->type_lookup(p, this);
index fffcb6074a7acfd87aacae1c64d7435a0df40491..1a879ba4b1ccd826d3367ceed3c4ddb880049988 100644 (file)
@@ -61,14 +61,13 @@ void FileSegments::clear()
 }
 
 // Update the segment list based on new data
-void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t offset)
+void FileSegments::add(const uint8_t* file_data, int64_t data_size, uint64_t offset)
 {
-    FileSegment* new_segment = new FileSegment();
-    new_segment->offset = offset;
-    new_segment->data = new std::string((const char*)file_data, data_size);
-
     if (!head)
     {
+        FileSegment* new_segment = new FileSegment();
+        new_segment->offset = offset;
+        new_segment->data = new std::string((const char*)file_data, data_size);
         head = new_segment;
         return;
     }
@@ -80,7 +79,6 @@ void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t of
     FileSegment* left = nullptr;
     FileSegment* previous = nullptr;
     bool find_left = false;
-    bool is_overlap = false;
 
     // Find left boundary, left points to segment that needs update
     while (current_segment)
@@ -99,41 +97,65 @@ void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t of
     // New segment should be at the end of link list
     if (!find_left)
     {
-        previous->next = new_segment;
+        left = previous;
+        if (left->offset +left->data->size() >start)
+        {
+            offset = left->offset + left->data->size();
+            data_size = end -offset;
+            file_data = file_data + offset - start;
+        }
     }
     // New segment should be at the start of link list
     else if (!left)
     {
-        if (end <= head->offset)
+        if (end > head->offset)
         {
-            new_segment->next = head;
-            head = new_segment;
-        }
-        else
-        {
-            is_overlap = true;
+            /* Overlap, trim off extra data from end */
+            data_size = head->offset - offset;
         }
     }
     else
     {
-        if ((left->offset + left->data->size() > start) ||
-            (left->next->offset < end))
+        //Left Overlap
+        if ( (left->offset + left->data->size() > start)  )
         {
-            is_overlap = true;
+            offset = left->offset + left->data->size();
+            data_size = end - offset;
+            file_data = file_data + offset - start;
         }
-        else
+        //Right Overlap
+        if ( (left->next->offset < end) )
         {
-            new_segment->next = left->next;
-            left->next = new_segment;
+            data_size = left->next->offset - offset;
         }
+
     }
 
     // ignore overlap case
-    if (is_overlap)
+    if (data_size <= 0)
     {
-        delete new_segment;
         return;
     }
+
+    FileSegment* new_segment = new FileSegment();
+    new_segment->offset = offset;
+    new_segment->data = new std::string((const char*)file_data, data_size);
+
+    if (!find_left)
+    {
+        previous->next = new_segment;
+
+    }
+    else if (!left)
+    {
+        new_segment->next = head;
+        head = new_segment;
+    }
+    else
+    {
+        new_segment->next = left->next;
+        left->next = new_segment;
+    }
 }
 
 FilePosition FileSegments::get_file_position(uint64_t data_size, uint64_t file_size)
index b52e4214be896209cb3e73eb91ab622f0d95a8f3..39a59e1eafab24ae4c44d47eff2ba72d2981eea9 100644 (file)
@@ -62,7 +62,7 @@ private:
     uint64_t current_offset;
     snort::FileContext* context = nullptr;
 
-    void add(const uint8_t* file_data, uint64_t data_size, uint64_t offset);
+    void add(const uint8_t* file_data, int64_t data_size, uint64_t offset);
     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 7e985db0d85fb51ef80b81ceb9f36ea2086f07c5..0fba9cc5cc18fe2993bba63368d4383b0f7d5fb3 100644 (file)
@@ -248,7 +248,7 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
             const Smb2NegotiateResponseHdr* neg_resp_hdr = (const Smb2NegotiateResponseHdr*)smb_data;
             if (neg_resp_hdr->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)
             {
-                Packet *p = DetectionEngine::get_current_packet();
+                Packetp = DetectionEngine::get_current_packet();
                 Dce2SmbFlowData* fd =
                     create_expected_smb_flow_data(p, (dce2SmbProtoConf *)sd.config);
                 if (fd)
@@ -439,7 +439,9 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr,
                 session->process(command, SMB2_CMD_TYPE_RESPONSE, smb_hdr, end, flow_key);
             }
             else
+            {
                 SMB2_HANDLE_INVALID_STRUC_SIZE(ioctl)
+            }
         }
         break;
     default:
@@ -509,11 +511,16 @@ void Dce2Smb2SessionData::process()
     else
     {
         tcp_file_tracker_mutex.lock();
-        if ( tcp_file_tracker and tcp_file_tracker->accepting_raw_data())
+        if ( tcp_file_tracker and tcp_file_tracker->accepting_raw_data_from(flow_key))
         {
             debug_logf(dce_smb_trace, 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);
+            tcp_file_tracker->stop_accepting_raw_data_from(flow_key);
+        }
+        else
+        {
+            debug_logf(dce_smb_trace, p, "not processing raw data\n");
         }
         tcp_file_tracker_mutex.unlock();
     }
index d74ca11ae2afe48aa586083c805b0ee2c118878a..c4e1e97001b15e85d41f34d321bc5ab724bccf1b 100644 (file)
@@ -35,14 +35,30 @@ using namespace snort;
 
 #define UNKNOWN_FILE_SIZE  (~0)
 
-void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow)
+void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow, uint64_t offset)
 {
     if (flow)
     {
-        smb2_pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
+        uint32_t current_flow_key = flow->get_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.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(this);
     }
 }
+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()
 {
@@ -102,7 +118,9 @@ void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint6
 
 bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key)
 {
-    uint64_t file_offset = file_offsets[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;
@@ -117,9 +135,13 @@ bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key)
 }
 
 bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const uint8_t* file_data,
-    uint32_t data_size, const uint64_t offset)
+    uint32_t data_size, const uint64_t offset, uint64_t max_offset)
 {
-    file_offsets[current_flow_key] = 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();
     return process_data(current_flow_key, file_data, data_size);
 }
 
@@ -141,7 +163,10 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
 
     int64_t file_detection_depth = current_flow->get_smb_file_depth();
     int64_t detection_size = 0;
-    uint64_t file_offset = file_offsets[current_flow_key];
+    Packet* p = DetectionEngine::get_current_packet();
+    flow_state_mutex.lock();
+    uint64_t file_offset = flow_state[current_flow_key].file_offset;
+    flow_state_mutex.unlock();
 
     if (file_detection_depth == 0)
         detection_size = data_size;
@@ -163,8 +188,6 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     if (ignore)
         return true;
 
-    Packet* p = DetectionEngine::get_current_packet();
-
     if (file_size and file_offset > file_size)
     {
         debug_logf(dce_smb_trace, p, "file_process: bad offset\n");
@@ -202,7 +225,9 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui
     }
 
     file_offset += data_size;
-    file_offsets[current_flow_key] = file_offset;
+    flow_state_mutex.lock();
+    flow_state[current_flow_key].file_offset = file_offset;
+    flow_state_mutex.unlock();
     return true;
 }
 
index c5aa334d1ea7455bc3b7f937b45c71242816b4a0..55baa7375efee181c70bb499ed5318d00676bacf 100644 (file)
 
 class Dce2Smb2TreeTracker;
 
+typedef struct _tcp_flow_state
+{
+    Dce2SmbPduState pdu_state;
+    uint64_t file_offset;
+    uint64_t max_offset;
+} tcp_flow_state;
+
 class Dce2Smb2FileTracker
 {
 public:
@@ -38,20 +45,24 @@ public:
     Dce2Smb2FileTracker(uint64_t file_idv, const uint32_t flow_key, Dce2Smb2TreeTracker* p_tree) :
         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), smb2_pdu_state(DCE2_SMB_PDU_STATE__COMMAND), parent_tree(p_tree)
+        direction(FILE_DOWNLOAD), parent_tree(p_tree)
     {
         debug_logf(dce_smb_trace, 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);
+    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);
     bool close(const uint32_t);
     void set_info(char*, uint16_t, uint64_t);
-    void accept_raw_data_from(Dce2Smb2SessionData*);
-    bool accepting_raw_data()
-    { return (smb2_pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA); }
+    void accept_raw_data_from(Dce2Smb2SessionData*, uint64_t = 0);
+    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; }
     Dce2Smb2TreeTracker* get_parent() { return parent_tree; }
@@ -68,10 +79,10 @@ private:
     uint64_t file_name_hash;
     char* file_name;
     FileDirection direction;
-    std::atomic<Dce2SmbPduState> smb2_pdu_state;
     Dce2Smb2TreeTracker* parent_tree;
-    std::unordered_map<uint32_t, uint64_t,std::hash<uint32_t> > file_offsets;
+    std::unordered_map<uint32_t, tcp_flow_state, std::hash<uint32_t> > flow_state;
     std::mutex process_file_mutex;
+    std::mutex flow_state_mutex;
 };
 
 using  Dce2Smb2FileTrackerMap =
index 8fa45c417fa5dd52c502ea795fac94e07bf855b5..57582e363c41e173dfe70649434b1b0003ccae76 100644 (file)
@@ -309,8 +309,12 @@ void Dce2Smb2TreeTracker::process_read_response(const uint64_t message_id,
     {
         const uint8_t* file_data =  (const uint8_t*)read_resp_hdr +
             SMB2_READ_RESPONSE_STRUC_SIZE - 1;
-        int data_size = end - file_data;
-        if (file_tracker->process_data(current_flow_key, file_data, data_size, read_request->get_offset()))
+        // 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)))
             {
@@ -338,6 +342,19 @@ void Dce2Smb2TreeTracker::process_read_request(const uint64_t message_id,
         debug_logf(dce_smb_trace, GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: store failed\n");
         delete read_request;
     }
+    Dce2Smb2FileTracker* file_tracker = find_file(file_id);
+    Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key);
+    if (file_tracker)
+    {
+        debug_logf(dce_smb_trace, GET_CURRENT_PACKET,
+            "SMB2_COM_READ_REQ: start accepting Raw Data\n");
+        file_tracker->accept_raw_data_from(current_flow,offset);
+    }
+    else
+    {
+        debug_logf(dce_smb_trace, GET_CURRENT_PACKET,
+            "SMB2_COM_READ_REQ: file tracker missing\n");
+    }
 }
 
 void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
@@ -365,9 +382,13 @@ void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id,
     if (file_tracker)
     {
         file_tracker->set_direction(FILE_UPLOAD);
-        int data_size = end - file_data;
+        // 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))
+        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)))
             {