diff --git a/CVE-2022-41556.patch b/CVE-2022-41556.patch new file mode 100644 index 0000000000000000000000000000000000000000..f08206b63fc298d53f109fe8a715700dd8bc406e --- /dev/null +++ b/CVE-2022-41556.patch @@ -0,0 +1,194 @@ +From bcddbe186f010e2964f7551141c0b8350b36817d Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Sat, 22 Feb 2020 16:57:10 -0500 +Subject: [PATCH] [mod_proxy] stream request using HTTP/1.1 chunked (fixes + #3006) + +stream request body using HTTP/1.1 Transfer-Encoding: chunked + +(Note: if backend proxy target does not support HTTP/1.1, + then do not use server.stream-request-body = 1 or 2) + +If not streaming to backend, collect request body +(now supporting Transfer-Encoding: chunked from client + and then sending with Content-Length to backend) + +x-ref: + "Lighty returns HTTP 411 Length Required with proxy and streaming requests/reponses body" + https://redmine.lighttpd.net/issues/3006 +--- + src/gw_backend.c | 35 +++++++++++++++----------------- + src/http-header-glue.c | 8 -------- + src/mod_cgi.c | 4 +++- + src/mod_proxy.c | 46 +++++++++++++++++++++++++++++++++++++++++- + 4 files changed, 64 insertions(+), 29 deletions(-) + +diff --git a/src/gw_backend.c b/src/gw_backend.c +index d8b880868..aa98a8e48 100644 +--- a/src/gw_backend.c ++++ b/src/gw_backend.c +@@ -2052,43 +2052,40 @@ handler_t gw_handle_subrequest(request_st * const r, void *p_d) { + } + else { + handler_t rc = connection_handle_read_post_state(r); +- chunkqueue *req_cq = r->reqbody_queue; +- #if 0 /*(not reached since we send 411 Length Required below)*/ ++ ++ /* XXX: create configurable flag */ ++ /* CGI environment requires that Content-Length be set. ++ * Send 411 Length Required if Content-Length missing. ++ * (occurs here if client sends Transfer-Encoding: chunked ++ * and module is flagged to stream request body to backend) */ ++ if (-1 == r->reqbody_length && hctx->opts.backend != BACKEND_PROXY){ ++ return (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST) ++ ? connection_handle_read_post_error(r, 411) ++ : HANDLER_WAIT_FOR_EVENT; ++ } ++ + if (hctx->wb_reqlen < -1 && r->reqbody_length >= 0) { + /* (completed receiving Transfer-Encoding: chunked) */ +- hctx->wb_reqlen = -hctx->wb_reqlen + r->reqbody_length; ++ hctx->wb_reqlen = -hctx->wb_reqlen; + if (hctx->stdin_append) { + handler_t rca = hctx->stdin_append(hctx); + if (HANDLER_GO_ON != rca) return rca; + } + } +- #endif ++ + if ((0 != hctx->wb->bytes_in || -1 == hctx->wb_reqlen) +- && !chunkqueue_is_empty(req_cq)) { ++ && !chunkqueue_is_empty(r->reqbody_queue)) { + if (hctx->stdin_append) { + handler_t rca = hctx->stdin_append(hctx); + if (HANDLER_GO_ON != rca) return rca; + } + else +- chunkqueue_append_chunkqueue(hctx->wb, req_cq); ++ chunkqueue_append_chunkqueue(hctx->wb, r->reqbody_queue); + if (fdevent_fdnode_interest(hctx->fdn) & FDEVENT_OUT) { + return (rc == HANDLER_GO_ON) ? HANDLER_WAIT_FOR_EVENT : rc; + } + } + if (rc != HANDLER_GO_ON) return rc; +- +- +- /* XXX: create configurable flag */ +- /* CGI environment requires that Content-Length be set. +- * Send 411 Length Required if Content-Length missing. +- * (occurs here if client sends Transfer-Encoding: chunked +- * and module is flagged to stream request body to backend) */ +- /* proxy currently sends HTTP/1.0 request and ideally should send +- * Content-Length with request if request body is present, so +- * send 411 Length Required if Content-Length missing. */ +- if (-1 == r->reqbody_length) { +- return connection_handle_read_post_error(r, 411); +- } + } + } + +diff --git a/src/http-header-glue.c b/src/http-header-glue.c +index 72a328e71..cf77ae1a8 100644 +--- a/src/http-header-glue.c ++++ b/src/http-header-glue.c +@@ -1036,14 +1036,6 @@ static int http_response_process_headers(request_st * const r, http_response_opt + r->content_length = strtoul(value, NULL, 10); + break; + case HTTP_HEADER_TRANSFER_ENCODING: +- if (opts->backend == BACKEND_PROXY) { +- log_error(r->conf.errh, __FILE__, __LINE__, +- "proxy backend sent invalid response header " +- "(Transfer-Encoding) to HTTP/1.0 request"); +- r->http_status = 502; /* Bad Gateway */ +- r->handler_module = NULL; +- return -1; +- } + break; + default: + break; +diff --git a/src/mod_cgi.c b/src/mod_cgi.c +index 5e14df178..78e89ce8f 100644 +--- a/src/mod_cgi.c ++++ b/src/mod_cgi.c +@@ -982,7 +982,9 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { + * (occurs here if client sends Transfer-Encoding: chunked + * and module is flagged to stream request body to backend) */ + if (-1 == r->reqbody_length) { +- return connection_handle_read_post_error(r, 411); ++ return (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST) ++ ? connection_handle_read_post_error(r, 411) ++ : HANDLER_WAIT_FOR_EVENT; + } + } + } +diff --git a/src/mod_proxy.c b/src/mod_proxy.c +index 31a4f930b..e0d2cf5e7 100644 +--- a/src/mod_proxy.c ++++ b/src/mod_proxy.c +@@ -813,6 +813,42 @@ static void proxy_set_Forwarded(connection * const con, request_st * const r, co + } + + ++static handler_t proxy_stdin_append(gw_handler_ctx *hctx) { ++ /*handler_ctx *hctx = (handler_ctx *)gwhctx;*/ ++ chunkqueue * const req_cq = hctx->r->reqbody_queue; ++ const off_t req_cqlen = req_cq->bytes_in - req_cq->bytes_out; ++ if (req_cqlen) { ++ /* XXX: future: use http_chunk_len_append() */ ++ buffer * const tb = hctx->r->tmp_buf; ++ buffer_clear(tb); ++ buffer_append_uint_hex_lc(tb, (uintmax_t)req_cqlen); ++ buffer_append_string_len(tb, CONST_STR_LEN("\r\n")); ++ ++ const off_t len = (off_t)buffer_string_length(tb) ++ + 2 /*(+2 end chunk "\r\n")*/ ++ + req_cqlen; ++ if (-1 != hctx->wb_reqlen) ++ hctx->wb_reqlen += (hctx->wb_reqlen >= 0) ? len : -len; ++ ++ (chunkqueue_is_empty(hctx->wb) || hctx->wb->first->type == MEM_CHUNK) ++ /* else FILE_CHUNK for temp file */ ++ ? chunkqueue_append_mem(hctx->wb, CONST_BUF_LEN(tb)) ++ : chunkqueue_append_mem_min(hctx->wb, CONST_BUF_LEN(tb)); ++ chunkqueue_steal(hctx->wb, req_cq, req_cqlen); ++ ++ chunkqueue_append_mem_min(hctx->wb, CONST_STR_LEN("\r\n")); ++ } ++ ++ if (hctx->wb->bytes_in == hctx->wb_reqlen) {/*hctx->r->reqbody_length >= 0*/ ++ /* terminate STDIN */ ++ chunkqueue_append_mem(hctx->wb, CONST_STR_LEN("0\r\n\r\n")); ++ hctx->wb_reqlen += (int)sizeof("0\r\n\r\n"); ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++ + static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { + handler_ctx *hctx = (handler_ctx *)gwhctx; + request_st * const r = hctx->gw.r; +@@ -831,7 +867,13 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { + buffer_append_string_buffer(b, &r->target); + if (remap_headers) + http_header_remap_uri(b, buffer_string_length(b) - buffer_string_length(&r->target), &hctx->conf.header, 1); +- if (!upgrade) ++ ++ int stream_chunked = 0; ++ if (-1 == r->reqbody_length && r->conf.stream_request_body) { ++ stream_chunked = 1; ++ hctx->gw.stdin_append = proxy_stdin_append; ++ } ++ if (!stream_chunked && !upgrade) + buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0\r\n")); + else + buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.1\r\n")); +@@ -869,6 +911,8 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { + buf, li_itostrn(buf, sizeof(buf), r->reqbody_length)); + } + } ++ else if (stream_chunked) ++ buffer_append_string_len(b, CONST_STR_LEN("Transfer-Encoding: chunked\r\n")); + + /* request header */ + for (size_t i = 0, used = r->rqst_headers.used; i < used; ++i) { diff --git a/lighttpd.spec b/lighttpd.spec index 51b6b047564ff44ab94787c686cb6291d63eb058..5f6d720fb6463d385f4b1ab3109caad3258c3f35 100644 --- a/lighttpd.spec +++ b/lighttpd.spec @@ -20,7 +20,7 @@ Summary: Lightning fast webserver with light system requirements Name: lighttpd Version: 1.4.56 -Release: 2 +Release: 3 License: BSD-3-Clause and OML and GPLv3 and GPLv2 URL: https://github.com/lighttpd/lighttpd1.4 Source0: http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-%{version}.tar.gz @@ -31,6 +31,7 @@ Source4: lighttpd.service Patch0: lighttpd-1.4.56-defaultconf.patch Patch1: CVE-2022-22707.patch Patch2: CVE-2022-37797.patch +Patch3: CVE-2022-41556.patch Requires: %{name}-filesystem %if %{with systemd} Requires(post): systemd @@ -110,6 +111,7 @@ for the directories. %patch0 -p0 -b .defaultconf %patch1 -p1 %patch2 -p1 +%patch3 -p1 %build autoreconf -if @@ -256,6 +258,9 @@ fi %attr(0700, lighttpd, lighttpd) %dir %{webroot}/ %changelog +* Mon Oct 10 2022 guofengjie -1:1.4.56-3 +- Fix CVE-2022-41556 + * Fri Sep 30 2022 yaoxin - 1.4.56-2 - Fix excuting systemctl start lighttpd.service error