[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