Fix CVE-2021-30640

(cherry picked from commit ad3e1f9e6fe4ebfbfc6ee3b0922b0c39a936d543)
This commit is contained in:
wang_yue111 2021-07-29 16:54:15 +08:00 committed by openeuler-sync-bot
parent 33910cb590
commit 9cbeb1e6aa
14 changed files with 1973 additions and 1 deletions

204
CVE-2021-30640-1.patch Normal file
View File

@ -0,0 +1,204 @@
From 6a719704236d3ce02100606290ff59b6a11f6b20 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 11:12:02 +0100
Subject: [PATCH] Add attribute value escaping to support user names containing ';'
---
java/org/apache/catalina/realm/JNDIRealm.java | 79 ++++++++++++++++-
.../TestJNDIRealmAttributeValueEscape.java | 86 +++++++++++++++++++
2 files changed, 163 insertions(+), 2 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 19fa704..54921dc 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1603,8 +1603,11 @@ public class JNDIRealm extends RealmBase {
if (username == null || userPatternArray[curUserPattern] == null)
return null;
- // Form the dn from the user pattern
- String dn = connection.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 = connection.userPatternFormatArray[curUserPattern].format(
+ new String[] { doAttributeValueEscaping(username) });
try {
user = getUserByPattern(connection.context, username, attrIds, dn);
@@ -2820,6 +2823,78 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
}
+ /**
+ * 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;
+
+@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
--
2.23.0

71
CVE-2021-30640-2.patch Normal file
View File

@ -0,0 +1,71 @@
From f9a89674c08b55677424df7bd41685e72316e6bf Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 11:35:07 +0100
Subject: [PATCH] Rename for clarity
---
java/org/apache/catalina/realm/JNDIRealm.java | 30 +++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 54921dc..b60f393 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1942,7 +1942,7 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
return list;
// Set up parameters for an appropriate search
- String filter = connection.roleFormat.format(new String[] { doRFC2254Encoding(dn), username, userRoleId });
+ String filter = connection.roleFormat.format(new String[] { doFilterEscaping(dn), username, userRoleId });
SearchControls controls = new SearchControls();
if (roleSubtree)
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
@@ -2010,7 +2010,7 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
Map<String, String> newThisRound = new HashMap<>(); // Stores the groups we find in this iteration
for (Entry<String, String> group : newGroups.entrySet()) {
- filter = connection.roleFormat.format(new String[] { doRFC2254Encoding(group.getKey()),
+ filter = connection.roleFormat.format(new String[] { doFilterEscaping(group.getKey()),
group.getValue(), group.getValue() });
if (containerLog.isTraceEnabled()) {
@@ -2730,10 +2730,36 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
* ) -&gt; \29
* \ -&gt; \5c
* \0 -&gt; \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 -&gt; Replacement
+ * ---------------------------
+ * * -&gt; \2a
+ * ( -&gt; \28
+ * ) -&gt; \29
+ * \ -&gt; \5c
+ * \0 -&gt; \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);
--
2.23.0

36
CVE-2021-30640-3.patch Normal file
View File

@ -0,0 +1,36 @@
From 2e3924d0a8372ced148b42016432c038dd1ae487 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 11:43:51 +0100
Subject: [PATCH] Expand tests and fix escaping issue when searching for users by filter
---
java/org/apache/catalina/realm/JNDIRealm.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index b60f393..dcec473 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1648,7 +1648,9 @@ public class JNDIRealm extends RealmBase {
return null;
// Form the search filter
- String filter = connection.userSearchFormat.format(new String[] { username });
+ // Escape in case username contains a character with special meaning in
+ // a search filter.
+ String filter = connection.userSearchFormat.format(new String[] { doFilterEscaping(username) });
// Set up the search controls
SearchControls constraints = new SearchControls();
@@ -1913,6 +1915,8 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
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();
--
2.23.0

37
CVE-2021-30640-4.patch Normal file
View File

@ -0,0 +1,37 @@
From 954eb10e9957055f60ee1e427baabfa32fc3d78b Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 12:11:35 +0100
Subject: [PATCH] Expand tests and fix an issue in escaping for group search
---
java/org/apache/catalina/realm/JNDIRealm.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index dcec473..1021ce8 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1918,6 +1918,8 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
// This is returned from the directory so will be attribute value
// escaped if required
String dn = user.getDN();
+ // This is the name the user provided to the authentication process so
+ // it will not be escaped
String username = user.getUserName();
String userRoleId = user.getUserRoleId();
@@ -1946,7 +1948,10 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
return list;
// Set up parameters for an appropriate search
- String filter = connection.roleFormat.format(new String[] { doFilterEscaping(dn), username, userRoleId });
+ String filter = connection.roleFormat.format(new String[] {
+ doFilterEscaping(dn),
+ doFilterEscaping(doAttributeValueEscaping(username)),
+ userRoleId });
SearchControls controls = new SearchControls();
if (roleSubtree)
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
--
2.23.0

32
CVE-2021-30640-5.patch Normal file
View File

@ -0,0 +1,32 @@
From a13034d94c927286a7f4e17ab4f662727fbe6e9f Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 12:20:06 +0100
Subject: [PATCH] Expand tests and fix escaping issue in userRoleAttribute filter
---
java/org/apache/catalina/realm/JNDIRealm.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 1021ce8..a3b6f86 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1947,11 +1947,13 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
if ((connection.roleFormat == null) || (roleName == null))
return list;
- // Set up parameters for an appropriate search
+ // 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 = connection.roleFormat.format(new String[] {
doFilterEscaping(dn),
doFilterEscaping(doAttributeValueEscaping(username)),
- userRoleId });
+ doFilterEscaping(doAttributeValueEscaping(userRoleId)) });
SearchControls controls = new SearchControls();
if (roleSubtree)
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
--
2.23.0

32
CVE-2021-30640-6.patch Normal file
View File

@ -0,0 +1,32 @@
From fd48ca875aaa46920b6d94fe737420d3985ad7d4 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 12:54:24 +0100
Subject: [PATCH] Expanded tests to cover nested roles and fix escaping issues in search
---
java/org/apache/catalina/realm/JNDIRealm.java | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index a3b6f86..cfe1c15 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -2021,8 +2021,13 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
Map<String, String> newThisRound = new HashMap<>(); // Stores the groups we find in this iteration
for (Entry<String, String> group : newGroups.entrySet()) {
- filter = connection.roleFormat.format(new String[] { doFilterEscaping(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 = connection.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);
--
2.23.0

35
CVE-2021-30640-7.patch Normal file
View File

@ -0,0 +1,35 @@
From 3383668c05becf01fe175aba928177b648f327ec Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 14:47:07 +0100
Subject: [PATCH] Expand testing to cover substitution in roleBase. Fix bugs.
The code incorrectly referred to the original roleBase rather than the local version that includes the substituted value(s).
---
java/org/apache/catalina/realm/JNDIRealm.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index cfe1c15..c78068b 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1988,7 +1988,7 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
Attributes attrs = result.getAttributes();
if (attrs == null)
continue;
- String dname = getDistinguishedName(connection.context, roleBase, result);
+ String dname = getDistinguishedName(connection.context, base, result);
String name = getAttributeValue(roleName, attrs);
if (name != null && dname != null) {
groupMap.put(dname, name);
@@ -2033,7 +2033,7 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
containerLog.trace("Perform a nested group search with base "+ roleBase + " and filter " + filter);
}
- results = searchAsUser(connection.context, user, roleBase, filter, controls,
+ results = searchAsUser(connection.context, user, base, filter, controls,
isRoleSearchAsUser());
try {
--
2.23.0

28
CVE-2021-30640-8.patch Normal file
View File

@ -0,0 +1,28 @@
From c703ec491aca94cb17853808c7ce0c4fd99992bb Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 13 Apr 2021 15:19:31 +0100
Subject: [PATCH] Expand tests to cover escaping of substituted roleBaes values
While the UnboundedID LDAP SDK doesn't appear to have a preference some servers (Windows AD, OpenLDAP) do appear to.
---
java/org/apache/catalina/realm/JNDIRealm.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index c78068b..7a8c5f6 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1967,7 +1967,9 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
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 = connection.roleBaseFormat.format(nameParts);
} else {
--
2.23.0

45
CVE-2021-30640-pre1.patch Normal file
View File

@ -0,0 +1,45 @@
From 700d26b69df3f1003ce8443d5569911c36b113de Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Tue, 5 Mar 2019 19:19:32 +0000
Subject: [PATCH] Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63213
Ensure the correct escaping of group names when searching for nested
groups when the JNDIRealm is configured with roleNested set to true.
---
java/org/apache/catalina/realm/JNDIRealm.java | 3 ++-
webapps/docs/changelog.xml | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index e980bdf..034c0f0 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -2010,7 +2010,8 @@ 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[] { group.getKey(), group.getValue(), group.getValue() });
+ filter = roleFormat.format(new String[] { doRFC2254Encoding(group.getKey()),
+ group.getValue(), group.getValue() });
if (containerLog.isTraceEnabled()) {
containerLog.trace("Perform a nested group search with base "+ roleBase + " and filter " + filter);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 35b8eab..f088e0d 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -55,6 +55,11 @@
<fix>
Encode the output of the SSI <code>printenv</code> command. (markt)
</fix>
+ <fix>
+ <bug>63213</bug>: Ensure the correct escaping of group names when
+ searching for nested groups when the JNDIRealm is configured with
+ <code>roleNested</code> set to <code>true</code>. (markt)
+ </fix>
</changelog>
</subsection>
</section>
--
2.23.0

44
CVE-2021-30640-pre2.patch Normal file
View File

@ -0,0 +1,44 @@
From 824c531393aa030f161e1ec352a65b7e9302d6b6 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Fri, 26 Jul 2019 14:59:57 +0100
Subject: [PATCH] Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63550
Only use the alternateURL for the JNDIRealm when it has been specified
---
java/org/apache/catalina/realm/JNDIRealm.java | 4 ++++
webapps/docs/changelog.xml | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 034c0f0..505dd13 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -2378,6 +2378,10 @@ public class JNDIRealm extends RealmBase {
context = createDirContext(getDirectoryContextEnvironment());
} catch (Exception e) {
+ if (alternateURL == null || alternateURL.length() == 0) {
+ // No alternate URL. Re-throw the exception.
+ throw e;
+ }
connectionAttempt = 1;
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f088e0d..7bcc3d9 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -248,6 +248,10 @@
</subsection>
<subsection name="Jasper">
<changelog>
+ <fix>
+ <bug>63550</bug>: Only try the <code>alternateURL</code> in the
+ <code>JNDIRealm</code> if one has been specified. (markt)
+ </fix>
<add>
<bug>50234</bug>: Add the capability to generate a web-fragment.xml file
to JspC. (markt)
--
2.23.0

1089
CVE-2021-30640-pre3.patch Normal file

File diff suppressed because it is too large Load Diff

53
CVE-2021-30640-pre4.patch Normal file
View File

@ -0,0 +1,53 @@
From 36710841d24807a6837757a24952ab5e6ced6ec8 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Wed, 23 Jan 2019 15:09:37 +0000
Subject: [PATCH] Refactor to simplify the fix for BZ 63026
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.5.x/trunk@1851939 13f79535-47bb-0310-9956-ffa450edef68
---
java/org/apache/catalina/realm/JNDIRealm.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index b624c5b..5714496 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -2763,6 +2763,7 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
// we need to composite a name with the base name, the context name, and
// the result name. For non-relative names, use the returned name.
String resultName = result.getName();
+ Name name;
if (result.isRelative()) {
if (containerLog.isTraceEnabled()) {
containerLog.trace(" search returned relative name: " + resultName);
@@ -2774,9 +2775,8 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
// Bugzilla 32269
Name entryName = parser.parse(new CompositeName(resultName).get(0));
- Name name = contextName.addAll(baseName);
+ name = contextName.addAll(baseName);
name = name.addAll(entryName);
- return name.toString();
} else {
if (containerLog.isTraceEnabled()) {
containerLog.trace(" search returned absolute name: " + resultName);
@@ -2792,14 +2792,14 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
"Search returned unparseable absolute name: " +
resultName );
}
- Name name = parser.parse(pathComponent.substring(1));
- return name.toString();
+ name = parser.parse(pathComponent.substring(1));
} catch ( URISyntaxException e ) {
throw new InvalidNameException(
"Search returned unparseable absolute name: " +
resultName );
}
}
+ return name.toString();
}
--
2.23.0

250
CVE-2021-30640-pre5.patch Normal file
View File

@ -0,0 +1,250 @@
From 4bee1e769bce86cd53ce80eb18c15449ea0df34b Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Wed, 23 Jan 2019 15:11:07 +0000
Subject: [PATCH] Add a new attribute, forceDnHexEscape, to the JNDIRealm that
forces escaping in the String representation of a distinguished name to use
the \nn form. This may avoid issues with realms using Active Directory which
appears to be more tolerant of optional escaping when the \nn form is used.
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.5.x/trunk@1851941 13f79535-47bb-0310-9956-ffa450edef68
---
java/org/apache/catalina/realm/JNDIRealm.java | 95 ++++++++++++++++++-
.../TestJNDIRealmConvertToHexEscape.java | 70 ++++++++++++++
webapps/docs/changelog.xml | 8 ++
webapps/docs/config/realm.xml | 9 ++
4 files changed, 181 insertions(+), 1 deletion(-)
create mode 100644 test/org/apache/catalina/realm/TestJNDIRealmConvertToHexEscape.java
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 5714496..19fa704 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -487,8 +487,19 @@ public class JNDIRealm extends RealmBase {
protected int connectionPoolSize = 1;
+ private boolean forceDnHexEscape = false;
+
+
// ------------------------------------------------------------- Properties
+ public boolean getForceDnHexEscape() {
+ return forceDnHexEscape;
+ }
+
+ public void setForceDnHexEscape(boolean forceDnHexEscape) {
+ this.forceDnHexEscape = forceDnHexEscape;
+ }
+
/**
* @return the type of authentication to use.
*/
@@ -2799,7 +2810,89 @@ System.out.println("userRoleName " + userRoleName + " " + attrs.get(userRoleName
resultName );
}
}
- return name.toString();
+
+ if (getForceDnHexEscape()) {
+ // Bug 63026
+ return convertToHexEscape(name.toString());
+ } else {
+ return name.toString();
+ }
+ }
+
+
+ protected static String convertToHexEscape(String input) {
+ if (input.indexOf('\\') == -1) {
+ // No escaping present. Return original.
+ return input;
+ }
+
+ // +6 allows for 3 escaped characters by default
+ StringBuilder result = new StringBuilder(input.length() + 6);
+ boolean previousSlash = false;
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+
+ if (previousSlash) {
+ switch (c) {
+ case ' ': {
+ result.append("\\20");
+ break;
+ }
+ case '\"': {
+ result.append("\\22");
+ break;
+ }
+ case '#': {
+ result.append("\\23");
+ break;
+ }
+ case '+': {
+ result.append("\\2B");
+ break;
+ }
+ case ',': {
+ result.append("\\2C");
+ break;
+ }
+ case ';': {
+ result.append("\\3B");
+ break;
+ }
+ case '<': {
+ result.append("\\3C");
+ break;
+ }
+ case '=': {
+ result.append("\\3D");
+ break;
+ }
+ case '>': {
+ result.append("\\3E");
+ break;
+ }
+ case '\\': {
+ result.append("\\5C");
+ break;
+ }
+ default:
+ result.append('\\');
+ result.append(c);
+ }
+ previousSlash = false;
+ } else {
+ if (c == '\\') {
+ previousSlash = true;
+ } else {
+ result.append(c);
+ }
+ }
+ }
+
+ if (previousSlash) {
+ result.append('\\');
+ }
+
+ return result.toString();
}
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmConvertToHexEscape.java b/test/org/apache/catalina/realm/TestJNDIRealmConvertToHexEscape.java
new file mode 100644
index 0000000..8c610a3
--- /dev/null
+++ b/test/org/apache/catalina/realm/TestJNDIRealmConvertToHexEscape.java
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+@RunWith(Parameterized.class)
+public class TestJNDIRealmConvertToHexEscape {
+
+ @Parameterized.Parameters(name = "{index}: in[{0}], out[{1}]")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+
+ parameterSets.add(new String[] { "none", "none" });
+ parameterSets.add(new String[] { "\\", "\\" });
+ parameterSets.add(new String[] { "\\\\", "\\5C" });
+ parameterSets.add(new String[] { "\\5C", "\\5C" });
+ parameterSets.add(new String[] { "\\ ", "\\20" });
+ parameterSets.add(new String[] { "\\20", "\\20" });
+ parameterSets.add(new String[] { "\\ foo", "\\20foo" });
+ parameterSets.add(new String[] { "\\20foo", "\\20foo" });
+ parameterSets.add(new String[] { "\\ foo", "\\20 foo" });
+ parameterSets.add(new String[] { "\\20 foo", "\\20 foo" });
+ parameterSets.add(new String[] { "\\ \\ foo", "\\20\\20foo" });
+ parameterSets.add(new String[] { "\\20\\20foo", "\\20\\20foo" });
+ parameterSets.add(new String[] { "foo\\ ", "foo\\20" });
+ parameterSets.add(new String[] { "foo\\20", "foo\\20" });
+ parameterSets.add(new String[] { "foo \\ ", "foo \\20" });
+ parameterSets.add(new String[] { "foo \\20", "foo \\20" });
+ parameterSets.add(new String[] { "foo\\ \\ ", "foo\\20\\20" });
+ parameterSets.add(new String[] { "foo\\20\\20", "foo\\20\\20" });
+
+ return parameterSets;
+ }
+
+
+ @Parameter(0)
+ public String in;
+ @Parameter(1)
+ public String out;
+
+
+ @Test
+ public void testConvertToHexEscape() throws Exception {
+ String result = JNDIRealm.convertToHexEscape(in);
+ Assert.assertEquals(out, result);
+ }
+}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 173c209..a7bb52c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -794,6 +794,14 @@
a plain text response. Based on a suggestion from Muthukumar Marikani.
(markt)
</add>
+ <add>
+ <bug>63026</bug>: Add a new attribute, <code>forceDnHexEscape</code>, to
+ the <code>JNDIRealm</code> that forces escaping in the String
+ representation of a distinguished name to use the <code>\nn</code> form.
+ This may avoid issues with realms using Active Directory which appears
+ to be more tolerant of optional escaping when the <code>\nn</code> form
+ is used. (markt)
+ </add>
</changelog>
</subsection>
</section>
diff --git a/webapps/docs/config/realm.xml b/webapps/docs/config/realm.xml
index a4bc5ef..715ceb7 100644
--- a/webapps/docs/config/realm.xml
+++ b/webapps/docs/config/realm.xml
@@ -463,6 +463,15 @@
"finding" and "searching". If not specified, "always" is used.</p>
</attribute>
+ <attribute name="forceDnHexEscape" required="false">
+ <p>A setting of <code>true</code> forces escaping in the String
+ representation of a distinguished name to use the <code>\nn</code> form.
+ This may avoid issues with realms using Active Directory which appears
+ to be more tolerant of optional escaping when the <code>\nn</code> form
+ is used. If not specified, the default of <code>false</code> will be
+ used.</p>
+ </attribute>
+
<attribute name="hostnameVerifierClassName" required="false">
<p>The name of the class to use for hostname verification when
using StartTLS for securing the connection to the ldap server.
--
2.23.0

