VYPR
Medium severity5.9NVD Advisory· Published Apr 24, 2017· Updated May 13, 2026

CVE-2016-5016

CVE-2016-5016

Description

Pivotal Cloud Foundry 239 and earlier, UAA (aka User Account and Authentication Server) 3.4.1 and earlier, UAA release 12.2 and earlier, PCF (aka Pivotal Cloud Foundry) Elastic Runtime 1.6.x before 1.6.35, and PCF Elastic Runtime 1.7.x before 1.7.13 does not validate if a certificate is expired.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
>= 3.0.0, < 3.3.0.33.3.0.3
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
>= 3.4.0, < 3.4.23.4.2

Patches

3
0a78612f981c

Wrap trustmanager in custom trustmanager

https://github.com/cloudfoundry/uaaMadhura BhaveJul 14, 2016via ghsa
11 files changed · +423 7
  • scripts/ldap/truststore-with-ldap-certs.jks+0 0 added
  • server.jks+0 0 added
  • server/src/main/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapProperties.java+10 3 modified
    @@ -14,13 +14,16 @@
     
     package org.cloudfoundry.identity.uaa.provider.ldap;
     
    +import java.security.KeyManagementException;
    +import java.security.NoSuchAlgorithmException;
     import java.util.LinkedHashMap;
     import java.util.Map;
     
     public class ProcessLdapProperties {
     
         public static final String LDAP_SOCKET_FACTORY = "java.naming.ldap.factory.socket";
         public static final String SKIP_SSL_VERIFICATION_SOCKET_FACTORY = "org.apache.directory.api.util.DummySSLSocketFactory";
    +    public static final String EXPIRY_CHECKING_SOCKET_FACTORY = "org.cloudfoundry.identity.uaa.security.LdapSocketFactory";
     
         private boolean disableSslVerification;
         private String baseUrl;
    @@ -30,10 +33,14 @@ public ProcessLdapProperties(String baseUrl, boolean disableSslVerification) {
             this.disableSslVerification = disableSslVerification;
         }
     
    -    public Map process(Map map) {
    +    public Map process(Map map) throws KeyManagementException, NoSuchAlgorithmException {
             Map result = new LinkedHashMap(map);
    -        if (isDisableSslVerification() && isLdapsUrl()) {
    -            result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +        if(isLdapsUrl()) {
    +            if (isDisableSslVerification()) {
    +                result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +            } else {
    +                result.put(LDAP_SOCKET_FACTORY, EXPIRY_CHECKING_SOCKET_FACTORY);
    +            }
             }
             return result;
         }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactory.java+72 0 added
    @@ -0,0 +1,72 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.SocketFactory;
    +import javax.net.ssl.SSLContext;
    +import javax.net.ssl.SSLSocketFactory;
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.X509TrustManager;
    +import java.io.IOException;
    +import java.net.InetAddress;
    +import java.net.Socket;
    +import java.security.SecureRandom;
    +
    +public class LdapSocketFactory  extends SSLSocketFactory {
    +
    +  private static SocketFactory instance;
    +  private SSLSocketFactory delegate;
    +
    +  public static SocketFactory getDefault() {
    +    if(instance == null) {
    +      instance = new LdapSocketFactory();
    +    }
    +
    +    return instance;
    +  }
    +
    +  public LdapSocketFactory() {
    +    try {
    +      X509TrustManager trustManager = new X509ExpiryCheckingTrustManager();
    +      TrustManager[] tma = new TrustManager[]{trustManager};
    +      SSLContext sc = SSLContext.getInstance("TLS");
    +      sc.init(null, tma, new SecureRandom());
    +      this.delegate = sc.getSocketFactory();
    +    } catch (Exception e) {
    +      e.printStackTrace();
    +    }
    +  }
    +
    +  @Override
    +  public String[] getDefaultCipherSuites() {
    +    return delegate.getDefaultCipherSuites();
    +  }
    +
    +  @Override
    +  public String[] getSupportedCipherSuites() {
    +    return delegate.getSupportedCipherSuites();
    +  }
    +
    +  @Override
    +  public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
    +    return delegate.createSocket(socket, s, i, b);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i) throws IOException{
    +    return delegate.createSocket(s, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException {
    +    return delegate.createSocket(s, i, inetAddress, i1);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
    +    return delegate.createSocket(inetAddress, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
    +    return delegate.createSocket(inetAddress, i, inetAddress1, i1);
    +  }
    +}
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManager.java+65 0 added
    @@ -0,0 +1,65 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.TrustManagerFactory;
    +import javax.net.ssl.X509TrustManager;
    +import java.security.KeyStore;
    +import java.security.KeyStoreException;
    +import java.security.NoSuchAlgorithmException;
    +import java.security.cert.CertificateException;
    +import java.security.cert.X509Certificate;
    +
    +public class X509ExpiryCheckingTrustManager implements X509TrustManager {
    +
    +    private X509TrustManager delegate;
    +
    +    public X509ExpiryCheckingTrustManager() {
    +        try {
    +            TrustManagerFactory tmf;
    +            tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +            tmf.init((KeyStore) null);
    +            X509TrustManager x509Tm = null;
    +            for (TrustManager tm : tmf.getTrustManagers()) {
    +                if (tm instanceof X509TrustManager) {
    +                    x509Tm = (X509TrustManager) tm;
    +                    break;
    +                }
    +            }
    +            delegate = x509Tm;
    +        } catch (NoSuchAlgorithmException | KeyStoreException e) {
    +        }
    +    }
    +
    +    protected void setDelegate(X509TrustManager delegate) {
    +        this.delegate = delegate;
    +    }
    +
    +    @Override
    +    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkClientTrusted(x509Certificates, s);
    +        }
    +    }
    +
    +    @Override
    +    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkServerTrusted(x509Certificates, s);
    +        }
    +        for (X509Certificate certificate : x509Certificates) {
    +            certificate.checkValidity();
    +        }
    +    }
    +
    +    @Override
    +    public X509Certificate[] getAcceptedIssuers() {
    +        if (delegate != null) {
    +            return delegate.getAcceptedIssuers();
    +        }
    +        return new X509Certificate[0];
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapPropertiesTest.java+12 1 modified
    @@ -35,4 +35,15 @@ public void testProcess() throws Exception {
             process.setBaseUrl("ldaps://localhost:636");
             assertEquals(ProcessLdapProperties.SKIP_SSL_VERIFICATION_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void process_whenSslValidationIsEnabled() throws Exception {
    +        Map<String,String> properties = new HashMap<>();
    +        ProcessLdapProperties process = new ProcessLdapProperties("ldap://localhost:389", false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setDisableSslVerification(false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setBaseUrl("ldaps://localhost:636");
    +        assertEquals(ProcessLdapProperties.EXPIRY_CHECKING_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactoryTest.java+7 0 added
    @@ -0,0 +1,7 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import static org.junit.Assert.*;
    +
    +public class LdapSocketFactoryTest {
    +
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManagerTest.java+59 0 added
    @@ -0,0 +1,59 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import org.junit.Assert;
    +import org.junit.Test;
    +import org.mockito.Mockito;
    +import org.springframework.security.saml.trust.X509TrustManager;
    +
    +import java.security.cert.CertificateExpiredException;
    +import java.security.cert.X509Certificate;
    +
    +import static org.mockito.Mockito.doNothing;
    +import static org.mockito.Mockito.doThrow;
    +import static org.mockito.Mockito.verify;
    +
    +public class X509ExpiryCheckingTrustManagerTest {
    +
    +  @Test
    +  public void checkServerTrusted_throwsExceptionWhenCertIsExpired() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +    doThrow(new CertificateExpiredException()).when(certificate).checkValidity();
    +    try {
    +      manager.checkServerTrusted(x509Certificates,"string");
    +      Assert.fail();
    +    } catch (CertificateExpiredException e) {
    +      verify(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +      verify(certificate).checkValidity();
    +    }
    +  }
    +
    +  @Test
    +  public void checkClientTrusted_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +    manager.checkClientTrusted(x509Certificates, "string");
    +    verify(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +  }
    +
    +  @Test
    +  public void checkAcceptedIssuers_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    manager.getAcceptedIssuers();
    +    verify(mockedDelegate).getAcceptedIssuers();
    +  }
    +}
    
  • .travis.yml+1 1 modified
    @@ -41,7 +41,7 @@ install:
       fi
     - mkdir -p $HOME/build/cloudfoundry/uaa/uaa/build/reports/tests
     script:
    -- ./gradlew -Dspring.profiles.active=$TESTENV jacocoRootReport
    +- ./gradlew -Dspring.profiles.active=$TESTENV -Djavax.net.ssl.trustStore=$TRAVIS_BUILD_DIR/scripts/ldap/truststore-with-ldap-certs.jks -Djavax.net.ssl.trustStoreType=JKS jacocoRootReport
     after_success:
     - ./gradlew coveralls
     - for i in $(find $HOME/build/cloudfoundry/uaa/ -name reports -type d); do rm -rf $i; done
    
  • uaa/src/main/resources/uaa.yml+2 2 modified
    @@ -1,8 +1,8 @@
    -# Configuration in this file is overridden by an external file
    +# Configuration in this file ixs overridden by an external file
     # if any of these exist:
     # [$UAA_CONFIG_URL, $UAA_CONFIG_PATH/uaa.yml, $CLOUD_FOUNDRY_CONFIG_PATH/uaa.yml]
     
    -#spring_profiles: mysql,default
    +#spring_profiles: mysql,default,ldap
     #spring_profiles: postgresql,default
     #spring_profiles: ldap,default,hsqldb
     #spring_profiles: saml
    
  • uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/LdapLoginIT.java+195 0 added
    @@ -0,0 +1,195 @@
    +package org.cloudfoundry.identity.uaa.integration.feature;
    +
    +import org.cloudfoundry.identity.uaa.ServerRunning;
    +import org.cloudfoundry.identity.uaa.constants.OriginKeys;
    +import org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils;
    +import org.cloudfoundry.identity.uaa.integration.util.ScreenshotOnFail;
    +import org.cloudfoundry.identity.uaa.login.test.LoginServerClassRunner;
    +import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
    +import org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition;
    +import org.cloudfoundry.identity.uaa.scim.ScimUser;
    +import org.cloudfoundry.identity.uaa.test.UaaTestAccounts;
    +import org.hamcrest.Matchers;
    +import org.junit.Before;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.runner.RunWith;
    +import org.openqa.selenium.By;
    +import org.openqa.selenium.WebDriver;
    +import org.springframework.beans.factory.annotation.Autowired;
    +import org.springframework.beans.factory.annotation.Value;
    +import org.springframework.security.oauth2.client.test.TestAccounts;
    +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
    +import org.springframework.test.context.ContextConfiguration;
    +import org.springframework.web.client.RestOperations;
    +import org.springframework.web.client.RestTemplate;
    +
    +import static org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils.doesSupportZoneDNS;
    +import static org.junit.Assert.assertThat;
    +import static org.junit.Assume.assumeTrue;
    +
    +@RunWith(LoginServerClassRunner.class)
    +@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
    +public class LdapLoginIT {
    +
    +
    +
    +    @Autowired
    +    @Rule
    +    public IntegrationTestRule integrationTestRule;
    +
    +    @Rule
    +    public ScreenshotOnFail screenShootRule = new ScreenshotOnFail();
    +
    +    @Autowired
    +    RestOperations restOperations;
    +
    +    @Autowired
    +    WebDriver webDriver;
    +
    +    @Value("${integration.test.base_url}")
    +    String baseUrl;
    +
    +    @Autowired
    +    TestClient testClient;
    +
    +    ServerRunning serverRunning = ServerRunning.isRunning();
    +
    +
    +    @Before
    +    public void clearWebDriverOfCookies() throws Exception {
    +        screenShootRule.setWebDriver(webDriver);
    +        webDriver.get(baseUrl + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone1.localhost") + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone2.localhost") + "/logout.do");
    +        webDriver.manage().deleteAllCookies();
    +    }
    +
    +    @Test
    +    public void ldapLogin_withValidSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone2.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone2";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone2.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +          IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +            UaaTestAccounts.standard(serverRunning),
    +            "identity",
    +            "identitysecret",
    +            email,
    +            "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +          "ldaps://52.87.212.253:636/",
    +          "cn=admin,dc=test,dc=com",
    +          "password",
    +          "dc=test,dc=com",
    +          "cn={0}",
    +          "ou=scopes,dc=test,dc=com",
    +          "member={0}",
    +          "mail",
    +          null,
    +          false,
    +          true,
    +          true,
    +          100,
    +          false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to"));
    +    }
    +
    +    @Test
    +    public void ldapLogin_withExpiredSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone1.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone1";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone1.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +                IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +                        UaaTestAccounts.standard(serverRunning),
    +                        "identity",
    +                        "identitysecret",
    +                        email,
    +                        "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +                "ldaps://52.20.5.106:636/",
    +                "cn=admin,dc=test,dc=com",
    +                "password",
    +                "dc=test,dc=com",
    +                "cn={0}",
    +                "ou=scopes,dc=test,dc=com",
    +                "member={0}",
    +                "mail",
    +                null,
    +                false,
    +                true,
    +                true,
    +                100,
    +                false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Welcome to The Twiglet Zone[" + zoneId + "]!"));
    +    }
    +}
    
bc91ccd2029e

Wrap trustmanager in custom trustmanager

https://github.com/cloudfoundry/uaaMadhura BhaveJul 14, 2016via ghsa
11 files changed · +423 7
  • scripts/ldap/truststore-with-ldap-certs.jks+0 0 added
  • server.jks+0 0 added
  • server/src/main/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapProperties.java+10 3 modified
    @@ -14,13 +14,16 @@
     
     package org.cloudfoundry.identity.uaa.provider.ldap;
     
    +import java.security.KeyManagementException;
    +import java.security.NoSuchAlgorithmException;
     import java.util.LinkedHashMap;
     import java.util.Map;
     
     public class ProcessLdapProperties {
     
         public static final String LDAP_SOCKET_FACTORY = "java.naming.ldap.factory.socket";
         public static final String SKIP_SSL_VERIFICATION_SOCKET_FACTORY = "org.apache.directory.api.util.DummySSLSocketFactory";
    +    public static final String EXPIRY_CHECKING_SOCKET_FACTORY = "org.cloudfoundry.identity.uaa.security.LdapSocketFactory";
     
         private boolean disableSslVerification;
         private String baseUrl;
    @@ -30,10 +33,14 @@ public ProcessLdapProperties(String baseUrl, boolean disableSslVerification) {
             this.disableSslVerification = disableSslVerification;
         }
     
    -    public Map process(Map map) {
    +    public Map process(Map map) throws KeyManagementException, NoSuchAlgorithmException {
             Map result = new LinkedHashMap(map);
    -        if (isDisableSslVerification() && isLdapsUrl()) {
    -            result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +        if(isLdapsUrl()) {
    +            if (isDisableSslVerification()) {
    +                result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +            } else {
    +                result.put(LDAP_SOCKET_FACTORY, EXPIRY_CHECKING_SOCKET_FACTORY);
    +            }
             }
             return result;
         }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactory.java+72 0 added
    @@ -0,0 +1,72 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.SocketFactory;
    +import javax.net.ssl.SSLContext;
    +import javax.net.ssl.SSLSocketFactory;
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.X509TrustManager;
    +import java.io.IOException;
    +import java.net.InetAddress;
    +import java.net.Socket;
    +import java.security.SecureRandom;
    +
    +public class LdapSocketFactory  extends SSLSocketFactory {
    +
    +  private static SocketFactory instance;
    +  private SSLSocketFactory delegate;
    +
    +  public static SocketFactory getDefault() {
    +    if(instance == null) {
    +      instance = new LdapSocketFactory();
    +    }
    +
    +    return instance;
    +  }
    +
    +  public LdapSocketFactory() {
    +    try {
    +      X509TrustManager trustManager = new X509ExpiryCheckingTrustManager();
    +      TrustManager[] tma = new TrustManager[]{trustManager};
    +      SSLContext sc = SSLContext.getInstance("TLS");
    +      sc.init(null, tma, new SecureRandom());
    +      this.delegate = sc.getSocketFactory();
    +    } catch (Exception e) {
    +      e.printStackTrace();
    +    }
    +  }
    +
    +  @Override
    +  public String[] getDefaultCipherSuites() {
    +    return delegate.getDefaultCipherSuites();
    +  }
    +
    +  @Override
    +  public String[] getSupportedCipherSuites() {
    +    return delegate.getSupportedCipherSuites();
    +  }
    +
    +  @Override
    +  public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
    +    return delegate.createSocket(socket, s, i, b);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i) throws IOException{
    +    return delegate.createSocket(s, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException {
    +    return delegate.createSocket(s, i, inetAddress, i1);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
    +    return delegate.createSocket(inetAddress, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
    +    return delegate.createSocket(inetAddress, i, inetAddress1, i1);
    +  }
    +}
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManager.java+65 0 added
    @@ -0,0 +1,65 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.TrustManagerFactory;
    +import javax.net.ssl.X509TrustManager;
    +import java.security.KeyStore;
    +import java.security.KeyStoreException;
    +import java.security.NoSuchAlgorithmException;
    +import java.security.cert.CertificateException;
    +import java.security.cert.X509Certificate;
    +
    +public class X509ExpiryCheckingTrustManager implements X509TrustManager {
    +
    +    private X509TrustManager delegate;
    +
    +    public X509ExpiryCheckingTrustManager() {
    +        try {
    +            TrustManagerFactory tmf;
    +            tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +            tmf.init((KeyStore) null);
    +            X509TrustManager x509Tm = null;
    +            for (TrustManager tm : tmf.getTrustManagers()) {
    +                if (tm instanceof X509TrustManager) {
    +                    x509Tm = (X509TrustManager) tm;
    +                    break;
    +                }
    +            }
    +            delegate = x509Tm;
    +        } catch (NoSuchAlgorithmException | KeyStoreException e) {
    +        }
    +    }
    +
    +    protected void setDelegate(X509TrustManager delegate) {
    +        this.delegate = delegate;
    +    }
    +
    +    @Override
    +    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkClientTrusted(x509Certificates, s);
    +        }
    +    }
    +
    +    @Override
    +    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkServerTrusted(x509Certificates, s);
    +        }
    +        for (X509Certificate certificate : x509Certificates) {
    +            certificate.checkValidity();
    +        }
    +    }
    +
    +    @Override
    +    public X509Certificate[] getAcceptedIssuers() {
    +        if (delegate != null) {
    +            return delegate.getAcceptedIssuers();
    +        }
    +        return new X509Certificate[0];
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapPropertiesTest.java+12 1 modified
    @@ -35,4 +35,15 @@ public void testProcess() throws Exception {
             process.setBaseUrl("ldaps://localhost:636");
             assertEquals(ProcessLdapProperties.SKIP_SSL_VERIFICATION_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void process_whenSslValidationIsEnabled() throws Exception {
    +        Map<String,String> properties = new HashMap<>();
    +        ProcessLdapProperties process = new ProcessLdapProperties("ldap://localhost:389", false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setDisableSslVerification(false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setBaseUrl("ldaps://localhost:636");
    +        assertEquals(ProcessLdapProperties.EXPIRY_CHECKING_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactoryTest.java+7 0 added
    @@ -0,0 +1,7 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import static org.junit.Assert.*;
    +
    +public class LdapSocketFactoryTest {
    +
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManagerTest.java+59 0 added
    @@ -0,0 +1,59 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import org.junit.Assert;
    +import org.junit.Test;
    +import org.mockito.Mockito;
    +import org.springframework.security.saml.trust.X509TrustManager;
    +
    +import java.security.cert.CertificateExpiredException;
    +import java.security.cert.X509Certificate;
    +
    +import static org.mockito.Mockito.doNothing;
    +import static org.mockito.Mockito.doThrow;
    +import static org.mockito.Mockito.verify;
    +
    +public class X509ExpiryCheckingTrustManagerTest {
    +
    +  @Test
    +  public void checkServerTrusted_throwsExceptionWhenCertIsExpired() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +    doThrow(new CertificateExpiredException()).when(certificate).checkValidity();
    +    try {
    +      manager.checkServerTrusted(x509Certificates,"string");
    +      Assert.fail();
    +    } catch (CertificateExpiredException e) {
    +      verify(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +      verify(certificate).checkValidity();
    +    }
    +  }
    +
    +  @Test
    +  public void checkClientTrusted_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +    manager.checkClientTrusted(x509Certificates, "string");
    +    verify(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +  }
    +
    +  @Test
    +  public void checkAcceptedIssuers_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    manager.getAcceptedIssuers();
    +    verify(mockedDelegate).getAcceptedIssuers();
    +  }
    +}
    
  • .travis.yml+1 1 modified
    @@ -41,7 +41,7 @@ install:
       fi
     - mkdir -p $HOME/build/cloudfoundry/uaa/uaa/build/reports/tests
     script:
    -- ./gradlew -Dspring.profiles.active=$TESTENV jacocoRootReport
    +- ./gradlew -Dspring.profiles.active=$TESTENV -Djavax.net.ssl.trustStore=$TRAVIS_BUILD_DIR/scripts/ldap/truststore-with-ldap-certs.jks -Djavax.net.ssl.trustStoreType=JKS jacocoRootReport
     after_success:
     - ./gradlew coveralls
     - for i in $(find $HOME/build/cloudfoundry/uaa/ -name reports -type d); do rm -rf $i; done
    
  • uaa/src/main/resources/uaa.yml+2 2 modified
    @@ -1,8 +1,8 @@
    -# Configuration in this file is overridden by an external file
    +# Configuration in this file ixs overridden by an external file
     # if any of these exist:
     # [$UAA_CONFIG_URL, $UAA_CONFIG_PATH/uaa.yml, $CLOUD_FOUNDRY_CONFIG_PATH/uaa.yml]
     
    -#spring_profiles: mysql,default
    +#spring_profiles: mysql,default,ldap
     #spring_profiles: postgresql,default
     #spring_profiles: ldap,default,hsqldb
     #spring_profiles: saml
    
  • uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/LdapLoginIT.java+195 0 added
    @@ -0,0 +1,195 @@
    +package org.cloudfoundry.identity.uaa.integration.feature;
    +
    +import org.cloudfoundry.identity.uaa.ServerRunning;
    +import org.cloudfoundry.identity.uaa.constants.OriginKeys;
    +import org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils;
    +import org.cloudfoundry.identity.uaa.integration.util.ScreenshotOnFail;
    +import org.cloudfoundry.identity.uaa.login.test.LoginServerClassRunner;
    +import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
    +import org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition;
    +import org.cloudfoundry.identity.uaa.scim.ScimUser;
    +import org.cloudfoundry.identity.uaa.test.UaaTestAccounts;
    +import org.hamcrest.Matchers;
    +import org.junit.Before;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.runner.RunWith;
    +import org.openqa.selenium.By;
    +import org.openqa.selenium.WebDriver;
    +import org.springframework.beans.factory.annotation.Autowired;
    +import org.springframework.beans.factory.annotation.Value;
    +import org.springframework.security.oauth2.client.test.TestAccounts;
    +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
    +import org.springframework.test.context.ContextConfiguration;
    +import org.springframework.web.client.RestOperations;
    +import org.springframework.web.client.RestTemplate;
    +
    +import static org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils.doesSupportZoneDNS;
    +import static org.junit.Assert.assertThat;
    +import static org.junit.Assume.assumeTrue;
    +
    +@RunWith(LoginServerClassRunner.class)
    +@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
    +public class LdapLoginIT {
    +
    +
    +
    +    @Autowired
    +    @Rule
    +    public IntegrationTestRule integrationTestRule;
    +
    +    @Rule
    +    public ScreenshotOnFail screenShootRule = new ScreenshotOnFail();
    +
    +    @Autowired
    +    RestOperations restOperations;
    +
    +    @Autowired
    +    WebDriver webDriver;
    +
    +    @Value("${integration.test.base_url}")
    +    String baseUrl;
    +
    +    @Autowired
    +    TestClient testClient;
    +
    +    ServerRunning serverRunning = ServerRunning.isRunning();
    +
    +
    +    @Before
    +    public void clearWebDriverOfCookies() throws Exception {
    +        screenShootRule.setWebDriver(webDriver);
    +        webDriver.get(baseUrl + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone1.localhost") + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone2.localhost") + "/logout.do");
    +        webDriver.manage().deleteAllCookies();
    +    }
    +
    +    @Test
    +    public void ldapLogin_withValidSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone2.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone2";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone2.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +          IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +            UaaTestAccounts.standard(serverRunning),
    +            "identity",
    +            "identitysecret",
    +            email,
    +            "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +          "ldaps://52.87.212.253:636/",
    +          "cn=admin,dc=test,dc=com",
    +          "password",
    +          "dc=test,dc=com",
    +          "cn={0}",
    +          "ou=scopes,dc=test,dc=com",
    +          "member={0}",
    +          "mail",
    +          null,
    +          false,
    +          true,
    +          true,
    +          100,
    +          false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to"));
    +    }
    +
    +    @Test
    +    public void ldapLogin_withExpiredSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone1.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone1";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone1.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +                IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +                        UaaTestAccounts.standard(serverRunning),
    +                        "identity",
    +                        "identitysecret",
    +                        email,
    +                        "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +                "ldaps://52.20.5.106:636/",
    +                "cn=admin,dc=test,dc=com",
    +                "password",
    +                "dc=test,dc=com",
    +                "cn={0}",
    +                "ou=scopes,dc=test,dc=com",
    +                "member={0}",
    +                "mail",
    +                null,
    +                false,
    +                true,
    +                true,
    +                100,
    +                false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Welcome to The Twiglet Zone[" + zoneId + "]!"));
    +    }
    +}
    
f97049df1c6c

Wrap trustmanager in custom trustmanager

https://github.com/cloudfoundry/uaaMadhura BhaveJul 14, 2016via ghsa
11 files changed · +423 7
  • scripts/ldap/truststore-with-ldap-certs.jks+0 0 added
  • server.jks+0 0 added
  • server/src/main/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapProperties.java+10 3 modified
    @@ -14,13 +14,16 @@
     
     package org.cloudfoundry.identity.uaa.provider.ldap;
     
    +import java.security.KeyManagementException;
    +import java.security.NoSuchAlgorithmException;
     import java.util.LinkedHashMap;
     import java.util.Map;
     
     public class ProcessLdapProperties {
     
         public static final String LDAP_SOCKET_FACTORY = "java.naming.ldap.factory.socket";
         public static final String SKIP_SSL_VERIFICATION_SOCKET_FACTORY = "org.apache.directory.api.util.DummySSLSocketFactory";
    +    public static final String EXPIRY_CHECKING_SOCKET_FACTORY = "org.cloudfoundry.identity.uaa.security.LdapSocketFactory";
     
         private boolean disableSslVerification;
         private String baseUrl;
    @@ -30,10 +33,14 @@ public ProcessLdapProperties(String baseUrl, boolean disableSslVerification) {
             this.disableSslVerification = disableSslVerification;
         }
     
    -    public Map process(Map map) {
    +    public Map process(Map map) throws KeyManagementException, NoSuchAlgorithmException {
             Map result = new LinkedHashMap(map);
    -        if (isDisableSslVerification() && isLdapsUrl()) {
    -            result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +        if(isLdapsUrl()) {
    +            if (isDisableSslVerification()) {
    +                result.put(LDAP_SOCKET_FACTORY, SKIP_SSL_VERIFICATION_SOCKET_FACTORY);
    +            } else {
    +                result.put(LDAP_SOCKET_FACTORY, EXPIRY_CHECKING_SOCKET_FACTORY);
    +            }
             }
             return result;
         }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactory.java+72 0 added
    @@ -0,0 +1,72 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.SocketFactory;
    +import javax.net.ssl.SSLContext;
    +import javax.net.ssl.SSLSocketFactory;
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.X509TrustManager;
    +import java.io.IOException;
    +import java.net.InetAddress;
    +import java.net.Socket;
    +import java.security.SecureRandom;
    +
    +public class LdapSocketFactory  extends SSLSocketFactory {
    +
    +  private static SocketFactory instance;
    +  private SSLSocketFactory delegate;
    +
    +  public static SocketFactory getDefault() {
    +    if(instance == null) {
    +      instance = new LdapSocketFactory();
    +    }
    +
    +    return instance;
    +  }
    +
    +  public LdapSocketFactory() {
    +    try {
    +      X509TrustManager trustManager = new X509ExpiryCheckingTrustManager();
    +      TrustManager[] tma = new TrustManager[]{trustManager};
    +      SSLContext sc = SSLContext.getInstance("TLS");
    +      sc.init(null, tma, new SecureRandom());
    +      this.delegate = sc.getSocketFactory();
    +    } catch (Exception e) {
    +      e.printStackTrace();
    +    }
    +  }
    +
    +  @Override
    +  public String[] getDefaultCipherSuites() {
    +    return delegate.getDefaultCipherSuites();
    +  }
    +
    +  @Override
    +  public String[] getSupportedCipherSuites() {
    +    return delegate.getSupportedCipherSuites();
    +  }
    +
    +  @Override
    +  public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
    +    return delegate.createSocket(socket, s, i, b);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i) throws IOException{
    +    return delegate.createSocket(s, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException {
    +    return delegate.createSocket(s, i, inetAddress, i1);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
    +    return delegate.createSocket(inetAddress, i);
    +  }
    +
    +  @Override
    +  public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
    +    return delegate.createSocket(inetAddress, i, inetAddress1, i1);
    +  }
    +}
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManager.java+65 0 added
    @@ -0,0 +1,65 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.TrustManagerFactory;
    +import javax.net.ssl.X509TrustManager;
    +import java.security.KeyStore;
    +import java.security.KeyStoreException;
    +import java.security.NoSuchAlgorithmException;
    +import java.security.cert.CertificateException;
    +import java.security.cert.X509Certificate;
    +
    +public class X509ExpiryCheckingTrustManager implements X509TrustManager {
    +
    +    private X509TrustManager delegate;
    +
    +    public X509ExpiryCheckingTrustManager() {
    +        try {
    +            TrustManagerFactory tmf;
    +            tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +            tmf.init((KeyStore) null);
    +            X509TrustManager x509Tm = null;
    +            for (TrustManager tm : tmf.getTrustManagers()) {
    +                if (tm instanceof X509TrustManager) {
    +                    x509Tm = (X509TrustManager) tm;
    +                    break;
    +                }
    +            }
    +            delegate = x509Tm;
    +        } catch (NoSuchAlgorithmException | KeyStoreException e) {
    +        }
    +    }
    +
    +    protected void setDelegate(X509TrustManager delegate) {
    +        this.delegate = delegate;
    +    }
    +
    +    @Override
    +    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkClientTrusted(x509Certificates, s);
    +        }
    +    }
    +
    +    @Override
    +    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    +        if (delegate == null) {
    +            throw new CertificateException();
    +        } else {
    +            delegate.checkServerTrusted(x509Certificates, s);
    +        }
    +        for (X509Certificate certificate : x509Certificates) {
    +            certificate.checkValidity();
    +        }
    +    }
    +
    +    @Override
    +    public X509Certificate[] getAcceptedIssuers() {
    +        if (delegate != null) {
    +            return delegate.getAcceptedIssuers();
    +        }
    +        return new X509Certificate[0];
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/provider/ldap/ProcessLdapPropertiesTest.java+12 1 modified
    @@ -35,4 +35,15 @@ public void testProcess() throws Exception {
             process.setBaseUrl("ldaps://localhost:636");
             assertEquals(ProcessLdapProperties.SKIP_SSL_VERIFICATION_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void process_whenSslValidationIsEnabled() throws Exception {
    +        Map<String,String> properties = new HashMap<>();
    +        ProcessLdapProperties process = new ProcessLdapProperties("ldap://localhost:389", false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setDisableSslVerification(false);
    +        assertNull(process.process(properties).get(LDAP_SOCKET_FACTORY));
    +        process.setBaseUrl("ldaps://localhost:636");
    +        assertEquals(ProcessLdapProperties.EXPIRY_CHECKING_SOCKET_FACTORY, process.process(properties).get(LDAP_SOCKET_FACTORY));
    +    }
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/LdapSocketFactoryTest.java+7 0 added
    @@ -0,0 +1,7 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import static org.junit.Assert.*;
    +
    +public class LdapSocketFactoryTest {
    +
    +}
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/security/X509ExpiryCheckingTrustManagerTest.java+59 0 added
    @@ -0,0 +1,59 @@
    +package org.cloudfoundry.identity.uaa.security;
    +
    +import org.junit.Assert;
    +import org.junit.Test;
    +import org.mockito.Mockito;
    +import org.springframework.security.saml.trust.X509TrustManager;
    +
    +import java.security.cert.CertificateExpiredException;
    +import java.security.cert.X509Certificate;
    +
    +import static org.mockito.Mockito.doNothing;
    +import static org.mockito.Mockito.doThrow;
    +import static org.mockito.Mockito.verify;
    +
    +public class X509ExpiryCheckingTrustManagerTest {
    +
    +  @Test
    +  public void checkServerTrusted_throwsExceptionWhenCertIsExpired() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +    doThrow(new CertificateExpiredException()).when(certificate).checkValidity();
    +    try {
    +      manager.checkServerTrusted(x509Certificates,"string");
    +      Assert.fail();
    +    } catch (CertificateExpiredException e) {
    +      verify(mockedDelegate).checkServerTrusted(x509Certificates, "string");
    +      verify(certificate).checkValidity();
    +    }
    +  }
    +
    +  @Test
    +  public void checkClientTrusted_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    X509Certificate certificate = Mockito.mock(X509Certificate.class);
    +    X509Certificate[] x509Certificates = {certificate};
    +
    +    doNothing().when(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +    manager.checkClientTrusted(x509Certificates, "string");
    +    verify(mockedDelegate).checkClientTrusted(x509Certificates, "string");
    +  }
    +
    +  @Test
    +  public void checkAcceptedIssuers_callsDelegate() throws Exception {
    +    X509ExpiryCheckingTrustManager manager = new X509ExpiryCheckingTrustManager();
    +    X509TrustManager mockedDelegate = Mockito.mock(X509TrustManager.class);
    +    manager.setDelegate(mockedDelegate);
    +
    +    manager.getAcceptedIssuers();
    +    verify(mockedDelegate).getAcceptedIssuers();
    +  }
    +}
    
  • .travis.yml+1 1 modified
    @@ -42,7 +42,7 @@ install:
       fi
     - mkdir -p $HOME/build/cloudfoundry/uaa/uaa/build/reports/tests
     script:
    -- ./gradlew -Dspring.profiles.active=$TESTENV jacocoRootReport
    +- ./gradlew -Dspring.profiles.active=$TESTENV -Djavax.net.ssl.trustStore=$TRAVIS_BUILD_DIR/scripts/ldap/truststore-with-ldap-certs.jks -Djavax.net.ssl.trustStoreType=JKS jacocoRootReport
     after_success:
     - ./gradlew coveralls
     - for i in $(find $HOME/build/cloudfoundry/uaa/ -name reports -type d); do rm -rf $i; done
    
  • uaa/src/main/resources/uaa.yml+2 2 modified
    @@ -1,8 +1,8 @@
    -# Configuration in this file is overridden by an external file
    +# Configuration in this file ixs overridden by an external file
     # if any of these exist:
     # [$UAA_CONFIG_URL, $UAA_CONFIG_PATH/uaa.yml, $CLOUD_FOUNDRY_CONFIG_PATH/uaa.yml]
     
    -#spring_profiles: mysql,default
    +#spring_profiles: mysql,default,ldap
     #spring_profiles: postgresql,default
     #spring_profiles: ldap,default,hsqldb
     #spring_profiles: saml
    
  • uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/LdapLoginIT.java+195 0 added
    @@ -0,0 +1,195 @@
    +package org.cloudfoundry.identity.uaa.integration.feature;
    +
    +import org.cloudfoundry.identity.uaa.ServerRunning;
    +import org.cloudfoundry.identity.uaa.constants.OriginKeys;
    +import org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils;
    +import org.cloudfoundry.identity.uaa.integration.util.ScreenshotOnFail;
    +import org.cloudfoundry.identity.uaa.login.test.LoginServerClassRunner;
    +import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
    +import org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition;
    +import org.cloudfoundry.identity.uaa.scim.ScimUser;
    +import org.cloudfoundry.identity.uaa.test.UaaTestAccounts;
    +import org.hamcrest.Matchers;
    +import org.junit.Before;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.runner.RunWith;
    +import org.openqa.selenium.By;
    +import org.openqa.selenium.WebDriver;
    +import org.springframework.beans.factory.annotation.Autowired;
    +import org.springframework.beans.factory.annotation.Value;
    +import org.springframework.security.oauth2.client.test.TestAccounts;
    +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
    +import org.springframework.test.context.ContextConfiguration;
    +import org.springframework.web.client.RestOperations;
    +import org.springframework.web.client.RestTemplate;
    +
    +import static org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils.doesSupportZoneDNS;
    +import static org.junit.Assert.assertThat;
    +import static org.junit.Assume.assumeTrue;
    +
    +@RunWith(LoginServerClassRunner.class)
    +@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
    +public class LdapLoginIT {
    +
    +
    +
    +    @Autowired
    +    @Rule
    +    public IntegrationTestRule integrationTestRule;
    +
    +    @Rule
    +    public ScreenshotOnFail screenShootRule = new ScreenshotOnFail();
    +
    +    @Autowired
    +    RestOperations restOperations;
    +
    +    @Autowired
    +    WebDriver webDriver;
    +
    +    @Value("${integration.test.base_url}")
    +    String baseUrl;
    +
    +    @Autowired
    +    TestClient testClient;
    +
    +    ServerRunning serverRunning = ServerRunning.isRunning();
    +
    +
    +    @Before
    +    public void clearWebDriverOfCookies() throws Exception {
    +        screenShootRule.setWebDriver(webDriver);
    +        webDriver.get(baseUrl + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone1.localhost") + "/logout.do");
    +        webDriver.get(baseUrl.replace("localhost", "testzone2.localhost") + "/logout.do");
    +        webDriver.manage().deleteAllCookies();
    +    }
    +
    +    @Test
    +    public void ldapLogin_withValidSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone2.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone2";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone2.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +          IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +          IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +            UaaTestAccounts.standard(serverRunning),
    +            "identity",
    +            "identitysecret",
    +            email,
    +            "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +          "ldaps://52.87.212.253:636/",
    +          "cn=admin,dc=test,dc=com",
    +          "password",
    +          "dc=test,dc=com",
    +          "cn={0}",
    +          "ou=scopes,dc=test,dc=com",
    +          "member={0}",
    +          "mail",
    +          null,
    +          false,
    +          true,
    +          true,
    +          100,
    +          false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to"));
    +    }
    +
    +    @Test
    +    public void ldapLogin_withExpiredSelfSignedCert() throws Exception {
    +        //ensure we are able to resolve DNS for hostname testzone1.localhost
    +        assumeTrue("Expected testzone1/2/3/4.localhost to resolve to 127.0.0.1", doesSupportZoneDNS());
    +        String zoneId = "testzone1";
    +        String zoneUrl = baseUrl.replace("localhost", "testzone1.localhost");
    +
    +        //identity client token
    +        RestTemplate identityClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[]{"zones.write", "zones.read", "scim.zones"}, "identity", "identitysecret")
    +        );
    +        //admin client token - to create users
    +        RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate(
    +                IntegrationTestUtils.getClientCredentialsResource(baseUrl, new String[0], "admin", "adminsecret")
    +        );
    +        //create the zone
    +        IntegrationTestUtils.createZoneOrUpdateSubdomain(identityClient, baseUrl, zoneId, zoneId);
    +
    +        //create a zone admin user
    +        String email = new RandomValueStringGenerator().generate() +"@samltesting.org";
    +        ScimUser user = IntegrationTestUtils.createUser(adminClient, baseUrl,email ,"firstname", "lastname", email, true);
    +        IntegrationTestUtils.makeZoneAdmin(identityClient, baseUrl, user.getId(), zoneId);
    +
    +        //get the zone admin token
    +        String zoneAdminToken =
    +                IntegrationTestUtils.getAuthorizationCodeToken(serverRunning,
    +                        UaaTestAccounts.standard(serverRunning),
    +                        "identity",
    +                        "identitysecret",
    +                        email,
    +                        "secr3T");
    +
    +        LdapIdentityProviderDefinition ldapIdentityProviderDefinition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
    +                "ldaps://52.20.5.106:636/",
    +                "cn=admin,dc=test,dc=com",
    +                "password",
    +                "dc=test,dc=com",
    +                "cn={0}",
    +                "ou=scopes,dc=test,dc=com",
    +                "member={0}",
    +                "mail",
    +                null,
    +                false,
    +                true,
    +                true,
    +                100,
    +                false);
    +
    +        IdentityProvider provider = new IdentityProvider();
    +        provider.setIdentityZoneId(zoneId);
    +        provider.setType(OriginKeys.LDAP);
    +        provider.setActive(true);
    +        provider.setConfig(ldapIdentityProviderDefinition);
    +        provider.setOriginKey(OriginKeys.LDAP);
    +        provider.setName("simplesamlphp for uaa");
    +        provider = IntegrationTestUtils.createOrUpdateProvider(zoneAdminToken,baseUrl,provider);
    +
    +        webDriver.get(zoneUrl + "/login");
    +        webDriver.findElement(By.name("username")).sendKeys("marissa4");
    +        webDriver.findElement(By.name("password")).sendKeys("ldap4");
    +        webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
    +        assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Welcome to The Twiglet Zone[" + zoneId + "]!"));
    +    }
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.