diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpNioSSLConnectionSupport.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpNioSSLConnectionSupport.java
index 346e20685f..981cd62be5 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpNioSSLConnectionSupport.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpNioSSLConnectionSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import java.security.GeneralSecurityException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.Assert;
@@ -31,15 +32,33 @@ import org.springframework.util.Assert;
/**
* Implementation of {@link TcpNioConnectionSupport} for SSL
* NIO connections.
+ *
* @author Gary Russell
+ *
* @since 2.2
*
*/
public class DefaultTcpNioSSLConnectionSupport extends AbstractTcpConnectionSupport implements TcpNioConnectionSupport {
- private volatile SSLContext sslContext;
+ private final SSLContext sslContext;
+ private final boolean sslVerifyHost;
+
+ /**
+ * Create an instance with host verification enabled.
+ * @param sslContextSupport the ssl context support.
+ */
public DefaultTcpNioSSLConnectionSupport(TcpSSLContextSupport sslContextSupport) {
+ this(sslContextSupport, true);
+ }
+
+ /**
+ * Create an instance.
+ * @param sslContextSupport the ssl context support.
+ * @param sslVerifyHost true to verify the host during handshake.
+ * @since 5.0.8
+ */
+ public DefaultTcpNioSSLConnectionSupport(TcpSSLContextSupport sslContextSupport, boolean sslVerifyHost) {
Assert.notNull(sslContextSupport, "TcpSSLContextSupport must not be null");
try {
this.sslContext = sslContextSupport.getSSLContext();
@@ -48,6 +67,7 @@ public class DefaultTcpNioSSLConnectionSupport extends AbstractTcpConnectionSupp
throw new IllegalArgumentException("Invalid TcpSSLContextSupport - it failed to provide an SSLContext", e);
}
Assert.notNull(this.sslContext, "SSLContext retrieved from context support must not be null");
+ this.sslVerifyHost = sslVerifyHost;
}
/**
@@ -56,8 +76,19 @@ public class DefaultTcpNioSSLConnectionSupport extends AbstractTcpConnectionSupp
@Override
public TcpNioConnection createNewConnection(SocketChannel socketChannel, boolean server, boolean lookupHost,
ApplicationEventPublisher applicationEventPublisher, String connectionFactoryName) throws Exception {
+
SSLEngine sslEngine = this.sslContext.createSSLEngine();
postProcessSSLEngine(sslEngine);
+ if (this.sslVerifyHost) {
+ SSLParameters sslParameters = sslEngine.getSSLParameters();
+ if (sslParameters == null) {
+ sslParameters = new SSLParameters();
+ }
+ // HTTPS works for any TCP connection.
+ // It checks SAN (Subject Alternative Name) as well as CN.
+ sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ sslEngine.setSSLParameters(sslParameters);
+ }
TcpNioSSLConnection tcpNioSSLConnection;
if (isPushbackCapable()) {
tcpNioSSLConnection = new PushBackTcpNioSSLConnection(socketChannel, server, lookupHost,
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSSLContextSupport.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSSLContextSupport.java
index bce4c44431..30cb1fbe0c 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSSLContextSupport.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSSLContextSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,12 +32,18 @@ import org.springframework.util.Assert;
* Default implementation of {@link TcpSSLContextSupport}; uses a
* 'TLS' (by default) {@link SSLContext}, initialized with 'JKS'
* keystores, managed by 'SunX509' Key and Trust managers.
+ *
* @author Gary Russell
+ *
* @since 2.1
*
*/
public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport {
+ private static final String DEFAULT_KEY_STORE_TYPE = "JKS";
+
+ private static final String DEFAULT_TRUST_STORE_TYPE = "JKS";
+
private final Resource keyStore;
private final Resource trustStore;
@@ -46,7 +52,11 @@ public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport {
private final char[] trustStorePassword;
- private volatile String protocol = "TLS";
+ private String protocol = "TLS";
+
+ private String keyStoreType = DEFAULT_KEY_STORE_TYPE;
+
+ private String trustStoreType = DEFAULT_TRUST_STORE_TYPE;
/**
* Prepares for the creation of an SSLContext using the supplied
@@ -69,9 +79,30 @@ public class DefaultTcpSSLContextSupport implements TcpSSLContextSupport {
this.trustStorePassword = trustStorePassword.toCharArray();
}
- public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
- KeyStore ks = KeyStore.getInstance("JKS");
- KeyStore ts = KeyStore.getInstance("JKS");
+ /**
+ * Set the key store type. Default JKS.
+ * @param keyStoreType the type.
+ * @since 5.0.8
+ */
+ public void setKeyStoreType(String keyStoreType) {
+ Assert.hasText(keyStoreType, "'keyStoreType' cannot be empty");
+ this.keyStoreType = keyStoreType;
+ }
+
+ /**
+ * Set the trust store type. Default JKS.
+ * @param trustStoreType the type.
+ * @since 5.0.8
+ */
+ public void setTrustStoreType(String trustStoreType) {
+ Assert.hasText(trustStoreType, "'trustStoreType' cannot be empty");
+ this.trustStoreType = trustStoreType;
+ }
+
+ @Override
+ public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
+ KeyStore ks = KeyStore.getInstance(this.keyStoreType);
+ KeyStore ts = KeyStore.getInstance(this.trustStoreType);
ks.load(this.keyStore.getInputStream(), this.keyStorePassword);
ts.load(this.trustStore.getInputStream(), this.trustStorePassword);
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSocketSupport.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSocketSupport.java
index a4712a751e..e675f7cd30 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSocketSupport.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/DefaultTcpSocketSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,25 +19,61 @@ package org.springframework.integration.ip.tcp.connection;
import java.net.ServerSocket;
import java.net.Socket;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+
/**
* Default implementation of {@link TcpSocketSupport}; makes no
* changes to sockets.
+ *
* @author Gary Russell
+ *
* @since 2.2
*
*/
public class DefaultTcpSocketSupport implements TcpSocketSupport {
+ private final boolean sslVerifyHost;
+
+ /**
+ * Construct an instance with host verification enabled.
+ */
+ public DefaultTcpSocketSupport() {
+ this(true);
+ }
+
+ /**
+ * Construct an instance with the provided sslVerifyHost.
+ * @param sslVerifyHost true to verify host during SSL handshake.
+ * @since 5.0.8.
+ */
+ public DefaultTcpSocketSupport(boolean sslVerifyHost) {
+ this.sslVerifyHost = sslVerifyHost;
+ }
+
/**
* No-Op.
*/
+ @Override
public void postProcessServerSocket(ServerSocket serverSocket) {
}
/**
- * No-Op.
+ * Enables host verification for SSL, if so configured.
*/
+ @Override
public void postProcessSocket(Socket socket) {
+ if (this.sslVerifyHost && socket instanceof SSLSocket) {
+ SSLSocket sslSocket = (SSLSocket) socket;
+ SSLParameters sslParameters = sslSocket.getSSLParameters();
+ if (sslParameters == null) {
+ sslParameters = new SSLParameters();
+ }
+ // HTTPS works for any TCP connection.
+ // It checks SAN (Subject Alternative Name) as well as CN.
+ sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ sslSocket.setSSLParameters(sslParameters);
+ }
}
}
diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
index 7a38a45b42..993735276d 100644
--- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
+++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
@@ -81,7 +81,9 @@
+ class="org.springframework.integration.ip.tcp.connection.DefaultTcpNioSSLConnectionSupport">
+
+
- (RETURN if same as keystore password):
+ Enter key password for
+ (RETURN if same as keystore password):
-$ keytool -list -v -keystore src/test/resources/test.ks
-Enter keystore password: secret
+ $ keytool -list -v -keystore src/test/resources/test.ks
+ Enter keystore password: secret
-Keystore type: JKS
-Keystore provider: SUN
+ Keystore type: JKS
+ Keystore provider: SUN
-Your keystore contains 1 entry
+ Your keystore contains 1 entry
-Alias name: sitestcertkey
-Creation date: Feb 25, 2012
-Entry type: PrivateKeyEntry
-Certificate chain length: 1
-Certificate[1]:
-Owner: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Issuer: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Serial number: 4f491902
-Valid from: Sat Feb 25 12:23:14 EST 2012 until: Mon Feb 01 12:23:14 EST 2112
-Certificate fingerprints:
- MD5: 4F:A9:76:0E:A9:C0:A8:B7:26:E7:7E:C7:E8:22:1F:8B
- SHA1: 88:AC:9E:4D:29:0D:3A:59:3B:73:95:4A:E1:BB:D0:22:89:37:64:4C
- Signature algorithm name: SHA1withRSA
- Version: 3
+ Alias name: sitestcertkey
+ Creation date: Aug 29, 2018
+ Entry type: PrivateKeyEntry
+ Certificate chain length: 1
+ Certificate[1]:
+ Owner: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Issuer: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Serial number: 3f2ab6ef
+ Valid from: Wed Aug 29 14:58:27 EDT 2018 until: Fri Aug 05 14:58:27 EDT 2118
+ Certificate fingerprints:
+ MD5: 74:14:93:3C:6E:7B:14:59:30:A3:90:C4:A2:AD:52:5E
+ SHA1: 12:BE:77:93:ED:C3:20:23:75:D7:D5:D9:FE:D9:5E:D1:D3:3E:E2:DC
+ SHA256: 6B:90:65:8D:AA:F6:F3:89:38:AE:92:8E:F0:83:26:17:DD:8A:2C:F6:7E:C5:39:F0:7E:DC:60:A3:6D:73:E1:7A
+ Signature algorithm name: SHA256withRSA
+ Subject Public Key Algorithm: 2048-bit RSA key
+ Version: 3
+
+ Extensions:
+
+ #1: ObjectId: 2.5.29.17 Criticality=false
+ SubjectAlternativeName [
+ DNSName: localhost
+ ]
+
+ #2: ObjectId: 2.5.29.14 Criticality=false
+ SubjectKeyIdentifier [
+ KeyIdentifier [
+ 0000: 78 2D FA 48 D8 21 73 86 68 CE 77 B9 98 5A BA 0F x-.H.!s.h.w..Z..
+ 0010: E2 FE CD 8C ....
+ ]
+ ]
-*******************************************
-*******************************************
-$ keytool -export -alias sitestcertkey -keystore src/test/resources/test.ks -rfc -file src/test/resources/test.cer
-Enter keystore password:
-Certificate stored in file
-
-$ keytool -import -alias sitestcertkey -file src/test/resources/test.cer -keystore src/test/resources/test.truststore.ks
-Enter keystore password: secret
-Re-enter new password: secret
-Owner: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Issuer: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Serial number: 4f491902
-Valid from: Sat Feb 25 12:23:14 EST 2012 until: Mon Feb 01 12:23:14 EST 2112
-Certificate fingerprints:
- MD5: 4F:A9:76:0E:A9:C0:A8:B7:26:E7:7E:C7:E8:22:1F:8B
- SHA1: 88:AC:9E:4D:29:0D:3A:59:3B:73:95:4A:E1:BB:D0:22:89:37:64:4C
- Signature algorithm name: SHA1withRSA
- Version: 3
-Trust this certificate? [no]: yes
-Certificate was added to keystore
-
-$ keytool -list -v -keystore src/test/resources/test.truststore.ks
-Enter keystore password: secret
-
-Keystore type: JKS
-Keystore provider: SUN
-
-Your keystore contains 1 entry
-
-Alias name: sitestcertkey
-Creation date: Feb 25, 2012
-Entry type: trustedCertEntry
-
-Owner: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Issuer: CN=Spring Integration, OU=SpringSource, O=VMware, L=Palo Alto, ST=CA, C=US
-Serial number: 4f491902
-Valid from: Sat Feb 25 12:23:14 EST 2012 until: Mon Feb 01 12:23:14 EST 2112
-Certificate fingerprints:
- MD5: 4F:A9:76:0E:A9:C0:A8:B7:26:E7:7E:C7:E8:22:1F:8B
- SHA1: 88:AC:9E:4D:29:0D:3A:59:3B:73:95:4A:E1:BB:D0:22:89:37:64:4C
- Signature algorithm name: SHA1withRSA
- Version: 3
+ *******************************************
+ *******************************************
-*******************************************
-*******************************************
+ $ keytool -export -alias sitestcertkey -keystore src/test/resources/test.ks -rfc -file src/test/resources/test.cer
+ Enter keystore password:
+ Certificate stored in file
- */
+ $ keytool -import -alias sitestcertkey -file src/test/resources/test.cer -keystore src/test/resources/test.truststore.ks
+ Enter keystore password: secret
+ Re-enter new password: secret
+ Owner: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Issuer: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Serial number: 3f2ab6ef
+ Valid from: Wed Aug 29 14:58:27 EDT 2018 until: Fri Aug 05 14:58:27 EDT 2118
+ Certificate fingerprints:
+ MD5: 74:14:93:3C:6E:7B:14:59:30:A3:90:C4:A2:AD:52:5E
+ SHA1: 12:BE:77:93:ED:C3:20:23:75:D7:D5:D9:FE:D9:5E:D1:D3:3E:E2:DC
+ SHA256: 6B:90:65:8D:AA:F6:F3:89:38:AE:92:8E:F0:83:26:17:DD:8A:2C:F6:7E:C5:39:F0:7E:DC:60:A3:6D:73:E1:7A
+ Signature algorithm name: SHA256withRSA
+ Subject Public Key Algorithm: 2048-bit RSA key
+ Version: 3
+
+ Extensions:
+
+ #1: ObjectId: 2.5.29.17 Criticality=false
+ SubjectAlternativeName [
+ DNSName: localhost
+ ]
+
+ #2: ObjectId: 2.5.29.14 Criticality=false
+ SubjectKeyIdentifier [
+ KeyIdentifier [
+ 0000: 78 2D FA 48 D8 21 73 86 68 CE 77 B9 98 5A BA 0F x-.H.!s.h.w..Z..
+ 0010: E2 FE CD 8C ....
+ ]
+ ]
+
+ Trust this certificate? [no]: yes
+ Certificate was added to keystore
+
+ $ keytool -list -v -keystore src/test/resources/test.truststore.ks
+ Enter keystore password: secret
+
+ Keystore type: JKS
+ Keystore provider: SUN
+
+ Your keystore contains 1 entry
+
+ Alias name: sitestcertkey
+ Creation date: Aug 29, 2018
+ Entry type: trustedCertEntry
+
+ Owner: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Issuer: CN=Spring Integration, OU=Spring, O=Pivotal Software Inc., L=San Francisco, ST=CA, C=US
+ Serial number: 3f2ab6ef
+ Valid from: Wed Aug 29 14:58:27 EDT 2018 until: Fri Aug 05 14:58:27 EDT 2118
+ Certificate fingerprints:
+ MD5: 74:14:93:3C:6E:7B:14:59:30:A3:90:C4:A2:AD:52:5E
+ SHA1: 12:BE:77:93:ED:C3:20:23:75:D7:D5:D9:FE:D9:5E:D1:D3:3E:E2:DC
+ SHA256: 6B:90:65:8D:AA:F6:F3:89:38:AE:92:8E:F0:83:26:17:DD:8A:2C:F6:7E:C5:39:F0:7E:DC:60:A3:6D:73:E1:7A
+ Signature algorithm name: SHA256withRSA
+ Subject Public Key Algorithm: 2048-bit RSA key
+ Version: 3
+
+ Extensions:
+
+ #1: ObjectId: 2.5.29.17 Criticality=false
+ SubjectAlternativeName [
+ DNSName: localhost
+ ]
+
+ #2: ObjectId: 2.5.29.14 Criticality=false
+ SubjectKeyIdentifier [
+ KeyIdentifier [
+ 0000: 78 2D FA 48 D8 21 73 86 68 CE 77 B9 98 5A BA 0F x-.H.!s.h.w..Z..
+ 0010: E2 FE CD 8C ....
+ ]
+ ]
+
+
+
+ *******************************************
+ *******************************************
+ */
@Test
public void testNetClientAndServerSSL() throws Exception {
System.setProperty("javax.net.debug", "all"); // SSL activity in the console
@@ -299,6 +353,7 @@ Certificate fingerprints:
TcpNetClientConnectionFactory client = new TcpNetClientConnectionFactory("localhost", server.getPort());
client.setTcpSocketFactorySupport(tcpSocketFactorySupport);
+ client.setTcpSocketSupport(new DefaultTcpSocketSupport(true));
client.start();
TcpConnection connection = client.getConnection();
@@ -338,7 +393,7 @@ Certificate fingerprints:
latch.countDown();
return false;
});
- server.setTcpSocketSupport(new DefaultTcpSocketSupport() {
+ server.setTcpSocketSupport(new DefaultTcpSocketSupport(false) {
@Override
public void postProcessServerSocket(ServerSocket serverSocket) {
@@ -356,6 +411,7 @@ Certificate fingerprints:
DefaultTcpNetSSLSocketFactorySupport clientTcpSocketFactorySupport =
new DefaultTcpNetSSLSocketFactorySupport(clientSslContextSupport);
client.setTcpSocketFactorySupport(clientTcpSocketFactorySupport);
+ client.setTcpSocketSupport(new DefaultTcpSocketSupport(false));
try {
client.start();
@@ -379,7 +435,7 @@ Certificate fingerprints:
"test.truststore.ks", "secret", "secret");
sslContextSupport.setProtocol("SSL");
DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport =
- new DefaultTcpNioSSLConnectionSupport(sslContextSupport);
+ new DefaultTcpNioSSLConnectionSupport(sslContextSupport, false);
server.setTcpNioConnectionSupport(tcpNioConnectionSupport);
final List> messages = new ArrayList>();
final CountDownLatch latch = new CountDownLatch(1);
@@ -402,7 +458,8 @@ Certificate fingerprints:
client.setSslHandshakeTimeout(34);
client.setTcpNioConnectionSupport(tcpNioConnectionSupport);
client.registerListener(message -> false);
- client.setApplicationEventPublisher(e -> { });
+ client.setApplicationEventPublisher(e -> {
+ });
client.start();
TcpConnection connection = client.getConnection();
@@ -445,7 +502,7 @@ Certificate fingerprints:
TcpSSLContextSupport serverSslContextSupport = new DefaultTcpSSLContextSupport("server.ks",
"server.truststore.ks", "secret", "secret");
DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport =
- new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport) {
+ new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport, false) {
@Override
protected void postProcessSSLEngine(SSLEngine sslEngine) {
@@ -469,7 +526,7 @@ Certificate fingerprints:
badClient ? "server.ks" : "client.ks",
"client.truststore.ks", "secret", "secret");
DefaultTcpNioSSLConnectionSupport clientTcpNioConnectionSupport =
- new DefaultTcpNioSSLConnectionSupport(clientSslContextSupport);
+ new DefaultTcpNioSSLConnectionSupport(clientSslContextSupport, false);
client.setTcpNioConnectionSupport(clientTcpNioConnectionSupport);
try {
@@ -492,7 +549,7 @@ Certificate fingerprints:
TcpSSLContextSupport serverSslContextSupport = new DefaultTcpSSLContextSupport("server.ks",
"server.truststore.ks", "secret", "secret");
DefaultTcpNioSSLConnectionSupport serverTcpNioConnectionSupport =
- new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport);
+ new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport, false);
server.setTcpNioConnectionSupport(serverTcpNioConnectionSupport);
final List> messages = new ArrayList>();
final CountDownLatch latch = new CountDownLatch(2);
@@ -525,7 +582,7 @@ Certificate fingerprints:
TcpSSLContextSupport clientSslContextSupport = new DefaultTcpSSLContextSupport("client.ks",
"client.truststore.ks", "secret", "secret");
DefaultTcpNioSSLConnectionSupport clientTcpNioConnectionSupport =
- new DefaultTcpNioSSLConnectionSupport(clientSslContextSupport);
+ new DefaultTcpNioSSLConnectionSupport(clientSslContextSupport, false);
client.setTcpNioConnectionSupport(clientTcpNioConnectionSupport);
client.registerListener(message -> {
messages.add(message);
@@ -533,7 +590,8 @@ Certificate fingerprints:
return false;
});
client.setDeserializer(deserializer);
- client.setApplicationEventPublisher(e -> { });
+ client.setApplicationEventPublisher(e -> {
+ });
client.start();
TcpConnection connection = client.getConnection();
diff --git a/spring-integration-ip/src/test/resources/test.cer b/spring-integration-ip/src/test/resources/test.cer
index e46e6ae864..faebc34c6b 100644
--- a/spring-integration-ip/src/test/resources/test.cer
+++ b/spring-integration-ip/src/test/resources/test.cer
@@ -1,13 +1,22 @@
-----BEGIN CERTIFICATE-----
-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
+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
-----END CERTIFICATE-----
diff --git a/spring-integration-ip/src/test/resources/test.ks b/spring-integration-ip/src/test/resources/test.ks
index 243b3d0244..235a45c499 100644
Binary files a/spring-integration-ip/src/test/resources/test.ks and b/spring-integration-ip/src/test/resources/test.ks differ
diff --git a/spring-integration-ip/src/test/resources/test.truststore.ks b/spring-integration-ip/src/test/resources/test.truststore.ks
index 24ead4bc6d..f60c4cd5c4 100644
Binary files a/spring-integration-ip/src/test/resources/test.truststore.ks and b/spring-integration-ip/src/test/resources/test.truststore.ks differ
diff --git a/src/reference/asciidoc/ip.adoc b/src/reference/asciidoc/ip.adoc
index 9d1b045577..8abe0652b0 100644
--- a/src/reference/asciidoc/ip.adoc
+++ b/src/reference/asciidoc/ip.adoc
@@ -719,7 +719,7 @@ Then you can examine the current state with `@adapter_id.isClientModeConnected()
The inbound TCP gateway `TcpInboundGateway` and outbound TCP gateway `TcpOutboundGateway` use a server and client connection factory, respectively.
Each connection can process a single request or response at a time.
-The inbound gateway, after constructing a message with the incoming payload and sending it to the requestChannel, waits for a response and sends the payload from the response message by writing it to the connection.
+The inbound gateway, after constructing a message with the incoming payload and sending it to the `requestChannel`, waits for a response and sends the payload from the response message by writing it to the connection.
NOTE: For the inbound gateway, you must retain or populate, the `ip_connectionId` header, because it is used to correlate the message to a connection.
Messages that originate at the gateway automatically have the header set.
@@ -1113,6 +1113,45 @@ Starting with version 4.3.6, when you use NIO, you can specify an `ssl-handshake
This timeout (the default is 30 seconds) is used during SSL handshake when waiting for data.
If the timeout is exceeded, the process is aborted and the socket is closed.
+[[tcp-ssl-host-verification]]
+==== Host Verification
+
+Starting with version 5.0.8, you can configure whether or not to enable host verification.
+Starting with version 5.1, it is enabled by default; the mechanism to disable it depends on whether or not you are using NIO.
+
+Host verification is used to ensure the server you are connected to matches information in the certificate, even if the certificate is trusted.
+
+When using NIO, configure the `DefaultTcpNioSSLConnectionSupport`, for example.
+
+====
+[source, java]
+----
+@Bean
+public DefaultTcpNioSSLConnectionSupport connectionSupport() {
+ DefaultTcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport("test.ks",
+ "test.truststore.ks", "secret", "secret");
+ sslContextSupport.setProtocol("SSL");
+ DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport =
+ new DefaultTcpNioSSLConnectionSupport(sslContextSupport, false);
+ return tcpNioConnectionSupport;
+}
+----
+====
+
+The second constructor argument disables host verification.
+The `connectionSupport` bean is then injected into the NIO connection factory.
+
+When not using NIO, the configuration is in the `TcpSocketSupport`:
+
+====
+[source, java]
+----
+connectionFactory.setTcpSocketSupport(new DefaultTcpSocketSupport(false));
+----
+====
+
+Again, the constructor argument disables host verification.
+
[[tcp-advanced-techniques]]
=== Advanced Techniques
diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc
index a3ee07bddd..2313072114 100644
--- a/src/reference/asciidoc/whats-new.adoc
+++ b/src/reference/asciidoc/whats-new.adoc
@@ -139,6 +139,14 @@ See <> and <> for more information.
In addition, the synchronizers for inbound channel adapters can now be provided with a `Comparator`.
This is useful when using `maxFetchSize` to limit the files retrieved.
+[[x51.-tcp]]
+=== TCP Support
+
+When using SSL, host verification is now enabled, by default, to prevent man-in-the-middle attacks with a trusted certificate.
+See <> for more information.
+
+In addition the key and trust store types can now be configured on the `DefaultTcpSSLContextSupport`.
+
[[x5.1-twitter]]
=== Twitter Support