[tomcat7] 05/06: Fixed CVE-2014-0227: Add an error flag in ChunkedInputFilter to allow subsequent attempts at reading after an error to fail fast

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Mon Jan 11 10:16:29 UTC 2016


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch wheezy
in repository tomcat7.

commit 9907927b53a48a68cc6f04b76097650e0ad1ba4f
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Fri Jan 8 11:58:02 2016 +0100

    Fixed CVE-2014-0227: Add an error flag in ChunkedInputFilter to allow subsequent attempts at reading after an error to fail fast
---
 debian/changelog                   |   4 +
 debian/patches/CVE-2014-0227.patch | 213 +++++++++++++++++++++++++++++++++++++
 debian/patches/series              |   1 +
 3 files changed, 218 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 769891d..061daa3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,6 +13,10 @@ tomcat7 (7.0.28-4+deb7u3) wheezy-security; urgency=high
     could enable the streaming of an unlimited amount of data to the server,
     bypassing the various size limits enforced on a request. This enabled
     a denial of service attack.
+  * Fixed CVE-2014-0227: Add an error flag in ChunkedInputFilter to allow
+    subsequent attempts at reading after an error to fail fast. This prevents
+    remote attackers from conducting HTTP request smuggling attacks or causing
+    a denial of service by streaming data with malformed chunked requests.
 
  -- Emmanuel Bourg <ebourg at apache.org>  Mon, 04 Jan 2016 12:03:34 +0100
 
