#include "service_inspectors/http_inspect/http_flow_data.h"
#include "service_inspectors/http_inspect/http_stream_splitter.h"
-#include "http2_dummy_packet.h"
#include "http2_utils.h"
using namespace snort;
if (cur_data > 0)
{
uint32_t http_flush_offset = 0;
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- uint32_t unused = 0;
session_data->stream_in_hi = session_data->current_stream[source_id];
if ((data_bytes_read == data_len) && (frame_flags & FLAG_END_STREAM))
{
HttpFlowData* const hi_flow = stream->get_hi_flow_data();
hi_flow->set_h2_body_state(source_id, H2_BODY_LAST_SEG);
}
- scan_result = session_data->hi_ss[source_id]->scan(&dummy_pkt, data + cur_data_offset,
- cur_data, unused, &http_flush_offset);
+ scan_result = session_data->hi_ss[source_id]->scan(session_data->flow, data + cur_data_offset, cur_data,
+ &http_flush_offset);
session_data->stream_in_hi = NO_STREAM_ID;
switch (scan_result)
{
#include "service_inspectors/http_inspect/http_inspect.h"
#include "service_inspectors/http_inspect/http_stream_splitter.h"
-#include "http2_dummy_packet.h"
#include "http2_flow_data.h"
#include "http2_module.h"
return (state == Http2Enums::STREAM_EXPECT_BODY) || (state == Http2Enums::STREAM_BODY);
}
-void Http2DataFrame::analyze_http1()
+void Http2DataFrame::analyze_http1(Packet* p)
{
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- dummy_pkt.packet_flags = (source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
- dummy_pkt.dsize = data_length;
- dummy_pkt.data = data_buffer;
- dummy_pkt.xtradata_mask = 0;
// FIXIT-E no checks here
- session_data->hi->eval(&dummy_pkt);
- detection_required = dummy_pkt.is_detection_required();
- xtradata_mask = dummy_pkt.xtradata_mask;
+ session_data->hi->eval(p, source_id, data_buffer, data_length);
}
-void Http2DataFrame::clear()
+void Http2DataFrame::clear(Packet* p)
{
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- session_data->hi->clear(&dummy_pkt);
+ session_data->hi->clear(p);
}
void Http2DataFrame::update_stream_state()
public:
~Http2DataFrame() override = default;
bool valid_sequence(Http2Enums::StreamState state) override;
- void analyze_http1() override;
- void clear() override;
+ void analyze_http1(snort::Packet*) override;
+ void clear(snort::Packet*) override;
- uint32_t get_xtradata_mask() override { return xtradata_mask; }
- bool is_detection_required() const override { return detection_required; }
+ bool is_detection_required() const override { return false; }
void update_stream_state() override;
friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const uint32_t, const uint8_t*,
const uint32_t data_length;
const uint8_t* const data_buffer;
- uint32_t xtradata_mask = 0;
- bool detection_required = false;
};
#endif
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2022 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.
-//--------------------------------------------------------------------------
-// http2_dummy_packet.h author Katura Harvey <katharve@cisco.com>
-
-/*
- * The purpose of this Packet subclass is to enable H2I to take direction from http_inspect on
- * whether or not to send a frame to detection. When http_inspect is processing normal HTTP/1.1
- * traffic it is dealing with a real packet that has a context, the field on which disable_all()
- * is called to disable detection on that packet. With HTTP/2 traffic, http_inspect is processing a
- * dummy packet that H2I created, which does not contain a context object. Rather than create an
- * entire new context object when we really only need a bool, http_inspect checks if the flow is
- * HTTP/2 and sets a bool instead of calling it's usual disable_all(). H2I checks the bool and can
- * then call disable_all() on the real packet.
- */
-
-#ifndef HTTP2_DUMMY_PACKET_H
-#define HTTP2_DUMMY_PACKET_H
-
-#include "protocols/packet.h"
-
-class Http2DummyPacket : public snort::Packet
-{
-public:
- Http2DummyPacket() : snort::Packet(false) { }
- bool is_detection_required() { return !disable_inspect; }
-};
-
-#endif
#ifndef HTTP2_FRAME_H
#define HTTP2_FRAME_H
+#include "protocols/packet.h"
#include "service_inspectors/http_inspect/http_common.h"
#include "service_inspectors/http_inspect/http_field.h"
const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* session_data,
HttpCommon::SourceId source_id, Http2Stream* stream);
virtual bool valid_sequence(Http2Enums::StreamState) { return true; }
- virtual void analyze_http1() { }
- virtual void clear() { }
+ virtual void analyze_http1(snort::Packet*) { }
+ virtual void clear(snort::Packet*) { }
virtual const Field& get_buf(unsigned id);
- virtual uint32_t get_xtradata_mask() { return 0; }
virtual bool is_detection_required() const { return true; }
virtual void update_stream_state() { }
#include "service_inspectors/http_inspect/http_inspect.h"
#include "service_inspectors/http_inspect/http_stream_splitter.h"
-#include "http2_dummy_packet.h"
#include "http2_enum.h"
#include "http2_flow_data.h"
#include "http2_hpack.h"
return stream->get_state(source_id) == STREAM_ERROR;
}
-void Http2HeadersFrame::clear()
+void Http2HeadersFrame::clear(Packet* p)
{
if (session_data->abort_flow[source_id] || in_error_state())
return;
- Packet dummy_pkt(false);
- dummy_pkt.flow = session_data->flow;
- session_data->hi->clear(&dummy_pkt);
+ session_data->hi->clear(p);
}
bool Http2HeadersFrame::decode_headers(Http2StartLine* start_line_generator, bool trailers)
return true;
}
-void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceId hi_source_id)
+void Http2HeadersFrame::process_decoded_headers(HttpFlowData* http_flow, SourceId hi_source_id, Packet* p)
{
if (session_data->abort_flow[source_id] or http1_header.length() < 0)
return;
if (http1_header.length() > 0)
{
uint32_t flush_offset;
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- const uint32_t unused = 0;
const StreamSplitter::Status header_scan_result =
- session_data->hi_ss[hi_source_id]->scan(&dummy_pkt, http1_header.start(),
- http1_header.length(), unused, &flush_offset);
+ session_data->hi_ss[hi_source_id]->scan(session_data->flow, http1_header.start(), http1_header.length(),
+ &flush_offset);
assert((session_data->is_processing_partial_header() and
(header_scan_result == StreamSplitter::SEARCH)) or
((!session_data->is_processing_partial_header() and
// http_inspect eval() of headers
{
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- dummy_pkt.packet_flags = (hi_source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
- dummy_pkt.dsize = stream_buf.length;
- dummy_pkt.data = stream_buf.data;
- dummy_pkt.xtradata_mask = 0;
- session_data->hi->eval(&dummy_pkt);
+ session_data->hi->eval(p, hi_source_id, stream_buf.data, stream_buf.length);
+
if (http_flow->get_type_expected(hi_source_id) == SEC_ABORT)
{
assert(session_data->is_processing_partial_header());
stream->set_state(hi_source_id, STREAM_ERROR);
}
- detection_required = dummy_pkt.is_detection_required();
- xtradata_mask = dummy_pkt.xtradata_mask;
}
}
class Http2HeadersFrame : public Http2Frame
{
public:
- void clear() override;
+ void clear(snort::Packet*) override;
const Field& get_buf(unsigned id) override;
- uint32_t get_xtradata_mask() override { return xtradata_mask; }
- bool is_detection_required() const override { return detection_required; }
+ bool is_detection_required() const override { return false; }
#ifdef REG_TEST
void print_frame(FILE* output) override;
const uint8_t* data_buffer, const uint32_t data_len, Http2FlowData* ssn_data,
HttpCommon::SourceId src_id, Http2Stream* stream);
bool decode_headers(Http2StartLine* start_line_generator, bool trailers);
- void process_decoded_headers(HttpFlowData* http_flow, HttpCommon::SourceId hi_source_id);
+ void process_decoded_headers(HttpFlowData* http_flow, HttpCommon::SourceId hi_source_id, snort::Packet* p);
uint8_t get_flags_mask() const override;
virtual bool in_error_state() const;
Field http1_header; // finalized headers to be passed to http_inspect
- uint32_t xtradata_mask = 0;
- bool detection_required = false;
Http2HpackDecoder* hpack_decoder;
uint8_t hpack_headers_offset = 0;
};
return (state == Http2Enums::STREAM_EXPECT_HEADERS);
}
-void Http2HeadersFrameHeader::analyze_http1()
+void Http2HeadersFrameHeader::analyze_http1(Packet* p)
{
HttpFlowData* http_flow;
- if (!process_start_line(http_flow, source_id))
+ if (!process_start_line(http_flow, source_id, p))
return;
// if END_STREAM flag set on headers, tell http_inspect not to expect a message body
if (get_flags() & FLAG_END_STREAM)
stream->get_hi_flow_data()->finish_h2_body(source_id, H2_BODY_NO_BODY, false);
- process_decoded_headers(http_flow, source_id);
+ process_decoded_headers(http_flow, source_id, p);
}
void Http2HeadersFrameHeader::update_stream_state()
const uint32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
bool valid_sequence(Http2Enums::StreamState state) override;
- void analyze_http1() override;
+ void analyze_http1(snort::Packet*) override;
void update_stream_state() override;
#ifdef REG_TEST
#include "service_inspectors/http_inspect/http_inspect.h"
#include "service_inspectors/http_inspect/http_stream_splitter.h"
-#include "http2_dummy_packet.h"
#include "http2_enum.h"
#include "http2_flow_data.h"
#include "http2_hpack.h"
return false;
}
-void Http2HeadersFrameTrailer::analyze_http1()
+void Http2HeadersFrameTrailer::analyze_http1(Packet* p)
{
HttpFlowData* const http_flow = stream->get_hi_flow_data();
assert(http_flow);
if (stream_buf.data != nullptr)
{
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- dummy_pkt.packet_flags = (source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
- dummy_pkt.dsize = stream_buf.length;
- dummy_pkt.data = stream_buf.data;
- session_data->hi->eval(&dummy_pkt);
+ session_data->hi->eval(p, source_id, stream_buf.data, stream_buf.length);
assert (!valid_headers || http_flow->get_type_expected(source_id) == SEC_TRAILER);
if (http_flow->get_type_expected(source_id) == SEC_ABORT)
{
stream->set_state(source_id, STREAM_ERROR);
return;
}
- session_data->hi->clear(&dummy_pkt);
+ session_data->hi->clear(p);
}
}
return;
}
- process_decoded_headers(http_flow, source_id);
+ process_decoded_headers(http_flow, source_id, p);
}
void Http2HeadersFrameTrailer::update_stream_state()
const uint32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
bool valid_sequence(Http2Enums::StreamState state) override;
- void analyze_http1() override;
+ void analyze_http1(snort::Packet*) override;
void update_stream_state() override;
#ifdef REG_TEST
#include "service_inspectors/http_inspect/http_inspect.h"
#include "service_inspectors/http_inspect/http_stream_splitter.h"
-#include "http2_dummy_packet.h"
#include "http2_enum.h"
#include "http2_flow_data.h"
#include "http2_hpack.h"
delete start_line_generator;
}
-bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow,
- SourceId hi_source_id)
+bool Http2HeadersFrameWithStartline::process_start_line(HttpFlowData*& http_flow, SourceId hi_source_id, Packet* p)
{
if (session_data->abort_flow[source_id])
return false;
// http_inspect scan() of start line
{
uint32_t flush_offset;
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- const uint32_t unused = 0;
const StreamSplitter::Status start_scan_result =
- session_data->hi_ss[hi_source_id]->scan(&dummy_pkt, start_line.start(),
- start_line.length(), unused, &flush_offset);
+ session_data->hi_ss[hi_source_id]->scan(session_data->flow, start_line.start(), start_line.length(),
+ &flush_offset);
if (start_scan_result != StreamSplitter::FLUSH)
{
stream->set_state(hi_source_id, STREAM_ERROR);
assert(http_flow);
// http_inspect eval() and clear() of start line
{
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
- dummy_pkt.packet_flags = (hi_source_id == SRC_CLIENT) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
- dummy_pkt.dsize = stream_buf.length;
- dummy_pkt.data = stream_buf.data;
- session_data->hi->eval(&dummy_pkt);
+ session_data->hi->eval(p, hi_source_id, stream_buf.data, stream_buf.length);
if (http_flow->get_type_expected(hi_source_id) != SEC_HEADER)
{
stream->set_state(hi_source_id, STREAM_ERROR);
return false;
}
- session_data->hi->clear(&dummy_pkt);
+ session_data->hi->clear(p);
}
return true;
}
HttpCommon::SourceId src_id, Http2Stream* stream_) :
Http2HeadersFrame(header_buffer, header_len, data_buffer, data_len, ssn_data, src_id,
stream_) { }
- bool process_start_line(HttpFlowData*& http_flow, HttpCommon::SourceId hi_source_id);
+ bool process_start_line(HttpFlowData*& http_flow, HttpCommon::SourceId hi_source_id, snort::Packet* p);
bool are_pseudo_headers_complete();
Http2StartLine* start_line_generator = nullptr;
// Otherwise we can return buffers for raw packets because frame header is available before
// frame is reassembled.
- if (!session_data->frame_in_detection)
+ if (session_data->stream_in_hi == Http2Enums::NO_STREAM_ID)
return false;
Http2Stream* const stream = session_data->find_processing_stream();
uint8_t* const frame_header_copy = new uint8_t[FRAME_HEADER_LENGTH];
memcpy(frame_header_copy, session_data->lead_frame_header[source_id], FRAME_HEADER_LENGTH);
stream->eval_frame(frame_header_copy, FRAME_HEADER_LENGTH,
- session_data->frame_data[source_id], session_data->frame_data_size[source_id], source_id);
+ session_data->frame_data[source_id], session_data->frame_data_size[source_id], source_id, p);
if (!stream->get_current_frame()->is_detection_required())
DetectionEngine::disable_all(p);
- p->xtradata_mask |= stream->get_xtradata_mask();
// The current frame now owns these buffers, clear them from the flow data
session_data->frame_data[source_id] = nullptr;
Http2Stream* stream = session_data->find_processing_stream();
assert(stream != nullptr);
- stream->clear_frame();
+ stream->clear_frame(p);
if (session_data->delete_stream)
session_data->delete_processing_stream();
session_data->stream_in_hi = NO_STREAM_ID;
return true;
}
-void Http2PushPromiseFrame::analyze_http1()
+void Http2PushPromiseFrame::analyze_http1(Packet* p)
{
if (!start_line_generator->generate_start_line(start_line, are_pseudo_headers_complete()))
{
}
HttpFlowData* http_flow;
- if (!process_start_line(http_flow, SRC_CLIENT))
+ if (!process_start_line(http_flow, SRC_CLIENT, p))
return;
// Push promise cannot have a message body
// FIXIT-E handle bad request lines and cases where a message body is implied
stream->get_hi_flow_data()->finish_h2_body(SRC_CLIENT, H2_BODY_NO_BODY, false);
- process_decoded_headers(http_flow, SRC_CLIENT);
+ process_decoded_headers(http_flow, SRC_CLIENT, p);
}
void Http2PushPromiseFrame::update_stream_state()
{
public:
bool valid_sequence(Http2Enums::StreamState state) override;
- void analyze_http1() override;
+ void analyze_http1(snort::Packet*) override;
void update_stream_state() override;
static uint32_t get_promised_stream_id(Http2EventGen* const events,
Http2Infractions* const infractions, const uint8_t* data_buffer, uint32_t data_len);
#include "service_inspectors/http_inspect/http_stream_splitter.h"
#include "http2_data_cutter.h"
-#include "http2_dummy_packet.h"
#include "http2_flow_data.h"
+using namespace snort;
using namespace HttpCommon;
using namespace Http2Enums;
}
void Http2Stream::eval_frame(const uint8_t* header_buffer, uint32_t header_len,
- const uint8_t* data_buffer, uint32_t data_len, SourceId source_id)
+ const uint8_t* data_buffer, uint32_t data_len, SourceId source_id, Packet* p)
{
assert(current_frame == nullptr);
current_frame = Http2Frame::new_frame(header_buffer, header_len, data_buffer,
{
if (current_frame->valid_sequence(state[source_id]))
{
- current_frame->analyze_http1();
+ current_frame->analyze_http1(p);
current_frame->update_stream_state();
}
else
}
}
-void Http2Stream::clear_frame()
+void Http2Stream::clear_frame(Packet* p)
{
assert(current_frame != nullptr);
- current_frame->clear();
+ current_frame->clear(p);
delete current_frame;
current_frame = nullptr;
bool clear_partial_buffer)
{
uint32_t http_flush_offset = 0;
- Http2DummyPacket dummy_pkt;
- dummy_pkt.flow = session_data->flow;
const H2BodyState body_state = expect_trailers ?
H2_BODY_COMPLETE_EXPECT_TRAILERS : H2_BODY_COMPLETE;
get_hi_flow_data()->finish_h2_body(source_id, body_state, clear_partial_buffer);
if (clear_partial_buffer)
{
- uint32_t unused = 0;
- const snort::StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
- &dummy_pkt, nullptr, 0, unused, &http_flush_offset);
- assert(scan_result == snort::StreamSplitter::FLUSH);
+ const StreamSplitter::Status scan_result = session_data->hi_ss[source_id]->scan(
+ session_data->flow, nullptr, 0, &http_flush_offset);
+ assert(scan_result == StreamSplitter::FLUSH);
UNUSED(scan_result);
}
}
~Http2Stream();
uint32_t get_stream_id() const { return stream_id; }
void eval_frame(const uint8_t* header_buffer, uint32_t header_len, const uint8_t* data_buffer,
- uint32_t data_len, HttpCommon::SourceId source_id);
+ uint32_t data_len, HttpCommon::SourceId source_id, snort::Packet* p);
void check_and_cleanup_completed();
- void clear_frame();
+ void clear_frame(snort::Packet* p);
const Field& get_buf(unsigned id);
HttpFlowData* get_hi_flow_data() const { return hi_flow_data; }
void set_hi_flow_data(HttpFlowData* flow_data);
- uint32_t get_xtradata_mask() { return (current_frame != nullptr) ?
- current_frame->get_xtradata_mask() : 0; }
Http2Frame *get_current_frame() { return current_frame; }
void set_state(HttpCommon::SourceId source_id, Http2Enums::StreamState new_state);
#include <cassert>
-#include "http2_dummy_packet.h"
#include "http2_enum.h"
using namespace Http2Enums;
#include "detection/detection_engine.h"
#include "detection/detection_util.h"
-#include "service_inspectors/http2_inspect/http2_dummy_packet.h"
#include "service_inspectors/http2_inspect/http2_flow_data.h"
#include "log/unified2.h"
#include "protocols/packet.h"
void HttpInspect::disable_detection(Packet* p)
{
HttpFlowData* session_data = http_get_flow_data(p->flow);
- if (session_data->for_http2)
- p->disable_inspect = true;
- else
+ if (!session_data->for_http2)
{
assert(p->context);
DetectionEngine::disable_all(p);
void HttpInspect::eval(Packet* p)
{
- Profile profile(HttpModule::get_profile_stats());
-
const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
+ eval(p, source_id, p->data, p->dsize);
+ return;
+}
+
+void HttpInspect::eval(Packet* p, SourceId source_id, const uint8_t* data, uint16_t dsize)
+{
+ Profile profile(HttpModule::get_profile_stats());
HttpFlowData* session_data = http_get_flow_data(p->flow);
if (session_data == nullptr)
// use due to calls to HttpInspect::eval on the raw stream_user packet
if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) ||
(session_data->type_expected[source_id] == SEC_ABORT) ||
- (session_data->octets_reassembled[source_id] != p->dsize))
+ (session_data->octets_reassembled[source_id] != dsize))
{
//assert(session_data->type_expected[source_id] != SEC_ABORT);
//assert(session_data->section_type[source_id] != SEC__NOT_COMPUTE);
- //assert(session_data->octets_reassembled[source_id] == p->dsize);
+ //assert(session_data->octets_reassembled[source_id] == dsize);
session_data->type_expected[source_id] = SEC_ABORT;
return;
}
if (!session_data->for_http2)
- HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, p->dsize);
+ HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, dsize);
session_data->octets_reassembled[source_id] = STAT_NOT_PRESENT;
}
// Limit alt_dsize of message body sections to request/response depth
+ // p->dsize is not a typo. The actual value on the reassembled packet is what matters for this purpose.
if ((session_data->detect_depth_remaining[source_id] > 0) &&
(session_data->detect_depth_remaining[source_id] < p->dsize))
{
p->set_detect_limit(session_data->detect_depth_remaining[source_id]);
}
- if (!process(p->data, p->dsize, p->flow, source_id, true))
- disable_detection(p);
+ process(data, dsize, p->flow, source_id, true, p);
-#ifdef REG_TEST
- else
- {
- if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
- {
- fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
- p->dsize);
- fflush(HttpTestManager::get_output_file());
- }
- }
-#endif
+ // Detection was done in process()
+ if (!session_data->for_http2)
+ disable_detection(p);
// If current transaction is complete then we are done with it. This is strictly a memory
// optimization not necessary for correct operation.
SetExtraData(p, xtra_jsnorm_id);
}
-bool HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow,
- SourceId source_id, bool buf_owner) const
+void HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow, SourceId source_id,
+ bool buf_owner, Packet* p) const
{
HttpMsgSection* current_section;
HttpFlowData* session_data = http_get_flow_data(flow);
{
delete[] data;
}
- return false;
+ return;
}
current_section->analyze();
#endif
current_section->publish();
- return current_section->detection_required();
+ if (current_section->run_detection(p))
+ {
+#ifdef REG_TEST
+ if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
+ {
+ fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
+ dsize);
+ fflush(HttpTestManager::get_output_file());
+ }
+#endif
+ }
}
void HttpInspect::clear(Packet* p)
bool configure(snort::SnortConfig*) override;
void show(const snort::SnortConfig*) const override;
void eval(snort::Packet* p) override;
+ void eval(snort::Packet* p, HttpCommon::SourceId source_id, const uint8_t* data, uint16_t dsize);
void clear(snort::Packet* p) override;
HttpStreamSplitter* get_splitter(bool is_client_to_server) override
HttpStreamSplitter splitter[2] = { { true, this }, { false, this } };
- bool process(const uint8_t* data, const uint16_t dsize, snort::Flow* const flow,
- HttpCommon::SourceId source_id_, bool buf_owner) const;
+ void process(const uint8_t* data, const uint16_t dsize, snort::Flow* const flow,
+ HttpCommon::SourceId source_id_, bool buf_owner, snort::Packet* p) const;
static HttpFlowData* http_get_flow_data(const snort::Flow* flow);
static void http_set_flow_data(snort::Flow* flow, HttpFlowData* flow_data);
}
}
+bool HttpMsgSection::run_detection(snort::Packet* p)
+{
+ if ((p == nullptr) || !detection_required())
+ return false;
+ DetectionEngine::detect(p);
+ return true;
+}
+
const Field& HttpMsgSection::classic_normalize(const Field& raw, Field& norm,
bool do_path, const HttpParaList::UriParam& uri_param)
{
#include "detection/detection_util.h"
#include "framework/cursor.h"
+#include "protocols/packet.h"
#include "http_buffer_info.h"
#include "http_common.h"
// Manages the splitter and communication between message sections
virtual void update_flow() = 0;
+ // Publish an inspection event for other modules to consume
+ virtual void publish() {}
+
+ // Call the detection engine to inspect the current packet
+ bool run_detection(snort::Packet* p);
+
const Field& get_classic_buffer(unsigned id, uint64_t sub_id, uint64_t form);
const Field& get_classic_buffer(const HttpBufferInfo& buf);
const Field& get_param_buffer(Cursor& c, const HttpParam& param);
int32_t get_status_code_num() const { return status_code_num; }
- // Publish an inspection event for other modules to consume.
- virtual void publish() { }
-
void clear();
bool is_clear() { return cleared; }
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;
+ Status scan(snort::Flow* flow, const uint8_t* data, uint32_t length, uint32_t* flush_offset);
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned, const
uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
bool finish(snort::Flow* flow) override;
#include "http_stream_splitter.h"
#include "packet_io/active.h"
+#include "protocols/packet.h"
#include "http_common.h"
#include "http_cutter.h"
StreamSplitter::Status HttpStreamSplitter::scan(Packet* pkt, const uint8_t* data, uint32_t length,
uint32_t, uint32_t* flush_offset)
{
- Profile profile(HttpModule::get_profile_stats());
+ return scan(pkt->flow, data, length, flush_offset);
+}
- Flow* const flow = pkt->flow;
+StreamSplitter::Status HttpStreamSplitter::scan(Flow* flow, const uint8_t* data, uint32_t length,
+ uint32_t* flush_offset)
+{
+ Profile profile(HttpModule::get_profile_stats());
// This is the session state information we share with HttpInspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
session_data->status_code_num = 200;
HttpModule::increment_peg_counts(PEG_RESPONSE);
prepare_flush(session_data, nullptr, SEC_HEADER, 0, 0, 0, false, 0, 0);
- my_inspector->process((const uint8_t*)"", 0, flow, SRC_SERVER, false);
+ my_inspector->process((const uint8_t*)"", 0, flow, SRC_SERVER, false, nullptr);
session_data->transaction[SRC_SERVER]->clear_section();
}