You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by lq...@apache.org on 2017/11/08 12:36:52 UTC
qpid-jms-amqp-0-x git commit: QPID-7964: [Java Client,
AMQP 0-x] In SCRAM SASL implementation do not incorrectly encode "="
and ", " for passwords
Repository: qpid-jms-amqp-0-x
Updated Branches:
refs/heads/master 56bacf627 -> 1043d0f4d
QPID-7964: [Java Client, AMQP 0-x] In SCRAM SASL implementation do not incorrectly encode "=" and "," for passwords
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/1043d0f4
Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/tree/1043d0f4
Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/diff/1043d0f4
Branch: refs/heads/master
Commit: 1043d0f4de9539b7a861cebcc3925c4acf13a431
Parents: 56bacf6
Author: Lorenz Quack <lq...@apache.org>
Authored: Wed Nov 8 12:36:15 2017 +0000
Committer: Lorenz Quack <lq...@apache.org>
Committed: Wed Nov 8 12:36:15 2017 +0000
----------------------------------------------------------------------
.../security/scram/AbstractScramSaslClient.java | 25 ++-
.../security/scram/ScramSHA1SaslClient.java | 4 +-
.../scram/ScramSHA1SaslClientFactory.java | 3 +-
.../security/scram/ScramSHA256SaslClient.java | 4 +-
.../scram/ScramSHA256SaslClientFactory.java | 3 +-
.../AbstractScramSHAMechanismTestBase.java | 202 +++++++++++++++++++
.../security/scram/ScramSHA1MechanismTest.java | 104 ++++++++++
.../scram/ScramSHA256MechanismTest.java | 65 ++++++
8 files changed, 398 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java b/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
index d9f6f53..6c23fd0 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
@@ -27,7 +27,6 @@ import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@@ -53,7 +52,7 @@ public abstract class AbstractScramSaslClient implements SaslClient
private final String _hmacName;
private String _username;
- private final String _clientNonce = UUID.randomUUID().toString();
+ private final String _clientNonce;
private String _serverNonce;
private byte[] _salt;
private int _iterationCount;
@@ -77,13 +76,14 @@ public abstract class AbstractScramSaslClient implements SaslClient
public AbstractScramSaslClient(final CallbackHandler cbh,
final String mechanism,
final String digestName,
- final String hmacName)
+ final String hmacName,
+ final String clientNonce)
{
_callbackHandler = cbh;
_mechanism = mechanism;
_digestName = digestName;
_hmacName = hmacName;
-
+ _clientNonce = clientNonce;
}
@Override
@@ -131,7 +131,15 @@ public abstract class AbstractScramSaslClient implements SaslClient
{
throw new SaslException("Server final message did not contain verifier");
}
- byte[] serverSignature = Strings.decodeBase64(parts[0].substring(2));
+ byte[] serverSignature;
+ try
+ {
+ serverSignature = Strings.decodeBase64(parts[0].substring(2));
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new SaslException("Server signature did not match");
+ }
if(!Arrays.equals(_serverSignature, serverSignature))
{
throw new SaslException("Server signature did not match");
@@ -289,7 +297,7 @@ public abstract class AbstractScramSaslClient implements SaslClient
NameCallback nameCallback = new NameCallback("Username?");
_callbackHandler.handle(new Callback[] { nameCallback });
_username = nameCallback.getName();
- buf.append(saslPrep(_username));
+ buf.append(escapeUsername(saslPrep(_username)));
buf.append(",r=");
buf.append(_clientNonce);
_clientFirstMessageBare = buf.toString();
@@ -314,6 +322,11 @@ public abstract class AbstractScramSaslClient implements SaslClient
throw new SaslException("Can only encode names and passwords which are restricted to ASCII characters");
}
+ return name;
+ }
+
+ private String escapeUsername(String name)
+ {
name = name.replace("=", "=3D");
name = name.replace(",", "=2C");
return name;
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClient.java b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClient.java
index b6704e9..bd05964 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClient.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClient.java
@@ -27,8 +27,8 @@ public class ScramSHA1SaslClient extends AbstractScramSaslClient
public static final String MECHANISM = "SCRAM-SHA-1";
- public ScramSHA1SaslClient(final CallbackHandler cbh)
+ public ScramSHA1SaslClient(final CallbackHandler cbh, final String clientNonce)
{
- super(cbh, MECHANISM, "SHA-1", "HmacSHA1");
+ super(cbh, MECHANISM, "SHA-1", "HmacSHA1", clientNonce);
}
}
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClientFactory.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClientFactory.java b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClientFactory.java
index 59ef236..7c0af3a 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClientFactory.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA1SaslClientFactory.java
@@ -21,6 +21,7 @@
package org.apache.qpid.client.security.scram;
import java.util.Map;
+import java.util.UUID;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslClient;
@@ -46,7 +47,7 @@ public class ScramSHA1SaslClientFactory implements SaslClientFactory
{
throw new SaslException("CallbackHandler must not be null");
}
- return new ScramSHA1SaslClient(cbh);
+ return new ScramSHA1SaslClient(cbh, UUID.randomUUID().toString());
}
}
return null;
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClient.java b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClient.java
index 8779c36..30fe02f 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClient.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClient.java
@@ -27,8 +27,8 @@ public class ScramSHA256SaslClient extends AbstractScramSaslClient
public static final String MECHANISM = "SCRAM-SHA-256";
- public ScramSHA256SaslClient(final CallbackHandler cbh)
+ public ScramSHA256SaslClient(final CallbackHandler cbh, final String clientNonce)
{
- super(cbh, MECHANISM, "SHA-256", "HmacSHA256");
+ super(cbh, MECHANISM, "SHA-256", "HmacSHA256", clientNonce);
}
}
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClientFactory.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClientFactory.java b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClientFactory.java
index fff762f..5dd7544 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClientFactory.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/ScramSHA256SaslClientFactory.java
@@ -21,6 +21,7 @@
package org.apache.qpid.client.security.scram;
import java.util.Map;
+import java.util.UUID;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslClient;
@@ -46,7 +47,7 @@ public class ScramSHA256SaslClientFactory implements SaslClientFactory
{
throw new SaslException("CallbackHandler must not be null");
}
- return new ScramSHA256SaslClient(cbh);
+ return new ScramSHA256SaslClient(cbh, UUID.randomUUID().toString());
}
}
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/test/java/org/apache/qpid/client/security/scram/AbstractScramSHAMechanismTestBase.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/qpid/client/security/scram/AbstractScramSHAMechanismTestBase.java b/client/src/test/java/org/apache/qpid/client/security/scram/AbstractScramSHAMechanismTestBase.java
new file mode 100644
index 0000000..53d911c
--- /dev/null
+++ b/client/src/test/java/org/apache/qpid/client/security/scram/AbstractScramSHAMechanismTestBase.java
@@ -0,0 +1,202 @@
+/*
+ * 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.scram;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.nio.charset.StandardCharsets;
+
+import javax.security.sasl.SaslException;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+
+/**
+ * The quoted text in the test method javadoc is taken from RFC 5802.
+ */
+public abstract class AbstractScramSHAMechanismTestBase extends QpidTestCase
+{
+ private final byte[] expectedClientInitialResponse;
+ private final byte[] serverFirstMessage;
+ private final byte[] expectedClientFinalMessage;
+ private final byte[] serverFinalMessage;
+
+ public AbstractScramSHAMechanismTestBase(byte[] expectedClientInitialResponse,
+ byte[] serverFirstMessage,
+ byte[] expectedClientFinalMessage,
+ byte[] serverFinalMessage)
+ {
+ this.expectedClientInitialResponse = expectedClientInitialResponse;
+ this.serverFirstMessage = serverFirstMessage;
+ this.expectedClientFinalMessage = expectedClientFinalMessage;
+ this.serverFinalMessage = serverFinalMessage;
+ }
+
+ protected abstract AbstractScramSaslClient getScramSaslClient() throws Exception;
+ protected abstract AbstractScramSaslClient getScramSaslClient(String username, String password) throws Exception;
+ protected abstract String getExpectedInitialResponseString(final String escapedUsername);
+
+
+ public void testSuccessfulAuthentication() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ byte[] clientInitialResponse = mechanism.evaluateChallenge(null);
+ assertArrayEquals(expectedClientInitialResponse, clientInitialResponse);
+
+ byte[] clientFinalMessage = mechanism.evaluateChallenge(serverFirstMessage);
+ assertArrayEquals(expectedClientFinalMessage, clientFinalMessage);
+
+ byte[] expectedFinalChallengeResponse = "".getBytes();
+ assertArrayEquals(expectedFinalChallengeResponse, mechanism.evaluateChallenge(serverFinalMessage));
+
+ assertTrue(mechanism.isComplete());
+ }
+
+ public void testServerFirstMessageMalformed() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ mechanism.evaluateChallenge(null);
+ try
+ {
+ mechanism.evaluateChallenge("badserverfirst".getBytes());
+ fail("Exception not thrown");
+ }
+ catch (SaslException s)
+ {
+ // PASS
+ }
+ }
+
+ /**
+ * 5.1. SCRAM Attributes
+ * "m: This attribute is reserved for future extensibility. In this
+ * version of SCRAM, its presence in a client or a server message
+ * MUST cause authentication failure when the attribute is parsed by
+ * the other end."
+ *
+ * @throws Exception if an unexpected exception is thrown.
+ */
+ public void testServerFirstMessageMandatoryExtensionRejected() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ mechanism.evaluateChallenge(null);
+ try
+ {
+ mechanism.evaluateChallenge("m=notsupported,s=,i=".getBytes());
+ fail("Exception not thrown");
+ }
+ catch (SaslException s)
+ {
+ // PASS
+ }
+ }
+
+ /**
+ * 5. SCRAM Authentication Exchange
+ * "In [the server first] response, the server sends a "server-first-message" containing the
+ * user's iteration count i and the user's salt, and appends its own
+ * nonce to the client-specified one."
+ *
+ * @throws Exception if an unexpected exception is thrown.
+ */
+ public void testServerFirstMessageInvalidNonceRejected() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ mechanism.evaluateChallenge(null);
+ try
+ {
+ mechanism.evaluateChallenge("r=invalidnonce,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096".getBytes());
+ fail("Exception not thrown");
+ }
+ catch (SaslException s)
+ {
+ // PASS
+ }
+ }
+
+ /**
+ * 5. SCRAM Authentication Exchange
+ * "The client then authenticates the server by computing the
+ * ServerSignature and comparing it to the value sent by the server. If
+ * the two are different, the client MUST consider the authentication
+ * exchange to be unsuccessful, and it might have to drop the
+ * connection."
+ *
+ * @throws Exception if an unexpected exception is thrown.
+ */
+ public void testServerSignatureDiffer() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ mechanism.evaluateChallenge(null);
+ mechanism.evaluateChallenge(serverFirstMessage);
+ try
+ {
+ mechanism.evaluateChallenge("v=badserverfinal".getBytes(StandardCharsets.US_ASCII));
+ fail("Exception not thrown");
+ }
+ catch (SaslException e)
+ {
+ // PASS
+ }
+ }
+
+ public void testIncompleteExchange() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient();
+
+ byte[] clientInitialResponse = mechanism.evaluateChallenge(null);
+ assertArrayEquals(expectedClientInitialResponse, clientInitialResponse);
+
+ byte[] clientFinalMessage = mechanism.evaluateChallenge(serverFirstMessage);
+ assertArrayEquals(expectedClientFinalMessage, clientFinalMessage);
+
+ assertFalse(mechanism.isComplete());
+ }
+
+ public void testDifferentClientNonceOnEachInstance() throws Exception
+ {
+ AbstractScramSaslClient mech = getScramSaslClient();
+
+ AbstractScramSaslClient mech2 = getScramSaslClient();
+
+ byte[] clientInitialResponse = mech.evaluateChallenge(null);
+ byte[] clientInitialResponse2 = mech2.evaluateChallenge(null);
+
+ assertTrue(new String(clientInitialResponse, StandardCharsets.UTF_8).startsWith("n,,n=user,r="));
+ assertTrue(new String(clientInitialResponse2, StandardCharsets.UTF_8).startsWith("n,,n=user,r="));
+
+ assertNotEquals(clientInitialResponse, clientInitialResponse2);
+ }
+
+
+ public void testUsernameCommaEqualsCharactersEscaped() throws Exception
+ {
+ String originalUsername = "user,name=";
+ String escapedUsername = "user=2Cname=3D";
+
+ String expectedInitialResponseString = getExpectedInitialResponseString(escapedUsername);
+
+ AbstractScramSaslClient mech = getScramSaslClient(originalUsername, "password");
+ byte[] clientInitialResponse = mech.evaluateChallenge(null);
+ assertArrayEquals(expectedInitialResponseString.getBytes(StandardCharsets.UTF_8), clientInitialResponse);
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA1MechanismTest.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA1MechanismTest.java b/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA1MechanismTest.java
new file mode 100644
index 0000000..8824bb6
--- /dev/null
+++ b/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA1MechanismTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.scram;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.security.UsernamePasswordCallbackHandler;
+import org.apache.qpid.jms.ConnectionURL;
+
+/**
+ * The known good used by these tests is taken from the example in RFC 5802 section 5.
+ */
+public class ScramSHA1MechanismTest extends AbstractScramSHAMechanismTestBase
+{
+
+ private static final String USERNAME = "user";
+ private static final String PASSWORD = "pencil";
+
+ private static final String CLIENT_NONCE = "fyko+d2lbbFgONRv9qkxdawL";
+
+ private static final byte[] EXPECTED_CLIENT_INITIAL_RESPONSE =
+ "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] SERVER_FIRST_MESSAGE =
+ "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] EXPECTED_CLIENT_FINAL_MESSAGE =
+ "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=".getBytes(
+ StandardCharsets.UTF_8);
+ private static final byte[] SERVER_FINAL_MESSAGE =
+ "v=rmF9pqV8S7suAoZWja4dJRkFsKQ=".getBytes(StandardCharsets.UTF_8);
+
+ public ScramSHA1MechanismTest()
+ {
+ super(EXPECTED_CLIENT_INITIAL_RESPONSE,
+ SERVER_FIRST_MESSAGE,
+ EXPECTED_CLIENT_FINAL_MESSAGE,
+ SERVER_FINAL_MESSAGE);
+ }
+
+ @Override
+ protected AbstractScramSaslClient getScramSaslClient() throws Exception
+ {
+ return getScramSaslClient(USERNAME, PASSWORD);
+ }
+
+ @Override
+ protected AbstractScramSaslClient getScramSaslClient(final String username, final String password) throws Exception
+ {
+
+ UsernamePasswordCallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
+ ConnectionURL connectionURL = new AMQConnectionURL(String.format("amqp://%s:%s@////", username, password));
+ callbackHandler.initialise(connectionURL);
+
+ return new ScramSHA1SaslClient(callbackHandler, CLIENT_NONCE);
+ }
+
+ @Override
+ protected String getExpectedInitialResponseString(final String escapedUsername)
+ {
+ return "n,,n=" + escapedUsername + ",r=" + CLIENT_NONCE;
+ }
+
+ public void testPasswordCommaEqualsCharactersNotEscaped() throws Exception
+ {
+ AbstractScramSaslClient mechanism = getScramSaslClient(USERNAME, PASSWORD + ",=");
+
+ byte[] clientInitialResponse = mechanism.evaluateChallenge(null);
+ assertArrayEquals(EXPECTED_CLIENT_INITIAL_RESPONSE, clientInitialResponse);
+
+ byte[] serverFirstMessage =
+ "r=fyko+d2lbbFgONRv9qkxdawLdcbfa301-1618-46ee-96c1-2bf60139dc7f,s=Q0zM1qzKMOmI0sAzE7dXt6ru4ZIXhAzn40g4mQXKQdw=,i=4096"
+ .getBytes(StandardCharsets.UTF_8);
+ byte[] expectedClientFinalMessage =
+ "c=biws,r=fyko+d2lbbFgONRv9qkxdawLdcbfa301-1618-46ee-96c1-2bf60139dc7f,p=quRNWvZqGUvPXoazebZe0ZYsjQI=".getBytes(
+ StandardCharsets.UTF_8);
+
+ byte[] clientFinalMessage = mechanism.evaluateChallenge(serverFirstMessage);
+
+ assertArrayEquals(expectedClientFinalMessage, clientFinalMessage);
+
+ byte[] serverFinalMessage = "v=dnJDHm3fp6WwVrl5yjZuqKp03lQ=".getBytes(StandardCharsets.UTF_8);
+ byte[] expectedFinalChallengeResponse = "".getBytes();
+
+ assertArrayEquals(expectedFinalChallengeResponse, mechanism.evaluateChallenge(serverFinalMessage));
+
+ assertTrue(mechanism.isComplete());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/qpid-jms-amqp-0-x/blob/1043d0f4/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA256MechanismTest.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA256MechanismTest.java b/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA256MechanismTest.java
new file mode 100644
index 0000000..18c0770
--- /dev/null
+++ b/client/src/test/java/org/apache/qpid/client/security/scram/ScramSHA256MechanismTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.scram;
+
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.security.UsernamePasswordCallbackHandler;
+import org.apache.qpid.jms.ConnectionURL;
+
+/**
+ * The known good used by these tests is taken from the example in RFC 7677 section 3.
+ */
+public class ScramSHA256MechanismTest extends AbstractScramSHAMechanismTestBase {
+
+ private static final String USERNAME = "user";
+ private static final String PASSWORD = "pencil";
+
+ private static final String CLIENT_NONCE = "rOprNGfwEbeRWgbNEkqO";
+
+ private static final byte[] EXPECTED_CLIENT_INITIAL_RESPONSE = "n,,n=user,r=rOprNGfwEbeRWgbNEkqO".getBytes();
+ private static final byte[] SERVER_FIRST_MESSAGE = "r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096".getBytes();
+ private static final byte[] EXPECTED_CLIENT_FINAL_MESSAGE = "c=biws,r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,p=dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ=".getBytes();
+ private static final byte[] SERVER_FINAL_MESSAGE = "v=6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4=".getBytes();
+
+ public ScramSHA256MechanismTest() {
+ super(EXPECTED_CLIENT_INITIAL_RESPONSE,
+ SERVER_FIRST_MESSAGE,
+ EXPECTED_CLIENT_FINAL_MESSAGE,
+ SERVER_FINAL_MESSAGE);
+ }
+
+ @Override
+ protected AbstractScramSaslClient getScramSaslClient() throws Exception
+ {
+ return getScramSaslClient(USERNAME, PASSWORD);
+ }
+
+ @Override
+ protected AbstractScramSaslClient getScramSaslClient(String username, String password) throws Exception
+ {
+ UsernamePasswordCallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
+ ConnectionURL connectionURL = new AMQConnectionURL(String.format("amqp://%s:%s@////", username, password));
+ callbackHandler.initialise(connectionURL);
+ return new ScramSHA256SaslClient(callbackHandler, CLIENT_NONCE);
+ }
+
+ @Override
+ protected String getExpectedInitialResponseString(final String escapedUsername)
+ {
+ return "n,,n=" + escapedUsername + ",r=" + CLIENT_NONCE;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org