]> granicus.if.org Git - apache/commitdiff
RFC2616 issue
authorJim Jagielski <jim@apache.org>
Tue, 17 Sep 2013 18:37:18 +0000 (18:37 +0000)
committerJim Jagielski <jim@apache.org>
Tue, 17 Sep 2013 18:37:18 +0000 (18:37 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1524161 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/log-message-tags/next-number
modules/http/http_filters.c
server/protocol.c

diff --git a/CHANGES b/CHANGES
index 5b82f041e45a72e05b1bf6914938b1a6ecf4d721..6a81e556a0a421a4214f21ba899b6144db51c0ec 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  * core: Fix RFC2616 compliance issue with 'identity' transfer-encoding.
+     [Yann Ylavic <ylavic.dev gmail com>, Jim Jagielski]
+
   *) WinNT MPM: If ap_run_pre_connection() fails or sets c->aborted, don't
      save the socket for reuse by the next worker as if it were an 
      APR_SO_DISCONNECTED socket. Restores 2.2 behavior. [Eric Covener]
index 6a5bdca5ee17a7a64ae46e06a55e3293fb9f23be..983711d6f2db911df8c65703989a914dedb3ea98 100644 (file)
@@ -1 +1 @@
-2536
+2540
index a4beb26bc947f605bc84f0a0b1d0fb1ee8f8050f..f708e02a62558d30dd793a7f09bce376639f3ecf 100644 (file)
@@ -227,19 +227,24 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
             if (!strcasecmp(tenc, "chunked")) {
                 ctx->state = BODY_CHUNK;
             }
-            /* test lenp, because it gives another case we can handle */
-            else if (!lenp) {
-                /* Something that isn't in HTTP, unless some future
-                 * edition defines new transfer encodings, is unsupported.
-                 */
+            /* RFC 2616 Section 4.4 states that if the message does
+             * include a non-identity transfer-coding, the Content-Length
+             * MUST be ignored.
+             */
+            else if (lenp) {
                 ap_log_rerror(
-                        APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01585) "Unknown Transfer-Encoding: %s", tenc);
-                return APR_ENOTIMPL;
+                        APLOG_MARK, APLOG_INFO, 0, f->r,
+                        APLOGNO(01586) "Identity or Unknown Transfer-Encoding (%s); using Content-Length", tenc);
+                tenc = NULL;
             }
             else {
-                ap_log_rerror(
-                        APLOG_MARK, APLOG_WARNING, 0, f->r, APLOGNO(01586) "Unknown Transfer-Encoding: %s; using Content-Length", tenc);
-                tenc = NULL;
+                /* Something that isn't in HTTP, unless some future
+                 * edition defines new transfer encodings, is unsupported.
+                 */
+                    ap_log_rerror(
+                            APLOG_MARK, APLOG_INFO, 0, f->r,
+                            APLOGNO(01585) "Unknown Transfer-Encoding: %s", tenc);
+                    return APR_ENOTIMPL;
             }
         }
         if (lenp && !tenc) {
index c1ecae705bc9b1242912d3869530ddc1d367fef0..1a8aa447600bb98a96bd4429745bbd5a2b569e45 100644 (file)
@@ -1091,6 +1091,8 @@ request_rec *ap_read_request(conn_rec *conn)
     }
 
     if (!r->assbackwards) {
+        const char *tenc, *clen;
+
         ap_get_mime_headers_core(r, tmp_bb);
         if (r->status != HTTP_OK) {
             ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00567)
@@ -1102,13 +1104,37 @@ request_rec *ap_read_request(conn_rec *conn)
             goto traceout;
         }
 
-        if (apr_table_get(r->headers_in, "Transfer-Encoding")
-            && apr_table_get(r->headers_in, "Content-Length")) {
+        if ((tenc = apr_table_get(r->headers_in, "Transfer-Encoding"))) {
             /* 2616 section 4.4, point 3: "if both Transfer-Encoding
              * and Content-Length are received, the latter MUST be
-             * ignored"; so unset it here to prevent any confusion
-             * later. */
-            apr_table_unset(r->headers_in, "Content-Length");
+             * ignored"; unless the former is "identity". So unset
+             * the one concerned here to prevent any confusion later.
+             */
+            if ((clen = apr_table_get(r->headers_in, "Content-Length"))) {
+                if (strcasecmp(tenc, "chunked") == 0) {
+                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(2537)
+                                  "client sent both Transfer-Encoding (chunked)"
+                                  " and Content-Length; using TE");
+                    apr_table_unset(r->headers_in, "Content-Length");
+                }
+                else {
+                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(2538)
+                                  "client sent identity or unknown Transfer-Encoding (%s);"
+                                  " using Content-Length", tenc);
+                    apr_table_unset(r->headers_in, "Transfer-Encoding");
+                }
+            }
+            else if (strcasecmp(tenc, "chunked") != 0) {
+                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(2539)
+                              "client sent unknown Transfer-Encoding;"
+                              " not implemented: %s", tenc);
+                r->status = HTTP_NOT_IMPLEMENTED;
+                ap_send_error_response(r, 0);
+                ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+                ap_run_log_transaction(r);
+                apr_brigade_destroy(tmp_bb);
+                goto traceout;
+            }
         }
     }
     else {