static const int GZIP_WINDOW_BITS = 31;
static const uint8_t GZIP_HEADER_FLAG_OFFSET = 3;
static const uint8_t GZIP_FLAG_FEXTRA = 0x4;
+static const uint8_t GZIP_RESERVED_FLAGS = 0xE0; // bits 5-7
static const int DEFLATE_WINDOW_BITS = 15;
static const int MAX_FIELD_NAME_LENGTH = 100;
// Plan to support max 8 xff headers
INF_METHOD_NOT_ON_ALLOWED_LIST = 136,
INF_METHOD_ON_DISALLOWED_LIST = 137,
INF_PIPELINE_MAX = 138,
+ INF_GZIP_RESERVED_FLAGS = 139,
INF__MAX_VALUE
};
EVENT_REQ_TOO_LONG = 285,
EVENT_UNEXPECTED_H2_PREFACE = 286,
EVENT_DISALLOWED_METHOD = 287,
+ EVENT_GZIP_RESERVED_FLAGS = 288,
EVENT__MAX_VALUE
};
uint32_t length, HttpEnums::CompressId& compression, z_stream*& compress_stream,
bool at_start, HttpInfractions* infractions, HttpEventGen* events,
HttpFlowData* session_data) const;
- void process_gzip_header(const uint8_t* data,
+ uint8_t* process_gzip_header(const uint8_t* data,
uint32_t length, HttpFlowData* session_data) const;
bool gzip_header_check_done(HttpFlowData* session_data) const;
StreamSplitter::Status handle_zero_nine(snort::Flow*, HttpFlowData*, const uint8_t* data,
}
}
-void HttpStreamSplitter::process_gzip_header(const uint8_t* data,
+uint8_t* HttpStreamSplitter::process_gzip_header(const uint8_t* data,
uint32_t length, HttpFlowData* session_data) const
{
uint32_t& header_bytes_processed = session_data->gzip_header_bytes_processed[source_id];
uint32_t input_bytes_processed = 0;
+ uint8_t* modified_data = nullptr;
if (session_data->gzip_state[source_id] == GZIP_TBD)
{
static const uint8_t gzip_magic[] = {0x1f, 0x8b, 0x08};
*session_data->get_infractions(source_id) += INF_GZIP_FEXTRA;
session_data->events[source_id]->create_event(EVENT_GZIP_FEXTRA);
}
+ if (gzip_flags & GZIP_RESERVED_FLAGS)
+ {
+ *session_data->get_infractions(source_id) += INF_GZIP_RESERVED_FLAGS;
+ session_data->events[source_id]->create_event(EVENT_GZIP_RESERVED_FLAGS);
+ modified_data = new uint8_t[length];
+ memcpy(modified_data, data, length);
+ modified_data[input_bytes_processed] &= ~GZIP_RESERVED_FLAGS;
+ }
header_bytes_processed++;
session_data->gzip_state[source_id] = GZIP_FLAGS_PROCESSED;
}
+ return modified_data;
}
bool HttpStreamSplitter::gzip_header_check_done(HttpFlowData* session_data) const
{
if ((compression == CMP_GZIP) || (compression == CMP_DEFLATE))
{
+ uint8_t* data_w_updated_hdr = nullptr;
if (compression == CMP_GZIP and !gzip_header_check_done(session_data))
- process_gzip_header(data, length, session_data);
+ data_w_updated_hdr = process_gzip_header(data, length, session_data);
- compress_stream->next_in = const_cast<Bytef*>(data);
+ if (data_w_updated_hdr != nullptr)
+ compress_stream->next_in = const_cast<Bytef*>(data_w_updated_hdr);
+ else
+ compress_stream->next_in = const_cast<Bytef*>(data);
compress_stream->avail_in = length;
compress_stream->next_out = buffer + offset;
compress_stream->avail_out = MAX_OCTETS - offset;
int ret_val = inflate(compress_stream, Z_SYNC_FLUSH);
+ delete[] data_w_updated_hdr;
+
if ((ret_val == Z_OK) || (ret_val == Z_STREAM_END))
{
offset = MAX_OCTETS - compress_stream->avail_out;