]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #307 in SNORT/snort3 from nhttp38 to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 1 Mar 2016 22:55:43 +0000 (17:55 -0500)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 1 Mar 2016 22:55:43 +0000 (17:55 -0500)
Squashed commit of the following:

commit 18c6399ec8cbeaf354b4a07515fe437adc730626
Author: Tom Peters <thopeter@cisco.com>
Date:   Tue Mar 1 17:21:19 2016 -0500

    code review comment

commit 6c41887b194bf5d53b125f81b32c324ecab4029e
Author: Tom Peters <thopeter@cisco.com>
Date:   Tue Mar 1 15:41:55 2016 -0500

    code review change

commit 03859f8b3a1d1be2fda77acdd78195f9b5e51f47
Author: Tom Peters <thopeter@cisco.com>
Date:   Mon Feb 15 11:36:52 2016 -0500

    NHI basic URI normalization with configuration options

16 files changed:
.gitignore
src/service_inspectors/nhttp_inspect/CMakeLists.txt
src/service_inspectors/nhttp_inspect/Makefile.am
src/service_inspectors/nhttp_inspect/nhttp_enum.h
src/service_inspectors/nhttp_inspect/nhttp_module.cc
src/service_inspectors/nhttp_inspect/nhttp_module.h
src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_section.h
src/service_inspectors/nhttp_inspect/nhttp_uri.cc
src/service_inspectors/nhttp_inspect/nhttp_uri.h
src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc
src/service_inspectors/nhttp_inspect/nhttp_uri_norm.h
src/service_inspectors/nhttp_inspect/nhttp_uri_tables.cc [deleted file]

index 57ef5424d7d7c7c19fea9114ab53dcfe5f785f1b..8ee77c5336225ecf439934dad470aaca37667584 100644 (file)
@@ -59,6 +59,7 @@ doc/snort_manual.text
 doc/snort_manual.tgz
 doc/snort_manual.xml
 doc/version.txt
