summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam A. Rowe Jr <wrowe@apache.org>2005-08-08 01:10:20 +0000
committerWilliam A. Rowe Jr <wrowe@apache.org>2005-08-08 01:10:20 +0000
commit26a9da60c4291dd590e8cf38e64b4a895464905e (patch)
treefa191e12a000f10cb48815a74fecc9a654cbf01d
parentafbee3617611a6663f8cbafcae4279c81f7eeabe (diff)
downloadhttpd-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.c26
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