]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2443 in SNORT/snort3 from ~MDAGON/snort3:field_127 to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Wed, 2 Sep 2020 20:06:26 +0000 (20:06 +0000)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Wed, 2 Sep 2020 20:06:26 +0000 (20:06 +0000)
Squashed commit of the following:

commit 18a108729bf0f36b122bebc77460447862c772f4
Author: mdagon <mdagon@cisco.com>
Date:   Tue Aug 18 14:43:56 2020 -0400

    payload_injector: support translation of header field value with length > 127

src/payload_injector/payload_injector_module.cc
src/payload_injector/payload_injector_module.h
src/payload_injector/payload_injector_translate_page.cc
src/payload_injector/test/payload_injector_test.cc
src/payload_injector/test/payload_injector_translate_test.cc
src/service_inspectors/http2_inspect/test/http2_hpack_int_decode_test.cc

index 88f81a1f8f5a8be2a3317b186c70b9bbfd45ec4d..094b7272b430e15721f2140e6720ee6a4a2d75a0 100644 (file)
@@ -57,8 +57,6 @@ static const std::map <InjectionReturnStatus, const char*> InjectionErrorToStrin
     { ERR_PAGE_TRANSLATION, "Error in translating HTTP block page to HTTP/2. "
       "Unsupported or bad format." },
     { ERR_HTTP2_MID_FRAME, "HTTP/2 - attempt to inject mid frame. Currently not supported." },
-    { ERR_HTTP2_HDR_FIELD_VAL_LEN, "HTTP/2 header field value length > 127. "
-      " Currently not supported." },
     { ERR_TRANSLATED_HDRS_SIZE,
       "HTTP/2 translated header size is bigger than expected. Update max size." },
     { ERR_HTTP2_BODY_SIZE, "HTTP/2 body is > 16k. Currently not supported." }
index 582ade686354c4234f39586d4e94019f3acce710..bcea004987a3841414d92a1b959fa9effcbaaee7 100644 (file)
@@ -48,9 +48,8 @@ enum InjectionReturnStatus : int8_t
     ERR_HTTP2_STREAM_ID_0 = -4,
     ERR_PAGE_TRANSLATION = -5,
     ERR_HTTP2_MID_FRAME = -6,
-    ERR_HTTP2_HDR_FIELD_VAL_LEN = -7,
-    ERR_TRANSLATED_HDRS_SIZE = -8,
-    ERR_HTTP2_BODY_SIZE = -9,
+    ERR_TRANSLATED_HDRS_SIZE = -7,
+    ERR_HTTP2_BODY_SIZE = -8,
     // Update InjectionErrorToString when adding/removing error codes
 };
 
@@ -95,5 +94,10 @@ public:
     static InjectionReturnStatus get_http2_payload(InjectionControl control, uint8_t*& http2_payload, uint32_t& payload_len);
 };
 
+#ifdef UNIT_TEST
+InjectionReturnStatus write_7_bit_prefix_int(uint32_t val, uint8_t*& out,
+                                            uint32_t& out_free_space);
+#endif
+
 #endif
 
index 31da9ea23a7bea393216baa36ce4d2ee162d745b..d85dbaab82367b903e1bd716e97ebc2f02e91b32 100644 (file)
@@ -53,25 +53,10 @@ static const char location[] = "Location: ";
 
 static const uint32_t max_hdr_size = 2000;
 
