summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnection.java56
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java30
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java17
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java5
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java99
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java78
9 files changed, 230 insertions, 71 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index ab59fee020..94a55ef52c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -111,7 +111,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/** Maps from session id (Integer) to AMQSession instance */
private final ChannelToSessionMap _sessions = new ChannelToSessionMap();
- private String _clientName;
+ private final String _clientName;
/** The user name to use for authentication */
private String _username;
@@ -126,7 +126,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private ConnectionListener _connectionListener;
- private ConnectionURL _connectionURL;
+ private final ConnectionURL _connectionURL;
/**
* Whether this connection is started, i.e. whether messages are flowing to consumers. It has no meaning for message
@@ -257,6 +257,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
*/
public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException
{
+ if (connectionURL == null)
+ {
+ throw new IllegalArgumentException("Connection must be specified");
+ }
+
// set this connection maxPrefetch
if (connectionURL.getOption(ConnectionURL.OPTIONS_MAXPREFETCH) != null)
{
@@ -264,7 +269,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the defaul value set for all connections
+ // use the default value set for all connections
_maxPrefetch = Integer.parseInt(System.getProperties().getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME,
ClientProperties.MAX_PREFETCH_DEFAULT));
}
@@ -278,7 +283,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the defaul value set for all connections
+ // use the default value set for all connections
_syncPersistence = Boolean.getBoolean(ClientProperties.SYNC_PERSISTENT_PROP_NAME);
if (_syncPersistence)
{
@@ -293,7 +298,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the defaul value set for all connections
+ // use the default value set for all connections
_syncAck = Boolean.getBoolean(ClientProperties.SYNC_ACK_PROP_NAME);
}
@@ -346,11 +351,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
_sslConfiguration = sslConfig;
- if (connectionURL == null)
- {
- throw new IllegalArgumentException("Connection must be specified");
- }
-
_connectionURL = connectionURL;
_clientName = connectionURL.getClientName();
@@ -535,14 +535,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
- protected AMQConnection(String username, String password, String clientName, String virtualHost)
- {
- _clientName = clientName;
- _username = username;
- _password = password;
- setVirtualHost(virtualHost);
- }
-
private void setVirtualHost(String virtualHost)
{
if (virtualHost != null && virtualHost.startsWith("/"))
@@ -696,20 +688,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
- private void reopenChannel(int channelId, int prefetchHigh, int prefetchLow, boolean transacted)
- throws AMQException, FailoverException
- {
- try
- {
- createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted);
- }
- catch (AMQException e)
- {
- deregisterSession(channelId);
- throw new AMQException(null, "Error reopening channel " + channelId + " after failover: " + e, e);
- }
- }
-
public void setFailoverPolicy(FailoverPolicy policy)
{
_failoverPolicy = policy;
@@ -1372,6 +1350,20 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return buf.toString();
}
+ /**
+ * Returns connection url.
+ * @return connection url
+ */
+ public ConnectionURL getConnectionURL()
+ {
+ return _connectionURL;
+ }
+
+ /**
+ * Returns stringified connection url. This url is suitable only for display
+ * as {@link AMQConnectionURL#toString()} converts any password to asterisks.
+ * @return connection url
+ */
public String toURL()
{
return _connectionURL.toString();
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index c81ad6422f..2b49bb8f81 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -226,7 +226,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener<Co
{
Object instance = mechanismClass.newInstance();
AMQCallbackHandler cbh = (AMQCallbackHandler) instance;
- cbh.initialise(protocolSession);
+ cbh.initialise(protocolSession.getAMQConnection().getConnectionURL());
return cbh;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
index 7976760696..5b7d272506 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
@@ -148,16 +148,6 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
return getAMQConnection().getVirtualHost();
}
- public String getUsername()
- {
- return getAMQConnection().getUsername();
- }
-
- public String getPassword()
- {
- return getAMQConnection().getPassword();
- }
-
public SaslClient getSaslClient()
{
return _saslClient;
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
index fbca444208..67dd1a58b6 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
@@ -22,9 +22,9 @@ package org.apache.qpid.client.security;
import javax.security.auth.callback.CallbackHandler;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
+import org.apache.qpid.jms.ConnectionURL;
public interface AMQCallbackHandler extends CallbackHandler
{
- void initialise(AMQProtocolSession protocolSession);
+ void initialise(ConnectionURL connectionURL);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
index 66176dac3c..6ec83f0a23 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
@@ -20,30 +20,29 @@
*/
package org.apache.qpid.client.security;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
+import org.apache.qpid.jms.ConnectionURL;
public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
{
- private static final Logger _logger = LoggerFactory.getLogger(UsernameHashedPasswordCallbackHandler.class);
+ private ConnectionURL _connectionURL;
- private AMQProtocolSession _protocolSession;
-
- public void initialise(AMQProtocolSession protocolSession)
+ /**
+ * @see org.apache.qpid.client.security.AMQCallbackHandler#initialise(org.apache.qpid.jms.ConnectionURL)
+ */
+ @Override
+ public void initialise(ConnectionURL connectionURL)
{
- _protocolSession = protocolSession;
+ _connectionURL = connectionURL;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
@@ -53,13 +52,13 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
Callback cb = callbacks[i];
if (cb instanceof NameCallback)
{
- ((NameCallback) cb).setName(_protocolSession.getUsername());
+ ((NameCallback) cb).setName(_connectionURL.getUsername());
}
else if (cb instanceof PasswordCallback)
{
try
{
- ((PasswordCallback) cb).setPassword(getHash(_protocolSession.getPassword()));
+ ((PasswordCallback) cb).setPassword(getHash(_connectionURL.getPassword()));
}
catch (NoSuchAlgorithmException e)
{
@@ -99,4 +98,5 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
return hash;
}
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
index c50c62710f..ad088722c8 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
@@ -27,15 +27,19 @@ import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
+import org.apache.qpid.jms.ConnectionURL;
public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
{
- private AMQProtocolSession _protocolSession;
+ private ConnectionURL _connectionURL;
- public void initialise(AMQProtocolSession protocolSession)
+ /**
+ * @see org.apache.qpid.client.security.AMQCallbackHandler#initialise(org.apache.qpid.jms.ConnectionURL)
+ */
+ @Override
+ public void initialise(final ConnectionURL connectionURL)
{
- _protocolSession = protocolSession;
+ _connectionURL = connectionURL;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
@@ -45,11 +49,11 @@ public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
Callback cb = callbacks[i];
if (cb instanceof NameCallback)
{
- ((NameCallback)cb).setName(_protocolSession.getUsername());
+ ((NameCallback)cb).setName(_connectionURL.getUsername());
}
else if (cb instanceof PasswordCallback)
{
- ((PasswordCallback)cb).setPassword(_protocolSession.getPassword().toCharArray());
+ ((PasswordCallback)cb).setPassword(_connectionURL.getPassword().toCharArray());
}
else
{
@@ -57,4 +61,5 @@ public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
}
}
}
+
}
diff --git a/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java b/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
index da44822ec3..5972bf3fae 100644
--- a/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
+++ b/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
@@ -79,11 +79,6 @@ public class MockAMQConnection extends AMQConnection
super(connectionURL, sslConfig);
}
- protected MockAMQConnection(String username, String password, String clientName, String virtualHost)
- {
- super(username, password, clientName, virtualHost);
- }
-
@Override
public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException
{
diff --git a/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java b/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java
new file mode 100644
index 0000000000..98fc09c25b
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java
@@ -0,0 +1,99 @@
+/*
+ *
+ * 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.security;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.MockAMQConnection;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+/**
+ * Unit tests for the UsernameHashPasswordCallbackHandler. This callback handler is
+ * used by the CRAM-MD5-HASHED SASL mechanism.
+ *
+ */
+public class UsernameHashedPasswordCallbackHandlerTest extends TestCase
+{
+ private AMQCallbackHandler _callbackHandler = new UsernameHashedPasswordCallbackHandler(); // Class under test
+ private static final String PROMPT_UNUSED = "unused";
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ final String url = "amqp://username:password@client/test?brokerlist='vm://:1'";
+ _callbackHandler.initialise(new AMQConnectionURL(url));
+ }
+
+ /**
+ * Tests that the callback handler can correctly retrieve the username from the connection url.
+ */
+ public void testNameCallback() throws Exception
+ {
+ final String expectedName = "username";
+ NameCallback nameCallback = new NameCallback(PROMPT_UNUSED);
+
+ assertNull("Unexpected name before test", nameCallback.getName());
+ _callbackHandler.handle(new Callback[] {nameCallback});
+ assertEquals("Unexpected name", expectedName, nameCallback.getName());
+ }
+
+ /**
+ * Tests that the callback handler can correctly retrieve the password from the connection url
+ * and calculate a MD5.
+ */
+ public void testDigestedPasswordCallback() throws Exception
+ {
+ final char[] expectedPasswordDigested = getHashPassword("password");
+
+ PasswordCallback passwordCallback = new PasswordCallback(PROMPT_UNUSED, false);
+ assertNull("Unexpected password before test", passwordCallback.getPassword());
+ _callbackHandler.handle(new Callback[] {passwordCallback});
+ assertTrue("Unexpected password", Arrays.equals(expectedPasswordDigested, passwordCallback.getPassword()));
+ }
+
+ private char[] getHashPassword(final String password) throws Exception
+ {
+ MessageDigest md5Digester = MessageDigest.getInstance("MD5");
+ final byte[] digest = md5Digester.digest(password.getBytes("UTF-8"));
+
+ char[] hash = new char[digest.length];
+
+ int index = 0;
+ for (byte b : digest)
+ {
+ hash[index++] = (char) b;
+ }
+
+ return hash;
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java b/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java
new file mode 100644
index 0000000000..05a60fbef7
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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.security;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.MockAMQConnection;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+/**
+ * Unit tests for the UsernamePasswordCallbackHandler.
+ *
+ */
+public class UsernamePasswordCallbackHandlerTest extends TestCase
+{
+ private AMQCallbackHandler _callbackHandler = new UsernamePasswordCallbackHandler(); // Class under test
+ private static final String PROMPT_UNUSED = "unused";
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ final String url = "amqp://username:password@client/test?brokerlist='vm://:1'";
+
+ _callbackHandler.initialise(new AMQConnectionURL(url));
+ }
+
+ /**
+ * Tests that the callback handler can correctly retrieve the username from the connection url.
+ */
+ public void testNameCallback() throws Exception
+ {
+ final String expectedName = "username";
+ NameCallback nameCallback = new NameCallback(PROMPT_UNUSED);
+
+ assertNull("Unexpected name before test", nameCallback.getName());
+ _callbackHandler.handle(new Callback[] {nameCallback});
+ assertEquals("Unexpected name", expectedName, nameCallback.getName());
+ }
+
+ /**
+ * Tests that the callback handler can correctly retrieve the password from the connection url.
+ */
+ public void testPasswordCallback() throws Exception
+ {
+ final String expectedPassword = "password";
+ PasswordCallback passwordCallback = new PasswordCallback(PROMPT_UNUSED, false);
+ assertNull("Unexpected password before test", passwordCallback.getPassword());
+ _callbackHandler.handle(new Callback[] {passwordCallback});
+ assertEquals("Unexpected password", expectedPassword, new String(passwordCallback.getPassword()));
+ }
+}