]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Squashed commit of the following:
authorRuss Combs <rucombs@cisco.com>
Thu, 13 Aug 2015 20:36:52 +0000 (16:36 -0400)
committerRuss Combs <rucombs@cisco.com>
Thu, 13 Aug 2015 20:36:52 +0000 (16:36 -0400)
commit 9cd674ab93a9a9835d0ae5868447e70789ebf480
Author: Tom Peters <thopeter@cisco.com>
Date:   Thu Jul 23 11:04:54 2015 -0400

    Flow depth support for NHI

28 files changed:
.gitignore
src/service_inspectors/nhttp_inspect/nhttp_api.cc
src/service_inspectors/nhttp_inspect/nhttp_cutter.cc
src/service_inspectors/nhttp_inspect/nhttp_cutter.h
src/service_inspectors/nhttp_inspect/nhttp_enum.h
src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc
src/service_inspectors/nhttp_inspect/nhttp_flow_data.h
src/service_inspectors/nhttp_inspect/nhttp_inspect.cc
src/service_inspectors/nhttp_inspect/nhttp_inspect.h
src/service_inspectors/nhttp_inspect/nhttp_module.cc
src/service_inspectors/nhttp_inspect/nhttp_module.h
src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_body.h
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk.h
src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h
src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_header.h
src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_request.h
src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_section.h
src/service_inspectors/nhttp_inspect/nhttp_msg_start.h
src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_status.h
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h
src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc

index 4a34bb1b3df00e0ebb99fbd177532b1680484e65..4805b22f371880c344562ee563bae698edad58ee 100644 (file)
@@ -46,6 +46,7 @@ doc/search_engine.txt
 doc/signals.txt
 doc/snort2lua_cmds.txt
 doc/snort_manual.chunked/
+doc/snort_manual.chunked.tgz
 doc/snort_manual.html
 doc/snort_manual.pdf
 doc/snort_manual.text
index d38aa853fe479f4ec2dea83c0759b6a98dda0e13..25792e8cdc255ce47eb861f701179550e6640e5f 100644 (file)
@@ -30,7 +30,7 @@ const char* NHttpApi::nhttp_help = "the new HTTP inspector!";
 Inspector* NHttpApi::nhttp_ctor(Module* mod)
 {
     const NHttpModule* const nhttp_mod = (NHttpModule*)mod;
-    return new NHttpInspect(nhttp_mod->get_test_input(), nhttp_mod->get_test_output());
+    return new NHttpInspect(nhttp_mod->get_params());
 }
 
 static const char* legacy_buffers[] =
index 4e68d139f9ea2757df0728cd85e7f2a918207c27..fcba4bd99bd40e9f98af16056a31cbca3c6ca351 100644 (file)
@@ -172,11 +172,28 @@ ScanResult NHttpHeaderCutter::cut(const uint8_t* buffer, uint32_t length,
     return SCAN_NOTFOUND;
 }
 
