diff --git a/src/main/java/com/rabbitmq/client/ConnectionFactory.java b/src/main/java/com/rabbitmq/client/ConnectionFactory.java index 279a015af7..e9af65a6b5 100644 --- a/src/main/java/com/rabbitmq/client/ConnectionFactory.java +++ b/src/main/java/com/rabbitmq/client/ConnectionFactory.java @@ -15,8 +15,6 @@ package com.rabbitmq.client; -import static java.util.concurrent.TimeUnit.*; - import com.rabbitmq.client.impl.AMQConnection; import com.rabbitmq.client.impl.ConnectionParams; import com.rabbitmq.client.impl.CredentialsProvider; @@ -32,6 +30,10 @@ import com.rabbitmq.client.impl.recovery.RetryHandler; import com.rabbitmq.client.impl.recovery.TopologyRecoveryFilter; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -50,10 +52,8 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeoutException; import java.util.function.Predicate; -import javax.net.SocketFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; + +import static java.util.concurrent.TimeUnit.MINUTES; /** * Convenience factory class to facilitate opening a {@link Connection} to a RabbitMQ node. @@ -132,7 +132,7 @@ public class ConnectionFactory implements Cloneable { // connections uses, see rabbitmq/rabbitmq-java-client#86 private ExecutorService shutdownExecutor; private ScheduledExecutorService heartbeatExecutor; - private SocketConfigurator socketConf = new DefaultSocketConfigurator(); + private SocketConfigurator socketConf = SocketConfigurators.defaultConfigurator(); private ExceptionHandler exceptionHandler = new DefaultExceptionHandler(); private CredentialsProvider credentialsProvider = new DefaultCredentialsProvider(DEFAULT_USER, DEFAULT_PASS); @@ -729,6 +729,44 @@ public void useSslProtocol(SSLContext context) { setSocketFactory(context.getSocketFactory()); } + /** + * Enable server hostname verification for TLS connections. + *
+ * This enables hostname verification regardless of the IO mode + * used (blocking or non-blocking IO). + *
+ * This can be called typically after setting the {@link SSLContext}
+ * with one of the useSslProtocol
methods.
+ *
+ * @see NioParams#enableHostnameVerification()
+ * @see NioParams#setSslEngineConfigurator(SslEngineConfigurator)
+ * @see SslEngineConfigurators#ENABLE_HOSTNAME_VERIFICATION
+ * @see SocketConfigurators#ENABLE_HOSTNAME_VERIFICATION
+ * @see ConnectionFactory#useSslProtocol(String)
+ * @see ConnectionFactory#useSslProtocol(SSLContext)
+ * @see ConnectionFactory#useSslProtocol()
+ * @see ConnectionFactory#useSslProtocol(String, TrustManager)
+ */
+ public void enableHostnameVerification() {
+ enableHostnameVerificationForNio();
+ enableHostnameVerificationForBlockingIo();
+ }
+
+ protected void enableHostnameVerificationForNio() {
+ if (this.nioParams == null) {
+ this.nioParams = new NioParams();
+ }
+ this.nioParams = this.nioParams.enableHostnameVerification();
+ }
+
+ protected void enableHostnameVerificationForBlockingIo() {
+ if (this.socketConf == null) {
+ this.socketConf = SocketConfigurators.builder().defaultConfigurator().enableHostnameVerification().build();
+ } else {
+ this.socketConf = this.socketConf.andThen(SocketConfigurators.enableHostnameVerification());
+ }
+ }
+
public static String computeDefaultTlsProcotol(String[] supportedProtocols) {
if(supportedProtocols != null) {
for (String supportedProtocol : supportedProtocols) {
diff --git a/src/main/java/com/rabbitmq/client/SocketChannelConfigurator.java b/src/main/java/com/rabbitmq/client/SocketChannelConfigurator.java
index 5aded698f9..ceb3a95a88 100644
--- a/src/main/java/com/rabbitmq/client/SocketChannelConfigurator.java
+++ b/src/main/java/com/rabbitmq/client/SocketChannelConfigurator.java
@@ -17,7 +17,9 @@
import java.io.IOException;
import java.nio.channels.SocketChannel;
+import java.util.Objects;
+@FunctionalInterface
public interface SocketChannelConfigurator {
/**
@@ -26,4 +28,18 @@ public interface SocketChannelConfigurator {
*/
void configure(SocketChannel socketChannel) throws IOException;
+ /**
+ * Returns a composed configurator that performs, in sequence, this
+ * operation followed by the {@code after} operation.
+ *
+ * @param after the operation to perform after this operation
+ * @return a composed configurator that performs in sequence this
+ * operation followed by the {@code after} operation
+ * @throws NullPointerException if {@code after} is null
+ */
+ default SocketChannelConfigurator andThen(SocketChannelConfigurator after) {
+ Objects.requireNonNull(after);
+ return t -> { configure(t); after.configure(t); };
+ }
+
}
diff --git a/src/main/java/com/rabbitmq/client/SocketChannelConfigurators.java b/src/main/java/com/rabbitmq/client/SocketChannelConfigurators.java
new file mode 100644
index 0000000000..566d3ddc13
--- /dev/null
+++ b/src/main/java/com/rabbitmq/client/SocketChannelConfigurators.java
@@ -0,0 +1,111 @@
+// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
+//
+// This software, the RabbitMQ Java client library, is triple-licensed under the
+// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
+// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
+// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
+// please see LICENSE-APACHE2.
+//
+// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
+// either express or implied. See the LICENSE file for specific language governing
+// rights and limitations of this software.
+//
+// If you have any questions regarding licensing, please contact us at
+// info@rabbitmq.com.
+
+package com.rabbitmq.client;
+
+/**
+ * Ready-to-use instances and builder for {@link SocketChannelConfigurator}.
+ *
+ * Note {@link SocketChannelConfigurator}s can be combined with + * {@link SocketChannelConfigurator#andThen(SocketChannelConfigurator)}. + * + * @since 5.4.0 + */ +public abstract class SocketChannelConfigurators { + + /** + * Disable Nagle's algorithm. + */ + public static final SocketChannelConfigurator DISABLE_NAGLE_ALGORITHM = + socketChannel -> SocketConfigurators.DISABLE_NAGLE_ALGORITHM.configure(socketChannel.socket()); + + /** + * Default {@link SocketChannelConfigurator} that disables Nagle's algorithm. + */ + public static final SocketChannelConfigurator DEFAULT = DISABLE_NAGLE_ALGORITHM; + + /** + * The default {@link SocketChannelConfigurator} that disables Nagle's algorithm. + * + * @return + */ + public static SocketChannelConfigurator defaultConfigurator() { + return DEFAULT; + } + + /** + * {@link SocketChannelConfigurator} that disables Nagle's algorithm. + * + * @return + */ + public static SocketChannelConfigurator disableNagleAlgorithm() { + return DISABLE_NAGLE_ALGORITHM; + } + + /** + * Builder to configure and creates a {@link SocketChannelConfigurator} instance. + * + * @return + */ + public static SocketChannelConfigurators.Builder builder() { + return new SocketChannelConfigurators.Builder(); + } + + public static class Builder { + + private SocketChannelConfigurator configurator = channel -> { + }; + + /** + * Set default configuration. + * + * @return + */ + public Builder defaultConfigurator() { + configurator = configurator.andThen(DEFAULT); + return this; + } + + /** + * Disable Nagle's Algorithm. + * + * @return + */ + public Builder disableNagleAlgorithm() { + configurator = configurator.andThen(DISABLE_NAGLE_ALGORITHM); + return this; + } + + /** + * Add an extra configuration step. + * + * @param extraConfiguration + * @return + */ + public Builder add(SocketChannelConfigurator extraConfiguration) { + configurator = configurator.andThen(extraConfiguration); + return this; + } + + /** + * Return the configured {@link SocketConfigurator}. + * + * @return + */ + public SocketChannelConfigurator build() { + return configurator; + } + } +} diff --git a/src/main/java/com/rabbitmq/client/SocketConfigurator.java b/src/main/java/com/rabbitmq/client/SocketConfigurator.java index 8896baf3e5..30c9ed4bab 100644 --- a/src/main/java/com/rabbitmq/client/SocketConfigurator.java +++ b/src/main/java/com/rabbitmq/client/SocketConfigurator.java @@ -17,11 +17,31 @@ import java.io.IOException; import java.net.Socket; +import java.util.Objects; +@FunctionalInterface public interface SocketConfigurator { + /** * Provides a hook to insert custom configuration of the sockets * used to connect to an AMQP server before they connect. */ void configure(Socket socket) throws IOException; + + /** + * Returns a composed configurator that performs, in sequence, this + * operation followed by the {@code after} operation. + * + * @param after the operation to perform after this operation + * @return a composed configurator that performs in sequence this + * operation followed by the {@code after} operation + * @throws NullPointerException if {@code after} is null + */ + default SocketConfigurator andThen(SocketConfigurator after) { + Objects.requireNonNull(after); + return t -> { + configure(t); + after.configure(t); + }; + } } diff --git a/src/main/java/com/rabbitmq/client/SocketConfigurators.java b/src/main/java/com/rabbitmq/client/SocketConfigurators.java new file mode 100644 index 0000000000..551ad95ca9 --- /dev/null +++ b/src/main/java/com/rabbitmq/client/SocketConfigurators.java @@ -0,0 +1,153 @@ +// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; + +/** + * Ready-to-use instances and builder for {@link SocketConfigurator}. + *
+ * Note {@link SocketConfigurator}s can be combined with + * {@link SocketConfigurator#andThen(SocketConfigurator)}. + * + * @since 5.4.0 + */ +public abstract class SocketConfigurators { + + /** + * Disable Nagle's algorithm. + */ + public static final SocketConfigurator DISABLE_NAGLE_ALGORITHM = socket -> socket.setTcpNoDelay(true); + + /** + * Default {@link SocketConfigurator} that disables Nagle's algorithm. + */ + public static final SocketConfigurator DEFAULT = DISABLE_NAGLE_ALGORITHM; + + /** + * Enable server hostname validation for TLS connections. + */ + public static final SocketConfigurator ENABLE_HOSTNAME_VERIFICATION = socket -> { + if (socket instanceof SSLSocket) { + SSLSocket sslSocket = (SSLSocket) socket; + SSLParameters sslParameters = enableHostnameVerification(sslSocket.getSSLParameters()); + sslSocket.setSSLParameters(sslParameters); + } + }; + + static final SSLParameters enableHostnameVerification(SSLParameters sslParameters) { + if (sslParameters == null) { + sslParameters = new SSLParameters(); + } + // It says HTTPS but works also for any TCP connection. + // It checks SAN (Subject Alternative Name) as well as CN. + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + return sslParameters; + } + + /** + * The default {@link SocketConfigurator} that disables Nagle's algorithm. + * + * @return + */ + public static SocketConfigurator defaultConfigurator() { + return DEFAULT; + } + + /** + * {@link SocketConfigurator} that disables Nagle's algorithm. + * + * @return + */ + public static SocketConfigurator disableNagleAlgorithm() { + return DISABLE_NAGLE_ALGORITHM; + } + + /** + * {@link SocketConfigurator} that enable server hostname verification for TLS connections. + * + * @return + */ + public static SocketConfigurator enableHostnameVerification() { + return ENABLE_HOSTNAME_VERIFICATION; + } + + /** + * Builder to configure and creates a {@link SocketConfigurator} instance. + * + * @return + */ + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private SocketConfigurator configurator = socket -> { + }; + + /** + * Set default configuration. + * + * @return + */ + public Builder defaultConfigurator() { + configurator = configurator.andThen(DEFAULT); + return this; + } + + /** + * Disable Nagle's Algorithm. + * + * @return + */ + public Builder disableNagleAlgorithm() { + configurator = configurator.andThen(DISABLE_NAGLE_ALGORITHM); + return this; + } + + /** + * Enable server hostname verification for TLS connections. + * + * @return + */ + public Builder enableHostnameVerification() { + configurator = configurator.andThen(ENABLE_HOSTNAME_VERIFICATION); + return this; + } + + /** + * Add an extra configuration step. + * + * @param extraConfiguration + * @return + */ + public Builder add(SocketConfigurator extraConfiguration) { + configurator = configurator.andThen(extraConfiguration); + return this; + } + + /** + * Return the configured {@link SocketConfigurator}. + * + * @return + */ + public SocketConfigurator build() { + return configurator; + } + } +} diff --git a/src/main/java/com/rabbitmq/client/SslEngineConfigurator.java b/src/main/java/com/rabbitmq/client/SslEngineConfigurator.java index 7986d4b9d2..01b22c4c05 100644 --- a/src/main/java/com/rabbitmq/client/SslEngineConfigurator.java +++ b/src/main/java/com/rabbitmq/client/SslEngineConfigurator.java @@ -17,7 +17,9 @@ import javax.net.ssl.SSLEngine; import java.io.IOException; +import java.util.Objects; +@FunctionalInterface public interface SslEngineConfigurator { /** @@ -27,4 +29,18 @@ public interface SslEngineConfigurator { */ void configure(SSLEngine sslEngine) throws IOException; + /** + * Returns a composed configurator that performs, in sequence, this + * operation followed by the {@code after} operation. + * + * @param after the operation to perform after this operation + * @return a composed configurator that performs in sequence this + * operation followed by the {@code after} operation + * @throws NullPointerException if {@code after} is null + */ + default SslEngineConfigurator andThen(SslEngineConfigurator after) { + Objects.requireNonNull(after); + return t -> { configure(t); after.configure(t); }; + } + } diff --git a/src/main/java/com/rabbitmq/client/SslEngineConfigurators.java b/src/main/java/com/rabbitmq/client/SslEngineConfigurators.java new file mode 100644 index 0000000000..119bb0314f --- /dev/null +++ b/src/main/java/com/rabbitmq/client/SslEngineConfigurators.java @@ -0,0 +1,116 @@ +// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.ssl.SSLParameters; + +/** + * Ready-to-use instances and builder for {@link SslEngineConfigurator}s. + *
+ * Note {@link SslEngineConfigurator}s can be combined with
+ * {@link SslEngineConfigurator#andThen(SslEngineConfigurator)}.
+ *
+ * @since 5.4.0
+ */
+public abstract class SslEngineConfigurators {
+
+ /**
+ * Default {@link SslEngineConfigurator}, does nothing.
+ */
+ public static SslEngineConfigurator DEFAULT = sslEngine -> {
+ };
+
+ /**
+ * {@link SslEngineConfigurator} that enables server hostname verification.
+ */
+ public static SslEngineConfigurator ENABLE_HOSTNAME_VERIFICATION = sslEngine -> {
+ SSLParameters sslParameters = SocketConfigurators.enableHostnameVerification(sslEngine.getSSLParameters());
+ sslEngine.setSSLParameters(sslParameters);
+ };
+
+ /**
+ * Default {@link SslEngineConfigurator}, does nothing.
+ *
+ * @return
+ */
+ public static SslEngineConfigurator defaultConfigurator() {
+ return DEFAULT;
+ }
+
+ /**
+ * {@link SslEngineConfigurator} that enables server hostname verification.
+ *
+ * @return
+ */
+ public static SslEngineConfigurator enableHostnameVerification() {
+ return ENABLE_HOSTNAME_VERIFICATION;
+ }
+
+ /**
+ * Builder to configure and creates a {@link SslEngineConfigurator} instance.
+ *
+ * @return
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private SslEngineConfigurator configurator = channel -> {
+ };
+
+ /**
+ * Set default configuration (no op).
+ *
+ * @return
+ */
+ public Builder defaultConfigurator() {
+ configurator = configurator.andThen(DEFAULT);
+ return this;
+ }
+
+ /**
+ * Enables server hostname verification.
+ *
+ * @return
+ */
+ public Builder enableHostnameVerification() {
+ configurator = configurator.andThen(ENABLE_HOSTNAME_VERIFICATION);
+ return this;
+ }
+
+ /**
+ * Add extra configuration step.
+ *
+ * @param extraConfiguration
+ * @return
+ */
+ public Builder add(SslEngineConfigurator extraConfiguration) {
+ configurator = configurator.andThen(extraConfiguration);
+ return this;
+ }
+
+ /**
+ * Return the configured {@link SslEngineConfigurator}.
+ *
+ * @return
+ */
+ public SslEngineConfigurator build() {
+ return configurator;
+ }
+ }
+}
diff --git a/src/main/java/com/rabbitmq/client/impl/nio/NioParams.java b/src/main/java/com/rabbitmq/client/impl/nio/NioParams.java
index 9f9da61795..80b8624447 100644
--- a/src/main/java/com/rabbitmq/client/impl/nio/NioParams.java
+++ b/src/main/java/com/rabbitmq/client/impl/nio/NioParams.java
@@ -15,14 +15,16 @@
package com.rabbitmq.client.impl.nio;
-import com.rabbitmq.client.DefaultSocketChannelConfigurator;
import com.rabbitmq.client.SocketChannelConfigurator;
+import com.rabbitmq.client.SocketChannelConfigurators;
import com.rabbitmq.client.SslEngineConfigurator;
import javax.net.ssl.SSLEngine;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
+import static com.rabbitmq.client.SslEngineConfigurators.ENABLE_HOSTNAME_VERIFICATION;
+
/**
* Parameters used to configure the NIO mode of a {@link com.rabbitmq.client.ConnectionFactory}.
*
@@ -68,7 +70,7 @@ public class NioParams {
/**
* the hook to configure the socket channel before it's open
*/
- private SocketChannelConfigurator socketChannelConfigurator = new DefaultSocketChannelConfigurator();
+ private SocketChannelConfigurator socketChannelConfigurator = SocketChannelConfigurators.defaultConfigurator();
/**
* the hook to configure the SSL engine before the connection is open
@@ -94,10 +96,27 @@ public NioParams(NioParams nioParams) {
setWriteQueueCapacity(nioParams.getWriteQueueCapacity());
setNioExecutor(nioParams.getNioExecutor());
setThreadFactory(nioParams.getThreadFactory());
+ setSocketChannelConfigurator(nioParams.getSocketChannelConfigurator());
setSslEngineConfigurator(nioParams.getSslEngineConfigurator());
setConnectionShutdownExecutor(nioParams.getConnectionShutdownExecutor());
}
+ /**
+ * Enable server hostname verification for TLS connections.
+ *
+ * @return this {@link NioParams} instance
+ * @see NioParams#setSslEngineConfigurator(SslEngineConfigurator)
+ * @see com.rabbitmq.client.SslEngineConfigurators#ENABLE_HOSTNAME_VERIFICATION
+ */
+ public NioParams enableHostnameVerification() {
+ if (this.sslEngineConfigurator == null) {
+ this.sslEngineConfigurator = ENABLE_HOSTNAME_VERIFICATION;
+ } else {
+ this.sslEngineConfigurator = this.sslEngineConfigurator.andThen(ENABLE_HOSTNAME_VERIFICATION);
+ }
+ return this;
+ }
+
public int getReadByteBufferSize() {
return readByteBufferSize;
}
diff --git a/src/test/java/com/rabbitmq/client/test/BrokerTestCase.java b/src/test/java/com/rabbitmq/client/test/BrokerTestCase.java
index 27ea0cbd0d..216cbb8e47 100644
--- a/src/test/java/com/rabbitmq/client/test/BrokerTestCase.java
+++ b/src/test/java/com/rabbitmq/client/test/BrokerTestCase.java
@@ -352,18 +352,6 @@ protected String generateExchangeName() {
}
protected SSLContext getSSLContext() throws NoSuchAlgorithmException {
- SSLContext c = null;
-
- // pick the first protocol available, preferring TLSv1.2, then TLSv1,
- // falling back to SSLv3 if running on an ancient/crippled JDK
- for(String proto : Arrays.asList("TLSv1.2", "TLSv1", "SSLv3")) {
- try {
- c = SSLContext.getInstance(proto);
- return c;
- } catch (NoSuchAlgorithmException x) {
- // keep trying
- }
- }
- throw new NoSuchAlgorithmException();
+ return TestUtils.getSSLContext();
}
}
diff --git a/src/test/java/com/rabbitmq/client/test/ChannelRpcTimeoutIntegrationTest.java b/src/test/java/com/rabbitmq/client/test/ChannelRpcTimeoutIntegrationTest.java
index 40d6a0ab5a..f880f617da 100644
--- a/src/test/java/com/rabbitmq/client/test/ChannelRpcTimeoutIntegrationTest.java
+++ b/src/test/java/com/rabbitmq/client/test/ChannelRpcTimeoutIntegrationTest.java
@@ -84,7 +84,7 @@ public void tearDown() throws Exception {
private FrameHandler createFrameHandler() throws IOException {
SocketFrameHandlerFactory socketFrameHandlerFactory = new SocketFrameHandlerFactory(ConnectionFactory.DEFAULT_CONNECTION_TIMEOUT,
- SocketFactory.getDefault(), new DefaultSocketConfigurator(), false, null);
+ SocketFactory.getDefault(), SocketConfigurators.defaultConfigurator(), false, null);
return socketFrameHandlerFactory.create(new Address("localhost"), null);
}
diff --git a/src/test/java/com/rabbitmq/client/test/TestUtils.java b/src/test/java/com/rabbitmq/client/test/TestUtils.java
index 5b0b7d0d7e..b6cb834773 100644
--- a/src/test/java/com/rabbitmq/client/test/TestUtils.java
+++ b/src/test/java/com/rabbitmq/client/test/TestUtils.java
@@ -30,7 +30,10 @@
import com.rabbitmq.tools.Host;
import org.slf4j.LoggerFactory;
+import javax.net.ssl.SSLContext;
import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Callable;
@@ -64,6 +67,22 @@ public static void close(Connection connection) {
}
}
+ public static SSLContext getSSLContext() throws NoSuchAlgorithmException {
+ SSLContext c = null;
+
+ // pick the first protocol available, preferring TLSv1.2, then TLSv1,
+ // falling back to SSLv3 if running on an ancient/crippled JDK
+ for(String proto : Arrays.asList("TLSv1.2", "TLSv1", "SSLv3")) {
+ try {
+ c = SSLContext.getInstance(proto);
+ return c;
+ } catch (NoSuchAlgorithmException x) {
+ // keep trying
+ }
+ }
+ throw new NoSuchAlgorithmException();
+ }
+
public static boolean isVersion37orLater(Connection connection) {
String currentVersion = null;
try {
diff --git a/src/test/java/com/rabbitmq/client/test/functional/UnexpectedFrames.java b/src/test/java/com/rabbitmq/client/test/functional/UnexpectedFrames.java
index 0ab8013969..698d8a8952 100644
--- a/src/test/java/com/rabbitmq/client/test/functional/UnexpectedFrames.java
+++ b/src/test/java/com/rabbitmq/client/test/functional/UnexpectedFrames.java
@@ -18,6 +18,7 @@
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultSocketConfigurator;
+import com.rabbitmq.client.SocketConfigurators;
import com.rabbitmq.client.impl.*;
import com.rabbitmq.client.impl.recovery.AutorecoveringConnection;
import com.rabbitmq.client.test.BrokerTestCase;
@@ -85,7 +86,7 @@ public ConfusedConnectionFactory() {
private static class ConfusedFrameHandlerFactory extends SocketFrameHandlerFactory {
private ConfusedFrameHandlerFactory() {
- super(1000, SocketFactory.getDefault(), new DefaultSocketConfigurator(), false);
+ super(1000, SocketFactory.getDefault(), SocketConfigurators.defaultConfigurator(), false);
}
@Override public FrameHandler create(Socket sock) throws IOException {
diff --git a/src/test/java/com/rabbitmq/client/test/ssl/HostnameVerification.java b/src/test/java/com/rabbitmq/client/test/ssl/HostnameVerification.java
new file mode 100644
index 0000000000..06ee47c0a9
--- /dev/null
+++ b/src/test/java/com/rabbitmq/client/test/ssl/HostnameVerification.java
@@ -0,0 +1,123 @@
+// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved.
+//
+// This software, the RabbitMQ Java client library, is triple-licensed under the
+// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
+// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
+// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
+// please see LICENSE-APACHE2.
+//
+// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
+// either express or implied. See the LICENSE file for specific language governing
+// rights and limitations of this software.
+//
+// If you have any questions regarding licensing, please contact us at
+// info@rabbitmq.com.
+
+package com.rabbitmq.client.test.ssl;
+
+import com.rabbitmq.client.Address;
+import com.rabbitmq.client.Connection;
+import com.rabbitmq.client.ConnectionFactory;
+import com.rabbitmq.client.test.TestUtils;
+import com.rabbitmq.tools.Host;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.util.function.Consumer;
+
+import static com.rabbitmq.client.test.TestUtils.getSSLContext;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(Parameterized.class)
+public class HostnameVerification {
+
+ static SSLContext sslContext;
+ @Parameterized.Parameter
+ public Consumer