From 18a1da2913e751dba5df53db9ed144f556f537f6 Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" Date: Thu, 22 Dec 2016 22:25:14 +0000 Subject: [PATCH] Crossport: r1758672 Backports: r1710095, r1727544 Submitted by: ylavic, rpluem core: Limit to ten the number of tolerated empty lines between request, and consume them before the pipelining check to avoid possible response delay when reading the next request without flushing. Before this commit, the maximum number of empty lines was the same as configured LimitRequestFields, defaulting to 100, which was way too much. We now use a fixed/hard limit of 10 (DEFAULT_LIMIT_BLANK_LINES). check_pipeline() is changed to check for (up to the limit) and comsume the trailing [CR]LFs so that they won't be interpreted as pipelined requests, otherwise we would block on the next read without flushing data, and hence possibly delay pending response(s) until the next/real request comes in or the keepalive timeout expires. Finally, when the maximum number of empty line is reached in read_request_line(), or that request line does not contains at least a method and an (valid) URI, we can fail early and avoid some failure detected in further processing. Ensure that proto_num and protocol is set in another "error out early" edge case. This can happen with invalid CONNECT requests as described in the PR. PR: 58929 Borrow Yann's effort at cross-porting this to 2.2.x git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x-merge-http-strict@1775758 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ include/httpd.h | 4 ++++ server/protocol.c | 21 ++++++++++++++------- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 5557aba1965..1402bb1926a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.32 + *) core: Limit to ten the number of tolerated empty lines between request. + [Yann Ylavic] + *) Core: reject NULLs in request line or request headers. PR 43039 [Nick Kew] diff --git a/include/httpd.h b/include/httpd.h index 963d4acda49..5aa8a02e357 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -205,6 +205,10 @@ extern "C" { #ifndef DEFAULT_LIMIT_REQUEST_FIELDS #define DEFAULT_LIMIT_REQUEST_FIELDS 100 #endif +/** default/hard limit on number of leading/trailing empty lines */ +#ifndef DEFAULT_LIMIT_BLANK_LINES +#define DEFAULT_LIMIT_BLANK_LINES 10 +#endif /** * The default default character set name to add if AddDefaultCharset is diff --git a/server/protocol.c b/server/protocol.c index a2190b356e0..76c15838484 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -562,12 +562,7 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) unsigned int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */ char http[5]; apr_size_t len; - int num_blank_lines = 0; - int max_blank_lines = r->server->limit_req_fields; - - if (max_blank_lines <= 0) { - max_blank_lines = DEFAULT_LIMIT_REQUEST_FIELDS; - } + int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES; /* Read past empty lines until we get a real request line, * a read error, the connection closes (EOF), or we timeout. @@ -614,7 +609,7 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); return 0; } - } while ((len <= 0) && (++num_blank_lines < max_blank_lines)); + } while ((len <= 0) && (--num_blank_lines >= 0)); r->request_time = apr_time_now(); ll = r->the_request; @@ -622,6 +617,13 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) uri = ap_getword_white(r->pool, &ll); + if (!*r->method || !*uri) { + r->status = HTTP_BAD_REQUEST; + r->proto_num = HTTP_VERSION(1,0); + r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); + return 0; + } + /* Provide quick information about the request method as soon as known */ r->method_number = ap_method_number_of(r->method); @@ -630,6 +632,11 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) } ap_parse_uri(r, uri); + if (r->status != HTTP_OK) { + r->proto_num = HTTP_VERSION(1,0); + r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); + return 0; + } if (ll[0]) { r->assbackwards = 0; -- 2.47.2