]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1149 in SNORT/snort3 from smtp_pending to master
authorHui Cao (huica) <huica@cisco.com>
Wed, 21 Mar 2018 16:26:04 +0000 (12:26 -0400)
committerHui Cao (huica) <huica@cisco.com>
Wed, 21 Mar 2018 16:26:04 +0000 (12:26 -0400)
Squashed commit of the following:

commit 64ee34a53ba68281c11c6728fa5ba15160080610
Author: Michael Altizer (mialtize) <mialtize@cisco.com>
Date:   Tue Mar 13 18:30:44 2018 -0400

    file_api: combine file cache for file resume and partial file processing

12 files changed:
src/file_api/CMakeLists.txt
src/file_api/file_cache.cc
src/file_api/file_cache.h
src/file_api/file_enforcer.cc [deleted file]
src/file_api/file_enforcer.h [deleted file]
src/file_api/file_flows.cc
src/file_api/file_flows.h
src/file_api/file_lib.cc
src/file_api/file_policy.cc
src/file_api/file_service.cc
src/file_api/file_service.h
src/mime/decode_buffer.cc

index b0edfaa4887fde85b680febe374617358fc731af..d26ec94b10f5091214e3a6f126b48c244ed7816a 100644 (file)
@@ -20,8 +20,6 @@ add_library ( file_api OBJECT
     file_cache.cc
     file_cache.h
     file_config.cc 
-    file_enforcer.cc 
-    file_enforcer.h 
     file_flows.cc 
     file_identifier.cc
     file_lib.cc 
index 8bbd52be2dc74416ef4470e644318c091afd48c9..86b061f9bb7407eecaf743e43cf5e33979eab4c1 100644 (file)
 #include "log/messages.h"
 #include "main/snort_config.h"
 #include "main/snort_debug.h"
+#include "main/thread_config.h"
+#include "packet_io/active.h"
 #include "time/packet_time.h"
 
+#include "file_flows.h"
+#include "file_service.h"
 #include "file_stats.h"
 
 using namespace snort;
 
+static int file_cache_anr_free_func(void*, void* data)
+{
+    FileCache::FileNode* node = (FileCache::FileNode*)data;
+
+    if (!node)
+        return 0;
+
+    time_t now = packet_time();
+    // only recycle expired nodes
+    if (now > node->expires)
+    {
+        delete node->file;
+        return 0;
+    }
+    else
+        return 1;
+}
+
 static int file_cache_free_func(void*, void* data)
 {
     FileCache::FileNode* node = (FileCache::FileNode*)data;
     if (node)
     {
         delete node->file;
-        node->file = nullptr;
     }
     return 0;
 }
 
-FileCache::FileCache()
+FileCache::FileCache(int64_t max_files_cached)
 {
-    FileConfig* conf = get_file_config();
-    int max_files;
-    if (conf)
-        max_files = conf->max_files_cached;
-    else
-        max_files = DEFAULT_MAX_FILES_CACHED;
-
+    max_files = max_files_cached;
     fileHash = xhash_new(max_files, sizeof(FileHashKey), sizeof(FileNode),
-        0, 1, nullptr, file_cache_free_func, 1);
+        0, 1, file_cache_anr_free_func, file_cache_free_func, 1);
     if (!fileHash)
         FatalError("Failed to create the expected channel hash table.\n");
     xhash_set_max_nodes(fileHash, max_files);
@@ -68,7 +83,35 @@ FileCache::~FileCache()
     }
 }
 
