You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2017/07/14 12:51:25 UTC

qpid-jms-amqp-0-x git commit: QPID-7292: [AMQP 0.x] Qpid clients should verify the server-final message when using SCRAM-* authentication

Repository: qpid-jms-amqp-0-x
Updated Branches:
  refs/heads/master aeb7377c8 -> 8e652dd7a


QPID-7292: [AMQP 0.x] Qpid clients should verify the server-final message when using SCRAM-* authentication


Project: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/commit/8e652dd7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/tree/8e652dd7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/diff/8e652dd7

Branch: refs/heads/master
Commit: 8e652dd7aa8aaa23e38f6364bff45feab4a5ee8f
Parents: aeb7377
Author: Alex Rudyy <or...@apache.org>
Authored: Fri Jul 14 13:50:15 2017 +0100
Committer: Alex Rudyy <or...@apache.org>
Committed: Fri Jul 14 13:50:15 2017 +0100

----------------------------------------------------------------------
 .../handler/ConnectionTuneMethodHandler.java    |  35 +++++-
 .../apache/qpid/transport/ClientDelegate.java   |  38 ++++++-
 .../ConnectionTuneMethodHandlerTest.java        | 106 +++++++++++++++++++
 3 files changed, 177 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/8e652dd7/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java b/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
index 1f2df20..6094495 100644
--- a/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
+++ b/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
@@ -20,9 +20,13 @@
  */
 package org.apache.qpid.client.handler;
 
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.qpid.QpidException;
 import org.apache.qpid.client.ConnectionTuneParameters;
 import org.apache.qpid.client.protocol.AMQProtocolSession;
 import org.apache.qpid.client.state.AMQState;
@@ -47,9 +51,12 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener<Con
     protected ConnectionTuneMethodHandler()
     { }
 
-    public void methodReceived(AMQProtocolSession session, ConnectionTuneBody frame, int channelId)
+    public void methodReceived(AMQProtocolSession session, ConnectionTuneBody frame, int channelId) throws QpidException
     {
         _logger.debug("ConnectionTune frame received");
+
+        verifySaslNegotiationComplete(session);
+
         final MethodRegistry methodRegistry = session.getMethodRegistry();
 
         ConnectionTuneParameters params = session.getConnectionTuneParameters();
@@ -86,5 +93,31 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener<Con
         session.writeFrame(openBody.generateFrame(channelId));
     }
 
