diff --git a/build-configuration/pom.xml b/build-configuration/pom.xml index 413c53a2e41a..4921bd61de78 100644 --- a/build-configuration/pom.xml +++ b/build-configuration/pom.xml @@ -183,8 +183,6 @@ 2.6 1.9.12 4.1.43.Final - 1.0.0 - 2.0.25.Final 3.14.3 1.12 1.5.0 @@ -196,6 +194,7 @@ 2.2.0.Final 10.0.0.Final 1.10.3.Final + 1.0.9.Final-SNAPSHOT 4.3.1 4.11.0 5.0.3.Final diff --git a/client/hotrod-client/pom.xml b/client/hotrod-client/pom.xml index 54b15c99a73f..122ff07a8584 100644 --- a/client/hotrod-client/pom.xml +++ b/client/hotrod-client/pom.xml @@ -197,11 +197,24 @@ test + + org.wildfly.openssl + wildfly-openssl-java + test + + + + org.wildfly.openssl + wildfly-openssl-linux-x86_64 + test + + org.mockito mockito-core test + org.apache.geronimo.components geronimo-transaction @@ -213,6 +226,7 @@ + org.objectweb.howl howl diff --git a/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/transport/netty/ChannelInitializer.java b/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/transport/netty/ChannelInitializer.java index d98ef8f8db28..fe09871128f4 100644 --- a/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/transport/netty/ChannelInitializer.java +++ b/client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/transport/netty/ChannelInitializer.java @@ -12,7 +12,6 @@ import java.util.function.BiConsumer; import javax.net.ssl.SNIHostName; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; @@ -106,26 +105,27 @@ protected void initChannel(Channel channel) throws Exception { private void initSsl(Channel channel) { SslConfiguration ssl = configuration.security().ssl(); - SslContext nettySslContext; - SSLContext jdkSslContext = ssl.sslContext(); - if (jdkSslContext == null) { + SslContext sslContext; + if (ssl.sslContext() == null) { SslContextBuilder builder = SslContextBuilder.forClient(); try { if (ssl.keyStoreFileName() != null) { - builder.keyManager(SslContextFactory.getKeyManagerFactory( - ssl.keyStoreFileName(), - ssl.keyStoreType(), - ssl.keyStorePassword(), - ssl.keyStoreCertificatePassword(), - ssl.keyAlias(), - configuration.classLoader())); + builder.keyManager(new SslContextFactory() + .keyStoreFileName(ssl.keyStoreFileName()) + .keyStoreType(ssl.keyStoreType()) + .keyStorePassword(ssl.keyStorePassword()) + .keyAlias(ssl.keyAlias()) + .keyStoreCertificatePassword(ssl.keyStoreCertificatePassword()) + .classLoader(configuration.classLoader()) + .getKeyManagerFactory()); } if (ssl.trustStoreFileName() != null) { - builder.trustManager(SslContextFactory.getTrustManagerFactory( - ssl.trustStoreFileName(), - ssl.trustStoreType(), - ssl.trustStorePassword(), - configuration.classLoader())); + builder.trustManager(new SslContextFactory() + .trustStoreFileName(ssl.trustStoreFileName()) + .trustStoreType(ssl.trustStoreType()) + .trustStorePassword(ssl.trustStorePassword()) + .classLoader(configuration.classLoader()) + .getTrustManagerFactory()); } if (ssl.trustStorePath() != null) { builder.trustManager(new File(ssl.trustStorePath())); @@ -133,14 +133,14 @@ private void initSsl(Channel channel) { if (ssl.protocol() != null) { builder.protocols(ssl.protocol()); } - nettySslContext = builder.build(); + sslContext = builder.build(); } catch (Exception e) { throw new CacheConfigurationException(e); } } else { - nettySslContext = new JdkSslContext(jdkSslContext, true, ClientAuth.NONE); + sslContext = new JdkSslContext(ssl.sslContext(), true, ClientAuth.NONE); } - SslHandler sslHandler = nettySslContext.newHandler(channel.alloc(), ssl.sniHostName(), -1); + SslHandler sslHandler = sslContext.newHandler(channel.alloc(), ssl.sniHostName(), -1); if (ssl.sniHostName() != null) { SSLParameters sslParameters = sslHandler.engine().getSSLParameters(); sslParameters.setServerNames(Collections.singletonList(new SNIHostName(ssl.sniHostName()))); diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslAuthenticationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslAuthenticationTest.java index 5216cf5b9bb5..35194356c499 100644 --- a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslAuthenticationTest.java +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslAuthenticationTest.java @@ -149,14 +149,14 @@ protected void clearContent() { } - public void testSSLAuthentication() throws Exception { + public void testSSLAuthentication() { RemoteCache cache = remoteCacheManager.getCache(); cache.put("k","v"); assertEquals("v", cache.get("k")); } @Test(expectedExceptions = HotRodClientException.class, expectedExceptionsMessageRegExp = ".*ISPN000287.*") - public void testSSLUnauthorized() throws Exception { + public void testSSLUnauthorized() { RemoteCache cache = remoteCacheManager.getCache(UNAUTHORIZED); cache.put("k1","v1"); assertEquals("v1", cache.get("k1")); diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/SSLClassPathConfigurationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/SSLClassPathConfigurationTest.java index cf620d08952e..4da991e336dd 100644 --- a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/SSLClassPathConfigurationTest.java +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/SSLClassPathConfigurationTest.java @@ -17,7 +17,13 @@ public void testLoadTrustStore() { char[] password = "secret".toCharArray(); SSLContext context = - SslContextFactory.getContext(keyStoreFileName, "pkcs12", password, truststoreFileName, "pkcs12", password); + new SslContextFactory() + .keyStoreFileName(keyStoreFileName) + .keyStoreType("pkcs12") + .keyStorePassword(password) + .trustStoreFileName(truststoreFileName) + .trustStoreType("pkcs12") + .trustStorePassword(password).getContext(); assertNotNull(context); } diff --git a/client/rest-client/src/main/java/org/infinispan/client/rest/RestRawClient.java b/client/rest-client/src/main/java/org/infinispan/client/rest/RestRawClient.java index 9c36a8f79987..adc5f8d07fb1 100644 --- a/client/rest-client/src/main/java/org/infinispan/client/rest/RestRawClient.java +++ b/client/rest-client/src/main/java/org/infinispan/client/rest/RestRawClient.java @@ -1,5 +1,6 @@ package org.infinispan.client.rest; +import java.util.Collections; import java.util.Map; import java.util.concurrent.CompletionStage; @@ -12,5 +13,9 @@ public interface RestRawClient { CompletionStage putValue(String url, Map headers, String body, String bodyMediaType); - CompletionStage get(String url); + default CompletionStage get(String url) { + return get(url, Collections.emptyMap()); + } + + CompletionStage get(String url, Map headers); } diff --git a/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestClientOkHttp.java b/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestClientOkHttp.java index fa633ad3a56f..af4c5641c254 100644 --- a/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestClientOkHttp.java +++ b/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestClientOkHttp.java @@ -11,8 +11,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.infinispan.client.rest.RestCacheClient; @@ -28,6 +28,7 @@ import org.infinispan.client.rest.configuration.AuthenticationConfiguration; import org.infinispan.client.rest.configuration.RestClientConfiguration; import org.infinispan.client.rest.configuration.ServerConfiguration; +import org.infinispan.client.rest.configuration.SslConfiguration; import org.infinispan.client.rest.impl.okhttp.auth.AutoDetectAuthenticator; import org.infinispan.client.rest.impl.okhttp.auth.BasicAuthenticator; import org.infinispan.client.rest.impl.okhttp.auth.BearerAuthenticator; @@ -36,6 +37,7 @@ import org.infinispan.client.rest.impl.okhttp.auth.CachingAuthenticatorWrapper; import org.infinispan.client.rest.impl.okhttp.auth.DigestAuthenticator; import org.infinispan.client.rest.impl.okhttp.auth.NegotiateAuthenticator; +import org.infinispan.commons.util.SslContextFactory; import okhttp3.Authenticator; import okhttp3.Call; @@ -64,13 +66,32 @@ public RestClientOkHttp(RestClientConfiguration configuration) { builder .connectTimeout(configuration.connectionTimeout(), TimeUnit.MILLISECONDS) .readTimeout(configuration.socketTimeout(), TimeUnit.MILLISECONDS); + SslConfiguration ssl = configuration.security().ssl(); + if (ssl.enabled()) { + SSLContext sslContext = ssl.sslContext(); + if (sslContext == null) { + SslContextFactory sslContextFactory = new SslContextFactory() + .keyStoreFileName(ssl.keyStoreFileName()) + .keyStorePassword(ssl.keyStorePassword()) + .keyStoreType(ssl.keyStoreType()) + .trustStoreFileName(ssl.trustStoreFileName()) + .trustStorePassword(ssl.trustStorePassword()) + .trustStoreType(ssl.trustStoreType()) + .classLoader(Thread.currentThread().getContextClassLoader()) + .useNativeIfAvailable(false); + sslContext = sslContextFactory.getContext(); + try { + TrustManagerFactory tmf = sslContextFactory.getTrustManagerFactory(); + builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0]); + } catch (Exception e) { + throw new RuntimeException(e); + } - SSLContext sslContext = configuration.security().ssl().sslContext(); - if (sslContext != null) { - builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) configuration.security().ssl().trustManagers()[0]); - HostnameVerifier hostnameVerifier = configuration.security().ssl().hostnameVerifier(); - if (hostnameVerifier != null) { - builder.hostnameVerifier(hostnameVerifier); + } else { + builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) ssl.trustManagers()[0]); + } + if (ssl.hostnameVerifier() != null) { + builder.hostnameVerifier(ssl.hostnameVerifier()); } } @@ -79,7 +100,7 @@ public RestClientOkHttp(RestClientConfiguration configuration) { builder.protocols(Arrays.asList(Protocol.HTTP_1_1)); break; case HTTP_20: - if (sslContext == null) { + if (!ssl.enabled()) { builder.protocols(Arrays.asList(Protocol.H2_PRIOR_KNOWLEDGE)); } else { builder.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1)); @@ -120,7 +141,7 @@ public RestClientOkHttp(RestClientConfiguration configuration) { httpClient = builder.build(); ServerConfiguration server = configuration.servers().get(0); - baseURL = String.format("%s://%s:%d", sslContext == null ? "http" : "https", server.host(), server.port()).replaceAll("//", "/"); + baseURL = String.format("%s://%s:%d", ssl.enabled() ? "https" : "http", server.host(), server.port()).replaceAll("//", "/"); } @Override diff --git a/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestRawClientOkHttp.java b/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestRawClientOkHttp.java index 6d1f29961c3f..406981ad841d 100644 --- a/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestRawClientOkHttp.java +++ b/client/rest-client/src/main/java/org/infinispan/client/rest/impl/okhttp/RestRawClientOkHttp.java @@ -43,8 +43,9 @@ public CompletionStage putValue(String url, Map he } @Override - public CompletionStage get(String url) { + public CompletionStage get(String url, Map headers) { Request.Builder builder = new Request.Builder().get().url(restClient.getBaseURL() + url); + headers.forEach(builder::header); return restClient.execute(builder); } } diff --git a/commons/pom.xml b/commons/pom.xml index 41dc0a2fb37b..6d8782317da0 100644 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -52,6 +52,12 @@ provided + + org.wildfly.openssl + wildfly-openssl-java + true + + org.apache.karaf.features framework diff --git a/commons/src/main/java/org/infinispan/commons/logging/Log.java b/commons/src/main/java/org/infinispan/commons/logging/Log.java index 09208f025b1b..cb36e73266bc 100644 --- a/commons/src/main/java/org/infinispan/commons/logging/Log.java +++ b/commons/src/main/java/org/infinispan/commons/logging/Log.java @@ -1,6 +1,7 @@ package org.infinispan.commons.logging; import static org.jboss.logging.Logger.Level.ERROR; +import static org.jboss.logging.Logger.Level.INFO; import static org.jboss.logging.Logger.Level.WARN; import java.io.IOException; @@ -209,6 +210,14 @@ public interface Log extends BasicLogger { // @Message(value = "Unable to marshall Object '%s' wrapped by '%s', the wrapped object must be registered with the marshallers SerializationContext", id = 945) // MarshallingException unableToMarshallRuntimeObject(String wrappedObjectClass, String wrapperClass); + @LogMessage(level = INFO) + @Message(value = "Using OpenSSL Provider", id = 946) + void openSSLAvailable(); + + @LogMessage(level = INFO) + @Message(value = "Using Java SSL Provider", id = 947) + void openSSLNotAvailable(); + //----- counters exceptions // don't use the same id range ------ @Message(value = CounterOutOfBoundsException.FORMAT_MESSAGE, id = 29501) diff --git a/commons/src/main/java/org/infinispan/commons/util/SslContextFactory.java b/commons/src/main/java/org/infinispan/commons/util/SslContextFactory.java index 95f69753f36f..d8795bb5fd07 100644 --- a/commons/src/main/java/org/infinispan/commons/util/SslContextFactory.java +++ b/commons/src/main/java/org/infinispan/commons/util/SslContextFactory.java @@ -16,6 +16,8 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import org.wildfly.openssl.OpenSSLProvider; + /** * SslContextFactory. * @@ -26,47 +28,112 @@ public class SslContextFactory { private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; private static final String DEFAULT_SSL_PROTOCOL = "TLSv1.2"; private static final String CLASSPATH_RESOURCE = "classpath:"; + private static final String SSL_PROTOCOL_PREFIX; + + static { + String sslProtocolPrefix = ""; + if (Boolean.parseBoolean(SecurityActions.getProperty("org.infinispan.openssl", "true"))) { + try { + OpenSSLProvider.register(); + sslProtocolPrefix = "openssl."; + SECURITY.openSSLAvailable(); + } catch (Throwable e) { + SECURITY.openSSLNotAvailable(); + } + } + SSL_PROTOCOL_PREFIX = sslProtocolPrefix; + } + + private String keyStoreFileName; + private char[] keyStorePassword; + private char[] keyStoreCertificatePassword; + private String keyStoreType = DEFAULT_KEYSTORE_TYPE; + private String keyAlias; + private String trustStoreFileName; + private char[] trustStorePassword; + private String trustStoreType = DEFAULT_KEYSTORE_TYPE; + private String sslProtocol = DEFAULT_SSL_PROTOCOL; + private boolean useNativeIfAvailable = true; + private ClassLoader classLoader; + + public SslContextFactory() { + } - public static SSLContext getContext(String keyStoreFileName, char[] keyStorePassword, String trustStoreFileName, char[] trustStorePassword) { - return getContext(keyStoreFileName, keyStorePassword, null, trustStoreFileName, trustStorePassword, DEFAULT_SSL_PROTOCOL); + public SslContextFactory keyStoreFileName(String keyStoreFileName) { + this.keyStoreFileName = keyStoreFileName; + return this; } - public static SSLContext getContext(String keyStoreFileName, char[] keyStorePassword, String trustStoreFileName, char[] trustStorePassword, String sslProtocol) { - return getContext(keyStoreFileName, keyStorePassword, null, trustStoreFileName, trustStorePassword, sslProtocol); + public SslContextFactory keyStorePassword(char[] keyStorePassword) { + this.keyStorePassword = keyStorePassword; + return this; } - public static SSLContext getContext(String keyStoreFileName, char[] keyStorePassword, char[] keyStoreCertificatePassword, String trustStoreFileName, char[] trustStorePassword) { - return getContext(keyStoreFileName, keyStorePassword, keyStoreCertificatePassword, trustStoreFileName, trustStorePassword, DEFAULT_SSL_PROTOCOL); + public SslContextFactory keyStoreCertificatePassword(char[] keyStoreCertificatePassword) { + this.keyStoreCertificatePassword = keyStoreCertificatePassword; + return this; } - public static SSLContext getContext(String keyStoreFileName, char[] keyStorePassword, char[] keyStoreCertificatePassword, - String trustStoreFileName, char[] trustStorePassword, String sslProtocol) { - return getContext(keyStoreFileName, DEFAULT_KEYSTORE_TYPE, keyStorePassword, keyStoreCertificatePassword, null, trustStoreFileName, DEFAULT_KEYSTORE_TYPE, trustStorePassword, sslProtocol, null); + public SslContextFactory keyStoreType(String keyStoreType) { + if (keyStoreType != null) { + this.keyStoreType = keyStoreType; + } + return this; + } + + public SslContextFactory keyAlias(String keyAlias) { + this.keyAlias = keyAlias; + return this; } - public static SSLContext getContext(String keyStoreFileName, String keyStoreType, char[] keyStorePassword, - String trustStoreFileName, String trustStoreType, char[] trustStorePassword) { - return getContext(keyStoreFileName, keyStoreType, keyStorePassword, null, null, - trustStoreFileName, trustStoreType, trustStorePassword, DEFAULT_SSL_PROTOCOL, null); + public SslContextFactory trustStoreFileName(String trustStoreFileName) { + this.trustStoreFileName = trustStoreFileName; + return this; } - public static SSLContext getContext(String keyStoreFileName, String keyStoreType, char[] keyStorePassword, char[] keyStoreCertificatePassword, - String keyAlias, String trustStoreFileName, String trustStoreType, char[] trustStorePassword, String sslProtocol, - ClassLoader classLoader) { + public SslContextFactory trustStorePassword(char[] trustStorePassword) { + this.trustStorePassword = trustStorePassword; + return this; + } + + public SslContextFactory trustStoreType(String trustStoreType) { + if (trustStoreType != null) { + this.trustStoreType = trustStoreType; + } + return this; + } + + public SslContextFactory sslProtocol(String sslProtocol) { + if (sslProtocol != null) { + this.sslProtocol = sslProtocol; + } + return this; + } + + public SslContextFactory useNativeIfAvailable(boolean useNativeIfAvailable) { + this.useNativeIfAvailable = useNativeIfAvailable; + return this; + } + + public SslContextFactory classLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + return this; + } + + public SSLContext getContext() { try { KeyManager[] keyManagers = null; if (keyStoreFileName != null) { - KeyManagerFactory kmf = getKeyManagerFactory(keyStoreFileName, keyStoreType, keyStorePassword, keyStoreCertificatePassword, keyAlias, classLoader); + KeyManagerFactory kmf = getKeyManagerFactory(); keyManagers = kmf.getKeyManagers(); } - TrustManager[] trustManagers = null; if (trustStoreFileName != null) { - TrustManagerFactory tmf = getTrustManagerFactory(trustStoreFileName, trustStoreType, trustStorePassword, classLoader); + TrustManagerFactory tmf = getTrustManagerFactory(); trustManagers = tmf.getTrustManagers(); } - - SSLContext sslContext = SSLContext.getInstance(sslProtocol == null ? DEFAULT_SSL_PROTOCOL : sslProtocol); + String protocol = useNativeIfAvailable ? SSL_PROTOCOL_PREFIX + sslProtocol : sslProtocol; + SSLContext sslContext = SSLContext.getInstance(protocol); sslContext.init(keyManagers, trustManagers, null); return sslContext; } catch (Exception e) { @@ -74,7 +141,7 @@ public static SSLContext getContext(String keyStoreFileName, String keyStoreType } } - public static KeyManagerFactory getKeyManagerFactory(String keyStoreFileName, String keyStoreType, char[] keyStorePassword, char[] keyStoreCertificatePassword, String keyAlias, ClassLoader classLoader) throws IOException, GeneralSecurityException { + public KeyManagerFactory getKeyManagerFactory() throws IOException, GeneralSecurityException { KeyStore ks = KeyStore.getInstance(keyStoreType != null ? keyStoreType : DEFAULT_KEYSTORE_TYPE); loadKeyStore(ks, keyStoreFileName, keyStorePassword, classLoader); char[] keyPassword = keyStoreCertificatePassword == null ? keyStorePassword : keyStoreCertificatePassword; @@ -95,7 +162,7 @@ public static KeyManagerFactory getKeyManagerFactory(String keyStoreFileName, St return kmf; } - public static TrustManagerFactory getTrustManagerFactory(String trustStoreFileName, String trustStoreType, char[] trustStorePassword, ClassLoader classLoader) throws IOException, GeneralSecurityException { + public TrustManagerFactory getTrustManagerFactory() throws IOException, GeneralSecurityException { KeyStore ks = KeyStore.getInstance(trustStoreType != null ? trustStoreType : DEFAULT_KEYSTORE_TYPE); loadKeyStore(ks, trustStoreFileName, trustStorePassword, classLoader); TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); diff --git a/documentation/src/main/asciidoc/topics/dependencies_maven/netty_bom.xml b/documentation/src/main/asciidoc/topics/dependencies_maven/netty_bom.xml index b5ad9f5d7e5e..cc9bebef2193 100644 --- a/documentation/src/main/asciidoc/topics/dependencies_maven/netty_bom.xml +++ b/documentation/src/main/asciidoc/topics/dependencies_maven/netty_bom.xml @@ -10,8 +10,3 @@ - - io.netty - netty-tcnative-boringssl-static - - diff --git a/pom.xml b/pom.xml index d899616ad48d..3044a9593a76 100644 --- a/pom.xml +++ b/pom.xml @@ -304,8 +304,6 @@ ${version.netty} ${version.netty} ${version.netty} - ${version.netty.tcnative} - ${version.netty.tcnative} ${version.netty} ${version.netty} ${version.netty} @@ -455,7 +453,6 @@ 1.24 3.1.0 3.1.4 - 1.0.0 ${version.eclipse.aether} ${version.eclipse.aether} ${version.eclipse.aether} @@ -754,6 +751,13 @@ 3.0.0.Final 3.0.0.Final 2.0.0.Final + ${version.org.wildfly.openssl} + ${versionx.org.wildfly.openssl.natives} + ${versionx.org.wildfly.openssl.natives} + ${versionx.org.wildfly.openssl.natives} + ${versionx.org.wildfly.openssl.natives} + ${versionx.org.wildfly.openssl.natives} + ${versionx.org.wildfly.openssl.natives} 1.1.0.Final ${version.org.wildfly.elytron} 1.1.2.Final @@ -1199,18 +1203,6 @@ netty-resolver ${versionx.io.netty.netty-resolver} - - io.netty - netty-tcnative - ${versionx.io.netty.netty-tcnative} - linux-x86_64 - - - io.netty - netty-tcnative-boringssl-static - ${versionx.io.netty.netty-tcnative-boringssl-static} - test - io.netty netty-transport @@ -2051,12 +2043,6 @@ ${versionx.org.codehaus.woodstox.stax2-api} test - - org.conscrypt - conscrypt-openjdk - ${versionx.org.conscrypt.conscrypt-openjdk} - linux-x86_64 - org.eclipse.aether aether-api @@ -3794,6 +3780,41 @@ wildfly-transactions ${versionx.org.wildfly.wildfly-transactions} + + org.wildfly.openssl + wildfly-openssl-java + ${version.org.wildfly.openssl} + + + org.wildfly.openssl + wildfly-openssl-linux-i386 + ${versionx.org.wildfly.openssl.wildfly-openssl-linux-i386} + + + org.wildfly.openssl + wildfly-openssl-linux-x86_64 + ${versionx.org.wildfly.openssl.wildfly-openssl-linux-x86_64} + + + org.wildfly.openssl + wildfly-openssl-macosx-x86_64 + ${versionx.org.wildfly.openssl.wildfly-openssl-macosx-x86_64} + + + org.wildfly.openssl + wildfly-openssl-solaris-x86_64 + ${versionx.org.wildfly.openssl.wildfly-openssl-solaris-x86_64} + + + org.wildfly.openssl + wildfly-openssl-windows-i386 + ${versionx.org.wildfly.openssl.wildfly-openssl-windows-i386} + + + org.wildfly.openssl + wildfly-openssl-windows-x86_64 + ${versionx.org.wildfly.openssl.wildfly-openssl-windows-x86_64} + org.wildfly.arquillian wildfly-arquillian-common diff --git a/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java b/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java index 5ad90d3eda92..f6a4d7e208d2 100644 --- a/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java +++ b/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java @@ -380,7 +380,7 @@ public void cacheManagerStarting(GlobalComponentRegistry gcr, GlobalConfiguratio gcr.registerComponent(new QueryCache(), QueryCache.class); SerializationContextRegistry ctxRegistry = gcr.getComponent(SerializationContextRegistry.class); - ctxRegistry.addContextInitializer(SerializationContextRegistry.MarshallerType.PERSISTENCE, new PersistenceContextInitializerImpl()); + ctxRegistry.addContextInitializer(SerializationContextRegistry.MarshallerType.PERSISTENCE, new PersistenceContextInitializerImpl()); Map> externalizerMap = globalCfg.serialization().advancedExternalizers(); externalizerMap.put(ExternalizerIds.ICKLE_FILTER_AND_CONVERTER, new IckleFilterAndConverter.IckleFilterAndConverterExternalizer()); diff --git a/server/core/pom.xml b/server/core/pom.xml index 0815b9c647d5..1d46e1a7a6ed 100644 --- a/server/core/pom.xml +++ b/server/core/pom.xml @@ -18,22 +18,6 @@ io.netty netty-handler - - - - org.conscrypt - conscrypt-openjdk - ${version.netty-conscrypt-optional} - ${os.detected.classifier} - true - - - - io.netty - netty-tcnative - ${versionx.io.netty.netty-tcnative} - ${os.detected.classifier} - true io.netty diff --git a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientByteArrayOutputStream.java b/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientByteArrayOutputStream.java deleted file mode 100644 index cc85ffb4840d..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientByteArrayOutputStream.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2014 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.netty.handler.ssl; - -import java.io.ByteArrayOutputStream; - -import javax.net.ssl.SSLEngine; - -/** - * Super hacky class that allows the client and server hello message to be modified and the corresponding hash generated - * at runtime. - * - * - * @author Stuart Douglas - */ -class ALPNHackClientByteArrayOutputStream extends ByteArrayOutputStream { - - private final SSLEngine sslEngine; - private boolean ready = true; - /** - * the server hello that was sent over the wire, before we messed with it - */ - private byte[] receivedServerHello; - private byte[] sentClientHello; - - ALPNHackClientByteArrayOutputStream(SSLEngine sslEngine) { - this.sslEngine = sslEngine; - } - - @Override - public void write(byte[] b, int off, int len) { - if(ready) { - if(b[off] == 2) { // server hello - ready = false; //we are done processing - byte[] newData; - if(receivedServerHello != null) { - int b1 = b[off + 1]; - int b2 = b[off + 2]; - int b3 = b[off + 3]; - int length = (b1 & 0xFF) << 16 | (b2 & 0xFF) << 8 | b3 & 0xFF; - if(length + 4 == len) { - newData = receivedServerHello; - } else { - newData = new byte[receivedServerHello.length + len - 4 - length]; - System.arraycopy(receivedServerHello, 0, newData, 0, receivedServerHello.length); - System.arraycopy(b, length + 4, newData, receivedServerHello.length, len - 4 -length); - } - } else { - newData = new byte[len]; - System.arraycopy(b, off, newData, 0, len); - } - ALPNHackSSLEngine.regenerateHashes(sslEngine, this, sentClientHello, newData); - return; - } - } - super.write(b, off, len); - } - - byte[] getSentClientHello() { - return sentClientHello; - } - - void setSentClientHello(byte[] sentClientHello) { - this.sentClientHello = sentClientHello; - } - - byte[] getReceivedServerHello() { - return receivedServerHello; - } - - void setReceivedServerHello(byte[] receivedServerHello) { - this.receivedServerHello = receivedServerHello; - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientHelloExplorer.java b/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientHelloExplorer.java deleted file mode 100644 index 536f2df74df2..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackClientHelloExplorer.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2014 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.netty.handler.ssl; - -import javax.net.ssl.SSLException; -import java.io.ByteArrayOutputStream; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is used to both read and write the ALPN protocol names in the ClientHello SSL message. - * - * If the out parameter is not null then the read function is being used, while if it present then it is rewriting - * the hello message to include ALPN. - * - * Even though this dual approach is not particularly clean it does remove the need to have two versions of each function, - * that do almost exactly the same thing. - * - */ -final class ALPNHackClientHelloExplorer { - - // Private constructor prevents construction outside this class. - private ALPNHackClientHelloExplorer() { - } - - /** - * The header size of TLS/SSL records. - *

- * The value of this constant is {@value}. - */ - public static final int RECORD_HEADER_SIZE = 0x05; - - /** - * - * - */ - static List exploreClientHello(ByteBuffer source) - throws SSLException { - - ByteBuffer input = source.duplicate(); - - // Do we have a complete header? - if (input.remaining() < RECORD_HEADER_SIZE) { - throw new BufferUnderflowException(); - } - List alpnProtocols = new ArrayList<>(); - // Is it a handshake message? - byte firstByte = input.get(); - byte secondByte = input.get(); - byte thirdByte = input.get(); - - if ((firstByte & 0x80) != 0 && thirdByte == 0x01) { - // looks like a V2ClientHello, we ignore it. - return null; - } else if (firstByte == 22) { // 22: handshake record - if(secondByte == 3 && thirdByte >= 1 && thirdByte <= 3) { - exploreTLSRecord(input, - firstByte, secondByte, thirdByte, alpnProtocols, null); - return alpnProtocols; - } - return null; - } else { - throw new SSLException("No handshake record"); - } - } - - static byte[] rewriteClientHello(byte[] source, List alpnProtocols) throws SSLException { - ByteBuffer input = ByteBuffer.wrap(source); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - // Do we have a complete header? - if (input.remaining() < RECORD_HEADER_SIZE) { - throw new BufferUnderflowException(); - } - try { - - // Is it a handshake message? - byte firstByte = input.get(); - byte secondByte = input.get(); - byte thirdByte = input.get(); - out.write(firstByte & 0xFF); - out.write(secondByte & 0xFF); - out.write(thirdByte & 0xFF); - if ((firstByte & 0x80) != 0 && thirdByte == 0x01) { - // looks like a V2ClientHello, we ignore it. - return null; - } else if (firstByte == 22) { // 22: handshake record - if (secondByte == 3 && thirdByte == 3) { - //TLS1.2 is the only one we care about. Previous versions can't use HTTP/2, newer versions won't be backported to JDK8 - exploreTLSRecord(input, - firstByte, secondByte, thirdByte, alpnProtocols, out); - //we need to adjust the record length; - int clientHelloLength = out.size() - 9; - byte[] data = out.toByteArray(); - int newLength = data.length - 5; - data[3] = (byte) ((newLength >> 8) & 0xFF); - data[4] = (byte) (newLength & 0xFF); - - //now we need to adjust the handshake frame length - data[6] = (byte) ((clientHelloLength >> 16) & 0xFF); - data[7] = (byte) ((clientHelloLength >> 8) & 0xFF); - data[8] = (byte) (clientHelloLength & 0xFF); - - return data; - } - return null; - } else { - throw new SSLException("No handshake record"); - } - } catch (ALPNPresentException e) { - return null; - } - } - - /* - * struct { - * uint8 major; - * uint8 minor; - * } ProtocolVersion; - * - * enum { - * change_cipher_spec(20), alert(21), handshake(22), - * application_data(23), (255) - * } ContentType; - * - * struct { - * ContentType type; - * ProtocolVersion version; - * uint16 length; - * opaque fragment[TLSPlaintext.length]; - * } TLSPlaintext; - */ - private static void exploreTLSRecord( - ByteBuffer input, byte firstByte, byte secondByte, - byte thirdByte, List alpnProtocols, ByteArrayOutputStream out) throws SSLException { - - // Is it a handshake message? - if (firstByte != 22) { // 22: handshake record - throw new SSLException("No handshake record"); - } - - // Is there enough data for a full record? - int recordLength = getInt16(input); - if (recordLength > input.remaining()) { - throw new BufferUnderflowException(); - } - if(out != null) { - out.write(0); - out.write(0); - } - - // We have already had enough source bytes. - try { - exploreHandshake(input, - secondByte, thirdByte, recordLength, alpnProtocols, out); - } catch (BufferUnderflowException ignored) { - throw new SSLException("No handshake record"); - } - } - - /* - * enum { - * hello_request(0), client_hello(1), server_hello(2), - * certificate(11), server_key_exchange (12), - * certificate_request(13), server_hello_done(14), - * certificate_verify(15), client_key_exchange(16), - * finished(20) - * (255) - * } HandshakeType; - * - * struct { - * HandshakeType msg_type; - * uint24 length; - * select (HandshakeType) { - * case hello_request: HelloRequest; - * case client_hello: ClientHello; - * case server_hello: ServerHello; - * case certificate: Certificate; - * case server_key_exchange: ServerKeyExchange; - * case certificate_request: CertificateRequest; - * case server_hello_done: ServerHelloDone; - * case certificate_verify: CertificateVerify; - * case client_key_exchange: ClientKeyExchange; - * case finished: Finished; - * } body; - * } Handshake; - */ - private static void exploreHandshake( - ByteBuffer input, byte recordMajorVersion, - byte recordMinorVersion, int recordLength, List alpnProtocols, ByteArrayOutputStream out) throws SSLException { - - // What is the handshake type? - byte handshakeType = input.get(); - if (handshakeType != 0x01) { // 0x01: client_hello message - throw new SSLException("Expected client hello"); - } - if(out != null) { - out.write(handshakeType & 0xFF); - } - - // What is the handshake body length? - int handshakeLength = getInt24(input); - if(out != null) { - //placeholder - out.write(0); - out.write(0); - out.write(0); - } - - // Theoretically, a single handshake message might span multiple - // records, but in practice this does not occur. - if (handshakeLength > recordLength - 4) { // 4: handshake header size - throw new SSLException("Multi record handshake"); - } - - input = input.duplicate(); - input.limit(handshakeLength + input.position()); - exploreClientHello(input, alpnProtocols, out); - } - - /* - * struct { - * uint32 gmt_unix_time; - * opaque random_bytes[28]; - * } Random; - * - * opaque SessionID<0..32>; - * - * uint8 CipherSuite[2]; - * - * enum { null(0), (255) } CompressionMethod; - * - * struct { - * ProtocolVersion client_version; - * Random random; - * SessionID session_id; - * CipherSuite cipher_suites<2..2^16-2>; - * CompressionMethod compression_methods<1..2^8-1>; - * select (extensions_present) { - * case false: - * struct {}; - * case true: - * Extension extensions<0..2^16-1>; - * }; - * } ClientHello; - */ - private static void exploreClientHello( - ByteBuffer input, - List alpnProtocols, - ByteArrayOutputStream out) throws SSLException { - - // client version - byte helloMajorVersion = input.get(); - byte helloMinorVersion = input.get(); - if(out != null) { - out.write(helloMajorVersion & 0xFF); - out.write(helloMinorVersion & 0xFF); - } - if(helloMajorVersion != 3 && helloMinorVersion != 3) { - //we only care about TLS 1.2 - return; - } - - - // ignore random - for(int i = 0; i < 32; ++i) {// 32: the length of Random - byte d = input.get(); - if(out != null) { - out.write(d & 0xFF); - } - } - - // session id - processByteVector8(input, out); - - // cipher_suites - processByteVector16(input, out); - - // compression methods - processByteVector8(input, out); - if (input.remaining() > 0) { - exploreExtensions(input, alpnProtocols, out); - } else if(out != null) { - byte[] data = generateAlpnExtension(alpnProtocols); - writeInt16(out, data.length); - out.write(data, 0, data.length); - } - } - - private static void writeInt16(ByteArrayOutputStream out, int l) { - if(out == null) return; - out.write((l >> 8) & 0xFF); - out.write(l & 0xFF); - } - - private static byte[] generateAlpnExtension(List alpnProtocols) { - ByteArrayOutputStream alpnBits = new ByteArrayOutputStream(); - alpnBits.write(0); - alpnBits.write(16); //ALPN type - int length = 2; - for(String p : alpnProtocols) { - length++; - length += p.length(); - } - writeInt16(alpnBits, length); - length -= 2; - writeInt16(alpnBits, length); - for(String p : alpnProtocols) { - alpnBits.write(p.length() & 0xFF); - for (int i = 0; i < p.length(); ++i) { - alpnBits.write(p.charAt(i) & 0xFF); - } - } - return alpnBits.toByteArray(); - } - - /* - * struct { - * ExtensionType extension_type; - * opaque extension_data<0..2^16-1>; - * } Extension; - * - * enum { - * server_name(0), max_fragment_length(1), - * client_certificate_url(2), trusted_ca_keys(3), - * truncated_hmac(4), status_request(5), (65535) - * } ExtensionType; - */ - private static void exploreExtensions(ByteBuffer input, List alpnProtocols, ByteArrayOutputStream out) - throws SSLException { - ByteArrayOutputStream extensionOut = out == null ? null : new ByteArrayOutputStream(); - int length = getInt16(input); // length of extensions - writeInt16(extensionOut, 0); //placeholder - while (length > 0) { - int extType = getInt16(input); // extenson type - writeInt16(extensionOut, extType); - int extLen = getInt16(input); // length of extension data - writeInt16(extensionOut, extLen); - if (extType == 16) { // 0x00: ty - if(out == null) { - exploreALPNExt(input, alpnProtocols); - } else { - throw new ALPNPresentException(); - } - } else { // ignore other extensions - processByteVector(input, extLen, extensionOut); - } - - length -= extLen + 4; - } - if(out != null) { - byte[] alpnBits = generateAlpnExtension(alpnProtocols); - extensionOut.write(alpnBits,0 ,alpnBits.length); - byte[] extensionsData = extensionOut.toByteArray(); - int newLength = extensionsData.length - 2; - extensionsData[0] = (byte) ((newLength >> 8) & 0xFF); - extensionsData[1] = (byte) (newLength & 0xFF); - out.write(extensionsData, 0, extensionsData.length); - } - - } - - private static void exploreALPNExt(ByteBuffer input, List alpnProtocols) { - int length = getInt16(input); - int end = input.position() + length; - while (input.position() < end) { - alpnProtocols.add(readByteVector8(input)); - } - } - - private static int getInt8(ByteBuffer input) { - return input.get(); - } - - private static int getInt16(ByteBuffer input) { - return (input.get() & 0xFF) << 8 | input.get() & 0xFF; - } - - private static int getInt24(ByteBuffer input) { - return (input.get() & 0xFF) << 16 | (input.get() & 0xFF) << 8 | - input.get() & 0xFF; - } - - private static void processByteVector8(ByteBuffer input, ByteArrayOutputStream out) { - int int8 = getInt8(input); - if(out != null) { - out.write(int8 & 0xFF); - } - processByteVector(input, int8, out); - } - - - private static void processByteVector(ByteBuffer input, int length, ByteArrayOutputStream out) { - for (int i = 0; i < length; ++i) { - byte b = input.get(); - if(out != null) { - out.write(b & 0xFF); - } - } - } - private static String readByteVector8(ByteBuffer input) { - int length = getInt8(input); - byte[] data = new byte[length]; - input.get(data); - return new String(data, StandardCharsets.US_ASCII); - } - - private static void processByteVector16(ByteBuffer input, ByteArrayOutputStream out) { - int int16 = getInt16(input); - writeInt16(out, int16); - processByteVector(input, int16, out); - } - - private static final class ALPNPresentException extends RuntimeException { - - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackSSLEngine.java b/server/core/src/main/java/io/netty/handler/ssl/ALPNHackSSLEngine.java deleted file mode 100644 index 4be5b9427c7b..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackSSLEngine.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2014 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.netty.handler.ssl; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.security.MessageDigest; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLSession; - -import org.infinispan.commons.logging.LogFactory; - -/** - * SSLEngine wrapper that provides some super hacky ALPN support on JDK8. - * - * Even though this is a nasty hack that relies on JDK internals it is still preferable to modifying the boot class path. - * - * It is expected to work with all JDK8 versions, however this cannot be guaranteed if the SSL internals are changed - * in an incompatible way. - * - * This class will go away once JDK8 is no longer in use. - * - * @author Stuart Douglas - */ -public class ALPNHackSSLEngine extends SSLEngine { - - private static final org.infinispan.commons.logging.Log log = LogFactory.getLog(ALPNHackSSLEngine.class); - - public static final boolean ENABLED; - - private static final Field HANDSHAKER; - private static final Field HANDSHAKER_PROTOCOL_VERSION; - private static final Field HANDSHAKE_HASH; - private static final Field HANDSHAKE_HASH_VERSION; - private static final Method HANDSHAKE_HASH_UPDATE; - private static final Method HANDSHAKE_HASH_PROTOCOL_DETERMINED; - private static final Field HANDSHAKE_HASH_DATA; - private static final Field HANDSHAKE_HASH_FIN_MD; - - private static final Class SSL_ENGINE_IMPL_CLASS; - - static { - - boolean enabled = true; - Field handshaker; - Field handshakeHash; - Field handshakeHashVersion; - Field handshakeHashData; - Field handshakeHashFinMd; - Field protocolVersion; - Method handshakeHashUpdate; - Method handshakeHashProtocolDetermined; - Class sslEngineImpleClass; - try { - Class protocolVersionClass = Class.forName("sun.security.ssl.ProtocolVersion", true, ClassLoader.getSystemClassLoader()); - sslEngineImpleClass = Class.forName("sun.security.ssl.SSLEngineImpl", true, ClassLoader.getSystemClassLoader()); - handshaker = sslEngineImpleClass.getDeclaredField("handshaker"); - handshaker.setAccessible(true); - handshakeHash = handshaker.getType().getDeclaredField("handshakeHash"); - handshakeHash.setAccessible(true); - protocolVersion = handshaker.getType().getDeclaredField("protocolVersion"); - protocolVersion.setAccessible(true); - handshakeHashVersion = handshakeHash.getType().getDeclaredField("version"); - handshakeHashVersion.setAccessible(true); - handshakeHashUpdate = handshakeHash.getType().getDeclaredMethod("update", byte[].class, int.class, int.class); - handshakeHashUpdate.setAccessible(true); - handshakeHashProtocolDetermined = handshakeHash.getType().getDeclaredMethod("protocolDetermined", protocolVersionClass); - handshakeHashProtocolDetermined.setAccessible(true); - handshakeHashData = handshakeHash.getType().getDeclaredField("data"); - handshakeHashData.setAccessible(true); - handshakeHashFinMd = handshakeHash.getType().getDeclaredField("finMD"); - handshakeHashFinMd.setAccessible(true); - - } catch (Exception e) { - log.debug("JDK8 ALPN Hack failed ", e); - enabled = false; - handshaker = null; - handshakeHash = null; - handshakeHashVersion = null; - handshakeHashUpdate = null; - handshakeHashProtocolDetermined = null; - handshakeHashData = null; - handshakeHashFinMd = null; - protocolVersion = null; - sslEngineImpleClass = null; - } - ENABLED = enabled && !Boolean.getBoolean("io.undertow.disable-jdk8-alpn"); - HANDSHAKER = handshaker; - HANDSHAKE_HASH = handshakeHash; - HANDSHAKE_HASH_PROTOCOL_DETERMINED = handshakeHashProtocolDetermined; - HANDSHAKE_HASH_VERSION = handshakeHashVersion; - HANDSHAKE_HASH_UPDATE = handshakeHashUpdate; - HANDSHAKE_HASH_DATA = handshakeHashData; - HANDSHAKE_HASH_FIN_MD = handshakeHashFinMd; - HANDSHAKER_PROTOCOL_VERSION = protocolVersion; - SSL_ENGINE_IMPL_CLASS = sslEngineImpleClass; - } - - private final SSLEngine delegate; - - //ALPN Hack specific variables - private boolean unwrapHelloSeen = false; - private boolean ourHelloSent = false; - private ALPNHackServerByteArrayOutputStream alpnHackServerByteArrayOutputStream; - private ALPNHackClientByteArrayOutputStream ALPNHackClientByteArrayOutputStream; - private List applicationProtocols; - private String selectedApplicationProtocol; - private ByteBuffer bufferedWrapData; - - public ALPNHackSSLEngine(SSLEngine delegate) { - this.delegate = delegate; - } - - public static boolean isEnabled(SSLEngine engine) { - if(!ENABLED) { - return false; - } - return SSL_ENGINE_IMPL_CLASS.isAssignableFrom(engine.getClass()); - } - - @Override - public SSLEngineResult wrap(ByteBuffer[] byteBuffers, int i, int i1, ByteBuffer byteBuffer) throws SSLException { - if(bufferedWrapData != null) { - int prod = bufferedWrapData.remaining(); - byteBuffer.put(bufferedWrapData); - bufferedWrapData = null; - return new SSLEngineResult(SSLEngineResult.Status.OK, SSLEngineResult.HandshakeStatus.NEED_WRAP, 0, prod); - } - int pos = byteBuffer.position(); - int limit = byteBuffer.limit(); - SSLEngineResult res = delegate.wrap(byteBuffers, i, i1, byteBuffer); - if(!ourHelloSent && res.bytesProduced() > 0) { - if(delegate.getUseClientMode() && applicationProtocols != null && !applicationProtocols.isEmpty()) { - ourHelloSent = true; - ALPNHackClientByteArrayOutputStream = replaceClientByteOutput(delegate); - ByteBuffer newBuf = byteBuffer.duplicate(); - newBuf.flip(); - byte[] data = new byte[newBuf.remaining()]; - newBuf.get(data); - byte[] newData = ALPNHackClientHelloExplorer.rewriteClientHello(data, applicationProtocols); - if(newData != null) { - byte[] clientHelloMesage = new byte[newData.length - 5]; - System.arraycopy(newData, 5, clientHelloMesage, 0 , clientHelloMesage.length); - ALPNHackClientByteArrayOutputStream.setSentClientHello(clientHelloMesage); - byteBuffer.clear(); - byteBuffer.put(newData); - } - } else if (!getUseClientMode()) { - if(selectedApplicationProtocol != null && alpnHackServerByteArrayOutputStream != null) { - byte[] newServerHello = alpnHackServerByteArrayOutputStream.getServerHello(); //this is the new server hello, it will be part of the first TLS plaintext record - if (newServerHello != null) { - byteBuffer.flip(); - List records = ALPNHackServerHelloExplorer.extractRecords(byteBuffer); - ByteBuffer newData = ALPNHackServerHelloExplorer.createNewOutputRecords(newServerHello, records); - byteBuffer.position(pos); //erase the data - byteBuffer.limit(limit); - if (newData.remaining() > byteBuffer.remaining()) { - int old = newData.limit(); - newData.limit(newData.position() + byteBuffer.remaining()); - res = new SSLEngineResult(res.getStatus(), res.getHandshakeStatus(), res.bytesConsumed(), newData.remaining()); - byteBuffer.put(newData); - newData.limit(old); - bufferedWrapData = newData; - } else { - res = new SSLEngineResult(res.getStatus(), res.getHandshakeStatus(), res.bytesConsumed(), newData.remaining()); - byteBuffer.put(newData); - } - } - } - } - } - if(res.bytesProduced() > 0) { - ourHelloSent = true; - } - return res; - } - - @Override - public SSLEngineResult unwrap(ByteBuffer dataToUnwrap, ByteBuffer[] byteBuffers, int i, int i1) throws SSLException { - if(!unwrapHelloSeen) { - if(!delegate.getUseClientMode() && applicationProtocols != null) { - try { - List result = ALPNHackClientHelloExplorer.exploreClientHello(dataToUnwrap.duplicate()); - if(result != null) { - for(String protocol : applicationProtocols) { - if(result.contains(protocol)) { - selectedApplicationProtocol = protocol; - break; - } - } - } - unwrapHelloSeen = true; - } catch (BufferUnderflowException e) { - return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, SSLEngineResult.HandshakeStatus.NEED_UNWRAP, 0, 0); - } - } else if(delegate.getUseClientMode() && ALPNHackClientByteArrayOutputStream != null) { - if(!dataToUnwrap.hasRemaining()) { - return delegate.unwrap(dataToUnwrap, byteBuffers, i, i1); - } - try { - ByteBuffer dup = dataToUnwrap.duplicate(); - int type = dup.get(); - int major = dup.get(); - int minor = dup.get(); - if(type == 22 && major == 3 && minor == 3) { - //we only care about TLS 1.2 - //split up the records, there may be multiple when doing a fast session resume - List records = ALPNHackServerHelloExplorer.extractRecords(dataToUnwrap.duplicate()); - - ByteBuffer firstRecord = records.get(0); //this will be the handshake record - - final AtomicReference alpnResult = new AtomicReference<>(); - ByteBuffer dupFirst = firstRecord.duplicate(); - dupFirst.position(firstRecord.position() + 5); - ByteBuffer firstLessFraming = dupFirst.duplicate(); - - byte[] result = ALPNHackServerHelloExplorer.removeAlpnExtensionsFromServerHello(dupFirst, alpnResult); - firstLessFraming.limit(dupFirst.position()); - unwrapHelloSeen = true; - if (result != null) { - selectedApplicationProtocol = alpnResult.get(); - int newFirstRecordLength = result.length + dupFirst.remaining(); - byte[] newFirstRecord = new byte[newFirstRecordLength]; - System.arraycopy(result, 0, newFirstRecord, 0, result.length); - dupFirst.get(newFirstRecord, result.length, dupFirst.remaining()); - dataToUnwrap.position(dataToUnwrap.limit()); - - byte[] originalFirstRecord = new byte[firstLessFraming.remaining()]; - firstLessFraming.get(originalFirstRecord); - - ByteBuffer newData = ALPNHackServerHelloExplorer.createNewOutputRecords(newFirstRecord, records); - dataToUnwrap.clear(); - dataToUnwrap.put(newData); - dataToUnwrap.flip(); - ALPNHackClientByteArrayOutputStream.setReceivedServerHello(originalFirstRecord); - } - } - } catch (BufferUnderflowException e) { - return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, SSLEngineResult.HandshakeStatus.NEED_UNWRAP, 0, 0); - } - } - } - SSLEngineResult res = delegate.unwrap(dataToUnwrap, byteBuffers, i, i1); - if(!delegate.getUseClientMode() && selectedApplicationProtocol != null && alpnHackServerByteArrayOutputStream == null) { - alpnHackServerByteArrayOutputStream = replaceServerByteOutput(delegate, selectedApplicationProtocol); - } - return res; - } - - @Override - public Runnable getDelegatedTask() { - return delegate.getDelegatedTask(); - } - - @Override - public void closeInbound() throws SSLException { - delegate.closeInbound(); - } - - @Override - public boolean isInboundDone() { - return delegate.isInboundDone(); - } - - @Override - public void closeOutbound() { - delegate.closeOutbound(); - } - - @Override - public boolean isOutboundDone() { - return delegate.isOutboundDone(); - } - - @Override - public String[] getSupportedCipherSuites() { - return delegate.getSupportedCipherSuites(); - } - - @Override - public String[] getEnabledCipherSuites() { - return delegate.getEnabledCipherSuites(); - } - - @Override - public void setEnabledCipherSuites(String[] strings) { - delegate.setEnabledCipherSuites(strings); - } - - @Override - public String[] getSupportedProtocols() { - return delegate.getSupportedProtocols(); - } - - @Override - public String[] getEnabledProtocols() { - return delegate.getEnabledProtocols(); - } - - @Override - public void setEnabledProtocols(String[] strings) { - delegate.setEnabledProtocols(strings); - } - - @Override - public SSLSession getSession() { - return delegate.getSession(); - } - - @Override - public void beginHandshake() throws SSLException { - delegate.beginHandshake(); - } - - @Override - public SSLEngineResult.HandshakeStatus getHandshakeStatus() { - return delegate.getHandshakeStatus(); - } - - @Override - public void setUseClientMode(boolean b) { - delegate.setUseClientMode(b); - } - - @Override - public boolean getUseClientMode() { - return delegate.getUseClientMode(); - } - - @Override - public void setNeedClientAuth(boolean b) { - delegate.setNeedClientAuth(b); - } - - @Override - public boolean getNeedClientAuth() { - return delegate.getNeedClientAuth(); - } - - @Override - public void setWantClientAuth(boolean b) { - delegate.setWantClientAuth(b); - } - - @Override - public boolean getWantClientAuth() { - return delegate.getWantClientAuth(); - } - - @Override - public void setEnableSessionCreation(boolean b) { - delegate.setEnableSessionCreation(b); - } - - @Override - public boolean getEnableSessionCreation() { - return delegate.getEnableSessionCreation(); - } - - /** - * JDK8 ALPN hack support method. - * - * These methods will be removed once JDK8 ALPN support is no longer required - * @param applicationProtocols - */ - public void setApplicationProtocols(List applicationProtocols) { - this.applicationProtocols = applicationProtocols; - } - - /** - * JDK8 ALPN hack support method. - * - * These methods will be removed once JDK8 ALPN support is no longer required - */ - public List getApplicationProtocols() { - return applicationProtocols; - } - - /** - * JDK8 ALPN hack support method. - * - * These methods will be removed once JDK8 ALPN support is no longer required - */ - public String getSelectedApplicationProtocol() { - return selectedApplicationProtocol; - } - - - static ALPNHackServerByteArrayOutputStream replaceServerByteOutput(SSLEngine sslEngine, String selectedAlpnProtocol) { - try { - Object handshaker = HANDSHAKER.get(sslEngine); - Object hash = HANDSHAKE_HASH.get(handshaker); - ByteArrayOutputStream existing = (ByteArrayOutputStream) HANDSHAKE_HASH_DATA.get(hash); - - ALPNHackServerByteArrayOutputStream out = new ALPNHackServerByteArrayOutputStream(sslEngine, existing.toByteArray(), selectedAlpnProtocol); - HANDSHAKE_HASH_DATA.set(hash, out); - return out; - } catch (Exception e) { - log.debug("Failed to replace hash output stream ", e); - return null; - } - } - - static ALPNHackClientByteArrayOutputStream replaceClientByteOutput(SSLEngine sslEngine) { - try { - Object handshaker = HANDSHAKER.get(sslEngine); - Object hash = HANDSHAKE_HASH.get(handshaker); - - ALPNHackClientByteArrayOutputStream out = new ALPNHackClientByteArrayOutputStream(sslEngine); - HANDSHAKE_HASH_DATA.set(hash, out); - return out; - } catch (Exception e) { - log.debug("Failed to replace hash output stream ", e); - return null; - } - } - static void regenerateHashes(SSLEngine sslEngineToHack, ByteArrayOutputStream data, byte[]... hashBytes) { - //hack up the SSL engine internal state - try { - Object handshaker = HANDSHAKER.get(sslEngineToHack); - Object hash = HANDSHAKE_HASH.get(handshaker); - data.reset(); - Object protocolVersion = HANDSHAKER_PROTOCOL_VERSION.get(handshaker); - HANDSHAKE_HASH_VERSION.set(hash, -1); - HANDSHAKE_HASH_PROTOCOL_DETERMINED.invoke(hash, protocolVersion); - MessageDigest digest = (MessageDigest) HANDSHAKE_HASH_FIN_MD.get(hash); - digest.reset(); - for (byte[] b : hashBytes) { - HANDSHAKE_HASH_UPDATE.invoke(hash, b, 0, b.length); - } - } catch (Exception e) { - e.printStackTrace(); //TODO: remove - throw new RuntimeException(e); - } - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerByteArrayOutputStream.java b/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerByteArrayOutputStream.java deleted file mode 100644 index 7dbc127f56e9..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerByteArrayOutputStream.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2014 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.netty.handler.ssl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; - -/** - * Super hacky class that allows the ServerHello message to be modified and the corresponding hash generated at runtime. - * - * - * @author Stuart Douglas - */ -class ALPNHackServerByteArrayOutputStream extends ByteArrayOutputStream { - - private final SSLEngine sslEngine; - - private byte[] serverHello; - private final String alpnProtocol; - private boolean ready = false; - - - ALPNHackServerByteArrayOutputStream(SSLEngine sslEngine, byte[] bytes, String alpnProtocol) { - this.sslEngine = sslEngine; - this.alpnProtocol = alpnProtocol; - try { - write(bytes); - } catch (IOException e) { - throw new RuntimeException(e); //never happen - } - ready = true; - } - - @Override - public void write(byte[] b, int off, int len) { - if(ready) { - if(b[off] == 2) { // server hello - ready = false; //we are done processing - - serverHello = new byte[len]; //TODO: actual ALPN - System.arraycopy(b, off, serverHello, 0, len); - try { - serverHello = ALPNHackServerHelloExplorer.addAlpnExtensionsToServerHello(serverHello, alpnProtocol); - } catch (SSLException e) { - throw new RuntimeException(e); - } - ALPNHackSSLEngine.regenerateHashes(sslEngine, this, toByteArray(), serverHello); - return; - } - } - super.write(b, off, len); - } - - byte[] getServerHello() { - return serverHello; - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerHelloExplorer.java b/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerHelloExplorer.java deleted file mode 100644 index b5cea62a9771..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/ALPNHackServerHelloExplorer.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2014 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.netty.handler.ssl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import javax.net.ssl.SSLException; - -/** - * Hacks up ALPN support into the server hello message - * - * This has two different usage modes, one is adding a selected protocol into the extensions, the other is removing - * all mention of ALPN and retuning the selected protocol. This dual mode does not make for the cleanest code - * but removes the need to have duplicate nearly identical methods. - * - * The if the selected protocol is set then this will be added. If the selected protocol is null then ALPN will be - * parsed and removed. - * - *

- * We only care about TLS 1.2, as TLS 1.1 is not allowed to use ALPN. - *

- * Super hacky, but slightly less hacky than modifying the boot class path - */ -final class ALPNHackServerHelloExplorer { - - // Private constructor prevents construction outside this class. - private ALPNHackServerHelloExplorer() { - } - - static byte[] addAlpnExtensionsToServerHello(byte[] source, String selectedAlpnProtocol) - throws SSLException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteBuffer input = ByteBuffer.wrap(source); - try { - - exploreHandshake(input, source.length, new AtomicReference<>(selectedAlpnProtocol), out); - //we need to adjust the record length; - int serverHelloLength = out.size() - 4; - out.write(source, input.position(), input.remaining()); //there may be more messages (cert etc), so we append them - byte[] data = out.toByteArray(); - - //now we need to adjust the handshake frame length - data[1] = (byte) ((serverHelloLength >> 16) & 0xFF); - data[2] = (byte) ((serverHelloLength >> 8) & 0xFF); - data[3] = (byte) (serverHelloLength & 0xFF); - return data; - } catch (AlpnProcessingException e) { - return source; - } - } - - /** - * removes the ALPN extensions from the server hello - * @param source - * @return - * @throws SSLException - */ - static byte[] removeAlpnExtensionsFromServerHello(ByteBuffer source, final AtomicReference selectedAlpnProtocol) - throws SSLException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - - exploreHandshake(source, source.remaining(), selectedAlpnProtocol, out); - //we need to adjust the record length; - int serverHelloLength = out.size() - 4; - byte[] data = out.toByteArray(); - - //now we need to adjust the handshake frame length - data[1] = (byte) ((serverHelloLength >> 16) & 0xFF); - data[2] = (byte) ((serverHelloLength >> 8) & 0xFF); - data[3] = (byte) (serverHelloLength & 0xFF); - return data; - } catch (AlpnProcessingException e) { - return null; - } - } - private static void exploreHandshake(ByteBuffer input, int recordLength, AtomicReference selectedAlpnProtocol, ByteArrayOutputStream out) throws SSLException { - - // What is the handshake type? - byte handshakeType = input.get(); - if (handshakeType != 0x02) { // 0x01: server_hello message - throw new SSLException("Expected server hello"); - } - out.write(handshakeType); - - // What is the handshake body length? - int handshakeLength = getInt24(input); - out.write(0); //placeholders - out.write(0); - out.write(0); - - // Theoretically, a single handshake message might span multiple - // records, but in practice this does not occur. - if (handshakeLength > recordLength - 4) { // 4: handshake header size - throw new SSLException("Multi record handshake"); - } - int old = input.limit(); - input.limit(handshakeLength + input.position()); - exploreServerHello(input, selectedAlpnProtocol, out); - input.limit(old); - } - - private static void exploreServerHello( ByteBuffer input, AtomicReference alpnProtocolReference, ByteArrayOutputStream out) throws SSLException { - - // server version - byte helloMajorVersion = input.get(); - byte helloMinorVersion = input.get(); - out.write(helloMajorVersion); - out.write(helloMinorVersion); - - for (int i = 0; i < 32; ++i) { //the Random is 32 bytes - out.write(input.get() & 0xFF); - } - - // ignore session id - processByteVector8(input, out); - - // ignore cipher_suite - out.write(input.get() & 0xFF); - out.write(input.get() & 0xFF); - - // ignore compression methods - out.write(input.get() & 0xFF); - - String existingAlpn = null; - ByteArrayOutputStream extensionsOutput = null; - if (input.remaining() > 0) { - extensionsOutput = new ByteArrayOutputStream(); - existingAlpn = exploreExtensions(input, extensionsOutput, alpnProtocolReference.get() == null); - } - - if (existingAlpn != null) { - if(alpnProtocolReference.get() != null) { - throw new AlpnProcessingException(); - } - alpnProtocolReference.set(existingAlpn); - byte[] existing = extensionsOutput.toByteArray(); - out.write(existing, 0, existing.length); - - } else if(alpnProtocolReference.get() != null) { - String selectedAlpnProtocol = alpnProtocolReference.get(); - ByteArrayOutputStream alpnBits = new ByteArrayOutputStream(); - alpnBits.write(0); - alpnBits.write(16); //ALPN type - int length = 3 + selectedAlpnProtocol.length(); //length of extension data - alpnBits.write((length >> 8) & 0xFF); - alpnBits.write(length & 0xFF); - length -= 2; - alpnBits.write((length >> 8) & 0xFF); - alpnBits.write(length & 0xFF); - alpnBits.write(selectedAlpnProtocol.length() & 0xFF); - for (int i = 0; i < selectedAlpnProtocol.length(); ++i) { - alpnBits.write(selectedAlpnProtocol.charAt(i) & 0xFF); - } - - if (extensionsOutput != null) { - byte[] existing = extensionsOutput.toByteArray(); - int newLength = existing.length - 2 + alpnBits.size(); - existing[0] = (byte) ((newLength >> 8) & 0xFF); - existing[1] = (byte) (newLength & 0xFF); - try { - out.write(existing); - out.write(alpnBits.toByteArray()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } else { - int al = alpnBits.size(); - out.write((al >> 8) & 0xFF); - out.write(al & 0xFF); - try { - out.write(alpnBits.toByteArray()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } else if(extensionsOutput != null){ - byte[] existing = extensionsOutput.toByteArray(); - out.write(existing, 0, existing.length); - } - } - - static List extractRecords(ByteBuffer data) { - List ret = new ArrayList<>(); - while (data.hasRemaining()) { - byte d1 = data.get(); - byte d2 = data.get(); - byte d3 = data.get(); - byte d4 = data.get(); - byte d5 = data.get(); - int length = (d4 & 0xFF) << 8 | d5 & 0xFF; - byte[] b = new byte[length + 5]; - b[0] = d1; - b[1] = d2; - b[2] = d3; - b[3] = d4; - b[4] = d5; - data.get(b, 5, length); - ret.add(ByteBuffer.wrap(b)); - } - return ret; - } - - private static String exploreExtensions(ByteBuffer input, ByteArrayOutputStream extensionOut, boolean removeAlpn) - throws SSLException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - String ret = null; - int length = getInt16(input); // length of extensions - out.write((length >> 8) & 0xFF); - out.write(length & 0xFF); - int originalLength = length; - while (length > 0) { - int extType = getInt16(input); // extenson type - int extLen = getInt16(input); // length of extension data - if(extType == 16) { - int vlen = getInt16(input); - ret = readByteVector8(input); - if(!removeAlpn) { - //we write the extension data back to the output stream - out.write((extType >> 8) & 0xFF); - out.write(extType & 0xFF); - out.write((extLen >> 8) & 0xFF); - out.write(extLen & 0xFF); - out.write((vlen >> 8) & 0xFF); - out.write(vlen & 0xFF); - out.write(ret.length() & 0xFF); - for(int i = 0; i < ret.length(); ++i) { - out.write(ret.charAt(i) & 0xFF); - } - } else { - originalLength -= 6; - originalLength -= vlen; - } - } else { - out.write((extType >> 8) & 0xFF); - out.write(extType & 0xFF); - out.write((extLen >> 8) & 0xFF); - out.write(extLen & 0xFF); - processByteVector(input, extLen, out); - } - length -= extLen + 4; - } - if(removeAlpn && ret == null) { - //there was not ALPN to remove, so this whole thing is unnecessary, throw an exception to abort - throw new AlpnProcessingException(); - } - byte[] data = out.toByteArray(); - data[0] = (byte) ((originalLength >> 8) & 0xFF); - data[1] = (byte) (originalLength & 0xFF); - extensionOut.write(data, 0, data.length); - return ret; - } - - private static String readByteVector8(ByteBuffer input) { - int length = getInt8(input); - byte[] data = new byte[length]; - input.get(data); - return new String(data, StandardCharsets.US_ASCII); - } - private static int getInt8(ByteBuffer input) { - return input.get(); - } - - private static int getInt16(ByteBuffer input) { - return (input.get() & 0xFF) << 8 | input.get() & 0xFF; - } - - private static int getInt24(ByteBuffer input) { - return (input.get() & 0xFF) << 16 | (input.get() & 0xFF) << 8 | - input.get() & 0xFF; - } - private static void processByteVector8(ByteBuffer input, ByteArrayOutputStream out) { - int int8 = getInt8(input); - out.write(int8 & 0xFF); - processByteVector(input, int8, out); - } - - - private static void processByteVector(ByteBuffer input, int length, ByteArrayOutputStream out) { - for (int i = 0; i < length; ++i) { - out.write(input.get() & 0xFF); - } - } - - static ByteBuffer createNewOutputRecords(byte[] newFirstMessage, List records) { - int length = newFirstMessage.length; - length += 5; //Framing layer - for (int i = 1; i < records.size(); ++i) { - //the first record is the old server hello, so we start at 1 rather than zero - ByteBuffer rec = records.get(i); - length += rec.remaining(); - } - byte[] newData = new byte[length]; - ByteBuffer ret = ByteBuffer.wrap(newData); - ByteBuffer oldHello = records.get(0); - ret.put(oldHello.get()); //type - ret.put(oldHello.get()); //major - ret.put(oldHello.get()); //minor - ret.put((byte) ((newFirstMessage.length >> 8) & 0xFF)); - ret.put((byte) (newFirstMessage.length & 0xFF)); - ret.put(newFirstMessage); - for (int i = 1; i < records.size(); ++i) { - ByteBuffer rec = records.get(i); - ret.put(rec); - } - ret.flip(); - return ret; - } - - private static final class AlpnProcessingException extends RuntimeException { - - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkApplicationProtocolNegotiator.java b/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkApplicationProtocolNegotiator.java deleted file mode 100644 index 241bad2bd966..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkApplicationProtocolNegotiator.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.netty.handler.ssl; - - -import java.util.List; - -import javax.net.ssl.SSLEngine; - -/** - * Netty's negotiator for Hacked ALPN SSL Engine. - * - * @author Sebastian Łaskawiec - */ -public class AlpnHackedJdkApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator { - - private static final SslEngineWrapperFactory ALPN_WRAPPER = new SslEngineWrapperFactory() { - @Override - public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator, - boolean isServer) { - ALPNHackSSLEngine wrappedEngine = new ALPNHackSSLEngine(engine); - wrappedEngine.setApplicationProtocols(applicationNegotiator.protocols()); - return new AlpnHackedJdkSslEngine(wrappedEngine); - } - }; - - public AlpnHackedJdkApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, List protocols) { - super(ALPN_WRAPPER - , failIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY - , failIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY - , protocols); - } - -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslContext.java b/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslContext.java deleted file mode 100644 index c120558a6b4d..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslContext.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.netty.handler.ssl; - -import javax.net.ssl.SSLContext; - -/** - * Hacked ALPN SSL Context for Netty. - * - * @author Sebastian Łaskawiec - */ -public class AlpnHackedJdkSslContext extends JdkSslContext { - - public AlpnHackedJdkSslContext(SSLContext sslContext, boolean isClient, Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, ClientAuth clientAuth) { - super(sslContext, isClient, ciphers, cipherFilter, createNegotiator(apn), clientAuth, null, false); - } - - private final static JdkApplicationProtocolNegotiator createNegotiator(ApplicationProtocolConfig apn) { - if (apn == null) { - return JdkDefaultApplicationProtocolNegotiator.INSTANCE; - } - return new AlpnHackedJdkApplicationProtocolNegotiator(apn.selectorFailureBehavior() == ApplicationProtocolConfig.SelectorFailureBehavior.FATAL_ALERT, apn.supportedProtocols()); - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslEngine.java b/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslEngine.java deleted file mode 100644 index c70727092e94..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedJdkSslEngine.java +++ /dev/null @@ -1,190 +0,0 @@ -package io.netty.handler.ssl; - -import java.nio.ByteBuffer; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSession; - -public class AlpnHackedJdkSslEngine extends SSLEngine implements ApplicationProtocolAccessor { - - private final ALPNHackSSLEngine engine; - private final AlpnHackedSslSession session; - - AlpnHackedJdkSslEngine(ALPNHackSSLEngine engine) { - this.engine = engine; - session = new AlpnHackedSslSession(engine); - } - - @Override - public AlpnHackedSslSession getSession() { - return session; - } - - @Override - public void closeInbound() throws SSLException { - engine.closeInbound(); - } - - @Override - public void closeOutbound() { - engine.closeOutbound(); - } - - @Override - public String getPeerHost() { - return engine.getPeerHost(); - } - - @Override - public int getPeerPort() { - return engine.getPeerPort(); - } - - @Override - public SSLEngineResult wrap(ByteBuffer byteBuffer, ByteBuffer byteBuffer2) throws SSLException { - return engine.wrap(byteBuffer, byteBuffer2); - } - - @Override - public SSLEngineResult wrap(ByteBuffer[] byteBuffers, ByteBuffer byteBuffer) throws SSLException { - return engine.wrap(byteBuffers, byteBuffer); - } - - @Override - public SSLEngineResult wrap(ByteBuffer[] byteBuffers, int i, int i2, ByteBuffer byteBuffer) throws SSLException { - return engine.wrap(byteBuffers, i, i2, byteBuffer); - } - - @Override - public SSLEngineResult unwrap(ByteBuffer byteBuffer, ByteBuffer byteBuffer2) throws SSLException { - return engine.unwrap(byteBuffer, byteBuffer2); - } - - @Override - public SSLEngineResult unwrap(ByteBuffer byteBuffer, ByteBuffer[] byteBuffers) throws SSLException { - return engine.unwrap(byteBuffer, byteBuffers); - } - - @Override - public SSLEngineResult unwrap(ByteBuffer byteBuffer, ByteBuffer[] byteBuffers, int i, int i2) throws SSLException { - return engine.unwrap(byteBuffer, byteBuffers, i, i2); - } - - @Override - public Runnable getDelegatedTask() { - return engine.getDelegatedTask(); - } - - @Override - public boolean isInboundDone() { - return engine.isInboundDone(); - } - - @Override - public boolean isOutboundDone() { - return engine.isOutboundDone(); - } - - @Override - public String[] getSupportedCipherSuites() { - return engine.getSupportedCipherSuites(); - } - - @Override - public String[] getEnabledCipherSuites() { - return engine.getEnabledCipherSuites(); - } - - @Override - public void setEnabledCipherSuites(String[] strings) { - engine.setEnabledCipherSuites(strings); - } - - @Override - public String[] getSupportedProtocols() { - return engine.getSupportedProtocols(); - } - - @Override - public String[] getEnabledProtocols() { - return engine.getEnabledProtocols(); - } - - @Override - public void setEnabledProtocols(String[] strings) { - engine.setEnabledProtocols(strings); - } - - @Override - public SSLSession getHandshakeSession() { - return engine.getHandshakeSession(); - } - - @Override - public void beginHandshake() throws SSLException { - engine.beginHandshake(); - } - - @Override - public SSLEngineResult.HandshakeStatus getHandshakeStatus() { - return engine.getHandshakeStatus(); - } - - @Override - public void setUseClientMode(boolean b) { - engine.setUseClientMode(b); - } - - @Override - public boolean getUseClientMode() { - return engine.getUseClientMode(); - } - - @Override - public void setNeedClientAuth(boolean b) { - engine.setNeedClientAuth(b); - } - - @Override - public boolean getNeedClientAuth() { - return engine.getNeedClientAuth(); - } - - @Override - public void setWantClientAuth(boolean b) { - engine.setWantClientAuth(b); - } - - @Override - public boolean getWantClientAuth() { - return engine.getWantClientAuth(); - } - - @Override - public void setEnableSessionCreation(boolean b) { - engine.setEnableSessionCreation(b); - } - - @Override - public boolean getEnableSessionCreation() { - return engine.getEnableSessionCreation(); - } - - @Override - public SSLParameters getSSLParameters() { - return engine.getSSLParameters(); - } - - @Override - public void setSSLParameters(SSLParameters sslParameters) { - engine.setSSLParameters(sslParameters); - } - - @Override - public String getNegotiatedApplicationProtocol() { - return engine.getSelectedApplicationProtocol(); - } -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedSslSession.java b/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedSslSession.java deleted file mode 100644 index b049aada784f..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/AlpnHackedSslSession.java +++ /dev/null @@ -1,134 +0,0 @@ -package io.netty.handler.ssl; - - -import java.security.Principal; -import java.security.cert.Certificate; - -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSessionContext; -import javax.security.cert.X509Certificate; - -/** - * Hacked ALPN SSL Session for Netty. This class allows to grab negotiated protocols out of Hacked ALPN SSL Engine. - * - * @author Sebastian Łaskawiec - */ -public class AlpnHackedSslSession implements SSLSession { - - private final ALPNHackSSLEngine engine; - - AlpnHackedSslSession(ALPNHackSSLEngine engine) { - this.engine = engine; - } - - private SSLSession unwrap() { - return engine.getSession(); - } - - @Override - public String getProtocol() { - return unwrap().getProtocol(); - } - - @Override - public byte[] getId() { - return unwrap().getId(); - } - - @Override - public SSLSessionContext getSessionContext() { - return unwrap().getSessionContext(); - } - - @Override - public long getCreationTime() { - return unwrap().getCreationTime(); - } - - @Override - public long getLastAccessedTime() { - return unwrap().getLastAccessedTime(); - } - - @Override - public void invalidate() { - unwrap().invalidate(); - } - - @Override - public boolean isValid() { - return unwrap().isValid(); - } - - @Override - public void putValue(String s, Object o) { - unwrap().putValue(s, o); - } - - @Override - public Object getValue(String s) { - return unwrap().getValue(s); - } - - @Override - public void removeValue(String s) { - unwrap().removeValue(s); - } - - @Override - public String[] getValueNames() { - return unwrap().getValueNames(); - } - - @Override - public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { - return unwrap().getPeerCertificates(); - } - - @Override - public Certificate[] getLocalCertificates() { - return unwrap().getLocalCertificates(); - } - - @Override - public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { - return unwrap().getPeerCertificateChain(); - } - - @Override - public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { - return unwrap().getPeerPrincipal(); - } - - @Override - public Principal getLocalPrincipal() { - return unwrap().getLocalPrincipal(); - } - - @Override - public String getCipherSuite() { - return unwrap().getCipherSuite(); - } - - @Override - public String getPeerHost() { - return unwrap().getPeerHost(); - } - - @Override - public int getPeerPort() { - return unwrap().getPeerPort(); - } - - @Override - public int getPacketBufferSize() { - return unwrap().getPacketBufferSize(); - } - - @Override - public int getApplicationBufferSize() { - return unwrap().getApplicationBufferSize(); - } - -} diff --git a/server/core/src/main/java/io/netty/handler/ssl/package-info.java b/server/core/src/main/java/io/netty/handler/ssl/package-info.java deleted file mode 100644 index 5621aa2381f6..000000000000 --- a/server/core/src/main/java/io/netty/handler/ssl/package-info.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * This package contains hacked SSL Engine for handling ALPN. - * - *

- * Unfortunately JDK 8 doesn't have support handling TLS/ALPN for negotiating protocols. Using OpenSSL doesn't - * improve the situation neither since we obtain an initialized {@link javax.net.ssl.SSLContext} from WildFly. - * There's also 3rd element of the puzzle - Netty, which contains its own class hierarchy for handling TLS. - * - * So in order to support TLS/ALPN without Jetty's agent (which requires specific version per JVM version), we need - * to wrap original {@link javax.net.ssl.SSLEngine} with {@link io.netty.handler.ssl.ALPNHackSSLEngine} (that - * supports ALPN) and then wrap it again in {@link io.netty.handler.ssl.AlpnHackedJdkSslEngine} (and friends) to - * pass it to Netty. - * - * All classes in this package can be removed once we are baselined on JDK9. - *

- */ -package io.netty.handler.ssl; diff --git a/server/core/src/main/java/org/infinispan/server/core/utils/SslUtils.java b/server/core/src/main/java/org/infinispan/server/core/utils/SslUtils.java index a158473d3cca..44f9f26d3bc5 100644 --- a/server/core/src/main/java/org/infinispan/server/core/utils/SslUtils.java +++ b/server/core/src/main/java/org/infinispan/server/core/utils/SslUtils.java @@ -8,7 +8,6 @@ import org.infinispan.server.core.configuration.SslConfiguration; import org.infinispan.server.core.configuration.SslEngineConfiguration; -import io.netty.handler.ssl.AlpnHackedJdkSslContext; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.IdentityCipherSuiteFilter; @@ -23,23 +22,24 @@ public class SslUtils { public static JdkSslContext createNettySslContext(SslConfiguration sslConfiguration, SslEngineConfiguration sslEngineConfiguration, ApplicationProtocolConfig alpnConfig) { - return createSslContext(createJdkSslContext(sslConfiguration, sslEngineConfiguration), requireClientAuth(sslConfiguration), alpnConfig); + return createSslContext(createJdkSslContext(sslEngineConfiguration), requireClientAuth(sslConfiguration), alpnConfig); } - public static SSLContext createJdkSslContext(SslConfiguration sslConfiguration, SslEngineConfiguration sslEngineConfiguration) { + public static SSLContext createJdkSslContext(SslEngineConfiguration sslEngineConfiguration) { if (sslEngineConfiguration.sslContext() != null) { return sslEngineConfiguration.sslContext(); } - return SslContextFactory.getContext( - sslEngineConfiguration.keyStoreFileName(), - sslEngineConfiguration.keyStoreType(), - sslEngineConfiguration.keyStorePassword(), - sslEngineConfiguration.keyStoreCertificatePassword(), - sslEngineConfiguration.keyAlias(), - sslEngineConfiguration.trustStoreFileName(), - sslEngineConfiguration.trustStoreType(), - sslEngineConfiguration.trustStorePassword(), - sslEngineConfiguration.protocol(), null); + return new SslContextFactory() + .keyStoreFileName(sslEngineConfiguration.keyStoreFileName()) + .keyStoreType(sslEngineConfiguration.keyStoreType()) + .keyStorePassword(sslEngineConfiguration.keyStorePassword()) + .keyStoreCertificatePassword(sslEngineConfiguration.keyStoreCertificatePassword()) + .keyAlias(sslEngineConfiguration.keyAlias()) + .trustStoreFileName(sslEngineConfiguration.trustStoreFileName()) + .trustStoreType(sslEngineConfiguration.trustStoreType()) + .trustStorePassword(sslEngineConfiguration.trustStorePassword()) + .sslProtocol(sslEngineConfiguration.protocol()) + .getContext(); } private static JdkSslContext createSslContext(SSLContext sslContext, ClientAuth clientAuth, ApplicationProtocolConfig alpnConfig) { @@ -47,19 +47,10 @@ private static JdkSslContext createSslContext(SSLContext sslContext, ClientAuth //If we won't, JdkSslContext will use common ciphers from DEFAULT and SUPPORTED, which gives us 5 out of ~50 available ciphers //Of course, we don't need to any specific engine configuration here... just a list of ciphers String[] ciphers = SslContextFactory.getEngine(sslContext, false, clientAuth == ClientAuth.REQUIRE).getSupportedCipherSuites(); - if (alpnConfig != null && !isJdkAlpn()) { - //we want to minimize the impact of possibly bugs in hacked SSL Context. - return new AlpnHackedJdkSslContext(sslContext, false, Arrays.asList(ciphers), IdentityCipherSuiteFilter.INSTANCE, alpnConfig, clientAuth); - } else { - return new JdkSslContext(sslContext, false, Arrays.asList(ciphers), IdentityCipherSuiteFilter.INSTANCE, alpnConfig, clientAuth, null, false); - } + return new JdkSslContext(sslContext, false, Arrays.asList(ciphers), IdentityCipherSuiteFilter.INSTANCE, alpnConfig, clientAuth, null, false); } private static ClientAuth requireClientAuth(SslConfiguration sslConfig) { return sslConfig.requireClientAuth() ? ClientAuth.REQUIRE : ClientAuth.NONE; } - - private static boolean isJdkAlpn() { - return !SecurityActions.getSystemProperty("java.version").startsWith("1.8"); - } } diff --git a/server/hotrod/pom.xml b/server/hotrod/pom.xml index 952863148b71..cd36ca52212a 100644 --- a/server/hotrod/pom.xml +++ b/server/hotrod/pom.xml @@ -68,6 +68,16 @@ wildfly-elytron test
+ + org.wildfly.openssl + wildfly-openssl-java + test + + + org.wildfly.openssl + wildfly-openssl-linux-x86_64 + test + org.testng testng diff --git a/server/hotrod/src/main/java/org/infinispan/server/hotrod/Authentication.java b/server/hotrod/src/main/java/org/infinispan/server/hotrod/Authentication.java index 537d5a077aed..162fadc3bc0e 100644 --- a/server/hotrod/src/main/java/org/infinispan/server/hotrod/Authentication.java +++ b/server/hotrod/src/main/java/org/infinispan/server/hotrod/Authentication.java @@ -4,6 +4,7 @@ import java.security.Principal; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; @@ -124,7 +125,10 @@ private SaslServer createSaslServer(String mech) throws Throwable { SslHandler sslHandler = channel.pipeline().get(SslHandler.class); if (sslHandler != null) { try { - principals.add(sslHandler.engine().getSession().getPeerPrincipal()); + // Principal peerPrincipal = sslHandler.engine().getSession().getPeerPrincipal(); + // Workaround WFSSL-19 + Principal peerPrincipal = ((X509Certificate)sslHandler.engine().getSession().getPeerCertificates()[0]).getSubjectX500Principal(); + principals.add(peerPrincipal); } catch (SSLPeerUnverifiedException e) { if ("EXTERNAL".equals(mech)) { throw log.externalMechNotAllowedWithoutSSLClientCert(); diff --git a/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSniFunctionalTest.java b/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSniFunctionalTest.java index 0c5bac28f33b..c10423870e7c 100644 --- a/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSniFunctionalTest.java +++ b/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSniFunctionalTest.java @@ -138,8 +138,14 @@ public HotrodClientBuilder(HotRodServer hotRodServer) { public HotrodClientBuilder useSslConfiguration(String keystoreFileName, String keystorePassword, String truststoreFileName, String truststorePassword) { - sslContext = SslContextFactory.getContext(keystoreFileName, "pkcs12", keystorePassword.toCharArray(), - truststoreFileName, "pkcs12", truststorePassword.toCharArray()); + sslContext = new SslContextFactory() + .keyStoreFileName(keystoreFileName) + .keyStorePassword(keystorePassword.toCharArray()) + .keyStoreType("pkcs12") + .trustStoreFileName(truststoreFileName) + .trustStorePassword(truststorePassword.toCharArray()) + .trustStoreType("pkcs12") + .getContext(); sslEngine = SslContextFactory.getEngine(sslContext, true, false); return this; } @@ -160,8 +166,6 @@ public HotRodClient build() { } class HotrodServerBuilder { - - String ip = "127.0.0.1"; HotRodServerConfigurationBuilder builder = new HotRodServerConfigurationBuilder() .proxyHost("127.0.0.1") .proxyPort(serverPort()) diff --git a/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSslFunctionalTest.java b/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSslFunctionalTest.java index 98319f0ff507..b32cbeb90609 100644 --- a/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSslFunctionalTest.java +++ b/server/hotrod/src/test/java/org/infinispan/server/hotrod/HotRodSslFunctionalTest.java @@ -43,8 +43,14 @@ protected HotRodServer createStartHotRodServer(EmbeddedCacheManager cacheManager @Override protected HotRodClient connectClient(byte protocolVersion) { SslConfiguration ssl = hotRodServer.getConfiguration().ssl(); - SSLContext sslContext = SslContextFactory.getContext(ssl.keyStoreFileName(), "pkcs12", ssl.keyStorePassword(), - ssl.trustStoreFileName(), "pkcs12", ssl.trustStorePassword()); + SSLContext sslContext = new SslContextFactory() + .keyStoreFileName(ssl.keyStoreFileName()) + .keyStorePassword(ssl.keyStorePassword()) + .keyStoreType("pkcs12") + .trustStoreFileName(ssl.trustStoreFileName()) + .trustStorePassword(ssl.trustStorePassword()) + .trustStoreType("pkcs12") + .getContext(); SSLEngine sslEngine = SslContextFactory.getEngine(sslContext, true, false); return new HotRodClient(host(), hotRodServer.getPort(), cacheName, 60, protocolVersion, sslEngine); } diff --git a/server/rest/pom.xml b/server/rest/pom.xml index 6031b8e43543..8d42102cb00e 100644 --- a/server/rest/pom.xml +++ b/server/rest/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 @@ -20,8 +21,8 @@ - org.infinispan - infinispan-server-core + org.infinispan + infinispan-server-core @@ -58,11 +59,11 @@ test - - org.infinispan.protostream - protostream-processor - test - + + org.infinispan.protostream + protostream-processor + test + org.infinispan @@ -96,8 +97,13 @@ netty-codec-http2 - io.netty - netty-tcnative-boringssl-static + org.wildfly.openssl + wildfly-openssl-java + test + + + org.wildfly.openssl + wildfly-openssl-linux-x86_64 test @@ -115,11 +121,11 @@ jmh-core test - - org.infinispan - infinispan-cachestore-jdbc - test - + + org.infinispan + infinispan-cachestore-jdbc + test + org.openjdk.jmh jmh-generator-annprocess @@ -130,95 +136,95 @@ infinispan-client-rest test - - org.apache.httpcomponents - httpcore - test - + + org.apache.httpcomponents + httpcore + test + - - maven-war-plugin - - - true - - - - org.apache.maven.plugins - maven-antrun-plugin - - - create-certificates - process-test-resources - - run - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + maven-war-plugin + + + true + + + + org.apache.maven.plugins + maven-antrun-plugin + + + create-certificates + process-test-resources + + run + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/server/rest/src/main/java/org/infinispan/rest/authentication/impl/ClientCertAuthenticator.java b/server/rest/src/main/java/org/infinispan/rest/authentication/impl/ClientCertAuthenticator.java index 08bf5c9cd3ce..88b89e3f2ef0 100644 --- a/server/rest/src/main/java/org/infinispan/rest/authentication/impl/ClientCertAuthenticator.java +++ b/server/rest/src/main/java/org/infinispan/rest/authentication/impl/ClientCertAuthenticator.java @@ -1,5 +1,7 @@ package org.infinispan.rest.authentication.impl; +import java.security.Principal; +import java.security.cert.X509Certificate; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -33,7 +35,9 @@ public CompletionStage challenge(RestRequest request, ChannelHandl SslHandler sslHandler = ctx.pipeline().get(SslHandler.class); SSLSession session = sslHandler.engine().getSession(); Subject subject = new Subject(); - subject.getPrincipals().add(session.getPeerPrincipal()); + // Workaround WFSSL-19 + Principal peerPrincipal = ((X509Certificate)session.getPeerCertificates()[0]).getSubjectX500Principal(); + subject.getPrincipals().add(peerPrincipal); request.setSubject(subject); return CompletableFuture.completedFuture(new NettyRestResponse.Builder().build()); } catch (SSLPeerUnverifiedException e) { diff --git a/server/rest/src/test/java/org/infinispan/rest/AuthenticationTest.java b/server/rest/src/test/java/org/infinispan/rest/AuthenticationTest.java index 0c40f6588d9e..57a16423f83c 100644 --- a/server/rest/src/test/java/org/infinispan/rest/AuthenticationTest.java +++ b/server/rest/src/test/java/org/infinispan/rest/AuthenticationTest.java @@ -44,7 +44,7 @@ public void afterSuite() throws Exception { } @AfterMethod(alwaysRun = true) - public void afterMethod() throws Exception { + public void afterMethod() { restServer.clear(); if (restServer != null) { restServer.stop(); diff --git a/server/rest/src/test/java/org/infinispan/rest/CertificateTest.java b/server/rest/src/test/java/org/infinispan/rest/CertificateTest.java index 3004e7d693d6..7f31905efa0c 100644 --- a/server/rest/src/test/java/org/infinispan/rest/CertificateTest.java +++ b/server/rest/src/test/java/org/infinispan/rest/CertificateTest.java @@ -1,10 +1,14 @@ package org.infinispan.rest; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.infinispan.rest.assertion.ResponseAssertion; +import static org.testng.AssertJUnit.assertEquals; + +import java.util.Collections; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; + +import org.infinispan.client.rest.RestClient; +import org.infinispan.client.rest.RestResponse; +import org.infinispan.client.rest.configuration.RestClientConfigurationBuilder; import org.infinispan.rest.authentication.impl.ClientCertAuthenticator; import org.infinispan.rest.helper.RestServerHelper; import org.infinispan.test.AbstractInfinispanTest; @@ -17,13 +21,13 @@ public class CertificateTest extends AbstractInfinispanTest { public static final String TRUST_STORE_PATH = CertificateTest.class.getClassLoader().getResource("./client.p12").getPath(); - public static final String KEY_STORE_PATH = CertificateTest.class.getClassLoader().getResource("./client.p12").getPath(); + public static final String KEY_STORE_PATH = TRUST_STORE_PATH; - private HttpClient client; + private RestClient client; private RestServerHelper restServer; @AfterSuite - public void afterSuite() throws Exception { + public void afterSuite() { restServer.stop(); } @@ -32,23 +36,11 @@ public void afterMethod() throws Exception { if (restServer != null) { restServer.stop(); } - client.stop(); + client.close(); } @Test public void shouldAllowProperCertificate() throws Exception { - //given - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setTrustStorePassword(TRUST_STORE_PATH); - sslContextFactory.setTrustStorePassword("secret"); - sslContextFactory.setTrustStoreType("pkcs12"); - sslContextFactory.setKeyStorePath(KEY_STORE_PATH); - sslContextFactory.setKeyStorePassword("secret"); - sslContextFactory.setKeyStoreType("pkcs12"); - - client = new HttpClient(sslContextFactory); - client.start(); - restServer = RestServerHelper.defaultRestServer() .withAuthenticator(new ClientCertAuthenticator()) .withKeyStore(KEY_STORE_PATH, "secret", "pkcs12") @@ -56,13 +48,22 @@ public void shouldAllowProperCertificate() throws Exception { .withClientAuth() .start(TestResourceTracker.getCurrentTestShortName()); + RestClientConfigurationBuilder config = new RestClientConfigurationBuilder(); + config.security().ssl().enable() + .trustStoreFileName(KEY_STORE_PATH) + .trustStorePassword("secret".toCharArray()) + .trustStoreType("pkcs12") + .keyStoreFileName(TRUST_STORE_PATH) + .keyStorePassword("secret".toCharArray()) + .keyStoreType("pkcs12") + .hostnameVerifier((hostname, session) -> true) + .addServer().host("localhost").port(restServer.getPort()); + client = RestClient.forConfiguration(config.build()); + //when - ContentResponse response = client - .newRequest(String.format("https://localhost:%d/rest/%s/%s", restServer.getPort(), "default", "test")) - .method(HttpMethod.GET) - .send(); + CompletionStage response = client.raw().get("/rest/default/test", Collections.emptyMap()); //then - ResponseAssertion.assertThat(response).isNotFound(); + assertEquals(404, response.toCompletableFuture().get(10, TimeUnit.MINUTES).getStatus()); } } diff --git a/server/rest/src/test/java/org/infinispan/rest/Http2Test.java b/server/rest/src/test/java/org/infinispan/rest/Http2Test.java index e0cd64a7f3a9..bf9e5638f6e9 100644 --- a/server/rest/src/test/java/org/infinispan/rest/Http2Test.java +++ b/server/rest/src/test/java/org/infinispan/rest/Http2Test.java @@ -21,7 +21,6 @@ import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.ssl.OpenSsl; import io.netty.util.CharsetUtil; /** @@ -105,11 +104,6 @@ private void clearTextUpgrade(boolean previousKnowledge) throws Exception { } private void secureUpgradeTest(Protocol choice) throws Exception { - if (!OpenSsl.isAlpnSupported()) { - throw new IllegalStateException("OpenSSL is not present, can not test TLS/ALPN support. " + - "Version: " + OpenSsl.versionString() + " Cause: " + OpenSsl.unavailabilityCause()); - } - //given restServer = RestServerHelper.defaultRestServer() .withKeyStore(KEY_STORE_PATH, "secret", "pkcs12") diff --git a/server/rest/src/test/java/org/infinispan/rest/client/NettyTruststoreUtil.java b/server/rest/src/test/java/org/infinispan/rest/client/NettyTruststoreUtil.java index c639fcd9410b..8be8852f0a15 100644 --- a/server/rest/src/test/java/org/infinispan/rest/client/NettyTruststoreUtil.java +++ b/server/rest/src/test/java/org/infinispan/rest/client/NettyTruststoreUtil.java @@ -1,28 +1,19 @@ package org.infinispan.rest.client; import java.io.File; -import java.io.FileInputStream; -import java.security.KeyStore; -import javax.net.ssl.KeyManagerFactory; - -import org.infinispan.client.rest.configuration.RestClientConfiguration; import org.infinispan.client.rest.configuration.Protocol; +import org.infinispan.client.rest.configuration.RestClientConfiguration; import org.infinispan.client.rest.configuration.SslConfiguration; import org.infinispan.commons.CacheConfigurationException; import org.infinispan.commons.util.SslContextFactory; -import io.netty.handler.codec.http2.Http2SecurityUtil; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ApplicationProtocolNames; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.JdkSslContext; -import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslProvider; -import io.netty.handler.ssl.SupportedCipherSuiteFilter; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; /** * A small util for creating Netty's SSL Context @@ -30,28 +21,6 @@ * @author Sebastian Łaskawiec */ public class NettyTruststoreUtil { - - public static SslContext createTruststoreContext(String truststore, char[] password, String... alpnProtocols) throws Exception { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(truststore), password); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, password); - - SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; - return SslContextBuilder.forClient() - .sslProvider(provider) - .keyManager(kmf) - .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .applicationProtocolConfig(new ApplicationProtocolConfig( - ApplicationProtocolConfig.Protocol.ALPN, - ApplicationProtocolConfig.SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, - ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, - alpnProtocols)) - .build(); - } - - public static SslContext createSslContext(RestClientConfiguration configuration) { SslConfiguration ssl = configuration.security().ssl(); if (!ssl.enabled()) { @@ -64,20 +33,22 @@ public static SslContext createSslContext(RestClientConfiguration configuration) try { if (ssl.keyStoreFileName() != null) { - builder.keyManager(SslContextFactory.getKeyManagerFactory( - ssl.keyStoreFileName(), - ssl.keyStoreType(), - ssl.keyStorePassword(), - ssl.keyStoreCertificatePassword(), - ssl.keyAlias(), - NettyTruststoreUtil.class.getClassLoader())); + builder.keyManager(new SslContextFactory() + .keyStoreFileName(ssl.keyStoreFileName()) + .keyStorePassword(ssl.keyStorePassword()) + .keyStoreCertificatePassword(ssl.keyStoreCertificatePassword()) + .keyStoreType(ssl.keyStoreType()) + .keyAlias(ssl.keyAlias()) + .classLoader(NettyTruststoreUtil.class.getClassLoader()) + .getKeyManagerFactory()); } if (ssl.trustStoreFileName() != null) { - builder.trustManager(SslContextFactory.getTrustManagerFactory( - ssl.trustStoreFileName(), - ssl.trustStoreType(), - ssl.trustStorePassword(), - NettyTruststoreUtil.class.getClassLoader())); + builder.trustManager(new SslContextFactory() + .trustStoreFileName(ssl.trustStoreFileName()) + .trustStorePassword(ssl.trustStorePassword()) + .trustStoreType(ssl.trustStoreType()) + .classLoader(NettyTruststoreUtil.class.getClassLoader()) + .getTrustManagerFactory()); } if (ssl.trustStorePath() != null) { builder.trustManager(new File(ssl.trustStorePath())); diff --git a/server/router/pom.xml b/server/router/pom.xml index 9747718ab272..e70bf5060348 100644 --- a/server/router/pom.xml +++ b/server/router/pom.xml @@ -99,8 +99,8 @@ test - io.netty - netty-tcnative-boringssl-static + org.wildfly.openssl + wildfly-openssl-java test diff --git a/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/HotRodServerRouteDestination.java b/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/HotRodServerRouteDestination.java index 8ec65491f560..76d1115f74e5 100644 --- a/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/HotRodServerRouteDestination.java +++ b/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/HotRodServerRouteDestination.java @@ -5,31 +5,31 @@ public class HotRodServerRouteDestination implements RouteDestination { - private final String name; - private final HotRodServer hotrodServer; + private final String name; + private final HotRodServer hotrodServer; - public HotRodServerRouteDestination(String name, HotRodServer hotRodServer) { - this.name = name; - this.hotrodServer = hotRodServer; - } + public HotRodServerRouteDestination(String name, HotRodServer hotRodServer) { + this.name = name; + this.hotrodServer = hotRodServer; + } - public HotRodServer getHotrodServer() { - return hotrodServer; - } + public HotRodServer getHotrodServer() { + return hotrodServer; + } - @Override - public String toString() { - return "HotRodServerRouteDestination{" + - "name='" + name + '}'; - } + @Override + public String toString() { + return "HotRodServerRouteDestination{" + + "name='" + name + '}'; + } - @Override - public void validate() { - if (name == null || "".equals(name)) { - throw new IllegalArgumentException("Name can not be null"); - } - if (hotrodServer == null) { - throw new IllegalArgumentException("Channels can not be null"); - } - } + @Override + public void validate() { + if (name == null || "".equals(name)) { + throw new IllegalArgumentException("Name can not be null"); + } + if (hotrodServer == null) { + throw new IllegalArgumentException("Channels can not be null"); + } + } } diff --git a/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/SniNettyRouteSource.java b/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/SniNettyRouteSource.java index ea022094a8c2..84bb29782f28 100644 --- a/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/SniNettyRouteSource.java +++ b/server/router/src/main/java/org/infinispan/server/router/routes/hotrod/SniNettyRouteSource.java @@ -12,61 +12,61 @@ public class SniNettyRouteSource implements SniRouteSource { - private final SslContext nettyContext; - private final SSLContext jdkContext; - private final String sniHostName; - - public SniNettyRouteSource(String sniHostName, SSLContext sslContext) { - this.sniHostName = sniHostName; - this.jdkContext = sslContext; - nettyContext = SslUtils.INSTANCE.toNettySslContext(Optional.ofNullable(jdkContext)); - } - - public SniNettyRouteSource(String sniHostName, String keyStoreFileName, char[] keyStorePassword) { - this(sniHostName, SslContextFactory.getContext(keyStoreFileName, keyStorePassword, null, null)); - } - - @Override - public SSLContext getSslContext() { - return jdkContext; - } - - @Override - public String getSniHostName() { - return sniHostName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - SniNettyRouteSource that = (SniNettyRouteSource) o; - - if (!getSniHostName().equals(that.getSniHostName())) return false; - - return true; - } - - @Override - public int hashCode() { - return getSniHostName().hashCode(); - } - - @Override - public String toString() { - return "SniNettyRouteSource{" + - "sniHostName='" + sniHostName + '\'' + - '}'; - } - - @Override - public void validate() { - if (sniHostName == null || "".equals(sniHostName)) { - throw new IllegalArgumentException("SNI Host name can not be null"); - } - if (jdkContext == null) { - throw new IllegalArgumentException("JDK SSL Context must not be null"); - } - } + private final SslContext nettyContext; + private final SSLContext jdkContext; + private final String sniHostName; + + public SniNettyRouteSource(String sniHostName, SSLContext sslContext) { + this.sniHostName = sniHostName; + this.jdkContext = sslContext; + nettyContext = SslUtils.INSTANCE.toNettySslContext(Optional.ofNullable(jdkContext)); + } + + public SniNettyRouteSource(String sniHostName, String keyStoreFileName, char[] keyStorePassword) { + this(sniHostName, new SslContextFactory().keyStoreFileName(keyStoreFileName).keyStorePassword(keyStorePassword).getContext()); + } + + @Override + public SSLContext getSslContext() { + return jdkContext; + } + + @Override + public String getSniHostName() { + return sniHostName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SniNettyRouteSource that = (SniNettyRouteSource) o; + + if (!getSniHostName().equals(that.getSniHostName())) return false; + + return true; + } + + @Override + public int hashCode() { + return getSniHostName().hashCode(); + } + + @Override + public String toString() { + return "SniNettyRouteSource{" + + "sniHostName='" + sniHostName + '\'' + + '}'; + } + + @Override + public void validate() { + if (sniHostName == null || "".equals(sniHostName)) { + throw new IllegalArgumentException("SNI Host name can not be null"); + } + if (jdkContext == null) { + throw new IllegalArgumentException("JDK SSL Context must not be null"); + } + } } diff --git a/server/runtime/pom.xml b/server/runtime/pom.xml index 5c19c81040ab..b1222996da18 100644 --- a/server/runtime/pom.xml +++ b/server/runtime/pom.xml @@ -131,10 +131,15 @@ metainf-services - io.netty - netty-tcnative - linux-x86_64 + org.wildfly.openssl + wildfly-openssl-java + + org.wildfly.openssl + wildfly-openssl-linux-x86_64 + compile + + junit diff --git a/server/runtime/src/main/java/org/infinispan/server/Server.java b/server/runtime/src/main/java/org/infinispan/server/Server.java index f881ff44cae9..54994744bf19 100644 --- a/server/runtime/src/main/java/org/infinispan/server/Server.java +++ b/server/runtime/src/main/java/org/infinispan/server/Server.java @@ -193,9 +193,6 @@ private Server(File serverRoot, Properties properties) { this.serverConf = new File(properties.getProperty(INFINISPAN_SERVER_CONFIG_PATH)); - //SecurityActions.addSecurityProvider(new WildFlyElytronProvider()); - - // Register only the providers that matter to us SecurityActions.addSecurityProvider(WildFlyElytronHttpBasicProvider.getInstance()); SecurityActions.addSecurityProvider(WildFlyElytronHttpBearerProvider.getInstance());