From a0e76f2259ea55a6e498a769a041288cecc907e3 Mon Sep 17 00:00:00 2001 From: "Russ Combs (rucombs)" Date: Tue, 2 Feb 2016 14:45:40 -0500 Subject: [PATCH] Merge pull request #229 in SNORT/snort3 from nhttp35 to master Squashed commit of the following: commit 1238765057b0a5b1208c64e1d7c5cf7200a53b4d Author: Tom Peters Date: Wed Jan 27 15:44:16 2016 -0500 URI normalization of headers, cookies, and post bodies --- .../nhttp_inspect/ips_nhttp.cc | 2 +- .../nhttp_inspect/nhttp_event_gen.h | 3 +- .../nhttp_inspect/nhttp_field.cc | 7 ++ .../nhttp_inspect/nhttp_field.h | 5 ++ .../nhttp_inspect/nhttp_inspect.cc | 10 +-- .../nhttp_inspect/nhttp_inspect.h | 2 +- .../nhttp_inspect/nhttp_msg_body.cc | 11 +++ .../nhttp_inspect/nhttp_msg_body.h | 15 +++- .../nhttp_inspect/nhttp_msg_head_shared.cc | 74 ++++++++++++++++++- .../nhttp_inspect/nhttp_msg_head_shared.h | 33 ++++++--- .../nhttp_inspect/nhttp_msg_section.cc | 33 ++++++--- .../nhttp_inspect/nhttp_msg_section.h | 3 +- .../nhttp_inspect/nhttp_uri.cc | 1 - .../nhttp_inspect/nhttp_uri_norm.cc | 41 ++++++++++ .../nhttp_inspect/nhttp_uri_norm.h | 8 +- 15 files changed, 207 insertions(+), 41 deletions(-) diff --git a/src/service_inspectors/nhttp_inspect/ips_nhttp.cc b/src/service_inspectors/nhttp_inspect/ips_nhttp.cc index d15d7e1e4..e80498708 100644 --- a/src/service_inspectors/nhttp_inspect/ips_nhttp.cc +++ b/src/service_inspectors/nhttp_inspect/ips_nhttp.cc @@ -190,7 +190,7 @@ int NHttpIpsOption::eval(Cursor& c, Packet* p) InspectionBuffer hb; if (! ((NHttpInspect*)(p->flow->gadget))-> - get_buf((unsigned)buffer_index, sub_id, form, nullptr, hb)) + nhttp_get_buf((unsigned)buffer_index, sub_id, form, nullptr, hb)) return DETECTION_OPTION_NO_MATCH; c.set(key, hb.data, hb.len); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h b/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h index 03364c505..6f957107f 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h @@ -34,8 +34,9 @@ class NHttpEventGen { public: + virtual ~NHttpEventGen() = default; void reset() { events_generated = 0; } - void create_event(NHttpEnums::EventSid sid) + virtual void create_event(NHttpEnums::EventSid sid) { assert(((int)sid > 0) && ((int)sid <= MAX)); if (!events_generated[sid-1]) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_field.cc b/src/service_inspectors/nhttp_inspect/nhttp_field.cc index b71850cb8..e00ad0fb9 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_field.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_field.cc @@ -49,6 +49,13 @@ void Field::set(StatusCode stat_code) length = stat_code; } +void Field::set(const Field& f) +{ + assert(length == STAT_NOT_COMPUTE); + assert(start == nullptr); + start = f.start; + length = f.length; +} #ifdef REG_TEST void Field::print(FILE* output, const char* name) const diff --git a/src/service_inspectors/nhttp_inspect/nhttp_field.h b/src/service_inspectors/nhttp_inspect/nhttp_field.h index 9342c8971..b98baed65 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_field.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_field.h @@ -41,8 +41,13 @@ public: explicit Field(int32_t length_) : length(length_) { assert(length<=0); } Field() = default; void set(int32_t length_, const uint8_t* start_); + void set(const Field& f); void set(NHttpEnums::StatusCode stat_code); void set(int32_t length) { set(static_cast(length)); } + // Only call this method if the field owns the dynamically allocated buffer you are deleting. + // This method is a convenience but you still must know where the buffer came from. Many fields + // refer to static buffers or a subfield of someone else's buffer. + void delete_buffer() { if (length >= 0) delete[] start; }; #ifdef REG_TEST void print(FILE* output, const char* name) const; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc index c1e4a8cbb..d20cee2a2 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc @@ -69,20 +69,20 @@ bool NHttpInspect::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer switch (ibt) { case InspectionBuffer::IBT_KEY: - return get_buf(NHTTP_BUFFER_URI, 0, 0, nullptr, b); + return nhttp_get_buf(NHTTP_BUFFER_URI, 0, 0, nullptr, b); case InspectionBuffer::IBT_HEADER: if (get_latest_is() == IS_TRAILER) - return get_buf(NHTTP_BUFFER_TRAILER, 0, 0, nullptr, b); + return nhttp_get_buf(NHTTP_BUFFER_TRAILER, 0, 0, nullptr, b); else - return get_buf(NHTTP_BUFFER_HEADER, 0, 0, nullptr, b); + return nhttp_get_buf(NHTTP_BUFFER_HEADER, 0, 0, nullptr, b); case InspectionBuffer::IBT_BODY: - return get_buf(NHTTP_BUFFER_CLIENT_BODY, 0, 0, nullptr, b); + return nhttp_get_buf(NHTTP_BUFFER_CLIENT_BODY, 0, 0, nullptr, b); default: return false; } } -SO_PUBLIC bool NHttpInspect::get_buf(unsigned id, uint64_t sub_id, uint64_t form, Packet*, +SO_PUBLIC bool NHttpInspect::nhttp_get_buf(unsigned id, uint64_t sub_id, uint64_t form, Packet*, InspectionBuffer& b) { if (latest_section == nullptr) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h index 48c001a4d..ec0039531 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h @@ -42,7 +42,7 @@ public: NHttpInspect(NHttpParaList params_); bool get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b) override; - bool get_buf(unsigned id, uint64_t sub_id, uint64_t form, Packet*, InspectionBuffer& b); + bool nhttp_get_buf(unsigned id, uint64_t sub_id, uint64_t form, Packet*, InspectionBuffer& b); bool get_fp_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b) override; bool configure(SnortConfig*) override { return true; } void show(SnortConfig*) override { LogMessage("NHttpInspect\n"); } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc index cabe241f5..1a6555db9 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc @@ -43,6 +43,12 @@ NHttpMsgBody::NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size, transaction->set_body(this); } +NHttpMsgBody::~NHttpMsgBody() +{ + if (classic_client_body_alloc) + classic_client_body.delete_buffer(); +} + void NHttpMsgBody::analyze() { detect_data.length = (msg_text.length <= session_data->detect_depth_remaining[source_id]) ? @@ -129,6 +135,11 @@ void NHttpMsgBody::do_file_processing() } } +const Field& NHttpMsgBody::get_classic_client_body() +{ + return classic_normalize(detect_data, classic_client_body, classic_client_body_alloc); +} + #ifdef REG_TEST // Common elements of print_section() for body sections void NHttpMsgBody::print_body_section(FILE* output) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h index 2470ebbad..9da03277a 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h @@ -30,25 +30,32 @@ class NHttpMsgBody : public NHttpMsgSection { public: + virtual ~NHttpMsgBody(); void analyze() override; const Field& get_detect_buf() const override { return detect_data; } NHttpEnums::InspectSection get_inspection_section() const override { return detection_section ? NHttpEnums::IS_DETECTION : NHttpEnums::IS_BODY; } + const Field& get_classic_client_body(); protected: NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_, NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_, const NHttpParaList* params_); - void do_file_processing(); int64_t body_octets; - Field detect_data; - Field file_data; - const bool detection_section; #ifdef REG_TEST void print_body_section(FILE* output); #endif + +private: + void do_file_processing(); + + Field detect_data; + Field file_data; + const bool detection_section; + Field classic_client_body; // URI normalization applied + bool classic_client_body_alloc = false; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc index ccce1123b..65d5a2ef1 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc @@ -23,6 +23,7 @@ #include "nhttp_enum.h" #include "nhttp_normalizers.h" +#include "nhttp_uri_norm.h" #include "nhttp_msg_head_shared.h" using namespace NHttpEnums; @@ -38,10 +39,14 @@ NHttpMsgHeadShared::~NHttpMsgHeadShared() { NormalizedHeader* temp_ptr = list_ptr; list_ptr = list_ptr->next; - if (temp_ptr->norm.length >= 0) - delete[] temp_ptr->norm.start; - delete temp_ptr; + temp_ptr->norm.delete_buffer(); } + if (classic_raw_header_alloc) + classic_raw_header.delete_buffer(); + if (classic_norm_header_alloc) + classic_norm_header.delete_buffer(); + if (classic_norm_cookie_alloc) + classic_norm_cookie.delete_buffer(); } // All the header processing that is done for every message (i.e. not just-in-time) is done here. @@ -230,6 +235,69 @@ int NHttpMsgHeadShared::get_header_count(HeaderId header_id) const return (node != nullptr) ? node->count : 0; } +const Field& NHttpMsgHeadShared::get_classic_raw_header() +{ + if (classic_raw_header.length != STAT_NOT_COMPUTE) + return classic_raw_header; + const HeaderId cookie_head = (source_id == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; + if (!headers_present[cookie_head]) + { + // There are no cookies so the classic headers are the whole thing + classic_raw_header.set(msg_text); + return classic_raw_header; + } + + // Figure out how much space to allocate by stepping through the headers in advance + int32_t length = 0; + for (int k = 0; k < num_headers; k++) + { + if (header_name_id[k] == cookie_head) + continue; + // All header line Fields point into the buffer holding the entire message section. + // Calculation must account for separators between header lines, but there are none + // following the final header line. + const int32_t head_len = (k == num_headers-1) ? header_line[k].length : + header_line[k+1].start - header_line[k].start; + length += head_len; + } + + // Step through headers again and do the copying this time + uint8_t* const buffer = new uint8_t[length]; + int32_t current = 0; + for (int k = 0; k < num_headers; k++) + { + if (header_name_id[k] == cookie_head) + continue; + const int32_t head_len = (k == num_headers-1) ? header_line[k].length : + header_line[k+1].start - header_line[k].start; + memcpy(buffer + current, header_line[k].start, head_len); + current += head_len; + } + assert(current == length); + + classic_raw_header.set(length, buffer); + classic_raw_header_alloc = true; + return classic_raw_header; +} + +const Field& NHttpMsgHeadShared::get_classic_norm_header() +{ + return classic_normalize(get_classic_raw_header(), classic_norm_header, + classic_norm_header_alloc); +} + +const Field& NHttpMsgHeadShared::get_classic_raw_cookie() +{ + HeaderId cookie_head = (source_id == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; + return get_header_value_norm(cookie_head); +} + +const Field& NHttpMsgHeadShared::get_classic_norm_cookie() +{ + return classic_normalize(get_classic_raw_cookie(), classic_norm_cookie, + classic_norm_cookie_alloc); +} + const Field& NHttpMsgHeadShared::get_header_value_norm(HeaderId header_id) { NormalizedHeader* node = get_header_node(header_id); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h index da809d463..757a8e0f4 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h @@ -37,7 +37,10 @@ public: void analyze() override; int32_t get_num_headers() const { return num_headers; } - const Field& get_headers() const { return msg_text; } + const Field& get_classic_raw_header(); + const Field& get_classic_raw_cookie(); + const Field& get_classic_norm_header(); + const Field& get_classic_norm_cookie(); const Field& get_header_line(int k) const { return header_line[k]; } const Field& get_header_name(int k) const { return header_name[k]; } const Field& get_header_value(int k) const { return header_value[k]; } @@ -58,6 +61,13 @@ protected: { } ~NHttpMsgHeadShared(); +#ifdef REG_TEST + void print_headers(FILE* output); +#endif + +private: + static const int MAX = NHttpEnums::HEAD__MAX_VALUE; + // Header normalization strategies. There should be one defined for every different way we can // process a header field value. static const HeaderNormalizer NORMALIZER_BASIC; @@ -69,28 +79,29 @@ protected: // Master table of known header fields and their normalization strategies. static const HeaderNormalizer* const header_norms[]; + // All of these are indexed by the relative position of the header field in the message + static const int MAX_HEADERS = 200; // I'm an arbitrary number. FIXIT-L + static const int MAX_HEADER_LENGTH = 4096; // Based on max cookie size of some browsers + void parse_header_block(); uint32_t find_header_end(const uint8_t* buffer, int32_t length, int& num_seps); void parse_header_lines(); void create_norm_head_list(); void derive_header_name_id(int index); - // All of these are indexed by the relative position of the header field in the message - static const int MAX_HEADERS = 200; // I'm an arbitrary number. FIXIT-L - static const int MAX_HEADER_LENGTH = 4096; // Based on max cookie size of some browsers + std::bitset headers_present = 0; int32_t num_headers = NHttpEnums::STAT_NOT_COMPUTE; Field* header_line = nullptr; Field* header_name = nullptr; NHttpEnums::HeaderId* header_name_id = nullptr; Field* header_value = nullptr; -#ifdef REG_TEST - void print_headers(FILE* output); -#endif - -private: - static const int MAX = NHttpEnums::HEAD__MAX_VALUE; - std::bitset headers_present = 0; + Field classic_raw_header; // raw headers with cookies spliced out + bool classic_raw_header_alloc = false; + Field classic_norm_header; // URI normalization applied + bool classic_norm_header_alloc = false; + Field classic_norm_cookie; // URI normalization applied to concatenated cookie values + bool classic_norm_cookie_alloc = false; struct NormalizedHeader { diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc index 0215018ac..505c48c3e 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc @@ -78,9 +78,25 @@ void NHttpMsgSection::update_depth() const } } +const Field& NHttpMsgSection::classic_normalize(const Field& raw, Field& norm, bool& norm_alloc) +{ + if (norm.length != STAT_NOT_COMPUTE) + return norm; + + if ((raw.length <= 0) || !UriNormalizer::need_norm_path(raw)) + { + norm.set(raw); + return norm; + } + uint8_t* buffer = new uint8_t[raw.length + UriNormalizer::URI_NORM_EXPANSION]; + UriNormalizer::classic_normalize(raw, norm, buffer); + norm_alloc = true; + return norm; +} + const Field& NHttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, uint64_t form) { - // Only use with buffers that support the request option + // buffer_side replaces source_id for buffers that support the request option const SourceId buffer_side = (form & FORM_REQUEST) ? SRC_CLIENT : source_id; switch (id) @@ -90,19 +106,16 @@ const Field& NHttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, u if (source_id != SRC_CLIENT) return Field::FIELD_NULL; NHttpMsgBody* body = transaction->get_body(); - return (body != nullptr) ? body->get_detect_buf() : Field::FIELD_NULL; + return (body != nullptr) ? body->get_classic_client_body() : Field::FIELD_NULL; } case NHTTP_BUFFER_COOKIE: case NHTTP_BUFFER_RAW_COOKIE: - // FIXIT-M when real cookie normalization is implemented these need to become separate cases. - // Currently "normalization" is aggregation of multiple cookies. That is correct for raw - // cookies and all there is for normalized cookies. { NHttpMsgHeader* header = transaction->get_header(buffer_side); if (header == nullptr) return Field::FIELD_NULL; - HeaderId cookie_head = (buffer_side == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; - return header->get_header_value_norm(cookie_head); + return (id == NHTTP_BUFFER_COOKIE) ? header->get_classic_norm_cookie() : + header->get_classic_raw_cookie(); } case NHTTP_BUFFER_HEADER: case NHTTP_BUFFER_TRAILER: @@ -114,7 +127,7 @@ const Field& NHttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, u if (header == nullptr) return Field::FIELD_NULL; if (sub_id == 0) - return header->get_headers(); + return header->get_classic_norm_header(); return header->get_header_value_norm((HeaderId)sub_id); } case NHTTP_BUFFER_METHOD: @@ -125,7 +138,7 @@ const Field& NHttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, u case NHTTP_BUFFER_RAW_HEADER: { NHttpMsgHeader* header = transaction->get_header(buffer_side); - return (header != nullptr) ? header->get_headers() : Field::FIELD_NULL; + return (header != nullptr) ? header->get_classic_raw_header() : Field::FIELD_NULL; } case NHTTP_BUFFER_STAT_CODE: { @@ -186,7 +199,7 @@ const Field& NHttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, u case NHTTP_BUFFER_RAW_TRAILER: { NHttpMsgTrailer* trailer = transaction->get_trailer(buffer_side); - return (trailer != nullptr) ? trailer->get_headers() : Field::FIELD_NULL; + return (trailer != nullptr) ? trailer->get_classic_raw_header() : Field::FIELD_NULL; } default: assert(false); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h index 623f1e8a0..4189264fe 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h @@ -79,8 +79,9 @@ protected: NHttpEnums::MethodId method_id; int32_t status_code_num; - // Convenience methods + // Convenience methods shared by multiple subclasses void update_depth() const; + static const Field& classic_normalize(const Field& raw, Field& norm, bool& norm_alloc); #ifdef REG_TEST void print_message_title(FILE* output, const char* title) const; void print_message_wrapup(FILE* output); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc index e398cb3cc..c080c1fa6 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc @@ -23,7 +23,6 @@ #include #include "nhttp_enum.h" -#include "nhttp_normalizers.h" #include "nhttp_uri.h" using namespace NHttpEnums; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc index 9f9050d54..6fd54ba59 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc @@ -171,6 +171,10 @@ void UriNormalizer::norm_backslash(uint8_t* buf, int32_t length, NHttpInfraction int32_t UriNormalizer::norm_path_clean(uint8_t* buf, const int32_t in_length, NHttpInfractions& infractions, NHttpEventGen& events) { + // This is supposed to be the path portion of a URI. Read NHttpUri::parse_uri() for an + // explanation. + assert(buf[0] == '/'); + int32_t length = 0; // It simplifies the code that handles /./ and /../ to pretend there is an extra '/' after the // buffer. Avoids making a special case of URIs that end in . or .. That is why the loop steps @@ -231,3 +235,40 @@ int32_t UriNormalizer::norm_path_clean(uint8_t* buf, const int32_t in_length, return length; } +// Provide traditional URI-style normalization for buffers that usually are not URIs +void UriNormalizer::classic_normalize(const Field& input, Field& result, uint8_t* buffer) +{ + // The requirements for generating events related to these normalizations are unclear. It + // definitely doesn't seem right to generate standard URI events. For now we won't generate + // any events at all because these buffers may well not be URIs so regardless of what we find + // it is "normal". Similarly we don't have any reason to track any infractions. + + // We want to reuse all the URI-normalization functions without complicating their event and + // infraction logic with legacy problems. The following centralizes all the messiness here so + // that we can conveniently modify it as requirements are better understood. + + class NHttpDummyEventGen : public NHttpEventGen + { + void create_event(NHttpEnums::EventSid) override {} + }; + + NHttpInfractions unused; + NHttpDummyEventGen dummy_ev; + + // Normalize character escape sequences + int32_t data_length = norm_char_clean(input.start, input.length, buffer, unused, dummy_ev); + + // Normalize path directory traversals + // Find the leading slash if there is one + int32_t uri_offset; + for (uri_offset = 0; (uri_offset < data_length) && (buffer[uri_offset] != '/'); uri_offset++); + if (uri_offset < data_length) + { + norm_backslash(buffer + uri_offset, data_length - uri_offset, unused, dummy_ev); + data_length = uri_offset + + norm_path_clean(buffer + uri_offset, data_length - uri_offset, unused, dummy_ev); + } + + result.set(data_length, buffer); +} + diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.h b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.h index 1136d03b4..2d2ba8728 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.h @@ -23,22 +23,24 @@ #include "nhttp_field.h" #include "nhttp_infractions.h" #include "nhttp_event_gen.h" -#include "nhttp_normalizers.h" class UriNormalizer { public: + static const unsigned URI_NORM_EXPANSION = 1; + static void normalize(const Field& input, Field& result, bool do_path, uint8_t* buffer, NHttpInfractions& infractions, NHttpEventGen& events); static bool need_norm_path(const Field& uri_component); static bool need_norm_no_path(const Field& uri_component); - static const unsigned URI_NORM_EXPANSION = 1; + static void classic_normalize(const Field& input, Field& result, uint8_t* buffer); private: static const NHttpEnums::CharAction uri_char[256]; static const bool good_percent[256]; - static NormFunc norm_char_clean; + static int32_t norm_char_clean(const uint8_t* in_buf, int32_t in_length, uint8_t* out_buf, + NHttpInfractions& infractions, NHttpEventGen& events); static void norm_backslash(uint8_t* buf, int32_t length, NHttpInfractions& infractions, NHttpEventGen& events); static int32_t norm_path_clean(uint8_t* buf, const int32_t in_length, -- 2.47.3