-FileContext* FileCache::add(const FileHashKey& hashKey)
+void FileCache::set_block_timeout(int64_t timeout)
+{
+    std::lock_guard<std::mutex> lock(cache_mutex);
+    block_timeout = timeout;
+}
+
+void FileCache::set_lookup_timeout(int64_t timeout)
+{
+    std::lock_guard<std::mutex> lock(cache_mutex);
+    lookup_timeout = timeout;
+}
+
+void FileCache::set_max_files(int64_t max)
+{
+    std::lock_guard<std::mutex> lock(cache_mutex);
+
+    int64_t minimal_files = ThreadConfig::get_instance_max() + 1;
+    if (max < minimal_files)
+    {
+        max_files = minimal_files;
+        ErrorMessage("Maximal number of files cached should be greater than "
+            "number of threads\n");
+    }
+    else
+        max_files = max;
+    xhash_set_max_nodes(fileHash, max_files);
+}
+
+FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout)
 {
     FileNode new_node;
     /*
@@ -98,12 +141,11 @@ FileContext* FileCache::add(const FileHashKey& hashKey)
     return new_node.file;
 }
 
-FileContext* FileCache::find(const FileHashKey& hashKey)
+FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout)
 {
     std::lock_guard<std::mutex> lock(cache_mutex);
 
-    // No hash table, or its empty?  Get out of dodge.
-    if ((!fileHash) || (!xhash_count(fileHash)))
+    if (!xhash_count(fileHash))
     {
         DebugMessage(DEBUG_FILE, "No expected sessions\n");
         return nullptr;
@@ -130,7 +172,137 @@ FileContext* FileCache::find(const FileHashKey& hashKey)
         return nullptr;
     }
 
-    node->expires = now + timeout;
+    if (node->expires <  now + timeout)
+        node->expires = now + timeout;
     return node->file;
 }
 
+FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create,
+    int64_t timeout)
+{
+    FileHashKey hashKey;
+    hashKey.dip.set(flow->client_ip);
+    hashKey.sip.set(flow->server_ip);
+    hashKey.padding = 0;
+    hashKey.file_id = file_id;
+    FileContext* file = find(hashKey, timeout);
+    if (to_create and !file)
+       file = add(hashKey, timeout);
+
+    return file;
+}
+
+FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create)
+{
+    return get_file(flow, file_id, to_create, lookup_timeout);
+}
+
+FileVerdict FileCache::check_verdict(Flow* flow, FileInfo* file,
+    FilePolicyBase* policy)
+{
+    assert(file);
+
+    FileVerdict verdict = policy->type_lookup(flow, file);
+
+    if ( file->get_file_sig_sha256() and
+        ((verdict == FILE_VERDICT_UNKNOWN) ||
+        (verdict == FILE_VERDICT_STOP_CAPTURE)))
+    {
+        verdict = policy->signature_lookup(flow, file);
+    }
+
+    if ((verdict == FILE_VERDICT_UNKNOWN) ||
+        (verdict == FILE_VERDICT_STOP_CAPTURE))
+    {
+        verdict = file->verdict;
+    }
+
+    return verdict;
+}
+
+int FileCache::store_verdict(Flow* flow, FileInfo* file, int64_t timeout)
+{
+    assert(file);
+    uint64_t file_id = file->get_file_id();
+
+    if (!file_id)
+        return 0;
+
+    FileContext* file_got = get_file(flow, file_id, true, timeout);
+    if (file_got)
+        *((FileInfo*)(file_got)) = *file;
+    else
+        return -1;
+    return 0;
+}
+
+bool FileCache::apply_verdict(Flow* flow, FileInfo* file, FileVerdict verdict,
+    bool resume, FilePolicyBase* policy)
+{
+    file->verdict = verdict;
+
+    switch (verdict)
+    {
+
+    case FILE_VERDICT_UNKNOWN:
+        return false;
+    case FILE_VERDICT_LOG:
+        if (resume)
+            policy->log_file_action(flow, file, FILE_RESUME_LOG);
+        return false;
+    case FILE_VERDICT_BLOCK:
+         // can't block session inside a session
+         Active::set_delayed_action(Active::ACT_BLOCK, true);
+         break;
+
+    case FILE_VERDICT_REJECT:
+        // can't reset session inside a session
+        Active::set_delayed_action(Active::ACT_RESET, true);
+        break;
+    case FILE_VERDICT_PENDING:
+        Active::set_delayed_action(Active::ACT_DROP, true);
+        if (resume)
+            policy->log_file_action(flow, file, FILE_RESUME_BLOCK);
+        else
+        {
+            store_verdict(flow, file, lookup_timeout);
+            FileFlows* files = FileFlows::get_file_flows(flow);
+            if (files)
+                files->add_pending_file(file->get_file_id());
+        }
+        return true;
+    default:
+        return false;
+    }
+
+    if (resume)
+        policy->log_file_action(flow, file, FILE_RESUME_BLOCK);
+    else
+        store_verdict(flow, file, block_timeout);
+    return true;
+
+}
+
+FileVerdict FileCache::cached_verdict_lookup(Flow* flow, FileInfo* file,
+    FilePolicyBase* policy)
+{
+    FileVerdict verdict = FILE_VERDICT_UNKNOWN;
+
+    assert(file);
+    uint64_t file_id = file->get_file_id();
+    if (!file_id)
+        return verdict;
+
+    FileContext* file_found = get_file(flow, file_id, false);
+
+    if (file_found)
+    {
+        DebugMessage(DEBUG_FILE, "Found resumed file\n");
+        /*Query the file policy in case verdict has been changed*/
+        verdict = check_verdict(flow, file_found, policy);
+        apply_verdict(flow, file_found, verdict, true, policy);
+    }
+
+    return verdict;
+}
+
index 330388c130724909f8ba67ecb2a8f5659f2da22e..50f66f0e2852ec7169604be813a6c60df0f027ca 100644 (file)
 #include "file_config.h"
 
 struct XHash;
+struct XHashNode;
 
 class FileCache
 {
 public:
-// FIXIT-L Merge definition with duplicate in file_enforcer.h?
+
 PADDING_GUARD_BEGIN
     struct FileHashKey
     {
         snort::SfIp sip;
         snort::SfIp dip;
         uint32_t padding;
-        uint64_t file_sig;
+        uint64_t file_id;
     };
 PADDING_GUARD_END
 
@@ -50,15 +51,31 @@ PADDING_GUARD_END
         snort::FileContext* file;
     };
 
-    FileCache();
+    FileCache(int64_t max_files_cached);
     ~FileCache();
-    snort::FileContext* add(const FileHashKey&);
-    snort::FileContext* find(const FileHashKey&);
+
+    void set_block_timeout(int64_t);
+    void set_lookup_timeout(int64_t);
+    void set_max_files(int64_t);
+
+    snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create);
+    FileVerdict cached_verdict_lookup(snort::Flow*, snort::FileInfo*,
+        snort::FilePolicyBase*);
+    bool apply_verdict(snort::Flow*, snort::FileInfo*, FileVerdict, bool resume,
+        snort::FilePolicyBase*);
 
 private:
+    snort::FileContext* add(const FileHashKey&, int64_t timeout);
+    snort::FileContext* find(const FileHashKey&, int64_t);
+    snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create, int64_t timeout);
+    FileVerdict check_verdict(snort::Flow*, snort::FileInfo*, snort::FilePolicyBase*);
+    int store_verdict(snort::Flow*, snort::FileInfo*, int64_t timeout);
+
     /* The hash table of expected files */
     XHash* fileHash = nullptr;
-    uint32_t timeout = DEFAULT_FILE_BLOCK_TIMEOUT;
+    int64_t block_timeout = DEFAULT_FILE_BLOCK_TIMEOUT;
+    int64_t lookup_timeout = DEFAULT_FILE_LOOKUP_TIMEOUT;
+    int64_t max_files = DEFAULT_MAX_FILES_CACHED;
     std::mutex cache_mutex;
 };
 
