]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: message parser: Allow duplicate date header if HTTP_MESSAGE_PARSE_FLAG_STRI...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 11 Jul 2017 12:34:06 +0000 (14:34 +0200)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Thu, 27 Jul 2017 13:12:03 +0000 (15:12 +0200)
The last instance of the date header is used.

src/lib-http/http-message-parser.c
src/lib-http/test-http-request-parser.c
src/lib-http/test-http-response-parser.c

index 6082f02181d113cd8a23df84d599240548338bc8..1972895054a8512deb110ef94f2b23a954ff7f13 100644 (file)
@@ -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
index 948ad86946b4cb81d220d14f223ab2df99531f45..1b77fdb7ce03bda73905c51394884c44a8369d5e 100644 (file)
@@ -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
 };
index 982da97878284db37cc7d6f8032248c468472e37..9f9f0886de99498942cc832efe157f4d8a4b0013 100644 (file)
@@ -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
        }
 };