ARTEMIS-656 support host verification for SSL cert
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/cfbe06f3 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/cfbe06f3 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/cfbe06f3 Branch: refs/heads/master Commit: cfbe06f3bc4173fc19324de1d5b811067e2d1aa8 Parents: 113c2a3 Author: jbertram <[email protected]> Authored: Thu Aug 11 14:32:56 2016 -0500 Committer: Clebert Suconic <[email protected]> Committed: Mon Aug 15 13:58:25 2016 -0400 ---------------------------------------------------------------------- .../remoting/impl/netty/NettyConnector.java | 20 ++++- .../remoting/impl/netty/TransportConstants.java | 6 ++ .../core/remoting/impl/netty/NettyAcceptor.java | 23 +++++- docs/user-manual/en/configuring-transports.md | 12 +++ .../ssl/CoreClientOverOneWaySSLTest.java | 76 ++++++++++++++++- .../ssl/CoreClientOverTwoWaySSLTest.java | 81 ++++++++++++++++++- .../verified-client-side-keystore.jceks | Bin 0 -> 2203 bytes .../resources/verified-client-side-keystore.jks | Bin 0 -> 2226 bytes .../verified-client-side-truststore.jceks | Bin 0 -> 868 bytes .../verified-client-side-truststore.jks | Bin 0 -> 935 bytes .../verified-server-side-keystore.jceks | Bin 0 -> 1248 bytes .../resources/verified-server-side-keystore.jks | Bin 0 -> 2225 bytes .../verified-server-side-truststore.jceks | Bin 0 -> 935 bytes .../verified-server-side-truststore.jks | Bin 0 -> 935 bytes 14 files changed, 212 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java ---------------------------------------------------------------------- diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java index 62c405b..49c936b 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java @@ -18,6 +18,7 @@ package org.apache.activemq.artemis.core.remoting.impl.netty; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; import java.io.IOException; import java.net.ConnectException; import java.net.Inet6Address; @@ -197,6 +198,8 @@ public class NettyConnector extends AbstractConnector { private String enabledProtocols; + private boolean verifyHost; + private boolean tcpNoDelay; private int tcpSendBufferSize; @@ -306,6 +309,8 @@ public class NettyConnector extends AbstractConnector { enabledCipherSuites = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES, configuration); enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration); + + verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration); } else { keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER; @@ -316,6 +321,7 @@ public class NettyConnector extends AbstractConnector { trustStorePassword = TransportConstants.DEFAULT_TRUSTSTORE_PASSWORD; enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES; enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS; + verifyHost = TransportConstants.DEFAULT_VERIFY_HOST; } tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration); @@ -462,7 +468,13 @@ public class NettyConnector extends AbstractConnector { public void initChannel(Channel channel) throws Exception { final ChannelPipeline pipeline = channel.pipeline(); if (sslEnabled && !useServlet) { - SSLEngine engine = context.createSSLEngine(); + SSLEngine engine; + if (verifyHost) { + engine = context.createSSLEngine(host, port); + } + else { + engine = context.createSSLEngine(); + } engine.setUseClientMode(true); @@ -496,6 +508,12 @@ public class NettyConnector extends AbstractConnector { engine.setEnabledProtocols(originalProtocols); } + if (verifyHost) { + SSLParameters sslParameters = engine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + engine.setSSLParameters(sslParameters); + } + SslHandler handler = new SslHandler(engine); pipeline.addLast(handler); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java ---------------------------------------------------------------------- diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java index 53dc204..40aed3d 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java @@ -87,6 +87,8 @@ public class TransportConstants { public static final String NEED_CLIENT_AUTH_PROP_NAME = "needClientAuth"; + public static final String VERIFY_HOST_PROP_NAME = "verifyHost"; + public static final String BACKLOG_PROP_NAME = "backlog"; public static final String NETTY_VERSION; @@ -155,6 +157,8 @@ public class TransportConstants { public static final boolean DEFAULT_NEED_CLIENT_AUTH = false; + public static final boolean DEFAULT_VERIFY_HOST = false; + public static final boolean DEFAULT_TCP_NODELAY = true; public static final int DEFAULT_TCP_SENDBUFFER_SIZE = 32768; @@ -226,6 +230,7 @@ public class TransportConstants { allowableAcceptorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME); allowableAcceptorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME); allowableAcceptorKeys.add(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME); + allowableAcceptorKeys.add(TransportConstants.VERIFY_HOST_PROP_NAME); allowableAcceptorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME); allowableAcceptorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME); allowableAcceptorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME); @@ -270,6 +275,7 @@ public class TransportConstants { allowableConnectorKeys.add(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME); allowableConnectorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME); allowableConnectorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME); + allowableConnectorKeys.add(TransportConstants.VERIFY_HOST_PROP_NAME); allowableConnectorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME); allowableConnectorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME); allowableConnectorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java index f5742c5..ce506cb 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java @@ -19,12 +19,15 @@ package org.apache.activemq.artemis.core.remoting.impl.netty; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLParameters; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -138,6 +141,8 @@ public class NettyAcceptor extends AbstractAcceptor { private final boolean needClientAuth; + private final boolean verifyHost; + private final boolean tcpNoDelay; private final int backlog; @@ -224,6 +229,8 @@ public class NettyAcceptor extends AbstractAcceptor { enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration); needClientAuth = ConfigurationHelper.getBooleanProperty(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, TransportConstants.DEFAULT_NEED_CLIENT_AUTH, configuration); + + verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration); } else { keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER; @@ -235,6 +242,7 @@ public class NettyAcceptor extends AbstractAcceptor { enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES; enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS; needClientAuth = TransportConstants.DEFAULT_NEED_CLIENT_AUTH; + verifyHost = TransportConstants.DEFAULT_VERIFY_HOST; } tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration); @@ -391,7 +399,13 @@ public class NettyAcceptor extends AbstractAcceptor { ise.initCause(e); throw ise; } - SSLEngine engine = context.createSSLEngine(); + SSLEngine engine; + if (verifyHost) { + engine = context.createSSLEngine(host, port); + } + else { + engine = context.createSSLEngine(); + } engine.setUseClientMode(false); @@ -439,6 +453,13 @@ public class NettyAcceptor extends AbstractAcceptor { } engine.setEnabledProtocols(set.toArray(new String[set.size()])); + + if (verifyHost) { + SSLParameters sslParameters = engine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + engine.setSSLParameters(sslParameters); + } + return new SslHandler(engine); } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/docs/user-manual/en/configuring-transports.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/configuring-transports.md b/docs/user-manual/en/configuring-transports.md index 872fe2f..a44da35 100644 --- a/docs/user-manual/en/configuring-transports.md +++ b/docs/user-manual/en/configuring-transports.md @@ -395,6 +395,18 @@ following additional properties: connecting to this acceptor that 2-way SSL is required. Valid values are `true` or `false`. Default is `false`. +- `verifyHost` + + When used on an `acceptor` the `CN` of the connecting client's SSL certificate + will be compared to its hostname to verify they match. This is useful + only for 2-way SSL. + + When used on a `connector` the `CN` of the server's SSL certificate will be + compared to its hostname to verify they match. This is useful for both 1-way + and 2-way SSL. + + Valid values are `true` or `false`. Default is `false`. + ## Configuring Netty HTTP Netty HTTP tunnels packets over the HTTP protocol. It can be useful in http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLTest.java index 50ac998..de46bcd 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLTest.java @@ -55,7 +55,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase { @Parameterized.Parameters(name = "storeType={0}") public static Collection getParameters() { - return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}}); + return Arrays.asList(new Object[][]{ + {"JCEKS"}, + {"JKS"} + }); } public CoreClientOverOneWaySSLTest(String storeType) { @@ -78,6 +81,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase { * keytool -export -keystore other-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample * keytool -import -keystore other-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt * + * keytool -genkey -keystore verified-server-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA + * keytool -export -keystore verified-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore verified-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * * Commands to create the JCEKS artifacts: * keytool -genkey -keystore server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" * keytool -export -keystore server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample @@ -86,6 +93,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase { * keytool -genkey -keystore other-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=Other ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" * keytool -export -keystore other-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample * keytool -import -keystore other-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" + * keytool -export -keystore verified-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore verified-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt */ private String storeType; private String SERVER_SIDE_KEYSTORE; @@ -124,6 +135,56 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase { } @Test + public void testOneWaySSLVerifyHost() throws Exception { + createCustomSslServer(null, null, true); + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator)); + ClientSession session = addClientSession(sf.createSession(false, true, true)); + session.createQueue(CoreClientOverOneWaySSLTest.QUEUE, CoreClientOverOneWaySSLTest.QUEUE, false); + ClientProducer producer = addClientProducer(session.createProducer(CoreClientOverOneWaySSLTest.QUEUE)); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = addClientConsumer(session.createConsumer(CoreClientOverOneWaySSLTest.QUEUE)); + session.start(); + + Message m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testOneWaySSLVerifyHostNegative() throws Exception { + createCustomSslServer(null, null, false); + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + + try { + ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator)); + fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name."); + } + catch (Exception e) { + // ignore + } + } + + @Test public void testOneWaySSLReloaded() throws Exception { createCustomSslServer(); server.createQueue(CoreClientOverOneWaySSLTest.QUEUE, CoreClientOverOneWaySSLTest.QUEUE, null, false, false); @@ -589,11 +650,22 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase { } private void createCustomSslServer(String cipherSuites, String protocols) throws Exception { + createCustomSslServer(cipherSuites, protocols, false); + } + + private void createCustomSslServer(String cipherSuites, String protocols, boolean useVerifiedKeystore) throws Exception { Map<String, Object> params = new HashMap<>(); params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true); params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); - params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE); + + if (useVerifiedKeystore) { + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_KEYSTORE); + } + else { + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE); + } params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.HOST_PROP_NAME, "localhost"); if (cipherSuites != null) { params.put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, cipherSuites); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWaySSLTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWaySSLTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWaySSLTest.java index 0d553ad..403ebc3 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWaySSLTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverTwoWaySSLTest.java @@ -36,6 +36,7 @@ import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; import org.apache.activemq.artemis.api.core.client.ActiveMQClient; import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.utils.RandomUtil; import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; @@ -56,7 +57,9 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase { @Parameterized.Parameters(name = "storeType={0}") public static Collection getParameters() { - return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}}); + return Arrays.asList(new Object[][]{ + {"JCEKS"}, + {"JKS"}}); } public CoreClientOverTwoWaySSLTest(String storeType) { @@ -77,10 +80,18 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase { * keytool -export -keystore client-side-keystore.jks -file activemq-jks.cer -storepass secureexample * keytool -import -keystore server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt * + * keytool -genkey -keystore verified-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA + * keytool -export -keystore verified-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample + * keytool -import -keystore verified-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt + * * Commands to create the JCEKS artifacts: * keytool -genkey -keystore client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA * keytool -export -keystore client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample * keytool -import -keystore server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt + * + * keytool -genkey -keystore verified-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA + * keytool -export -keystore verified-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample + * keytool -import -keystore verified-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt */ private String storeType; @@ -149,6 +160,72 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase { } @Test + public void testTwoWaySSLVerifyClientHost() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + acceptor.getConfiguration().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_TRUSTSTORE); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + String text = RandomUtil.randomString(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = createSessionFactory(locator); + ClientSession session = sf.createSession(false, true, true); + session.createQueue(CoreClientOverTwoWaySSLTest.QUEUE, CoreClientOverTwoWaySSLTest.QUEUE, false); + ClientProducer producer = session.createProducer(CoreClientOverTwoWaySSLTest.QUEUE); + + ClientMessage message = createTextMessage(session, text); + producer.send(message); + + ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWaySSLTest.QUEUE); + session.start(); + + Message m = consumer.receive(1000); + Assert.assertNotNull(m); + Assert.assertEquals(text, m.getBodyBuffer().readString()); + } + + @Test + public void testTwoWaySSLVerifyClientHostNegative() throws Exception { + NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL"); + acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true); + server.getRemotingService().stop(false); + server.getRemotingService().start(); + server.getRemotingService().startAcceptors(); + + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + + server.getRemotingService().addIncomingInterceptor(new MyInterceptor()); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + try { + ClientSessionFactory sf = createSessionFactory(locator); + fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name."); + } + catch (Exception e) { + // ignore + } + } + + @Test public void testTwoWaySSLWithoutClientKeyStore() throws Exception { tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); @@ -183,7 +260,7 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase { params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType); params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType); params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); - ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params)); + ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params, "nettySSL")); server = createServer(false, config); server.start(); waitForServerToStart(server); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-client-side-keystore.jceks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-client-side-keystore.jceks b/tests/unit-tests/src/test/resources/verified-client-side-keystore.jceks new file mode 100644 index 0000000..250832b Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-client-side-keystore.jceks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-client-side-keystore.jks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-client-side-keystore.jks b/tests/unit-tests/src/test/resources/verified-client-side-keystore.jks new file mode 100644 index 0000000..88e7e40 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-client-side-keystore.jks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-client-side-truststore.jceks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-client-side-truststore.jceks b/tests/unit-tests/src/test/resources/verified-client-side-truststore.jceks new file mode 100644 index 0000000..ad63172 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-client-side-truststore.jceks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-client-side-truststore.jks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-client-side-truststore.jks b/tests/unit-tests/src/test/resources/verified-client-side-truststore.jks new file mode 100644 index 0000000..1d992c7 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-client-side-truststore.jks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-server-side-keystore.jceks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-server-side-keystore.jceks b/tests/unit-tests/src/test/resources/verified-server-side-keystore.jceks new file mode 100644 index 0000000..7a46162 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-server-side-keystore.jceks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-server-side-keystore.jks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-server-side-keystore.jks b/tests/unit-tests/src/test/resources/verified-server-side-keystore.jks new file mode 100644 index 0000000..55c7603 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-server-side-keystore.jks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-server-side-truststore.jceks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-server-side-truststore.jceks b/tests/unit-tests/src/test/resources/verified-server-side-truststore.jceks new file mode 100644 index 0000000..e2bd4b3 Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-server-side-truststore.jceks differ http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cfbe06f3/tests/unit-tests/src/test/resources/verified-server-side-truststore.jks ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/resources/verified-server-side-truststore.jks b/tests/unit-tests/src/test/resources/verified-server-side-truststore.jks new file mode 100644 index 0000000..8d2288a Binary files /dev/null and b/tests/unit-tests/src/test/resources/verified-server-side-truststore.jks differ
