From 1018ff992215e1e9271b2eb77cd878fa721fee65 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Thu, 6 Oct 2016 00:16:06 -0400 Subject: [PATCH] [core] server.max-request-field-size (fixes #2130) limits total size per request of request headers submitted by client default limit set to 8k (prior lighttpd <= 1.4.41 hard-coded 64k limit) (similar to Apache directive LimitRequestFieldSize) x-ref: "limits the size of HTTP request header" https://redmine.lighttpd.net/issues/2130 --- src/base.h | 1 + src/configfile.c | 2 ++ src/connections.c | 14 ++++++++------ src/server.c | 1 + 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/base.h b/src/base.h index 24de4a9f..0e4e7157 100644 --- a/src/base.h +++ b/src/base.h @@ -539,6 +539,7 @@ typedef struct { array *modules; array *upload_tempdirs; unsigned int upload_temp_file_size; + unsigned int max_request_field_size; unsigned short max_worker; unsigned short max_fds; diff --git a/src/configfile.c b/src/configfile.c index 01fcec33..26556108 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -122,6 +122,7 @@ static int config_insert(server *srv) { { "server.bsd-accept-filter", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 75 */ { "server.stream-request-body", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 76 */ { "server.stream-response-body", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 77 */ + { "server.max-request-field-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_SERVER }, /* 78 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -160,6 +161,7 @@ static int config_insert(server *srv) { cv[72].destination = &(srv->srvconf.http_header_strict); cv[73].destination = &(srv->srvconf.http_host_strict); cv[74].destination = &(srv->srvconf.http_host_normalize); + cv[78].destination = &(srv->srvconf.max_request_field_size); srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); diff --git a/src/connections.c b/src/connections.c index f3fe0737..0417a9f0 100644 --- a/src/connections.c +++ b/src/connections.c @@ -911,18 +911,20 @@ found_header_end: } connection_set_state(srv, con, CON_STATE_REQUEST_END); - } else if (chunkqueue_length(cq) > 64 * 1024) { - log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 414"); - - con->http_status = 414; /* Request-URI too large */ - con->keep_alive = 0; - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); } else if (is_closed) { /* the connection got closed and we didn't got enough data to leave CON_STATE_READ; * the only way is to leave here */ connection_set_state(srv, con, CON_STATE_ERROR); } + if ((last_chunk ? buffer_string_length(con->request.request) : (size_t)chunkqueue_length(cq)) + > srv->srvconf.max_request_field_size) { + log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 431"); + con->http_status = 431; /* Request Header Fields Too Large */ + con->keep_alive = 0; + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); + } + chunkqueue_remove_finished_chunks(cq); return 0; diff --git a/src/server.c b/src/server.c index a803bda1..68042532 100644 --- a/src/server.c +++ b/src/server.c @@ -281,6 +281,7 @@ static server *server_init(void) { srv->srvconf.http_host_strict = 1; /*(implies http_host_normalize)*/ srv->srvconf.http_host_normalize = 0; srv->srvconf.high_precision_timestamps = 0; + srv->srvconf.max_request_field_size = 8192; /* use syslog */ srv->errorlog_fd = STDERR_FILENO;