assert(false);
}
}
+
+#ifdef REG_TEST
+void Http2DataFrame::print_frame(FILE* output)
+{
+ fprintf(output, "Data frame\n");
+ Http2Frame::print_frame(output);
+}
+#endif
friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*,
const int32_t, Http2FlowData*, HttpCommon::SourceId, Http2Stream* stream);
+#ifdef REG_TEST
+ void print_frame(FILE* output) override;
+#endif
+
private:
Http2DataFrame(const uint8_t* header_buffer, const int32_t header_len,
const uint8_t* data_buffer, const int32_t data_len, Http2FlowData* ssn_data,
FlowData(inspector_id),
flow(flow_),
hi((HttpInspect*)(flow->assistant_gadget)),
- hpack_decoder{Http2HpackDecoder(this, SRC_CLIENT), Http2HpackDecoder(this, SRC_SERVER)}
+ hpack_decoder { Http2HpackDecoder(this, SRC_CLIENT, events[SRC_CLIENT],
+ infractions[SRC_CLIENT]),
+ Http2HpackDecoder(this, SRC_SERVER, events[SRC_SERVER],
+ infractions[SRC_SERVER]) }
{
if (hi != nullptr)
{
// 0 element refers to client frame, 1 element refers to server frame
+ // There is currently one infraction and one event object per flow per direction. This may
+ // change in the future.
+ Http2Infractions* const infractions[2] = { new Http2Infractions, new Http2Infractions };
+ Http2EventGen* const events[2] = { new Http2EventGen, new Http2EventGen };
+
// Stream ID of the frame currently being read in and processed
uint32_t current_stream[2] = { Http2Enums::NO_STREAM_ID, Http2Enums::NO_STREAM_ID };
// At any given time there may be different streams going in each direction. But only one of
uint8_t padding_octets_in_frame[2] = { 0, 0 };
bool get_padding_len[2] = { false, false };
- // These will eventually be moved over to the frame/stream object, as they are moved to the
- // transaction in NHI. Also as in NHI accessor methods will need to be added.
- Http2Infractions* infractions[2] = { new Http2Infractions, new Http2Infractions };
- Http2EventGen* events[2] = { new Http2EventGen, new Http2EventGen };
-
#ifdef REG_TEST
static uint64_t instance_count;
uint64_t seq_num;
// Decode headers
if (!hpack_decoder.decode_headers((data.start() + hpack_headers_offset), data.length() -
- hpack_headers_offset, decoded_headers, start_line_generator,
- session_data->events[source_id], session_data->infractions[source_id]))
+ hpack_headers_offset, decoded_headers, start_line_generator))
{
session_data->frame_type[source_id] = FT__ABORT;
error_during_decode = true;
void Http2HeadersFrame::print_frame(FILE* output)
{
if (!trailer)
- fprintf(output, "\nHeaders frame\n");
+ fprintf(output, "Headers frame\n");
else
fprintf(output, "Trailing Headers frame\n");
if (error_during_decode)
if (!entry)
{
- infractions += INF_HPACK_INDEX_OUT_OF_BOUNDS;
+ *infractions += INF_HPACK_INDEX_OUT_OF_BOUNDS;
events->create_event(EVENT_MISFORMATTED_HTTP2);
return false;
}
// table exceeds the Snort hard-coded limit of 512
if (!decode_table.add_index(name, value))
{
- infractions += INF_DYNAMIC_TABLE_OVERFLOW;
+ *infractions += INF_DYNAMIC_TABLE_OVERFLOW;
events->create_event(EVENT_DYNAMIC_TABLE_OVERFLOW);
return false;
}
if (!entry)
{
- infractions += INF_HPACK_INDEX_OUT_OF_BOUNDS;
+ *infractions += INF_HPACK_INDEX_OUT_OF_BOUNDS;
events->create_event(EVENT_MISFORMATTED_HTTP2);
return false;
}
if (entry->value.length() <= 0)
{
- infractions += INF_LOOKUP_EMPTY_VALUE;
+ *infractions += INF_LOOKUP_EMPTY_VALUE;
events->create_event(EVENT_MISFORMATTED_HTTP2);
}
// get_start_line() and get_decoded_headers() to generate and obtain these fields.
bool Http2HpackDecoder::decode_headers(const uint8_t* encoded_headers,
const uint32_t encoded_headers_length, uint8_t* decoded_headers,
- Http2StartLine *start_line_generator, Http2EventGen* stream_events,
- Http2Infractions* stream_infractions)
+ Http2StartLine *start_line_generator)
{
uint32_t total_bytes_consumed = 0;
uint32_t line_bytes_consumed = 0;
bool success = true;
start_line = start_line_generator;
decoded_headers_size = 0;
- events = stream_events;
- infractions = stream_infractions;
pseudo_headers_fragment_size = 0;
decode_error = false;
class Http2HpackDecoder
{
public:
- Http2HpackDecoder(Http2FlowData* flow_data, HttpCommon::SourceId src_id) :
- decode_table(flow_data, src_id) { }
+ Http2HpackDecoder(Http2FlowData* flow_data, HttpCommon::SourceId src_id,
+ Http2EventGen* const _events, Http2Infractions* const _infractions) :
+ events(_events), infractions(_infractions), decode_table(flow_data, src_id) { }
bool decode_headers(const uint8_t* encoded_headers, const uint32_t encoded_headers_length,
- uint8_t* decoded_headers, Http2StartLine* start_line,
- Http2EventGen* stream_events, Http2Infractions* stream_infractions);
+ uint8_t* decoded_headers, Http2StartLine* start_line);
bool write_decoded_headers(const uint8_t* in_buffer, const uint32_t in_length,
uint8_t* decoded_header_buffer, uint32_t decoded_header_length, uint32_t& bytes_written);
bool decode_header_line(const uint8_t* encoded_header_buffer,
uint32_t decoded_headers_size;
uint32_t pseudo_headers_fragment_size;
bool decode_error;
- Http2EventGen* events;
- Http2Infractions* infractions;
+ Http2EventGen* const events;
+ Http2Infractions* const infractions;
static Http2HpackIntDecode decode_int7;
static Http2HpackIntDecode decode_int6;
}
bool Http2HpackIntDecode::translate(const uint8_t* in_buff, const uint32_t in_len,
- uint32_t& bytes_consumed, uint64_t& result, Http2EventGen* events,
- Http2Infractions* infractions) const
+ uint32_t& bytes_consumed, uint64_t& result, Http2EventGen* const events,
+ Http2Infractions* const infractions) const
{
bytes_consumed = 0;
result = 0;
public:
Http2HpackIntDecode(uint8_t prefix);
bool translate(const uint8_t* in_buff, const uint32_t in_len, uint32_t& bytes_consumed,
- uint64_t& result, Http2EventGen* events, Http2Infractions* infractions) const;
+ uint64_t& result, Http2EventGen* const events, Http2Infractions* const infractions) const;
private:
const uint8_t prefix_mask;
bool Http2HpackStringDecode::translate(const uint8_t* in_buff, const uint32_t in_len,
uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
- Http2EventGen* events, Http2Infractions* infractions) const
+ Http2EventGen* const events, Http2Infractions* const infractions) const
{
bytes_consumed = 0;
bytes_written = 0;
bool Http2HpackStringDecode::get_string(const uint8_t* in_buff, const uint32_t encoded_len,
uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
- Http2EventGen* events, Http2Infractions* infractions) const
+ Http2EventGen* const events, Http2Infractions* const infractions) const
{
if (encoded_len > out_len)
{
bool Http2HpackStringDecode::get_huffman_string(const uint8_t* in_buff, const uint32_t encoded_len,
uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
- Http2EventGen* events, Http2Infractions* infractions) const
+ Http2EventGen* const events, Http2Infractions* const infractions) const
{
const uint32_t last_encoded_byte = bytes_consumed + encoded_len;
uint8_t byte;
Http2HpackStringDecode() : decode7(7) { }
bool translate(const uint8_t* in_buff, const uint32_t in_len, uint32_t& bytes_consumed,
uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
- Http2EventGen* events, Http2Infractions* infractions) const;
+ Http2EventGen* const events, Http2Infractions* const infractions) const;
private:
bool get_string(const uint8_t* in_buff, const uint32_t encoded_len, uint32_t& bytes_consumed,
- uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written, Http2EventGen* events,
- Http2Infractions* infractions) const;
+ uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written, Http2EventGen* const
+ events, Http2Infractions* const infractions) const;
bool get_huffman_string(const uint8_t* in_buff, const uint32_t encoded_len,
uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t&
- bytes_written, Http2EventGen* events, Http2Infractions* infractions) const;
+ bytes_written, Http2EventGen* const events, Http2Infractions* const infractions) const;
bool get_next_byte(const uint8_t* in_buff, const uint32_t last_byte,
uint32_t& bytes_consumed, uint8_t& cur_bit, uint8_t match_len, uint8_t& byte,
bool& another_search) const;
using namespace HttpCommon;
using namespace Http2Enums;
+static void print_flow_issues(FILE*, Http2Infractions* const, Http2EventGen* const);
+
Http2Inspect::Http2Inspect(const Http2ParaList* params_) : params(params_)
{
#ifdef REG_TEST
printf("Finished processing section from test %" PRIi64 "\n",
HttpTestManager::get_test_number());
}
+ print_flow_issues(HttpTestManager::get_output_file(), session_data->infractions[source_id],
+ session_data->events[source_id]);
}
#endif
}
stream->clear_frame();
}
+static void print_flow_issues(FILE* output, Http2Infractions* const infractions,
+ Http2EventGen* const events)
+{
+ fprintf(output, "Infractions: %016" PRIx64 ", Events: %016" PRIx64 "\n\n",
+ infractions->get_raw(), events->get_raw());
+}
value_coming = SCHEME;
else
{
- infractions += INF_INVALID_PSEUDO_HEADER;
+ *infractions += INF_INVALID_PSEUDO_HEADER;
events->create_event(EVENT_INVALID_HEADER);
value_coming = HEADER__INVALID;
}
{
if (method.length() <= 0)
{
- infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
+ *infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
events->create_event(EVENT_REQUEST_WITHOUT_REQUIRED_FIELD);
return false;
}
// FIXIT-L May want to be more lenient than RFC on generating start line
if (authority.length() <= 0)
{
- infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
+ *infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
events->create_event(EVENT_REQUEST_WITHOUT_REQUIRED_FIELD);
return false;
}
// Should not have a scheme or path
if ( scheme.length() > 0 or path.length() > 0)
{
- infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
+ *infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
events->create_event(EVENT_INVALID_HEADER);
}
start_line_length = method.length() + authority.length() + http_version_length +
else
{
// FIXIT-L May want to be more lenient than RFC on generating start line
- infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
+ *infractions += INF_PSEUDO_HEADER_URI_FORM_MISMATCH;
events->create_event(EVENT_MISFORMATTED_HTTP2);
return false;
}
bool generate_start_line() override;
friend Http2StartLine* Http2StartLine::new_start_line_generator(HttpCommon::SourceId source_id,
- Http2EventGen* events, Http2Infractions* infractions);
+ Http2EventGen* const events, Http2Infractions* const infractions);
private:
- Http2RequestLine(Http2EventGen* evs, Http2Infractions* infrs) : Http2StartLine(evs, infrs) { }
+ Http2RequestLine(Http2EventGen* const evs, Http2Infractions* const infrs) :
+ Http2StartLine(evs, infrs) { }
Field method;
Field path;
#ifdef REG_TEST
void Http2SettingsFrame::print_frame(FILE* output)
{
- fprintf(output, "Settings frame:");
+ fprintf(output, "\nSettings frame:");
if (bad_frame)
fprintf(output, " Error in settings frame.");
fprintf(output, "\n");
Http2Frame::print_frame(output);
- fprintf(output, "\n");
}
#endif
}
Http2StartLine* Http2StartLine::new_start_line_generator(SourceId source_id,
- Http2EventGen* events, Http2Infractions* infractions)
+ Http2EventGen* const events, Http2Infractions* const infractions)
{
if (source_id == SRC_CLIENT)
return new Http2RequestLine(events, infractions);
{
if (finalized)
{
- infractions += INF_PSEUDO_HEADER_AFTER_REGULAR_HEADER;
+ *infractions += INF_PSEUDO_HEADER_AFTER_REGULAR_HEADER;
events->create_event(EVENT_INVALID_HEADER);
}
}
{
public:
static Http2StartLine* new_start_line_generator(HttpCommon::SourceId source_id,
- Http2EventGen* events, Http2Infractions* infractions);
+ Http2EventGen* const events, Http2Infractions* const infractions);
virtual ~Http2StartLine();
const Field* get_start_line();
virtual void process_pseudo_header_name(const uint8_t* const& name, uint32_t length) = 0;
- virtual void process_pseudo_header_value(const uint8_t* const& value, const uint32_t length) = 0;
+ virtual void process_pseudo_header_value(const uint8_t* const& value, const uint32_t length) =
+ 0;
bool finalize();
bool is_finalized() { return finalized; }
bool is_pseudo_value() { return value_coming != Http2Enums::HEADER__NONE; }
bool is_pseudo_name(const uint8_t* const& name) { return name[0] == ':'; }
protected:
- Http2StartLine(Http2EventGen* events, Http2Infractions* infractions) : events(events),
- infractions(infractions) { }
+ Http2StartLine(Http2EventGen* const events, Http2Infractions* const infractions) :
+ events(events), infractions(infractions) { }
void process_pseudo_header_precheck();
virtual bool generate_start_line() = 0;
- Http2EventGen* events;
- Http2Infractions* infractions;
+ Http2EventGen* const events;
+ Http2Infractions* const infractions;
bool finalized = false;
uint32_t start_line_length = 0;
uint8_t *start_line_buffer = nullptr;
value_coming = STATUS;
else
{
- infractions += INF_INVALID_PSEUDO_HEADER;
+ *infractions += INF_INVALID_PSEUDO_HEADER;
events->create_event(EVENT_INVALID_HEADER);
value_coming = HEADER__INVALID;
}
if (status.length() <= 0)
{
- infractions += INF_RESPONSE_WITHOUT_STATUS;
+ *infractions += INF_RESPONSE_WITHOUT_STATUS;
events->create_event(EVENT_RESPONSE_WITHOUT_STATUS);
return false;
}
bool generate_start_line() override;
friend Http2StartLine* Http2StartLine::new_start_line_generator(HttpCommon::SourceId source_id,
- Http2EventGen* events, Http2Infractions* infractions);
+ Http2EventGen* const events, Http2Infractions* const infractions);
private:
- Http2StatusLine(Http2EventGen* evs, Http2Infractions* infrs) : Http2StartLine(evs, infrs) { }
+ Http2StatusLine(Http2EventGen* const evs, Http2Infractions* const infrs) :
+ Http2StartLine(evs, infrs) { }
Field status;