From: Hui Cao (huica) Date: Tue, 4 Oct 2016 16:22:04 +0000 (-0400) Subject: Merge pull request #652 in SNORT/snort3 from file_mime to master X-Git-Tag: 3.0.0-233~241 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb4f0c318b8d62d5e392eab9ac05cc5cfa7a4602;p=thirdparty%2Fsnort3.git Merge pull request #652 in SNORT/snort3 from file_mime to master Squashed commit of the following: commit 908af0c0d4393fdc06032f3abf9e8a38b9f61c80 Author: huica Date: Fri Sep 30 15:09:11 2016 -0400 Support http file upload processing and process decode/detection depths --- diff --git a/src/file_api/circular_buffer.cc b/src/file_api/circular_buffer.cc index 3189bf563..d36d16eac 100644 --- a/src/file_api/circular_buffer.cc +++ b/src/file_api/circular_buffer.cc @@ -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); diff --git a/src/file_api/file_capture.h b/src/file_api/file_capture.h index ce824284a..df3db60b6 100644 --- a/src/file_api/file_capture.h +++ b/src/file_api/file_capture.h @@ -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 diff --git a/src/file_api/file_enforcer.cc b/src/file_api/file_enforcer.cc index 787e26a0d..9e949d0b6 100644 --- a/src/file_api/file_enforcer.cc +++ b/src/file_api/file_enforcer.cc @@ -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"); } diff --git a/src/file_api/file_mempool.cc b/src/file_api/file_mempool.cc index 5fa52a430..73e2d1e4c 100644 --- a/src/file_api/file_mempool.cc +++ b/src/file_api/file_mempool.cc @@ -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 lock(pool_mutex); @@ -166,7 +166,7 @@ void* FileMemPool::m_alloc() { if (cbuffer_read(released_list, &b)) { - return NULL; + return nullptr; } } diff --git a/src/file_api/file_service.cc b/src/file_api/file_service.cc index cce96dee3..77cdf265e 100644 --- a/src/file_api/file_service.cc +++ b/src/file_api/file_service.cc @@ -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) diff --git a/src/mime/decode_b64.cc b/src/mime/decode_b64.cc index 131e9fb12..3e64f1f9a 100644 --- a/src/mime/decode_b64.cc +++ b/src/mime/decode_b64.cc @@ -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] = diff --git a/src/mime/decode_b64.h b/src/mime/decode_b64.h index a7bd436fb..93a59933c 100644 --- a/src/mime/decode_b64.h +++ b/src/mime/decode_b64.h @@ -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 diff --git a/src/mime/decode_base.cc b/src/mime/decode_base.cc index 00fb459d7..7c6425e35 100644 --- a/src/mime/decode_base.cc +++ b/src/mime/decode_base.cc @@ -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() { - } + diff --git a/src/mime/decode_base.h b/src/mime/decode_base.h index f796b6bc9..d49652c82 100644 --- a/src/mime/decode_base.h +++ b/src/mime/decode_base.h @@ -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 diff --git a/src/mime/decode_bit.cc b/src/mime/decode_bit.cc index 09416360d..23d9a9a72 100644 --- a/src/mime/decode_bit.cc +++ b/src/mime/decode_bit.cc @@ -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() { - } - diff --git a/src/mime/decode_bit.h b/src/mime/decode_bit.h index 4fd76401b..5ea46f2b0 100644 --- a/src/mime/decode_bit.h +++ b/src/mime/decode_bit.h @@ -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; }; diff --git a/src/mime/decode_buffer.cc b/src/mime/decode_buffer.cc index 0424c0f7d..19483512e 100644 --- a/src/mime/decode_buffer.cc +++ b/src/mime/decode_buffer.cc @@ -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; } + diff --git a/src/mime/decode_buffer.h b/src/mime/decode_buffer.h index ed4e92c9e..81972884b 100644 --- a/src/mime/decode_buffer.h +++ b/src/mime/decode_buffer.h @@ -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; diff --git a/src/mime/decode_qp.cc b/src/mime/decode_qp.cc index 7a7891a62..f5daea186 100644 --- a/src/mime/decode_qp.cc +++ b/src/mime/decode_qp.cc @@ -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; } + diff --git a/src/mime/decode_qp.h b/src/mime/decode_qp.h index 993334661..f778d4039 100644 --- a/src/mime/decode_qp.h +++ b/src/mime/decode_qp.h @@ -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, diff --git a/src/mime/decode_uu.cc b/src/mime/decode_uu.cc index 1de0b886a..a31f3f414 100644 --- a/src/mime/decode_uu.cc +++ b/src/mime/decode_uu.cc @@ -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; } + diff --git a/src/mime/decode_uu.h b/src/mime/decode_uu.h index 73a6ab7c0..7f73a3f78 100644 --- a/src/mime/decode_uu.h +++ b/src/mime/decode_uu.h @@ -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 diff --git a/src/mime/file_mime_config.cc b/src/mime/file_mime_config.cc index 57588e8dd..854c44bf5 100644 --- a/src/mime/file_mime_config.cc +++ b/src/mime/file_mime_config.cc @@ -28,13 +28,9 @@ #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"); } + diff --git a/src/mime/file_mime_config.h b/src/mime/file_mime_config.h index 6a4f01c77..f3d2b8a09 100644 --- a/src/mime/file_mime_config.h +++ b/src/mime/file_mime_config.h @@ -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 diff --git a/src/mime/file_mime_decode.cc b/src/mime/file_mime_decode.cc index 5a63557e5..08b96753c 100644 --- a/src/mime/file_mime_decode.cc +++ b/src/mime/file_mime_decode.cc @@ -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; } + diff --git a/src/mime/file_mime_log.cc b/src/mime/file_mime_log.cc index 29daa9c0c..f458a4567 100644 --- a/src/mime/file_mime_log.cc +++ b/src/mime/file_mime_log.cc @@ -40,11 +40,10 @@ #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); } + diff --git a/src/mime/file_mime_log.h b/src/mime/file_mime_log.h index 0afd0e5b7..a450ff67b 100644 --- a/src/mime/file_mime_log.h +++ b/src/mime/file_mime_log.h @@ -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(); diff --git a/src/mime/file_mime_paf.cc b/src/mime/file_mime_paf.cc index 671946ceb..0d3c2c295 100644 --- a/src/mime/file_mime_paf.cc +++ b/src/mime/file_mime_paf.cc @@ -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; diff --git a/src/mime/file_mime_paf.h b/src/mime/file_mime_paf.h index 2b898d593..ab0c0365f 100644 --- a/src/mime/file_mime_paf.h +++ b/src/mime/file_mime_paf.h @@ -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 '-' */ }; diff --git a/src/mime/file_mime_process.cc b/src/mime/file_mime_process.cc index 5a3961766..3cb267fc2 100644 --- a/src/mime/file_mime_process.cc +++ b/src/mime/file_mime_process.cc @@ -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); } + diff --git a/src/mime/file_mime_process.h b/src/mime/file_mime_process.h index c0f53d417..f60ea68a5 100644 --- a/src/mime/file_mime_process.h +++ b/src/mime/file_mime_process.h @@ -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); diff --git a/src/service_inspectors/http_inspect/http_msg_body.cc b/src/service_inspectors/http_inspect/http_msg_body.cc index 67c59b3cf..60cbdac83 100644 --- a/src/service_inspectors/http_inspect/http_msg_body.cc +++ b/src/service_inspectors/http_inspect/http_msg_body.cc @@ -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) diff --git a/src/service_inspectors/http_inspect/http_msg_header.cc b/src/service_inspectors/http_inspect/http_msg_header.cc index b70c7a5b2..6411354eb 100644 --- a/src/service_inspectors/http_inspect/http_msg_header.cc +++ b/src/service_inspectors/http_inspect/http_msg_header.cc @@ -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 { diff --git a/src/service_inspectors/http_inspect/http_stream_splitter_scan.cc b/src/service_inspectors/http_inspect/http_stream_splitter_scan.cc index 5f795fb60..4a3db64da 100644 --- a/src/service_inspectors/http_inspect/http_stream_splitter_scan.cc +++ b/src/service_inspectors/http_inspect/http_stream_splitter_scan.cc @@ -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; }