diff --git a/auth/client/pom.xml b/auth/client/pom.xml index 5b4994afd41..2242098cf45 100644 --- a/auth/client/pom.xml +++ b/auth/client/pom.xml @@ -52,6 +52,10 @@ org.wildfly.security wildfly-elytron-credential-store + + org.wildfly.security + wildfly-elytron-dynamic-ssl + org.wildfly.security wildfly-elytron-keystore @@ -76,7 +80,7 @@ org.wildfly.security wildfly-elytron-x500-cert - + org.jboss.logging jboss-logging-annotations @@ -146,6 +150,14 @@ jmockit test + + + + org.mockito + mockito-all + 1.9.5 + test + + - diff --git a/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContext.java b/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContext.java index fc2c6b086b8..13d58004014 100644 --- a/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContext.java +++ b/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContext.java @@ -354,6 +354,10 @@ public T runAsSupplierEx(ExceptionSupplier action return runExFunction(ExceptionSupplier::get, action); } + RuleNode> getSslRules() { + return this.sslRules; + } + public ContextManager getInstanceContextManager() { return getContextManager(); } diff --git a/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContextConfigurationClient.java b/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContextConfigurationClient.java index 3c1ecc883b4..dd56805e376 100644 --- a/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContextConfigurationClient.java +++ b/auth/client/src/main/java/org/wildfly/security/auth/client/AuthenticationContextConfigurationClient.java @@ -30,7 +30,9 @@ import java.security.Principal; import java.security.PrivilegedAction; import java.security.Provider; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.function.Supplier; import java.util.function.UnaryOperator; @@ -196,6 +198,21 @@ private static AuthenticationConfiguration initializeConfiguration(final URI uri return configuration; } + + List getConfiguredSSLContexts(AuthenticationContext authenticationContext) { + List sslContexts = new ArrayList<>(); + RuleNode> node = authenticationContext.getSslRules(); + while (node != null) { + try { + sslContexts.add(node.getConfiguration().create()); + } catch (GeneralSecurityException ignored) { + ignored.printStackTrace(); + } + node = node.getNext(); + } + return sslContexts; + } + /** * Get the SSL context which matches the given URI, or {@link SSLContext#getDefault()} if there is none. * diff --git a/auth/client/src/main/java/org/wildfly/security/auth/client/DynamicSSLContextImpl.java b/auth/client/src/main/java/org/wildfly/security/auth/client/DynamicSSLContextImpl.java new file mode 100644 index 00000000000..998f177442f --- /dev/null +++ b/auth/client/src/main/java/org/wildfly/security/auth/client/DynamicSSLContextImpl.java @@ -0,0 +1,45 @@ +package org.wildfly.security.auth.client; + +import org.kohsuke.MetaInfServices; +import org.wildfly.security.dynamic.ssl.ssl.DynamicSSLContextSPI; + +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.security.AccessController; +import java.security.GeneralSecurityException; +import java.security.PrivilegedAction; +import java.util.List; + +@MetaInfServices(value = DynamicSSLContextSPI.class) +public class DynamicSSLContextImpl implements DynamicSSLContextSPI { + + private SSLContext configuredDefaultSSLContext; + private final AuthenticationContextConfigurationClient AUTH_CONTEXT_CLIENT = + AccessController.doPrivileged((PrivilegedAction) AuthenticationContextConfigurationClient::new); + private AuthenticationContext authenticationContext = AuthenticationContext.captureCurrent(); + private List configuredSSLContexts; + + public DynamicSSLContextImpl() { + this.configuredSSLContexts = AUTH_CONTEXT_CLIENT.getConfiguredSSLContexts(authenticationContext); + } + + @Override + public SSLContext getConfiguredDefault() { + return this.configuredDefaultSSLContext; + } + + @Override + public List getConfiguredSSLContexts() { + return this.configuredSSLContexts; + } + + @Override + public SSLContext getSSLContext(URI uri) { + try { + return AUTH_CONTEXT_CLIENT.getSSLContext(uri, authenticationContext); + } catch (GeneralSecurityException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/auth/client/src/test/java/org/wildfly/security/auth/client/DynamicSSLContextIntersectionTest.java b/auth/client/src/test/java/org/wildfly/security/auth/client/DynamicSSLContextIntersectionTest.java new file mode 100644 index 00000000000..96610b7f2ac --- /dev/null +++ b/auth/client/src/test/java/org/wildfly/security/auth/client/DynamicSSLContextIntersectionTest.java @@ -0,0 +1,106 @@ +package org.wildfly.security.auth.client; + +import org.junit.Assert; +import org.junit.Test; +import org.wildfly.security.dynamic.ssl.ssl.DynamicSSLContext; +import org.wildfly.security.dynamic.ssl.ssl.DynamicSslContextSpi; +import org.wildfly.security.SecurityFactory; +import org.wildfly.security.auth.client.mocks.MockSSLContext; +import org.wildfly.security.auth.client.mocks.MockSSLContextSPI; +import org.wildfly.security.auth.client.mocks.MockSSLSocketFactory; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import java.security.GeneralSecurityException; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DynamicSSLContextIntersectionTest { + + @Test + public void testIntersectionOfSupportedCipherSuites() throws GeneralSecurityException { + + SSLSocketFactory sslSocketFactory0Ciphers = new MockSSLSocketFactory() { + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + }; + + SSLSocketFactory sslSocketFactory3Ciphers = new MockSSLSocketFactory() { + @Override + public String[] getSupportedCipherSuites() { + return new String[]{"TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLS_CIPHER_SUITE_NOT_COMMON"}; + } + }; + + SSLSocketFactory sslSocketFactory4Ciphers = new MockSSLSocketFactory() { + @Override + public String[] getSupportedCipherSuites() { + return new String[]{"TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_CCM_8_SHA256", "TLS_AES_128_GCM_SHA256", "TLS_AES_128_CCM_SHA256"}; + } + }; + + SSLContext sslContext0Ciphers = new MockSSLContext(new MockSSLContextSPI() { + @Override + protected SSLSocketFactory engineGetSocketFactory() { + return sslSocketFactory0Ciphers; + } + }); + + SSLContext sslContext3Ciphers = new MockSSLContext(new MockSSLContextSPI() { + @Override + protected SSLSocketFactory engineGetSocketFactory() { + return sslSocketFactory3Ciphers; + } + }); + + SSLContext sslContext4Ciphers = new MockSSLContext(new MockSSLContextSPI() { + @Override + protected SSLSocketFactory engineGetSocketFactory() { + return sslSocketFactory4Ciphers; + } + }); + + + SecurityFactory sslContextSecurityFactory0Ciphers = mock(SecurityFactory.class); + SecurityFactory sslContextSecurityFactoryt3Ciphers = mock(SecurityFactory.class); + SecurityFactory sslContextSecurityFactory4Ciphers = mock(SecurityFactory.class); + + when(sslContextSecurityFactory0Ciphers.create()).thenReturn(sslContext0Ciphers); + when(sslContextSecurityFactoryt3Ciphers.create()).thenReturn(sslContext3Ciphers); + when(sslContextSecurityFactory4Ciphers.create()).thenReturn(sslContext4Ciphers); + + AuthenticationContext ctx = AuthenticationContext.empty() + .withSsl(MatchRule.ALL.matchHost("host1"), sslContextSecurityFactory4Ciphers) + .withSsl(MatchRule.ALL.matchHost("host2"), sslContextSecurityFactoryt3Ciphers); + ctx.run(checkResultIntersectionSizeIs(2)); + ctx = AuthenticationContext.empty() + .withSsl(MatchRule.ALL.matchHost("host1"), sslContextSecurityFactory4Ciphers) + .withSsl(MatchRule.ALL.matchHost("host2"), sslContextSecurityFactoryt3Ciphers) + .withSsl(MatchRule.ALL.matchHost("host3"), sslContextSecurityFactory0Ciphers); + ctx.run(checkResultIntersectionSizeIs(0)); + ctx = AuthenticationContext.empty() + .withSsl(MatchRule.ALL.matchHost("host3"), sslContextSecurityFactory0Ciphers) + .withSsl(MatchRule.ALL.matchHost("host3"), sslContextSecurityFactory0Ciphers); + ctx.run(checkResultIntersectionSizeIs(0)); + ctx = AuthenticationContext.empty() + .withSsl(MatchRule.ALL.matchHost("host1"), sslContextSecurityFactory4Ciphers) + .withSsl(MatchRule.ALL.matchHost("host1"), sslContextSecurityFactory4Ciphers); + ctx.run(checkResultIntersectionSizeIs(4)); + } + + private Runnable checkResultIntersectionSizeIs(int intersectionSize) { + return () -> { + try { + DynamicSslContextSpi dynamicSslContextSpi = new DynamicSslContextSpi(SSLContext.getDefault()); + SSLContext dynamicSSLContext = new DynamicSSLContext(dynamicSslContextSpi, null, null); + Assert.assertEquals(dynamicSSLContext.getSocketFactory().getSupportedCipherSuites().length, intersectionSize); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + }; + } +} diff --git a/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContext.java b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContext.java new file mode 100644 index 00000000000..cc542df5edb --- /dev/null +++ b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContext.java @@ -0,0 +1,10 @@ +package org.wildfly.security.auth.client.mocks; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLContextSpi; + +public class MockSSLContext extends SSLContext { + public MockSSLContext(final SSLContextSpi mockContextSpi) { + super(mockContextSpi, null, null); + } +} diff --git a/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContextSPI.java b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContextSPI.java new file mode 100644 index 00000000000..935f0a1b7ab --- /dev/null +++ b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLContextSPI.java @@ -0,0 +1,40 @@ +package org.wildfly.security.auth.client.mocks; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContextSpi; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.TrustManager; +import java.security.SecureRandom; + +public abstract class MockSSLContextSPI extends SSLContextSpi { + @Override + protected void engineInit(KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom secureRandom) { + } + + @Override + protected SSLServerSocketFactory engineGetServerSocketFactory() { + return null; + } + + @Override + protected SSLEngine engineCreateSSLEngine() { + return null; + } + + @Override + protected SSLEngine engineCreateSSLEngine(String s, int i) { + return null; + } + + @Override + protected SSLSessionContext engineGetServerSessionContext() { + return null; + } + + @Override + protected SSLSessionContext engineGetClientSessionContext() { + return null; + } +} diff --git a/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLSocketFactory.java b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLSocketFactory.java new file mode 100644 index 00000000000..0a4da9ef235 --- /dev/null +++ b/auth/client/src/test/java/org/wildfly/security/auth/client/mocks/MockSSLSocketFactory.java @@ -0,0 +1,39 @@ +package org.wildfly.security.auth.client.mocks; + +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +public abstract class MockSSLSocketFactory extends SSLSocketFactory { + @Override + public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException { + return null; + } + + @Override + public Socket createSocket(String s, int i) throws IOException, UnknownHostException { + return null; + } + + @Override + public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException { + return null; + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i) throws IOException { + return null; + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException { + return null; + } + + @Override + public String[] getDefaultCipherSuites() { + return new String[0]; + } +} diff --git a/dynamic-ssl/pom.xml b/dynamic-ssl/pom.xml new file mode 100644 index 00000000000..c2f4aad3c7e --- /dev/null +++ b/dynamic-ssl/pom.xml @@ -0,0 +1,23 @@ + + + + org.wildfly.security + wildfly-elytron-parent + 1.11.3.CR1-SNAPSHOT + + + 4.0.0 + + wildfly-elytron-dynamic-ssl + + WildFly Elytron - Dynamic SSL + WildFly Security Dynamic SSL Implementation + + + junit + junit + + + diff --git a/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContext.java b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContext.java new file mode 100644 index 00000000000..0f8d3647b22 --- /dev/null +++ b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContext.java @@ -0,0 +1,12 @@ +package org.wildfly.security.dynamic.ssl.ssl; + +import javax.net.ssl.SSLContext; +import java.security.Provider; + +// TODO remove public and user will have to use AuthenticationContextConfigurationClient to get it +public final class DynamicSSLContext extends SSLContext { + + public DynamicSSLContext(DynamicSslContextSpi contextSpi, Provider provider, String protocol) { + super(contextSpi, provider, protocol); + } +} diff --git a/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContextSPI.java b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContextSPI.java new file mode 100644 index 00000000000..8d9e7d91ad0 --- /dev/null +++ b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSSLContextSPI.java @@ -0,0 +1,12 @@ +package org.wildfly.security.dynamic.ssl.ssl; + +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.util.List; + +public interface DynamicSSLContextSPI { + + SSLContext getConfiguredDefault(); + List getConfiguredSSLContexts(); + SSLContext getSSLContext(URI uri); +} diff --git a/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslContextSpi.java b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslContextSpi.java new file mode 100644 index 00000000000..593df04e0e6 --- /dev/null +++ b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslContextSpi.java @@ -0,0 +1,91 @@ +package org.wildfly.security.dynamic.ssl.ssl; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLContextSpi; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.SecureRandom; +import java.util.Iterator; +import java.util.Objects; +import java.util.ServiceLoader; + +// TODO remove public +public final class DynamicSslContextSpi extends SSLContextSpi { + + private final DynamicSSLContextSPI dynamicSSLContextImpl; + private final SSLContext configuredDefaultSSLContext; + private volatile SSLSocketFactory sslSocketFactory; + + public DynamicSslContextSpi(final SSLContext configuredDefaultSSLContext) throws Exception{ + Objects.requireNonNull(configuredDefaultSSLContext); + this.configuredDefaultSSLContext = configuredDefaultSSLContext; + Iterator dynamicSSLContextSPIIterator = ServiceLoader.load(DynamicSSLContextSPI.class).iterator(); + if(dynamicSSLContextSPIIterator.hasNext()) { + dynamicSSLContextImpl = dynamicSSLContextSPIIterator.next(); + } else { + throw new Exception("must be provided"); + } + } + + @Override + protected void engineInit(KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom secureRandom) { + // ignore + } + + @Override + protected SSLSocketFactory engineGetSocketFactory() { + if (sslSocketFactory == null) { + synchronized (this) { + if (sslSocketFactory == null) { + sslSocketFactory = new DynamicSslSocketFactory(configuredDefaultSSLContext.getSocketFactory(), dynamicSSLContextImpl); + } + } + } + return sslSocketFactory; + } + + @Override + protected SSLServerSocketFactory engineGetServerSocketFactory() { + return this.configuredDefaultSSLContext.getServerSocketFactory(); + } + + @Override + protected SSLEngine engineCreateSSLEngine() { + return this.configuredDefaultSSLContext.createSSLEngine(); + } + + @Override + protected SSLEngine engineCreateSSLEngine(String host, int port) { + try { + return dynamicSSLContextImpl + .getSSLContext(new URI(null, null, host, port, null, null, null)) + .createSSLEngine(host, port); + } catch (URISyntaxException e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected SSLSessionContext engineGetServerSessionContext() { + throw new UnsupportedOperationException("Dynamic SSLContext does not support sessions"); + } + + @Override + protected SSLSessionContext engineGetClientSessionContext() { + throw new UnsupportedOperationException("Dynamic SSLContext does not support sessions"); + + } + + @Override + protected SSLParameters engineGetSupportedSSLParameters() { + return this.configuredDefaultSSLContext.getSupportedSSLParameters(); + } +} diff --git a/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslSocketFactory.java b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslSocketFactory.java new file mode 100644 index 00000000000..e452bbd7c3b --- /dev/null +++ b/dynamic-ssl/src/main/java/org/wildfly/security/dynamic/ssl/ssl/DynamicSslSocketFactory.java @@ -0,0 +1,122 @@ +package org.wildfly.security.dynamic.ssl.ssl; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// TODO remove public +public final class DynamicSslSocketFactory extends SSLSocketFactory { + + private DynamicSSLContextSPI dynamicSSLContextImpl; + private volatile String[] intersectionCipherSuite; + private SSLSocketFactory configuredDefaultSslSocketFactory; + + public DynamicSslSocketFactory(SSLSocketFactory configuredDefaultSslSocketFactory, DynamicSSLContextSPI dynamicSSLContextImpl) { + super(); + this.configuredDefaultSslSocketFactory = configuredDefaultSslSocketFactory; + this.dynamicSSLContextImpl = dynamicSSLContextImpl; + } + + @Override + public Socket createSocket() throws IOException { + return configuredDefaultSslSocketFactory.createSocket(); + } + + @Override + public Socket createSocket(InetAddress address, int port) throws IOException { + return createSocketBasedOnPeerInfo(null, port, address, null, null, null, null); + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + return createSocketBasedOnPeerInfo(host, port, null, null, null, null, null); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException { + return createSocketBasedOnPeerInfo(host, port, null, localAddress, localPort, null, null); + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return createSocketBasedOnPeerInfo(null, port, address, localAddress, localPort, null, null); + + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { + return createSocketBasedOnPeerInfo(host, port, null, null, null, socket, autoClose); + } + + @Override + public String[] getDefaultCipherSuites() { + return dynamicSSLContextImpl.getConfiguredDefault().getSocketFactory().getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + String[] val = intersectionCipherSuite; + if (val == null) { + synchronized (this) { + val = intersectionCipherSuite; + if (intersectionCipherSuite == null) { + val = intersectionCipherSuite = getIntersection(); + } + } + } + return val; + } + + private Socket createSocketBasedOnPeerInfo(String hostname, Integer port, InetAddress address, InetAddress localAddress, Integer localPort, Socket socket, Boolean autoClose) throws IOException { + try { + SSLSocketFactory socketFactory = this.dynamicSSLContextImpl.getSSLContext(new URI(null, null, hostname == null ? address.getHostName() : hostname, port, null, null, null)) + .getSocketFactory(); + + // resolve socket + if (socket != null && autoClose != null) { + return socketFactory.createSocket(socket, hostname, port, autoClose); + } + + // resolves InetAddresses callbacks + if (address != null) { + return localAddress == null ? + socketFactory.createSocket(address, port) : socketFactory.createSocket(address, port, localAddress, localPort); + } + if (localAddress != null && localPort != null) { + return socketFactory.createSocket(hostname, port, localAddress, localPort); + } + + // default + return socketFactory.createSocket(hostname, port); + } catch (URISyntaxException e) { + throw new UnknownHostException(e.getMessage()); + } + } + + private String[] getIntersection() { + List sslContexts = dynamicSSLContextImpl.getConfiguredSSLContexts(); + Map counts = new HashMap<>(); + List intersection = new ArrayList<>(); + sslContexts.forEach(c -> { + String[] cipherSuites = c.getSocketFactory().getSupportedCipherSuites(); + for (String cipherSuite : cipherSuites) { + counts.merge(cipherSuite, 1, (a, b) -> a + b); + } + }); + counts.forEach((c, v) -> { + if (sslContexts.size() == v) { + intersection.add(c); + } + }); + return intersection.toArray(new String[0]); + } +} diff --git a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java new file mode 100644 index 00000000000..7a433e8f2cc --- /dev/null +++ b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java @@ -0,0 +1,28 @@ +package org.wildfly.security.dynamic.ssl; + +import org.junit.Test; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; + +public class DynamicSSLContextTest { + // create multiple SSLServerSockets on diff ports wid different ssls. use client to connect to each successfully + // hosts i would have to create new virtual network interface which would be difficult to port with tests and so on? + // sni uses different hostnames so i will not use it in my tests + // maybe for different hosts i can look at mock servers and farah i think used example.com for letsencrypt + + @Test + public void testServer() throws IOException, NoSuchAlgorithmException { + SSLServerSocketHelper server1 = new SSLServerSocketHelper("src/test/resources/server1.keystore.jks", "src/test/resources/server1.truststore.jks", 10000); + server1.run(); + // Create socket factory + SSLSocketFactory sslSocketFactory = SSLContext.getDefault().getSocketFactory(); + + // Create socket + SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 10000); + sslSocket.startHandshake(); + } +} diff --git a/pom.xml b/pom.xml index 7aa688acd22..c3b4b700e69 100644 --- a/pom.xml +++ b/pom.xml @@ -515,6 +515,11 @@ wildfly-elytron-digest ${project.version} + + org.wildfly.security + wildfly-elytron-dynamic-ssl + ${project.version} + org.wildfly.security wildfly-elytron-http @@ -1284,6 +1289,7 @@ credential/source/deprecated credential/source/impl digest + dynamic-ssl http/base http/basic http/bearer diff --git a/wildfly-elytron/pom.xml b/wildfly-elytron/pom.xml index 19029a0e426..98f70eeb058 100644 --- a/wildfly-elytron/pom.xml +++ b/wildfly-elytron/pom.xml @@ -289,6 +289,10 @@ org.wildfly.security wildfly-elytron-digest + + org.wildfly.security + wildfly-elytron-dynamic-ssl + org.wildfly.security wildfly-elytron-http @@ -617,6 +621,11 @@ wildfly-elytron-digest ${project.version} + + org.wildfly.security + wildfly-elytron-dynamic-ssl + ${project.version} + org.wildfly.security wildfly-elytron-http