+extra/m4/*.m4
 extra/rule.xxd
 extra/snort_examples-1.0.tar.gz
 install-sh
index 71484325d2f509fe1d77461cbca270467a2a8727..afa2f9724e9600f3bf33a3f0f27df844d2ab6e65 100644 (file)
@@ -36,7 +36,6 @@ set (FILE_LIST
     nhttp_str_to_code.h
     nhttp_api.cc nhttp_api.h
     nhttp_tables.cc
-    nhttp_uri_tables.cc
     nhttp_module.cc
     nhttp_module.h
     nhttp_test_input.cc
index 7f1b39b44f386edf0e7976b4ae22c37081b743ad..0d25febbb10b94ddedc7092fbb14d5266155ddee 100644 (file)
@@ -19,7 +19,6 @@ nhttp_normalizers.cc nhttp_normalizers.h \
 nhttp_str_to_code.cc nhttp_str_to_code.h \
 nhttp_api.cc nhttp_api.h \
 nhttp_tables.cc \
-nhttp_uri_tables.cc \
 nhttp_module.cc nhttp_module.h \
 nhttp_test_input.cc nhttp_test_input.h \
 nhttp_flow_data.cc nhttp_flow_data.h \
index fe4d4bbc5bee20d347b8786f41fed4cddf0325ba..740c74cae008a65555b541cffe5b17074536e471 100644 (file)
@@ -130,8 +130,8 @@ enum Infraction
     INF_BAD_URI,
     INF_ZERO_NINE_REQ,
     INF_ZERO_NINE_CONTINUE,
-    INF_URI_PERCENT_NORMAL,
-    INF_URI_PERCENT_ASCII,
+    INF_NOT_USED_2,
+    INF_URI_PERCENT_UNRESERVED,
     INF_URI_PERCENT_UTF8,
     INF_URI_PERCENT_UCODE,
     INF_URI_PERCENT_OTHER,
@@ -177,7 +177,7 @@ enum Infraction
 };
 
 // Types of character for URI scanning
-enum CharAction { CHAR_NORMAL=2, CHAR_PERCENT, CHAR_PATH, CHAR_INVALID, CHAR_EIGHTBIT };
+enum CharAction { CHAR_NORMAL=2, CHAR_PERCENT, CHAR_PATH, CHAR_EIGHTBIT, CHAR_SUBSTIT };
 
 // Transfer codings
 enum Transcoding { TRANSCODE__OTHER=1, TRANSCODE_CHUNKED, TRANSCODE_GZIP, TRANSCODE_DEFLATE,
index a23946ed64ab76f23ef5d44fca0ab02749aae9a0..70a906e5646474f23abc3d05e485c684d2a761cb 100644 (file)
 #include <string.h>
 #include <sys/types.h>
 
+#include "nhttp_uri_norm.h"
 #include "nhttp_module.h"
 
+using namespace NHttpEnums;
+
 const Parameter NHttpModule::nhttp_params[] =
 {
     { "request_depth", Parameter::PT_INT, "-1:", "-1",
@@ -29,6 +32,17 @@ const Parameter NHttpModule::nhttp_params[] =
     { "response_depth", Parameter::PT_INT, "-1:", "-1",
           "maximum response message body bytes to examine (-1 no limit)" },
     { "unzip", Parameter::PT_BOOL, nullptr, "true", "decompress gzip and deflate message bodies" },
+    { "bad_characters", Parameter::PT_BIT_LIST, "255", nullptr,
+          "alert when any of specified bytes are present in URI after percent decoding" },
+    { "ignore_unreserved", Parameter::PT_STRING, "(optional)", nullptr,
+          "do not alert when the specified unreserved characters are percent-encoded in a URI."
+          "Unreserved characters are 0-9, a-z, A-Z, period, underscore, tilde, and minus." },
+    { "backslash_to_slash", Parameter::PT_BOOL, nullptr, "false",
+          "replace \\ with / when normalizing URIs" },
+    { "plus_to_space", Parameter::PT_BOOL, nullptr, "true",
+          "replace + with <sp> when normalizing URIs" },
+    { "simplify_path", Parameter::PT_BOOL, nullptr, "true",
+          "reduce URI directory path to simplest form" },
 #ifdef REG_TEST
     { "test_input", Parameter::PT_BOOL, nullptr, "false", "read HTTP messages from text file" },
     { "test_output", Parameter::PT_BOOL, nullptr, "false", "print out HTTP section data" },
@@ -57,6 +71,34 @@ bool NHttpModule::set(const char*, Value& val, SnortConfig*)
     {
         params.unzip = val.get_bool();
     }
+    else if (val.is("bad_characters"))
+    {
+        val.get_bits(params.uri_param.bad_characters);
+    }
+    else if (val.is("ignore_unreserved"))
+    {
+        const char* ignore = val.get_string();
+        while (*ignore != '\0')
+        {
+            params.uri_param.unreserved_char[*(ignore++)] = false;
+        }
+    }
+    else if (val.is("backslash_to_slash"))
+    {
+        params.uri_param.backslash_to_slash = val.get_bool();
+        params.uri_param.uri_char['\\'] = val.get_bool() ? CHAR_SUBSTIT : CHAR_NORMAL;
+    }
+    else if (val.is("plus_to_space"))
+    {
+        params.uri_param.plus_to_space = val.get_bool();
+        params.uri_param.uri_char['+'] = val.get_bool() ? CHAR_SUBSTIT : CHAR_NORMAL;
+    }
+    else if (val.is("simplify_path"))
+    {
+        params.uri_param.simplify_path = val.get_bool();
+        params.uri_param.uri_char['/'] = val.get_bool() ? CHAR_PATH : CHAR_NORMAL;
+        params.uri_param.uri_char['.'] = val.get_bool() ? CHAR_PATH : CHAR_NORMAL;
+    }
 #ifdef REG_TEST
     else if (val.is("test_input"))
     {
@@ -78,3 +120,62 @@ bool NHttpModule::set(const char*, Value& val, SnortConfig*)
     return true;
 }
 
+// Some values in these tables may be changed by configuration parameters.
+NHttpParaList::UriParam::UriParam() :
+  // Characters that should not be percent-encoded
+  // 0-9, a-z, A-Z, tilde, period, underscore, and minus
+  // Initializer string for std::bitset is in reverse order. The first character is element 255
+  // and the last is element 0.
+  unreserved_char { std::string(
+      "00000000" "00000000" "00000000" "00000000"
+      "00000000" "00000000" "00000000" "00000000"
+      "00000000" "00000000" "00000000" "00000000"
+      "00000000" "00000000" "00000000" "00000000"
+      "01000111" "11111111" "11111111" "11111110"
+      "10000111" "11111111" "11111111" "11111110"
+      "00000011" "11111111" "01100000" "00000000"
+      "00000000" "00000000" "00000000" "00000000" ) },
+
+  uri_char {
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PERCENT,   CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_SUBSTIT,   CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PATH,      CHAR_PATH,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PATH,      CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
+
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
+    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT
+  }
+{}
+
index 4ef87d22c98edc95e116c8aab8af3c17215594b6..d4c3fd10ae5660e9ed0d4c08756c240feaccb78e 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef NHTTP_MODULE_H
 #define NHTTP_MODULE_H
 
+#include <string>
+#include <bitset>
+
 #include "framework/module.h"
 
 #include "nhttp_enum.h"
@@ -33,6 +36,19 @@ public:
     long request_depth;
     long response_depth;
     bool unzip;
+    struct UriParam
+    {
+    public:
+        UriParam();
+
+        bool backslash_to_slash;
+        bool plus_to_space;
+        bool simplify_path;
+        std::bitset<256> bad_characters;
+        std::bitset<256> unreserved_char;
+        NHttpEnums::CharAction uri_char[256];
+    };
+    UriParam uri_param;
 #ifdef REG_TEST
     bool test_input;
     bool test_output;
index b353e60983b86593c7f48ece75b02b62f1534c98..6e212e22004bbe4974f3710714f32d23ee598387 100644 (file)
@@ -137,7 +137,8 @@ void NHttpMsgBody::do_file_processing()
 
 const Field& NHttpMsgBody::get_classic_client_body()
 {
-    return classic_normalize(detect_data, classic_client_body, classic_client_body_alloc);
+    return classic_normalize(detect_data, classic_client_body, classic_client_body_alloc,
+        params->uri_param);
 }
 
 #ifdef REG_TEST
index 65d5a2ef1407e71f812bbe59db3678f523dbdabb..dd162d9526f72585f3f8751cccf8c03143c51a87 100644 (file)
@@ -283,7 +283,7 @@ const Field& NHttpMsgHeadShared::get_classic_raw_header()
 const Field& NHttpMsgHeadShared::get_classic_norm_header()
 {
     return classic_normalize(get_classic_raw_header(), classic_norm_header,
-        classic_norm_header_alloc);
+        classic_norm_header_alloc, params->uri_param);
 }
 
 const Field& NHttpMsgHeadShared::get_classic_raw_cookie()
@@ -295,7 +295,7 @@ const Field& NHttpMsgHeadShared::get_classic_raw_cookie()
 const Field& NHttpMsgHeadShared::get_classic_norm_cookie()
 {
     return classic_normalize(get_classic_raw_cookie(), classic_norm_cookie,
-        classic_norm_cookie_alloc);
+        classic_norm_cookie_alloc, params->uri_param);
 }
 
 const Field& NHttpMsgHeadShared::get_header_value_norm(HeaderId header_id)
index e8447e8cfeed873590d58b5edbefc293dc354a50..74009df65ba79cfbb87a756805c9688383b9a84b 100644 (file)
@@ -83,7 +83,7 @@ void NHttpMsgRequest::parse_start_line()
     if (first_end < last_begin)
     {
         uri = new NHttpUri(start_line.start + first_end + 1, last_begin - first_end - 1,
-            method_id, infractions, events);
+            method_id, params->uri_param, infractions, events);
     }
     else
     {
@@ -115,7 +115,7 @@ bool NHttpMsgRequest::handle_zero_nine()
             int32_t uri_end;
             for (uri_end = start_line.length - 1; is_sp_tab[start_line.start[uri_end]]; uri_end--);
             uri = new NHttpUri(start_line.start + uri_begin, uri_end - uri_begin + 1, method_id,
-                infractions, events);
+                params->uri_param, infractions, events);
         }
         else
         {
index 700ee02326480f46fb7011e374f70947d8ef5758..d87ecb437c04bf0e8d9b426aea6e0d1d4d1cfddd 100644 (file)
@@ -79,18 +79,19 @@ void NHttpMsgSection::update_depth() const
     }
 }
 
-const Field& NHttpMsgSection::classic_normalize(const Field& raw, Field& norm, bool& norm_alloc)
+const Field& NHttpMsgSection::classic_normalize(const Field& raw, Field& norm, bool& norm_alloc,
+    const NHttpParaList::UriParam& uri_param)
 {
     if (norm.length != STAT_NOT_COMPUTE)
         return norm;
 
-    if ((raw.length <= 0) || !UriNormalizer::need_norm_path(raw))
+    if ((raw.length <= 0) || !UriNormalizer::classic_need_norm(raw, true, uri_param))
     {
         norm.set(raw);
         return norm;
     }
     uint8_t* buffer = new uint8_t[raw.length + UriNormalizer::URI_NORM_EXPANSION];
-    UriNormalizer::classic_normalize(raw, norm, buffer);
+    UriNormalizer::classic_normalize(raw, norm, buffer, uri_param);
     norm_alloc = true;
     return norm;
 }
index d64a14101b394acb76389d005bb9d704c79442f0..d005336ec66f9d19e2dbcc884e14b91746adfb71 100644 (file)
@@ -82,7 +82,8 @@ protected:
 
     // Convenience methods shared by multiple subclasses
     void update_depth() const;
-    static const Field& classic_normalize(const Field& raw, Field& norm, bool& norm_alloc);
+    static const Field& classic_normalize(const Field& raw, Field& norm, bool& norm_alloc,
+        const NHttpParaList::UriParam& uri_param);
 #ifdef REG_TEST
     void print_section_title(FILE* output, const char* title) const;
     void print_section_wrapup(FILE* output) const;
index c080c1fa6b07645d20fe411a892c4b11f0485a8b..fe579f57197df5801dedfa198a8b52dd27c4c579 100644 (file)
@@ -155,9 +155,6 @@ void NHttpUri::parse_abs_path()
 
 void NHttpUri::normalize()
 {
-    // FIXIT-P generating the normalized URI components directly into the normalized classic buffer
-    // would save a lot of memory and some copying.
-
     // Divide the URI up into its six components: scheme, host, port, path, query, and fragment
     parse_uri();
     parse_authority();
@@ -166,13 +163,15 @@ void NHttpUri::normalize()
     // Almost all HTTP requests are honest and rarely need expensive normalization processing. We
     // do a quick scan for red flags and only perform normalization if something comes up.
     // Otherwise we set the normalized fields to point at the raw values.
-    if ((host.length > 0) && UriNormalizer::need_norm_no_path(host))
+    if ((host.length > 0) && UriNormalizer::need_norm(host, false, uri_param, infractions, events))
         infractions += INF_URI_NEED_NORM_HOST;
-    if ((path.length > 0) && UriNormalizer::need_norm_path(path))
+    if ((path.length > 0) && UriNormalizer::need_norm(path, true, uri_param, infractions, events))
         infractions += INF_URI_NEED_NORM_PATH;
-    if ((query.length > 0) && UriNormalizer::need_norm_no_path(query))
+    if ((query.length > 0) && UriNormalizer::need_norm(query, false, uri_param, infractions,
+            events))
         infractions += INF_URI_NEED_NORM_QUERY;
-    if ((fragment.length > 0) && UriNormalizer::need_norm_no_path(fragment))
+    if ((fragment.length > 0) && UriNormalizer::need_norm(fragment, false, uri_param, infractions,
+            events))
         infractions += INF_URI_NEED_NORM_FRAGMENT;
 
     if (!((infractions & INF_URI_NEED_NORM_PATH)  || (infractions & INF_URI_NEED_NORM_HOST) ||
@@ -200,7 +199,8 @@ void NHttpUri::normalize()
     if (host.length > 0)
     {
         if (infractions & INF_URI_NEED_NORM_HOST)
-            UriNormalizer::normalize(host, host_norm, false, current, infractions, events);
+            UriNormalizer::normalize(host, host_norm, false, current, uri_param, infractions,
+                events);
         else
         {
             // The host component is not changing but other parts of the URI are being normalized.
@@ -222,7 +222,8 @@ void NHttpUri::normalize()
     if (path.length > 0)
     {
         if (infractions & INF_URI_NEED_NORM_PATH)
-            UriNormalizer::normalize(path, path_norm, true, current, infractions, events);
+            UriNormalizer::normalize(path, path_norm, true, current, uri_param, infractions,
+                events);
         else
         {
             memcpy(current, path.start, path.length);
@@ -235,7 +236,8 @@ void NHttpUri::normalize()
         memcpy(current, "?", 1);
         current += 1;
         if (infractions & INF_URI_NEED_NORM_QUERY)
-            UriNormalizer::normalize(query, query_norm, false, current, infractions, events);
+            UriNormalizer::normalize(query, query_norm, false, current, uri_param, infractions,
+                events);
         else
         {
             memcpy(current, query.start, query.length);
@@ -248,7 +250,8 @@ void NHttpUri::normalize()
         memcpy(current, "#", 1);
         current += 1;
         if (infractions & INF_URI_NEED_NORM_FRAGMENT)
-            UriNormalizer::normalize(fragment, fragment_norm, false, current, infractions, events);
+            UriNormalizer::normalize(fragment, fragment_norm, false, current, uri_param,
+                infractions, events);
         else
         {
             memcpy(current, fragment.start, fragment.length);
index 89f2643709b6bf8038f517d1196b8567ca36a753..dfd835e05d40c93a7e54d7df71159c0c09ba1aad 100644 (file)
@@ -21,6 +21,7 @@
 #define NHTTP_URI_H
 
 #include "nhttp_str_to_code.h"
+#include "nhttp_module.h"
 #include "nhttp_uri_norm.h"
 #include "nhttp_field.h"
 #include "nhttp_infractions.h"
 class NHttpUri
 {
 public:
-    NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method,
-        NHttpInfractions& infractions_, NHttpEventGen& events_) :
-        uri(length, start), method_id(method), infractions(infractions_), events(events_)
+    NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method_id_,
+        const NHttpParaList::UriParam& uri_param_, NHttpInfractions& infractions_,
+        NHttpEventGen& events_) :
+        uri(length, start), method_id(method_id_), uri_param(uri_param_),
+        infractions(infractions_), events(events_)
         { normalize(); }
     ~NHttpUri();
     const Field& get_uri() const { return uri; }
@@ -58,6 +61,7 @@ public:
 private:
     const Field uri;
     const NHttpEnums::MethodId method_id;
+    const NHttpParaList::UriParam& uri_param;
     NHttpInfractions& infractions;
     NHttpEventGen& events;
 
index 6fd54ba59a0f382921fc14a711148b5eec1d1316..c34337f1ae267bdecde2de9c7d29c2a7c90c2185 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <assert.h>
 #include <sys/types.h>
+#include <cstring>
 
 #include "nhttp_enum.h"
 #include "nhttp_uri_norm.h"
 using namespace NHttpEnums;
 
 void UriNormalizer::normalize(const Field& input, Field& result, bool do_path, uint8_t* buffer,
-    NHttpInfractions& infractions, NHttpEventGen& events)
+    const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions, NHttpEventGen& events)
 {
-    // Normalize character escape sequences
-    int32_t data_length = norm_char_clean(input.start, input.length, buffer, infractions, events);
+    // Normalize percent encodings and similar escape sequences
+    int32_t data_length = norm_char_clean(input, buffer, uri_param, infractions, events);
+
+    detect_bad_char(Field(data_length, buffer), uri_param, infractions, events);
+
+    norm_substitute(buffer, data_length, uri_param, infractions, events);
 
     // Normalize path directory traversals
-    if (do_path)
+    if (do_path && uri_param.simplify_path)
     {
-        norm_backslash(buffer, data_length, infractions, events);
         data_length = norm_path_clean(buffer, data_length, infractions, events);
     }
 
     result.set(data_length, buffer);
 }
 
-bool UriNormalizer::need_norm_no_path(const Field& uri_component)
+bool UriNormalizer::need_norm(const Field& uri_component, bool do_path,
+    const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions, NHttpEventGen& events)
+{
+    bool need_it;
+    if (do_path && uri_param.simplify_path)
+        need_it = need_norm_path(uri_component, uri_param);
+    else
+        need_it = need_norm_no_path(uri_component, uri_param);
+
+    if (!need_it)
+    {
+        // Since we are not going to normalize we need to check for bad characters now
+        detect_bad_char(uri_component, uri_param, infractions, events);
+    }
+
+    return need_it;
+}
+
+bool UriNormalizer::need_norm_no_path(const Field& uri_component,
+    const NHttpParaList::UriParam& uri_param)
 {
     const int32_t& length = uri_component.length;
     const uint8_t* const & buf = uri_component.start;
     for (int32_t k = 0; k < length; k++)
     {
-         if ((uri_char[buf[k]] == CHAR_NORMAL) || (uri_char[buf[k]] == CHAR_PATH))
-            continue;
-        return true;
+        if ((uri_param.uri_char[buf[k]] == CHAR_PERCENT) ||
+            (uri_param.uri_char[buf[k]] == CHAR_SUBSTIT))
+            return true;
     }
     return false;
 }
 
-bool UriNormalizer::need_norm_path(const Field& uri_component)
+bool UriNormalizer::need_norm_path(const Field& uri_component,
+    const NHttpParaList::UriParam& uri_param)
 {
     const int32_t& length = uri_component.length;
     const uint8_t* const & buf = uri_component.start;
     for (int32_t k = 0; k < length; k++)
     {
-        if (uri_char[buf[k]] == CHAR_NORMAL)
-            continue;
-        if ((buf[k] == '/') && ((k == 0) || (buf[k-1] != '/')))
-            continue;
-        if (  (buf[k] == '.')                                               &&
-              ((k == 0) || (uri_char[buf[k-1]] == CHAR_NORMAL))             &&
-              ((k == length-1) || (uri_char[buf[k+1]] == CHAR_NORMAL)))
+        switch (uri_param.uri_char[buf[k]])
+        {
+        case CHAR_NORMAL:
+        case CHAR_EIGHTBIT:
             continue;
-        return true;
+        case CHAR_PERCENT:
+        case CHAR_SUBSTIT:
+            return true;
+        case CHAR_PATH:
+            if (buf[k] == '/')
+            {
+                // slash is safe if not preceded by another slash
+                if ((k == 0) || (buf[k-1] != '/'))
+                    continue;
+                return true;
+            }
+            else if (buf[k] == '.')
+            {
+                // period is safe if not preceded or followed by another path character
+                if (((k == 0) || (uri_param.uri_char[buf[k-1]] != CHAR_PATH))          &&
+                    ((k == length-1) || (uri_param.uri_char[buf[k+1]] != CHAR_PATH)))
+                    continue;
+                return true;
+            }
+            else
+            {
+                return true;
+            }
+        }
     }
     return false;
 }
 
-int32_t UriNormalizer::norm_char_clean(const uint8_t* in_buf, int32_t in_length, uint8_t* out_buf,
-    NHttpInfractions& infractions, NHttpEventGen& events)
+int32_t UriNormalizer::norm_char_clean(const Field& input, uint8_t* out_buf,
+    const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions, NHttpEventGen& events)
 {
     int32_t length = 0;
-    for (int32_t k = 0; k < in_length; k++)
+    for (int32_t k = 0; k < input.length; k++)
     {
-        switch (uri_char[in_buf[k]])
+        switch (uri_param.uri_char[input.start[k]])
         {
         case CHAR_NORMAL:
         case CHAR_PATH:
-            out_buf[length++] = in_buf[k];
-            break;
-        case CHAR_INVALID:
-            infractions += INF_URI_BAD_CHAR;
-            events.create_event(EVENT_NON_RFC_CHAR);
-            out_buf[length++] = in_buf[k];
-            break;
         case CHAR_EIGHTBIT:
-            infractions += INF_URI_8BIT_CHAR;
-            events.create_event(EVENT_BARE_BYTE);
-            out_buf[length++] = in_buf[k];
+        case CHAR_SUBSTIT:
+            out_buf[length++] = input.start[k];
             break;
         case CHAR_PERCENT:
-            if ((k+2 < in_length) && (as_hex[in_buf[k+1]] != -1) && (as_hex[in_buf[k+2]] != -1))
+            if ((k+2 < input.length) && (as_hex[input.start[k+1]] != -1) &&
+                (as_hex[input.start[k+2]] != -1))
             {
-                if (as_hex[in_buf[k+1]] <= 7)
-                {
-                    uint8_t value = as_hex[in_buf[k+1]] * 16 + as_hex[in_buf[k+2]];
-                    if (good_percent[value])
-                    {
-                        // Normal % escape of an ASCII special character that is supposed to be
-                        // escaped
-                        infractions += INF_URI_PERCENT_NORMAL;
-                        out_buf[length++] = '%';
-                    }
-                    else
-                    {
-                        // Suspicious % escape of an ASCII character that does not need to be
-                        // escaped
-                        infractions += INF_URI_PERCENT_ASCII;
-                        events.create_event(EVENT_ASCII);
-                        if (uri_char[value] == CHAR_INVALID)
-                        {
-                            infractions += INF_URI_BAD_CHAR;
-                            events.create_event(EVENT_NON_RFC_CHAR);
-                        }
-                        out_buf[length++] = value;
-                        k += 2;
-                    }
-                }
-                else
-                {
-                    // UTF-8 decoding not implemented yet
-                    infractions += INF_URI_PERCENT_UTF8;
-                    events.create_event(EVENT_UTF_8);
-                    out_buf[length++] = '%';
-                }
+                // %hh => hex value
+                out_buf[length++] = as_hex[input.start[k+1]] * 16 + as_hex[input.start[k+2]];
+                k += 2;
             }
-            else if ((k+5 < in_length) && (in_buf[k+1] == 'u') && (as_hex[in_buf[k+2]] != -1) &&
-                (as_hex[in_buf[k+3]] != -1)
-                && (as_hex[in_buf[k+4]] != -1) && (as_hex[in_buf[k+5]] != -1))
+            else if ((k+1 < input.length) && (input.start[k+1] == '%'))
             {
-                // 'u' UTF-16 decoding not implemented yet
-                infractions += INF_URI_PERCENT_UCODE;
-                events.create_event(EVENT_U_ENCODE);
+                // %% => %
                 out_buf[length++] = '%';
+                k += 1;
             }
             else
             {
-                // Don't recognize it
-                infractions += INF_URI_PERCENT_OTHER;
+                // don't recognize, pass through for now (FIXIT-H unfinished feature)
                 out_buf[length++] = '%';
             }
+
+            // The result of percent decoding should not be an "unreserved" character. That's a
+            // strong clue someone is hiding something.
+            if (uri_param.unreserved_char[out_buf[length-1]])
+            {
+                infractions += INF_URI_PERCENT_UNRESERVED;
+                events.create_event(EVENT_ASCII);
+            }
             break;
         }
     }
     return length;
 }
 
-// Convert URI backslashes to slashes
-void UriNormalizer::norm_backslash(uint8_t* buf, int32_t length, NHttpInfractions& infractions,
-    NHttpEventGen& events)
+void UriNormalizer::detect_bad_char(const Field& uri_component,
+    const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions, NHttpEventGen& events)
 {
-    for (int32_t k = 0; k < length; k++)
+    // If the bad character detection feature is not configured we quit
+    if (uri_param.bad_characters.count() == 0)
+        return;
+
+    for (int32_t k = 0; k < uri_component.length; k++)
+    {
+        if (uri_param.bad_characters[uri_component.start[k]])
+        {
+            infractions += INF_URI_BAD_CHAR;
+            events.create_event(EVENT_NON_RFC_CHAR);
+            return;
+        }
+    }
+}
+
+// Replace backslash with slash and plus with space
+void UriNormalizer::norm_substitute(uint8_t* buf, int32_t length,
+    const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions, NHttpEventGen& events)
+{
+    if (uri_param.backslash_to_slash)
+    {
+        for (int32_t k = 0; k < length; k++)
+        {
+            if (buf[k] == '\\')
+            {
+                buf[k] = '/';
+                infractions += INF_URI_BACKSLASH;
+                events.create_event(EVENT_IIS_BACKSLASH);
+            }
+        }
+    }
+    if (uri_param.plus_to_space)
     {
-        if (buf[k] == '\\')
+        for (int32_t k = 0; k < length; k++)
         {
-            buf[k] = '/';
-            infractions += INF_URI_BACKSLASH;
-            events.create_event(EVENT_IIS_BACKSLASH);
+            if (buf[k] == '+')
+            {
+                buf[k] = ' ';
+            }
         }
     }
 }
@@ -236,7 +279,8 @@ int32_t UriNormalizer::norm_path_clean(uint8_t* buf, const int32_t in_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)
+void UriNormalizer::classic_normalize(const Field& input, Field& result, uint8_t* buffer,
+    const NHttpParaList::UriParam& uri_param)
 {
     // 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
@@ -247,28 +291,36 @@ void UriNormalizer::classic_normalize(const Field& input, Field& result, uint8_t
     // 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);
+    int32_t data_length = norm_char_clean(input, buffer, uri_param, 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)
+    if (uri_param.simplify_path)
     {
-        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);
+        // Normalize path directory traversals
+        // Find the leading slash if there is one
+        uint8_t* first_slash = (uint8_t*)memchr(buffer, '/', data_length);
+        if (first_slash != nullptr)
+        {
+            const int32_t uri_offset = first_slash - buffer;
+            norm_substitute(buffer + uri_offset, data_length - uri_offset, uri_param, 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);
 }
 
+bool UriNormalizer::classic_need_norm(const Field& uri_component, bool do_path,
+    const NHttpParaList::UriParam& uri_param)
+{
+    NHttpInfractions unused;
+    NHttpDummyEventGen dummy_ev;
+
+    return need_norm(uri_component, do_path, uri_param, unused, dummy_ev);
+}
+
index 2d2ba8728a530d61371b1fa6b516c444d95fd79f..6a3ba488896d12e0c58ed4e54baec8fe0631bb10 100644 (file)
@@ -21,6 +21,7 @@
 #define NHTTP_URI_NORM_H
 
 #include "nhttp_field.h"
+#include "nhttp_module.h"
 #include "nhttp_infractions.h"
 #include "nhttp_event_gen.h"
 
@@ -29,22 +30,39 @@ class UriNormalizer
 public:
     static const unsigned URI_NORM_EXPANSION = 1;
 
+    static bool need_norm(const Field& uri_component, bool do_path,
+        const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions,
+        NHttpEventGen& events);
     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 void classic_normalize(const Field& input, Field& result, uint8_t* buffer);
+        const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions,
+        NHttpEventGen& events);
+    static bool classic_need_norm(const Field& uri_component, bool do_path,
+        const NHttpParaList::UriParam& uri_param);
+    static void classic_normalize(const Field& input, Field& result, uint8_t* buffer,
+        const NHttpParaList::UriParam& uri_param);
 
 private:
-    static const NHttpEnums::CharAction uri_char[256];
-    static const bool good_percent[256];
-
-    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,
+    static bool need_norm_path(const Field& uri_component,
+        const NHttpParaList::UriParam& uri_param);
+    static bool need_norm_no_path(const Field& uri_component,
+        const NHttpParaList::UriParam& uri_param);
+    static int32_t norm_char_clean(const Field& input, uint8_t* out_buf,
+        const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions,
+        NHttpEventGen& events);
+    static void norm_substitute(uint8_t* buf, int32_t length,
+        const NHttpParaList::UriParam& uri_param,  NHttpInfractions& infractions,
         NHttpEventGen& events);
     static int32_t norm_path_clean(uint8_t* buf, const int32_t in_length,
         NHttpInfractions& infractions, NHttpEventGen& events);
+    static void detect_bad_char(const Field& uri_component,
+        const NHttpParaList::UriParam& uri_param, NHttpInfractions& infractions,
+        NHttpEventGen& events);
+
+    // An artifice used by the classic normalization methods to disable event generation
+    class NHttpDummyEventGen : public NHttpEventGen
+    {
+        void create_event(NHttpEnums::EventSid) override {}
+    };
 };
 
 #endif
diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri_tables.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri_tables.cc
deleted file mode 100644 (file)
index a619612..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 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.
-//--------------------------------------------------------------------------
-// nhttp_uri_tables.cc author Tom Peters <thopeter@cisco.com>
-
-#include <string.h>
-#include <sys/types.h>
-
-#include "nhttp_enum.h"
-#include "nhttp_uri_norm.h"
-
-using namespace NHttpEnums;
-
-const CharAction UriNormalizer::uri_char[256] =
-{
-    CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,
-    CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,
-    CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,
-    CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,   CHAR_INVALID,
-
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PERCENT,   CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PATH,      CHAR_PATH,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_PATH,      CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,
-    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_NORMAL,    CHAR_INVALID,
-
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,
-    CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT,  CHAR_EIGHTBIT
-};
-
-const bool UriNormalizer::good_percent[256] =
-{
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false,  true, false, true,  false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-    false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false
-};
-