You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by an...@apache.org on 2018/09/18 07:03:08 UTC
activemq-artemis git commit: ARTEMIS-1919 implement SNI properly
Repository: activemq-artemis
Updated Branches:
refs/heads/2.6.x 2d2c1c830 -> 737fbbab3
ARTEMIS-1919 implement SNI properly
(cherry picked from commit c60d17884a42b4bf4cb5e249f8020b19e0725eb6)
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/737fbbab
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/737fbbab
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/737fbbab
Branch: refs/heads/2.6.x
Commit: 737fbbab39dc613746136c8fa8d1d957714d2b28
Parents: 2d2c1c8
Author: Justin Bertram <jb...@apache.org>
Authored: Tue Sep 11 11:06:01 2018 -0500
Committer: andytaylor <an...@gmail.com>
Committed: Tue Sep 18 08:02:25 2018 +0100
----------------------------------------------------------------------
.../remoting/impl/netty/NettyConnector.java | 20 ++-
.../core/remoting/impl/netty/NettyAcceptor.java | 13 ++
docs/user-manual/en/configuring-transports.md | 12 ++
.../ssl/CoreClientOverOneWaySSLTest.java | 123 ++++++++++++++++++-
4 files changed, 158 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/737fbbab/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 6400b44..8dd35e4 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
@@ -16,6 +16,12 @@
*/
package org.apache.activemq.artemis.core.remoting.impl.netty;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
@@ -28,6 +34,7 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -42,12 +49,6 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
@@ -377,6 +378,7 @@ public class NettyConnector extends AbstractConnector {
enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS;
verifyHost = TransportConstants.DEFAULT_VERIFY_HOST;
trustAll = TransportConstants.DEFAULT_TRUST_ALL;
+ sniHost = TransportConstants.DEFAULT_SNIHOST_CONFIG;
useDefaultSslContext = TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT;
}
@@ -564,6 +566,12 @@ public class NettyConnector extends AbstractConnector {
engine.setSSLParameters(sslParameters);
}
+ if (sniHost != null) {
+ SSLParameters sslParameters = engine.getSSLParameters();
+ sslParameters.setServerNames(Arrays.asList(new SNIHostName(sniHost)));
+ engine.setSSLParameters(sslParameters);
+ }
+
SslHandler handler = new SslHandler(engine);
pipeline.addLast("ssl", handler);
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/737fbbab/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 ed1a941..992f7d8 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
@@ -16,6 +16,7 @@
*/
package org.apache.activemq.artemis.core.remoting.impl.netty;
+import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLHandshakeException;
@@ -28,6 +29,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -175,6 +177,8 @@ public class NettyAcceptor extends AbstractAcceptor {
private final String kerb5Config;
+ private String sniHost;
+
private final boolean tcpNoDelay;
private final int backlog;
@@ -286,6 +290,8 @@ public class NettyAcceptor extends AbstractAcceptor {
verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration);
sslProvider = ConfigurationHelper.getStringProperty(TransportConstants.SSL_PROVIDER, TransportConstants.DEFAULT_SSL_PROVIDER, configuration);
+
+ sniHost = ConfigurationHelper.getStringProperty(TransportConstants.SNIHOST_PROP_NAME, TransportConstants.DEFAULT_SNIHOST_CONFIG, configuration);
} else {
keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
keyStorePath = TransportConstants.DEFAULT_KEYSTORE_PATH;
@@ -300,6 +306,7 @@ public class NettyAcceptor extends AbstractAcceptor {
wantClientAuth = TransportConstants.DEFAULT_WANT_CLIENT_AUTH;
verifyHost = TransportConstants.DEFAULT_VERIFY_HOST;
sslProvider = TransportConstants.DEFAULT_SSL_PROVIDER;
+ sniHost = TransportConstants.DEFAULT_SNIHOST_CONFIG;
}
tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration);
@@ -534,6 +541,12 @@ public class NettyAcceptor extends AbstractAcceptor {
engine.setSSLParameters(sslParameters);
}
+ if (sniHost != null) {
+ SSLParameters sslParameters = engine.getSSLParameters();
+ sslParameters.setSNIMatchers(Arrays.asList(SNIHostName.createSNIMatcher(sniHost)));
+ engine.setSSLParameters(sslParameters);
+ }
+
return new SslHandler(engine);
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/737fbbab/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 d2a0282..09fdb41 100644
--- a/docs/user-manual/en/configuring-transports.md
+++ b/docs/user-manual/en/configuring-transports.md
@@ -451,6 +451,18 @@ additional properties:
https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations for more
information's.
+- `sniHost`
+
+ When used on an `acceptor` the `sniHost` is a *regular expression* used to
+ match the [`server_name`](https://tools.ietf.org/html/rfc6066) extension on
+ incoming SSL connections. If the name doesn't match then the connection to
+ the acceptor will be rejected. A WARN message will be logged if this happens.
+ If the incoming connection doesn't include the `server_name` extension then
+ the connection will be accepted.
+
+ When used on a `connector` the `sniHost` value is used for the `server_name`
+ extension on the SSL connection.
+
### 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/737fbbab/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 b9b9bc8..5accbe8 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
@@ -154,6 +154,108 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
}
@Test
+ public void testOneWaySSLwithSNI() throws Exception {
+ createCustomSslServer("myhost\\.com");
+ 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.SNIHOST_PROP_NAME, "myhost.com");
+
+ 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();
+
+ ClientMessage m = consumer.receive(1000);
+ Assert.assertNotNull(m);
+ Assert.assertEquals(text, m.getBodyBuffer().readString());
+ }
+
+ @Test
+ public void testOneWaySSLwithSNINegative() throws Exception {
+ createCustomSslServer("myhost\\.com");
+
+ 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.SNIHOST_PROP_NAME, "badhost.com");
+
+ ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
+ try {
+ ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));
+ fail("Should have failed due to unrecognized SNI host name");
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ @Test
+ public void testOneWaySSLwithSNIOnlyOnTheClient() throws Exception {
+ createCustomSslServer();
+ 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.SNIHOST_PROP_NAME, "myhost.com");
+
+ 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();
+
+ ClientMessage m = consumer.receive(1000);
+ Assert.assertNotNull(m);
+ Assert.assertEquals(text, m.getBodyBuffer().readString());
+ }
+
+ @Test
+ public void testOneWaySSLwithSNIOnlyOnTheBroker() throws Exception {
+ createCustomSslServer("myhost\\.com");
+ 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);
+
+ 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();
+
+ ClientMessage m = consumer.receive(1000);
+ Assert.assertNotNull(m);
+ Assert.assertEquals(text, m.getBodyBuffer().readString());
+ }
+
+ @Test
public void testOneWaySSLwithURL() throws Exception {
createCustomSslServer();
String text = RandomUtil.randomString();
@@ -260,7 +362,7 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
@Test
public void testOneWaySSLVerifyHost() throws Exception {
- createCustomSslServer(null, null, true);
+ createCustomSslServer(true);
String text = RandomUtil.randomString();
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
@@ -288,7 +390,7 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
@Test
public void testOneWaySSLVerifyHostNegative() throws Exception {
- createCustomSslServer(null, null, false);
+ createCustomSslServer();
String text = RandomUtil.randomString();
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
@@ -752,16 +854,29 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
}
private void createCustomSslServer(String cipherSuites, String protocols) throws Exception {
- createCustomSslServer(cipherSuites, protocols, false);
+ createCustomSslServer(cipherSuites, protocols, false, null);
+ }
+
+ private void createCustomSslServer(String sniHost) throws Exception {
+ createCustomSslServer(null, null, false, sniHost);
+ }
+
+ private void createCustomSslServer(boolean useVerifiedKeystore) throws Exception {
+ createCustomSslServer(null, null, useVerifiedKeystore, null);
}
private void createCustomSslServer(String cipherSuites,
String protocols,
- boolean useVerifiedKeystore) throws Exception {
+ boolean useVerifiedKeystore,
+ String sniHost) throws Exception {
Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
+ if (sniHost != null) {
+ params.put(TransportConstants.SNIHOST_PROP_NAME, sniHost);
+ }
+
if (useVerifiedKeystore) {
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_KEYSTORE);
} else {