From 93e6fe777952fb969b945d0c1167dfcbff581bf5 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 06 2019 09:59:17 +0000 Subject: import http-parser-2.7.1-8.el7 --- diff --git a/SOURCES/CVE-2018-12121-backport.patch b/SOURCES/CVE-2018-12121-backport.patch new file mode 100644 index 0000000..ba38f23 --- /dev/null +++ b/SOURCES/CVE-2018-12121-backport.patch @@ -0,0 +1,67 @@ +diff -up http-parser-2.7.1/http_parser.c.cve http-parser-2.7.1/http_parser.c +--- http-parser-2.7.1/http_parser.c.cve 2019-03-22 22:33:28.577238523 +0100 ++++ http-parser-2.7.1/http_parser.c 2019-03-22 22:35:12.237323250 +0100 +@@ -29,6 +29,8 @@ + #include + #include + ++static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; ++ + #ifndef ULLONG_MAX + # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ + #endif +@@ -141,20 +143,20 @@ do { + } while (0) + + /* Don't allow the total size of the HTTP headers (including the status +- * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect ++ * line) to exceed max_header_size. This check is here to protect + * embedders against denial-of-service attacks where the attacker feeds + * us a never-ending header that the embedder keeps buffering. + * + * This check is arguably the responsibility of embedders but we're doing + * it on the embedder's behalf because most won't bother and this way we +- * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger ++ * make the web a little safer. max_header_size is still far bigger + * than any reasonable request or response so this should never affect + * day-to-day operation. + */ + #define COUNT_HEADER_SIZE(V) \ + do { \ + parser->nread += (V); \ +- if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ ++ if (UNLIKELY(parser->nread > (max_header_size))) { \ + SET_ERRNO(HPE_HEADER_OVERFLOW); \ + goto error; \ + } \ +@@ -1538,7 +1540,7 @@ reexecute: + const char* p_lf; + size_t limit = data + len - p; + +- limit = MIN(limit, HTTP_MAX_HEADER_SIZE); ++ limit = MIN(limit, max_header_size); + + p_cr = (const char*) memchr(p, CR, limit); + p_lf = (const char*) memchr(p, LF, limit); +@@ -2468,3 +2470,8 @@ http_parser_version(void) { + HTTP_PARSER_VERSION_MINOR * 0x00100 | + HTTP_PARSER_VERSION_PATCH * 0x00001; + } ++ ++void ++http_parser_set_max_header_size(uint32_t size) { ++ max_header_size = size; ++} +diff -up http-parser-2.7.1/http_parser.h.cve http-parser-2.7.1/http_parser.h +--- http-parser-2.7.1/http_parser.h.cve 2019-03-22 22:33:37.133245016 +0100 ++++ http-parser-2.7.1/http_parser.h 2019-03-22 22:34:03.640265140 +0100 +@@ -426,6 +426,9 @@ void http_parser_pause(http_parser *pars + /* Checks if this is the final chunk of the body. */ + int http_body_is_final(const http_parser *parser); + ++/* Change the maximum header size provided at compile time. */ ++void http_parser_set_max_header_size(uint32_t size); ++ + #ifdef __cplusplus + } + #endif diff --git a/SOURCES/CVE-2018-7159-Dissallow-empty-Content-Length.patch b/SOURCES/CVE-2018-7159-Dissallow-empty-Content-Length.patch new file mode 100644 index 0000000..83e92fe --- /dev/null +++ b/SOURCES/CVE-2018-7159-Dissallow-empty-Content-Length.patch @@ -0,0 +1,46 @@ +From 350258965909f249f9c59823aac240313e0d0120 Mon Sep 17 00:00:00 2001 +From: Olga Batyshkina +Date: Wed, 19 Dec 2018 16:02:23 +0100 +Subject: [PATCH] Disallow empty Content-Length + +PR-URL: https://github.com/nodejs/http-parser/pull/459 +Reviewed-By: Ben Noordhuis +--- + http_parser.c | 5 +++++ + test.c | 7 +++++++ + 2 files changed, 12 insertions(+) + +diff --git a/http_parser.c b/http_parser.c +index cd5d0d5..228ada5 100644 +--- a/http_parser.c ++++ b/http_parser.c +@@ -1740,6 +1740,11 @@ size_t http_parser_execute (http_parser *parser, + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; ++ case h_content_length: ++ /* do not allow empty content length */ ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ goto error; ++ break; + default: + break; + } +diff --git a/test.c b/test.c +index 25c8f5f..c3fddd5 100644 +--- a/test.c ++++ b/test.c +@@ -4182,6 +4182,13 @@ main (void) + test_invalid_header_field_token_error(HTTP_RESPONSE); + test_invalid_header_field_content_error(HTTP_RESPONSE); + ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length:\r\n" // empty ++ "\r\n", ++ HPE_INVALID_CONTENT_LENGTH, ++ HTTP_REQUEST); ++ + test_simple_type( + "POST / HTTP/1.1\r\n" + "Content-Length: 42 \r\n" // Note the surrounding whitespace. diff --git a/SOURCES/CVE-2018-7159-Fix-Content-Lenght-with-obsolete-line-folding-backport.patch b/SOURCES/CVE-2018-7159-Fix-Content-Lenght-with-obsolete-line-folding-backport.patch new file mode 100644 index 0000000..bcc2deb --- /dev/null +++ b/SOURCES/CVE-2018-7159-Fix-Content-Lenght-with-obsolete-line-folding-backport.patch @@ -0,0 +1,50 @@ +diff -up http-parser-2.7.1/http_parser.c.cve http-parser-2.7.1/http_parser.c +--- http-parser-2.7.1/http_parser.c.cve 2019-03-23 09:08:12.831806096 +0100 ++++ http-parser-2.7.1/http_parser.c 2019-03-23 09:09:45.047875248 +0100 +@@ -1483,6 +1483,11 @@ reexecute: + parser->header_state = h_content_length_num; + break; + ++ /* when obsolete line folding is encountered for content length ++ * continue to the s_header_value state */ ++ case h_content_length_ws: ++ break; ++ + case h_connection: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { +@@ -1727,6 +1732,10 @@ reexecute: + case s_header_value_lws: + { + if (ch == ' ' || ch == '\t') { ++ if (parser->header_state == h_content_length_num) { ++ /* treat obsolete line folding as space */ ++ parser->header_state = h_content_length_ws; ++ } + UPDATE_STATE(s_header_value_start); + REEXECUTE(); + } +diff -up http-parser-2.7.1/test.c.cve http-parser-2.7.1/test.c +--- http-parser-2.7.1/test.c.cve 2019-03-23 09:08:12.831806096 +0100 ++++ http-parser-2.7.1/test.c 2019-03-23 09:09:45.049875249 +0100 +@@ -3968,6 +3968,20 @@ main (void) + HPE_INVALID_CONTENT_LENGTH, + HTTP_REQUEST); + ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length: 42\r\n" ++ " Hello world!\r\n", ++ HPE_INVALID_CONTENT_LENGTH, ++ HTTP_REQUEST); ++ ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length: 42\r\n" ++ " \r\n", ++ HPE_OK, ++ HTTP_REQUEST); ++ + //// RESPONSES + + for (i = 0; i < response_count; i++) { diff --git a/SOURCES/CVE-2018-7159-reject-interior-blanks-in-Content-Length-backport.patch b/SOURCES/CVE-2018-7159-reject-interior-blanks-in-Content-Length-backport.patch new file mode 100644 index 0000000..01a0d8a --- /dev/null +++ b/SOURCES/CVE-2018-7159-reject-interior-blanks-in-Content-Length-backport.patch @@ -0,0 +1,84 @@ +diff -up http-parser-2.7.1/http_parser.c.cve http-parser-2.7.1/http_parser.c +--- http-parser-2.7.1/http_parser.c.cve 2019-03-23 08:58:04.459272497 +0100 ++++ http-parser-2.7.1/http_parser.c 2019-03-23 08:58:21.204279947 +0100 +@@ -376,6 +376,8 @@ enum header_states + + , h_connection + , h_content_length ++ , h_content_length_num ++ , h_content_length_ws + , h_transfer_encoding + , h_upgrade + +@@ -1478,6 +1480,7 @@ reexecute: + + parser->flags |= F_CONTENTLENGTH; + parser->content_length = ch - '0'; ++ parser->header_state = h_content_length_num; + break; + + case h_connection: +@@ -1565,10 +1568,18 @@ reexecute: + break; + + case h_content_length: ++ if (ch == ' ') break; ++ h_state = h_content_length_num; ++ /* FALLTHROUGH */ ++ ++ case h_content_length_num: + { + uint64_t t; + +- if (ch == ' ') break; ++ if (ch == ' ') { ++ h_state = h_content_length_ws; ++ break; ++ } + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); +@@ -1591,6 +1602,12 @@ reexecute: + break; + } + ++ case h_content_length_ws: ++ if (ch == ' ') break; ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ parser->header_state = h_state; ++ goto error; ++ + /* Transfer-Encoding: chunked */ + case h_matching_transfer_encoding_chunked: + parser->index++; +diff -up http-parser-2.7.1/test.c.cve http-parser-2.7.1/test.c +--- http-parser-2.7.1/test.c.cve 2019-03-23 08:57:50.851266439 +0100 ++++ http-parser-2.7.1/test.c 2019-03-23 08:58:25.545281880 +0100 +@@ -3947,6 +3947,27 @@ main (void) + test_invalid_header_field_token_error(HTTP_RESPONSE); + test_invalid_header_field_content_error(HTTP_RESPONSE); + ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length: 42 \r\n" // Note the surrounding whitespace. ++ "\r\n", ++ HPE_OK, ++ HTTP_REQUEST); ++ ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length: 4 2\r\n" ++ "\r\n", ++ HPE_INVALID_CONTENT_LENGTH, ++ HTTP_REQUEST); ++ ++ test_simple_type( ++ "POST / HTTP/1.1\r\n" ++ "Content-Length: 13 37\r\n" ++ "\r\n", ++ HPE_INVALID_CONTENT_LENGTH, ++ HTTP_REQUEST); ++ + //// RESPONSES + + for (i = 0; i < response_count; i++) { diff --git a/SOURCES/cve-tests-backport.patch b/SOURCES/cve-tests-backport.patch new file mode 100644 index 0000000..a425a96 --- /dev/null +++ b/SOURCES/cve-tests-backport.patch @@ -0,0 +1,40 @@ +diff -up http-parser-2.7.1/test.c.tests-simple-type http-parser-2.7.1/test.c +--- http-parser-2.7.1/test.c.tests-simple-type 2019-04-01 11:47:35.658031500 +0200 ++++ http-parser-2.7.1/test.c 2019-04-01 11:48:20.275113054 +0200 +@@ -3313,18 +3313,18 @@ test_message_count_body (const struct me + } + + void +-test_simple (const char *buf, enum http_errno err_expected) ++test_simple_type (const char *buf, ++ enum http_errno err_expected, ++ enum http_parser_type type) + { +- parser_init(HTTP_REQUEST); ++ parser_init(type); + + enum http_errno err; + + parse(buf, strlen(buf)); +- err = HTTP_PARSER_ERRNO(parser); ++ err = HTTP_PARSER_ERRNO(parser); + parse(NULL, 0); + +- parser_free(); +- + /* In strict mode, allow us to pass with an unexpected HPE_STRICT as + * long as the caller isn't expecting success. + */ +@@ -3340,6 +3340,12 @@ test_simple (const char *buf, enum http_ + } + + void ++test_simple (const char *buf, enum http_errno err_expected) ++{ ++ test_simple_type(buf, err_expected, HTTP_REQUEST); ++} ++ ++void + test_invalid_header_content (int req, const char* str) + { + http_parser parser; diff --git a/SPECS/http-parser.spec b/SPECS/http-parser.spec index 218db5c..1479589 100644 --- a/SPECS/http-parser.spec +++ b/SPECS/http-parser.spec @@ -5,7 +5,7 @@ Name: http-parser Version: %{somajor}.%{sominor}.%{sopoint} -Release: 5%{?dist} +Release: 8%{?dist} Summary: HTTP request/response parser for C License: MIT @@ -14,6 +14,11 @@ Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz # https://github.com/nodejs/http-parser/commit/335850f6b868d3411968cbf5a4d59fe619dee36f Patch0001: %{name}-0001-parser-HTTP_STATUS_MAP-XX-and-enum-http_status.patch +Patch0002: CVE-2018-12121-backport.patch +Patch0003: CVE-2018-7159-reject-interior-blanks-in-Content-Length-backport.patch +Patch0004: CVE-2018-7159-Fix-Content-Lenght-with-obsolete-line-folding-backport.patch +Patch0005: CVE-2018-7159-Dissallow-empty-Content-Length.patch +Patch0006: cve-tests-backport.patch BuildRequires: gcc BuildRequires: cmake @@ -101,10 +106,25 @@ make test -C %{_target_platform} %{_libdir}/libhttp_parser_strict.so %changelog +* Mon Apr 1 2019 Jakub Hrozek - 2.7.1-8 +- Backport needed test fixes +- Related: rhbz#1666024 - CVE-2018-7159 http-parser: nodejs: HTTP parser + allowed for spaces inside Content-Length header + values [rhel-7] + +* Sat Mar 23 2019 Jakub Hrozek - 2.7.1-7 +- Resolves: rhbz#1666024 - CVE-2018-7159 http-parser: nodejs: HTTP parser + allowed for spaces inside Content-Length header + values [rhel-7] + +* Fri Mar 22 2019 Jakub Hrozek - 2.7.1-6 +- Resolves: rhbz#1666381 - CVE-2018-12121 http-parser: nodejs: Denial of + Service with large HTTP headers [rhel-7] + * Thu Aug 10 2017 Fabiano FidĂȘncio - 2.7.1-5 - Bump http-parser release number to avoid people pulling EPEL package instead of RHEL package - Resolves: rhbz#1480321 + Resolves: rhbz#1479471 * Wed Feb 01 2017 Fabiano FidĂȘncio - 2.7.1-1 - Import spec file and patches from latest fc25 package