diff --git a/debian/patches/CVE-2014-0227.patch b/debian/patches/CVE-2014-0227.patch
new file mode 100644
index 0000000..66e72b3
--- /dev/null
+++ b/debian/patches/CVE-2014-0227.patch
@@ -0,0 +1,213 @@
+Description: CVE-2014-0227: Add an error flag in ChunkedInputFilter to allow subsequent
+ attempts at reading after an error to fail fast. This prevents remote attackers from
+ conducting HTTP request smuggling attacks or causing a denial of service by streaming
+ data with malformed chunked requests.
+Origin: backport, https://svn.apache.org/r1601333
+--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
++++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+@@ -29,6 +29,7 @@
+ import org.apache.tomcat.util.buf.HexUtils;
+ import org.apache.tomcat.util.buf.MessageBytes;
+ import org.apache.tomcat.util.http.MimeHeaders;
++import org.apache.tomcat.util.res.StringManager;
+ 
+ /**
+  * Chunked input filter. Parses chunked data according to
+@@ -39,6 +40,8 @@
+  */
+ public class ChunkedInputFilter implements InputFilter {
+ 
++    private static final StringManager sm = StringManager.getManager(
++            ChunkedInputFilter.class.getPackage().getName());
+ 
+     // -------------------------------------------------------------- Constants
+ 
+@@ -135,6 +138,11 @@
+      */
+     private long extensionSize;
+ 
++    /**
++     * Flag that indicates if an error has occurred.
++     */
++    private boolean error;
++
+ 
+     // ----------------------------------------------------------- Constructors
+     public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
+@@ -162,6 +170,8 @@
+         if (endChunk)
+             return -1;
+ 
++        checkError();
++
+         if(needCRLFParse) {
+             needCRLFParse = false;
+             parseCRLF(false);
+@@ -169,7 +179,7 @@
+ 
+         if (remaining <= 0) {
+             if (!parseChunkHeader()) {
+-                throw new IOException("Invalid chunk header");
++                throwIOException(sm.getString("chunkedInputFilter.invalidHeader"));
+             }
+             if (endChunk) {
+                 parseEndChunk();
+@@ -180,7 +190,9 @@
+         int result = 0;
+ 
+         if (pos >= lastValid) {
+-            readBytes();
++            if (readBytes() < 0) {
++                throwIOException(sm.getString("chunkedInputFilter.eos"));
++            }
+         }
+ 
+         if (remaining > (lastValid - pos)) {
+@@ -269,6 +281,7 @@
+         trailingHeaders.recycle();
+         trailingHeaders.setLimit(maxTrailerSize);
+         extensionSize = 0;
++        error = false;
+     }
+ 
+ 
+@@ -351,7 +364,7 @@
+                 // validated. Currently it is simply ignored.
+                 extensionSize++;
+                 if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
+-                    throw new IOException("maxExtensionSize exceeded");
++                    throwIOException(sm.getString("chunkedInputFilter.maxExtension"));
+                 }
+             }
+ 
+@@ -403,19 +416,19 @@
+ 
+             if (pos >= lastValid) {
+                 if (readBytes() <= 0)
+-                    throw new IOException("Invalid CRLF");
++                    throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoData"));
+             }
+ 
+             if (buf[pos] == Constants.CR) {
+-                if (crfound) throw new IOException("Invalid CRLF, two CR characters encountered.");
++                if (crfound) throwIOException(sm.getString("chunkedInputFilter.invalidCrlfCRCR"));
+                 crfound = true;
+             } else if (buf[pos] == Constants.LF) {
+                 if (!tolerant && !crfound) {
+-                    throw new IOException("Invalid CRLF, no CR character encountered.");
++                    throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoCR"));
+                 }
+                 eol = true;
+             } else {
+-                throw new IOException("Invalid CRLF");
++                throwIOException(sm.getString("chunkedInputFilter.invalidCrlf"));
+             }
+ 
+             pos++;
+@@ -445,7 +458,7 @@
+         // Read new bytes if needed
+         if (pos >= lastValid) {
+             if (readBytes() <0)
+-                throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
++                throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
+         }
+     
+         chr = buf[pos];
+@@ -470,7 +483,7 @@
+             // Read new bytes if needed
+             if (pos >= lastValid) {
+                 if (readBytes() <0)
+-                    throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
++                    throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
+             }
+     
+             chr = buf[pos];
+@@ -511,7 +524,7 @@
+                 // Read new bytes if needed
+                 if (pos >= lastValid) {
+                     if (readBytes() <0)
+-                        throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
++                        throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
+                 }
+     
+                 chr = buf[pos];
+@@ -521,7 +534,7 @@
+                     // limit placed on trailing header size
+                     int newlimit = trailingHeaders.getLimit() -1;
+                     if (trailingHeaders.getEnd() > newlimit) {
+-                        throw new IOException("Exceeded maxTrailerSize");
++                        throwIOException(sm.getString("chunkedInputFilter.maxTrailer"));
+                     }
+                     trailingHeaders.setLimit(newlimit);
+                 } else {
+@@ -536,7 +549,7 @@
+                 // Read new bytes if needed
+                 if (pos >= lastValid) {
+                     if (readBytes() <0)
+-                        throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
++                        throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
+                 }
+     
+                 chr = buf[pos];
+@@ -561,7 +574,7 @@
+             // Read new bytes if needed
+             if (pos >= lastValid) {
+                 if (readBytes() <0)
+-                    throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
++                    throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
+             }
+     
+             chr = buf[pos];
+@@ -582,4 +595,23 @@
+     
+         return true;
+     }
++
++
++    private void throwIOException(String msg) throws IOException {
++        error = true;
++        throw new IOException(msg);
++    }
++
++
++    private void throwEOFException(String msg) throws IOException {
++        error = true;
++        throw new EOFException(msg);
++    }
++
++
++    private void checkError() throws IOException {
++        if (error) {
++            throw new IOException(sm.getString("chunkedInputFilter.error"));
++        }
++    }
+ }
+--- /dev/null
++++ b/java/org/apache/coyote/http11/filters/LocalStrings.properties
+@@ -0,0 +1,25 @@
++# Licensed to the Apache Software Foundation (ASF) under one or more
++# contributor license agreements.  See the NOTICE file distributed with
++# this work for additional information regarding copyright ownership.
++# The ASF licenses this file to You under the Apache License, Version 2.0
++# (the "License"); you may not use this file except in compliance with
++# the License.  You may obtain a copy of the License at
++#
++#     http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++chunkedInputFilter.error=No data available due to previous error
++chunkedInputFilter.eos=Unexpected end of stream while reading request body
++chunkedInputFilter.eosTrailer=Unexpected end of stream while reading trailer headers
++chunkedInputFilter.invalidCrlf=Invalid end of line sequence (character other than CR or LF found)
++chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR)
++chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF)
++chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read)
++chunkedInputFilter.invalidHeader=Invalid chunk header
++chunkedInputFilter.maxExtension=maxExtensionSize exceeded
++chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
+\ No newline at end of file
diff --git a/debian/patches/series b/debian/patches/series
index b0add1f..9a2673f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -25,3 +25,4 @@ CVE-2014-7810.patch
 CVE-2014-0099.patch
 CVE-2013-4444.patch
 CVE-2014-0075.patch
+CVE-2014-0227.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/tomcat7.git



More information about the pkg-java-commits mailing list