diff --git a/src/file_api/file_enforcer.cc b/src/file_api/file_enforcer.cc
deleted file mode 100644 (file)
index 3e3beb8..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2012-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
-// 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.
-//--------------------------------------------------------------------------
-/*
- **  Author(s):  Hui Cao <huica@cisco.com>
- **
- **  NOTES
- **  9.25.2012 - Initial Source Code. Hui Cao
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "file_enforcer.h"
-
-#include "log/messages.h"
-#include "main/snort_debug.h"
-#include "packet_io/active.h"
-#include "time/packet_time.h"
-
-#include "file_service.h"
-
-using namespace snort;
-
-static int file_node_free_func(void*, void* data)
-{
-    FileEnforcer::FileNode* node = (FileEnforcer::FileNode*)data;
-    assert(node);
-    delete node->file;
-    node->file = nullptr;
-    return 0;
-}
-
-FileEnforcer::FileEnforcer()
-{
-    fileHash = xhash_new(MAX_FILES_TRACKED, sizeof(FileHashKey), sizeof(FileNode),
-        MAX_MEMORY_USED, 1, nullptr, file_node_free_func, 1);
-    if (!fileHash)
-        FatalError("Failed to create the expected channel hash table.\n");
-}
-
-FileEnforcer::~FileEnforcer()
-{
-    if (fileHash)
-    {
-        xhash_delete(fileHash);
-    }
-}
-
-void FileEnforcer::update_file_node(FileNode* node, FileInfo* file)
-{
-    *(node->file) = *file;
-}
-
-FileVerdict FileEnforcer::check_verdict(snort::Flow* flow, FileNode* node,
-    XHashNode* hash_node, FilePolicyBase* policy)
-{
-    assert(node->file);
-
-    FileVerdict verdict = policy->type_lookup(flow, node->file);
-
-    if ((verdict == FILE_VERDICT_UNKNOWN) ||
-        (verdict == FILE_VERDICT_STOP_CAPTURE))
-    {
-        verdict = policy->signature_lookup(flow, node->file);
-    }
-
-    if ((verdict == FILE_VERDICT_UNKNOWN) ||
-        (verdict == FILE_VERDICT_STOP_CAPTURE))
-    {
-        verdict = node->file->verdict;
-    }
-
-    if (verdict == FILE_VERDICT_LOG)
-    {
-        xhash_free_node(fileHash, hash_node);
-    }
-
-    return verdict;
-}
-
-int FileEnforcer::store_verdict(snort::Flow* flow, FileInfo* file)
-{
-    assert(file);
-    uint64_t file_sig = file->get_file_id();
-
-    if (!file_sig)
-        return 0;
-
-    time_t now = packet_time();
-    FileHashKey hashKey;
-    hashKey.dip.set(flow->client_ip);
-    hashKey.sip.set(flow->server_ip);
-    hashKey.padding = 0;
-    hashKey.file_sig = file_sig;
-
-    FileNode* node;
-    XHashNode* hash_node = xhash_find_node(fileHash, &hashKey);
-    if (hash_node)
-    {
-        if (!(node = (FileNode*)hash_node->data))
-            xhash_free_node(fileHash, hash_node);
-    }
-    else
-        node = nullptr;
-
-    if (node)
-    {
-        node->expires = now + timeout;
-        update_file_node(node, file);
-    }
-    else
-    {
-        FileNode new_node;
-        DebugMessage(DEBUG_FILE, "Adding file node\n");
-
-        new_node.file = new FileInfo();
-
-        update_file_node(&new_node, file);
-
-        /*
-         * use the time that we keep files around
-         * since this info would effectively be invalid
-         * after that anyway because the file that
-         * caused this will be gone.
-         */
-        new_node.expires = now + timeout;
-
-        /* Add it to the table */
-        if (xhash_add(fileHash, &hashKey, &new_node) != XHASH_OK)
-        {
-            /* Uh, shouldn't get here...
-             * There is already a node or couldn't alloc space
-             * for key.  This means bigger problems, but fail
-             * gracefully.
-             */
-            DebugMessage(DEBUG_FILE,
-                "Failed to add file node to hash table\n");
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-bool FileEnforcer::apply_verdict(Flow* flow, FileInfo* file, FileVerdict verdict,
-    bool resume, FilePolicyBase* policy)
-{
-    if ( verdict == FILE_VERDICT_UNKNOWN )
-        return false;
-
-    file->verdict = verdict;
-
-    if (verdict == FILE_VERDICT_LOG)
-    {
-        if (resume)
-            policy->log_file_action(flow, file, FILE_RESUME_LOG);
-    }
-    else if (verdict == FILE_VERDICT_BLOCK)
-    {
-        // can't block session inside a session
-        snort::Active::set_delayed_action(Active::ACT_BLOCK, true);
-        store_verdict(flow, file);
-        if (resume)
-            policy->log_file_action(flow, file, FILE_RESUME_BLOCK);
-        return true;
-    }
-    else if (verdict == FILE_VERDICT_REJECT)
-    {
-        // can't reset session inside a session
-        snort::Active::set_delayed_action(Active::ACT_RESET, true);
-        store_verdict(flow, file);
-        if (resume)
-            policy->log_file_action(flow, file, FILE_RESUME_BLOCK);
-        return true;
-    }
-    else if (verdict == FILE_VERDICT_PENDING)
-    {
-        /*Take the cached verdict*/
-        snort::Active::set_delayed_action(Active::ACT_DROP, true);
-        if (resume)
-            policy->log_file_action(flow, file, FILE_RESUME_BLOCK);
-        return true;
-    }
-
-    return false;
-}
-
-FileVerdict FileEnforcer::cached_verdict_lookup(snort::Flow* flow, FileInfo* file,
-    FilePolicyBase* policy)
-{
-    FileVerdict verdict = FILE_VERDICT_UNKNOWN;
-    XHashNode* hash_node;
-    FileNode* node;
-
-    /* No hash table, or its empty?  Get out of dodge.  */
-    if ((!fileHash) || (!xhash_count(fileHash)))
-    {
-        DebugMessage(DEBUG_FILE, "No expected sessions\n");
-        return verdict;
-    }
-
-    assert(file);
-    uint64_t file_sig = file->get_file_id();
-    if (!file_sig)
-        return verdict;
-
-    FileHashKey hashKey;
-    hashKey.dip.set(flow->client_ip);
-    hashKey.sip.set(flow->server_ip);
-    hashKey.padding = 0;
-    hashKey.file_sig = file_sig;
-
-    hash_node = xhash_find_node(fileHash, &hashKey);
-
-    if (hash_node)
-    {
-        if (!(node = (FileNode*)hash_node->data))
-            xhash_free_node(fileHash, hash_node);
-    }
-    else
-        return verdict;
-
-    if (node && node->file)
-    {
-        DebugMessage(DEBUG_FILE, "Found resumed file\n");
-        if (node->expires && packet_time() > node->expires)
-        {
-            DebugMessage(DEBUG_FILE, "File expired\n");
-            xhash_free_node(fileHash, hash_node);
-            return verdict;
-        }
-        /*Query the file policy in case verdict has been changed*/
-        verdict = check_verdict(flow, node, hash_node, policy);
-        apply_verdict(flow, node->file, verdict, true, policy);
-    }
-
-    return verdict;
-}
-
diff --git a/src/file_api/file_enforcer.h b/src/file_api/file_enforcer.h
deleted file mode 100644 (file)
index 170ece7..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2012-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
-// 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.
-//--------------------------------------------------------------------------
-
-// file_enforcer.h author Hui Cao <huica@cisco.com>
-
-#ifndef FILE_ENFORCER_H
-#define FILE_ENFORCER_H
-
-// If a file transferred through HTTP is blocked, a new session might be created
-// to request the file data left. To block the new session, we use URL and IPs
-// to continue blocking the same file.
-
-#include "hash/xhash.h"
-#include "sfip/sf_ip.h"
-#include "utils/cpp_macros.h"
-
-#include "file_config.h"
-#include "file_policy.h"
-
-namespace snort
-{
-class FileInfo;
-class FilePolicyBase;
-class Flow;
-}
-
-#define MAX_FILES_TRACKED 16384
-#define MAX_MEMORY_USED (10*1024*1024)  // 10M
-
-class FileEnforcer
-{
-public:
-    struct FileNode
-    {
-        time_t expires;
-        snort::FileInfo* file;
-    };
-
-    FileEnforcer();
-    ~FileEnforcer();
-    FileVerdict cached_verdict_lookup(snort::Flow*, snort::FileInfo*, snort::FilePolicyBase*);
-    bool apply_verdict(snort::Flow*, snort::FileInfo*, FileVerdict, bool resume, snort::FilePolicyBase*);
-
-private:
-// FIXIT-L Merge definition with duplicate in file_cache.h?
-PADDING_GUARD_BEGIN
-    struct FileHashKey
-    {
-        snort::SfIp sip;
-        snort::SfIp dip;
-        uint32_t padding;
-        uint64_t file_sig;
-    };
-PADDING_GUARD_END
-
-    void update_file_node(FileNode*, snort::FileInfo*);
-    FileVerdict check_verdict(snort::Flow*, FileNode*, XHashNode*, snort::FilePolicyBase*);
-    int store_verdict(snort::Flow*, snort::FileInfo*);
-
-    /* The hash table of expected files */
-    XHash* fileHash = nullptr;
-    uint32_t timeout = DEFAULT_FILE_BLOCK_TIMEOUT;
-};
-
-#endif
-
index 38b713e1c05a7a7d8793808237e97e63a1f1d649..a4df7afa43d043474fe50b2063cf8c5b90558e7b 100644 (file)
@@ -35,7 +35,6 @@
 
 #include "file_cache.h"
 #include "file_config.h"
-#include "file_enforcer.h"
 #include "file_lib.h"
 #include "file_service.h"
 
@@ -49,14 +48,14 @@ void FileFlows::handle_retransmit (Packet*)
     if (file_policy == nullptr)
         return;
 
-    FileContext* file = get_current_file_context();
+    FileContext* file = get_file_context(pending_file_id, false);
     if ((file == nullptr) or (file->verdict != FILE_VERDICT_PENDING))
         return;
 
     FileVerdict verdict = file_policy->signature_lookup(flow, file);
-    FileEnforcer* file_enforcer = FileService::get_file_enforcer();
-    if (file_enforcer)
-        file_enforcer->apply_verdict(flow, file, verdict, false,file_policy);
+    FileCache* file_cache = FileService::get_file_cache();
+    if (file_cache)
+        file_cache->apply_verdict(flow, file, verdict, false, file_policy);
     file->log_file_event(flow, file_policy);
 }
 
@@ -119,12 +118,6 @@ uint64_t FileFlows::get_new_file_instance()
 
 FileFlows::~FileFlows()
 {
-    /*Clean up all the file contexts*/
-    if ( pending_context and (main_context != pending_context))
-    {
-        delete(pending_context);
-    }
-
     delete(main_context);
 }
 
@@ -159,17 +152,7 @@ FileContext* FileFlows::get_file_context(uint64_t file_id, bool to_create)
     FileCache* file_cache = FileService::get_file_cache();
     assert(file_cache);
 
-    FileCache::FileHashKey key;
-    key.dip.set(flow->client_ip);
-    key.sip.set(flow->server_ip);
-    key.padding = 0;
-    key.file_sig = file_id;
-
-    FileContext* context = file_cache->find(key);
-
-    if (!context && to_create)
-        context = file_cache->add(key);
-
+    FileContext* context = file_cache->get_file(flow, file_id, to_create);
     current_file_id = file_id;
     return context;
 }
@@ -258,6 +241,10 @@ void FileFlows::set_file_name(const uint8_t* fname, uint32_t name_size)
     }
 }
 
+void FileFlows::add_pending_file(uint64_t file_id)
+{
+    current_file_id = pending_file_id = file_id;
+}
 namespace snort
 {
 FilePosition get_file_position(Packet* pkt)
@@ -288,6 +275,22 @@ FileInspect:: ~FileInspect()
         delete config;
 }
 
