[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#639825: Apache2 seek broken



On Wednesday 31 August 2011, Takis Issaris wrote:

> Range: bytes=0-

I suspect that your client tries this first request, and when it sees 
the 200 instead of the 206, it assumes that the server doesn't support 
ranges at all.

Can you rebuild apache2 ...lenny10 with the attached patch and try if 
it fixes your problem? Thanks in advance.

Stefan

diff -u apache2-2.2.9/debian/changelog apache2-2.2.9/debian/changelog
--- apache2-2.2.9/debian/changelog
+++ apache2-2.2.9/debian/changelog
@@ -1,3 +1,9 @@
+apache2 (2.2.9-10+lenny10+sf1) UNRELEASED; urgency=low
+
+  * Try to fix #639825
+
+ -- Stefan Fritsch <sf@debian.org>  Thu, 01 Sep 2011 00:45:58 +0200
+
 apache2 (2.2.9-10+lenny10) lenny-security; urgency=high
 
   * Fix CVE-2011-3192: DoS by high memory usage for a large number of
diff -u apache2-2.2.9/debian/patches/082_CVE-2011-3192.dpatch apache2-2.2.9/debian/patches/082_CVE-2011-3192.dpatch
--- apache2-2.2.9/debian/patches/082_CVE-2011-3192.dpatch
+++ apache2-2.2.9/debian/patches/082_CVE-2011-3192.dpatch
@@ -7,8 +7,8 @@
 
 @DPATCH@
 diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' lenny-apache2~/modules/http/byterange_filter.c lenny-apache2/modules/http/byterange_filter.c
---- lenny-apache2~/modules/http/byterange_filter.c	2011-08-29 21:02:58.000000000 +0200
-+++ lenny-apache2/modules/http/byterange_filter.c	2011-08-29 21:03:26.877437934 +0200
+--- lenny-apache2~/modules/http/byterange_filter.c	2011-09-01 00:49:35.000000000 +0200
++++ lenny-apache2/modules/http/byterange_filter.c	2011-09-01 00:50:00.644199224 +0200
 @@ -55,65 +55,8 @@
  #include <unistd.h>
  #endif
@@ -77,7 +77,7 @@
  
  /*
   * Here we try to be compatible with clients that want multipart/x-byteranges
-@@ -131,28 +74,200 @@
+@@ -131,28 +74,214 @@
  }
  
  #define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT
@@ -251,6 +251,20 @@
 +    apr_off_t start;
 +    apr_off_t end;
 +} indexes_t;
++
++static apr_status_t send_416(ap_filter_t *f, apr_bucket_brigade *tmpbb)
++{
++    apr_bucket *e;
++    conn_rec *c = f->r->connection;
++    ap_remove_output_filter(f);
++    f->r->status = HTTP_OK;
++    e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
++                               f->r->pool, c->bucket_alloc);
++    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
++    e = apr_bucket_eos_create(c->bucket_alloc);
++    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
++    return ap_pass_brigade(f->next, tmpbb);
++}
  
  AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f,
                                                           apr_bucket_brigade *bb)
@@ -285,7 +299,7 @@
      for (e = APR_BRIGADE_FIRST(bb);
           (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e)
            && e->length != (apr_size_t)-1);
-@@ -160,90 +275,80 @@
+@@ -160,90 +289,84 @@
          clength += e->length;
      }
  
@@ -317,8 +331,13 @@
 -    ctx->num_ranges = num_ranges;
 -    /* create a brigade in case we never call ap_save_brigade() */
 -    ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
--
++    /* this brigade holds what we will be sending */
++    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
+ 
 -    if (ctx->num_ranges > 1) {
++    if (num_ranges < 0)
++        return send_416(f, bsend);
++
 +    if (num_ranges > 1) {
          /* Is ap_make_content_type required here? */
          const char *orig_ct = ap_make_content_type(r, r->content_type);
@@ -362,16 +381,16 @@
 +        ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
      }
  
-     /* this brigade holds what we will be sending */
-     bsend = apr_brigade_create(r->pool, c->bucket_alloc);
-+    tmpbb = apr_brigade_create(r->pool, c->bucket_alloc);
- 
+-    /* this brigade holds what we will be sending */
+-    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
+-
 -    while ((current = ap_getword(r->pool, &r->range, ','))
 -           && (rv = parse_byterange(current, clength, &range_start,
 -                                    &range_end))) {
 -        apr_bucket *e2;
 -        apr_bucket *ec;
--
++    tmpbb = apr_brigade_create(r->pool, c->bucket_alloc);
+ 
 -        if (rv == -1) {
 -            continue;
 -        }
@@ -411,7 +430,7 @@
              apr_table_setn(r->headers_out, "Content-Range",
                             apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
                                          range_start, range_end, clength));
-@@ -251,7 +356,7 @@
+@@ -251,7 +374,7 @@
          else {
              char *ts;
  
@@ -420,7 +439,7 @@
                                         r->pool, c->bucket_alloc);
              APR_BRIGADE_INSERT_TAIL(bsend, e);
  
-@@ -263,23 +368,19 @@
+@@ -263,42 +386,31 @@
              APR_BRIGADE_INSERT_TAIL(bsend, e);
          }
  
@@ -457,8 +476,16 @@
      }
  
      if (found == 0) {
-@@ -294,11 +395,11 @@
-         return ap_pass_brigade(f->next, bsend);
+-        ap_remove_output_filter(f);
+-        r->status = HTTP_OK;
+         /* bsend is assumed to be empty if we get here. */
+-        e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
+-                                   r->pool, c->bucket_alloc);
+-        APR_BRIGADE_INSERT_TAIL(bsend, e);
+-        e = apr_bucket_eos_create(c->bucket_alloc);
+-        APR_BRIGADE_INSERT_TAIL(bsend, e);
+-        return ap_pass_brigade(f->next, bsend);
++        return send_416(f, bsend);
      }
  
 -    if (ctx->num_ranges > 1) {
@@ -471,7 +498,7 @@
          ap_xlate_proto_to_ascii(end, strlen(end));
          e = apr_bucket_pool_create(end, strlen(end), r->pool, c->bucket_alloc);
          APR_BRIGADE_INSERT_TAIL(bsend, e);
-@@ -309,24 +410,32 @@
+@@ -309,24 +421,32 @@
  
      /* we're done with the original content - all of our data is in bsend. */
      apr_brigade_cleanup(bb);
@@ -491,7 +518,7 @@
      const char *ct;
 -    int num_ranges;
 +    char *cur;
-+    int num_ranges = 0;
++    int num_ranges = 0, unsatisfiable = 0;
 +    apr_off_t sum_lengths = 0;
 +    indexes_t *idx;
 +    int ranges = 1;
@@ -507,7 +534,7 @@
       * backwards-compatibility with second-draft Luotonen/Franks
       * byte-ranges (e.g. Netscape Navigator 2-3).
       *
-@@ -356,7 +465,8 @@
+@@ -356,7 +476,8 @@
         return 0;
      }
  
