From d2b70898b95e22a5dbae4cbc006ff50fdfc4b240 Mon Sep 17 00:00:00 2001 From: "Tom Peters (thopeter)" Date: Fri, 29 Oct 2021 18:25:31 +0000 Subject: [PATCH] Merge pull request #3133 in SNORT/snort3 from ~KATHARVE/snort3:http_zip_decomp to master Squashed commit of the following: commit eb7b2596fc637c46f2bcda85c222818cf47bed44 Author: Katura Harvey Date: Fri Oct 22 11:03:25 2021 -0400 http_inspect: file decompression improvements --- src/decompress/file_decomp_zip.cc | 11 +++++++---- .../http_inspect/http_flow_data.h | 2 ++ .../http_inspect/http_msg_body.cc | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/decompress/file_decomp_zip.cc b/src/decompress/file_decomp_zip.cc index adbcb5738..79e7d0e33 100644 --- a/src/decompress/file_decomp_zip.cc +++ b/src/decompress/file_decomp_zip.cc @@ -84,7 +84,7 @@ static fd_status_t Inflate(fd_session_t* SessionPtr) if ( z_ret != Z_OK ) return File_Decomp_Error; - if ( SessionPtr->Avail_Out == 0 ) + if ( SessionPtr->Avail_Out == 0 and SessionPtr->Avail_In > 0) return File_Decomp_BlockOut; return File_Decomp_OK; @@ -140,6 +140,7 @@ fd_status_t File_Decomp_End_ZIP(fd_session_t* SessionPtr) fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) { uint8_t byte; + bool output_blocked = false; if ( SessionPtr == nullptr ) return File_Decomp_Error; @@ -161,7 +162,7 @@ fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) { // check if we read a local_header if ( parser->local_header != ZIP_LOCAL_HEADER ) - return File_Decomp_Complete; + return output_blocked ? File_Decomp_BlockOut : File_Decomp_Complete; // read a local_header, reset the index parser->Index = 0; @@ -391,6 +392,8 @@ fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) if ( status == File_Decomp_BlockOut ) { // ran out of output space + // Save this status because we need to return it to the inspector so it can alert + output_blocked = true; if ( parser->data_descriptor ) { // close the inflate stream @@ -498,7 +501,7 @@ fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) Move_N(SessionPtr, min); // get more input - return File_Decomp_BlockIn; + return output_blocked ? File_Decomp_BlockOut : File_Decomp_BlockIn; } if ( SessionPtr->Avail_Out < skip ) @@ -550,6 +553,6 @@ fd_status_t File_Decomp_ZIP(fd_session_t* SessionPtr) parser->Index++; } - return File_Decomp_BlockIn; + return output_blocked ? File_Decomp_BlockOut : File_Decomp_BlockIn; } diff --git a/src/service_inspectors/http_inspect/http_flow_data.h b/src/service_inspectors/http_inspect/http_flow_data.h index cf02b77f6..084e61500 100644 --- a/src/service_inspectors/http_inspect/http_flow_data.h +++ b/src/service_inspectors/http_inspect/http_flow_data.h @@ -174,6 +174,8 @@ private: HttpCommon::STAT_NOT_PRESENT }; int32_t publish_depth_remaining[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT }; + int32_t file_decomp_buffer_size_remaining[2] = { HttpCommon::STAT_NOT_PRESENT, + HttpCommon::STAT_NOT_PRESENT }; uint64_t expected_trans_num[2] = { 1, 1 }; // number of user data octets seen so far (regular body or chunks) diff --git a/src/service_inspectors/http_inspect/http_msg_body.cc b/src/service_inspectors/http_inspect/http_msg_body.cc index b48394cc6..722ec1159 100644 --- a/src/service_inspectors/http_inspect/http_msg_body.cc +++ b/src/service_inspectors/http_inspect/http_msg_body.cc @@ -125,7 +125,12 @@ void HttpMsgBody::analyze() msg_text.start() + partial_inspected_octets); } else + { + // First flush of inspection section - set full file decompress buffer size + session_data->file_decomp_buffer_size_remaining[source_id] = + FileService::decode_conf.get_decompress_buffer_size(); msg_text_new.set(msg_text); + } int32_t& pub_depth_remaining = session_data->publish_depth_remaining[source_id]; if (pub_depth_remaining > 0) @@ -155,7 +160,10 @@ void HttpMsgBody::analyze() if (partial_detect_length > 0) { - const int32_t total_length = partial_detect_length + decompressed_file_body.length(); + const int32_t total_length = partial_detect_length + + decompressed_file_body.length(); + assert(total_length <= + (int64_t)FileService::decode_conf.get_decompress_buffer_size()); uint8_t* const cumulative_buffer = new uint8_t[total_length]; memcpy(cumulative_buffer, partial_detect_buffer, partial_detect_length); memcpy(cumulative_buffer + partial_detect_length, decompressed_file_body.start(), @@ -251,7 +259,7 @@ void HttpMsgBody::do_file_decompression(const Field& input, Field& output) output.set(input); return; } - const uint32_t buffer_size = FileService::decode_conf.get_decompress_buffer_size(); + const uint32_t buffer_size = session_data->file_decomp_buffer_size_remaining[source_id]; uint8_t* buffer = new uint8_t[buffer_size]; session_data->fd_alert_context.infractions = transaction->get_infractions(source_id); session_data->fd_alert_context.events = session_data->events[source_id]; @@ -279,7 +287,11 @@ void HttpMsgBody::do_file_decompression(const Field& input, Field& output) create_event(EVENT_FILE_DECOMPR_OVERRUN); // Fall through default: - output.set(session_data->fd_state->Next_Out - buffer, buffer, true); + const uint32_t output_length = session_data->fd_state->Next_Out - buffer; + output.set(output_length, buffer, true); + assert((uint64_t)session_data->file_decomp_buffer_size_remaining[source_id] >= + output_length); + session_data->file_decomp_buffer_size_remaining[source_id] -= output_length; break; } } -- 2.47.3