]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #652 in SNORT/snort3 from file_mime to master
authorHui Cao (huica) <huica@cisco.com>
Tue, 4 Oct 2016 16:22:04 +0000 (12:22 -0400)
committerHui Cao (huica) <huica@cisco.com>
Tue, 4 Oct 2016 16:22:04 +0000 (12:22 -0400)
Squashed commit of the following:

commit 908af0c0d4393fdc06032f3abf9e8a38b9f61c80
Author: huica <huica@cisco.com>
Date:   Fri Sep 30 15:09:11 2016 -0400

    Support http file upload processing and process decode/detection depths

29 files changed:
src/file_api/circular_buffer.cc
src/file_api/file_capture.h
src/file_api/file_enforcer.cc
src/file_api/file_mempool.cc
src/file_api/file_service.cc
src/mime/decode_b64.cc
src/mime/decode_b64.h
src/mime/decode_base.cc
src/mime/decode_base.h
src/mime/decode_bit.cc
src/mime/decode_bit.h
src/mime/decode_buffer.cc
src/mime/decode_buffer.h
src/mime/decode_qp.cc
src/mime/decode_qp.h
src/mime/decode_uu.cc
src/mime/decode_uu.h
src/mime/file_mime_config.cc
src/mime/file_mime_config.h
src/mime/file_mime_decode.cc
src/mime/file_mime_log.cc
src/mime/file_mime_log.h
src/mime/file_mime_paf.cc
src/mime/file_mime_paf.h
src/mime/file_mime_process.cc
src/mime/file_mime_process.h
src/service_inspectors/http_inspect/http_msg_body.cc
src/service_inspectors/http_inspect/http_msg_header.cc
src/service_inspectors/http_inspect/http_stream_splitter_scan.cc

index 3189bf5635030887700c7cb83295c24f9a094b74..d36d16eac8ced28273b1390706c11cae1bb6ecf0 100644 (file)
@@ -59,7 +59,7 @@ CircularBuffer* cbuffer_init(uint64_t size)
     if (!cb->elems)
     {
         snort_free(cb);
-        return NULL;
+        return nullptr;
     }
 
     return cb;
@@ -70,7 +70,7 @@ void cbuffer_free(CircularBuffer* cb)
     if (cb && cb->elems)
     {
         snort_free(cb->elems);
-        cb->elems = NULL;
+        cb->elems = nullptr;
     }
 
     snort_free(cb);
index ce824284aa6b3a80cda80251a2c3d1c61e7ccd32..df3db60b6bac1572838a9af42c6602eaf36a752a 100644 (file)
@@ -67,10 +67,10 @@ public:
     bool is_reserved() { return reserved; }
 
     // Get the file that is reserved in memory, this should be called repeatedly
-    // until NULL is returned to get the full file
+    // until nullptr is returned to get the full file
     // Returns:
     //   the next memory block
-    //   NULL: end of file or fail to get file
+    //   nullptr: end of file or fail to get file
     FileCaptureBlock* get_file_data(uint8_t** buff, int* size);
 
     // Get the file size captured in the file buffer
index 787e26a0d68ba858c4b762cb5e676ca834d71f16..9e949d0b60858998f512ead090e7b838a859dba8 100644 (file)
@@ -44,7 +44,7 @@
 FileEnforcer::FileEnforcer()
 {
     fileHash = sfxhash_new(MAX_FILES_TRACKED, sizeof(FileHashKey), sizeof(FileNode),
-        MAX_MEMORY_USED, 1, NULL, NULL, 1);
+        MAX_MEMORY_USED, 1, nullptr, nullptr, 1);
     if (!fileHash)
         FatalError("Failed to create the expected channel hash table.\n");
 }
index 5fa52a43044a0e674bf2b48f47ef8e9438eeedee..73e2d1e4cc01e50a1f5cec02674785c3788a62d1 100644 (file)
@@ -153,12 +153,12 @@ FileMemPool::~FileMemPool()
  * Args:
  *   FileMemPool: pointer to a FileMemPool struct
  *
- * Returns: a pointer to the FileMemPool object on success, NULL on failure
+ * Returns: a pointer to the FileMemPool object on success, nullptr on failure
  */
 
 void* FileMemPool::m_alloc()
 {
-    void* b = NULL;
+    void* b = nullptr;
 
     std::lock_guard<std::mutex> lock(pool_mutex);
 
@@ -166,7 +166,7 @@ void* FileMemPool::m_alloc()
     {
         if (cbuffer_read(released_list, &b))
         {
-            return NULL;
+            return nullptr;
         }
     }
 
index cce96dee35de3cc91212b4dd467305c73d67d8b2..77cdf265eb2cee20ce013442da1a4cfc615858b6 100644 (file)
@@ -96,14 +96,6 @@ void FileService::start_file_processing()
     }
 }
 
-/*
- * - Only accepts 1 (ONE) callback being registered.
- *
- * - Call with NULL callback to "force" (guarantee) file type identification.
- *
- * TBD: Remove per-context "file_type_enabled" checking to simplify implementation.
- *
- */
 void FileService::enable_file_type()
 {
     if (!file_type_id_enabled)
index 131e9fb1243b3da8c0b73ee9863b293189a73556..3e64f1f9acaf988138c2e11146e52d1a5a7b8dc3 100644 (file)
@@ -83,15 +83,15 @@ DecodeResult B64Decode::decode_data(const uint8_t* start, const uint8_t* end)
     return DECODE_SUCCESS;
 }
 
-B64Decode::B64Decode(int max_depth):DataDecode(max_depth)
+B64Decode::B64Decode(int max_depth, int detect_depth) : DataDecode(max_depth, detect_depth)
 {
     buffer = new DecodeBuffer(max_depth);
 }
 
 B64Decode::~B64Decode()
 {
-   if (buffer)
-       delete buffer;
+    if (buffer)
+        delete buffer;
 }
 
 uint8_t sf_decode64tab[256] =
index a7bd436fb357df8bfd6546b56f7136c9997edb00..93a59933c02e0186d515bf150558173cb20a93d3 100644 (file)
@@ -30,7 +30,7 @@
 class B64Decode : public DataDecode
 {
 public:
-    B64Decode(int max_depth);
+    B64Decode(int max_depth, int detect_depth);
     ~B64Decode();
 
     // Main function to decode file data
@@ -47,7 +47,7 @@ SO_PUBLIC int sf_base64decode(
     uint8_t* inbuf, uint32_t inbuf_size,
     uint8_t* outbuf, uint32_t outbuf_size,
     uint32_t* bytes_written
-);
+    );
 
 #endif
 
index 00fb459d75e6ec3967d69f9049eb068072c75b16..7c6425e357a9fea740d6faa8028763fa0628ebf9 100644 (file)
@@ -30,22 +30,23 @@ void DataDecode::reset_decoded_bytes()
 void DataDecode::reset_decode_state()
 {
     reset_decoded_bytes();
+    decode_bytes_read = 0;
 }
 
 int DataDecode::get_detection_depth()
 {
     // unlimited
-    if (!decode_depth)
+    if (!detection_depth)
         return decoded_bytes;
     // exceeded depth before (decode_bytes_read has been updated)
-    else if (decode_depth < (int64_t)decode_bytes_read - decoded_bytes)
+    else if (detection_depth < (int64_t)decode_bytes_read - decoded_bytes)
         return 0;
     // lower than depth
-    else if (decode_depth > (int64_t)decode_bytes_read)
+    else if (detection_depth > (int64_t)decode_bytes_read)
         return decoded_bytes;
     // cut off
     else
-        return (decode_depth + (int64_t )decoded_bytes - decode_bytes_read);
+        return (detection_depth + (int64_t )decoded_bytes - decode_bytes_read);
 }
 
 int DataDecode::get_decoded_data(uint8_t** buf,  uint32_t* size)
@@ -55,7 +56,7 @@ int DataDecode::get_decoded_data(uint8_t** buf,  uint32_t* size)
     else
         return 0;
 
-    if (decodePtr != NULL)
+    if (decodePtr != nullptr)
         *buf = decodePtr;
     else
         return 0;
@@ -63,16 +64,14 @@ int DataDecode::get_decoded_data(uint8_t** buf,  uint32_t* size)
     return (*size);
 }
 
-#define MAX_DEPTH       65536
-
-DataDecode::DataDecode(int max_depth)
+DataDecode::DataDecode(int, int detect_depth)
 {
-    decode_depth = max_depth;
+    detection_depth = detect_depth;
     decode_bytes_read = 0;
     decoded_bytes = 0;
 }
 
 DataDecode::~DataDecode()
 {
-
 }
+
index f796b6bc9e92a00de48bb241ff24d2c5c128fd51..d49652c826d28adfe83b5803d031fa3fc78149b5 100644 (file)
@@ -30,12 +30,12 @@ enum DecodeResult
     DECODE_SUCCESS,
     DECODE_EXCEEDED, // Decode Complete when we reach the max depths
     DECODE_FAIL
-} ;
+};
 
 class DataDecode
 {
 public:
-    DataDecode(int max_depth);
+    DataDecode(int max_depth, int detect_depth);
     virtual ~DataDecode();
 
     // Main function to decode file data
@@ -48,13 +48,14 @@ public:
 
     virtual void reset_decode_state();
 
+    // Used to limit number of bytes examined for rule evaluation
     int get_detection_depth();
 
 protected:
     uint32_t decoded_bytes = 0;
     uint32_t decode_bytes_read;
     uint8_t* decodePtr = nullptr;
-    int decode_depth;
+    int detection_depth;
 };
 
 #endif
index 09416360df9ec1a577f5c3663ae9c5fc64b96cd2..23d9a9a72f13fd8ef1ee6ae6c64a99f86686b0d9 100644 (file)
@@ -29,34 +29,23 @@ void BitDecode::reset_decode_state()
 DecodeResult BitDecode::decode_data(const uint8_t* start, const uint8_t* end)
 {
     uint32_t bytes_avail = 0;
-    uint32_t act_size = 0;
+    uint32_t act_size = end - start;
 
     if (!(decode_depth))
     {
-        bytes_avail = buf_size;
+        bytes_avail = act_size;
     }
-    else if ( decode_depth < 0 )
+    else if ( (uint32_t)decode_depth > decode_bytes_read )
     {
-        return DECODE_EXCEEDED;
+        bytes_avail = (uint32_t)decode_depth - decode_bytes_read;
     }
     else
-    {
-        bytes_avail = decode_depth - decode_bytes_read;
-    }
-
-    /* 1. Stop decoding when we have reached either the decode depth or encode depth.
-     * 2. Stop decoding when we are out of memory */
-    if (bytes_avail ==0)
     {
         reset_decode_state();
         return DECODE_EXCEEDED;
     }
 
-    if ( (uint32_t)(end-start) < bytes_avail )
-    {
-        act_size = ( end - start);
-    }
-    else
+    if ( act_size > bytes_avail )
     {
         act_size = bytes_avail;
     }
@@ -68,14 +57,8 @@ DecodeResult BitDecode::decode_data(const uint8_t* start, const uint8_t* end)
     return DECODE_SUCCESS;
 }
 
-#define MAX_DEPTH       65536
-
-BitDecode::BitDecode(int max_depth):DataDecode(max_depth)
+BitDecode::BitDecode(int max_depth, int detect_depth) : DataDecode(max_depth, detect_depth)
 {
-    if (!max_depth)
-        buf_size = MAX_DEPTH;
-    else
-        buf_size = max_depth;
     decode_depth = max_depth;
     decode_bytes_read = 0;
     decoded_bytes = 0;
@@ -83,7 +66,5 @@ BitDecode::BitDecode(int max_depth):DataDecode(max_depth)
 
 BitDecode::~BitDecode()
 {
-
 }
 
-
index 4fd76401bc84267dc45a05be9fd5c644f4e2db06..5ea46f2b05f2e15d4d8431e72bc379e8d8d7f9d2 100644 (file)
@@ -28,7 +28,7 @@
 class BitDecode : public DataDecode
 {
 public:
-    BitDecode(int max_depth);
+    BitDecode(int max_depth, int detect_depth);
     ~BitDecode();
 
     // Main function to decode file data
@@ -37,7 +37,6 @@ public:
     void reset_decode_state() override;
 
 private:
-    uint32_t buf_size;
     int decode_depth;
 };
 
index 0424c0f7dd16717de304c9107b6bb4db7052952f..19483512ea6298e31712ca5bbfc8a012fd549606 100644 (file)
@@ -51,7 +51,6 @@ bool DecodeBuffer::check_restore_buffer()
     if (prev_encoded_bytes > encode_avail)
         prev_encoded_bytes = encode_avail;
 
-
     uint32_t prev_bytes = prev_encoded_bytes;
 
     uint32_t i = 0;
@@ -129,3 +128,4 @@ void DecodeBuffer::save_buffer(uint8_t* buff, uint32_t buff_size)
     prev_encoded_bytes = buff_size;
     prev_encoded_buf = buff;
 }
+
index ed4e92c9e2a76acbc491754b2e127e7c823a7518..81972884bf5cbd72fb69c1e02f77c318cb9b1b6a 100644 (file)
@@ -41,12 +41,12 @@ public:
     void update_buffer(uint32_t act_encode_size, uint32_t act_decode_size);
 
     void reset();
-    uint8_t* get_decode_buff() {return decodeBuf;}
-    uint8_t* get_encode_buff() {return encodeBuf;}
-    uint32_t get_decode_bytes_read() {return decode_bytes_read;}
+    uint8_t* get_decode_buff() { return decodeBuf; }
+    uint8_t* get_encode_buff() { return encodeBuf; }
+    uint32_t get_decode_bytes_read() { return decode_bytes_read; }
     uint32_t get_decode_avail();
     uint32_t get_encode_avail();
-    uint32_t get_prev_encoded_bytes() {return prev_encoded_bytes;}
+    uint32_t get_prev_encoded_bytes() { return prev_encoded_bytes; }
 
 private:
     uint32_t buf_size;
index 7a7891a62dc91824e7852877feb3e005a9ad83ec..f5daea186369ae9917eb92f5da12f6a2cb4ea918 100644 (file)
@@ -61,8 +61,8 @@ DecodeResult QPDecode::decode_data(const uint8_t* start, const uint8_t* end)
     }
     else if (!act_decode_size && !encode_avail)
     {
-       reset_decode_state();
-       return DECODE_FAIL;
+        reset_decode_state();
+        return DECODE_FAIL;
     }
 
     if (bytes_read < act_encode_size)
@@ -78,8 +78,7 @@ DecodeResult QPDecode::decode_data(const uint8_t* start, const uint8_t* end)
     return DECODE_SUCCESS;
 }
 
-
-QPDecode::QPDecode(int max_depth):DataDecode(max_depth)
+QPDecode::QPDecode(int max_depth, int detect_depth) : DataDecode(max_depth, detect_depth)
 {
     buffer = new DecodeBuffer(max_depth);
 }
@@ -88,7 +87,6 @@ QPDecode::~QPDecode()
 {
     if (buffer)
         delete buffer;
-
 }
 
 int sf_qpdecode(char* src, uint32_t slen, char* dst, uint32_t dlen, uint32_t* bytes_read,
@@ -165,3 +163,4 @@ int sf_qpdecode(char* src, uint32_t slen, char* dst, uint32_t dlen, uint32_t* by
 
     return 0;
 }
+
index 993334661b2ad41b8eb5a4500858716f6785e2b5..f778d40394a8cffdfff8f1ab150f60a3e02c39e1 100644 (file)
@@ -28,7 +28,7 @@
 class QPDecode : public DataDecode
 {
 public:
-    QPDecode(int max_depth);
+    QPDecode(int max_depth, int detect_depth);
     ~QPDecode();
 
     // Main function to decode file data
@@ -38,7 +38,6 @@ public:
 
 private:
     class DecodeBuffer* buffer = nullptr;
-
 };
 
 int sf_qpdecode(char* src, uint32_t slen, char* dst, uint32_t dlen, uint32_t* bytes_read,
index 1de0b886a9efb8fe622ad6900010c589066a81d5..a31f3f414c455ae63992473fa52910b40429e917 100644 (file)
@@ -70,8 +70,8 @@ DecodeResult UUDecode::decode_data(const uint8_t* start, const uint8_t* end)
     act_encode_size = act_encode_size + buffer->get_prev_encoded_bytes();
 
     if (sf_uudecode(buffer->get_encode_buff(), act_encode_size, buffer->get_decode_buff(),
-        buffer->get_decode_avail(), &bytes_read, &act_decode_size,
-        &(begin_found), &(end_found)) != 0)
+            buffer->get_decode_avail(), &bytes_read, &act_decode_size,
+            &(begin_found), &(end_found)) != 0)
     {
         reset_decode_state();
         return DECODE_FAIL;
@@ -104,8 +104,7 @@ DecodeResult UUDecode::decode_data(const uint8_t* start, const uint8_t* end)
     return DECODE_SUCCESS;
 }
 
-
-UUDecode::UUDecode(int max_depth):DataDecode(max_depth)
+UUDecode::UUDecode(int max_depth, int detect_depth) : DataDecode(max_depth, detect_depth)
 {
     buffer = new DecodeBuffer(max_depth);
 }
@@ -114,7 +113,6 @@ UUDecode::~UUDecode()
 {
     if (buffer)
         delete buffer;
-
 }
 
 int sf_uudecode(uint8_t* src, uint32_t slen, uint8_t* dst, uint32_t dlen, uint32_t* bytes_read,
@@ -240,3 +238,4 @@ int sf_uudecode(uint8_t* src, uint32_t slen, uint8_t* dst, uint32_t dlen, uint32
     *bytes_copied = dptr - dst;
     return 0;
 }
+
index 73a6ab7c0f13d4ac7c5f0b4f7450390e70587233..7f73a3f78b523ce2229804c3082810ff9f544fec 100644 (file)
@@ -27,7 +27,7 @@
 class UUDecode : public DataDecode
 {
 public:
-    UUDecode(int max_depth);
+    UUDecode(int max_depth, int detect_depth);
     ~UUDecode();
 
     // Main function to decode file data
index 57588e8dd1eede1eb3c32140e3ae6f4ed2f411fe..854c44bf59d29e0c3c579ea1e46053162864b4f6 100644 (file)
 
 #include "file_mime_process.h"
 
-void DecodeConfig::update_max_depth(int64_t depth)
+DecodeConfig::DecodeConfig()
 {
-    // 0 means unlimited
-    if (!depth)
-        max_depth = MAX_DEPTH;
-    else if (max_depth < depth)
-        max_depth = depth;
+    sync_all_depths();
 }
 
 void DecodeConfig::set_ignore_data(bool ignored)
@@ -60,7 +56,6 @@ int DecodeConfig::get_max_mime_mem()
 void DecodeConfig::set_b64_depth(int depth)
 {
     b64_depth = depth;
-    update_max_depth(depth);
 }
 
 int DecodeConfig::get_b64_depth()
@@ -71,7 +66,6 @@ int DecodeConfig::get_b64_depth()
 void DecodeConfig::set_qp_depth(int depth)
 {
     qp_depth = depth;
-    update_max_depth(depth);
 }
 
 int DecodeConfig::get_qp_depth()
@@ -82,7 +76,6 @@ int DecodeConfig::get_qp_depth()
 void DecodeConfig::set_bitenc_depth(int depth)
 {
     bitenc_depth = depth;
-    update_max_depth(depth);
 }
 
 int DecodeConfig::get_bitenc_depth()
@@ -93,7 +86,6 @@ int DecodeConfig::get_bitenc_depth()
 void DecodeConfig::set_uu_depth(int depth)
 {
     uu_depth = depth;
-    update_max_depth(depth);
 }
 
 int DecodeConfig::get_uu_depth()
@@ -106,37 +98,32 @@ int64_t DecodeConfig::get_file_depth()
     return file_depth;
 }
 
-int DecodeConfig::get_max_depth()
-{
-    return max_depth;
-}
-
 bool DecodeConfig::is_decoding_enabled()
 {
-    if (max_depth > -1)
-        return true;
-    else
-        return false;
-}
-
-void DecodeConfig::set_file_depth(int64_t file_depth)
-{
-    if ((!file_depth) || (file_depth > MAX_DEPTH))
-    {
-        max_depth = MAX_DEPTH;
-    }
-    else if (file_depth > max_depth)
-    {
-        max_depth = (int)file_depth;
-    }
+    return decode_enabled;
 }
 
 // update file depth and max_depth etc
 void DecodeConfig::sync_all_depths()
 {
     file_depth = FileService::get_max_file_depth();
+    if ((file_depth >= 0)or (b64_depth >= 0) or (qp_depth >= 0)
+        or (bitenc_depth >= 0) or (uu_depth >= 0))
+        decode_enabled = true;
+    else
+        decode_enabled = false;
+}
 
-    set_file_depth(file_depth);
+int DecodeConfig::get_max_depth(int decode_depth)
+{
+    sync_all_depths();
+
+    if (!file_depth or !decode_depth)
+        return 0;
+    else if (file_depth > decode_depth)
+        return file_depth;
+    else
+        return decode_depth;
 }
 
 void DecodeConfig::print_decode_conf()
@@ -206,3 +193,4 @@ void DecodeConfig::print_decode_conf()
     else
         LogMessage("    Non-Encoded MIME attachment Extraction/text: %s\n", "Disabled");
 }
+
index 6a4f01c77d6f8ef4efe06fd662adca5384ab4cf5..f3d2b8a09bba983fd4484361f7b581131919015c 100644 (file)
@@ -38,6 +38,7 @@
 class SO_PUBLIC DecodeConfig
 {
 public:
+    DecodeConfig();
     void set_ignore_data(bool);
     bool is_ignore_data();
     void set_max_mime_mem(int);
@@ -50,11 +51,11 @@ public:
     int get_bitenc_depth();
     void set_uu_depth(int);
     int get_uu_depth();
-    int get_max_depth();
     int64_t get_file_depth();
     bool is_decoding_enabled();
     void sync_all_depths();
     void print_decode_conf();
+    int get_max_depth(int);
 
 private:
     bool ignore_data = false;
@@ -64,9 +65,7 @@ private:
     int bitenc_depth = DEFAULT_DEPTH;
     int uu_depth = DEFAULT_DEPTH;
     int64_t file_depth = MIN_DEPTH;
-    int max_depth = DEFAULT_DEPTH;  //is the max of all depths
-    void set_file_depth(int64_t);
-    void update_max_depth(int64_t);
+    bool decode_enabled = true;
 };
 
 #endif
index 5a63557e5bfa779b51553e3e34e97e46fa797a57..08b96753c86a630986edbbd33962f65dd5dc61cb 100644 (file)
@@ -41,9 +41,10 @@ void MimeDecode::clear_decode_state()
         decoder->reset_decode_state();
 }
 
