]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
stop using flags to determine splitter direction and a new test case
authorTom Peters <thopeter@cisco.com>
Tue, 19 Aug 2014 17:52:51 +0000 (13:52 -0400)
committerTom Peters <thopeter@cisco.com>
Tue, 19 Aug 2014 17:52:51 +0000 (13:52 -0400)
src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc
src/service_inspectors/nhttp_inspect/nhttp_inspect.cc
src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc
src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.h
src/service_inspectors/nhttp_inspect/nhttp_test_input.cc
src/service_inspectors/nhttp_inspect/nhttp_test_input.h
src/service_inspectors/nhttp_inspect/nhttp_test_msgs.txt

index cfe57b96fec726abf47fbce485d1b8532844c1f5..856ad7b7f78e96ae4dd2d095b2bd5f036a46563e 100644 (file)
@@ -41,7 +41,7 @@ using namespace NHttpEnums;
 
 unsigned NHttpFlowData::nhttp_flow_id = 0;
 
-NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) {}
+NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) { }
 
 NHttpFlowData::~NHttpFlowData() {
     delete request_line;
index 97f5c2c22aa7beb8d8a06635a934bf4598d75dbb..e4a2cdb3acf138f39dce77d1081319419cec8938 100644 (file)
@@ -136,7 +136,9 @@ void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* cons
     msg_section->legacy_clients();
 
     if (test_output) {
-        if (!NHttpTestInput::test_input) msg_section->print_section(stdout);
+        if (!NHttpTestInput::test_input) {
+            msg_section->print_section(stdout);
+        }
         else {
             if (NHttpTestInput::test_input_source->get_test_number() != file_test_number) {
                 if (test_out) fclose (test_out);
@@ -148,6 +150,7 @@ void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* cons
             msg_section->print_section(test_out);
             printf("Finished processing section from test %" PRIi64 "\n", file_test_number);
         }
+        fflush(nullptr);
     }
 }
 
index 4bc7c347b04ddbb54a2580e65b5d612205413646..5d8bc042a89b0aa4d7821b3bb325cc75b3f14144 100644 (file)
@@ -65,7 +65,7 @@ const StreamBuffer* NHttpStreamSplitter::reassemble(Flow* flow, unsigned /*total
         section_buffer = new uint8_t[65536];
     }
 
-    SourceId source_id = (flags & PKT_FROM_CLIENT) ? SRC_CLIENT : SRC_SERVER;
+    SourceId source_id = to_server() ? SRC_CLIENT : SRC_SERVER;
 
     copied = len;
 
@@ -97,23 +97,27 @@ const StreamBuffer* NHttpStreamSplitter::reassemble(Flow* flow, unsigned /*total
     return nullptr;
 }
 
-PAF_Status NHttpStreamSplitter::scan (Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flush_offset) {
+PAF_Status NHttpStreamSplitter::scan (Flow* flow, const uint8_t* data, uint32_t length, uint32_t, uint32_t* flush_offset) {
     // When the system begins providing TCP connection close information this won't always be false. &&&
     bool tcp_close = false;
 
-    // This is the session state information we share with HTTP Inspect and store with stream. A session is defined by a TCP connection.
-    // Since PAF is the first to see a new TCP connection the new flow data object is created here.
+    // This is the session state information we share with HTTP Inspect and store with stream. A session is defined
+    // by a TCP connection. Since PAF is the first to see a new TCP connection the new flow data object is created here.
     NHttpFlowData* session_data = (NHttpFlowData*)flow->get_application_data(NHttpFlowData::nhttp_flow_id);
     if (session_data == nullptr) flow->set_application_data(session_data = new NHttpFlowData);
     assert(session_data != nullptr);
 
-    SourceId source_id = (flags & PKT_FROM_CLIENT) ? SRC_CLIENT : SRC_SERVER;
+    SourceId source_id = to_server() ? SRC_CLIENT : SRC_SERVER;
 
     if (NHttpTestInput::test_input) {
+        // This block substitutes a completely new data buffer supplied by the test tool in place of the "real" data.
+        // It also rewrites the buffer length, source ID, and TCP close indicator.
         *flush_offset = length;
         bool need_break;
-        NHttpTestInput::test_input_source->scan((uint8_t*&)data, length, source_id, tcp_close, need_break);
+        uint8_t* test_data = nullptr;
+        NHttpTestInput::test_input_source->scan(test_data, length, source_id, tcp_close, need_break);
         if (length == 0) return PAF_FLUSH;
+        data = test_data;
         if (need_break) flow->set_application_data(session_data = new NHttpFlowData);
     }
 
@@ -177,9 +181,13 @@ PAF_Status NHttpStreamSplitter::scan (Flow* flow, const uint8_t* data, uint32_t
       case SEC_BODY:
       case SEC_CHUNKBODY:
         paf_max = 16384;
-        prepare_flush(session_data, flush_offset, source_id, type,
-           tcp_close && (session_data->octets_expected[source_id] >= length),
-           0, session_data->octets_expected[source_id]);
+        if ((!tcp_close) || (length > session_data->octets_expected[source_id])) {
+            prepare_flush(session_data, flush_offset, source_id, type, false, 0, session_data->octets_expected[source_id]);
+        }
+        else {
+            // The TCP connection has closed and this is the possibly incomplete final section
+            prepare_flush(session_data, flush_offset, source_id, type, true,  0, length);
+        }
         return PAF_FLUSH;
       case SEC_ABORT:
         return PAF_ABORT;
index 29b5e35c8c0ecb441211a56c1284390eb2d2302b..0afec8c47d567327eb180381f993f68dbdd074a8 100644 (file)
@@ -37,9 +37,9 @@ class NHttpInspect;
 class NHttpStreamSplitter : public StreamSplitter {
 public:
     NHttpStreamSplitter(bool is_client_to_server, NHttpInspect* my_inspector_) : StreamSplitter(is_client_to_server),
-       my_inspector(my_inspector_) {};
+       my_inspector(my_inspector_) { };
     ~NHttpStreamSplitter() { delete[] section_buffer; };
-    PAF_Status scan(Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flush_offset);
+    PAF_Status scan(Flow* flow, const uint8_t* data, uint32_t length, uint32_t not_used, uint32_t* flush_offset);
     const StreamBuffer* reassemble(Flow* flow, unsigned total, unsigned offset, const uint8_t* data, unsigned len,
        uint32_t flags, unsigned& copied);
     bool is_paf() { return true; };
index c8fb6f2ce69db28cc68d7dde6881c5fe935123d2..a85c6d9e046db3f1b4dcdf2af31e275b35c96e57 100644 (file)
@@ -75,11 +75,11 @@ void NHttpTestInput::scan(uint8_t*& data, uint32_t &length, SourceId &source_id,
             // Must present unflushed leftovers to PAF again.
             // If we don't take this opportunity to left justify our data in the buffer we may "walk" to the right until we run out of buffer space
             memmove(msg_buf, msg_buf+flush_octets, length);
-            tcp_close = tcp_already_closed;
+            tcp_close = tcp_closed;
             return;
         }
         // If we reach here then PAF has already flushed all the data we have read so far.
-        tcp_already_closed = false;
+        tcp_closed = false;
     }
     else {
         // The data we gave PAF last time was not flushed
@@ -136,6 +136,10 @@ void NHttpTestInput::scan(uint8_t*& data, uint32_t &length, SourceId &source_id,
                 else if ((command_length == strlen("break")) && !memcmp(command_value, "break", strlen("break"))) {
                     need_break = true;
                 }
+                else if ((command_length == strlen("tcpclose")) && !memcmp(command_value, "tcpclose", strlen("tcpclose"))) {
+                    tcp_close = true;
+                    tcp_closed = true;
+                }
                 else if ((command_length == strlen("bodyend")) && !memcmp(command_value, "bodyend", strlen("bodyend"))) {
                     term_bytes[0] = 'x';
                     term_bytes[1] = 'y';
index 94e507cfe78e3bf74e4540ed05fd269581d76005..911e55a3cefd939afa8077cf46590e88d0c43b73 100644 (file)
@@ -44,7 +44,7 @@ private:
     FILE *test_data_file;
     uint8_t msg_buf[2 * NHttpEnums::MAXOCTETS];
     bool just_flushed = true;   // all octets sent to inspection and must resume reading the file
-    bool tcp_already_closed = false;  // so we can keep presenting a TCP close to PAF until all the remaining octets are consumed and flushed
+    bool tcp_closed = false;  // so we can keep presenting a TCP close to PAF until all the remaining octets are consumed and flushed
     uint32_t flush_octets = 0;  // number of octets that have been flushed and must go to inspection
     uint32_t previous_offset = 0;   // last character in the buffer shown to PAF but not flushed yet
     uint32_t end_offset = 0;   // last read character in the buffer
index 256b01856189d2424623507b25e59f4ea7d78877..242b0cdf96ac40dd698079ee09e6f1c8215cb6f6 100644 (file)
@@ -4,6 +4,12 @@
 # Within a paragraph the placement of new lines does not have any effect. Format a paragraph any way you are comfortable. Extra blank lines
 # between paragraphs also do not have any effect.
 #
+# Each paragraph represents a TCP segment. The splitter can be tested by putting multiple sections in the same paragraph (splitter must split)
+# or continuing a section in the next paragraph (splitter must search and reassamble).
+#
+# It is not necessary to specify complete body and chunk body sections. Specify at least one octet that will begin the section and the
+# remainder will be autofilled in 16384-octet sections up to the length flushed.
+#
 # Lines beginning with # are comments. Lines beginning with @ are commands. This does not apply to lines in the middle of a paragraph.
 #
 # Command lines are left justified, lower case, with no whitespace:
@@ -683,6 +689,19 @@ Accept-Language: is\r\n
 @break
 @request
 
+POST /basic/request/response/pair/with/large/bodies/both/ways HTTP/1.1\r\n
+Host: www.testcase.com\r\n
+Content-Length: 50000\r\n
+\r\n
+
+body1-start
+
+@response
+
+HTTP/1.1 200 OK\r\n
+Content-Length: 60000\r\n
+\r\n
+body2-start
 
 
 # ***********************************************************************************************