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:23:23 UTC
[tomcat] branch master updated (1db93d3 -> b201511)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git.
from 1db93d3 Update version number
new fa4d19c Start to expand JNDIRealm unit tests
new f4d9bde Add attribute value escaping to support user names containing ';'
new 4e61e1d Rename for clarity
new d5303a5 Expand tests and fix escaping issue when searching for users by filter
new b930d0b Expand tests and fix an issue in escaping for group search
new 17208c6 Expand tests and fix escaping issue in userRoleAttribute filter
new bd4d1fb Expanded tests to cover nested roles and fix escaping issues in search
new 81f16b0 Expand testing to cover substitution in roleBase. Fix bugs.
new eeb7351 Expand tests to cover escaping of substituted roleBaes values
new b201511 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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit eeb7351219bd8803c0053e1e80444664a7cf5b51
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 43e9ca8..04768e8 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1904,7 +1904,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit fa4d19c0c6ea28eae41c29ed5b16a2ccbd7e9ba1
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 fd8d153..2c3323a 100644
--- a/build.properties.default
+++ b/build.properties.default
@@ -250,6 +250,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.version=8.22
checkstyle.checksum.enabled=true
diff --git a/build.xml b/build.xml
index 38aeaf2..835cc36 100644
--- a/build.xml
+++ b/build.xml
@@ -3271,6 +3271,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 8e002bd..646bdab 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 10.0.6 (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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit b930d0b3161d9ec78d5fa57f886ed2de4680518b
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 ec36187..cdb9f9e 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1847,7 +1847,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();
@@ -1880,7 +1884,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 17208c645d68d2af1444ee8c64f36a9b8f0ba76f
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 cdb9f9e..59a56d8 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1883,11 +1883,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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f4d9bdef53ec009b7717620d890465fa273721a6
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 cda0603..dc10675 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1541,8 +1541,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);
@@ -2823,6 +2826,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 81f16b0a7186ed02efbfac336589d6cff28d1e89
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 4f61ad6..43e9ca8 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1927,7 +1927,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);
@@ -1974,7 +1974,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit bd4d1fbe9146dff4714130594afd668406a6a5ef
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 59a56d8..4f61ad6 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1961,8 +1961,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4e61e1d625a4a64d6b775e3a03c77a0b100d56d7
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 dc10675..c16c7b7 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1876,7 +1876,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);
@@ -1948,7 +1948,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()) {
@@ -2738,10 +2738,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] 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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d5303a506c7533803d2b3bc46e6120ce673a6667
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 c16c7b7..ec36187 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -1585,7 +1585,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();
@@ -1753,6 +1755,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
[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 master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit b201511dfb4f74faa5ebd21248a269bbbd9b21b4
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 646bdab..e898958 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