-void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf, MimeStats* mime_stats)
+void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf,
+    MimeStats* mime_stats)
 {
-    const char* tmp = NULL;
+    const char* tmp = nullptr;
 
     if (decoder)
         delete decoder;
@@ -55,12 +56,13 @@ void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf,
         if (config->get_b64_depth() > -1)
         {
             tmp = SnortStrcasestr(start, length, "base64");
-            if ( tmp != NULL )
+            if ( tmp != nullptr )
             {
                 decode_type = DECODE_B64;
                 if (mime_stats)
                     mime_stats->b64_attachments++;
-                decoder = new B64Decode(config->get_b64_depth());
+                decoder = new B64Decode(config->get_max_depth(config->get_b64_depth()),
+                    config->get_b64_depth());
                 return;
             }
         }
@@ -68,12 +70,13 @@ void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf,
         if (config->get_qp_depth() > -1)
         {
             tmp = SnortStrcasestr(start, length, "quoted-printable");
-            if ( tmp != NULL )
+            if ( tmp != nullptr )
             {
                 decode_type = DECODE_QP;
                 if (mime_stats)
                     mime_stats->qp_attachments++;
-                decoder = new QPDecode(config->get_qp_depth());
+                decoder = new QPDecode(config->get_max_depth(config->get_qp_depth()),
+                    config->get_qp_depth());
                 return;
             }
         }
@@ -81,12 +84,13 @@ void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf,
         if (config->get_uu_depth() > -1)
         {
             tmp = SnortStrcasestr(start, length, "uuencode");
-            if ( tmp != NULL )
+            if ( tmp != nullptr )
             {
                 decode_type = DECODE_UU;
                 if (mime_stats)
                     mime_stats->uu_attachments++;
-                decoder = new UUDecode(config->get_uu_depth());
+                decoder = new UUDecode(config->get_max_depth(config->get_uu_depth()),
+                    config->get_uu_depth());
                 return;
             }
         }
@@ -97,24 +101,25 @@ void MimeDecode::process_decode_type(const char* start, int length, bool cnt_xf,
         decode_type = DECODE_BITENC;
         if (mime_stats)
             mime_stats->bitenc_attachments++;
-        decoder = new BitDecode(config->get_bitenc_depth());
+        decoder = new BitDecode(config->get_max_depth(config->get_bitenc_depth()),
+            config->get_bitenc_depth());
         return;
     }
 }
 
 DecodeResult MimeDecode::decode_data(const uint8_t* start, const uint8_t* end)
 {
-    return (decoder? decoder->decode_data(start,end):DECODE_SUCCESS);
+    return (decoder ? decoder->decode_data(start,end) : DECODE_SUCCESS);
 }
 
 int MimeDecode::get_detection_depth()
 {
-    return (decoder?decoder->get_detection_depth():0);
+    return (decoder ? decoder->get_detection_depth() : 0);
 }
 
 int MimeDecode::get_decoded_data(uint8_t** buf,  uint32_t* size)
 {
-    return (decoder? decoder->get_decoded_data(buf, size):0);
+    return (decoder ? decoder->get_decoded_data(buf, size) : 0);
 }
 
 DecodeType MimeDecode::get_decode_type()
@@ -132,3 +137,4 @@ MimeDecode::~MimeDecode()
     if (decoder)
         delete decoder;
 }
+
index 29daa9c0cdff8d451ad0c68a7c2f2fb945cb2e67..f458a456731785fb1c40fd6c07ca28f39f8a6464 100644 (file)
 #define MIME_FLAG_FILENAME_PRESENT                0x00000004
 #define MIME_FLAG_EMAIL_HDRS_PRESENT              0x00000008
 