@@ -517,7 +544,7 @@
       * Note that this check will return false (as required) if either
       * of the two etags are weak.
       */
-@@ -373,17 +483,77 @@
+@@ -373,17 +494,90 @@
          }
      }
  
@@ -541,14 +568,22 @@
 +        char *errp;
 +        apr_off_t number, start, end;
 +
++	if (!*cur)
++	    break;
++
++        /*
++         * Per RFC 2616 14.35.1: If there is at least one syntactically invalid
++         * byte-range-spec, we must ignore the whole header.
++         */
++
 +        if (!(dash = strchr(cur, '-'))) {
-+            break;
++            return 0;
 +        }
 +
 +        if (dash == range) {
 +            /* In the form "-5" */
 +            if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
-+                break;
++                return 0;
 +            }
 +            start = clength - number;
 +            end = clength - 1;
@@ -556,14 +591,17 @@
 +        else {
 +            *dash++ = '\0';
 +            if (apr_strtoff(&number, cur, &errp, 10) || *errp) {
-+                break;
++                return 0;
 +            }
 +            start = number;
 +            if (*dash) {
 +                if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
-+                    break;
++                    return 0;
 +                }
 +                end = number;
++                if (start > end) {
++                    return 0;
++                }
 +            }
 +            else {                  /* "5-" */
 +                end = clength - 1;
@@ -573,15 +611,14 @@
 +        if (start < 0) {
 +            start = 0;
 +        }
++        if (start >= clength) {
++            unsatisfiable = 1;
++            continue;
++        }
 +        if (end >= clength) {
 +            end = clength - 1;
 +        }
 +
-+        if (start > end) {
-+            /* ignore? count? */
-+            break;
-+        }
-+
 +        idx = (indexes_t *)apr_array_push(*indexes);
 +        idx->start = start;
 +        idx->end = end;
@@ -589,10 +626,13 @@
 +        /* new set again */
 +        num_ranges++;
 +    }
-+
-+    if (sum_lengths >= clength) {
++    if (num_ranges == 0 && unsatisfiable) {
++        /* If all ranges are unsatisfiable, we should return 416 */
++        return -1;
++    }
++    if (sum_lengths > clength) {
 +        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-+                      "Sum of ranges not smaller than file, ignoring.");
++                      "Sum of ranges larger than file, ignoring.");
 +        return 0;
      }
  

Reply to: