#! /bin/sh /usr/share/dpatch/dpatch-run
## 214_CVE-2011-3368_part2.dpatch by Steve Beattie <sbeattie@ubuntu.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: CVE-2011-3368 for http 0.9 protocol
# Origin: http://svn.apache.org/viewvc?view=revision&revision=1100200
# Subject: RE: CVE-2011-3368 not fully fixed?
#
# [From http://marc.info/?l=apache-httpd-dev&m=131955975103801&w=2]
#
# I did some further analysis. While the patch for trunk is still fine
# as it shortens the path for bailing out the behaviour was already
# correct with trunk and 2.2.21. So the HTTP/0.9 behaviour you see does NOT happen
# with 2.2.x >= 2.2.18 (plus patch) and trunk. You are affected by an old logic
# that was changed in r1100200 and hence changed since 2.2.18.
#
# [Ubuntu note: patch differs from upstream by removing the differences to
#  the CHANGES and STATUS files to reduce the possibility of conflicts
#  -- sbeattie]
#
@DPATCH@
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' apache2-2.2.17~/modules/http/http_filters.c apache2-2.2.17/modules/http/http_filters.c
--- apache2-2.2.17~/modules/http/http_filters.c	2010-02-26 01:32:15.000000000 -0800
+++ apache2-2.2.17/modules/http/http_filters.c	2011-11-02 11:33:00.000000000 -0700
@@ -380,8 +380,13 @@
 
             /* Detect chunksize error (such as overflow) */
             if (rv != APR_SUCCESS || ctx->remaining < 0) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading first chunk %s ", 
+                              (ctx->remaining < 0) ? "(overflow)" : "");
                 ctx->remaining = 0; /* Reset it in case we have to
                                      * come back here later */
+                if (APR_STATUS_IS_TIMEUP(rv)) { 
+                    http_error = HTTP_REQUEST_TIME_OUT;
+                }
                 return bail_out_on_error(ctx, f, http_error);
             }
 
@@ -481,10 +486,14 @@
 
                 /* Detect chunksize error (such as overflow) */
                 if (rv != APR_SUCCESS || ctx->remaining < 0) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading chunk %s ", 
+                                  (ctx->remaining < 0) ? "(overflow)" : "");
                     ctx->remaining = 0; /* Reset it in case we have to
                                          * come back here later */
-                    bail_out_on_error(ctx, f, http_error);
-                    return rv;
+                    if (APR_STATUS_IS_TIMEUP(rv)) { 
+                        http_error = HTTP_REQUEST_TIME_OUT;
+                    }
+                    return bail_out_on_error(ctx, f, http_error);
                 }
 
                 if (!ctx->remaining) {
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' apache2-2.2.17~/server/protocol.c apache2-2.2.17/server/protocol.c
--- apache2-2.2.17~/server/protocol.c	2010-03-01 20:01:29.000000000 -0800
+++ apache2-2.2.17/server/protocol.c	2011-11-02 11:33:00.000000000 -0700
@@ -608,6 +608,9 @@
                 r->proto_num = HTTP_VERSION(1,0);
                 r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
             }
+            else if (rv == APR_TIMEUP) {
+                r->status = HTTP_REQUEST_TIME_OUT;
+            }
             return 0;
         }
     } while ((len <= 0) && (++num_blank_lines < max_blank_lines));
@@ -691,7 +694,12 @@
                          &len, r, 0, bb);
 
         if (rv != APR_SUCCESS) {
-            r->status = HTTP_BAD_REQUEST;
+            if (rv == APR_TIMEUP) {
+                r->status = HTTP_REQUEST_TIME_OUT;
+            }
+            else {
+                r->status = HTTP_BAD_REQUEST;
+            }
 
             /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
              * finding the end-of-line.  This is only going to happen if it
@@ -877,7 +885,7 @@
     r->read_length     = 0;
     r->read_body       = REQUEST_NO_BODY;
 
-    r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
+    r->status          = HTTP_OK;  /* Until further notice */
     r->the_request     = NULL;
 
     /* Begin by presuming any module can make its own path_info assumptions,
@@ -898,6 +906,14 @@
             apr_brigade_destroy(tmp_bb);
             return r;
         }
+        else if (r->status == HTTP_REQUEST_TIME_OUT) {
+            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+            if (!r->connection->keepalives) {
+                ap_run_log_transaction(r);
+            }
+            apr_brigade_destroy(tmp_bb);
+            return r;
+        }
 
         apr_brigade_destroy(tmp_bb);
         return NULL;
@@ -916,7 +932,7 @@
 
     if (!r->assbackwards) {
         ap_get_mime_headers_core(r, tmp_bb);
-        if (r->status != HTTP_REQUEST_TIME_OUT) {
+        if (r->status != HTTP_OK) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                           "request failed: error reading the headers");
             ap_send_error_response(r, 0);
@@ -957,8 +973,6 @@
 
     apr_brigade_destroy(tmp_bb);
 
-    r->status = HTTP_OK;                         /* Until further notice. */
-
     /* update what we think the virtual host is based on the headers we've
      * now read. may update status.
      */
