activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From andytay...@apache.org
Subject [2/2] activemq-artemis git commit: ARTEMIS-1919 implement SNI properly
Date Tue, 18 Sep 2018 07:00:25 GMT
ARTEMIS-1919 implement SNI properly


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/c60d1788
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/c60d1788
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/c60d1788

Branch: refs/heads/master
Commit: c60d17884a42b4bf4cb5e249f8020b19e0725eb6
Parents: 50b18df
Author: Justin Bertram <jbertram@apache.org>
Authored: Tue Sep 11 11:06:01 2018 -0500
Committer: andytaylor <andy.tayls67@gmail.com>
Committed: Tue Sep 18 08:00:05 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/c60d1788/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 2ef5fed..4a87770 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;
@@ -383,6 +384,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;
       }
 
@@ -571,6 +573,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/c60d1788/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 fb46ff4..47a66f5 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/c60d1788/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 ee3a047..00df421 100644
--- a/docs/user-manual/en/configuring-transports.md
+++ b/docs/user-manual/en/configuring-transports.md
@@ -460,6 +460,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/c60d1788/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 2bc3212..c6457c6 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();
@@ -264,7 +366,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);
@@ -292,7 +394,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);
@@ -763,16 +865,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 {


Mime
View raw message