]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backport yet another security fix; if stream_cl exceeds the 'stated'
authorWilliam A. Rowe Jr <wrowe@apache.org>
Mon, 8 Aug 2005 01:10:20 +0000 (01:10 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Mon, 8 Aug 2005 01:10:20 +0000 (01:10 +0000)
  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

modules/proxy/proxy_http.c

index 0457cb87a39ba574d1e9de0d01157e90cce067dd..d76345e405b192c399b2d40f20d1fb4f80962e24 100644 (file)
@@ -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