From 04fac30d756769aaa62d7758d222fe96279a8d50 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Fri, 13 Dec 2013 17:19:43 -0600 Subject: [PATCH] SEC-2449: default port should fallback to dynamic value --- .../LdapServerBeanDefinitionParserTests.java | 24 ++++++++++--- .../ldap/LdapServerBeanDefinitionParser.java | 34 +++++++++++++++++-- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java index ed6bf73ec9..52b9f216c4 100644 --- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java @@ -12,7 +12,10 @@ */ package org.springframework.security.config.ldap; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.net.ServerSocket; import org.junit.After; import org.junit.Test; @@ -50,10 +53,11 @@ public class LdapServerBeanDefinitionParserTests { } @Test - public void useOfUrlAttributeCreatesCorrectContextSource() { + public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception { + int port = getDefaultPort(); // Create second "server" with a url pointing at embedded one - appCtx = new InMemoryXmlApplicationContext("" + - ""); + appCtx = new InMemoryXmlApplicationContext("" + + ""); // Check the default context source is still there. appCtx.getBean(BeanIds.CONTEXT_SOURCE); @@ -83,4 +87,16 @@ public class LdapServerBeanDefinitionParserTests { assertEquals("classpath*:*.ldif", ReflectionTestUtils.getField(dsContainer, "ldifResources")); } + + private int getDefaultPort() throws IOException { + ServerSocket server = null; + try { + server = new ServerSocket(0); + return server.getLocalPort(); + } finally { + try { + server.close(); + } catch(IOException e) {} + } + } } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index 2ee269d458..e4d07d60ee 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java @@ -1,5 +1,8 @@ package org.springframework.security.config.ldap; +import java.io.IOException; +import java.net.ServerSocket; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; @@ -9,6 +12,7 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.config.BeanIds; +import org.springframework.security.ldap.server.ApacheDSContainer; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -40,7 +44,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { /** Defines the port the LDAP_PROVIDER server should run on */ public static final String ATT_PORT = "port"; - public static final String OPT_DEFAULT_PORT = "33389"; + private static final int DEFAULT_PORT = 33389; + public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT); public BeanDefinition parse(Element elt, ParserContext parserContext) { @@ -101,7 +106,10 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { String port = element.getAttribute(ATT_PORT); if (!StringUtils.hasText(port)) { - port = OPT_DEFAULT_PORT; + port = getDefaultPort(); + if(logger.isDebugEnabled()) { + logger.debug("Using default port of " + port); + } } String url = "ldap://127.0.0.1:" + port + "/" + suffix; @@ -134,4 +142,26 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { return (RootBeanDefinition) contextSource.getBeanDefinition(); } + + private String getDefaultPort() { + ServerSocket serverSocket = null; + try { + try { + serverSocket = new ServerSocket(DEFAULT_PORT); + } catch (IOException e) { + try { + serverSocket = new ServerSocket(0); + } catch(IOException e2) { + return String.valueOf(DEFAULT_PORT); + } + } + return String.valueOf(serverSocket.getLocalPort()); + } finally { + if(serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) {} + } + } + } }