]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #3133 in SNORT/snort3 from ~KATHARVE/snort3:http_zip_decomp to...
authorTom Peters (thopeter) <thopeter@cisco.com>
Fri, 29 Oct 2021 18:25:31 +0000 (18:25 +0000)
committerTom Peters (thopeter) <thopeter@cisco.com>
Fri, 29 Oct 2021 18:25:31 +0000 (18:25 +0000)
Squashed commit of the following:

commit eb7b2596fc637c46f2bcda85c222818cf47bed44
Author: Katura Harvey <katharve@cisco.com>
Date:   Fri Oct 22 11:03:25 2021 -0400

    http_inspect: file decompression improvements

src/decompress/file_decomp_zip.cc
src/service_inspectors/http_inspect/http_flow_data.h
src/service_inspectors/http_inspect/http_msg_body.cc

index adbcb5738eec6603bddbb03eb1cf1dc7e48744e6..79e7d0e33338f4a1e6f840e1aad7897df444efa3 100644 (file)
@@ -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;
 }
 
index cf02b77f6dbc0596d73bf3ebd5955024da281a41..084e615004086e8c73cdf35a3f01771b674a7b78 100644 (file)
@@ -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)
index b48394cc639ce9ddfa32bc6520e910f22437ebda..722ec11590f4ac314be2481c0862308f51699522 100644 (file)
@@ -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;
     }
 }