changeset 9242:ddcedfa3a809

HTTP: just one empty line now accepted when parsing request line. This ensures that multiple CRLFs cannot be used as a DoS vector, and also in line with RFC 9112 ("SHOULD ignore at least one empty line"). Further, bare CRs are no longer accepted.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 30 Mar 2024 05:10:40 +0300
parents 07ca679842de
children 2956b59565c9
files src/http/ngx_http_parse.c src/http/ngx_http_request.c
diffstat 2 files changed, 28 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -106,6 +106,8 @@ ngx_http_parse_request_line(ngx_http_req
     u_char  c, ch, *p, *m;
     enum {
         sw_start = 0,
+        sw_newline,
+        sw_method_start,
         sw_method,
         sw_spaces_before_uri,
         sw_schema,
@@ -143,7 +145,13 @@ ngx_http_parse_request_line(ngx_http_req
         case sw_start:
             r->request_start = p;
 
-            if (ch == CR || ch == LF) {
+            if (ch == CR) {
+                state = sw_newline;
+                break;
+            }
+
+            if (ch == LF) {
+                state = sw_method_start;
                 break;
             }
 
@@ -154,6 +162,25 @@ ngx_http_parse_request_line(ngx_http_req
             state = sw_method;
             break;
 
+        case sw_newline:
+
+            if (ch == LF) {
+                state = sw_method_start;
+                break;
+            }
+
+            return NGX_HTTP_PARSE_INVALID_REQUEST;
+
+        case sw_method_start:
+            r->request_start = p;
+
+            if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+
+            state = sw_method;
+            break;
+
         case sw_method:
             if (ch == ' ') {
                 r->method_end = p - 1;
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1623,16 +1623,6 @@ ngx_http_alloc_large_header_buffer(ngx_h
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http alloc large header buffer");
 
-    if (request_line && r->state == 0) {
-
-        /* the client fills up the buffer with "\r\n" */
-
-        r->header_in->pos = r->header_in->start;
-        r->header_in->last = r->header_in->start;
-
-        return NGX_OK;
-    }
-
     old = request_line ? r->request_start : r->header_name_start;
 
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);