[Git][java-team/tomcat9][buster] 3 commits: Fix CVE-2021-33037 and CVE-2021-30640

Markus Koschany (@apo) gitlab at salsa.debian.org
Sun Aug 8 14:19:00 BST 2021



Markus Koschany pushed to branch buster at Debian Java Maintainers / tomcat9


Commits:
f6ccb1fb by Markus Koschany at 2021-08-07T18:23:23+02:00
Fix CVE-2021-33037 and CVE-2021-30640

- - - - -
2799bf6b by Markus Koschany at 2021-08-07T18:44:11+02:00
Update changelog and patch headers

- - - - -
0ce07f71 by Markus Koschany at 2021-08-07T18:52:17+02:00
Fix failing test

- - - - -


4 changed files:

- debian/changelog
- + debian/patches/CVE-2021-30640.patch
- + debian/patches/CVE-2021-33037.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,9 +1,27 @@
+tomcat9 (9.0.31-1~deb10u5) buster-security; urgency=high
+
+  * Team upload.
+  * Fix CVE-2021-30640:
+    A vulnerability in the JNDI Realm of Apache Tomcat allows an attacker to
+    authenticate using variations of a valid user name and/or to bypass some of
+    the protection provided by the LockOut Realm.
+  * Fix CVE-2021-33037:
+    Apache Tomcat did not correctly parse the HTTP transfer-encoding request
+    header in some circumstances leading to the possibility to request
+    smuggling when used with a reverse proxy. Specifically: - Tomcat
+    incorrectly ignored the transfer encoding header if the client declared it
+    would only accept an HTTP/1.0 response; - Tomcat honoured the identify
+    encoding; and - Tomcat did not ensure that, if present, the chunked
+    encoding was the final encoding. (Closes: #991046)
+
+ -- Markus Koschany <apo at debian.org>  Sat, 07 Aug 2021 18:25:15 +0200
+
 tomcat9 (9.0.31-1~deb10u4) buster-security; urgency=medium
 
   * CVE-2021-25122
   * CVE-2021-25329
 
- -- Moritz Mühlenhoff <jmm at debian.org>  Mon, 12 Apr 2021 16:45:06 +0200
+ -- Moritz Mühlenhoff <jmm at debian.org>  Mon, 12 Apr 2021 16:45:06 +0200
 
 tomcat9 (9.0.31-1~deb10u3) buster-security; urgency=medium
 
@@ -132,7 +150,7 @@ tomcat9 (9.0.16-4) unstable; urgency=medium
   * debian/libexec/tomcat-locate-java.sh: Remove shebang and make
     not executable as this is only ever sourced (makes no sense otherwise)
 
-  [ Christian Hänsel ]
+  [ Christian Hänsel ]
   * Restored the variable expansion in /etc/default/tomcat9 (Closes: #926319)
 
  -- Emmanuel Bourg <ebourg at apache.org>  Thu, 13 Jun 2019 23:26:12 +0200


=====================================
debian/patches/CVE-2021-30640.patch
=====================================
@@ -0,0 +1,327 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 7 Aug 2021 18:21:31 +0200
+Subject: CVE-2021-30640
+
+Bug-Debian: https://bugs.debian.org/991046
+Origin: https://github.com/apache/tomcat/commit/c4df8d44a959a937d507d15e5b1ca35c3dbc41eb
+Origin: https://github.com/apache/tomcat/commit/749f3cc192c68c34f2375509aea087be45fc4434
+Origin: https://github.com/apache/tomcat/commit/c6b6e1015ae44c936971b6bf8bce70987935b92e
+Origin: https://github.com/apache/tomcat/commit/91ecdc61ce3420054c04114baaaf1c1e0cbd5d56
+Origin: https://github.com/apache/tomcat/commit/e50067486cf86564175ca0cfdcbf7d209c6df862
+Origin: https://github.com/apache/tomcat/commit/b5585a9e5d4fec020cc5ebadb82f899fae22bc43
+Origin: https://github.com/apache/tomcat/commit/329932012d3a9b95fde0b18618416e659ecffdc0
+Origin: https://github.com/apache/tomcat/commit/3ce84512ed8783577d9945df28da5a033465b945
+---
+ java/org/apache/catalina/realm/JNDIRealm.java      | 139 +++++++++++++++++++--
+ .../realm/TestJNDIRealmAttributeValueEscape.java   |  86 +++++++++++++
+ 2 files changed, 214 insertions(+), 11 deletions(-)
+ create mode 100644 test/org/apache/catalina/realm/TestJNDIRealmAttributeValueEscape.java
+
+diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
+index 26c97f1..1cc524a 100644
+--- a/java/org/apache/catalina/realm/JNDIRealm.java
++++ b/java/org/apache/catalina/realm/JNDIRealm.java
+@@ -1619,8 +1619,11 @@ public class JNDIRealm extends RealmBase {
+         if (username == null || userPatternFormatArray[curUserPattern] == null)
+             return null;
+ 
+-        // Form the dn from the user pattern
+-        String dn = userPatternFormatArray[curUserPattern].format(new String[] { username });
++        // Form the DistinguishedName from the user pattern.
++        // Escape in case username contains a character with special meaning in
++        // an attribute value.
++        String dn = userPatternFormatArray[curUserPattern].format(
++                new String[] { doAttributeValueEscaping(username) });
+ 
+         try {
+             user = getUserByPattern(context, username, attrIds, dn);
+@@ -1660,8 +1663,9 @@ public class JNDIRealm extends RealmBase {
+         if (username == null || userSearchFormat == null)
+             return null;
+ 
+-        // Form the search filter
+-        String filter = userSearchFormat.format(new String[] { username });
++        // Escape in case username contains a character with special meaning in
++        // a search filter.
++        String filter = userSearchFormat.format(new String[] { doFilterEscaping(username) });
+ 
+         // Set up the search controls
+         SearchControls constraints = new SearchControls();
+@@ -1923,6 +1927,8 @@ public class JNDIRealm extends RealmBase {
+         if (user == null)
+             return null;
+ 
++        // This is returned from the directory so will be attribute value
++        // escaped if required
+         String dn = user.getDN();
+         String username = user.getUserName();
+         String userRoleId = user.getUserRoleId();
+@@ -1951,8 +1957,14 @@ public class JNDIRealm extends RealmBase {
+         if ((roleFormat == null) || (roleName == null))
+             return list;
+ 
+-        // Set up parameters for an appropriate search
+-        String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username, userRoleId });
++        // Set up parameters for an appropriate search filter
++        // The dn is already attribute value escaped but the others are not
++        // This is a filter so all input will require filter escaping
++        String filter = roleFormat.format(new String[] {
++                doFilterEscaping(dn),
++                doFilterEscaping(doAttributeValueEscaping(username)),
++                doFilterEscaping(doAttributeValueEscaping(userRoleId)) });
++
+         SearchControls controls = new SearchControls();
+         if (roleSubtree)
+             controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+@@ -1966,7 +1978,9 @@ public class JNDIRealm extends RealmBase {
+             Name name = np.parse(dn);
+             String nameParts[] = new String[name.size()];
+             for (int i = 0; i < name.size(); i++) {
+-                nameParts[i] = name.get(i);
++                // May have been returned with \<char> escaping rather than
++                // \<hex><hex>. Make sure it is \<hex><hex>.
++                nameParts[i] =  convertToHexEscape(name.get(i));
+             }
+             base = roleBaseFormat.format(nameParts);
+         } else {
+@@ -1987,7 +2001,7 @@ public class JNDIRealm extends RealmBase {
+                 Attributes attrs = result.getAttributes();
+                 if (attrs == null)
+                     continue;
+-                String dname = getDistinguishedName(context, roleBase, result);
++                String dname = getDistinguishedName(context, base, result);
+                 String name = getAttributeValue(roleName, attrs);
+                 if (name != null && dname != null) {
+                     groupMap.put(dname, name);
+@@ -2020,14 +2034,19 @@ public class JNDIRealm extends RealmBase {
+                 Map<String, String> newThisRound = new HashMap<>(); // Stores the groups we find in this iteration
+ 
+                 for (Entry<String, String> group : newGroups.entrySet()) {
+-                    filter = roleFormat.format(new String[] { doRFC2254Encoding(group.getKey()),
+-                            group.getValue(), group.getValue() });
++                    // Group key is already value escaped if required
++                    // Group value is not value escaped
++                    // Everything needs to be filter escaped
++                    filter = roleFormat.format(new String[] {
++                            doFilterEscaping(group.getKey()),
++                            doFilterEscaping(doAttributeValueEscaping(group.getValue())),
++                            doFilterEscaping(doAttributeValueEscaping(group.getValue())) });
+ 
+                     if (containerLog.isTraceEnabled()) {
+                         containerLog.trace("Perform a nested group search with base "+ roleBase + " and filter " + filter);
+                     }
+ 
+-                    results = searchAsUser(context, user, roleBase, filter, controls,
++                    results = searchAsUser(context, user, base, filter, controls,
+                             isRoleSearchAsUser());
+ 
+                     try {
+@@ -2704,10 +2723,36 @@ public class JNDIRealm extends RealmBase {
+      *     )  -> \29
+      *     \  -> \5c
+      *     \0 -> \00
++     *
+      * @param inString string to escape according to RFC 2254 guidelines
++     *
+      * @return String the escaped/encoded result
++     *
++     * @deprecated Will be removed in Tomcat 10.1.x onwards
+      */
++    @Deprecated
+     protected String doRFC2254Encoding(String inString) {
++        return doFilterEscaping(inString);
++    }
++
++
++    /**
++     * Given an LDAP search string, returns the string with certain characters
++     * escaped according to RFC 2254 guidelines.
++     * The character mapping is as follows:
++     *     char ->  Replacement
++     *    ---------------------------
++     *     *  -> \2a
++     *     (  -> \28
++     *     )  -> \29
++     *     \  -> \5c
++     *     \0 -> \00
++     *
++     * @param inString string to escape according to RFC 2254 guidelines
++     *
++     * @return String the escaped/encoded result
++     */
++    protected String doFilterEscaping(String inString) {
+         StringBuilder buf = new StringBuilder(inString.length());
+         for (int i = 0; i < inString.length(); i++) {
+             char c = inString.charAt(i);
+@@ -2797,6 +2842,78 @@ public class JNDIRealm extends RealmBase {
+     }
+ 
+ 
++    /**
++     * Implements the necessary escaping to represent an attribute value as a
++     * String as per RFC 4514.
++     *
++     * @param input The original attribute value
++     * @return      The string representation of the attribute value
++     */
++    protected String doAttributeValueEscaping(String input) {
++        int len = input.length();
++        StringBuilder result = new StringBuilder();
++
++        for (int i = 0; i < len; i++) {
++            char c = input.charAt(i);
++            switch (c) {
++                case ' ': {
++                    if (i == 0 || i == (len -1)) {
++                        result.append("\\20");
++                    } else {
++                        result.append(c);
++                    }
++                    break;
++                }
++                case '#': {
++                    if (i == 0 ) {
++                        result.append("\\23");
++                    } else {
++                        result.append(c);
++                    }
++                    break;
++                }
++                case '\"': {
++                    result.append("\\22");
++                    break;
++                }
++                case '+': {
++                    result.append("\\2B");
++                    break;
++                }
++                case ',': {
++                    result.append("\\2C");
++                    break;
++                }
++                case ';': {
++                    result.append("\\3B");
++                    break;
++                }
++                case '<': {
++                    result.append("\\3C");
++                    break;
++                }
++                case '>': {
++                    result.append("\\3E");
++                    break;
++                }
++                case '\\': {
++                    result.append("\\5C");
++                    break;
++                }
++                case '\u0000': {
++                    result.append("\\00");
++                    break;
++                }
++                default:
++                    result.append(c);
++            }
++
++        }
++
++        return result.toString();
++    }
++
++
+     protected static String convertToHexEscape(String input) {
+         if (input.indexOf('\\') == -1) {
+             // No escaping present. Return original.
+diff --git a/test/org/apache/catalina/realm/TestJNDIRealmAttributeValueEscape.java b/test/org/apache/catalina/realm/TestJNDIRealmAttributeValueEscape.java
+new file mode 100644
+index 0000000..677bcc5
+--- /dev/null
++++ b/test/org/apache/catalina/realm/TestJNDIRealmAttributeValueEscape.java
+@@ -0,0 +1,86 @@
++/*
++ * 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.
++ */
++package org.apache.catalina.realm;
++
++import java.util.ArrayList;
++import java.util.Collection;
++import java.util.List;
++
++import org.junit.Assert;
++import org.junit.Test;
++import org.junit.runner.RunWith;
++import org.junit.runners.Parameterized;
++import org.junit.runners.Parameterized.Parameter;
++
++ at RunWith(Parameterized.class)
++public class TestJNDIRealmAttributeValueEscape {
++
++    @Parameterized.Parameters(name = "{index}: in[{0}], out[{1}]")
++    public static Collection<Object[]> parameters() {
++        List<Object[]> parameterSets = new ArrayList<>();
++
++        // No escaping required
++        parameterSets.add(new String[] { "none", "none" });
++        // Simple cases (same order as RFC 4512 section 2)
++        // Each appearing at the beginning, middle and ent
++        parameterSets.add(new String[] { " test", "\\20test" });
++        parameterSets.add(new String[] { "te st", "te st" });
++        parameterSets.add(new String[] { "test ", "test\\20" });
++        parameterSets.add(new String[] { "#test", "\\23test" });
++        parameterSets.add(new String[] { "te#st", "te#st" });
++        parameterSets.add(new String[] { "test#", "test#" });
++        parameterSets.add(new String[] { "\"test", "\\22test" });
++        parameterSets.add(new String[] { "te\"st", "te\\22st" });
++        parameterSets.add(new String[] { "test\"", "test\\22" });
++        parameterSets.add(new String[] { "+test", "\\2Btest" });
++        parameterSets.add(new String[] { "te+st", "te\\2Bst" });
++        parameterSets.add(new String[] { "test+", "test\\2B" });
++        parameterSets.add(new String[] { ",test", "\\2Ctest" });
++        parameterSets.add(new String[] { "te,st", "te\\2Cst" });
++        parameterSets.add(new String[] { "test,", "test\\2C" });
++        parameterSets.add(new String[] { ";test", "\\3Btest" });
++        parameterSets.add(new String[] { "te;st", "te\\3Bst" });
++        parameterSets.add(new String[] { "test;", "test\\3B" });
++        parameterSets.add(new String[] { "<test", "\\3Ctest" });
++        parameterSets.add(new String[] { "te<st", "te\\3Cst" });
++        parameterSets.add(new String[] { "test<", "test\\3C" });
++        parameterSets.add(new String[] { ">test", "\\3Etest" });
++        parameterSets.add(new String[] { "te>st", "te\\3Est" });
++        parameterSets.add(new String[] { "test>", "test\\3E" });
++        parameterSets.add(new String[] { "\\test", "\\5Ctest" });
++        parameterSets.add(new String[] { "te\\st", "te\\5Cst" });
++        parameterSets.add(new String[] { "test\\", "test\\5C" });
++        parameterSets.add(new String[] { "\u0000test", "\\00test" });
++        parameterSets.add(new String[] { "te\u0000st", "te\\00st" });
++        parameterSets.add(new String[] { "test\u0000", "test\\00" });
++        return parameterSets;
++    }
++
++
++    @Parameter(0)
++    public String in;
++    @Parameter(1)
++    public String out;
++
++    private JNDIRealm realm = new JNDIRealm();
++
++    @Test
++    public void testConvertToHexEscape() throws Exception {
++        String result = realm.doAttributeValueEscaping(in);
++        Assert.assertEquals(out, result);
++    }
++}
+\ No newline at end of file


=====================================
debian/patches/CVE-2021-33037.patch
=====================================
@@ -0,0 +1,239 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 7 Aug 2021 18:22:55 +0200
+Subject: CVE-2021-33037
+
+Bug-Debian: https://bugs.debian.org/991046
+Origin: https://github.com/apache/tomcat/commit/45d70a86a901cbd534f8f570bed2aec9f7f7b88e
+Origin: https://github.com/apache/tomcat/commit/05f9e8b00f5d9251fcd3c95dcfd6cf84177f46c8
+Origin: https://github.com/apache/tomcat/commit/a2c3dc4c96168743ac0bab613709a5bbdaec41d0
+---
+ java/org/apache/coyote/http11/Http11Processor.java |  25 ++--
+ .../apache/coyote/http11/TestHttp11Processor.java  | 133 +++++++++++++++++----
+ webapps/docs/changelog.xml                         |  15 +++
+ 3 files changed, 140 insertions(+), 33 deletions(-)
+
+diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java
+index e790d95..17a3295 100644
+--- a/java/org/apache/coyote/http11/Http11Processor.java
++++ b/java/org/apache/coyote/http11/Http11Processor.java
+@@ -208,14 +208,22 @@ public class Http11Processor extends AbstractProcessor {
+      * supported, a 501 response will be returned to the client.
+      */
+     private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
++        if (contentDelimitation) {
++            // Chunked has already been specified and it must be the final
++            // encoding.
++            // 400 - Bad request
++            response.setStatus(400);
++            setErrorState(ErrorState.CLOSE_CLEAN, null);
++            if (log.isDebugEnabled()) {
++                log.debug(sm.getString("http11processor.request.prepare") +
++                          " Tranfer encoding lists chunked before [" + encodingName + "]");
++            }
++            return;
++        }
+ 
+         // Parsing trims and converts to lower case.
+-
+-        if (encodingName.equals("identity")) {
+-            // Skip
+-        } else if (encodingName.equals("chunked")) {
+-            inputBuffer.addActiveFilter
+-                (inputFilters[Constants.CHUNKED_FILTER]);
++        if (encodingName.equals("chunked")) {
++            inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
+             contentDelimitation = true;
+         } else {
+             for (int i = pluggableFilterIndex; i < inputFilters.length; i++) {
+@@ -719,13 +727,14 @@ public class Http11Processor extends AbstractProcessor {
+         InputFilter[] inputFilters = inputBuffer.getFilters();
+ 
+         // Parse transfer-encoding header
+-        if (http11) {
++        // HTTP specs say an HTTP 1.1 server should accept any recognised
++        // HTTP 1.x header from a 1.x client unless the specs says otherwise.
++        if (!http09) {
+             MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
+             if (transferEncodingValueMB != null) {
+                 List<String> encodingNames = new ArrayList<>();
+                 if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
+                     for (String encodingName : encodingNames) {
+-                        // "identity" codings are ignored
+                         addInputFilter(inputFilters, encodingName);
+                     }
+                 } else {
+diff --git a/test/org/apache/coyote/http11/TestHttp11Processor.java b/test/org/apache/coyote/http11/TestHttp11Processor.java
+index f7f5f74..b574868 100644
+--- a/test/org/apache/coyote/http11/TestHttp11Processor.java
++++ b/test/org/apache/coyote/http11/TestHttp11Processor.java
+@@ -250,31 +250,6 @@ public class TestHttp11Processor extends TomcatBaseTest {
+     }
+ 
+ 
+-    @Test
+-    public void testWithTEIdentity() throws Exception {
+-        getTomcatInstanceTestWebapp(false, true);
+-
+-        String request =
+-            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
+-            "Host: any" + SimpleHttpClient.CRLF +
+-            "Transfer-encoding: identity" + SimpleHttpClient.CRLF +
+-            "Content-Length: 9" + SimpleHttpClient.CRLF +
+-            "Content-Type: application/x-www-form-urlencoded" +
+-                    SimpleHttpClient.CRLF +
+-            "Connection: close" + SimpleHttpClient.CRLF +
+-                SimpleHttpClient.CRLF +
+-            "test=data";
+-
+-        Client client = new Client(getPort());
+-        client.setRequest(new String[] {request});
+-
+-        client.connect();
+-        client.processRequest();
+-        Assert.assertTrue(client.isResponse200());
+-        Assert.assertTrue(client.getResponseBody().contains("test - data"));
+-    }
+-
+-
+     @Test
+     public void testWithTESavedRequest() throws Exception {
+         getTomcatInstanceTestWebapp(false, true);
+@@ -1643,4 +1618,112 @@ public class TestHttp11Processor extends TomcatBaseTest {
+             out.print(" and request.getServerPort() is " + req.getServerPort());
+         }
+     }
++
++
++    @Test
++    public void testTEHeaderUnknown01() throws Exception {
++        doTestTEHeaderInvalid("identity", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown02() throws Exception {
++        doTestTEHeaderInvalid("identity, chunked", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown03() throws Exception {
++        doTestTEHeaderInvalid("unknown, chunked", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown04() throws Exception {
++        doTestTEHeaderInvalid("void", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown05() throws Exception {
++        doTestTEHeaderInvalid("void, chunked", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown06() throws Exception {
++        doTestTEHeaderInvalid("void, identity", false);
++    }
++
++
++    @Test
++    public void testTEHeaderUnknown07() throws Exception {
++        doTestTEHeaderInvalid("identity, void", false);
++    }
++
++
++    @Test
++    public void testTEHeaderChunkedNotLast01() throws Exception {
++        doTestTEHeaderInvalid("chunked, void", true);
++    }
++
++
++    private void doTestTEHeaderInvalid(String headerValue, boolean badRequest) throws Exception {
++        Tomcat tomcat = getTomcatInstance();
++
++        // No file system docBase required
++        Context ctx = tomcat.addContext("", null);
++
++        // Add servlet
++        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
++        ctx.addServletMappingDecoded("/foo", "TesterServlet");
++
++        tomcat.start();
++
++        String request =
++                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
++                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
++                "Transfer-Encoding: " + headerValue + SimpleHttpClient.CRLF +
++                SimpleHttpClient.CRLF;
++
++        Client client = new Client(tomcat.getConnector().getLocalPort());
++        client.setRequest(new String[] {request});
++
++        client.connect();
++        client.processRequest(false);
++
++        if (badRequest) {
++            Assert.assertTrue(client.isResponse400());
++        } else {
++            Assert.assertTrue(client.isResponse501());
++        }
++    }
++
++
++    @Test
++    public void testWithTEChunkedHttp10() throws Exception {
++
++        getTomcatInstanceTestWebapp(false, true);
++
++        String request =
++            "POST /test/echo-params.jsp HTTP/1.0" + SimpleHttpClient.CRLF +
++            "Host: any" + SimpleHttpClient.CRLF +
++            "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
++            "Content-Type: application/x-www-form-urlencoded" +
++                    SimpleHttpClient.CRLF +
++            "Connection: close" + SimpleHttpClient.CRLF +
++            SimpleHttpClient.CRLF +
++            "9" + SimpleHttpClient.CRLF +
++            "test=data" + SimpleHttpClient.CRLF +
++            "0" + SimpleHttpClient.CRLF +
++            SimpleHttpClient.CRLF;
++
++        Client client = new Client(getPort());
++        client.setRequest(new String[] {request});
++
++        client.connect();
++        client.processRequest();
++        Assert.assertTrue(client.isResponse200());
++        Assert.assertTrue(client.getResponseBody().contains("test - data"));
++    }
+ }
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 9128471..436c92b 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -790,6 +790,21 @@
+         <bug>64467</bug>: Improve performance of closing idle HTTP/2 streams.
+         (markt)
+       </fix>
++      <fix>
++        Remove support for the <code>identity</code> transfer encoding. The
++        inclusion of this encoding in RFC 2616 was an error that was corrected
++        in 2001. Requests using this transfer encoding will now receive a 501
++        response. (markt)
++      </fix>
++      <fix>
++        Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
++        clients. (markt)
++      </fix>
++      <fix>
++        Ensure that if the transfer encoding header contains the
++        <code>chunked</code>, that the <code>chunked</code> encoding is the
++        final encoding listed. (markt)
++      </fix>
+     </changelog>
+   </subsection>
+ </section>


=====================================
debian/patches/series
=====================================
@@ -21,3 +21,5 @@ CVE-2020-13943.patch
 CVE-2020-17527.patch
 CVE-2021-25122.patch
 CVE-2021-25329.patch
+CVE-2021-30640.patch
+CVE-2021-33037.patch



View it on GitLab: https://salsa.debian.org/java-team/tomcat9/-/compare/a6542f113d1e72b96f2e24a8f47c31f66c5bd0c8...0ce07f71b8de8a6246c64239168053ac3001ca84

-- 
View it on GitLab: https://salsa.debian.org/java-team/tomcat9/-/compare/a6542f113d1e72b96f2e24a8f47c31f66c5bd0c8...0ce07f71b8de8a6246c64239168053ac3001ca84
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20210808/5512d4d1/attachment.htm>


More information about the pkg-java-commits mailing list