From 230d12d425c00ef1e534b6bd750ab1d38e991db1 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Wed, 29 Aug 2018 14:04:45 -0400 Subject: [PATCH] TCP, SSL, Enable Host Verification by default Make key/trust store types configurable; add a test with host violation. * Fix some typos and code style in the related classed and docs * Add asserts for the store type properties --- .../DefaultTcpNioSSLConnectionSupport.java | 35 ++- .../DefaultTcpSSLContextSupport.java | 41 ++- .../connection/DefaultTcpSocketSupport.java | 40 ++- .../ip/config/ParserUnitTests-context.xml | 4 +- .../ip/tcp/connection/PushbackTcpTests.java | 4 +- .../ip/tcp/connection/SocketSupportTests.java | 240 +++++++++++------- .../src/test/resources/test.cer | 31 ++- .../src/test/resources/test.ks | Bin 1386 -> 2316 bytes .../src/test/resources/test.truststore.ks | Bin 681 -> 1027 bytes src/reference/asciidoc/ip.adoc | 41 ++- src/reference/asciidoc/whats-new.adoc | 8 + 11 files changed, 329 insertions(+), 115 deletions(-) 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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 -----END CERTIFICATE----- diff --git a/spring-integration-ip/src/test/resources/test.ks b/spring-integration-ip/src/test/resources/test.ks index 243b3d0244aa7df52bda5e82e727f6b15eef7d20..235a45c49988798a61d9ddaf69f40d2cd2cf0fac 100644 GIT binary patch literal 2316 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 diff --git a/spring-integration-ip/src/test/resources/test.truststore.ks b/spring-integration-ip/src/test/resources/test.truststore.ks index 24ead4bc6dd844adfa16f76f4d17d08bacce6300..f60c4cd5c452ef2167b5e047206cb6be6eb552fd 100644 GIT binary patch literal 1027 zcmezO_TO6u1_mY|W(3o`#hE3k#U;t9MJ3s(l|a$dcI8hV46G4)rUsS_49t5CnwWPQ zG%+n)z|6$R#KdB+we7tDFB_*;n@8JsUPeZ4RtAH{219NGPB!LH7B*p~&|nycLzv0g z(NN4l1SG>Q%p07Tr{GqUn3tScoSbhcXCMO-=MokT$Slh*Nz73Q&QB{TPb^AR@XSlr zGvo)_0+i<#W(zJT%FIhQls1qA2`~!_K?H!xN>bB{5=%1k^9&Tkc?~TLEQ~A-Ele$p z%%ddujSN8o2BuJf!QjXyMkVB+V`ODuZerwTFlb`rVrpV!WSD%KBsA$<3TO>L=@MHgE72)}fXFC>GEPv*8F7T*dUH#Ks6{%?x5 z@loc=z8P#NsF$a<#NuDO-I}$g#zqmx?mqnM8T;|&Z<~Lo*Eqav>R+EIx2!&L;^JwJ zvkv*p{QB+OmAI`>TRdKzKGSh8>X)}Whe_u17R4lkyXPbSuY6$;I#o?pbd#X{WQU_0 z*CbunIMp#xZ1TMm$|03<*K7Z6c;V?3G&zVd;f{Zuf?9I%6jk?sZ|4-|Oe+v)VrFDu zTx@P&3QjVzf-JlS+)bQ0`N@en8TrK}2C~5Tm*ry-V-cy){pE2(vA8YcT=~u!QM>pb z{X5%(9JIhx2@G0B2BB7sP^ll&_Gj?!*|xf#^Qbb*N^{A>TNbXYSG?rbd0+uk-3w8b zwpfn!D?UDw2nt`N_=(%{D@%RYWvlWPLK}FED?Y4HYdLP%`S)324)g1UlL{=VgI06x z$@zMsF*NSfb|K-JhWyi+K2)(AzHd3==k3ql8Sa;HJv&$Vdb#_X$yWu;wc3^%MD$G- zo|50GGkxLJxiO7lMO&6CN8Q&J)vAv@v+8S=3-#it6txsd&m?<YW;3>rI`8XFnTEtFfiqeo-ofg4=sXEGi;I(tX}k$|$IgClyR4a* z85tOnod=9OW}v%rHTl*~n)&ru*F&R3l@I@46zsA66j&&3(IW2iyjA>xOxV|u#C2xg z-Z%52c3xfi>s9AG+n@)UKI?aC$F?z^T#}M>@{G+b;{`vTUfrdlcVp^A0cXLp7qXAp zt>8QMcE`t0T5DHpJy?20V)sM++M=nVHx-W`SsWL>G>4;YQ(shX4{MM7#`y`mPNw~y Q6lG#+x^TZZpI`4m0LCWfF#rGn 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