From: Mladen Turk Date: Thu, 18 Sep 2008 09:35:30 +0000 (+0000) Subject: Always send body (zero size at least) whenever C-L is present in the request X-Git-Tag: 2.3.0~295 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2eac3620194b9b465e8010714e5c3a0e8114dfc;p=apache Always send body (zero size at least) whenever C-L is present in the request git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@696614 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 787acdd80e..0a3a5c9d89 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,14 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) mod_proxy_ajp: Fix wrongly formatted requests where client + sets Content-Length header, but doesn't provide a body. + Servlet container always expects that next packet is + body whenever C-L is present in the headers. This can lead + to wrong interpretation of the packets. In this case + send the empty body packet, so container can deal with + that. [Mladen Turk] + *) mod_authnz_ldap: don't return NULL-valued environment variables to other modules. PR 39045 [Francois Pesce ] diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c index 1627b8ffa7..3bd0dd7529 100644 --- a/modules/proxy/mod_proxy_ajp.c +++ b/modules/proxy/mod_proxy_ajp.c @@ -116,6 +116,27 @@ static int is_idempotent(request_rec *r) } } +static apr_off_t get_content_length(request_rec * r) +{ + apr_off_t len = 0; + + if (r->clength > 0) { + return r->clength; + } + else if (r->main == NULL || r->main == r) { + const char *clp = apr_table_get(r->headers_in, "Content-Length"); + + if (clp) { + char *errp; + if (apr_strtoff(&len, clp, &errp, 10) || *errp || len < 0) { + len = 0; /* parse error */ + } + } + } + + return len; +} + /* * XXX: AJP Auto Flushing * @@ -166,6 +187,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, ap_get_module_config(r->server->module_config, &proxy_module); apr_size_t maxsize = AJP_MSG_BUFFER_SZ; int send_body = 0; + apr_off_t content_length = 0; if (psf->io_buffer_size_set) maxsize = psf->io_buffer_size; @@ -221,6 +243,8 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: request is chunked"); } else { + /* Get client provided Content-Length header */ + content_length = get_content_length(r); status = ap_get_brigade(r->input_filters, input_brigade, AP_MODE_READBYTES, APR_BLOCK_READ, maxsize - AJP_HEADER_SZ); @@ -277,6 +301,27 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, conn->worker->s->transferred += bufsiz; send_body = 1; } + else if (content_length > 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, + "proxy: read zero bytes, expecting" + " %" APR_OFF_T_FMT " bytes", + content_length); + status = ajp_send_data_msg(conn->sock, msg, 0); + if (status != APR_SUCCESS) { + /* We had a failure: Close connection to backend */ + conn->close++; + ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, + "proxy: send failed to %pI (%s)", + conn->worker->cp->addr, + conn->worker->hostname); + return HTTP_INTERNAL_SERVER_ERROR; + } + else { + /* Client send zero bytes with C-L > 0 + */ + return HTTP_BAD_REQUEST; + } + } } /* read the response */