]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
*) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
authorStefan Eissing <icing@apache.org>
Thu, 18 Jul 2019 12:31:01 +0000 (12:31 +0000)
committerStefan Eissing <icing@apache.org>
Thu, 18 Jul 2019 12:31:01 +0000 (12:31 +0000)
     merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1863276 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/http2/h2_stream.c

diff --git a/CHANGES b/CHANGES
index 7890098d2cf4fe2db4df6e70be1f346a7e4f6798..7eece02270f5f660b7a606bb45bd58e68d7a2eba 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
+     merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]
+
   *) mod_http2: fixed a bug that prevented proper stream cleanup when connection
      throttling was in place. Stream resets by clients on streams initiated by them
      are counted as possible trigger for throttling. [Stefan Eissing] 
index ddbf73b1e593bbf8f9118036d721374eb7b412be..1d97b3f2e86d2c42f4f7bea6dc770a8883ce6600 100644 (file)
@@ -398,12 +398,7 @@ apr_status_t h2_stream_send_frame(h2_stream *stream, int ftype, int flags, size_
                 ap_assert(stream->request == NULL);
                 ap_assert(stream->rtmp != NULL);
                 status = h2_stream_end_headers(stream, 1, 0);
-                if (status != APR_SUCCESS) {
-                    return status;
-                }
-                set_policy_for(stream, stream->rtmp);
-                stream->request = stream->rtmp;
-                stream->rtmp = NULL;
+                if (status != APR_SUCCESS) goto leave;
             break;
             
         default:
@@ -415,6 +410,7 @@ apr_status_t h2_stream_send_frame(h2_stream *stream, int ftype, int flags, size_
     if (status == APR_SUCCESS && eos) {
         status = transit(stream, on_event(stream, H2_SEV_CLOSED_L));
     }
+leave:
     return status;
 }
 
@@ -456,12 +452,7 @@ apr_status_t h2_stream_recv_frame(h2_stream *stream, int ftype, int flags, size_
                     return APR_EINVAL;
                 }
                 status = h2_stream_end_headers(stream, eos, frame_len);
-                if (status != APR_SUCCESS) {
-                    return status;
-                }
-                set_policy_for(stream, stream->rtmp);
-                stream->request = stream->rtmp;
-                stream->rtmp = NULL;
+                if (status != APR_SUCCESS) goto leave;
             }
             break;
             
@@ -472,6 +463,7 @@ apr_status_t h2_stream_recv_frame(h2_stream *stream, int ftype, int flags, size_
     if (status == APR_SUCCESS && eos) {
         status = transit(stream, on_event(stream, H2_SEV_CLOSED_R));
     }
+leave:
     return status;
 }
 
@@ -761,9 +753,45 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
     return status;
 }
 
+typedef struct {
+    apr_size_t maxlen;
+    const char *failed_key;
+} val_len_check_ctx;
+
+static int table_check_val_len(void *baton, const char *key, const char *value)
+{
+    val_len_check_ctx *ctx = baton;
+
+    if (strlen(value) <= ctx->maxlen) return 1;
+    ctx->failed_key = key;
+    return 0;
+}
+
 apr_status_t h2_stream_end_headers(h2_stream *stream, int eos, size_t raw_bytes)
 {
-    return h2_request_end_headers(stream->rtmp, stream->pool, eos, raw_bytes);
+    apr_status_t status;
+    val_len_check_ctx ctx;
+    
+    status = h2_request_end_headers(stream->rtmp, stream->pool, eos, raw_bytes);
+    if (APR_SUCCESS == status) {
+        set_policy_for(stream, stream->rtmp);
+        stream->request = stream->rtmp;
+        stream->rtmp = NULL;
+        
+        ctx.maxlen = stream->session->s->limit_req_fieldsize;
+        ctx.failed_key = NULL;
+        apr_table_do(table_check_val_len, &ctx, stream->request->headers, NULL);
+        if (ctx.failed_key) {
+            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, stream->session->c,  
+                          H2_STRM_LOG(APLOGNO(), stream,"Request header exceeds "
+                                      "LimitRequestFieldSize: %.*s"),
+                          (int)H2MIN(strlen(ctx.failed_key), 80), ctx.failed_key);
+            set_error_response(stream, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+            /* keep on returning APR_SUCCESS, so that we send a HTTP response and
+             * do not RST the stream. */
+        }
+    }
+    return status;
 }
 
 static apr_bucket *get_first_headers_bucket(apr_bucket_brigade *bb)