static const uint32_t HTTP2_GID = 121;
-// Message originator--client or server
-enum SourceId { SRC__NOT_COMPUTE=-14, SRC_CLIENT=0, SRC_SERVER=1 };
-
// Frame type codes (fourth octet of frame header)
enum FrameType { FT_DATA=0, FT_HEADERS=1, FT_PRIORITY=2, FT_RST_STREAM=3, FT_SETTINGS=4,
FT_PUSH_PROMISE=5, FT_PING=6, FT_GOAWAY=7, FT_WINDOW_UPDATE=8, FT_CONTINUATION=9 };
#include "http2_flow_data.h"
+#include "service_inspectors/http_inspect/http_test_manager.h"
+
#include "http2_enum.h"
#include "http2_module.h"
unsigned Http2FlowData::inspector_id = 0;
+#ifdef REG_TEST
+uint64_t Http2FlowData::instance_count = 0;
+#endif
+
Http2FlowData::Http2FlowData() : FlowData(inspector_id)
{
+#ifdef REG_TEST
+ seq_num = ++instance_count;
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ printf("HTTP/2 Flow Data construct %" PRIu64 "\n", seq_num);
+ fflush(nullptr);
+ }
+#endif
Http2Module::increment_peg_counts(PEG_CONCURRENT_SESSIONS);
if (Http2Module::get_peg_counts(PEG_MAX_CONCURRENT_SESSIONS) <
Http2Module::get_peg_counts(PEG_CONCURRENT_SESSIONS))
Http2FlowData::~Http2FlowData()
{
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ printf("HTTP/2 Flow Data destruct %" PRIu64 "\n", seq_num);
+ fflush(nullptr);
+ }
+#endif
if (Http2Module::get_peg_counts(PEG_CONCURRENT_SESSIONS) > 0)
Http2Module::decrement_peg_counts(PEG_CONCURRENT_SESSIONS);
#define HTTP2_FLOW_DATA_H
#include "flow/flow.h"
+#include "service_inspectors/http_inspect/http_common.h"
#include "stream/stream_splitter.h"
#include "http2_enum.h"
friend class Http2Inspect;
friend class Http2StreamSplitter;
friend const snort::StreamBuffer implement_reassemble(Http2FlowData*, unsigned, unsigned,
- const uint8_t*, unsigned, uint32_t, unsigned&, Http2Enums::SourceId);
+ const uint8_t*, unsigned, uint32_t, HttpCommon::SourceId);
friend snort::StreamSplitter::Status implement_scan(Http2FlowData*, const uint8_t*, uint32_t,
- uint32_t*, Http2Enums::SourceId);
- friend bool implement_get_buf(unsigned id, Http2FlowData*, Http2Enums::SourceId,
+ uint32_t*, HttpCommon::SourceId);
+ friend bool implement_get_buf(unsigned id, Http2FlowData*, HttpCommon::SourceId,
snort::InspectionBuffer&);
size_t size_of() override
uint32_t leftover_data[2] = { 0, 0 };
uint32_t octets_seen[2] = { 0, 0 };
bool frame_in_detection = false;
+
+#ifdef REG_TEST
+ static uint64_t instance_count;
+ uint64_t seq_num;
+#endif
};
#endif
#include "http2_inspect.h"
#include "detection/detection_engine.h"
#include "protocols/packet.h"
-#include "service_inspectors/http_inspect/http_enum.h"
+#include "service_inspectors/http_inspect/http_common.h"
#include "service_inspectors/http_inspect/http_field.h"
#include "service_inspectors/http_inspect/http_test_manager.h"
#include "stream/stream.h"
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
Http2Inspect::Http2Inspect(const Http2ParaList* params_) : params(params_)
{
+#ifdef REG_TEST
+ if (params->test_input)
+ {
+ HttpTestManager::activate_test_input(HttpTestManager::IN_HTTP2);
+ }
+ if (params->test_output)
+ {
+ HttpTestManager::activate_test_output(HttpTestManager::IN_HTTP2);
+ }
+ if ((params->test_input) || (params->test_output))
+ {
+ HttpTestManager::set_print_amount(params->print_amount);
+ HttpTestManager::set_print_hex(params->print_hex);
+ HttpTestManager::set_show_pegs(params->show_pegs);
+ HttpTestManager::set_show_scan(params->show_scan);
+ }
+#endif
}
bool Http2Inspect::configure(SnortConfig* )
session_data->frame_in_detection = true;
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
{
Field((session_data->frame_header[source_id] != nullptr) ? FRAME_HEADER_LENGTH :
- HttpEnums::STAT_NOT_PRESENT,
- session_data->frame_header[source_id]).print(stdout, "frame header");
+ HttpCommon::STAT_NOT_PRESENT,
+ session_data->frame_header[source_id]).print(HttpTestManager::get_output_file(),
+ "Frame Header");
Field((session_data->frame_data[source_id] != nullptr) ?
- (int) session_data->frame_data_size[source_id] : HttpEnums::STAT_NOT_PRESENT,
- session_data->frame_data[source_id]).print(stdout, "frame data");
+ (int) session_data->frame_data_size[source_id] : HttpCommon::STAT_NOT_PRESENT,
+ session_data->frame_data[source_id]).print(HttpTestManager::get_output_file(),
+ "Frame Data");
}
#endif
}
//-------------------------------------------------------------------------
#include "log/messages.h"
+#include "service_inspectors/http_inspect/http_common.h"
#include "http2_enum.h"
#include "http2_flow_data.h"
const Http2ParaList* const params;
};
-bool implement_get_buf(unsigned id, Http2FlowData* session_data, Http2Enums::SourceId source_id,
+bool implement_get_buf(unsigned id, Http2FlowData* session_data, HttpCommon::SourceId source_id,
snort::InspectionBuffer& b);
#endif
#endif
#include "http2_inspect.h"
+#include "http2_enum.h"
#include "http2_flow_data.h"
+#include "service_inspectors/http_inspect/http_common.h"
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
bool implement_get_buf(unsigned id, Http2FlowData* session_data, SourceId source_id,
const Parameter Http2Module::http2_params[] =
{
+#ifdef REG_TEST
+ { "test_input", Parameter::PT_BOOL, nullptr, "false",
+ "read HTTP/2 messages from text file" },
+
+ { "test_output", Parameter::PT_BOOL, nullptr, "false",
+ "print out HTTP section data" },
+
+ { "print_amount", Parameter::PT_INT, "1:max53", "1200",
+ "number of characters to print from a Field" },
+
+ { "print_hex", Parameter::PT_BOOL, nullptr, "false",
+ "nonprinting characters printed in [HH] format instead of using an asterisk" },
+
+ { "show_pegs", Parameter::PT_BOOL, nullptr, "true",
+ "display peg counts with test output" },
+
+ { "show_scan", Parameter::PT_BOOL, nullptr, "false",
+ "display scanned segments" },
+#endif
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
return true;
}
-bool Http2Module::set(const char*, Value& /*val*/, SnortConfig*)
+bool Http2Module::set(const char*, Value& val, SnortConfig*)
{
+#ifdef REG_TEST
+ if (val.is("test_input"))
+ {
+ params->test_input = val.get_bool();
+ }
+ else if (val.is("test_output"))
+ {
+ params->test_output = val.get_bool();
+ }
+ else if (val.is("print_amount"))
+ {
+ params->print_amount = val.get_int64();
+ }
+ else if (val.is("print_hex"))
+ {
+ params->print_hex = val.get_bool();
+ }
+ else if (val.is("show_pegs"))
+ {
+ params->show_pegs = val.get_bool();
+ }
+ else if (val.is("show_scan"))
+ {
+ params->show_scan = val.get_bool();
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+#else
+ UNUSED(val);
return false;
+#endif
}
bool Http2Module::end(const char*, int, SnortConfig*)
struct Http2ParaList
{
public:
+#ifdef REG_TEST
+ int64_t print_amount;
+
+ bool test_input;
+ bool test_output;
+ bool print_hex;
+ bool show_pegs;
+ bool show_scan;
+#endif
};
class Http2Module : public snort::Module
#include <cassert>
#include "protocols/packet.h"
+#include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_field.h"
+#include "service_inspectors/http_inspect/http_stream_splitter.h"
+#include "service_inspectors/http_inspect/http_test_input.h"
+#include "service_inspectors/http_inspect/http_test_manager.h"
#include "http2_stream_splitter.h"
#include "http2_module.h"
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
// Mindless scan() that just flushes whatever it is given
StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* data, uint32_t length,
uint32_t, uint32_t* flush_offset)
{
+ snort::Profile profile(Http2Module::get_profile_stats());
+
// This is the session state information we share with Http2Inspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
// connection the new flow data object is created here.
Http2Module::increment_peg_counts(PEG_FLOW);
}
- return implement_scan(session_data, data, length, flush_offset, source_id);
+#ifdef REG_TEST
+ uint32_t dummy_flush_offset;
+
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ // 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.
+ *flush_offset = length;
+ uint8_t* test_data = nullptr;
+ HttpTestManager::get_test_input_source()->scan(test_data, length, source_id,
+ session_data->seq_num);
+ if (length == 0)
+ return StreamSplitter::FLUSH;
+ data = test_data;
+ flush_offset = &dummy_flush_offset;
+ }
+ else if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+ {
+ printf("HTTP/2 scan from flow data %" PRIu64
+ " direction %d length %u client port %hu server port %hu\n", session_data->seq_num,
+ source_id, length, pkt->flow->client_port, pkt->flow->server_port);
+ fflush(stdout);
+ if (HttpTestManager::get_show_scan())
+ {
+ Field(length, data).print(stdout, "Scan segment");
+ }
+ }
+#endif
+
+ const StreamSplitter::Status ret_val =
+ implement_scan(session_data, data, length, flush_offset, source_id);
+
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ if (ret_val == StreamSplitter::FLUSH)
+ HttpTestManager::get_test_input_source()->flush(*flush_offset);
+#endif
+
+ return HttpStreamSplitter::status_value(ret_val, true);
}
// Generic reassemble() copies the inputs unchanged into a static buffer
const StreamBuffer Http2StreamSplitter::reassemble(Flow* flow, unsigned total, unsigned offset,
const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied)
{
+ snort::Profile profile(Http2Module::get_profile_stats());
+
+ copied = len;
+
Http2FlowData* session_data = (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
assert(session_data != nullptr);
- return implement_reassemble(session_data, total, offset, data, len, flags, copied, source_id);
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+ {
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ snort::StreamBuffer http_buf { nullptr, 0 };
+ if (!(flags & PKT_PDU_TAIL))
+ {
+ return http_buf;
+ }
+ bool tcp_close;
+ bool partial_flush;
+ uint8_t* test_buffer;
+ HttpTestManager::get_test_input_source()->reassemble(&test_buffer, len, source_id,
+ tcp_close, partial_flush);
+ if (tcp_close)
+ {
+ finish(flow);
+ }
+ if (partial_flush)
+ {
+ init_partial_flush(flow);
+ }
+ if (test_buffer == nullptr)
+ {
+ // Source ID does not match test data, no test data was flushed, preparing for a
+ // partial flush, preparing for a TCP connection close, or there is no more test
+ // data
+ return http_buf;
+ }
+ data = test_buffer;
+ total = len;
+ }
+ else
+ {
+ printf("HTTP/2 reassemble from flow data %" PRIu64
+ " direction %d total %u length %u\n", session_data->seq_num, source_id,
+ total, len);
+ fflush(stdout);
+ }
+ }
+#endif
+
+ return implement_reassemble(session_data, total, offset, data, len, flags, source_id);
}
// Eventually we will need to address unexpected connection closes
-bool Http2StreamSplitter::finish(Flow* /*flow*/) { return false; }
+bool Http2StreamSplitter::finish(Flow* flow)
+{
+ snort::Profile profile(Http2Module::get_profile_stats());
+
+ Http2FlowData* session_data = (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
+ // FIXIT-M - this assert has been changed to check for null session data and return false if so
+ // due to lack of reliable feedback to stream that scan has been called...if that is
+ // addressed in stream reassembly rewrite this can be reverted to an assert
+ //assert(session_data != nullptr);
+ if(!session_data)
+ return false;
+
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+ {
+ if (!HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ printf("Finish from flow data %" PRIu64 " direction %d\n", session_data->seq_num,
+ source_id);
+ fflush(stdout);
+ }
+ }
+#endif
+
+ // FIXIT-H not supported yet
+ return false;
+}
+
+bool Http2StreamSplitter::init_partial_flush(snort::Flow* flow)
+{
+ snort::Profile profile(Http2Module::get_profile_stats());
+
+ if (source_id != SRC_SERVER)
+ {
+ assert(false);
+ return false;
+ }
+
+ Http2FlowData* session_data = (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
+ assert(session_data != nullptr);
+ UNUSED(session_data); // just for a little while
+
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP2))
+ {
+ printf("HTTP/2 partial flush from flow data %" PRIu64 "\n", session_data->seq_num);
+ fflush(stdout);
+ }
+#endif
+
+ // FIXIT-H not supported yet
+ return false;
+}
#ifndef HTTP2_STREAM_SPLITTER_H
#define HTTP2_STREAM_SPLITTER_H
+#include "service_inspectors/http_inspect/http_common.h"
#include "stream/stream_splitter.h"
#include "http2_enum.h"
{
public:
Http2StreamSplitter(bool is_client_to_server) : snort::StreamSplitter(is_client_to_server),
- source_id(is_client_to_server ? Http2Enums::SRC_CLIENT : Http2Enums::SRC_SERVER) { }
+ source_id(is_client_to_server ? HttpCommon::SRC_CLIENT : HttpCommon::SRC_SERVER) { }
Status scan(snort::Packet* pkt, const uint8_t* data, uint32_t length, uint32_t not_used,
uint32_t* flush_offset) override;
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned offset, const
uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
bool finish(snort::Flow* flow) override;
+ bool init_partial_flush(snort::Flow* flow) override;
bool is_paf() override { return true; }
// FIXIT-M should return actual packet buffer size
unsigned max(snort::Flow*) override { return Http2Enums::MAX_OCTETS; }
private:
- const Http2Enums::SourceId source_id;
+ const HttpCommon::SourceId source_id;
};
snort::StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
- uint32_t length, uint32_t* flush_offset, Http2Enums::SourceId source_id);
+ uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id);
const snort::StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
- unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied,
- Http2Enums::SourceId source_id);
+ unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
+ HttpCommon::SourceId source_id);
#endif
#include "http2_stream_splitter.h"
#include "protocols/packet.h"
+#include "service_inspectors/http_inspect/http_common.h"
#include "http2_flow_data.h"
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
- uint32_t length, uint32_t* flush_offset, Http2Enums::SourceId source_id)
+ uint32_t length, uint32_t* flush_offset, HttpCommon::SourceId source_id)
{
if (session_data->preface[source_id])
{
}
const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
- unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied,
- Http2Enums::SourceId source_id)
+ unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
+ HttpCommon::SourceId source_id)
{
assert(offset+len <= total);
assert(total >= FRAME_HEADER_LENGTH);
assert(session_data->frame_size[source_id] == total);
memcpy(session_data->frame[source_id]+offset, data, len);
- copied = len;
if (flags & PKT_PDU_TAIL)
{
assert(offset+len == total);
IpsOption::EvalStatus Http2IpsOption::eval(Cursor& c, Packet* p)
{
- Profile profile(Http2CursorModule::http2_ps[psi]);
+ RuleProfile profile(Http2CursorModule::http2_ps[psi]);
if (!p->flow || !p->flow->gadget)
return NO_MATCH;
#ifndef HTTP2_FLOW_DATA_TEST_H
#define HTTP2_FLOW_DATA_TEST_H
-#include "service_inspectors/http2_inspect/http2_enum.h"
+#include "service_inspectors/http_inspect/http_common.h"
+//#include "service_inspectors/http2_inspect/http2_enum.h"
#include "service_inspectors/http2_inspect/http2_flow_data.h"
#include "service_inspectors/http2_inspect/http2_module.h"
class Http2FlowDataTest : public Http2FlowData
{
public:
- bool get_preface(Http2Enums::SourceId source_id) { return preface[source_id]; }
- void set_preface(bool value, Http2Enums::SourceId source_id) { preface[source_id] = value; }
- bool get_header_coming(Http2Enums::SourceId source_id) { return header_coming[source_id]; }
- void set_header_coming(bool value, Http2Enums::SourceId source_id)
+ bool get_preface(HttpCommon::SourceId source_id) { return preface[source_id]; }
+ void set_preface(bool value, HttpCommon::SourceId source_id) { preface[source_id] = value; }
+ bool get_header_coming(HttpCommon::SourceId source_id) { return header_coming[source_id]; }
+ void set_header_coming(bool value, HttpCommon::SourceId source_id)
{ header_coming[source_id] = value; }
- uint8_t* get_frame_header(Http2Enums::SourceId source_id) { return frame_header[source_id]; }
- void set_frame_header(uint8_t* value, Http2Enums::SourceId source_id)
+ uint8_t* get_frame_header(HttpCommon::SourceId source_id) { return frame_header[source_id]; }
+ void set_frame_header(uint8_t* value, HttpCommon::SourceId source_id)
{ frame_header[source_id] = value; }
- uint8_t* get_frame(Http2Enums::SourceId source_id) { return frame[source_id]; }
- void set_frame(uint8_t* value, Http2Enums::SourceId source_id) { frame[source_id] = value; }
- uint32_t get_frame_size(Http2Enums::SourceId source_id) { return frame_size[source_id]; }
- void set_frame_size(uint32_t value, Http2Enums::SourceId source_id)
+ uint8_t* get_frame(HttpCommon::SourceId source_id) { return frame[source_id]; }
+ void set_frame(uint8_t* value, HttpCommon::SourceId source_id) { frame[source_id] = value; }
+ uint32_t get_frame_size(HttpCommon::SourceId source_id) { return frame_size[source_id]; }
+ void set_frame_size(uint32_t value, HttpCommon::SourceId source_id)
{ frame_size[source_id] = value; }
- uint8_t* get_frame_data(Http2Enums::SourceId source_id) { return frame_data[source_id]; }
- void set_frame_data(uint8_t* value, Http2Enums::SourceId source_id)
+ uint8_t* get_frame_data(HttpCommon::SourceId source_id) { return frame_data[source_id]; }
+ void set_frame_data(uint8_t* value, HttpCommon::SourceId source_id)
{ frame_data[source_id] = value; }
- uint32_t get_frame_data_size(Http2Enums::SourceId source_id)
+ uint32_t get_frame_data_size(HttpCommon::SourceId source_id)
{ return frame_data_size[source_id]; }
- void set_frame_data_size(uint32_t value, Http2Enums::SourceId source_id)
+ void set_frame_data_size(uint32_t value, HttpCommon::SourceId source_id)
{ frame_data_size[source_id] = value; }
- uint32_t get_leftover_data(Http2Enums::SourceId source_id) { return leftover_data[source_id]; }
- void set_leftover_data(uint32_t value, Http2Enums::SourceId source_id)
+ uint32_t get_leftover_data(HttpCommon::SourceId source_id) { return leftover_data[source_id]; }
+ void set_leftover_data(uint32_t value, HttpCommon::SourceId source_id)
{ leftover_data[source_id] = value; }
};
#include "service_inspectors/http2_inspect/http2_stream_splitter.h"
#include "protocols/packet.h"
+#include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_test_manager.h"
#include "service_inspectors/http2_inspect/http2_enum.h"
#include "http2_flow_data_test.h"
#include <CppUTestExt/MockSupport.h>
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
+// Stubs whose sole purpose is to make the test code link
+unsigned HttpTestManager::test_input = IN_NONE;
+unsigned HttpTestManager::test_output = IN_NONE;
+
TEST_GROUP(http2_get_buf_test)
{
Http2FlowDataTest* session_data = nullptr;
#include "service_inspectors/http2_inspect/http2_stream_splitter.h"
#include "protocols/packet.h"
+#include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_test_manager.h"
#include "service_inspectors/http2_inspect/http2_enum.h"
#include "http2_flow_data_test.h"
#include <CppUTestExt/MockSupport.h>
using namespace snort;
+using namespace HttpCommon;
using namespace Http2Enums;
+// Stubs whose sole purpose is to make the test code link
+unsigned HttpTestManager::test_input = IN_NONE;
+unsigned HttpTestManager::test_output = IN_NONE;
+
TEST_GROUP(http2_scan_test)
{
Http2FlowDataTest* session_data = nullptr;
TEST_GROUP(http2_reassemble_test)
{
Http2FlowDataTest* session_data = nullptr;
- unsigned copied = 0;
void setup() override
{
session_data->set_header_coming(true, SRC_CLIENT);
const StreamBuffer buffer = implement_reassemble(session_data, 19, 0,
(const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789",
- 19, PKT_PDU_TAIL, copied, SRC_CLIENT);
- CHECK(copied == 19);
+ 19, PKT_PDU_TAIL, SRC_CLIENT);
CHECK(buffer.length == 10);
CHECK(memcmp(buffer.data, "0123456789", 10) == 0);
}
session_data->set_header_coming(true, SRC_SERVER);
const StreamBuffer buffer = implement_reassemble(session_data, 19, 0,
(const uint8_t*)"\x00\x00\x0A\x02\x00\x00\x00\x00\x00" "0123456789",
- 19, PKT_PDU_TAIL, copied, SRC_SERVER);
- CHECK(copied == 19);
+ 19, PKT_PDU_TAIL, SRC_SERVER);
CHECK(buffer.length == 10);
CHECK(memcmp(buffer.data, "0123456789", 10) == 0);
}
session_data->set_header_coming(false, SRC_CLIENT);
const StreamBuffer buffer = implement_reassemble(session_data, 24, 0,
(const uint8_t*)"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
- 24, PKT_PDU_TAIL, copied, SRC_CLIENT);
- CHECK(copied == 24);
+ 24, PKT_PDU_TAIL, SRC_CLIENT);
CHECK(buffer.length == 24);
CHECK(memcmp(buffer.data, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24) == 0);
}
session_data->set_header_coming(true, SRC_CLIENT);
StreamBuffer buffer = implement_reassemble(session_data, 19, 0,
(const uint8_t*)"\x00\x00\x0A\x02\x00\x00",
- 6, 0, copied, SRC_CLIENT);
- CHECK(copied == 6);
+ 6, 0, SRC_CLIENT);
CHECK(buffer.length == 0);
CHECK(buffer.data == nullptr);
buffer = implement_reassemble(session_data, 19, 6,
(const uint8_t*)"\x00\x00\x00" "01234",
- 8, 0, copied, SRC_CLIENT);
- CHECK(copied == 8);
+ 8, 0, SRC_CLIENT);
CHECK(buffer.length == 0);
CHECK(buffer.data == nullptr);
buffer = implement_reassemble(session_data, 19, 14,
(const uint8_t*)"56789",
- 5, PKT_PDU_TAIL, copied, SRC_CLIENT);
- CHECK(copied == 5);
+ 5, PKT_PDU_TAIL, SRC_CLIENT);
CHECK(buffer.length == 10);
CHECK(memcmp(buffer.data, "0123456789", 10) == 0);
}
session_data->set_header_coming(false, SRC_CLIENT);
StreamBuffer buffer = implement_reassemble(session_data, 24, 0,
(const uint8_t*)"P",
- 1, 0, copied, SRC_CLIENT);
- CHECK(copied == 1);
+ 1, 0, SRC_CLIENT);
CHECK(buffer.length == 0);
CHECK(buffer.data == nullptr);
buffer = implement_reassemble(session_data, 24, 1,
(const uint8_t*)"RI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
- 23, PKT_PDU_TAIL, copied, SRC_CLIENT);
- CHECK(copied == 23);
+ 23, PKT_PDU_TAIL, SRC_CLIENT);
CHECK(buffer.length == 24);
CHECK(memcmp(buffer.data, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24) == 0);
}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// http_common.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef HTTP_COMMON_H
+#define HTTP_COMMON_H
+
+#include <cstdint>
+
+namespace HttpCommon
+{
+// Field status codes for when no valid value is present in length or integer value. Positive
+// values are actual length or field value.
+enum StatusCode { STAT_NO_SOURCE=-16, STAT_NOT_CONFIGURED=-15, STAT_NOT_COMPUTE=-14,
+ STAT_PROBLEMATIC=-12, STAT_NOT_PRESENT=-11, STAT_EMPTY_STRING=0, STAT_OTHER=1 };
+
+// Message originator--client or server
+enum SourceId { SRC__NOT_COMPUTE=-14, SRC_CLIENT=0, SRC_SERVER=1 };
+
+} // end namespace HttpCommon
+
+#endif
+
// This can grow into a bitmap for the get_buf() form parameter
static const uint64_t FORM_REQUEST = 0x1;
-// Field status codes for when no valid value is present in length or integer value. Positive
-// values are actual length or field value.
-enum StatusCode { STAT_NO_SOURCE=-16, STAT_NOT_CONFIGURED=-15, STAT_NOT_COMPUTE=-14,
- STAT_PROBLEMATIC=-12, STAT_NOT_PRESENT=-11, STAT_EMPTY_STRING=0, STAT_OTHER=1 };
-
-// Message originator--client or server
-enum SourceId { SRC__NOT_COMPUTE=-14, SRC_CLIENT=0, SRC_SERVER=1 };
-
// Type of message section
enum SectionType { SEC_DISCARD = -19, SEC_ABORT = -18, SEC__NOT_COMPUTE=-14, SEC__NOT_PRESENT=-11,
SEC_REQUEST = 2, SEC_STATUS, SEC_HEADER, SEC_BODY_CL, SEC_BODY_CHUNK, SEC_TRAILER,
#include "http_field.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_test_manager.h"
+using namespace HttpCommon;
using namespace HttpEnums;
const Field Field::FIELD_NULL { STAT_NO_SOURCE };
#include <cstdio>
#include <cassert>
+#include "http_common.h"
#include "http_enum.h"
// Individual pieces of the message found during parsing.
const uint8_t* start() const { return strt; }
void set(int32_t length, const uint8_t* start, bool own_the_buffer_ = false);
void set(const Field& f);
- void set(HttpEnums::StatusCode stat_code);
- void set(int32_t length) { set(static_cast<HttpEnums::StatusCode>(length)); }
+ void set(HttpCommon::StatusCode stat_code);
+ void set(int32_t length) { set(static_cast<HttpCommon::StatusCode>(length)); }
#ifdef REG_TEST
void print(FILE* output, const char* name) const;
Field& operator=(const Field&) = delete;
const uint8_t* strt = nullptr;
- int32_t len = HttpEnums::STAT_NOT_COMPUTE;
+ int32_t len = HttpCommon::STAT_NOT_COMPUTE;
bool own_the_buffer = false;
};
#include "decompress/file_decomp.h"
#include "http_cutter.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_module.h"
#include "http_test_manager.h"
#include "http_transaction.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
unsigned HttpFlowData::inspector_id = 0;
{
#ifdef REG_TEST
seq_num = ++instance_count;
- if (HttpTestManager::use_test_output() && !HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
printf("Flow Data construct %" PRIu64 "\n", seq_num);
fflush(nullptr);
HttpFlowData::~HttpFlowData()
{
#ifdef REG_TEST
- if (!HttpTestManager::use_test_input() && HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
printf("Flow Data destruct %" PRIu64 "\n", seq_num);
fflush(nullptr);
delete[] pipeline;
}
-HttpInfractions* HttpFlowData::get_infractions(HttpEnums::SourceId source_id)
+HttpInfractions* HttpFlowData::get_infractions(SourceId source_id)
{
if (infractions[source_id] != nullptr)
return infractions[source_id];
return transaction[source_id]->get_infractions(source_id);
}
-HttpEventGen* HttpFlowData::get_events(HttpEnums::SourceId source_id)
+HttpEventGen* HttpFlowData::get_events(SourceId source_id)
{
if (events[source_id] != nullptr)
return events[source_id];
#include "utils/util_utf.h"
#include "decompress/file_decomp.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_event.h"
class HttpTransaction;
private:
// Convenience routines
- void half_reset(HttpEnums::SourceId source_id);
- void trailer_prep(HttpEnums::SourceId source_id);
+ void half_reset(HttpCommon::SourceId source_id);
+ void trailer_prep(HttpCommon::SourceId source_id);
void garbage_collect();
// 0 element refers to client request, 1 element refers to server response
// *** StreamSplitter => Inspector (facts about the most recent message section)
HttpEnums::SectionType section_type[2] = { HttpEnums::SEC__NOT_COMPUTE,
HttpEnums::SEC__NOT_COMPUTE };
- int32_t num_head_lines[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
+ int32_t num_head_lines[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
bool tcp_close[2] = { false, false };
bool partial_flush[2] = { false, false };
// hide this from StreamSplitter.
HttpInfractions* infractions[2] = { new HttpInfractions, new HttpInfractions };
HttpEventGen* events[2] = { new HttpEventGen, new HttpEventGen };
- HttpInfractions* get_infractions(HttpEnums::SourceId source_id);
- HttpEventGen* get_events(HttpEnums::SourceId source_id);
+ HttpInfractions* get_infractions(HttpCommon::SourceId source_id);
+ HttpEventGen* get_events(HttpCommon::SourceId source_id);
// *** Inspector => StreamSplitter (facts about the message section that is coming next)
HttpEnums::SectionType type_expected[2] = { HttpEnums::SEC_REQUEST, HttpEnums::SEC_STATUS };
// length of the data from Content-Length field
z_stream* compress_stream[2] = { nullptr, nullptr };
uint64_t zero_nine_expected = 0;
- int64_t data_length[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
+ int64_t data_length[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
uint32_t section_size_target[2] = { 0, 0 };
HttpEnums::CompressId compression[2] = { HttpEnums::CMP_NONE, HttpEnums::CMP_NONE };
HttpEnums::DetectionStatus detection_status[2] = { HttpEnums::DET_ON, HttpEnums::DET_ON };
snort::MimeSession* mime_state[2] = { nullptr, nullptr };
snort::UtfDecodeSession* utf_state = nullptr; // SRC_SERVER only
fd_session_t* fd_state = nullptr; // SRC_SERVER only
- int64_t file_depth_remaining[2] = { HttpEnums::STAT_NOT_PRESENT,
- HttpEnums::STAT_NOT_PRESENT };
- int64_t detect_depth_remaining[2] = { HttpEnums::STAT_NOT_PRESENT,
- HttpEnums::STAT_NOT_PRESENT };
+ int64_t file_depth_remaining[2] = { HttpCommon::STAT_NOT_PRESENT,
+ HttpCommon::STAT_NOT_PRESENT };
+ int64_t detect_depth_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)
- int64_t body_octets[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
- int32_t status_code_num = HttpEnums::STAT_NOT_PRESENT;
+ int64_t body_octets[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
+ int32_t status_code_num = HttpCommon::STAT_NOT_PRESENT;
HttpEnums::VersionId version_id[2] = { HttpEnums::VERS__NOT_PRESENT,
HttpEnums::VERS__NOT_PRESENT };
HttpEnums::MethodId method_id = HttpEnums::METH__NOT_PRESENT;
#include "config.h"
#endif
+#include "http_common.h"
#include "http_enum.h"
#include "http_header_normalizer.h"
#include <cstring>
+using namespace HttpCommon;
using namespace HttpEnums;
// This derivation removes leading and trailing linear white space and replaces internal strings of
#include "protocols/packet.h"
#include "stream/stream.h"
+#include "http_common.h"
#include "http_context_data.h"
+#include "http_enum.h"
#include "http_js_norm.h"
#include "http_msg_body.h"
#include "http_msg_body_chunk.h"
#include "http_test_manager.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
uint32_t HttpInspect::xtra_trueip_id;
#ifdef REG_TEST
if (params->test_input)
{
- HttpTestManager::activate_test_input();
+ HttpTestManager::activate_test_input(HttpTestManager::IN_HTTP);
}
if (params->test_output)
{
- HttpTestManager::activate_test_output();
+ HttpTestManager::activate_test_output(HttpTestManager::IN_HTTP);
+ }
+ if ((params->test_input) || (params->test_output))
+ {
+ HttpTestManager::set_print_amount(params->print_amount);
+ HttpTestManager::set_print_hex(params->print_hex);
+ HttpTestManager::set_show_pegs(params->show_pegs);
+ HttpTestManager::set_show_scan(params->show_scan);
}
- HttpTestManager::set_print_amount(params->print_amount);
- HttpTestManager::set_print_hex(params->print_hex);
- HttpTestManager::set_show_pegs(params->show_pegs);
- HttpTestManager::set_show_scan(params->show_scan);
#endif
}
HttpMsgSection* current_section = HttpContextData::get_snapshot(p);
if (current_section == nullptr)
- return HttpEnums::IS_NONE;
+ return IS_NONE;
// FIXIT-L revisit why we need this check. We should not be getting a current section back
// for a raw packet but one of the test cases did exactly that.
if (!(p->packet_flags & PKT_PSEUDO))
- return HttpEnums::IS_NONE;
+ return IS_NONE;
return current_section->get_inspection_section();
}
HttpMsgSection* current_section = HttpContextData::get_snapshot(p);
if (current_section == nullptr)
- return HttpEnums::SRC__NOT_COMPUTE;
+ return SRC__NOT_COMPUTE;
return current_section->get_source_id();
}
#ifdef REG_TEST
else
{
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
p->dsize);
session_data->section_type[source_id] = SEC__NOT_COMPUTE;
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
current_section->print_section(HttpTestManager::get_output_file());
fflush(HttpTestManager::get_output_file());
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
printf("Finished processing section from test %" PRIi64 "\n",
HttpTestManager::get_test_number());
// HttpInspect class
//-------------------------------------------------------------------------
+#include "http_common.h"
#include "http_enum.h"
#include "http_field.h"
#include "http_module.h"
return new HttpStreamSplitter(is_client_to_server, this);
}
static HttpEnums::InspectSection get_latest_is(const snort::Packet* p);
- static HttpEnums::SourceId get_latest_src(const snort::Packet* p);
+ static HttpCommon::SourceId get_latest_src(const snort::Packet* p);
// Callbacks that provide "extra data"
static int get_xtra_trueip(snort::Flow*, uint8_t**, uint32_t*, uint32_t*);
friend HttpStreamSplitter;
bool process(const uint8_t* data, const uint16_t dsize, snort::Flow* const flow,
- HttpEnums::SourceId source_id_, bool buf_owner) const;
+ HttpCommon::SourceId source_id_, bool buf_owner) const;
const HttpParaList* const params;
#include "utils/util_jsnorm.h"
#include "utils/safec.h"
+#include "http_enum.h"
+
using namespace HttpEnums;
using namespace snort;
#include "log/messages.h"
+#include "http_enum.h"
#include "http_js_norm.h"
#include "http_uri_norm.h"
#include "file_api/file_flows.h"
#include "http_api.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_js_norm.h"
#include "http_msg_request.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgBody::HttpMsgBody(const uint8_t* buffer, const uint16_t buf_size,
#ifndef HTTP_MSG_BODY_H
#define HTTP_MSG_BODY_H
-#include "http_msg_section.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_field.h"
+#include "http_msg_section.h"
//-------------------------------------------------------------------------
// HttpMsgBody class
protected:
HttpMsgBody(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_);
int64_t body_octets;
#endif
#include "http_msg_body_chunk.h"
+#include "http_common.h"
-using namespace HttpEnums;
+using namespace HttpCommon;
void HttpMsgBodyChunk::update_flow()
{
#ifndef HTTP_MSG_BODY_CHUNK_H
#define HTTP_MSG_BODY_CHUNK_H
+#include "http_common.h"
#include "http_msg_body.h"
//-------------------------------------------------------------------------
{
public:
HttpMsgBodyChunk(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_, const HttpParaList* params_)
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ const HttpParaList* params_)
: HttpMsgBody(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_) {}
void update_flow() override;
#include "http_msg_body_cl.h"
-using namespace HttpEnums;
-
void HttpMsgBodyCl::update_flow()
{
if (session_data->cutter[source_id] != nullptr)
#ifndef HTTP_MSG_BODY_CL_H
#define HTTP_MSG_BODY_CL_H
-#include "http_msg_section.h"
-#include "http_msg_body.h"
+#include "http_common.h"
#include "http_field.h"
+#include "http_msg_body.h"
+#include "http_msg_section.h"
//-------------------------------------------------------------------------
// HttpMsgBodyCl class
{
public:
HttpMsgBodyCl(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_)
: HttpMsgBody(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_) {}
void update_flow() override;
#include "http_msg_body_old.h"
-using namespace HttpEnums;
-
void HttpMsgBodyOld::update_flow()
{
// Always more body expected
#ifndef HTTP_MSG_BODY_OLD_H
#define HTTP_MSG_BODY_OLD_H
-#include "http_msg_section.h"
-#include "http_msg_body.h"
+#include "http_common.h"
#include "http_field.h"
+#include "http_msg_body.h"
+#include "http_msg_section.h"
//-------------------------------------------------------------------------
// HttpMsgBodyOld class
{
public:
HttpMsgBodyOld(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_)
: HttpMsgBody(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_) {}
void update_flow() override;
#include "config.h"
#endif
+#include "http_common.h"
+#include "http_enum.h"
#include "http_msg_head_shared.h"
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgHeadShared::~HttpMsgHeadShared()
#include <bitset>
-#include "http_str_to_code.h"
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_field.h"
#include "http_header_normalizer.h"
#include "http_msg_section.h"
-#include "http_field.h"
+#include "http_str_to_code.h"
//-------------------------------------------------------------------------
// HttpMsgHeadShared class
protected:
HttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size,
- HttpFlowData* session_data_, HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpFlowData* session_data_, HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_)
: HttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
{ }
NormalizedHeader* get_header_node(HttpEnums::HeaderId k) const;
NormalizedHeader* norm_heads = nullptr;
- int32_t num_headers = HttpEnums::STAT_NOT_COMPUTE;
+ int32_t num_headers = HttpCommon::STAT_NOT_COMPUTE;
std::bitset<MAX> headers_present = 0;
};
#include "file_api/file_flows.h"
#include "file_api/file_service.h"
#include "http_api.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_msg_request.h"
#include "http_msg_body.h"
#include "pub_sub/http_events.h"
#include "sfip/sf_ip.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgHeader::HttpMsgHeader(const uint8_t* buffer, const uint16_t buf_size,
#include "file_api/file_api.h"
+#include "http_common.h"
#include "http_enum.h"
#include "http_field.h"
#include "http_msg_head_shared.h"
{
public:
HttpMsgHeader(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_);
HttpEnums::InspectSection get_inspection_section() const override
{ return HttpEnums::IS_HEADER; }
#include "http_msg_request.h"
#include "http_api.h"
+#include "http_common.h"
+#include "http_enum.h"
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgRequest::HttpMsgRequest(const uint8_t* buffer, const uint16_t buf_size,
#ifndef HTTP_MSG_REQUEST_H
#define HTTP_MSG_REQUEST_H
+#include "http_common.h"
+#include "http_enum.h"
+#include "http_msg_start.h"
#include "http_str_to_code.h"
#include "http_uri.h"
#include "http_uri_norm.h"
-#include "http_msg_start.h"
-#include "http_field.h"
//-------------------------------------------------------------------------
// HttpMsgRequest class
{
public:
HttpMsgRequest(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_);
~HttpMsgRequest() override { delete uri; }
void gen_events() override;
#include "http_msg_section.h"
#include "http_context_data.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_msg_body.h"
#include "http_msg_head_shared.h"
#include "http_msg_header.h"
#include "http_test_manager.h"
#include "stream/flush_bucket.h"
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgSection::HttpMsgSection(const uint8_t* buffer, const uint16_t buf_size,
#include "detection/detection_util.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_field.h"
#include "http_module.h"
#include "http_flow_data.h"
virtual HttpEnums::InspectSection get_inspection_section() const
{ return HttpEnums::IS_NONE; }
virtual bool detection_required() const = 0;
- HttpEnums::SourceId get_source_id() const { return source_id; }
+ HttpCommon::SourceId get_source_id() const { return source_id; }
HttpTransaction* get_transaction() const { return transaction; }
const HttpParaList* get_params() const { return params; }
HttpMsgRequest* get_request() const { return request; }
HttpMsgStatus* get_status() const { return status; }
- HttpMsgHeader* get_header(HttpEnums::SourceId source_id) const { return header[source_id]; }
- HttpMsgTrailer* get_trailer(HttpEnums::SourceId source_id) const
+ HttpMsgHeader* get_header(HttpCommon::SourceId source_id) const { return header[source_id]; }
+ HttpMsgTrailer* get_trailer(HttpCommon::SourceId source_id) const
{ return trailer[source_id]; }
virtual HttpMsgBody* get_body() { return nullptr; }
protected:
HttpMsgSection(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_, const HttpParaList*
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_, const HttpParaList*
params_);
void get_related_sections();
HttpTransaction* const transaction;
uint64_t trans_num;
int32_t status_code_num;
- const HttpEnums::SourceId source_id;
+ const HttpCommon::SourceId source_id;
HttpEnums::VersionId version_id;
HttpEnums::MethodId method_id;
const bool tcp_close;
#include "http_msg_start.h"
+#include "http_enum.h"
+
using namespace HttpEnums;
void HttpMsgStart::analyze()
#ifndef HTTP_MSG_START_H
#define HTTP_MSG_START_H
-#include "http_msg_section.h"
+#include "http_common.h"
#include "http_field.h"
+#include "http_msg_section.h"
//-------------------------------------------------------------------------
// HttpMsgStart class
protected:
HttpMsgStart(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_)
: HttpMsgSection(buffer, buf_size, session_data_, source_id_, buf_owner, flow_, params_)
{ }
#include "http_msg_status.h"
#include "http_api.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_msg_header.h"
#include "stream/stream.h"
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgStatus::HttpMsgStatus(const uint8_t* buffer, const uint16_t buf_size,
#ifndef HTTP_MSG_STATUS_H
#define HTTP_MSG_STATUS_H
-#include "http_msg_start.h"
+#include "http_common.h"
#include "http_field.h"
+#include "http_msg_start.h"
//-------------------------------------------------------------------------
// HttpMsgStatus class
{
public:
HttpMsgStatus(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_);
void gen_events() override;
void update_flow() override;
#include "http_msg_trailer.h"
#include "http_api.h"
+#include "http_common.h"
+#include "http_enum.h"
+using namespace HttpCommon;
using namespace HttpEnums;
HttpMsgTrailer::HttpMsgTrailer(const uint8_t* buffer, const uint16_t buf_size,
#ifndef HTTP_MSG_TRAILER_H
#define HTTP_MSG_TRAILER_H
+#include "http_common.h"
+#include "http_enum.h"
#include "http_msg_head_shared.h"
//-------------------------------------------------------------------------
{
public:
HttpMsgTrailer(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
- HttpEnums::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_);
HttpEnums::InspectSection get_inspection_section() const override
{ return HttpEnums::IS_TRAILER; }
#include "config.h"
#endif
+#include "http_common.h"
#include "http_normalizers.h"
#include <cstring>
+using namespace HttpCommon;
using namespace HttpEnums;
// Collection of stock normalization functions. This will probably grow throughout the life of the
#include <cstring>
-#include "http_enum.h"
+#include "http_common.h"
// Need to replace this simple algorithm for better performance FIXIT-P
int32_t str_to_code(const uint8_t* text, const int32_t text_len, const StrCode table[])
return table[k].code;
}
}
- return HttpEnums::STAT_OTHER;
+ return HttpCommon::STAT_OTHER;
}
int32_t substr_to_code(const uint8_t* text, const int32_t text_len, const StrCode table[])
return table[k].code;
}
}
- return HttpEnums::STAT_OTHER;
+ return HttpCommon::STAT_OTHER;
}
#include "stream/stream_splitter.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_flow_data.h"
#include "http_test_manager.h"
HttpStreamSplitter(bool is_client_to_server, HttpInspect* my_inspector_) :
snort::StreamSplitter(is_client_to_server),
my_inspector(my_inspector_),
- source_id(is_client_to_server ? HttpEnums::SRC_CLIENT : HttpEnums::SRC_SERVER) {}
+ source_id(is_client_to_server ? HttpCommon::SRC_CLIENT : HttpCommon::SRC_SERVER) {}
Status scan(snort::Packet* pkt, const uint8_t* data, uint32_t length, uint32_t not_used,
uint32_t* flush_offset) override;
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned, const
bool finish(snort::Flow* flow) override;
bool init_partial_flush(snort::Flow* flow) override;
bool is_paf() override { return true; }
+ static StreamSplitter::Status status_value(StreamSplitter::Status ret_val, bool http2 = false);
// FIXIT-M should return actual packet buffer size
unsigned max(snort::Flow*) override { return HttpEnums::MAX_OCTETS; }
static void detain_packet(snort::Packet* pkt);
HttpInspect* const my_inspector;
- const HttpEnums::SourceId source_id;
+ const HttpCommon::SourceId source_id;
};
#endif
#include "file_api/file_flows.h"
+#include "http_common.h"
#include "http_cutter.h"
+#include "http_enum.h"
#include "http_module.h"
#include "http_msg_request.h"
#include "http_stream_splitter.h"
#include "http_test_input.h"
+using namespace HttpCommon;
using namespace HttpEnums;
bool HttpStreamSplitter::finish(snort::Flow* flow)
return false;
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
if (!HttpTestManager::get_test_input_source()->finish())
return false;
}
#ifdef REG_TEST
- if (HttpTestManager::use_test_output() && !HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) &&
+ !HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
printf("Partial flush from flow data %" PRIu64 "\n", session_data->seq_num);
fflush(stdout);
assert(session_data != nullptr);
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
if (!(flags & PKT_PDU_TAIL))
{
if (session_data->section_type[source_id] == SEC_DISCARD)
{
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
fprintf(HttpTestManager::get_output_file(), "Discarded %u octets\n\n", len);
fflush(HttpTestManager::get_output_file());
#include "config.h"
#endif
+#include "http_common.h"
#include "http_cutter.h"
+#include "http_enum.h"
#include "http_inspect.h"
#include "http_module.h"
#include "http_stream_splitter.h"
#include "stream/stream.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
// Convenience function. All housekeeping that must be done before we can return FLUSH to stream.
if (flush_offset != nullptr)
{
#ifdef REG_TEST
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
HttpTestManager::get_test_input_source()->flush(num_flushed);
}
}
}
-static StreamSplitter::Status status_value(StreamSplitter::Status ret_val)
+// FIXIT-M this function is shared code that needs to get rolled up into a utility that supports
+// HI, H2I, and future service inspectors
+StreamSplitter::Status HttpStreamSplitter::status_value(StreamSplitter::Status ret_val, bool http2)
{
+ UNUSED(http2);
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ const HttpTestManager::INPUT_TYPE type =
+ http2 ? HttpTestManager::IN_HTTP2 : HttpTestManager::IN_HTTP;
+ if (HttpTestManager::use_test_output(type))
{
fprintf(HttpTestManager::get_output_file(), "scan() returning status %d\n", ret_val);
fflush(HttpTestManager::get_output_file());
}
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(type))
{
if (ret_val == StreamSplitter::ABORT)
return StreamSplitter::ABORT;
void HttpStreamSplitter::detain_packet(Packet* pkt)
{
#ifdef REG_TEST
- if (HttpTestManager::use_test_output())
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
fprintf(HttpTestManager::get_output_file(), "Packet detain request\n");
fflush(HttpTestManager::get_output_file());
}
- if (!HttpTestManager::use_test_input())
+ if (!HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
#endif
Stream::set_packet_action_to_hold(pkt);
HttpModule::increment_peg_counts(PEG_DETAINED);
return status_value(StreamSplitter::ABORT);
#ifdef REG_TEST
- if (HttpTestManager::use_test_input())
+ if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
// 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.
return StreamSplitter::FLUSH;
data = test_data;
}
- else if (HttpTestManager::use_test_output())
+ else if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
printf("Scan from flow data %" PRIu64
" direction %d length %u client port %hu server port %hu\n", session_data->seq_num,
#include "config.h"
#endif
+#include "http_enum.h"
#include "http_msg_header.h"
#include "http_msg_request.h"
#include "http_test_input.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_module.h"
#include "http_test_manager.h"
+using namespace HttpCommon;
using namespace HttpEnums;
static unsigned convert_num_octets(const char buffer[], unsigned length)
#include <cstdio>
+#include "http_common.h"
#include "http_enum.h"
#include "http_flow_data.h"
public:
HttpTestInput(const char* fileName);
~HttpTestInput();
- void scan(uint8_t*& data, uint32_t& length, HttpEnums::SourceId source_id, uint64_t seq_num);
+ void scan(uint8_t*& data, uint32_t& length, HttpCommon::SourceId source_id, uint64_t seq_num);
void flush(uint32_t num_octets);
- void reassemble(uint8_t** buffer, unsigned& length, HttpEnums::SourceId source_id,
+ void reassemble(uint8_t** buffer, unsigned& length, HttpCommon::SourceId source_id,
bool& tcp_close, bool& partial_flush);
bool finish();
bool flushed = false;
// current direction of traffic flow. Toggled by commands in file.
- HttpEnums::SourceId last_source_id = HttpEnums::SRC_CLIENT;
+ HttpCommon::SourceId last_source_id = HttpCommon::SRC_CLIENT;
// reassemble() just completed and all flushed octets forwarded, time to resume scan()
bool just_flushed = true;
#include "http_test_input.h"
-bool HttpTestManager::test_input = false;
-bool HttpTestManager::test_output = false;
+unsigned HttpTestManager::test_input = IN_NONE;
+unsigned HttpTestManager::test_output = IN_NONE;
HttpTestInput* HttpTestManager::test_input_source = nullptr;
const char* HttpTestManager::test_output_prefix = "httpresults/testcase";
int64_t HttpTestManager::test_number = -1;
}
}
-void HttpTestManager::activate_test_input()
+void HttpTestManager::activate_test_input(INPUT_TYPE type)
{
- test_input = true;
+ test_input |= type;
if (test_input_source == nullptr)
{
test_input_source = new HttpTestInput("http_test_msgs.txt");
class HttpTestManager
{
public:
- static bool use_test_input() { return test_input; }
- static void activate_test_input();
- static void activate_test_output() { test_output = true; }
+ // Bitmap: 1, 2, 4, 8, ...
+ enum INPUT_TYPE { IN_NONE = 0, IN_HTTP = 0x1, IN_HTTP2 = 0x2 };
+
+ static bool use_test_input(INPUT_TYPE type) { return (type & test_input) != 0; }
+ static void activate_test_input(INPUT_TYPE type);
+ static void activate_test_output(INPUT_TYPE type) { test_output |= type; }
static HttpTestInput* get_test_input_source() { return test_input_source; }
static void update_test_number(int64_t new_test_number);
- static bool use_test_output() { return test_output || test_input; }
+ static bool use_test_output(INPUT_TYPE type)
+ { return (test_output & type) || (test_input & type); }
static FILE* get_output_file() { return (test_out != nullptr) ? test_out : stdout; }
static int64_t get_test_number() { return test_number; }
static void set_print_amount(long print_amount_) { print_amount = print_amount_; }
private:
HttpTestManager() = delete;
- static bool test_input;
+ static unsigned test_input;
static HttpTestInput* test_input_source;
// Printing results of message processing
- static bool test_output;
+ static unsigned test_output;
static const char* test_output_prefix;
static FILE* test_out;
static int64_t test_number;
#include "http_transaction.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_event.h"
#include "http_msg_body.h"
#include "http_msg_header.h"
#include "http_msg_status.h"
#include "http_msg_trailer.h"
+using namespace HttpCommon;
using namespace HttpEnums;
static void delete_section_list(HttpMsgSection* section_list)
body_list = latest_body;
}
-HttpInfractions* HttpTransaction::get_infractions(HttpEnums::SourceId source_id)
+HttpInfractions* HttpTransaction::get_infractions(SourceId source_id)
{
return infractions[source_id];
}
-HttpEventGen* HttpTransaction::get_events(HttpEnums::SourceId source_id)
+HttpEventGen* HttpTransaction::get_events(SourceId source_id)
{
return events[source_id];
}
#ifndef TRANSACTION_H
#define TRANSACTION_H
+#include "http_common.h"
#include "http_enum.h"
#include "http_flow_data.h"
public:
~HttpTransaction();
static HttpTransaction* attach_my_transaction(HttpFlowData* session_data,
- HttpEnums::SourceId source_id);
+ HttpCommon::SourceId source_id);
static void delete_transaction(HttpTransaction* transaction, HttpFlowData* session_data);
HttpMsgRequest* get_request() const { return request; }
HttpMsgStatus* get_status() const { return status; }
void set_status(HttpMsgStatus* status_) { status = status_; }
- HttpMsgHeader* get_header(HttpEnums::SourceId source_id) const { return header[source_id]; }
- void set_header(HttpMsgHeader* header_, HttpEnums::SourceId source_id)
+ HttpMsgHeader* get_header(HttpCommon::SourceId source_id) const { return header[source_id]; }
+ void set_header(HttpMsgHeader* header_, HttpCommon::SourceId source_id)
{ header[source_id] = header_; }
- HttpMsgTrailer* get_trailer(HttpEnums::SourceId source_id) const
+ HttpMsgTrailer* get_trailer(HttpCommon::SourceId source_id) const
{ return trailer[source_id]; }
- void set_trailer(HttpMsgTrailer* trailer_, HttpEnums::SourceId source_id)
+ void set_trailer(HttpMsgTrailer* trailer_, HttpCommon::SourceId source_id)
{ trailer[source_id] = trailer_; }
void set_body(HttpMsgBody* latest_body);
- HttpInfractions* get_infractions(HttpEnums::SourceId source_id);
- HttpEventGen* get_events(HttpEnums::SourceId source_id);
+ HttpInfractions* get_infractions(HttpCommon::SourceId source_id);
+ HttpEventGen* get_events(HttpCommon::SourceId source_id);
void set_one_hundred_response();
bool final_response() const { return !second_response_expected; }
#include "http_uri.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "hash/hashfcn.h"
+using namespace HttpCommon;
using namespace HttpEnums;
void HttpUri::parse_uri()
#include <sstream>
+#include "http_enum.h"
#include "log/messages.h"
using namespace HttpEnums;
#include "log/messages.h"
#include "protocols/packet.h"
+#include "http_common.h"
+#include "http_enum.h"
#include "http_flow_data.h"
#include "http_inspect.h"
#include "http_msg_head_shared.h"
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
THREAD_LOCAL std::array<ProfileStats, PSI_MAX> HttpCursorModule::http_ps;
#include "config.h"
#endif
+#include "service_inspectors/http_inspect/http_common.h"
#include "service_inspectors/http_inspect/http_field.h"
#include "service_inspectors/http_inspect/http_normalizers.h"
#include "service_inspectors/http_inspect/http_test_manager.h"
#include <CppUTestExt/MockSupport.h>
using namespace snort;
-using namespace HttpEnums;
+using namespace HttpCommon;
// Stubs whose sole purpose is to make the test code link
const bool HttpEnums::is_sp_tab[256] {};
#include "config.h"
#endif
+#include "service_inspectors/http_inspect/http_common.h"
#include "service_inspectors/http_inspect/http_enum.h"
#include "service_inspectors/http_inspect/http_flow_data.h"
#include "service_inspectors/http_inspect/http_module.h"
#include <CppUTestExt/MockSupport.h>
using namespace snort;
+using namespace HttpCommon;
using namespace HttpEnums;
namespace snort