View File

@ -13,7 +13,7 @@
Name: tomcat
Epoch: 1
Version: %{major_version}.%{minor_version}.%{micro_version}
Release: 19
Release: 20
Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies
License: ASL 2.0
URL: http://tomcat.apache.org/
@ -85,6 +85,19 @@ Patch6040: CVE-2021-25329.patch
Patch6041: CVE-2021-33037-1.patch
Patch6042: CVE-2021-33037-2.patch
Patch6043: CVE-2021-33037-3.patch
Patch6044: CVE-2021-30640-pre1.patch
Patch6045: CVE-2021-30640-pre2.patch
Patch6046: CVE-2021-30640-pre3.patch
Patch6047: CVE-2021-30640-pre4.patch
Patch6048: CVE-2021-30640-pre5.patch
Patch6049: CVE-2021-30640-1.patch
Patch6050: CVE-2021-30640-2.patch
Patch6051: CVE-2021-30640-3.patch
Patch6052: CVE-2021-30640-4.patch
Patch6053: CVE-2021-30640-5.patch
Patch6054: CVE-2021-30640-6.patch
Patch6055: CVE-2021-30640-7.patch
Patch6056: CVE-2021-30640-8.patch
BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon
BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant
@ -486,6 +499,9 @@ fi
%{_javadocdir}/%{name}
%changelog
* Thu Jul 29 2021 wangyue <wangyue92@huawei.com> - 1:9.0.10-20
- Fix CVE-2021-30640
* Mon Jul 19 2021 wangyue <wangyue92@huawei.com> - 1:9.0.10-19
- Fix CVE-2021-33037