Remove ApacheDS Support
Closes gh-13852
This commit is contained in:
@@ -15,12 +15,6 @@ dependencies {
|
||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
||||
optional 'ldapsdk:ldapsdk'
|
||||
optional "com.unboundid:unboundid-ldapsdk"
|
||||
optional "org.apache.directory.server:apacheds-core"
|
||||
optional "org.apache.directory.server:apacheds-core-entry"
|
||||
optional "org.apache.directory.server:apacheds-protocol-shared"
|
||||
optional "org.apache.directory.server:apacheds-protocol-ldap"
|
||||
optional "org.apache.directory.server:apacheds-server-jndi"
|
||||
optional 'org.apache.directory.shared:shared-ldap'
|
||||
api ('org.springframework.ldap:spring-ldap-core') {
|
||||
exclude(group: 'commons-logging', module: 'commons-logging')
|
||||
exclude(group: 'org.springframework', module: 'spring-beans')
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class DefaultSpringSecurityContextSourceTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+6
-6
@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class SpringSecurityLdapTemplateITests {
|
||||
|
||||
@Autowired
|
||||
@@ -116,10 +116,10 @@ public class SpringSecurityLdapTemplateITests {
|
||||
assertThat(values).hasSize(1);
|
||||
Map<String, List<String>> record = values.iterator().next();
|
||||
assertAttributeValue(record, "uid", "bob");
|
||||
assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "objectClass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertThat(record.containsKey("userPassword")).isFalse();
|
||||
assertThat(record.containsKey("userPassword")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,10 +129,10 @@ public class SpringSecurityLdapTemplateITests {
|
||||
assertThat(values).hasSize(1);
|
||||
Map<String, List<String>> record = values.iterator().next();
|
||||
assertAttributeValue(record, "uid", "bob");
|
||||
assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "objectClass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertThat(record.containsKey("userPassword")).isFalse();
|
||||
assertThat(record.containsKey("userPassword")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,7 +145,7 @@ public class SpringSecurityLdapTemplateITests {
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertThat(record.containsKey("userPassword")).isFalse();
|
||||
assertThat(record.containsKey("objectclass")).isFalse();
|
||||
assertThat(record.containsKey("objectClass")).isFalse();
|
||||
}
|
||||
|
||||
protected void assertAttributeValue(Map<String, List<String>> record, String attributeName, String... values) {
|
||||
|
||||
+8
-8
@@ -20,31 +20,31 @@ import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ldap.core.ContextSource;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@Configuration
|
||||
public class ApacheDsContainerConfig implements DisposableBean {
|
||||
public class UnboundIdContainerConfig implements DisposableBean {
|
||||
|
||||
private ApacheDSContainer container;
|
||||
private UnboundIdContainer container;
|
||||
|
||||
@Bean
|
||||
ApacheDSContainer ldapContainer() throws Exception {
|
||||
this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
UnboundIdContainer ldapContainer() {
|
||||
this.container = new UnboundIdContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
this.container.setPort(0);
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ContextSource contextSource(ApacheDSContainer ldapContainer) throws Exception {
|
||||
ContextSource contextSource(UnboundIdContainer ldapContainer) {
|
||||
return new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:" + ldapContainer.getLocalPort() + "/dc=springframework,dc=org");
|
||||
"ldap://127.0.0.1:" + ldapContainer.getPort() + "/dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
public void destroy() {
|
||||
this.container.stop();
|
||||
}
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
@@ -53,7 +53,7 @@ import static org.mockito.Mockito.spy;
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class BindAuthenticatorTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.keygen.KeyGenerators;
|
||||
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -46,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class PasswordComparisonAuthenticatorTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class FilterBasedLdapUserSearchTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+8
-8
@@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ldap.core.ContextSource;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = FilterBasedLdapUserSearchWithSpacesTests.ApacheDsContainerWithSpacesConfig.class)
|
||||
@ContextConfiguration(classes = FilterBasedLdapUserSearchWithSpacesTests.UnboundIdContainerWithSpacesConfig.class)
|
||||
public class FilterBasedLdapUserSearchWithSpacesTests {
|
||||
|
||||
@Autowired
|
||||
@@ -61,22 +61,22 @@ public class FilterBasedLdapUserSearchWithSpacesTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ApacheDsContainerWithSpacesConfig implements DisposableBean {
|
||||
static class UnboundIdContainerWithSpacesConfig implements DisposableBean {
|
||||
|
||||
private ApacheDSContainer container;
|
||||
private UnboundIdContainer container;
|
||||
|
||||
@Bean
|
||||
ApacheDSContainer ldapContainer() throws Exception {
|
||||
this.container = new ApacheDSContainer("dc=spring framework,dc=org",
|
||||
UnboundIdContainer ldapContainer() {
|
||||
this.container = new UnboundIdContainer("dc=spring framework,dc=org",
|
||||
"classpath:test-server-with-spaces.ldif");
|
||||
this.container.setPort(0);
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ContextSource contextSource(ApacheDSContainer ldapContainer) {
|
||||
ContextSource contextSource(UnboundIdContainer ldapContainer) {
|
||||
return new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:" + ldapContainer.getLocalPort() + "/dc=spring%20framework,dc=org");
|
||||
"ldap://127.0.0.1:" + ldapContainer.getPort() + "/dc=spring%20framework,dc=org");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-221
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.security.ldap.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Useful for debugging the container by itself.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
* @author Gunnar Hillert
|
||||
* @author Evgeniy Cheban
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ApacheDSContainerTests {
|
||||
|
||||
@TempDir
|
||||
public File temporaryFolder;
|
||||
|
||||
// SEC-2162
|
||||
@Test
|
||||
public void failsToStartThrowsException() throws Exception {
|
||||
ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:missing.ldif");
|
||||
List<Integer> ports = getDefaultPorts(1);
|
||||
server1.setPort(ports.get(0));
|
||||
server2.setPort(ports.get(0));
|
||||
try {
|
||||
server1.afterPropertiesSet();
|
||||
try {
|
||||
server2.afterPropertiesSet();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (RuntimeException success) {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
server1.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
try {
|
||||
server2.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SEC-2161
|
||||
@Test
|
||||
public void multipleInstancesSimultanciously() throws Exception {
|
||||
ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
List<Integer> ports = getDefaultPorts(2);
|
||||
server1.setPort(ports.get(0));
|
||||
server2.setPort(ports.get(1));
|
||||
try {
|
||||
server1.afterPropertiesSet();
|
||||
server2.afterPropertiesSet();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
server1.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
try {
|
||||
server2.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithLdapOverSslWithoutCertificate() throws Exception {
|
||||
ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
List<Integer> ports = getDefaultPorts(1);
|
||||
server.setPort(ports.get(0));
|
||||
server.setLdapOverSslEnabled(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(server::afterPropertiesSet)
|
||||
.withMessage("When LdapOverSsl is enabled, the keyStoreFile property must be set.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
public void startWithLdapOverSslWithWrongPassword() throws Exception {
|
||||
final ClassPathResource keyStoreResource = new ClassPathResource(
|
||||
"/org/springframework/security/ldap/server/spring.keystore");
|
||||
final File temporaryKeyStoreFile = new File(this.temporaryFolder, "spring.keystore");
|
||||
FileCopyUtils.copy(keyStoreResource.getInputStream(), new FileOutputStream(temporaryKeyStoreFile));
|
||||
|
||||
assertThat(temporaryKeyStoreFile).isFile();
|
||||
|
||||
ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
|
||||
List<Integer> ports = getDefaultPorts(1);
|
||||
server.setPort(ports.get(0));
|
||||
|
||||
server.setLdapOverSslEnabled(true);
|
||||
server.setKeyStoreFile(temporaryKeyStoreFile);
|
||||
server.setCertificatePassord("incorrect-password");
|
||||
assertThatExceptionOfType(RuntimeException.class).isThrownBy(server::afterPropertiesSet)
|
||||
.withMessage("Server startup failed")
|
||||
.withRootCauseInstanceOf(UnrecoverableKeyException.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test starts an LDAP server using LDAPs (LDAP over SSL). A self-signed
|
||||
* certificate is being used, which was previously generated with:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* keytool -genkey -alias spring -keyalg RSA -keystore spring.keystore -validity 3650 -storetype JKS \
|
||||
* -dname "CN=localhost, OU=Spring, O=Pivotal, L=Kailua-Kona, ST=HI, C=US" -keypass spring -storepass spring
|
||||
* }
|
||||
* </pre>
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
public void startWithLdapOverSsl() throws Exception {
|
||||
|
||||
final ClassPathResource keyStoreResource = new ClassPathResource(
|
||||
"/org/springframework/security/ldap/server/spring.keystore");
|
||||
final File temporaryKeyStoreFile = new File(this.temporaryFolder, "spring.keystore");
|
||||
FileCopyUtils.copy(keyStoreResource.getInputStream(), new FileOutputStream(temporaryKeyStoreFile));
|
||||
|
||||
assertThat(temporaryKeyStoreFile).isFile();
|
||||
|
||||
ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
|
||||
List<Integer> ports = getDefaultPorts(1);
|
||||
server.setPort(ports.get(0));
|
||||
|
||||
server.setLdapOverSslEnabled(true);
|
||||
server.setKeyStoreFile(temporaryKeyStoreFile);
|
||||
server.setCertificatePassord("spring");
|
||||
|
||||
try {
|
||||
server.afterPropertiesSet();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
server.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Integer> getDefaultPorts(int count) throws IOException {
|
||||
List<ServerSocket> connections = new ArrayList<>();
|
||||
List<Integer> availablePorts = new ArrayList<>(count);
|
||||
try {
|
||||
for (int i = 0; i < count; i++) {
|
||||
ServerSocket socket = new ServerSocket(0);
|
||||
connections.add(socket);
|
||||
availablePorts.add(socket.getLocalPort());
|
||||
}
|
||||
return availablePorts;
|
||||
}
|
||||
finally {
|
||||
for (ServerSocket conn : connections) {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetWhenPortIsZeroThenRandomPortIsSelected() throws Exception {
|
||||
ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
|
||||
server.setPort(0);
|
||||
try {
|
||||
server.afterPropertiesSet();
|
||||
|
||||
assertThat(server.getPort()).isEqualTo(0);
|
||||
assertThat(server.getLocalPort()).isNotEqualTo(0);
|
||||
}
|
||||
finally {
|
||||
server.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.security.ldap.server;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests reproducing problems with loading structures from ldif on embedded ApacheDS
|
||||
* server.
|
||||
*
|
||||
* @author Marcin Zajączkowski
|
||||
*/
|
||||
public class ApacheDSEmbeddedLdifTests {
|
||||
|
||||
private static final String LDAP_ROOT = "ou=ssattributes,dc=springframework,dc=org";
|
||||
|
||||
private static final int LDAP_PORT = 52389;
|
||||
|
||||
private ApacheDSContainer server;
|
||||
|
||||
private SpringSecurityLdapTemplate ldapTemplate;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
// TODO: InMemoryXmlApplicationContext would be useful here, but it is not visible
|
||||
this.server = new ApacheDSContainer(LDAP_ROOT, "classpath:test-server-custom-attribute-types.ldif");
|
||||
this.server.setPort(LDAP_PORT);
|
||||
this.server.afterPropertiesSet();
|
||||
|
||||
this.ldapTemplate = new SpringSecurityLdapTemplate(createLdapContextSource());
|
||||
}
|
||||
|
||||
private LdapContextSource createLdapContextSource() {
|
||||
LdapContextSource ldapContextSource = new LdapContextSource();
|
||||
ldapContextSource.setUrl("ldap://localhost:" + LDAP_PORT);
|
||||
ldapContextSource.setBase(LDAP_ROOT);
|
||||
ldapContextSource.afterPropertiesSet();
|
||||
return ldapContextSource;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
if (this.server != null) {
|
||||
this.server.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Disabled // Not fixed yet
|
||||
@Test // SEC-2387
|
||||
public void customAttributeTypesShouldBeProperlyCreatedWhenLoadedFromLdif() {
|
||||
assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "uid", "objectWithCustomAttribute1"))
|
||||
.isTrue();
|
||||
assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "customAttribute", "I am custom"))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
+8
-8
@@ -31,7 +31,7 @@ import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(
|
||||
classes = DefaultLdapAuthoritiesPopulatorGetGrantedAuthoritiesTests.ApacheDsContainerWithUndefinedGroupRoleAttributeConfig.class)
|
||||
classes = DefaultLdapAuthoritiesPopulatorGetGrantedAuthoritiesTests.UnboundIdContainerWithUndefinedGroupRoleAttributeConfig.class)
|
||||
public class DefaultLdapAuthoritiesPopulatorGetGrantedAuthoritiesTests {
|
||||
|
||||
@Autowired
|
||||
@@ -77,22 +77,22 @@ public class DefaultLdapAuthoritiesPopulatorGetGrantedAuthoritiesTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ApacheDsContainerWithUndefinedGroupRoleAttributeConfig implements DisposableBean {
|
||||
static class UnboundIdContainerWithUndefinedGroupRoleAttributeConfig implements DisposableBean {
|
||||
|
||||
private ApacheDSContainer container;
|
||||
private UnboundIdContainer container;
|
||||
|
||||
@Bean
|
||||
ApacheDSContainer ldapContainer() throws Exception {
|
||||
this.container = new ApacheDSContainer("dc=springframework,dc=org",
|
||||
UnboundIdContainer ldapContainer() {
|
||||
this.container = new UnboundIdContainer("dc=springframework,dc=org",
|
||||
"classpath:test-server-with-undefined-group-role-attributes.ldif");
|
||||
this.container.setPort(0);
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ContextSource contextSource(ApacheDSContainer ldapContainer) {
|
||||
ContextSource contextSource(UnboundIdContainer ldapContainer) {
|
||||
return new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:" + ldapContainer.getLocalPort() + "/dc=springframework,dc=org");
|
||||
"ldap://127.0.0.1:" + ldapContainer.getPort() + "/dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@ import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -44,7 +44,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
|
||||
|
||||
+2
-2
@@ -34,9 +34,9 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
|
||||
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -52,7 +52,7 @@ import static org.mockito.Mockito.verify;
|
||||
* @author Roman Zabaluev
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class LdapUserDetailsManagerTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ldap.core.ContextSource;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.ldap.ApacheDsContainerConfig;
|
||||
import org.springframework.security.ldap.UnboundIdContainerConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = ApacheDsContainerConfig.class)
|
||||
@ContextConfiguration(classes = UnboundIdContainerConfig.class)
|
||||
public class NestedLdapAuthoritiesPopulatorTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.security.ldap.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.directory.server.core.DefaultDirectoryService;
|
||||
import org.apache.directory.server.core.authn.AuthenticationInterceptor;
|
||||
import org.apache.directory.server.core.entry.ServerEntry;
|
||||
import org.apache.directory.server.core.exception.ExceptionInterceptor;
|
||||
import org.apache.directory.server.core.interceptor.Interceptor;
|
||||
import org.apache.directory.server.core.normalization.NormalizationInterceptor;
|
||||
import org.apache.directory.server.core.operational.OperationalAttributeInterceptor;
|
||||
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
|
||||
import org.apache.directory.server.core.referral.ReferralInterceptor;
|
||||
import org.apache.directory.server.core.subtree.SubentryInterceptor;
|
||||
import org.apache.directory.server.ldap.LdapServer;
|
||||
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
|
||||
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
|
||||
import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
|
||||
import org.apache.directory.shared.ldap.name.LdapDN;
|
||||
import org.apache.mina.transport.socket.SocketAcceptor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Provides lifecycle services for the embedded apacheDS server defined by the supplied
|
||||
* configuration. Used by {@code LdapServerBeanDefinitionParser}. An instance will be
|
||||
* stored in the application context for each embedded server instance. It will start the
|
||||
* server when the context is initialized and shut it down when it is closed. It is
|
||||
* intended for temporary embedded use and will not retain changes across start/stop
|
||||
* boundaries. The working directory is deleted on shutdown.
|
||||
*
|
||||
* <p>
|
||||
* If used repeatedly in a single JVM process with the same configuration (for example,
|
||||
* when repeatedly loading an application context during testing), it's important that the
|
||||
* application context is closed to allow the bean to be disposed of and the server
|
||||
* shutdown prior to attempting to start it again.
|
||||
* <p>
|
||||
* This class is intended for testing and internal security namespace use, only, and is
|
||||
* not considered part of the framework's public API.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
* @author Gunnar Hillert
|
||||
* @author Evgeniy Cheban
|
||||
* @deprecated For removal in 7.0. Use {@link UnboundIdContainer} instead because ApacheDS
|
||||
* 1.x is no longer supported with no GA version to replace it.
|
||||
*/
|
||||
@Deprecated(since = "5.2", forRemoval = true)
|
||||
public class ApacheDSContainer
|
||||
implements EmbeddedLdapServerContainer, InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
final DefaultDirectoryService service;
|
||||
|
||||
LdapServer server;
|
||||
|
||||
private TcpTransport transport;
|
||||
|
||||
private ApplicationContext ctxt;
|
||||
|
||||
private File workingDir;
|
||||
|
||||
private boolean running;
|
||||
|
||||
private final String ldifResources;
|
||||
|
||||
private final JdbmPartition partition;
|
||||
|
||||
private final String root;
|
||||
|
||||
private int port = 53389;
|
||||
|
||||
private int localPort;
|
||||
|
||||
private boolean ldapOverSslEnabled;
|
||||
|
||||
private File keyStoreFile;
|
||||
|
||||
private String certificatePassord;
|
||||
|
||||
public ApacheDSContainer(String root, String ldifs) throws Exception {
|
||||
this.ldifResources = ldifs;
|
||||
this.service = new DefaultDirectoryService();
|
||||
List<Interceptor> list = new ArrayList<>();
|
||||
list.add(new NormalizationInterceptor());
|
||||
list.add(new AuthenticationInterceptor());
|
||||
list.add(new ReferralInterceptor());
|
||||
list.add(new ExceptionInterceptor());
|
||||
list.add(new OperationalAttributeInterceptor());
|
||||
list.add(new SubentryInterceptor());
|
||||
this.service.setInterceptors(list);
|
||||
this.partition = new JdbmPartition();
|
||||
this.partition.setId("rootPartition");
|
||||
this.partition.setSuffix(root);
|
||||
this.root = root;
|
||||
this.service.addPartition(this.partition);
|
||||
this.service.setExitVmOnShutdown(false);
|
||||
this.service.setShutdownHookEnabled(false);
|
||||
this.service.getChangeLog().setEnabled(false);
|
||||
this.service.setDenormalizeOpAttrsEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.workingDir == null) {
|
||||
String apacheWorkDir = System.getProperty("apacheDSWorkDir");
|
||||
if (apacheWorkDir == null) {
|
||||
apacheWorkDir = createTempDirectory("apacheds-spring-security-");
|
||||
}
|
||||
setWorkingDirectory(new File(apacheWorkDir));
|
||||
}
|
||||
Assert.isTrue(!this.ldapOverSslEnabled || this.keyStoreFile != null,
|
||||
"When LdapOverSsl is enabled, the keyStoreFile property must be set.");
|
||||
this.server = new LdapServer();
|
||||
this.server.setDirectoryService(this.service);
|
||||
// AbstractLdapIntegrationTests assume IPv4, so we specify the same here
|
||||
this.transport = new TcpTransport(this.port);
|
||||
if (this.ldapOverSslEnabled) {
|
||||
this.transport.setEnableSSL(true);
|
||||
this.server.setKeystoreFile(this.keyStoreFile.getAbsolutePath());
|
||||
this.server.setCertificatePassword(this.certificatePassord);
|
||||
}
|
||||
this.server.setTransports(this.transport);
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.ctxt = applicationContext;
|
||||
}
|
||||
|
||||
public void setWorkingDirectory(File workingDir) {
|
||||
Assert.notNull(workingDir, "workingDir cannot be null");
|
||||
this.logger.info("Setting working directory for LDAP_PROVIDER: " + workingDir.getAbsolutePath());
|
||||
Assert.isTrue(!workingDir.exists(),
|
||||
"The specified working directory '" + workingDir.getAbsolutePath()
|
||||
+ "' already exists. Another directory service instance may be using it or it may be from a "
|
||||
+ " previous unclean shutdown. Please confirm and delete it or configure a different "
|
||||
+ "working directory");
|
||||
this.workingDir = workingDir;
|
||||
this.service.setWorkingDirectory(workingDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port that is resolved by {@link TcpTransport}.
|
||||
* @return the port that is resolved by {@link TcpTransport}
|
||||
*/
|
||||
public int getLocalPort() {
|
||||
return this.localPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to {@code true} will enable LDAP over SSL (LDAPs). If set to {@code true}
|
||||
* {@link ApacheDSContainer#setCertificatePassord(String)} must be set as well.
|
||||
* @param ldapOverSslEnabled If not set, will default to false
|
||||
*/
|
||||
public void setLdapOverSslEnabled(boolean ldapOverSslEnabled) {
|
||||
this.ldapOverSslEnabled = ldapOverSslEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The keyStore must not be null and must be a valid file. Will set the keyStore file
|
||||
* on the underlying {@link LdapServer}.
|
||||
* @param keyStoreFile Mandatory if LDAPs is enabled
|
||||
*/
|
||||
public void setKeyStoreFile(File keyStoreFile) {
|
||||
Assert.notNull(keyStoreFile, "The keyStoreFile must not be null.");
|
||||
Assert.isTrue(keyStoreFile.isFile(), "The keyStoreFile must be a file.");
|
||||
this.keyStoreFile = keyStoreFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will set the certificate password on the underlying {@link LdapServer}.
|
||||
* @param certificatePassord May be null
|
||||
*/
|
||||
public void setCertificatePassord(String certificatePassord) {
|
||||
this.certificatePassord = certificatePassord;
|
||||
}
|
||||
|
||||
public DefaultDirectoryService getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (isRunning()) {
|
||||
return;
|
||||
}
|
||||
Assert.state(!this.service.isStarted(), "DirectoryService is already running.");
|
||||
this.logger.info("Starting directory server...");
|
||||
try {
|
||||
this.service.startup();
|
||||
this.server.start();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException("Server startup failed", ex);
|
||||
}
|
||||
try {
|
||||
this.service.getAdminSession().lookup(this.partition.getSuffixDn());
|
||||
}
|
||||
catch (LdapNameNotFoundException ex) {
|
||||
handleLdapNameNotFoundException();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.logger.error("Lookup failed", ex);
|
||||
}
|
||||
SocketAcceptor socketAcceptor = this.server.getSocketAcceptor(this.transport);
|
||||
InetSocketAddress localAddress = socketAcceptor.getLocalAddress();
|
||||
this.localPort = localAddress.getPort();
|
||||
this.running = true;
|
||||
try {
|
||||
importLdifs();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException("Failed to import LDIF file(s)", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLdapNameNotFoundException() {
|
||||
try {
|
||||
LdapDN dn = new LdapDN(this.root);
|
||||
Assert.isTrue(this.root.startsWith("dc="), "root must start with dc=");
|
||||
String dc = this.root.substring(3, this.root.indexOf(','));
|
||||
ServerEntry entry = this.service.newEntry(dn);
|
||||
entry.add("objectClass", "top", "domain", "extensibleObject");
|
||||
entry.add("dc", dc);
|
||||
this.service.getAdminSession().add(entry);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.logger.error("Failed to create dc entry", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
this.logger.info("Shutting down directory server ...");
|
||||
try {
|
||||
this.server.stop();
|
||||
this.service.shutdown();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.logger.error("Shutdown failed", ex);
|
||||
return;
|
||||
}
|
||||
this.running = false;
|
||||
if (this.workingDir.exists()) {
|
||||
this.logger.info("Deleting working directory " + this.workingDir.getAbsolutePath());
|
||||
deleteDir(this.workingDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void importLdifs() throws Exception {
|
||||
// Import any ldif files
|
||||
Resource[] ldifs = (this.ctxt != null) ? this.ctxt.getResources(this.ldifResources)
|
||||
: new PathMatchingResourcePatternResolver().getResources(this.ldifResources);
|
||||
// Note that we can't just import using the ServerContext returned
|
||||
// from starting Apache DS, apparently because of the long-running issue
|
||||
// DIRSERVER-169.
|
||||
// We need a standard context.
|
||||
// DirContext dirContext = contextSource.getReadWriteContext();
|
||||
if (ldifs == null || ldifs.length == 0) {
|
||||
return;
|
||||
}
|
||||
Assert.isTrue(ldifs.length == 1, () -> "More than one LDIF resource found with the supplied pattern:"
|
||||
+ this.ldifResources + " Got " + Arrays.toString(ldifs));
|
||||
String ldifFile = getLdifFile(ldifs);
|
||||
this.logger.info("Loading LDIF file: " + ldifFile);
|
||||
LdifFileLoader loader = new LdifFileLoader(this.service.getAdminSession(), new File(ldifFile), null,
|
||||
getClass().getClassLoader());
|
||||
loader.execute();
|
||||
}
|
||||
|
||||
private String getLdifFile(Resource[] ldifs) throws IOException {
|
||||
try {
|
||||
return ldifs[0].getFile().getAbsolutePath();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return ldifs[0].getURI().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String createTempDirectory(String prefix) throws IOException {
|
||||
String parentTempDir = System.getProperty("java.io.tmpdir");
|
||||
String fileNamePrefix = prefix + System.nanoTime();
|
||||
String fileName = fileNamePrefix;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
File tempDir = new File(parentTempDir, fileName);
|
||||
if (!tempDir.exists()) {
|
||||
return tempDir.getAbsolutePath();
|
||||
}
|
||||
fileName = fileNamePrefix + "~" + i;
|
||||
}
|
||||
throw new IOException(
|
||||
"Failed to create a temporary directory for file at " + new File(parentTempDir, fileNamePrefix));
|
||||
}
|
||||
|
||||
private boolean deleteDir(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
String[] children = dir.list();
|
||||
for (String child : children) {
|
||||
boolean success = deleteDir(new File(dir, child));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Embedded Apache Directory Server implementation, as used by the configuration
|
||||
* namespace.
|
||||
* Embedded UnboundID Server implementation, as used by the configuration namespace.
|
||||
*/
|
||||
package org.springframework.security.ldap.server;
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.directory.server.core.avltree;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.apache.directory.shared.ldap.util.StringTools;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class to serialize the Array data.
|
||||
*
|
||||
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
|
||||
* @version $Rev$, $Date$
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ArrayMarshaller<E> implements Marshaller<ArrayTree<E>> {
|
||||
|
||||
/** static logger */
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ArrayMarshaller.class);
|
||||
|
||||
/** used for serialized form of an empty AvlTree */
|
||||
private static final byte[] EMPTY_TREE = new byte[1];
|
||||
|
||||
/** marshaller to be used for marshalling the keys */
|
||||
private Marshaller<E> keyMarshaller;
|
||||
|
||||
/** key Comparator for the AvlTree */
|
||||
private Comparator<E> comparator;
|
||||
|
||||
/**
|
||||
* Creates a new instance of AvlTreeMarshaller with a custom key Marshaller.
|
||||
* @param comparator Comparator to be used for key comparision
|
||||
* @param keyMarshaller marshaller for keys
|
||||
*/
|
||||
public ArrayMarshaller(Comparator<E> comparator, Marshaller<E> keyMarshaller) {
|
||||
this.comparator = comparator;
|
||||
this.keyMarshaller = keyMarshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of AvlTreeMarshaller with the default key Marshaller which
|
||||
* uses Java Serialization.
|
||||
* @param comparator Comparator to be used for key comparision
|
||||
*/
|
||||
public ArrayMarshaller(Comparator<E> comparator) {
|
||||
this.comparator = comparator;
|
||||
this.keyMarshaller = DefaultMarshaller.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals the given tree to bytes
|
||||
* @param tree the tree to be marshalled
|
||||
*/
|
||||
public byte[] serialize(ArrayTree<E> tree) {
|
||||
if ((tree == null) || tree.isEmpty()) {
|
||||
return EMPTY_TREE;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(byteStream);
|
||||
byte[] data = null;
|
||||
|
||||
try {
|
||||
out.writeByte(0); // represents the start of an Array byte stream
|
||||
out.writeInt(tree.size());
|
||||
|
||||
for (int position = 0; position < tree.size(); position++) {
|
||||
E value = tree.get(position);
|
||||
byte[] bytes = this.keyMarshaller.serialize(value);
|
||||
|
||||
// Write the key length
|
||||
out.writeInt(bytes.length);
|
||||
|
||||
// Write the key if its length is not null
|
||||
if (bytes.length != 0) {
|
||||
out.write(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
out.flush();
|
||||
data = byteStream.toByteArray();
|
||||
|
||||
// Try to deserialize, just to see
|
||||
try {
|
||||
deserialize(data);
|
||||
}
|
||||
catch (NullPointerException npe) {
|
||||
System.out.println("Bad serialization, tree : [" + StringTools.dumpBytes(data) + "]");
|
||||
throw npe;
|
||||
}
|
||||
|
||||
out.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Array from given bytes of data.
|
||||
* @param data byte array to be converted into an array
|
||||
*/
|
||||
public ArrayTree<E> deserialize(byte[] data) throws IOException {
|
||||
try {
|
||||
if ((data == null) || (data.length == 0)) {
|
||||
throw new IOException("Null or empty data array is invalid.");
|
||||
}
|
||||
|
||||
if ((data.length == 1) && (data[0] == 0)) {
|
||||
E[] array = (E[]) new Object[] {};
|
||||
ArrayTree<E> tree = new ArrayTree<E>(this.comparator, array);
|
||||
return tree;
|
||||
}
|
||||
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(data);
|
||||
DataInputStream din = new DataInputStream(bin);
|
||||
|
||||
byte startByte = din.readByte();
|
||||
|
||||
if (startByte != 0) {
|
||||
throw new IOException("wrong array serialized data format");
|
||||
}
|
||||
|
||||
int size = din.readInt();
|
||||
E[] nodes = (E[]) new Object[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
// Read the object's size
|
||||
int dataSize = din.readInt();
|
||||
|
||||
if (dataSize != 0) {
|
||||
byte[] bytes = new byte[dataSize];
|
||||
|
||||
din.read(bytes);
|
||||
E key = this.keyMarshaller.deserialize(bytes);
|
||||
nodes[i] = key;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTree<E> arrayTree = new ArrayTree<E>(this.comparator, nodes);
|
||||
|
||||
return arrayTree;
|
||||
}
|
||||
catch (NullPointerException npe) {
|
||||
System.out.println("Bad tree : [" + StringTools.dumpBytes(data) + "]");
|
||||
throw npe;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -29,7 +29,6 @@ import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.apache.directory.shared.ldap.util.EmptyEnumeration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -175,7 +174,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||
@Test
|
||||
public void noUserSearchCausesUsernameNotFound() throws Exception {
|
||||
given(this.ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class)))
|
||||
.willReturn(new EmptyEnumeration<>());
|
||||
.willReturn(new MockNamingEnumeration(null));
|
||||
this.provider.contextFactory = createContextFactoryReturning(this.ctx);
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.provider.authenticate(this.joe));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user