+    private void verifySaslNegotiationComplete(final AMQProtocolSession session) throws QpidException
+    {
+        SaslClient client = session.getSaslClient();
+        if (client == null)
+        {
+            throw new QpidException("No SASL client set up - cannot proceed with connection open");
+        }
+
+        if (!client.isComplete())
+        {
+            throw new QpidException("SASL negotiation has not been completed - cannot proceed with connection open");
+        }
 
+        String mechanismName = client.getMechanismName();
+        try
+        {
+            client.dispose();
+        }
+        catch (SaslException e)
+        {
+            _logger.warn("Disposal of client sasl for mechanism '{}' has failed", mechanismName, e);
+        }
+        finally
+        {
+            session.setSaslClient(null);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/8e652dd7/client/src/main/java/org/apache/qpid/transport/ClientDelegate.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/transport/ClientDelegate.java b/client/src/main/java/org/apache/qpid/transport/ClientDelegate.java
index ea05408..b6852b1 100644
--- a/client/src/main/java/org/apache/qpid/transport/ClientDelegate.java
+++ b/client/src/main/java/org/apache/qpid/transport/ClientDelegate.java
@@ -30,11 +30,11 @@ import java.util.Map;
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 
-import org.apache.qpid.configuration.CommonProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.configuration.CommonProperties;
 import org.apache.qpid.properties.ConnectionStartProperties;
 
 
@@ -134,6 +134,16 @@ public class ClientDelegate extends ConnectionDelegate
     @Override
     public void connectionTune(Connection conn, ConnectionTune tune)
     {
+        try
+        {
+            verifySaslNegotiationComplete(conn);
+        }
+        catch (SaslException e)
+        {
+            conn.exception(e);
+            return;
+        }
+
         int heartbeatInterval = _connectionSettings.getHeartbeatInterval010();
         float heartbeatTimeoutFactor = _connectionSettings.getHeartbeatTimeoutFactor();
         int actualHeartbeatInterval = calculateHeartbeatInterval(heartbeatInterval,
@@ -225,4 +235,30 @@ public class ClientDelegate extends ConnectionDelegate
     {
         return _connectionSettings;
     }
+
+    private void verifySaslNegotiationComplete(Connection connection) throws SaslException
+    {
+        SaslClient client = connection.getSaslClient();
+        if (client != null)
+        {
+            if (!client.isComplete())
+            {
+                throw new SaslException("SASL negotiation has not been completed - cannot proceed with connection open");
+            }
+
+            String mechanismName = client.getMechanismName();
+            try
+            {
+                client.dispose();
+            }
+            catch (SaslException e)
+            {
+                LOGGER.warn("Disposal of client sasl for mechanism '{}' has failed", mechanismName, e);
+            }
+            finally
+            {
+                connection.setSaslClient(null);
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/8e652dd7/client/src/test/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandlerTest.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandlerTest.java b/client/src/test/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandlerTest.java
new file mode 100644
index 0000000..f42a3e1
--- /dev/null
+++ b/client/src/test/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandlerTest.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.handler;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.security.sasl.SaslClient;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.ConnectionTuneParameters;
+import org.apache.qpid.client.MockAMQConnection;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.framing.ConnectionTuneBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ConnectionTuneMethodHandlerTest extends QpidTestCase
+{
+    private static final int CHANNEL_ID = 0;
+    private AMQProtocolSession _amqProtocolSession;
+    private ConnectionTuneBody _body;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _amqProtocolSession = mock(AMQProtocolSession.class);
+        _body = mock(ConnectionTuneBody.class);
+    }
+
+    public void testMethodReceived_SaslClientIsNotFound() throws Exception
+    {
+        ConnectionTuneMethodHandler handler = ConnectionTuneMethodHandler.getInstance();
+        try
+        {
+            handler.methodReceived(_amqProtocolSession, _body, CHANNEL_ID);
+            fail("Exception is not thrown");
+        }
+        catch (QpidException e)
+        {
+            // pass
+        }
+    }
+
+    public void testMethodReceived_SaslNegotiationIsNotComplete() throws Exception
+    {
+        ConnectionTuneMethodHandler handler = ConnectionTuneMethodHandler.getInstance();
+        try
+        {
+            final SaslClient saslClient = mock(SaslClient.class);
+            when(saslClient.isComplete()).thenReturn(false);
+            when(_amqProtocolSession.getSaslClient()).thenReturn(saslClient);
+            handler.methodReceived(_amqProtocolSession, _body, CHANNEL_ID);
+            fail("Exception is not thrown");
+        }
+        catch (QpidException e)
+        {
+            // pass
+        }
+    }
+
+    public void testMethodReceived_SaslNegotiationIsComplete() throws Exception
+    {
+        ConnectionTuneMethodHandler handler = ConnectionTuneMethodHandler.getInstance();
+        final SaslClient saslClient = mock(SaslClient.class);
+        when(saslClient.isComplete()).thenReturn(true);
+        final AMQStateManager stateManager = mock(AMQStateManager.class);
+        ConnectionTuneParameters parameters = new ConnectionTuneParameters();
+        final AMQConnection connection = new MockAMQConnection("loaclhost", "test", "test", "client", "virtualhost");
+        final MethodRegistry methodRegistry = new MethodRegistry(ProtocolVersion.getLatestSupportedVersion());
+        when(_amqProtocolSession.getSaslClient()).thenReturn(saslClient);
+        when(_amqProtocolSession.getStateManager()).thenReturn(stateManager);
+        when(_amqProtocolSession.getMethodRegistry()).thenReturn(methodRegistry);
+        when(_amqProtocolSession.getConnectionTuneParameters()).thenReturn(parameters);
+        when(_amqProtocolSession.getAMQConnection()).thenReturn(connection);
+
+        handler.methodReceived(_amqProtocolSession, _body, CHANNEL_ID);
+        verify(stateManager, times(1)).changeState(AMQState.CONNECTION_NOT_OPENED);
+        verify(saslClient, times(1)).isComplete();
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org