-
 /* Extract the filename from the header */
 int MailLogState::extract_file_name(const char** start, int length, bool* disp_cont)
 {
-    const char* tmp = NULL;
+    const char* tmp = nullptr;
     const char* end = *start+length;
 
     if (length <= 0)
@@ -54,7 +53,7 @@ int MailLogState::extract_file_name(const char** start, int length, bool* disp_c
     {
         tmp = SnortStrcasestr(*start, length, "filename");
 
-        if ( tmp == NULL )
+        if ( tmp == nullptr )
             return -1;
 
         tmp = tmp + 8;
@@ -81,7 +80,7 @@ int MailLogState::extract_file_name(const char** start, int length, bool* disp_c
             }
             *start = tmp;
             tmp = SnortStrnPbrk(*start,(end - tmp),"\"");
-            if (tmp == NULL )
+            if (tmp == nullptr )
             {
                 if ((end - tmp) > 0 )
                 {
@@ -168,7 +167,6 @@ int MailLogState::log_file_name(const uint8_t* start, int length, bool* disp_con
     return 0;
 }
 
-
 void MailLogState::set_file_name_from_log(Flow* flow)
 {
     FileFlows* files = FileFlows::get_file_flows(flow);
@@ -234,7 +232,7 @@ int MailLogState::log_email_id(const uint8_t* start, int length, EmailUserType t
         return -1;
 
     tmp_eol = (uint8_t*)memchr(start, ':', length);
-    if (tmp_eol == NULL)
+    if (tmp_eol == nullptr)
         return -1;
 
     if ((tmp_eol+1) < (start+length))
@@ -305,7 +303,6 @@ void MailLogState::get_email_hdrs(uint8_t** buf, uint32_t* len)
 {
     *buf = emailHdrs;
     *len = hdrs_logged;
-
 }
 
 void MailLogState::get_email_id(uint8_t** buf, uint32_t* len, EmailUserType type)
@@ -353,7 +350,7 @@ bool MailLogState::is_email_to_present()
 MailLogState::MailLogState(MailLogConfig* conf)
 {
     if (conf && (conf->log_email_hdrs || conf->log_filename
-        || conf->log_mailfrom || conf->log_rcptto))
+            || conf->log_mailfrom || conf->log_rcptto))
     {
         uint32_t bufsz = (2* MAX_EMAIL) + MAX_FILE + conf->email_hdrs_log_depth;
         buf = (uint8_t*)snort_calloc(bufsz);
@@ -374,6 +371,7 @@ MailLogState::MailLogState(MailLogConfig* conf)
 
 MailLogState::~MailLogState()
 {
-    if (buf != NULL)
+    if (buf != nullptr)
         snort_free(buf);
 }
+
index 0afd0e5b75459154e9d877f30087c4353fc822a1..a450ff67be4e4a067e89c4ebd1c3b5a91417effc 100644 (file)
@@ -51,15 +51,15 @@ public:
     ~MailLogState();
 
     /* accumulate MIME attachment filenames. The filenames are appended by commas */
-    int log_file_name (const uint8_t* start, int length, bool* disp_cont);
+    int log_file_name(const uint8_t* start, int length, bool* disp_cont);
     void set_file_name_from_log(Flow*);
 
     int log_email_hdrs(const uint8_t* start, int length);
     int log_email_id (const uint8_t* start, int length, EmailUserType);
 
-    void get_file_name (uint8_t** buf, uint32_t* len);
-    void get_email_hdrs (uint8_t** buf, uint32_t* len);
-    void get_email_id (uint8_t** buf, uint32_t* len, EmailUserType);
+    void get_file_name(uint8_t** buf, uint32_t* len);
+    void get_email_hdrs(uint8_t** buf, uint32_t* len);
+    void get_email_id(uint8_t** buf, uint32_t* len, EmailUserType);
 
     bool is_file_name_present();
     bool is_email_hdrs_present();
index 671946cebc1c8e84e456077c930d987ba8d28728..0d3c2c29518e2c19f3964fa8515e6b0bf9ac9ca4 100644 (file)
@@ -50,7 +50,7 @@ static inline bool store_boundary(MimeDataPafInfo* data_info,  uint8_t val)
         if (val == '=')
             data_info->boundary_search++;
         else if (!isspace(val))
-            data_info->boundary_search = NULL;
+            data_info->boundary_search = nullptr;
     }
     else if (*(data_info->boundary_search) == '\0')
     {
@@ -88,7 +88,7 @@ static inline bool store_boundary(MimeDataPafInfo* data_info,  uint8_t val)
         if ((val == '.') || isspace (val))
             data_info->boundary_search = (char*)&boundary_str[0];
         else
-            data_info->boundary_search = NULL;
+            data_info->boundary_search = nullptr;
     }
 
     return false;
@@ -101,15 +101,8 @@ static inline bool check_boundary(MimeDataPafInfo* data_info,  uint8_t data)
     switch (data_info->boundary_state)
     {
     case MIME_PAF_BOUNDARY_UNKNOWN:
-        if (data == '\n')
-            data_info->boundary_state = MIME_PAF_BOUNDARY_LF;
-        break;
-
-    case MIME_PAF_BOUNDARY_LF:
         if (data == '-')
             data_info->boundary_state = MIME_PAF_BOUNDARY_HYPEN_FIRST;
-        else if (data != '\n')
-            data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
         break;
 
     case MIME_PAF_BOUNDARY_HYPEN_FIRST:
@@ -118,8 +111,6 @@ static inline bool check_boundary(MimeDataPafInfo* data_info,  uint8_t data)
             data_info->boundary_state = MIME_PAF_BOUNDARY_HYPEN_SECOND;
             data_info->boundary_search = data_info->boundary;
         }
-        else if (data == '\n')
-            data_info->boundary_state = MIME_PAF_BOUNDARY_LF;
         else
             data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
         break;
@@ -139,6 +130,8 @@ static inline bool check_boundary(MimeDataPafInfo* data_info,  uint8_t data)
         }
         else if (*(data_info->boundary_search) == data)
             data_info->boundary_search++;
+        else if (data == '-')
+            data_info->boundary_state = MIME_PAF_BOUNDARY_HYPEN_FIRST;
         else
             data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
         break;
@@ -149,7 +142,7 @@ static inline bool check_boundary(MimeDataPafInfo* data_info,  uint8_t data)
 
 void reset_mime_paf_state(MimeDataPafInfo* data_info)
 {
-    data_info->boundary_search = NULL;
+    data_info->boundary_search = nullptr;
     data_info->boundary_len = 0;
     data_info->boundary[0] = '\0';
     data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
index 2b898d593c5131caef5de98e302874d05f990346..ab0c0365ff9c8cea51a2392ea965d7066037e6a5 100644 (file)
@@ -39,7 +39,6 @@ enum MimeDataState
 enum MimeBoundaryState
 {
     MIME_PAF_BOUNDARY_UNKNOWN = 0,      /* UNKNOWN */
-    MIME_PAF_BOUNDARY_LF,               /* '\n' */
     MIME_PAF_BOUNDARY_HYPEN_FIRST,      /* First '-' */
     MIME_PAF_BOUNDARY_HYPEN_SECOND      /* Second '-' */
 };
index 5a3961766dc298f7cafd4a6539a77c105b870098..3cb267fc2783a54ac34e1f77f738710f6034e2d6 100644 (file)
@@ -43,7 +43,7 @@ struct MimeToken
     const char* name;
     int name_len;
     int search_id;
-} ;
+};
 
 enum MimeHdrEnum
 {
@@ -58,27 +58,27 @@ const MimeToken mime_hdrs[] =
     { "Content-type:", 13, HDR_CONTENT_TYPE },
     { "Content-Transfer-Encoding:", 26, HDR_CONT_TRANS_ENC },
     { "Content-Disposition:", 20, HDR_CONT_DISP },
-    { NULL,             0, 0 }
+    { nullptr,             0, 0 }
 };
 
 struct MIMESearch
 {
     const char* name;
     int name_len;
-} ;
+};
 
 struct MIMESearchInfo
 {
     int id;
     int index;
     int length;
-} ;
+};
 
 MIMESearchInfo mime_search_info;
 
 SearchTool* mime_hdr_search_mpse = nullptr;
 MIMESearch mime_hdr_search[HDR_LAST];
-MIMESearch* mime_current_search = NULL;
+MIMESearch* mime_current_search = nullptr;
 
 static void get_mime_eol(const uint8_t* ptr, const uint8_t* end,
     const uint8_t** eol, const uint8_t** eolm)
@@ -95,7 +95,7 @@ static void get_mime_eol(const uint8_t* ptr, const uint8_t* end,
     }
 
     tmp_eol = (uint8_t*)memchr(ptr, '\n', end - ptr);
-    if (tmp_eol == NULL)
+    if (tmp_eol == nullptr)
     {
         tmp_eol = end;
         tmp_eolm = end;
@@ -148,12 +148,12 @@ void MimeSession::setup_decode(const char* data, int size, bool cnt_xf)
     /* Check for Encoding Type */
     if ( decode_conf && decode_conf->is_decoding_enabled())
     {
-        if (decode_state == NULL)
+        if (decode_state == nullptr)
         {
             decode_state = new MimeDecode(decode_conf);
         }
 
-        if (decode_state != NULL)
+        if (decode_state != nullptr)
         {
             decode_state->process_decode_type(data, size, cnt_xf, mime_stats);
             state_flags |= MIME_FLAG_EMAIL_ATTACH;
@@ -176,9 +176,9 @@ const uint8_t* MimeSession::process_mime_header(const uint8_t* ptr,
     const uint8_t* eol = data_end_marker;
     const uint8_t* eolm = eol;
     const uint8_t* colon;
-    const uint8_t* content_type_ptr = NULL;
-    const uint8_t* cont_trans_enc = NULL;
-    const uint8_t* cont_disp = NULL;
+    const uint8_t* content_type_ptr = nullptr;
+    const uint8_t* cont_trans_enc = nullptr;
+    const uint8_t* cont_disp = nullptr;
     int header_found;
     const uint8_t* start_hdr;
 
@@ -314,14 +314,14 @@ const uint8_t* MimeSession::process_mime_header(const uint8_t* ptr,
 
         int ret = handle_header_line(ptr, eol, max_header_name_len);
         if (ret < 0)
-            return NULL;
+            return nullptr;
         else if (ret > 0)
         {
             /* assume we guessed wrong and are in the body */
             data_state = STATE_DATA_BODY;
             state_flags &=
                 ~(MIME_FLAG_FOLDING | MIME_FLAG_IN_CONTENT_TYPE | MIME_FLAG_DATA_HEADER_CONT
-                    | MIME_FLAG_IN_CONT_TRANS_ENC | MIME_FLAG_IN_CONT_DISP);
+                | MIME_FLAG_IN_CONT_TRANS_ENC | MIME_FLAG_IN_CONT_DISP);
             return ptr;
         }
 
@@ -349,34 +349,34 @@ const uint8_t* MimeSession::process_mime_header(const uint8_t* ptr,
          * because boundary=BOUNDARY can be split across mulitple folded lines before
          * or after the '=' */
         if ((state_flags &
-            (MIME_FLAG_IN_CONTENT_TYPE | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONTENT_TYPE)
+                (MIME_FLAG_IN_CONTENT_TYPE | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONTENT_TYPE)
         {
             if ((data_state == STATE_MIME_HEADER) && !(state_flags &
-                MIME_FLAG_EMAIL_ATTACH))
+                    MIME_FLAG_EMAIL_ATTACH))
             {
                 setup_decode((const char*)content_type_ptr, (eolm - content_type_ptr), false);
             }
 
             state_flags &= ~MIME_FLAG_IN_CONTENT_TYPE;
-            content_type_ptr = NULL;
+            content_type_ptr = nullptr;
         }
         else if ((state_flags &
-            (MIME_FLAG_IN_CONT_TRANS_ENC | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONT_TRANS_ENC)
+                (MIME_FLAG_IN_CONT_TRANS_ENC | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONT_TRANS_ENC)
         {
             setup_decode((const char*)cont_trans_enc, (eolm - cont_trans_enc), true);
 
             state_flags &= ~MIME_FLAG_IN_CONT_TRANS_ENC;
 
-            cont_trans_enc = NULL;
+            cont_trans_enc = nullptr;
         }
         else if (((state_flags &
-            (MIME_FLAG_IN_CONT_DISP | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONT_DISP) && cont_disp)
+                    (MIME_FLAG_IN_CONT_DISP | MIME_FLAG_FOLDING)) == MIME_FLAG_IN_CONT_DISP) &&
+            cont_disp)
         {
             bool disp_cont = (state_flags & MIME_FLAG_IN_CONT_DISP_CONT) ? true : false;
             if (log_config->log_filename && log_state )
             {
                 log_state->log_file_name(cont_disp, eolm - cont_disp, &disp_cont);
-
             }
             if (disp_cont)
             {
@@ -388,11 +388,9 @@ const uint8_t* MimeSession::process_mime_header(const uint8_t* ptr,
                 state_flags &= ~MIME_FLAG_IN_CONT_DISP_CONT;
             }
 
-            cont_disp = NULL;
+            cont_disp = nullptr;
         }
 
-        data_state = STATE_DATA_HEADER;
-
         ptr = eol;
 
         if (ptr == data_end_marker)
@@ -444,7 +442,6 @@ static const uint8_t* GetDataEnd(const uint8_t* data_start,
 const uint8_t* MimeSession::process_mime_body(const uint8_t* ptr,
     const uint8_t* data_end, bool is_data_end)
 {
-
     if (state_flags & MIME_FLAG_EMAIL_ATTACH)
     {
         const uint8_t* attach_start = ptr;
@@ -499,8 +496,8 @@ const uint8_t* MimeSession::process_mime_data_paf(
     {
         if ((start < end) && (*start == '.'))
         {
-            const uint8_t* eol = NULL;
-            const uint8_t* eolm = NULL;
+            const uint8_t* eol = nullptr;
+            const uint8_t* eolm = nullptr;
 
             get_mime_eol(start, end, &eol, &eolm);
 
@@ -511,7 +508,7 @@ const uint8_t* MimeSession::process_mime_data_paf(
                 /* if we're normalizing and not ignoring data copy data end marker
                  * and dot to alt buffer */
                 if (normalize_data(start, end) < 0)
-                    return NULL;
+                    return nullptr;
 
                 reset_mime_state();
 
@@ -553,16 +550,16 @@ const uint8_t* MimeSession::process_mime_data_paf(
 #endif
 
         start = process_mime_header(start, end);
-        if (start == NULL)
-            return NULL;
+        if (start == nullptr)
+            return nullptr;
     }
 
     if (normalize_data(start, end) < 0)
-        return NULL;
+        return nullptr;
     /* now we shouldn't have to worry about copying any data to the alt buffer
      *      * only mime headers if we find them and only if we're ignoring data */
 
-    while ((start != NULL) && (start < end))
+    while ((start != nullptr) && (start < end))
     {
         switch (data_state)
         {
@@ -579,10 +576,10 @@ const uint8_t* MimeSession::process_mime_data_paf(
 
     /* We have either reached the end of MIME header or end of MIME encoded data*/
 
-    if ((decode_state) != NULL)
+    if ((decode_state) != nullptr)
     {
         DecodeConfig* conf= decode_conf;
-        uint8_t* buffer = NULL;
+        uint8_t* buffer = nullptr;
         uint32_t buf_size = 0;
 
         decode_state->get_decoded_data(&buffer, &buf_size);
@@ -602,22 +599,22 @@ const uint8_t* MimeSession::process_mime_data_paf(
         }
         if (mime_stats)
         {
-            switch(decode_state->get_decode_type())
+            switch (decode_state->get_decode_type())
             {
-                case DECODE_B64:
-                    mime_stats->b64_bytes += buf_size;
-                    break;
-                case DECODE_QP:
-                    mime_stats->qp_bytes += buf_size;
-                    break;
-                case DECODE_UU:
-                    mime_stats->uu_bytes += buf_size;
-                    break;
-                case DECODE_BITENC:
-                    mime_stats->bitenc_bytes += buf_size;
-                    break;
-                default:
-                    break;
+            case DECODE_B64:
+                mime_stats->b64_bytes += buf_size;
+                break;
+            case DECODE_QP:
+                mime_stats->qp_bytes += buf_size;
+                break;
+            case DECODE_UU:
+                mime_stats->uu_bytes += buf_size;
+                break;
+            case DECODE_BITENC:
+                mime_stats->bitenc_bytes += buf_size;
+                break;
+            default:
+                break;
             }
         }
 
@@ -663,6 +660,7 @@ const uint8_t* MimeSession::process_mime_data(Flow* flow, const uint8_t* start,
             finalFilePosition(&position);
             process_mime_data_paf(flow, attach_start, attach_end,
                 upload, position);
+            data_state = STATE_MIME_HEADER;
             position = SNORT_FILE_START;
             attach_start = start + 1;
         }
@@ -710,14 +708,14 @@ void MimeSession::init()
 
     /* Header search */
     mime_hdr_search_mpse = new SearchTool();
-    if (mime_hdr_search_mpse == NULL)
+    if (mime_hdr_search_mpse == nullptr)
     {
         // FIXIT-M make configurable or at least fall back to any
         // available search engine
         FatalError("Could not instantiate ac_bnfa search engine.\n");
     }
 
-    for (tmp = &mime_hdrs[0]; tmp->name != NULL; tmp++)
+    for (tmp = &mime_hdrs[0]; tmp->name != nullptr; tmp++)
     {
         mime_hdr_search[tmp->search_id].name = tmp->name;
         mime_hdr_search[tmp->search_id].name_len = tmp->name_len;
@@ -731,7 +729,7 @@ void MimeSession::init()
 // Free anything that needs it before shutting down preprocessor
 void MimeSession::exit()
 {
-    if (mime_hdr_search_mpse != NULL)
+    if (mime_hdr_search_mpse != nullptr)
         delete mime_hdr_search_mpse;
 }
 
@@ -751,3 +749,4 @@ MimeSession::~MimeSession()
     if ( log_state )
         delete(log_state);
 }
+
index c0f53d417a285b8660de3feb841bb129340a105b..f60ea68a56ea67f2e66d1045093c4e00e482717e 100644 (file)
@@ -82,10 +82,10 @@ private:
 
     // SMTP, IMAP, POP might have different implementation for this
     virtual int handle_header_line(const uint8_t*, const uint8_t*, int) { return 0; }
-    virtual int normalize_data(const uint8_t* , const uint8_t* ) { return 0; }
+    virtual int normalize_data(const uint8_t*, const uint8_t*) { return 0; }
     virtual void decode_alert() { }
-    virtual void reset_state(Flow* ) { }
-    virtual bool is_end_of_data(Flow* ) { return false; }
+    virtual void reset_state(Flow*) { }
+    virtual bool is_end_of_data(Flow*) { return false; }
 
     void reset_mime_state();
     void setup_decode(const char* data, int size, bool cnt_xf);
index 67c59b3cf7d1b5fc5bb4733ef06c53c46e54432e..60cbdac83c70824096d6868cf89f7b179eb07555 100644 (file)
@@ -137,12 +137,13 @@ void HttpMsgBody::do_file_processing()
     const int32_t fp_length = (file_data.length <= session_data->file_depth_remaining[source_id]) ?
         file_data.length : session_data->file_depth_remaining[source_id];
 
-    if (source_id == SRC_SERVER)
+    if (!session_data->mime_state)
     {
         FileFlows* file_flows = FileFlows::get_file_flows(flow);
+        bool download = (source_id == SRC_SERVER);
 
         if (file_flows->file_process(file_data.start, fp_length,
-            file_position, false))
+            file_position, !download))
         {
             session_data->file_depth_remaining[source_id] -= fp_length;
 
@@ -169,7 +170,7 @@ void HttpMsgBody::do_file_processing()
     else
     {
         session_data->mime_state->process_mime_data(flow, file_data.start,
-            fp_length, true, file_position);
+            fp_length, true, SNORT_FILE_POSITION_UNKNOWN);
 
         session_data->file_depth_remaining[source_id] -= fp_length;
         if (session_data->file_depth_remaining[source_id] == 0)
index b70c7a5b29df9a01d118d00973d352d51b114d17..6411354ebdabd4debb4f97530efe066a48f68dab 100644 (file)
@@ -206,10 +206,16 @@ void HttpMsgHeader::setup_file_processing()
            session_data->file_depth_remaining[source_id] = 0;
            return;
         }
-
-        if (source_id == SRC_CLIENT)
+        // FIXIT check boundary to make sure this is not MIME for sure
+        if ((source_id == SRC_CLIENT) and (get_header_value_norm(HEAD_CONTENT_TYPE).length > 0 ))
         {
             session_data->mime_state = new MimeSession(&decode_conf, &mime_conf);
+            const Field& headers = get_classic_raw_header();
+            if (headers.length > 0)
+            {
+                session_data->mime_state->process_mime_data(flow, headers.start,
+                    headers.length, true, SNORT_FILE_POSITION_UNKNOWN);
+            }
         }
         else
         {
index 5f795fb60e4e4bda11132789f8393abde4aea5ff..4a3db64dadb820296e8ae63e0670c9af8af578be 100644 (file)
@@ -253,15 +253,16 @@ bool HttpStreamSplitter::finish(Flow* flow)
         (session_data->cutter[source_id] != nullptr)               &&
         (session_data->cutter[source_id]->get_octets_seen() == 0))
     {
-        if (source_id == SRC_SERVER)
+        if (!session_data->mime_state)
         {
             FileFlows* file_flows = FileFlows::get_file_flows(flow);
-            file_flows->file_process(nullptr, 0, SNORT_FILE_END, false);
+            bool download = (source_id == SRC_SERVER);
+            file_flows->file_process(nullptr, 0, SNORT_FILE_END, !download);
         }
-        else if (session_data->mime_state != nullptr)
+        else
         {
             session_data->mime_state->process_mime_data(flow, nullptr, 0, true,
-                SNORT_FILE_END);
+                SNORT_FILE_POSITION_UNKNOWN);
             delete session_data->mime_state;
             session_data->mime_state = nullptr;
         }