| /* |
| * 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.net.InetAddress; |
| 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.listener.InMemoryListenerConfig; |
| 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 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 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[{5}], pwd[{6}]") |
| public static Collection<Object[]> parameters() { |
| List<Object[]> parameterSets = new ArrayList<>(); |
| for (String userRoleAttribute : new String[] { "cn", null }) { |
| for (String roleSearch : new String[] { ROLE_SEARCH_A, ROLE_SEARCH_B, ROLE_SEARCH_C }) { |
| if (userRoleAttribute != null) { |
| addUsers(USER_PATTERN, null, null, roleSearch, ROLE_BASE, userRoleAttribute, parameterSets, 1); |
| addUsers(USER_PATTERN, null, null, roleSearch, ROLE_BASE, userRoleAttribute, parameterSets, 4); |
| addUsers(null, USER_SEARCH, USER_BASE, roleSearch, ROLE_BASE, userRoleAttribute, parameterSets, 1); |
| addUsers(null, USER_SEARCH, USER_BASE, roleSearch, ROLE_BASE, userRoleAttribute, parameterSets, 4); |
| } |
| } |
| 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" }, |
| userRoleAttribute, Integer.valueOf(1) }); |
| 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" }, |
| userRoleAttribute, Integer.valueOf(4) }); |
| } |
| return parameterSets; |
| } |
| |
| |
| private static void addUsers(String userPattern, String userSearch, String userBase, String roleSearch, |
| String roleBase, String userRoleAttribute, List<Object[]> parameterSets, int poolSize) { |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "test", "test", new String[] {"TestGroup"}, userRoleAttribute, Integer.valueOf(poolSize) }); |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "t;", "test", new String[] {"TestGroup"}, userRoleAttribute, Integer.valueOf(poolSize) }); |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "t*", "test", new String[] {"TestGroup"}, userRoleAttribute, Integer.valueOf(poolSize) }); |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "t=", "test", new String[] {"Test<Group*2", "Test>Group*3"}, userRoleAttribute, Integer.valueOf(poolSize) }); |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "norole", "test", new String[0], userRoleAttribute, Integer.valueOf(poolSize) }); |
| // Bug 65373 |
| parameterSets.add(new Object[] { userPattern, userSearch, userBase, roleSearch, roleBase, |
| "<>+=\"#;,rrr", "<>+=\"#;,rrr", new String[0], userRoleAttribute, Integer.valueOf(poolSize) }); |
| } |
| |
| |
| @Parameter(0) |
| public String realmConfigUserPattern; |
| @Parameter(1) |
| public String realmConfigUserSearch; |
| @Parameter(2) |
| public String realmConfigUserBase; |
| @Parameter(3) |
| public String realmConfigRoleSearch; |
| @Parameter(4) |
| public String realmConfigRoleBase; |
| @Parameter(5) |
| public String username; |
| @Parameter(6) |
| public String credentials; |
| @Parameter(7) |
| public String[] groups; |
| @Parameter(8) |
| public String realmConfigUserRoleAttribute; |
| @Parameter(9) |
| public int poolSize; |
| |
| @Test |
| public void testAuthentication() throws Exception { |
| JNDIRealm realm = new JNDIRealm(); |
| realm.containerLog = LogFactory.getLog(TestJNDIRealmIntegration.class); |
| |
| realm.setConnectionURL("ldap://localhost:" + ldapServer.getListenPort()); |
| realm.setUserPattern(realmConfigUserPattern); |
| realm.setUserSearch(realmConfigUserSearch); |
| realm.setUserBase(realmConfigUserBase); |
| realm.setUserRoleAttribute(realmConfigUserRoleAttribute); |
| realm.setRoleName("cn"); |
| realm.setRoleBase(realmConfigRoleBase); |
| realm.setRoleSearch(realmConfigRoleSearch); |
| realm.setRoleNested(true); |
| realm.setConnectionPoolSize(poolSize); |
| |
| // If using pooling, simply try more to see what happens |
| for (int i = 0; i < poolSize; i++) { |
| 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"); |
| InetAddress localhost = InetAddress.getByName("localhost"); |
| InMemoryListenerConfig listenerConfig = |
| new InMemoryListenerConfig("localListener", localhost, 0, null, null, null); |
| config.setListenerConfigs(listenerConfig); |
| config.addAdditionalBindCredentials("cn=admin", "password"); |
| ldapServer = new InMemoryDirectoryServer(config); |
| |
| ldapServer.startListening(); |
| |
| try (LDAPConnection conn = ldapServer.getConnection()) { |
| |
| // Note: Only the DNs need attribute value escaping |
| 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 addUserTestSemicolon = new AddRequest( |
| "dn: cn=t\\;,ou=people,dc=example,dc=com", |
| "objectClass: top", |
| "objectClass: person", |
| "objectClass: organizationalPerson", |
| "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 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 addUserNoRole = new AddRequest( |
| "dn: cn=norole,ou=people,dc=example,dc=com", |
| "objectClass: top", |
| "objectClass: person", |
| "objectClass: organizationalPerson", |
| "cn: norole", |
| "sn: No Role", |
| "userPassword: test"); |
| result = conn.processOperation(addUserNoRole); |
| 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"); |
| 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()); |
| |
| AddRequest addPeopleSub = new AddRequest( |
| "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=s\\;ub,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=s\\;ub,ou=people,dc=example,dc=com", |
| "objectClass: top", |
| "objectClass: groupOfNames", |
| "cn: TestGroup4", |
| "member: cn=testsub,ou=s\\;ub,ou=people,dc=example,dc=com"); |
| result = conn.processOperation(addGroupTest4); |
| Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode()); |
| |
| // Bug 65373 |
| AddRequest addUserBug65373 = new AddRequest( |
| "dn: cn=\\3C\\3E\\2B=\\22#\\3B\\2Crrr,ou=people,dc=example,dc=com", |
| "objectClass: top", |
| "objectClass: person", |
| "objectClass: organizationalPerson", |
| "cn: <>+=\"#;,rrr", |
| "sn: Bug 65373", |
| "userPassword: <>+=\"#;,rrr"); |
| result = conn.processOperation(addUserBug65373); |
| Assert.assertEquals(ResultCode.SUCCESS, result.getResultCode()); |
| } |
| } |
| |
| |
| @AfterClass |
| public static void destroyLDAP() { |
| ldapServer.shutDown(true); |
| } |
| } |