+bool FileInspect::configure(SnortConfig*)
+{
+    if (!config)
+        return true;
+
+    FileCache* file_cache = FileService::get_file_cache();
+    if (file_cache)
+    {
+        file_cache->set_block_timeout(config->file_block_timeout);
+        file_cache->set_lookup_timeout(config->file_lookup_timeout);
+        file_cache->set_max_files(config->max_files_cached);
+    }
+
+    return true;
+}
+
 static Module* mod_ctor()
 { return new FileIdModule; }
 
index 592276f7e82bea0f9830a6821ba9031678816cb4..4f794f02c526feedd73aee1621fa6228f4b84aff 100644 (file)
@@ -42,7 +42,7 @@ public:
     FileInspect(FileIdModule*);
     ~FileInspect() override;
     void eval(Packet*) override { }
-
+    bool configure(SnortConfig*) override;
     FileConfig* config;
 };
 
@@ -77,6 +77,8 @@ public:
         gen_signature = enable;
     }
 
+    void add_pending_file(uint64_t file_id);
+
     // This is used when there is only one file per session
     bool file_process(const uint8_t* file_data, int data_size, FilePosition,
         bool upload, size_t file_index = 0);
@@ -94,9 +96,9 @@ private:
     void init_file_context(FileDirection, FileContext*);
     FileContext* find_main_file_context(FilePosition, FileDirection, size_t id = 0);
     FileContext* main_context = nullptr;
