diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2005-08-08 01:10:20 +0000 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2005-08-08 01:10:20 +0000 |
commit | 26a9da60c4291dd590e8cf38e64b4a895464905e (patch) | |
tree | fa191e12a000f10cb48815a74fecc9a654cbf01d | |
parent | afbee3617611a6663f8cbafcae4279c81f7eeabe (diff) | |
download | httpd-26a9da60c4291dd590e8cf38e64b4a895464905e.tar.gz |
Backport yet another security fix; if stream_cl exceeds the 'stated'
CL which proxy_request_body asked us to send, then we have to quit
forwarding any more bytes (we won't even pass the header if we
hadn't yet.)
Closes an HTTP Request splitting edge case.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/proxy-reqbody-2.0.x@230722 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | modules/proxy/proxy_http.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index 0457cb87a3..d76345e405 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -570,9 +570,13 @@ static apr_status_t stream_reqbody_cl(apr_pool_t *p, apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc; apr_bucket_brigade *b; apr_bucket *e; + apr_off_t cl_val = 0; + apr_off_t bytes; + apr_off_t bytes_streamed = 0; if (old_cl_val) { add_cl(p, bucket_alloc, header_brigade, old_cl_val); + cl_val = atol(old_cl_val); } terminate_headers(bucket_alloc, header_brigade); @@ -585,6 +589,9 @@ static apr_status_t stream_reqbody_cl(apr_pool_t *p, return status; } + apr_brigade_length(input_brigade, 1, &bytes); + bytes_streamed += bytes; + /* If this brigade contains EOS, either stop or remove it. */ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { seen_eos = 1; @@ -601,6 +608,18 @@ static apr_status_t stream_reqbody_cl(apr_pool_t *p, apr_bucket_delete(e); } + /* C-L < bytes streamed?!? + * We will error out after the body is completely + * consumed, but we can't stream more bytes at the + * back end since they would in part be interpreted + * as another request! If nothing is sent, then + * just send nothing. + * + * Prevents HTTP Response Splitting. + */ + if (bytes_streamed > cl_val) + continue; + if (header_brigade) { /* we never sent the header brigade, so go ahead and * take care of that now @@ -619,6 +638,13 @@ static apr_status_t stream_reqbody_cl(apr_pool_t *p, } } while (!seen_eos); + if (bytes_streamed != cl_val) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "proxy: client %s given Content-Length did not match" + " number of body bytes read", r->connection->remote_ip); + return APR_EOF; + } + if (header_brigade) { /* we never sent the header brigade since there was no request * body; send it now |