diff --git a/src/lib-http/http-message-parser.c b/src/lib-http/http-message-parser.c index 6082f02181..1972895054 100644 --- a/src/lib-http/http-message-parser.c +++ b/src/lib-http/http-message-parser.c @@ -193,6 +193,8 @@ http_message_parse_header(struct http_message_parser *parser, /* Content-Length: */ if (strcasecmp(name, "Content-Length") == 0) { if (parser->msg.have_content_length) { + /* There is no acceptable way to allow duplicates for this + header. */ parser->error = "Duplicate Content-Length header"; parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE; return -1; @@ -215,9 +217,12 @@ http_message_parse_header(struct http_message_parser *parser, /* Date: */ if (strcasecmp(name, "Date") == 0) { if (parser->msg.date != (time_t)-1) { - parser->error = "Duplicate Date header"; - parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE; - return -1; + if ((parser->flags & HTTP_MESSAGE_PARSE_FLAG_STRICT) != 0) { + parser->error = "Duplicate Date header"; + parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE; + return -1; + } + /* Allow the duplicate; last instance is used */ } /* RFC 7231, Section 7.1.1.2: Date diff --git a/src/lib-http/test-http-request-parser.c b/src/lib-http/test-http-request-parser.c index 948ad86946..1b77fdb7ce 100644 --- a/src/lib-http/test-http-request-parser.c +++ b/src/lib-http/test-http-request-parser.c @@ -137,6 +137,19 @@ valid_request_parse_tests[] = { }, .version_major = 1, .version_minor = 1, .expect_100_continue = TRUE + },{ .request = + "GET / HTTP/1.1\r\n" + "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n" + "Host: example.com\r\n" + "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n" + "\r\n", + .method = "GET", + .target_raw = "/", + .target = { + .format = HTTP_REQUEST_TARGET_FORMAT_ORIGIN, + .url = { .host_name = "example.com" } + }, + .version_major = 1, .version_minor = 1, } }; @@ -354,6 +367,15 @@ invalid_request_parse_tests[] = { "Transfer-Encoding: cuneiform, chunked\r\n" "\r\n", .error_code = HTTP_REQUEST_PARSE_ERROR_NOT_IMPLEMENTED + },{ + .request = + "GET / HTTP/1.1\r\n" + "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n" + "Host: example.com\r\n" + "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n" + "\r\n", + .flags = HTTP_REQUEST_PARSE_FLAG_STRICT, + .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST } // FIXME: test request limits }; diff --git a/src/lib-http/test-http-response-parser.c b/src/lib-http/test-http-response-parser.c index 982da97878..9f9f0886de 100644 --- a/src/lib-http/test-http-response-parser.c +++ b/src/lib-http/test-http-response-parser.c @@ -53,6 +53,13 @@ static const struct valid_parse_test_response valid_responses3[] = { } }; +static const struct valid_parse_test_response valid_responses4[] = { + { + .status = 200, + .payload = "Duplicate headers" + } +}; + static const struct valid_parse_test valid_response_parse_tests[] = { { .input = @@ -114,6 +121,20 @@ valid_response_parse_tests[] = { "Frop!", .responses = valid_responses3, .responses_count = N_ELEMENTS(valid_responses3) + },{ + .input = + "HTTP/1.1 200 OK\r\n" + "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n" + "Server: Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze14\r\n" + "Content-Length: 17\r\n" + "Keep-Alive: timeout=15, max=99\r\n" + "Connection: Keep-Alive\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n" + "\r\n" + "Duplicate headers", + .responses = valid_responses4, + .responses_count = N_ELEMENTS(valid_responses4) } }; @@ -239,6 +260,19 @@ static struct invalid_parse_test invalid_response_parse_tests[] = { "HTTP/1.1 302 Found\n\r" "Location: http://www.example.nl/\n\r" "Cache-Control: private\n\r" + },{ + .input = + "HTTP/1.1 200 OK\r\n" + "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n" + "Server: Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze14\r\n" + "Content-Length: 17\r\n" + "Keep-Alive: timeout=15, max=99\r\n" + "Connection: Keep-Alive\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n" + "\r\n" + "Duplicate headers", + .flags = HTTP_RESPONSE_PARSE_FLAG_STRICT } };