-// Write literal header field
-static InjectionReturnStatus write_indexed(const uint8_t* hdr, uint32_t len, uint8_t*& out,
-    uint32_t& out_free_space, const uint8_t* ind, uint8_t ind_size)
+static InjectionReturnStatus write_translation(uint8_t*& out, uint32_t& out_free_space,
+    const uint8_t* translation, uint32_t size)
 {
-    const uint8_t* sep = (const uint8_t*)memchr(hdr,':',len);
-    assert(sep != nullptr);
-    const uint32_t skip_len = strlen(": ");
-    assert((sep - hdr) >= skip_len);
-    const uint32_t val_len = len - (sep - hdr) - skip_len;
-    const uint8_t max_val_len = (1<<7) - 1; // FIXIT-E bigger than this will have to be 7 bit
-                                            // prefix
-                                            // encoded - currently not supported
-    if (val_len > max_val_len)
-        return ERR_HTTP2_HDR_FIELD_VAL_LEN;
-
-    if (val_len == 0)
-        return ERR_PAGE_TRANSLATION;
-
-    if (out_free_space < (val_len + 1 + ind_size))
+    if (out_free_space < size)
     {
 #ifndef UNIT_TEST
         assert(false);  // increase max_hdr_size
@@ -79,33 +64,68 @@ static InjectionReturnStatus write_indexed(const uint8_t* hdr, uint32_t len, uin
         return ERR_TRANSLATED_HDRS_SIZE;
     }
 
-    memcpy(out, ind, ind_size);
-    out += ind_size;
-    out[0] = val_len;
-    memcpy(out + 1, sep + skip_len, val_len);
-    out += 1 + val_len;
-    out_free_space -= val_len + 1 + ind_size;
+    memcpy(out, translation, size);
+    out += size;
+    out_free_space -= size;
 
     return INJECTION_SUCCESS;
 }
 
-// Write fixed translation
-static InjectionReturnStatus write_translation(uint8_t*& out, uint32_t& out_free_space,
-    const uint8_t* translation, uint8_t size)
-{
-    if (out_free_space < size)
-    {
 #ifndef UNIT_TEST
-        assert(false);  // increase max_hdr_size
+static
 #endif
-        return ERR_TRANSLATED_HDRS_SIZE;
+InjectionReturnStatus write_7_bit_prefix_int(uint32_t val, uint8_t*& out, uint32_t& out_free_space)
+{
+    uint8_t write_val;
+    if (val < ((1<<7) - 1))
+    {
+        write_val = val;
+        return write_translation(out, out_free_space, &write_val, 1);
     }
 
-    memcpy(out, translation, size);
-    out += size;
-    out_free_space -= size;
+    write_val = (1<<7) - 1;
+    InjectionReturnStatus status =  write_translation(out, out_free_space, &write_val, 1);
+    if (status != INJECTION_SUCCESS)
+        return status;
+    val -= write_val;
 
-    return INJECTION_SUCCESS;
+    while (val >= 128)
+    {
+        write_val = val % 128 + 128;
+        status =  write_translation(out, out_free_space, &write_val, 1);
+        if (status != INJECTION_SUCCESS)
+            return status;
+        val = val/128;
+    }
+    write_val = val;
+    status =  write_translation(out, out_free_space, &write_val, 1);
+    return status;
+}
+
+// Write literal header field
+static InjectionReturnStatus write_indexed(const uint8_t* hdr, uint32_t len, uint8_t*& out,
+    uint32_t& out_free_space, const uint8_t* ind, uint8_t ind_size)
+{
+    const uint8_t* sep = (const uint8_t*)memchr(hdr,':',len);
+    assert(sep != nullptr);
+    const uint32_t skip_len = strlen(": ");
+    assert((sep - hdr) >= skip_len);
+    const uint32_t val_len = len - (sep - hdr) - skip_len;
+
+    if (val_len == 0)
+        return ERR_PAGE_TRANSLATION;
+
+    InjectionReturnStatus status = write_translation(out, out_free_space, ind, ind_size);
+    if (status != INJECTION_SUCCESS)
+        return status;
+
+    status = write_7_bit_prefix_int(val_len, out, out_free_space);
+    if (status != INJECTION_SUCCESS)
+        return status;
+
+    status = write_translation(out, out_free_space, sep + skip_len, val_len);
+
+    return status;
 }
 
 static InjectionReturnStatus translate_hdr_field(const uint8_t* hdr, uint32_t len, uint8_t*& out,
@@ -165,7 +185,8 @@ static InjectionReturnStatus get_http2_hdr(const uint8_t* http_page, uint32_t le
     uint8_t* hdr_cur = http2_hdr;
     while ((page_cur - http_page) < len)
     {
-        const uint8_t* newline = (const uint8_t*)memchr(page_cur, '\n', len - (page_cur - http_page));
+        const uint8_t* newline = (const uint8_t*)memchr(page_cur, '\n', len - (page_cur -
+            http_page));
         if (newline != nullptr)
         {
             // FIXIT-E only \r\n should be supported
index f8216e0f189e60a824c4c13a9ffcef84a6f6218f..736f037591103e765160aea5a0659fb9f956e483 100644 (file)
@@ -346,18 +346,6 @@ TEST(payload_injector_translate_err_test, http2_page_translation_err)
         "Unsupported or bad format.") == 0);
 }
 
-TEST(payload_injector_translate_err_test, http2_field_len_err)
-{
-    Packet p(false);
-    p.packet_flags = PKT_STREAM_EST;
-    p.flow = &flow;
-    translation_status = ERR_HTTP2_HDR_FIELD_VAL_LEN;
-    status = mod.inject_http_payload(&p, control);
-    const char* err_string = mod.get_err_string(status);
-    CHECK(strcmp(err_string, "HTTP/2 header field value length > 127. "
-        " Currently not supported.") == 0);
-}
-
 TEST(payload_injector_translate_err_test, http2_hdrs_size)
 {
     Packet p(false);
index 27c964accaa6962b7480c52292710d75c0b3a4fc..df9af32f000a8c99f746054800585fbbf45d6287 100644 (file)
@@ -282,8 +282,8 @@ TEST(payload_injector_translate_test, missing_value)
     CHECK(status == ERR_PAGE_TRANSLATION);
 }
 
-// Header value has maximum supported length + 1
-TEST(payload_injector_translate_test, val_len_too_big)
+// Verify field value length is translated correctly
+TEST(payload_injector_translate_test, val_len1)
 {
     const uint32_t size = strlen("Location: ") + 128 + strlen("\r\n\r\nbody");
     uint8_t http_page[size];
@@ -297,11 +297,30 @@ TEST(payload_injector_translate_test, val_len_too_big)
     control.http_page_len = size;
     status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
 
-    CHECK(status == ERR_HTTP2_HDR_FIELD_VAL_LEN);
+    CHECK(status == INJECTION_SUCCESS);
+
+    uint8_t out[] =
+    {
+        0x0, 0x0, 0x84, 0x1, 0x4, 0x0, 0x0, 0x0, 0x1, 0xf, 0x1f, 0x7f, 0x1, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x0, 0x0, 0x4,
+        0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x6f, 0x64, 0x79
+    };
+    CHECK(payload_len == sizeof(out));
+    CHECK(memcmp(http2_payload, out, payload_len) == 0);
+
+    snort_free(http2_payload);
 }
 
-// Header value has maximum supported length 127
-TEST(payload_injector_translate_test, max_val)
+TEST(payload_injector_translate_test, val_len2)
 {
     const uint32_t size = strlen("Location: ") + 127 + strlen("\r\n\r\nbody");
     uint8_t http_page[size];
@@ -316,6 +335,88 @@ TEST(payload_injector_translate_test, max_val)
     status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
 
     CHECK(status == INJECTION_SUCCESS);
+    uint8_t out[] =
+    {
+        0x0, 0x0, 0x83, 0x1, 0x4, 0x0, 0x0, 0x0, 0x1, 0xf, 0x1f, 0x7f, 0x0, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x0, 0x0, 0x4, 0x0,
+        0x1, 0x0, 0x0, 0x0, 0x1, 0x62, 0x6f, 0x64, 0x79
+    };
+    CHECK(payload_len == sizeof(out));
+    CHECK(memcmp(http2_payload, out, payload_len) == 0);
+    snort_free(http2_payload);
+}
+
+TEST(payload_injector_translate_test, val_len3)
+{
+    const uint32_t size = strlen("Location: ") + 500 + strlen("\r\n\r\nbody");
+    uint8_t http_page[size];
+    memset(http_page, 'a', size);
+    memcpy(http_page, "Location: ", strlen("Location: "));
+    memcpy(http_page+500+strlen("Location: "), "\r\n\r\nbody", strlen("\r\n\r\nbody"));
+
+    InjectionControl control;
+    control.stream_id = 1;
+    control.http_page = http_page;
+    control.http_page_len = size;
+    status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
+
+    CHECK(status == INJECTION_SUCCESS);
+
+    uint8_t out[] =
+    {
+        0x0, 0x1, 0xf9, 0x1, 0x4, 0x0, 0x0, 0x0, 0x1, 0xf, 0x1f, 0x7f, 0xf5, 0x2,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,        0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+        0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x0, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0,
+        0x1, 0x62, 0x6f, 0x64, 0x79
+    };
+    CHECK(payload_len == sizeof(out));
+    CHECK(memcmp(http2_payload, out, payload_len) == 0);
     snort_free(http2_payload);
 }
 
@@ -401,6 +502,88 @@ TEST(payload_injector_translate_test, http2_hdr_too_big2)
     CHECK(status == ERR_TRANSLATED_HDRS_SIZE);
 }
 
+// Translated header > 2000. Fails while trying to write Location field value length - failure when
+// writing first byte of 2.
+TEST(payload_injector_translate_test, http2_hdr_too_big3)
+{
+    const uint32_t size = strlen("Connection: close\r\n") * 111 + strlen("Location: ") +
+        strlen("\r\n\r\nbody") + 130;
+    uint8_t http_page[size];
+
+    memset(http_page, 'a', size);
+    uint8_t* cur_pos = http_page;
+    for (int i=0; i < 111; i++)
+    {
+        memcpy(cur_pos, "Connection: close\r\n", strlen("Connection: close\r\n"));
+        cur_pos += strlen("Connection: close\r\n");
+    }
+    memcpy(cur_pos, "Location: ", strlen("Location: "));
+    memcpy(http_page+size-strlen("\r\n\r\nbody"), "\r\n\r\nbody", strlen("\r\n\r\nbody"));
+
+    InjectionControl control;
+    control.stream_id = 1;
+    control.http_page = http_page;
+    control.http_page_len = size;
+    status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
+
+    CHECK(status == ERR_TRANSLATED_HDRS_SIZE);
+}
+
+// Translated header > 2000. Fails while trying to write Location field value length - failure when
+// writing second byte of 3.
+TEST(payload_injector_translate_test, http2_hdr_too_big4)
+{
+    const uint32_t size = strlen("Connection: close\r\n") * 110 + strlen("Location: ")*2 +
+        strlen("\r\n\r\nbody") + 300 + 14;
+    uint8_t http_page[size];
+
+    memset(http_page, 'a', size);
+    uint8_t* cur_pos = http_page;
+    for (int i=0; i < 110; i++)
+    {
+        memcpy(cur_pos, "Connection: close\r\n", strlen("Connection: close\r\n"));
+        cur_pos += strlen("Connection: close\r\n");
+    }
+    memcpy(cur_pos, "Location: ", strlen("Location: "));
+    memcpy(cur_pos+strlen("Location: ")+14, "\r\nLocation: ", strlen("\r\nLocation: "));
+    memcpy(http_page+size-strlen("\r\n\r\nbody"), "\r\n\r\nbody", strlen("\r\n\r\nbody"));
+
+    InjectionControl control;
+    control.stream_id = 1;
+    control.http_page = http_page;
+    control.http_page_len = size;
+    status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
+
+    CHECK(status == ERR_TRANSLATED_HDRS_SIZE);
+}
+
+// Translated header > 2000. Fails while trying to write translation of second "Location: "
+TEST(payload_injector_translate_test, http2_hdr_too_big5)
+{
+    const uint32_t size = strlen("Connection: close\r\n") * 110 + strlen("Location: ")*2 +
+        strlen("\r\n\r\nbody") + 300 + 16;
+    uint8_t http_page[size];
+
+    memset(http_page, 'a', size);
+    uint8_t* cur_pos = http_page;
+    for (int i=0; i < 110; i++)
+    {
+        memcpy(cur_pos, "Connection: close\r\n", strlen("Connection: close\r\n"));
+        cur_pos += strlen("Connection: close\r\n");
+    }
+    memcpy(cur_pos, "Location: ", strlen("Location: "));
+    memcpy(cur_pos+strlen("Location: ")+16, "\r\nLocation: ", strlen("\r\nLocation: "));
+    memcpy(http_page+size-strlen("\r\n\r\nbody"), "\r\n\r\nbody", strlen("\r\n\r\nbody"));
+
+    InjectionControl control;
+    control.stream_id = 1;
+    control.http_page = http_page;
+    control.http_page_len = size;
+    status = PayloadInjectorModule::get_http2_payload(control, http2_payload, payload_len);
+
+    CHECK(status == ERR_TRANSLATED_HDRS_SIZE);
+}
+
 TEST(payload_injector_translate_test, payload_body_larger_than_max)
 {
     static const uint32_t size = (1<<14) + 1 + strlen("HTTP/1.1 403 Forbidden\r\n\r\n");
@@ -436,6 +619,30 @@ TEST(payload_injector_translate_test, http_page_is_0_length)
     CHECK(status == ERR_PAGE_TRANSLATION);
 }
 
+TEST(payload_injector_translate_test, 7_bit_int_min_max)
+{
+   uint8_t out[6];
+   uint32_t out_free_space = sizeof(out);
+
+   // Translate 0
+   uint8_t* cur = out;
+   InjectionReturnStatus status = write_7_bit_prefix_int(0, cur, out_free_space);
+   uint8_t expected_out[] = {0};
+   CHECK(status == INJECTION_SUCCESS);
+   CHECK(out_free_space == 5);
+   CHECK(memcmp(out, expected_out, 1) == 0);
+
+   // Translate max uint_32
+   cur = out;
+   out_free_space = sizeof(out);
+   status = write_7_bit_prefix_int(UINT32_MAX, cur, out_free_space);
+   uint8_t expected_out2[] = {0x7f, 0x80, 0xff, 0xff, 0xff, 0xf};
+   CHECK(status == INJECTION_SUCCESS);
+   CHECK(out_free_space == 0);
+   CHECK(memcmp(out, expected_out2, 6) == 0);
+}
+
+
 int main(int argc, char** argv)
 {
     return CommandLineTestRunner::RunAllTests(argc, argv);
index 208d02766046192eead1277edefa2f89a2939078..ed23e3516d8ea0758243d8b4be6ae4606bf67473 100644 (file)
@@ -154,6 +154,22 @@ TEST(http2_hpack_int_decode_success, 0_using_5_bits)
     CHECK(bytes_processed == 1);
 }
 
+TEST(http2_hpack_int_decode_success, MAX_UINT32_using_7_bits)
+{
+    // prepare decode object
+    Http2HpackIntDecode decode_7(7);
+    // prepare buf to decode - MAX_UINT32 using 7 bits
+    uint8_t buf[6] = {0x7f, 0x80, 0xff, 0xff, 0xff, 0xf};
+    // decode
+    uint32_t bytes_processed = 0;
+    uint64_t res = 0;
+    bool success = decode_7.translate(buf, 6, bytes_processed, res, &events, &inf);
+    // check results
+    CHECK(success == true);
+    CHECK(res == UINT32_MAX);
+    CHECK(bytes_processed == 6);
+}
+
 //
 // The following tests should result in a failure and set infractions/events
 //