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..3ffefc0f0f 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 disabled.
+ * @param sslContextSupport the ssl context support.
+ */
public DefaultTcpNioSSLConnectionSupport(TcpSSLContextSupport sslContextSupport) {
+ this(sslContextSupport, false);
+ }
+
+ /**
+ * 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..06760eca66 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 disabled.
+ */
+ public DefaultTcpSocketSupport() {
+ this(false);
+ }
+
+ /**
+ * 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();
@@ -402,7 +457,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();
@@ -533,7 +589,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 ac714e46f6..400199ffcc 100644
--- a/src/reference/asciidoc/ip.adoc
+++ b/src/reference/asciidoc/ip.adoc
@@ -655,7 +655,7 @@ For both inbound and outbound, if the adapter is started, you may force the adap
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/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, care must be taken to retain, or populate, the _ip_connectionId_ header because it is used to correlate the message to a connection.
Messages that originate at the gateway will automatically have the header set.
@@ -1014,6 +1014,45 @@ The keystore file names (first two constructor arguments) use the Spring `Resour
Starting with _version 4.3.6_, when using NIO, you can specify an `ssl-handshake-timeout` (seconds) on the connection factory.
This timeout (default 30) is used during SSL handshake when waiting for data; if the timeout is exceeded, the process is aborted and the socket 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 will be enabled by default; before that version, the mechanism to enable 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, true);
+ return tcpNioConnectionSupport;
+}
+----
+====
+
+The second constructor argument enables 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(true));
+----
+====
+
+Again, the constructor argument enables host verification.
+
[[tcp-advanced-techniques]]
=== Advanced Techniques
diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc
index fe0a8b848c..e879a115f0 100644
--- a/src/reference/asciidoc/whats-new.adoc
+++ b/src/reference/asciidoc/whats-new.adoc
@@ -314,6 +314,14 @@ See <> for more information.
IMPORTANT: Changes were made to the Micrometer `Meters` in _version 5.0.3_ to make them more suitable for use in dimensional systems.
Further changes were made in 5.0.4; if using Micrometer, a minimum of version 5.0.4 is recommended.
+[[x51.-tcp]]
+=== TCP Support
+
+When using SSL, host verification can be configured, 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`.
+
==== @EndpointId Annotations
@@ -325,4 +333,3 @@ See <> for more information.
Starting with _version 5.0.5_, generated bean names for the components in an `IntegrationFlow` include the flow bean name, followed by a dot, as a prefix.
See <> for more information.
-