-ScanResult NHttpBodyCutter::cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&,
-    uint32_t flow_target, uint32_t flow_max)
+ScanResult NHttpBodyCutter::cut(const uint8_t*, uint32_t length, NHttpInfractions&,
+    NHttpEventGen&, uint32_t flow_target, uint32_t flow_max)
 {
     assert(remaining > 0);
 
+    // Are we skipping to the next message?
+    if (flow_target == 0)
+    {
+        if (remaining <= length)
+        {
+            num_flush = remaining;
+            remaining = 0;
+            return SCAN_DISCARD;
+        }
+        else
+        {
+            num_flush = length;
+            remaining -= num_flush;
+            return SCAN_DISCARD_PIECE;
+        }
+    }
+
     // The normal body section size is flow_target. But if there are only flow_max or less
     // remaining we take the whole thing rather than leave a small final section.
     if (remaining <= flow_max)
@@ -197,6 +214,9 @@ ScanResult NHttpBodyCutter::cut(const uint8_t*, uint32_t, NHttpInfractions&, NHt
 ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
     NHttpInfractions& infractions, NHttpEventGen& events, uint32_t flow_target, uint32_t)
 {
+    // Are we skipping through the rest of this chunked body to the trailers and the next message?
+    const bool discard_mode = (flow_target == 0);
+
     if (new_section)
     {
         new_section = false;
@@ -204,8 +224,6 @@ ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
         num_good_chunks = 0;
     }
 
-    // FIXIT-M there are examples of chunk lengths with trailing white space, need to address that
-
     for (uint32_t k=0; k < length; k++)
     {
         switch (curr_state)
@@ -313,7 +331,7 @@ ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
                 // Terminating zero-length chunk
                 num_good_chunks++;
                 num_flush = k+1;
-                return SCAN_FOUND;
+                return !discard_mode ? SCAN_FOUND : SCAN_DISCARD;
             }
             else
             {
@@ -326,8 +344,10 @@ ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
         case CHUNK_DATA:
           {
             uint32_t skip_amount = (length-k <= expected) ? length-k : expected;
-            skip_amount = (skip_amount <= flow_target-data_seen) ? skip_amount :
-                flow_target-data_seen;
+            if (!discard_mode && (skip_amount > flow_target-data_seen))
+            { // Do not exceed requested section size
+                skip_amount = flow_target-data_seen;
+            }
             k += skip_amount - 1;
             if ((expected -= skip_amount) == 0)
             {
@@ -368,6 +388,11 @@ ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
             digits_seen = 0;
             break;
         case CHUNK_BAD:
+            // If we are skipping to the trailers and next message the broken chunk thwarts us
+            if (discard_mode)
+            {
+                return SCAN_ABORT;
+            }
             uint32_t skip_amount = length-k;
             skip_amount = (skip_amount <= flow_target-data_seen) ? skip_amount :
                 flow_target-data_seen;
@@ -384,6 +409,11 @@ ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
         }
     }
     octets_seen += length;
+    if (discard_mode)
+    {
+        num_flush = length;
+        return SCAN_DISCARD_PIECE;
+    }
     return SCAN_NOTFOUND;
 }
 
index ae284f67db84fef988cb4c839e7941050b34d888..ce68cc7edda82d3e8c927804ce2b4b1594264ebb 100644 (file)
@@ -100,7 +100,7 @@ class NHttpBodyCutter : public NHttpCutter
 public:
     explicit NHttpBodyCutter(int64_t expected_length) : remaining(expected_length)
         { assert(remaining > 0); }
-    NHttpEnums::ScanResult cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&,
+    NHttpEnums::ScanResult cut(const uint8_t*, uint32_t length, NHttpInfractions&, NHttpEventGen&,
         uint32_t flow_target, uint32_t flow_max) override;
 
 private:
index fb9d231779f48e19c7029ddc7205144bd4cc468b..e5848a2ab2310d53c28ab1cfee104c34693e6905 100644 (file)
@@ -27,6 +27,7 @@ namespace NHttpEnums
 static const int MAX_OCTETS = 65535;
 static const int DATA_BLOCK_SIZE = 16384;
 static const int FINAL_BLOCK_SIZE = 24576;
+static const int GZIP_BLOCK_SIZE = 4096;
 static const uint32_t NHTTP_GID = 219;
 
 // Field status codes for when no valid value is present in length or integer value. Positive
@@ -43,7 +44,8 @@ enum SectionType { SEC_DISCARD = -19, SEC_ABORT = -18, SEC__NOTCOMPUTE=-14, SEC_
     SEC_REQUEST = 2, SEC_STATUS, SEC_HEADER, SEC_BODY, SEC_CHUNK, SEC_TRAILER };
 
 // Result of scanning by splitter
-enum ScanResult { SCAN_NOTFOUND, SCAN_FOUND, SCAN_FOUND_PIECE, SCAN_DISCARD, SCAN_ABORT };
+enum ScanResult { SCAN_NOTFOUND, SCAN_FOUND, SCAN_FOUND_PIECE, SCAN_DISCARD, SCAN_DISCARD_PIECE,
+    SCAN_ABORT };
 
 // State machine for chunk parsing
 enum ChunkState { CHUNK_ZEROS, CHUNK_NUMBER, CHUNK_WHITESPACE, CHUNK_OPTIONS, CHUNK_HCRLF,
index 198831bb24845027f76e581e1340b28f93c7cc30..a5988e6e1cb7c5f20e8e6f223161cfd03ac908d7 100644 (file)
@@ -29,7 +29,6 @@ uint64_t NHttpFlowData::instance_count = 0;
 
 NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id)
 {
-    /* FIXIT-L Temporary printf while we shake out stream interface */
     if (!NHttpTestManager::use_test_input() && NHttpTestManager::use_test_output())
     {
         seq_num = ++instance_count;
@@ -40,7 +39,6 @@ NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id)
 
 NHttpFlowData::~NHttpFlowData()
 {
-    /* FIXIT-L Temporary printf while we shake out stream interface */
     if (!NHttpTestManager::use_test_input() && NHttpTestManager::use_test_output())
     {
         printf("Flow Data destruct %" PRIu64 "\n", seq_num);
@@ -71,8 +69,12 @@ void NHttpFlowData::half_reset(SourceId source_id)
     section_size_target[source_id] = 0;
     section_size_max[source_id] = 0;
     file_depth_remaining[source_id] = STAT_NOTPRESENT;
+    detect_depth_remaining[source_id] = STAT_NOTPRESENT;
     infractions[source_id].reset();
     events[source_id].reset();
+    chunk_offset[source_id] = 0;
+    chunk_state[source_id] = CHUNK_NUMBER;
+    chunk_expected_length[source_id] = 0;
 
     if (source_id == SRC_CLIENT)
     {
index fcc86a81ac477d230835d9a47f20f0363684df78..46710fe850e7d25db8612c2f3c45ca510afb1fd0 100644 (file)
@@ -96,6 +96,8 @@ private:
     NHttpEnums::MethodId method_id = NHttpEnums::METH__NOTPRESENT;
     int32_t status_code_num = NHttpEnums::STAT_NOTPRESENT;
     int64_t file_depth_remaining[2] = { NHttpEnums::STAT_NOTPRESENT, NHttpEnums::STAT_NOTPRESENT };
+    int64_t detect_depth_remaining[2] = { NHttpEnums::STAT_NOTPRESENT,
+        NHttpEnums::STAT_NOTPRESENT };
     MimeState* mime_state = nullptr;  // SRC_CLIENT only
 
     // number of user data octets seen so far (regular body or chunks)
index 61d54046acb6858ed1de8ac985440e0f96b3aa42..c0b1bbd1695eebd795acf32c8ddd8916e946ca30 100644 (file)
 
 using namespace NHttpEnums;
 
-NHttpInspect::NHttpInspect(bool test_input, bool test_output)
+NHttpInspect::NHttpInspect(NHttpParaList params_) : params(params_)
 {
-    if (test_input)
+    if (params.test_input)
     {
         NHttpTestManager::activate_test_input();
     }
-    if (test_output)
+    if (params.test_output)
     {
         NHttpTestManager::activate_test_output();
     }
@@ -97,23 +97,27 @@ bool NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* cons
     {
     case SEC_REQUEST:
         latest_section = new NHttpMsgRequest(data, dsize, session_data, source_id, buf_owner,
-            flow);
+            flow, &params);
         break;
     case SEC_STATUS:
-        latest_section = new NHttpMsgStatus(data, dsize, session_data, source_id, buf_owner, flow);
+        latest_section = new NHttpMsgStatus(data, dsize, session_data, source_id, buf_owner, flow,
+            &params);
         break;
     case SEC_HEADER:
-        latest_section = new NHttpMsgHeader(data, dsize, session_data, source_id, buf_owner, flow);
+        latest_section = new NHttpMsgHeader(data, dsize, session_data, source_id, buf_owner, flow,
+            &params);
         break;
     case SEC_BODY:
-        latest_section = new NHttpMsgBody(data, dsize, session_data, source_id, buf_owner, flow);
+        latest_section = new NHttpMsgBody(data, dsize, session_data, source_id, buf_owner, flow,
+            &params);
         break;
     case SEC_CHUNK:
-        latest_section = new NHttpMsgChunk(data, dsize, session_data, source_id, buf_owner, flow);
+        latest_section = new NHttpMsgChunk(data, dsize, session_data, source_id, buf_owner, flow,
+            &params);
         break;
     case SEC_TRAILER:
         latest_section = new NHttpMsgTrailer(data, dsize, session_data, source_id, buf_owner,
-            flow);
+            flow, &params);
         break;
     default:
         assert(0);
index b1b2958df95e30616d56baeb8f1c0fca27c53857..a8237fb3050a2a6319a084cbd24f5a7251f07fdf 100644 (file)
@@ -27,6 +27,7 @@
 #include "log/messages.h"
 
 #include "nhttp_enum.h"
+#include "nhttp_module.h"
 #include "nhttp_stream_splitter.h"
 
 class NHttpApi;
@@ -37,7 +38,7 @@ class NHttpInspect : public Inspector
 public:
     static THREAD_LOCAL uint8_t body_buffer[NHttpEnums::MAX_OCTETS];
 
-    NHttpInspect(bool test_input, bool test_output);
+    NHttpInspect(NHttpParaList params_);
 
     bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override;
     bool get_buf(unsigned, Packet*, InspectionBuffer&) override;
@@ -61,6 +62,8 @@ private:
         NHttpEnums::SourceId source_id_, bool buf_owner) const;
 
     static THREAD_LOCAL NHttpMsgSection* latest_section;
+
+    const NHttpParaList params;
 };
 
 #endif
index 771ed15631401fa69ebd2e933227f6eef2912ba7..13ba40d60acf94dc194aced478c228552ba4d00c 100644 (file)
@@ -26,13 +26,15 @@ const Parameter NHttpModule::nhttp_params[] =
 {
     { "test_input", Parameter::PT_BOOL, nullptr, "false", "read HTTP messages from text file" },
     { "test_output", Parameter::PT_BOOL, nullptr, "false", "print out HTTP section data" },
+    { "request_depth", Parameter::PT_INT, "-1:", "-1",
+          "maximum request message body bytes to examine (-1 no limit)" },
+    { "response_depth", Parameter::PT_INT, "-1:", "-1",
+          "maximum response message body bytes to examine (-1 no limit)" },
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
 bool NHttpModule::begin(const char*, int, SnortConfig*)
 {
-    test_input = false;
-    test_output = false;
     return true;
 }
 
@@ -40,11 +42,19 @@ bool NHttpModule::set(const char*, Value& val, SnortConfig*)
 {
     if (val.is("test_input"))
     {
-        test_input = val.get_bool();
+        params.test_input = val.get_bool();
     }
     else if (val.is("test_output"))
     {
-        test_output = val.get_bool();
+        params.test_output = val.get_bool();
+    }
+    else if (val.is("request_depth"))
+    {
+        params.request_depth = val.get_long();
+    }
+    else if (val.is("response_depth"))
+    {
+        params.response_depth = val.get_long();
     }
     else
     {
index f09fea5b6c57f6fdc239c99e914721b2e1e20fee..f7afed62a0bc7de42db1976bbd131558272cf846 100644 (file)
 #define NHTTP_NAME "new_http_inspect"
 #define NHTTP_HELP "new HTTP inspector"
 
+struct NHttpParaList
+{
+public:
+    bool test_input;
+    bool test_output;
+    long request_depth;
+    long response_depth;
+};
+
 class NHttpModule : public Module
 {
 public:
@@ -36,14 +45,12 @@ public:
     bool set(const char*, Value&, SnortConfig*) override;
     unsigned get_gid() const override { return NHttpEnums::NHTTP_GID; }
     const RuleMap* get_rules() const override { return nhttp_events; }
-    bool get_test_input() const { return test_input; }
-    bool get_test_output() const { return test_output; }
+    NHttpParaList get_params() const { return params; }
 
 private:
     static const Parameter nhttp_params[];
     static const RuleMap nhttp_events[];
-    bool test_input = false;
-    bool test_output = false;
+    NHttpParaList params;
 };
 
 #endif
index 2eae4015da85b8ab92443c83c1bebdeabd5961a0..c5ae1fbeacf16c250cbe90d8cc2b442b4e7ac246 100644 (file)
@@ -32,8 +32,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgBody::NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_),
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_),
     data_length(session_data->data_length[source_id]),
     body_octets(session_data->body_octets[source_id])
 {
@@ -42,13 +43,18 @@ NHttpMsgBody::NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size,
 
 void NHttpMsgBody::analyze()
 {
-    data.start = msg_text.start;
-    data.length = msg_text.length;
+    detect_data.length = (msg_text.length <= session_data->detect_depth_remaining[source_id]) ?
+       msg_text.length : session_data->detect_depth_remaining[source_id];
+    detect_data.start = msg_text.start;
+    session_data->detect_depth_remaining[source_id] -= detect_data.length;
 
     // Always set file data. File processing will later set a new value in some cases.
-    if (data.length > 0)
+    // FIXIT-M should file data length here be independent of file_depth_remaining?
+    file_data.length = msg_text.length;
+    if (file_data.length > 0)
     {
-        set_file_data(const_cast<uint8_t*>(data.start), (unsigned)data.length);
+        file_data.start = msg_text.start;
+        set_file_data(const_cast<uint8_t*>(file_data.start), (unsigned)file_data.length);
     }
 
     if (session_data->file_depth_remaining[source_id] > 0)
@@ -74,17 +80,17 @@ void NHttpMsgBody::do_file_processing()
     else file_position = SNORT_FILE_MIDDLE;
 
     // Chunked body with nothing but the zero length chunk?
-    if (front && (data.length == 0))
+    if (front && (file_data.length == 0))
     {
         return;
     }
 
-    const int32_t fp_length = (data.length <= session_data->file_depth_remaining[source_id]) ?
-        data.length : session_data->file_depth_remaining[source_id];
+    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 (file_api->file_process(flow, const_cast<uint8_t*>(data.start), fp_length,
+        if (file_api->file_process(flow, const_cast<uint8_t*>(file_data.start), fp_length,
             file_position, false, false))
         {
             session_data->file_depth_remaining[source_id] -= fp_length;
@@ -112,7 +118,7 @@ void NHttpMsgBody::do_file_processing()
     }
     else
     {
-        file_api->process_mime_data(flow, data.start, data.start + fp_length,
+        file_api->process_mime_data(flow, file_data.start, file_data.start + fp_length,
             session_data->mime_state, true, file_position);
 
         session_data->file_depth_remaining[source_id] -= fp_length;
@@ -133,7 +139,8 @@ void NHttpMsgBody::print_section(FILE* output)
     NHttpMsgSection::print_message_title(output, "body");
     fprintf(output, "Expected data length %" PRIi64 ", octets seen %" PRIi64 "\n", data_length,
         body_octets);
-    data.print(output, "Data");
+    detect_data.print(output, "Detect data");
+    file_data.print(output, "File data");
     NHttpMsgSection::print_message_wrapup(output);
 }
 
@@ -143,8 +150,7 @@ void NHttpMsgBody::update_flow()
     {
         // More body coming
         session_data->body_octets[source_id] = body_octets;
-        session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
-        session_data->section_size_max[source_id] = FINAL_BLOCK_SIZE;
+        update_depth();
         session_data->infractions[source_id] = infractions;
         session_data->events[source_id] = events;
     }
index 5b4e4659134ac618221912c01b5358db4559af70..3385c900cb491c7d97aed269d0a85a4adcd228b4 100644 (file)
@@ -31,18 +31,22 @@ class NHttpMsgBody : public NHttpMsgSection
 {
 public:
     NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     void analyze() override;
     void print_section(FILE* output) override;
     void gen_events() override;
     void update_flow() override;
-    Field& get_data() { return data; }
+    Field& get_detect_data() { return detect_data; }
+    bool worth_detection() const override { return (detect_data.length > 0); }
 
 protected:
-    int64_t data_length; // FIXIT-M this has no meaning in chunk subclass. Potential source of errors.
+    int64_t data_length; // FIXIT-M this has no meaning in chunk subclass. Potential source of
+                         // errors.
     int64_t body_octets;
 
-    Field data;
+    Field detect_data;
+    Field file_data;
 
     void do_file_processing();
 };
index 83b65e8d4aa2bbc9a0272cbdd173b0398cebfcd6..f39c55fdb9e15691f3a462d3b9e74c1c0eedb0b1 100644 (file)
@@ -29,8 +29,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgChunk::NHttpMsgChunk(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgBody(buffer, buf_size, session_data_, source_id_, buf_owner, flow_)
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgBody(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
 {
     transaction->set_body(this);
 }
@@ -41,7 +42,8 @@ void NHttpMsgChunk::print_section(FILE* output)
 {
     NHttpMsgSection::print_message_title(output, "chunked body");
     fprintf(output, "Cumulative octets %" PRIi64 "\n", body_octets);
-    data.print(output, "Data");
+    detect_data.print(output, "Detect data");
+    file_data.print(output, "File data");
     NHttpMsgSection::print_message_wrapup(output);
 }
 
@@ -64,7 +66,7 @@ void NHttpMsgChunk::update_flow()
     else
     {
         session_data->body_octets[source_id] = body_octets;
-        session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
+        update_depth();
         session_data->infractions[source_id] = infractions;
         session_data->events[source_id] = events;
     }
index 6fc42d67397ac9758302b11242d632912a0b9550..57ff77eaa17f4bde6924285d3f149d5bf3be5668 100644 (file)
@@ -30,7 +30,8 @@ class NHttpMsgChunk : public NHttpMsgBody
 {
 public:
     NHttpMsgChunk(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     void print_section(FILE* output) override;
     void gen_events() override;
     void update_flow() override;
index 588d23fc3a64f8cad2d35bda2b007102ae41d388..d0d6c32483e0abda66ffb48ad5d61909b08cabaa 100644 (file)
@@ -49,8 +49,10 @@ public:
 
 protected:
     NHttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size,
-        NHttpFlowData* session_data_, NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_)
-        : NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_) { }
+        NHttpFlowData* session_data_, NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_)
+        : NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
+        { }
 
     // Header normalization strategies. There should be one defined for every different way we can
     // process a header field value.
index d5d4721672fd2a7c6854d23dc8a020ace939dcc9..f447b9795b45ebbf9bd176e359a1cfeb596f2c26 100644 (file)
@@ -31,8 +31,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgHeader::NHttpMsgHeader(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgHeadShared(buffer, buf_size, session_data_, source_id_, buf_owner, flow_)
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgHeadShared(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
 {
     transaction->set_header(this, source_id);
 }
@@ -82,14 +83,7 @@ void NHttpMsgHeader::update_flow()
         // FIXIT-M inspect for Content-Length header which should not be present
         // Chunked body
         session_data->type_expected[source_id] = SEC_CHUNK;
-        session_data->body_octets[source_id] = 0;
-        session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
-        if (session_data->file_depth_remaining[1-source_id] <= 0)
-        {   // Bidirectional file processing is problematic FIXIT-M
-            session_data->file_depth_remaining[source_id] = file_api->get_max_file_depth();
-        }
-        session_data->infractions[source_id].reset();
-        session_data->events[source_id].reset();
+        prepare_body();
     }
     else if ((get_header_value_norm(HEAD_CONTENT_LENGTH).length > 0) &&
         (*(int64_t*)get_header_value_norm(HEAD_CONTENT_LENGTH).start > 0))
@@ -98,27 +92,7 @@ void NHttpMsgHeader::update_flow()
         session_data->type_expected[source_id] = SEC_BODY;
         session_data->data_length[source_id] = *(int64_t*)get_header_value_norm(
             HEAD_CONTENT_LENGTH).start;
-        session_data->body_octets[source_id] = 0;
-        session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
-        session_data->section_size_max[source_id] = FINAL_BLOCK_SIZE;
-        if (session_data->file_depth_remaining[1-source_id] <= 0)
-        {   // Bidirectional file processing is problematic FIXIT-M
-            session_data->file_depth_remaining[source_id] = file_api->get_max_file_depth();
-            if (source_id == SRC_CLIENT)
-            {
-                // FIXIT-L Cannot use new because file_api insists on freeing the mime_state using
-                // free().
-                session_data->mime_state = (MimeState*) new_calloc(1, sizeof(MimeState));
-                file_api->set_mime_log_config_defauts(&mime_conf);
-                session_data->mime_state->log_config = &mime_conf;
-                file_api->set_mime_decode_config_defauts(&decode_conf);
-                session_data->mime_state->decode_conf = &decode_conf;
-                file_api->set_log_buffers(&session_data->mime_state->log_state,
-                    session_data->mime_state->log_config);
-            }
-        }
-        session_data->infractions[source_id].reset();
-        session_data->events[source_id].reset();
+        prepare_body();
     }
     else
     {
@@ -130,3 +104,46 @@ void NHttpMsgHeader::update_flow()
     session_data->section_type[source_id] = SEC__NOTCOMPUTE;
 }
 
+// Common activities of preparing for upcoming regular body or chunked body
+void NHttpMsgHeader::prepare_body()
+{
+    session_data->body_octets[source_id] = 0;
+    const int64_t& depth = (source_id == SRC_CLIENT) ? params->request_depth :
+        params->response_depth;
+    session_data->detect_depth_remaining[source_id] = (depth != -1) ? depth : INT64_MAX;
+    setup_file_processing();
+    setup_decompression();
+    update_depth();
+    session_data->infractions[source_id].reset();
+    session_data->events[source_id].reset();
+}
+
+void NHttpMsgHeader::setup_file_processing()
+{
+    // FIXIT-M Bidirectional file processing is problematic so we don't do it. When the library
+    // fully supports it remove the outer if statement that prevents it from being done.
+    if (session_data->file_depth_remaining[1-source_id] == 0)
+    {
+        if ((session_data->file_depth_remaining[source_id] = file_api->get_max_file_depth()) < 0)
+        {
+           session_data->file_depth_remaining[source_id] = 0;
+        }
+        if (source_id == SRC_CLIENT)
+        {
+            // FIXIT-L Cannot use new because file_api insists on freeing the mime_state using
+            // free().
+            session_data->mime_state = (MimeState*) new_calloc(1, sizeof(MimeState));
+            file_api->set_mime_log_config_defauts(&mime_conf);
+            session_data->mime_state->log_config = &mime_conf;
+            file_api->set_mime_decode_config_defauts(&decode_conf);
+            session_data->mime_state->decode_conf = &decode_conf;
+            file_api->set_log_buffers(&session_data->mime_state->log_state,
+                session_data->mime_state->log_config);
+        }
+    }
+}
+
+void NHttpMsgHeader::setup_decompression()
+{
+}
+
index 0fe04b181f8edb8d10e0cea96f60416594b676f5..72e131a83b2979da81df9def85a6131686780ee5 100644 (file)
@@ -32,7 +32,8 @@ class NHttpMsgHeader : public NHttpMsgHeadShared
 {
 public:
     NHttpMsgHeader(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     void print_section(FILE* output) override;
     void gen_events() override;
     void update_flow() override;
@@ -40,6 +41,10 @@ private:
     // Dummy configurations to support MIME processing
     MAIL_LogConfig mime_conf;
     DecodeConfig decode_conf;
+
+    void prepare_body();
+    void setup_file_processing();
+    void setup_decompression();
 };
 
 #endif
index 4b3057511ad14c4484ce24cfbe51f4a931a523eb..2f58975c9e28572cbf89f84113c147e37950a2f5 100644 (file)
@@ -31,8 +31,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgRequest::NHttpMsgRequest(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgStart(buffer, buf_size, session_data_, source_id_, buf_owner, flow_)
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgStart(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
 {
     transaction->set_request(this);
 }
index 885b5ac3498b47fd4ad7a7d789dce746fd627503..34244c0a004e27a5132a07601e38f3f6dd65106c 100644 (file)
@@ -34,7 +34,8 @@ class NHttpMsgRequest : public NHttpMsgStart
 {
 public:
     NHttpMsgRequest(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     ~NHttpMsgRequest() { delete uri; }
     void print_section(FILE* output) override;
     void gen_events() override;
index 1609486d754912a48ee6121f1197cd0522263d27..e68ff5f146560b8381680d70d2a54431ce3f6663 100644 (file)
 using namespace NHttpEnums;
 
 NHttpMsgSection::NHttpMsgSection(const uint8_t* buffer, const uint16_t buf_size,
-       NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
+       NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+       const NHttpParaList* params_) :
     msg_text(buf_size, buffer),
     session_data(session_data_),
     source_id(source_id_),
     flow(flow_),
+    params(params_),
     transaction(NHttpTransaction::attach_my_transaction(session_data, source_id)),
     tcp_close(session_data->tcp_close[source_id]),
     scratch_pad(2*buf_size+500),
@@ -73,6 +75,18 @@ void NHttpMsgSection::print_message_wrapup(FILE* output)
     fprintf(output, "\n");
 }
 
+void NHttpMsgSection::update_depth() const
+{
+    const int64_t& depth = (session_data->file_depth_remaining[source_id] >=
+                            session_data->detect_depth_remaining[source_id]) ?
+        session_data->file_depth_remaining[source_id] :
+        session_data->detect_depth_remaining[source_id];
+    session_data->section_size_target[source_id] = (depth <= DATA_BLOCK_SIZE) ? depth :
+        DATA_BLOCK_SIZE;
+    session_data->section_size_max[source_id] = (depth <= FINAL_BLOCK_SIZE) ? depth :
+        FINAL_BLOCK_SIZE;
+}
+
 const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
 {
     // When current section is trailers, that is what will be used for header and cookie buffers.
@@ -81,7 +95,7 @@ const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
     case HTTP_BUFFER_CLIENT_BODY:
       {
         NHttpMsgBody* body = transaction->get_body();
-        return (body != nullptr) ? body->get_data() : Field::FIELD_NULL;
+        return (body != nullptr) ? body->get_detect_data() : Field::FIELD_NULL;
       }
     case HTTP_BUFFER_COOKIE:
       {
index 3c063da6fc15de758d13504096fc4765d5eea7be..a80f52f4ad725a8154fd7964ef0d1829b016ace8 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "nhttp_scratch_pad.h"
 #include "nhttp_field.h"
+#include "nhttp_module.h"
 #include "nhttp_flow_data.h"
 #include "nhttp_transaction.h"
 #include "nhttp_infractions.h"
@@ -50,7 +51,7 @@ public:
     const Field& get_legacy(unsigned buffer_id);
 
     // Should this section be sent directly to detection after inspection?
-    bool worth_detection() { return (msg_text.length > 0); }
+    virtual bool worth_detection() const { return (msg_text.length > 0); }
 
     NHttpEnums::MethodId get_method_id() const { return method_id; }
 
@@ -59,18 +60,21 @@ public:
 
 protected:
     NHttpMsgSection(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_, const NHttpParaList*
+        params_);
 
     // Convenience methods
     void print_message_title(FILE* output, const char* title) const;
     void print_message_wrapup(FILE* output);
+    void update_depth() const;
 
     const Field msg_text;
 
     NHttpFlowData* const session_data;
     const NHttpEnums::SourceId source_id;
     Flow* const flow;
-    NHttpTransaction* transaction;
+    const NHttpParaList* const params;
+    NHttpTransaction* const transaction;
     const bool tcp_close;
     ScratchPad scratch_pad;
 
index f80f61d5298316f23a55fe24854d62c2fcb81862..0f552b694fc8423147103aa6938e953a8b93f79d 100644 (file)
@@ -35,8 +35,9 @@ public:
 
 protected:
     NHttpMsgStart(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_) :
-        NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_) { }
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_, const NHttpParaList* params_)
+        : NHttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
+        { }
     virtual void parse_start_line() = 0;
     void derive_version_id();
 
index 48fa475a5de85ea3be48dc1cbc5016eab3c5e88a..b1b95d36549a034c5deefddceb4999b768fc6583 100644 (file)
@@ -31,8 +31,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgStatus::NHttpMsgStatus(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgStart(buffer, buf_size, session_data_, source_id_, buf_owner, flow_)
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgStart(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
 {
     transaction->set_status(this);
 }
index 9d116bb5527fb9fce5637e50b166cecbf7cb9b36..71c8ef42c705b28758c7ce4ba0ff7eaa7d5c3c46 100644 (file)
@@ -31,7 +31,8 @@ class NHttpMsgStatus : public NHttpMsgStart
 {
 public:
     NHttpMsgStatus(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     void print_section(FILE* output) override;
     void gen_events() override;
     void update_flow() override;
index f35a0232e88b1d0ec2d6243e28be3d98b2797528..2eeb39ecbac1178f2fb13f937673ab307b247c60 100644 (file)
@@ -29,8 +29,9 @@
 using namespace NHttpEnums;
 
 NHttpMsgTrailer::NHttpMsgTrailer(const uint8_t* buffer, const uint16_t buf_size,
-    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_) :
-    NHttpMsgHeadShared(buffer, buf_size, session_data_, source_id_, buf_owner, flow_)
+    NHttpFlowData* session_data_, SourceId source_id_, bool buf_owner, Flow* flow_,
+    const NHttpParaList* params_) :
+    NHttpMsgHeadShared(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
 {
     transaction->set_trailer(this, source_id);
 }
index e366337194cfebfe9b174125013fc7453677dfbe..44a1fb1894d6d27a2a40926d00ef5d70e32e2989 100644 (file)
@@ -30,7 +30,8 @@ class NHttpMsgTrailer : public NHttpMsgHeadShared
 {
 public:
     NHttpMsgTrailer(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
-        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_);
+        NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
+        const NHttpParaList* params_);
     void print_section(FILE* output) override;
     void gen_events() override;
     void update_flow() override;
index 1af30bcf4acc5d9911d2b9063b704243b25c9cc1..864b9bd6e3be28f83de7b0be891008b5eb178fdd 100644 (file)
@@ -247,10 +247,14 @@ StreamSplitter::Status NHttpStreamSplitter::scan(Flow* flow, const uint8_t* data
             return StreamSplitter::FLUSH;
         }
     case SCAN_DISCARD:
+    case SCAN_DISCARD_PIECE:
         prepare_flush(session_data, flush_offset, SEC_DISCARD, cutter->get_num_flush(),
             cutter->get_octets_seen(), 0, 0, false, 0);
-        delete cutter;
-        cutter = nullptr;
+        if (cut_result == SCAN_DISCARD)
+        {
+            delete cutter;
+            cutter = nullptr;
+        }
         return StreamSplitter::FLUSH;
     case SCAN_FOUND:
     case SCAN_FOUND_PIECE:
@@ -335,7 +339,29 @@ const StreamBuffer* NHttpStreamSplitter::reassemble(Flow* flow, unsigned total,
             fprintf(NHttpTestManager::get_output_file(), "Discarded %u octets\n\n", len);
             fflush(NHttpTestManager::get_output_file());
         }
-        session_data->section_type[source_id] = SEC__NOTCOMPUTE;
+        if (flags & PKT_PDU_TAIL)
+        {
+            session_data->section_type[source_id] = SEC__NOTCOMPUTE;
+
+            // When we are skipping through a message body beyond flow depth this is the end of
+            // the line. Here we do the message section's normal job of updating the flow for the
+            // next stage.
+            if (session_data->cutter[source_id] == nullptr)
+            {
+                if (session_data->type_expected[source_id] == SEC_BODY)
+                {
+                    session_data->type_expected[source_id] = (source_id == SRC_CLIENT) ?
+                        SEC_REQUEST : SEC_STATUS;
+                    session_data->half_reset(source_id);
+                }
+                else if (session_data->type_expected[source_id] == SEC_CHUNK)
+                {
+                    session_data->type_expected[source_id] = SEC_TRAILER;
+                    session_data->infractions[source_id].reset();
+                    session_data->events[source_id].reset();
+                }
+            }
+        }
         return nullptr;
     }