You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/04/13 14:30:15 UTC
[tomcat] branch 8.5.x updated (cb10b3f -> 999a22d)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git.
from cb10b3f Corrected instructions to reduce unit tests verbosity
new a1d06d5 Start to expand JNDIRealm unit tests
new 24dfb30 Add attribute value escaping to support user names containing ';'
new 0a272b0 Rename for clarity
new c9f21a2 Expand tests and fix escaping issue when searching for users by filter
new 4e86b4e Expand tests and fix an issue in escaping for group search
new 79580e7 Expand tests and fix escaping issue in userRoleAttribute filter
new d340767 Expanded tests to cover nested roles and fix escaping issues in search
new 6a9129a Expand testing to cover substitution in roleBase. Fix bugs.
new ad22db6 Expand tests to cover escaping of substituted roleBaes values
new 999a22d Update changelog
The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
build.properties.default | 9 +
build.xml | 9 +
java/org/apache/catalina/realm/JNDIRealm.java | 141 ++++++++++-
.../realm/TestJNDIRealmAttributeValueEscape.java | 86 +++++++
.../catalina/realm/TestJNDIRealmIntegration.java | 263 +++++++++++++++++++++
webapps/docs/changelog.xml | 12 +
6 files changed, 510 insertions(+), 10 deletions(-)
create mode 100644 test/org/apache/catalina/realm/TestJNDIRealmAttributeValueEscape.java
create mode 100644 test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 06/10: Expand tests and fix escaping issue in
userRoleAttribute filter
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 79580e7f70a07c083be07307376511bb864d5a7b
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 12:20:06 2021 +0100
Expand tests and fix escaping issue in userRoleAttribute filter
---
java/org/apache/catalina/realm/JNDIRealm.java | 6 ++++--
test/org/apache/catalina/realm/TestJNDIRealmIntegration.java | 8 +++++---
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index d6976c7..7598539 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1891,11 +1891,13 @@ public class JNDIRealm extends RealmBase {
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);
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index 3d9969e..8302e47 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -48,13 +48,14 @@ public class TestJNDIRealmIntegration {
private static final String USER_BASE = "ou=people,dc=example,dc=com";
private static final String ROLE_SEARCH_A = "member={0}";
private static final String ROLE_SEARCH_B = "member=cn={1},ou=people,dc=example,dc=com";
+ private static final String ROLE_SEARCH_C = "member=cn={2},ou=people,dc=example,dc=com";
private static InMemoryDirectoryServer ldapServer;
@Parameterized.Parameters(name = "{index}: user[{3}], pwd[{4}]")
public static Collection<Object[]> parameters() {
List<Object[]> parameterSets = new ArrayList<>();
- for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B }) {
+ for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B, ROLE_SEARCH_C }) {
addUsers(USER_PATTERN, null, null, roleSearch, parameterSets);
addUsers(null, USER_SEARCH, USER_BASE, roleSearch, parameterSets);
}
@@ -128,6 +129,7 @@ public class TestJNDIRealmIntegration {
try (LDAPConnection conn = ldapServer.getConnection()) {
+ // Note: Only the DNs need attribute value escaping
AddRequest addBase = new AddRequest(
"dn: dc=example,dc=com",
"objectClass: top",
@@ -159,7 +161,7 @@ public class TestJNDIRealmIntegration {
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
- "cn: t\\;",
+ "cn: t;",
"sn: Tsemicolon",
"userPassword: test");
result = conn.processOperation(addUserTestSemicolon);
@@ -170,7 +172,7 @@ public class TestJNDIRealmIntegration {
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
- "cn: t\\*",
+ "cn: t*",
"sn: Tasterisk",
"userPassword: test");
result = conn.processOperation(addUserTestAsterisk);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 02/10: Add attribute value escaping to support user names
containing '; '
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 24dfb30076997b640e5123e92c4b8d7f206f609c
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 11:12:02 2021 +0100
Add attribute value escaping to support user names containing ';'
---
java/org/apache/catalina/realm/JNDIRealm.java | 79 +++++++++++++++++++-
.../realm/TestJNDIRealmAttributeValueEscape.java | 86 ++++++++++++++++++++++
.../catalina/realm/TestJNDIRealmIntegration.java | 15 +++-
3 files changed, 177 insertions(+), 3 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index e4ba051..9f43b94 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1549,8 +1549,11 @@ public class JNDIRealm extends RealmBase {
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);
@@ -2839,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;
+
+@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
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index 03e1655..ca45053 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -50,6 +50,7 @@ public class TestJNDIRealmIntegration {
List<Object[]> parameterSets = new ArrayList<>();
parameterSets.add(new Object[] { "test", "test", new String[] {"TestGroup"} });
+ parameterSets.add(new Object[] { "t;", "test", new String[] {"TestGroup"} });
return parameterSets;
}
@@ -125,12 +126,24 @@ public class TestJNDIRealmIntegration {
result = conn.processOperation(addUserTest);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+ AddRequest addUserTestSemicolon = new AddRequest(
+ "dn: cn=t\\;,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "cn: test",
+ "sn: Test",
+ "userPassword: test");
+ result = conn.processOperation(addUserTestSemicolon);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
AddRequest addGroupTest = new AddRequest(
"dn: cn=TestGroup,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: groupOfNames",
"cn: TestGroup",
- "member: cn=test,ou=people,dc=example,dc=com");
+ "member: cn=test,ou=people,dc=example,dc=com",
+ "member: cn=t\\;,ou=people,dc=example,dc=com");
result = conn.processOperation(addGroupTest);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 03/10: Rename for clarity
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 0a272b00aed57526dbfc8b881ab253c23c61f100
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 11:35:07 2021 +0100
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 9f43b94..1b74c2b 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1884,7 +1884,7 @@ public class JNDIRealm extends RealmBase {
}
// 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);
@@ -1956,7 +1956,7 @@ 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 = connection.roleFormat.format(new String[] { doRFC2254Encoding(group.getKey()),
+ filter = connection.roleFormat.format(new String[] { doFilterEscaping(group.getKey()),
group.getValue(), group.getValue() });
if (containerLog.isTraceEnabled()) {
@@ -2754,10 +2754,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);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 01/10: Start to expand JNDIRealm unit tests
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit a1d06d540e74ee9a7eda27d97da33bc92ed2cbf4
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 10:13:12 2021 +0100
Start to expand JNDIRealm unit tests
---
build.properties.default | 9 ++
build.xml | 9 ++
.../catalina/realm/TestJNDIRealmIntegration.java | 144 +++++++++++++++++++++
webapps/docs/changelog.xml | 8 ++
4 files changed, 170 insertions(+)
diff --git a/build.properties.default b/build.properties.default
index 922064c..616ef3d 100644
--- a/build.properties.default
+++ b/build.properties.default
@@ -254,6 +254,15 @@ objenesis.home=${base.path}/objenesis-${objenesis.version}
objenesis.jar=${objenesis.home}/objenesis-${objenesis.version}.jar
objenesis.loc=${base-maven.loc}/org/objenesis/objenesis/${objenesis.version}/objenesis-${objenesis.version}.jar
+# ----- UnboundID, used by unit tests, version 5.1.4 or later -----
+unboundid.version=5.1.4
+unboundid.checksum.enabled=true
+unboundid.checksum.algorithm=SHA-512
+unboundid.checksum.value=04cf7f59eddebdd5b51e5be55021f9d9c667cca6101eac954e7a8d5b51f4c23372cd8f041640157f082435a166b75d85e79252b516130ede7d966dae6d3eae67
+unboundid.home=${base.path}/unboundid-${unboundid.version}
+unboundid.jar=${unboundid.home}/unboundid-ldapsdk-${unboundid.version}.jar
+unboundid.loc=${base-maven.loc}/com/unboundid/unboundid-ldapsdk/${unboundid.version}/unboundid-ldapsdk-${unboundid.version}.jar
+
# ----- Checkstyle, version 6.16 or later -----
# Checkstyle 7 requires Java 8
# Therefore, use checkstyle-backport-jre6
diff --git a/build.xml b/build.xml
index 3368c10..fffa5c1 100644
--- a/build.xml
+++ b/build.xml
@@ -2905,6 +2905,15 @@ skip.installer property in build.properties" />
<param name="checksum.value" value="${objenesis.checksum.value}"/>
</antcall>
+ <antcall target="downloadfile">
+ <param name="sourcefile" value="${unboundid.loc}"/>
+ <param name="destfile" value="${unboundid.jar}"/>
+ <param name="destdir" value="${unboundid.home}"/>
+ <param name="checksum.enabled" value="${unboundid.checksum.enabled}"/>
+ <param name="checksum.algorithm" value="${unboundid.checksum.algorithm}"/>
+ <param name="checksum.value" value="${unboundid.checksum.value}"/>
+ </antcall>
+
</target>
<target name="download-cobertura"
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
new file mode 100644
index 0000000..03e1655
--- /dev/null
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -0,0 +1,144 @@
+/*
+ * 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.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+import org.apache.juli.logging.LogFactory;
+
+import com.unboundid.ldap.listener.InMemoryDirectoryServer;
+import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
+import com.unboundid.ldap.sdk.AddRequest;
+import com.unboundid.ldap.sdk.LDAPConnection;
+import com.unboundid.ldap.sdk.LDAPResult;
+import com.unboundid.ldap.sdk.ResultCode;
+
+@RunWith(Parameterized.class)
+public class TestJNDIRealmIntegration {
+
+ private static InMemoryDirectoryServer ldapServer;
+
+ @Parameterized.Parameters(name = "{index}: in[{0}], out[{1}]")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+
+ parameterSets.add(new Object[] { "test", "test", new String[] {"TestGroup"} });
+
+ return parameterSets;
+ }
+
+
+ @Parameter(0)
+ public String username;
+ @Parameter(1)
+ public String credentials;
+ @Parameter(2)
+ public String[] groups;
+
+ @Test
+ public void testAuthenication() throws Exception {
+ JNDIRealm realm = new JNDIRealm();
+ realm.containerLog = LogFactory.getLog(TestJNDIRealmIntegration.class);
+
+ realm.setConnectionURL("ldap://localhost:" + ldapServer.getListenPort());
+ realm.setUserPattern("cn={0},ou=people,dc=example,dc=com");
+ realm.setRoleName("cn");
+ realm.setRoleBase("ou=people,dc=example,dc=com");
+ realm.setRoleSearch("member={0}");
+
+ GenericPrincipal p = (GenericPrincipal) realm.authenticate(username, credentials);
+
+ Assert.assertNotNull(p);
+ Assert.assertEquals(username, p.name);
+
+ Set<String> actualGroups = new HashSet<>(Arrays.asList(p.getRoles()));
+ Set<String> expectedGroups = new HashSet<>(Arrays.asList(groups));
+
+ Assert.assertEquals(expectedGroups.size(), actualGroups.size());
+ Set<String> tmp = new HashSet<>();
+ tmp.addAll(expectedGroups);
+ tmp.removeAll(actualGroups);
+ Assert.assertEquals(0, tmp.size());
+ }
+
+
+ @BeforeClass
+ public static void createLDAP() throws Exception {
+ InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
+ config.addAdditionalBindCredentials("cn=admin", "password");
+ ldapServer = new InMemoryDirectoryServer(config);
+
+ ldapServer.startListening();
+
+ try (LDAPConnection conn = ldapServer.getConnection()) {
+
+ AddRequest addBase = new AddRequest(
+ "dn: dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: domain",
+ "dc: example");
+ LDAPResult result = conn.processOperation(addBase);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addPeople = new AddRequest(
+ "dn: ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: organizationalUnit");
+ result = conn.processOperation(addPeople);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addUserTest = new AddRequest(
+ "dn: cn=test,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "cn: test",
+ "sn: Test",
+ "userPassword: test");
+ result = conn.processOperation(addUserTest);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addGroupTest = new AddRequest(
+ "dn: cn=TestGroup,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: groupOfNames",
+ "cn: TestGroup",
+ "member: cn=test,ou=people,dc=example,dc=com");
+ result = conn.processOperation(addGroupTest);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+ }
+ }
+
+
+ @AfterClass
+ public static void destroyLDAP() {
+ ldapServer.shutDown(true);
+ }
+}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 07d4857..2f71b9a 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -104,6 +104,14 @@
issues do not "pop up" wrt. others).
-->
<section name="Tomcat 8.5.66 (markt)" rtext="in development">
+ <subsection name="Catalina">
+ <changelog>
+ <scode>
+ Expand coverage of unit tests for JNDIRealm using the UnboundID LDAP SDK
+ for Java. (markt)
+ </scode>
+ </changelog>
+ </subsection>
<subsection name="Jasper">
<changelog>
<scode>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 08/10: Expand testing to cover substitution in roleBase.
Fix bugs.
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 6a9129ac9bd06555ce04bb564a76fc3987311f38
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 14:47:07 2021 +0100
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 +-
.../catalina/realm/TestJNDIRealmIntegration.java | 56 +++++++++++++++++-----
2 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 437e9a9..33895e4 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1935,7 +1935,7 @@ public class JNDIRealm extends RealmBase {
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);
@@ -1982,7 +1982,7 @@ public class JNDIRealm extends RealmBase {
" and filter " + filter);
}
- results = searchAsUser(connection.context, user, roleBase, filter, controls, isRoleSearchAsUser());
+ results = searchAsUser(connection.context, user, base, filter, controls, isRoleSearchAsUser());
try {
while (results.hasMore()) {
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index cf47369..d019fc0 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -49,29 +49,32 @@ public class TestJNDIRealmIntegration {
private static final String ROLE_SEARCH_A = "member={0}";
private static final String ROLE_SEARCH_B = "member=cn={1},ou=people,dc=example,dc=com";
private static final String ROLE_SEARCH_C = "member=cn={2},ou=people,dc=example,dc=com";
+ private static final String ROLE_BASE = "ou=people,dc=example,dc=com";
private static InMemoryDirectoryServer ldapServer;
- @Parameterized.Parameters(name = "{index}: user[{4}], pwd[{5}]")
+ @Parameterized.Parameters(name = "{index}: user[{5}], pwd[{6}]")
public static Collection<Object[]> parameters() {
List<Object[]> parameterSets = new ArrayList<>();
for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B, ROLE_SEARCH_C }) {
- addUsers(USER_PATTERN, null, null, roleSearch, parameterSets);
- addUsers(null, USER_SEARCH, USER_BASE, roleSearch, parameterSets);
+ addUsers(USER_PATTERN, null, null, roleSearch, ROLE_BASE, parameterSets);
+ addUsers(null, USER_SEARCH, USER_BASE, roleSearch, ROLE_BASE, parameterSets);
}
+ parameterSets.add(new Object[] { "cn={0},ou=sub,ou=people,dc=example,dc=com", null, null, ROLE_SEARCH_A,
+ "{3},ou=people,dc=example,dc=com", "testsub", "test", new String[] {"TestGroup4"} });
return parameterSets;
}
private static void addUsers(String userPattern, String userSearch, String userBase, String roleSearch,
- List<Object[]> parameterSets) {
- parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
+ String roleBase, List<Object[]> parameterSets) {
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase,
"test", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase,
"t;", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase,
"t*", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase,
"t=", "test", new String[] {"Test<Group*2", "Test>Group*3"} });
}
@@ -85,10 +88,12 @@ public class TestJNDIRealmIntegration {
@Parameter(3)
public String realmConfigRoleSearch;
@Parameter(4)
- public String username;
+ public String realmConfigRoleBase;
@Parameter(5)
- public String credentials;
+ public String username;
@Parameter(6)
+ public String credentials;
+ @Parameter(7)
public String[] groups;
@Test
@@ -102,7 +107,7 @@ public class TestJNDIRealmIntegration {
realm.setUserBase(realmConfigUserBase);
realm.setUserRoleAttribute("cn");
realm.setRoleName("cn");
- realm.setRoleBase("ou=people,dc=example,dc=com");
+ realm.setRoleBase(realmConfigRoleBase);
realm.setRoleSearch(realmConfigRoleSearch);
realm.setRoleNested(true);
@@ -171,7 +176,7 @@ public class TestJNDIRealmIntegration {
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
AddRequest addUserTestAsterisk = new AddRequest(
- "dn: cn=t\\*,ou=people,dc=example,dc=com",
+ "dn: cn=t*,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
@@ -220,6 +225,33 @@ public class TestJNDIRealmIntegration {
"member: cn=Test\\<Group*2,ou=people,dc=example,dc=com");
result = conn.processOperation(addGroupTest3);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addPeopleSub = new AddRequest(
+ "dn: ou=sub,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: organizationalUnit");
+ result = conn.processOperation(addPeopleSub);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addUserTestSub = new AddRequest(
+ "dn: cn=testsub,ou=sub,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "cn: testsub",
+ "sn: Testsub",
+ "userPassword: test");
+ result = conn.processOperation(addUserTestSub);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addGroupTest4 = new AddRequest(
+ "dn: cn=TestGroup4,ou=sub,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: groupOfNames",
+ "cn: TestGroup4",
+ "member: cn=testsub,ou=sub,ou=people,dc=example,dc=com");
+ result = conn.processOperation(addGroupTest4);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 10/10: Update changelog
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 999a22d1eca9e62be04d24a8e508c2afe1fcbada
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 15:19:37 2021 +0100
Update changelog
---
webapps/docs/changelog.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2f71b9a..63c9e6e 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -110,6 +110,10 @@
Expand coverage of unit tests for JNDIRealm using the UnboundID LDAP SDK
for Java. (markt)
</scode>
+ <fix>
+ <bug>65224</bug>: Ensure the correct escaping of attribute values and
+ search filters in the JNDIRealm. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 09/10: Expand tests to cover escaping of substituted
roleBaes values
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit ad22db641dcd61c2e8078f658fa709897b5da375
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 15:19:31 2021 +0100
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 +++-
test/org/apache/catalina/realm/TestJNDIRealmIntegration.java | 10 +++++-----
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 33895e4..f1354d1 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1912,7 +1912,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 = connection.roleBaseFormat.format(nameParts);
} else {
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index d019fc0..cd69267 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -60,7 +60,7 @@ public class TestJNDIRealmIntegration {
addUsers(USER_PATTERN, null, null, roleSearch, ROLE_BASE, parameterSets);
addUsers(null, USER_SEARCH, USER_BASE, roleSearch, ROLE_BASE, parameterSets);
}
- parameterSets.add(new Object[] { "cn={0},ou=sub,ou=people,dc=example,dc=com", null, null, ROLE_SEARCH_A,
+ parameterSets.add(new Object[] { "cn={0},ou=s\\;ub,ou=people,dc=example,dc=com", null, null, ROLE_SEARCH_A,
"{3},ou=people,dc=example,dc=com", "testsub", "test", new String[] {"TestGroup4"} });
return parameterSets;
}
@@ -227,14 +227,14 @@ public class TestJNDIRealmIntegration {
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
AddRequest addPeopleSub = new AddRequest(
- "dn: ou=sub,ou=people,dc=example,dc=com",
+ "dn: ou=s\\;ub,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: organizationalUnit");
result = conn.processOperation(addPeopleSub);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
AddRequest addUserTestSub = new AddRequest(
- "dn: cn=testsub,ou=sub,ou=people,dc=example,dc=com",
+ "dn: cn=testsub,ou=s\\;ub,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
@@ -245,11 +245,11 @@ public class TestJNDIRealmIntegration {
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
AddRequest addGroupTest4 = new AddRequest(
- "dn: cn=TestGroup4,ou=sub,ou=people,dc=example,dc=com",
+ "dn: cn=TestGroup4,ou=s\\;ub,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: groupOfNames",
"cn: TestGroup4",
- "member: cn=testsub,ou=sub,ou=people,dc=example,dc=com");
+ "member: cn=testsub,ou=s\\;ub,ou=people,dc=example,dc=com");
result = conn.processOperation(addGroupTest4);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 05/10: Expand tests and fix an issue in escaping for group
search
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4e86b4ea0d1a9b00fa93971c31b93ad1bd49c7fe
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 12:11:35 2021 +0100
Expand tests and fix an issue in escaping for group search
---
java/org/apache/catalina/realm/JNDIRealm.java | 9 +++++++-
.../catalina/realm/TestJNDIRealmIntegration.java | 26 ++++++++++++++--------
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index a1e9bc7..d6976c7 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1855,7 +1855,11 @@ public class JNDIRealm extends RealmBase {
return null;
}
+ // 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();
@@ -1888,7 +1892,10 @@ public class JNDIRealm extends RealmBase {
}
// 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);
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index ef0cc35..3d9969e 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -46,24 +46,29 @@ public class TestJNDIRealmIntegration {
private static final String USER_PATTERN = "cn={0},ou=people,dc=example,dc=com";
private static final String USER_SEARCH = "cn={0}";
private static final String USER_BASE = "ou=people,dc=example,dc=com";
+ private static final String ROLE_SEARCH_A = "member={0}";
+ private static final String ROLE_SEARCH_B = "member=cn={1},ou=people,dc=example,dc=com";
private static InMemoryDirectoryServer ldapServer;
@Parameterized.Parameters(name = "{index}: user[{3}], pwd[{4}]")
public static Collection<Object[]> parameters() {
List<Object[]> parameterSets = new ArrayList<>();
- addUsers(USER_PATTERN, null, null, parameterSets);
- addUsers(null, USER_SEARCH, USER_BASE, parameterSets);
+ for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B }) {
+ addUsers(USER_PATTERN, null, null, roleSearch, parameterSets);
+ addUsers(null, USER_SEARCH, USER_BASE, roleSearch, parameterSets);
+ }
return parameterSets;
}
- private static void addUsers(String userPattern, String userSearch, String userBase, List<Object[]> parameterSets) {
- parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ private static void addUsers(String userPattern, String userSearch, String userBase, String roleSearch,
+ List<Object[]> parameterSets) {
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
"test", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
"t;", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
"t*", "test", new String[] {"TestGroup"} });
}
@@ -75,10 +80,12 @@ public class TestJNDIRealmIntegration {
@Parameter(2)
public String realmConfigUserBase;
@Parameter(3)
- public String username;
+ public String realmConfigRoleSearch;
@Parameter(4)
- public String credentials;
+ public String username;
@Parameter(5)
+ public String credentials;
+ @Parameter(6)
public String[] groups;
@Test
@@ -90,9 +97,10 @@ public class TestJNDIRealmIntegration {
realm.setUserPattern(realmConfigUserPattern);
realm.setUserSearch(realmConfigUserSearch);
realm.setUserBase(realmConfigUserBase);
+ realm.setUserRoleAttribute("cn");
realm.setRoleName("cn");
realm.setRoleBase("ou=people,dc=example,dc=com");
- realm.setRoleSearch("member={0}");
+ realm.setRoleSearch(realmConfigRoleSearch);
GenericPrincipal p = (GenericPrincipal) realm.authenticate(username, credentials);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 07/10: Expanded tests to cover nested roles and fix
escaping issues in search
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d3407672774e372fae8b5898d55f85d16f22b972
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 12:54:24 2021 +0100
Expanded tests to cover nested roles and fix escaping issues in search
---
java/org/apache/catalina/realm/JNDIRealm.java | 9 ++++--
.../catalina/realm/TestJNDIRealmIntegration.java | 34 +++++++++++++++++++++-
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 7598539..437e9a9 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1969,8 +1969,13 @@ 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 = 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 +
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index 8302e47..cf47369 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -52,7 +52,7 @@ public class TestJNDIRealmIntegration {
private static InMemoryDirectoryServer ldapServer;
- @Parameterized.Parameters(name = "{index}: user[{3}], pwd[{4}]")
+ @Parameterized.Parameters(name = "{index}: user[{4}], pwd[{5}]")
public static Collection<Object[]> parameters() {
List<Object[]> parameterSets = new ArrayList<>();
for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B, ROLE_SEARCH_C }) {
@@ -71,6 +71,8 @@ public class TestJNDIRealmIntegration {
"t;", "test", new String[] {"TestGroup"} });
parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
"t*", "test", new String[] {"TestGroup"} });
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch,
+ "t=", "test", new String[] {"Test<Group*2", "Test>Group*3"} });
}
@@ -102,6 +104,7 @@ public class TestJNDIRealmIntegration {
realm.setRoleName("cn");
realm.setRoleBase("ou=people,dc=example,dc=com");
realm.setRoleSearch(realmConfigRoleSearch);
+ realm.setRoleNested(true);
GenericPrincipal p = (GenericPrincipal) realm.authenticate(username, credentials);
@@ -178,6 +181,17 @@ public class TestJNDIRealmIntegration {
result = conn.processOperation(addUserTestAsterisk);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+ AddRequest addUserTestEquals = new AddRequest(
+ "dn: cn=t\\=,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "cn: t=",
+ "sn: Tequals",
+ "userPassword: test");
+ result = conn.processOperation(addUserTestEquals);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
AddRequest addGroupTest = new AddRequest(
"dn: cn=TestGroup,ou=people,dc=example,dc=com",
"objectClass: top",
@@ -188,6 +202,24 @@ public class TestJNDIRealmIntegration {
"member: cn=t\\*,ou=people,dc=example,dc=com");
result = conn.processOperation(addGroupTest);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addGroupTest2 = new AddRequest(
+ "dn: cn=Test\\<Group*2,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: groupOfNames",
+ "cn: Test<Group*2",
+ "member: cn=t\\=,ou=people,dc=example,dc=com");
+ result = conn.processOperation(addGroupTest2);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
+ AddRequest addGroupTest3 = new AddRequest(
+ "dn: cn=Test\\>Group*3,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: groupOfNames",
+ "cn: Test>Group*3",
+ "member: cn=Test\\<Group*2,ou=people,dc=example,dc=com");
+ result = conn.processOperation(addGroupTest3);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 04/10: Expand tests and fix escaping issue when searching
for users by filter
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit c9f21a2a7908c7c4ecd4f9bb495d3ee36a2bd822
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 13 11:43:51 2021 +0100
Expand tests and fix escaping issue when searching for users by filter
---
java/org/apache/catalina/realm/JNDIRealm.java | 6 ++-
.../catalina/realm/TestJNDIRealmIntegration.java | 52 +++++++++++++++++-----
2 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index 1b74c2b..a1e9bc7 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1593,7 +1593,9 @@ public class JNDIRealm extends RealmBase {
}
// 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();
@@ -1761,6 +1763,8 @@ public class JNDIRealm extends RealmBase {
return false;
}
+ // This is returned from the directory so will be attribute value
+ // escaped if required
String dn = user.getDN();
if (dn == null) {
return false;
diff --git a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
index ca45053..ef0cc35 100644
--- a/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
+++ b/test/org/apache/catalina/realm/TestJNDIRealmIntegration.java
@@ -43,24 +43,42 @@ import com.unboundid.ldap.sdk.ResultCode;
@RunWith(Parameterized.class)
public class TestJNDIRealmIntegration {
+ private static final String USER_PATTERN = "cn={0},ou=people,dc=example,dc=com";
+ private static final String USER_SEARCH = "cn={0}";
+ private static final String USER_BASE = "ou=people,dc=example,dc=com";
+
private static InMemoryDirectoryServer ldapServer;
- @Parameterized.Parameters(name = "{index}: in[{0}], out[{1}]")
+ @Parameterized.Parameters(name = "{index}: user[{3}], pwd[{4}]")
public static Collection<Object[]> parameters() {
List<Object[]> parameterSets = new ArrayList<>();
+ addUsers(USER_PATTERN, null, null, parameterSets);
+ addUsers(null, USER_SEARCH, USER_BASE, parameterSets);
+ return parameterSets;
+ }
- parameterSets.add(new Object[] { "test", "test", new String[] {"TestGroup"} });
- parameterSets.add(new Object[] { "t;", "test", new String[] {"TestGroup"} });
- return parameterSets;
+ private static void addUsers(String userPattern, String userSearch, String userBase, List<Object[]> parameterSets) {
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ "test", "test", new String[] {"TestGroup"} });
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ "t;", "test", new String[] {"TestGroup"} });
+ parameterSets.add(new Object[] { userPattern, userSearch, userBase,
+ "t*", "test", new String[] {"TestGroup"} });
}
@Parameter(0)
- public String username;
+ public String realmConfigUserPattern;
@Parameter(1)
- public String credentials;
+ public String realmConfigUserSearch;
@Parameter(2)
+ public String realmConfigUserBase;
+ @Parameter(3)
+ public String username;
+ @Parameter(4)
+ public String credentials;
+ @Parameter(5)
public String[] groups;
@Test
@@ -69,7 +87,9 @@ public class TestJNDIRealmIntegration {
realm.containerLog = LogFactory.getLog(TestJNDIRealmIntegration.class);
realm.setConnectionURL("ldap://localhost:" + ldapServer.getListenPort());
- realm.setUserPattern("cn={0},ou=people,dc=example,dc=com");
+ realm.setUserPattern(realmConfigUserPattern);
+ realm.setUserSearch(realmConfigUserSearch);
+ realm.setUserBase(realmConfigUserBase);
realm.setRoleName("cn");
realm.setRoleBase("ou=people,dc=example,dc=com");
realm.setRoleSearch("member={0}");
@@ -131,19 +151,31 @@ public class TestJNDIRealmIntegration {
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
- "cn: test",
- "sn: Test",
+ "cn: t\\;",
+ "sn: Tsemicolon",
"userPassword: test");
result = conn.processOperation(addUserTestSemicolon);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+ AddRequest addUserTestAsterisk = new AddRequest(
+ "dn: cn=t\\*,ou=people,dc=example,dc=com",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "cn: t\\*",
+ "sn: Tasterisk",
+ "userPassword: test");
+ result = conn.processOperation(addUserTestAsterisk);
+ Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
+
AddRequest addGroupTest = new AddRequest(
"dn: cn=TestGroup,ou=people,dc=example,dc=com",
"objectClass: top",
"objectClass: groupOfNames",
"cn: TestGroup",
"member: cn=test,ou=people,dc=example,dc=com",
- "member: cn=t\\;,ou=people,dc=example,dc=com");
+ "member: cn=t\\;,ou=people,dc=example,dc=com",
+ "member: cn=t\\*,ou=people,dc=example,dc=com");
result = conn.processOperation(addGroupTest);
Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode());
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org