-    FileContext* pending_context = nullptr;
     FileContext* current_context = nullptr;
     uint64_t current_file_id = 0;
+    uint64_t pending_file_id = 0;
     bool gen_signature = false;
     Flow* flow = nullptr;
     FilePolicyBase* file_policy = nullptr;
index 3f0ad64d57528988b87f5e7e6d667ed0d501cd7d..1e85dd6219f66916c036a53a161d9c0539b928b7 100644 (file)
@@ -44,7 +44,7 @@
 #include "file_api.h"
 #include "file_capture.h"
 #include "file_config.h"
-#include "file_enforcer.h"
+#include "file_cache.h"
 #include "file_flows.h"
 #include "file_service.h"
 #include "file_segment.h"
@@ -106,6 +106,7 @@ void FileInfo::copy(const FileInfo& other)
     file_type_id = other.file_type_id;
     file_id = other.file_id;
     file_name = other.file_name;
+    file_name_set = other.file_name_set;
     verdict = other.verdict;
     file_type_enabled = other.file_type_enabled;
     file_signature_enabled = other.file_signature_enabled;
@@ -358,9 +359,9 @@ void FileContext::finish_signature_lookup(Flow* flow, bool final_lookup, FilePol
         verdict = policy->signature_lookup(flow, this);
         if ( verdict != FILE_VERDICT_UNKNOWN || final_lookup )
         {
-            FileEnforcer* file_enforcer = FileService::get_file_enforcer();
-            if (file_enforcer)
-                file_enforcer->apply_verdict(flow, this, verdict, false, policy);
+            FileCache* file_cache = FileService::get_file_cache();
+            if (file_cache)
+                file_cache->apply_verdict(flow, this, verdict, false, policy);
             log_file_event(flow, policy);
             config_file_signature(false);
             file_stats->signatures_processed[get_file_type()][get_file_direction()]++;
@@ -419,7 +420,7 @@ bool FileContext::process(Flow* flow, const uint8_t* file_data, int data_size,
         return false;
     }
 
-    if ((FileService::get_file_enforcer()->cached_verdict_lookup(flow, this,
+    if ((FileService::get_file_cache()->cached_verdict_lookup(flow, this,
         policy) != FILE_VERDICT_UNKNOWN))
         return true;
 
@@ -446,9 +447,9 @@ bool FileContext::process(Flow* flow, const uint8_t* file_data, int data_size,
             FileVerdict v = policy->type_lookup(flow, this);
             if ( v != FILE_VERDICT_UNKNOWN )
             {
-                FileEnforcer* file_enforcer = FileService::get_file_enforcer();
-                if (file_enforcer)
-                    file_enforcer->apply_verdict(flow, this, v, false, policy);
+                FileCache* file_cache = FileService::get_file_cache();
+                if (file_cache)
+                    file_cache->apply_verdict(flow, this, v, false, policy);
             }
 
             log_file_event(flow, policy);
index 4dfac414f54bc7c0f0b6f3c3c96aec94b201e542..e072455d9010c9c09cec95cd129e3e04ca201288 100644 (file)
@@ -27,7 +27,7 @@
 #include "hash/hashes.h"
 
 #include "file_capture.h"
-#include "file_enforcer.h"
+#include "file_lib.h"
 #include "file_service.h"
 
 using namespace snort;
index b8d1435cd268f8cce995f5b34ba6149cdfcc14a6..27a81da471d8cb6344631381b635285d4f176130 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "file_cache.h"
 #include "file_capture.h"
-#include "file_enforcer.h"
 #include "file_flows.h"
 #include "file_stats.h"
 
@@ -45,7 +44,6 @@ bool FileService::file_signature_enabled = false;
 bool FileService::file_capture_enabled = false;
 bool FileService::file_processing_initiated = false;
 
-FileEnforcer* FileService::file_enforcer = nullptr;
 FileCache* FileService::file_cache = nullptr;
 
 void FileService::init()
@@ -61,14 +59,15 @@ void FileService::post_init()
     if (!conf)
         return;
 
+    if (!file_cache)
+        file_cache = new FileCache(conf->max_files_cached);
+
     if (file_capture_enabled)
         FileCapture::init(conf->capture_memcap, conf->capture_block_size);
 }
 
 void FileService::close()
 {
-    if (file_enforcer)
-        delete file_enforcer;
     if (file_cache)
         delete file_cache;
 
@@ -82,42 +81,21 @@ void FileService::thread_init()
 void FileService::thread_term()
 { file_stats_term(); }
 
-void FileService::start_file_processing()
-{
-    if (!file_processing_initiated)
-    {
-        file_enforcer = new FileEnforcer;
-        file_cache = new FileCache;
-        file_processing_initiated = true;
-    }
-}
-
 void FileService::enable_file_type()
 {
-    if (!file_type_id_enabled)
-    {
-        file_type_id_enabled = true;
-        start_file_processing();
-    }
+    file_type_id_enabled = true;
 }
 
 void FileService::enable_file_signature()
 {
-    if (!file_signature_enabled)
-    {
-        file_signature_enabled = true;
-        start_file_processing();
-    }
+    file_signature_enabled = true;
 }
 
 /* Enable file capture, also enable file signature */
 void FileService::enable_file_capture()
 {
-    if (!file_capture_enabled)
-    {
-        file_capture_enabled = true;
-        enable_file_signature();
-    }
+    file_capture_enabled = true;
+    enable_file_signature();
 }
 
 bool FileService::is_file_service_enabled()
index 1ad4442d54d10d1b1726c4cd2666031610d93e83..bba93e9adb2cfc57ef04e921ba2e703cb1d051f4 100644 (file)
@@ -56,16 +56,13 @@ public:
     static bool is_file_service_enabled();
     static int64_t get_max_file_depth();
 
-    static FileEnforcer* get_file_enforcer() { return file_enforcer; }
     static FileCache* get_file_cache() { return file_cache; }
 
 private:
-    static void start_file_processing();
     static bool file_type_id_enabled;
     static bool file_signature_enabled;
     static bool file_capture_enabled;
     static bool file_processing_initiated;
-    static FileEnforcer* file_enforcer;
     static FileCache* file_cache;
 };
 } // namespace snort
index c644dab9a31806e3933e1184aa9eb8731c599df0..7f01ffb7c75c39eb19343dbd4b630ed8f9f0758c 100644 (file)
@@ -110,8 +110,8 @@ DecodeBuffer::DecodeBuffer(int max_depth)
     if (max_depth < 0)
         return;
 
-    encodeBuf = (uint8_t*)snort_calloc(buf_size);
-    decodeBuf = (uint8_t*)snort_calloc(buf_size);
+    encodeBuf = (uint8_t*)snort_alloc(buf_size);
+    decodeBuf = (uint8_t*)snort_alloc(buf_size);
 }
 
 DecodeBuffer::~DecodeBuffer()