summaryrefslogtreecommitdiff
path: root/java/broker-core/src
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2014-07-06 21:28:20 +0000
committerRobert Godfrey <rgodfrey@apache.org>2014-07-06 21:28:20 +0000
commit33c44bd0d25c4fb082a48820e5b2ced20e29c0b2 (patch)
tree3a96b4f453af0fa11aab2f82269bb01c4fe58d72 /java/broker-core/src
parent7f4550b66619ed14378c188972e72c319c79f9bc (diff)
downloadqpid-python-33c44bd0d25c4fb082a48820e5b2ced20e29c0b2.tar.gz
QPID-5878 : [Java Broker] Add SCRAM-SHA-256 SASL support
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1608295 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/broker-core/src')
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java3
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java397
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java4
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java349
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA256AuthenticationManager.java66
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java (renamed from java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java)49
6 files changed, 505 insertions, 363 deletions
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
index 597b9e3bb1..a2bb5cb91a 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
@@ -26,7 +26,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.log4j.Logger;
@@ -148,8 +147,6 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica
if(childClass == PreferencesProvider.class)
{
attributes = new HashMap<String, Object>(attributes);
- attributes.put(ConfiguredObject.ID, UUID.randomUUID());
- attributes.put(ConfiguredObject.DESIRED_STATE, State.ACTIVE);
PreferencesProvider pp = getObjectFactory().create(PreferencesProvider.class, attributes, this);
_preferencesProvider = pp;
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
new file mode 100644
index 0000000000..f08c37008a
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
@@ -0,0 +1,397 @@
+/*
+ *
+ * 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.server.security.auth.manager;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.auth.login.AccountNotFoundException;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.qpid.server.configuration.updater.Task;
+import org.apache.qpid.server.configuration.updater.VoidTaskWithException;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.User;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer;
+
+public abstract class AbstractScramAuthenticationManager<X extends AbstractScramAuthenticationManager<X>>
+ extends AbstractAuthenticationManager<X>
+ implements PasswordCredentialManagingAuthenticationProvider<X>
+{
+ public static final String SCRAM_USER_TYPE = "scram";
+
+ static final Charset ASCII = Charset.forName("ASCII");
+ private final SecureRandom _random = new SecureRandom();
+
+ private int _iterationCount = 4096;
+
+ private Map<String, ScramAuthUser> _users = new ConcurrentHashMap<String, ScramAuthUser>();
+
+
+ protected AbstractScramAuthenticationManager(final Map<String, Object> attributes, final Broker broker)
+ {
+ super(attributes, broker);
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return getMechanismName();
+ }
+
+ protected abstract String getMechanismName();
+
+ @Override
+ public SaslServer createSaslServer(final String mechanism,
+ final String localFQDN,
+ final Principal externalPrincipal)
+ throws SaslException
+ {
+ return new ScramSaslServer(this, getMechanismName(), getHmacName(), getDigestName());
+ }
+
+ protected abstract String getDigestName();
+
+ @Override
+ public AuthenticationResult authenticate(final SaslServer server, final byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ final String userId = server.getAuthorizationID();
+ return new AuthenticationResult(new UsernamePrincipal(userId));
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(final String username, final String password)
+ {
+ ScramAuthUser user = getUser(username);
+ if(user != null)
+ {
+ final String[] usernamePassword = user.getPassword().split(",");
+ byte[] salt = DatatypeConverter.parseBase64Binary(usernamePassword[0]);
+ try
+ {
+ if(Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[1]),
+ createSaltedPassword(salt, password)))
+ {
+ return new AuthenticationResult(new UsernamePrincipal(username));
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
+ }
+
+ }
+
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+
+
+ }
+
+
+ public int getIterationCount()
+ {
+ return _iterationCount;
+ }
+
+ public byte[] getSalt(final String username)
+ {
+ ScramAuthUser user = getUser(username);
+
+ if(user == null)
+ {
+ // don't disclose that the user doesn't exist, just generate random data so the failure is indistinguishable
+ // from the "wrong password" case
+
+ byte[] salt = new byte[32];
+ _random.nextBytes(salt);
+ return salt;
+ }
+ else
+ {
+ return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[0]);
+ }
+ }
+
+ private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
+
+ public byte[] getSaltedPassword(final String username) throws SaslException
+ {
+ ScramAuthUser user = getUser(username);
+ if(user == null)
+ {
+ throw new SaslException("Authentication Failed");
+ }
+ else
+ {
+ return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[1]);
+ }
+ }
+
+ private ScramAuthUser getUser(final String username)
+ {
+ return _users.get(username);
+ }
+
+ private byte[] createSaltedPassword(byte[] salt, String password) throws SaslException
+ {
+ Mac mac = createSha1Hmac(password.getBytes(ASCII));
+
+ mac.update(salt);
+ mac.update(INT_1);
+ byte[] result = mac.doFinal();
+
+ byte[] previous = null;
+ for(int i = 1; i < getIterationCount(); i++)
+ {
+ mac.update(previous != null? previous: result);
+ previous = mac.doFinal();
+ for(int x = 0; x < result.length; x++)
+ {
+ result[x] ^= previous[x];
+ }
+ }
+
+ return result;
+
+ }
+
+ private Mac createSha1Hmac(final byte[] keyBytes)
+ throws SaslException
+ {
+ try
+ {
+ SecretKeySpec key = new SecretKeySpec(keyBytes, getHmacName());
+ Mac mac = Mac.getInstance(getHmacName());
+ mac.init(key);
+ return mac;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+ protected abstract String getHmacName();
+
+ @Override
+ public boolean createUser(final String username, final String password, final Map<String, String> attributes)
+ {
+ return runTask(new Task<Boolean>()
+ {
+ @Override
+ public Boolean execute()
+ {
+ getSecurityManager().authoriseUserOperation(Operation.CREATE, username);
+ if (_users.containsKey(username))
+ {
+ throw new IllegalArgumentException("User '" + username + "' already exists");
+ }
+ try
+ {
+ Map<String, Object> userAttrs = new HashMap<String, Object>();
+ userAttrs.put(User.ID, UUID.randomUUID());
+ userAttrs.put(User.NAME, username);
+ userAttrs.put(User.PASSWORD, createStoredPassword(password));
+ userAttrs.put(User.TYPE, SCRAM_USER_TYPE);
+ ScramAuthUser user = new ScramAuthUser(userAttrs, AbstractScramAuthenticationManager.this);
+ user.create();
+
+ return true;
+ }
+ catch (SaslException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ });
+ }
+
+ org.apache.qpid.server.security.SecurityManager getSecurityManager()
+ {
+ return getBroker().getSecurityManager();
+ }
+
+ @Override
+ public void deleteUser(final String user) throws AccountNotFoundException
+ {
+ runTask(new VoidTaskWithException<AccountNotFoundException>()
+ {
+ @Override
+ public void execute() throws AccountNotFoundException
+ {
+ final ScramAuthUser authUser = getUser(user);
+ if(authUser != null)
+ {
+ authUser.setState(State.DELETED);
+ }
+ else
+ {
+ throw new AccountNotFoundException("No such user: '" + user + "'");
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setPassword(final String username, final String password) throws AccountNotFoundException
+ {
+ runTask(new VoidTaskWithException<AccountNotFoundException>()
+ {
+ @Override
+ public void execute() throws AccountNotFoundException
+ {
+
+ final ScramAuthUser authUser = getUser(username);
+ if (authUser != null)
+ {
+ authUser.setPassword(password);
+ }
+ else
+ {
+ throw new AccountNotFoundException("No such user: '" + username + "'");
+ }
+ }
+ });
+
+ }
+
+ @Override
+ public Map<String, Map<String, String>> getUsers()
+ {
+ return runTask(new Task<Map<String, Map<String, String>>>()
+ {
+ @Override
+ public Map<String, Map<String, String>> execute()
+ {
+
+ Map<String, Map<String, String>> users = new HashMap<String, Map<String, String>>();
+ for (String user : _users.keySet())
+ {
+ users.put(user, Collections.<String, String>emptyMap());
+ }
+ return users;
+ }
+ });
+ }
+
+ @Override
+ public void reload() throws IOException
+ {
+
+ }
+
+ @Override
+ public void recoverUser(final User user)
+ {
+ _users.put(user.getName(), (ScramAuthUser) user);
+ }
+
+ protected String createStoredPassword(final String password) throws SaslException
+ {
+ byte[] salt = new byte[32];
+ _random.nextBytes(salt);
+ byte[] passwordBytes = createSaltedPassword(salt, password);
+ return DatatypeConverter.printBase64Binary(salt) + "," + DatatypeConverter.printBase64Binary(passwordBytes);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C addChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ if(childClass == User.class)
+ {
+ String username = (String) attributes.get("name");
+ String password = (String) attributes.get("password");
+
+ if(createUser(username, password,null))
+ {
+ @SuppressWarnings("unchecked")
+ C user = (C) _users.get(username);
+ return user;
+ }
+ else
+ {
+ return null;
+
+ }
+ }
+ return super.addChild(childClass, attributes, otherParents);
+ }
+
+ void doDeleted()
+ {
+ deleted();
+ }
+
+ Map<String, ScramAuthUser> getUserMap()
+ {
+ return _users;
+ }
+
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java
index 15cd1d82a6..9a2d27f512 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java
@@ -44,12 +44,12 @@ import org.apache.qpid.server.security.access.Operation;
class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements User<ScramAuthUser>
{
- private ScramSHA1AuthenticationManager _authenticationManager;
+ private AbstractScramAuthenticationManager _authenticationManager;
@ManagedAttributeField
private String _password;
@ManagedObjectFactoryConstructor
- ScramAuthUser(final Map<String, Object> attributes, ScramSHA1AuthenticationManager parent)
+ ScramAuthUser(final Map<String, Object> attributes, AbstractScramAuthenticationManager parent)
{
super(parentsMap(parent), attributes);
_authenticationManager = parent;
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java
index 2138f4899e..6a48d29a71 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java
@@ -20,53 +20,23 @@
*/
package org.apache.qpid.server.security.auth.manager;
-import java.io.IOException;
import java.nio.charset.Charset;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import javax.security.auth.login.AccountNotFoundException;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-import javax.xml.bind.DatatypeConverter;
-
-import org.apache.qpid.server.configuration.updater.Task;
-import org.apache.qpid.server.configuration.updater.VoidTaskWithException;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
-import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
-import org.apache.qpid.server.model.State;
-import org.apache.qpid.server.model.User;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.UsernamePrincipal;
-import org.apache.qpid.server.security.auth.sasl.scram.ScramSHA1SaslServer;
@ManagedObject( category = false, type = "SCRAM-SHA-1" )
public class ScramSHA1AuthenticationManager
- extends AbstractAuthenticationManager<ScramSHA1AuthenticationManager>
- implements PasswordCredentialManagingAuthenticationProvider<ScramSHA1AuthenticationManager>
+ extends AbstractScramAuthenticationManager<ScramSHA1AuthenticationManager>
{
- public static final String SCRAM_USER_TYPE = "scram";
public static final String PROVIDER_TYPE = "SCRAM-SHA-1";
+ private static final String HMAC_NAME = "HmacSHA1";
+
static final Charset ASCII = Charset.forName("ASCII");
- public static final String HMAC_SHA_1 = "HmacSHA1";
- private final SecureRandom _random = new SecureRandom();
- private int _iterationCount = 4096;
- private Map<String, ScramAuthUser> _users = new ConcurrentHashMap<String, ScramAuthUser>();
+ private static final String MECHANISM = "SCRAM-SHA-1";
+ private static final String DIGEST_NAME = "SHA-1";
@ManagedObjectFactoryConstructor
@@ -76,318 +46,21 @@ public class ScramSHA1AuthenticationManager
}
@Override
- public void initialise()
- {
-
- }
-
- @Override
- public String getMechanisms()
- {
- return ScramSHA1SaslServer.MECHANISM;
- }
-
- @Override
- public SaslServer createSaslServer(final String mechanism,
- final String localFQDN,
- final Principal externalPrincipal)
- throws SaslException
- {
- return new ScramSHA1SaslServer(this);
- }
-
- @Override
- public AuthenticationResult authenticate(final SaslServer server, final byte[] response)
- {
- try
- {
- // Process response from the client
- byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
-
- if (server.isComplete())
- {
- final String userId = server.getAuthorizationID();
- return new AuthenticationResult(new UsernamePrincipal(userId));
- }
- else
- {
- return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
- }
- }
- catch (SaslException e)
- {
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
- }
- }
-
- @Override
- public AuthenticationResult authenticate(final String username, final String password)
- {
- ScramAuthUser user = getUser(username);
- if(user != null)
- {
- final String[] usernamePassword = user.getPassword().split(",");
- byte[] salt = DatatypeConverter.parseBase64Binary(usernamePassword[0]);
- try
- {
- if(Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[1]),createSaltedPassword(salt, password)))
- {
- return new AuthenticationResult(new UsernamePrincipal(username));
- }
- }
- catch (SaslException e)
- {
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
- }
-
- }
-
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
-
-
- }
-
-
- public int getIterationCount()
- {
- return _iterationCount;
- }
-
- public byte[] getSalt(final String username)
- {
- ScramAuthUser user = getUser(username);
-
- if(user == null)
- {
- // don't disclose that the user doesn't exist, just generate random data so the failure is indistinguishable
- // from the "wrong password" case
-
- byte[] salt = new byte[32];
- _random.nextBytes(salt);
- return salt;
- }
- else
- {
- return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[0]);
- }
- }
-
- private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
-
- public byte[] getSaltedPassword(final String username) throws SaslException
- {
- ScramAuthUser user = getUser(username);
- if(user == null)
- {
- throw new SaslException("Authentication Failed");
- }
- else
- {
- return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[1]);
- }
- }
-
- private ScramAuthUser getUser(final String username)
- {
- return _users.get(username);
- }
-
- private byte[] createSaltedPassword(byte[] salt, String password) throws SaslException
- {
- Mac mac = createSha1Hmac(password.getBytes(ASCII));
-
- mac.update(salt);
- mac.update(INT_1);
- byte[] result = mac.doFinal();
-
- byte[] previous = null;
- for(int i = 1; i < getIterationCount(); i++)
- {
- mac.update(previous != null? previous: result);
- previous = mac.doFinal();
- for(int x = 0; x < result.length; x++)
- {
- result[x] ^= previous[x];
- }
- }
-
- return result;
-
- }
-
- private Mac createSha1Hmac(final byte[] keyBytes)
- throws SaslException
- {
- try
- {
- SecretKeySpec key = new SecretKeySpec(keyBytes, HMAC_SHA_1);
- Mac mac = Mac.getInstance(HMAC_SHA_1);
- mac.init(key);
- return mac;
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new SaslException(e.getMessage(), e);
- }
- catch (InvalidKeyException e)
- {
- throw new SaslException(e.getMessage(), e);
- }
- }
-
- @Override
- public boolean createUser(final String username, final String password, final Map<String, String> attributes)
- {
- return runTask(new Task<Boolean>()
- {
- @Override
- public Boolean execute()
- {
- getSecurityManager().authoriseUserOperation(Operation.CREATE, username);
- if (_users.containsKey(username))
- {
- throw new IllegalArgumentException("User '" + username + "' already exists");
- }
- try
- {
- Map<String, Object> userAttrs = new HashMap<String, Object>();
- userAttrs.put(User.ID, UUID.randomUUID());
- userAttrs.put(User.NAME, username);
- userAttrs.put(User.PASSWORD, createStoredPassword(password));
- userAttrs.put(User.TYPE, SCRAM_USER_TYPE);
- ScramAuthUser user = new ScramAuthUser(userAttrs, ScramSHA1AuthenticationManager.this);
- user.create();
-
- return true;
- }
- catch (SaslException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
- });
- }
-
- SecurityManager getSecurityManager()
- {
- return getBroker().getSecurityManager();
- }
-
- @Override
- public void deleteUser(final String user) throws AccountNotFoundException
- {
- runTask(new VoidTaskWithException<AccountNotFoundException>()
- {
- @Override
- public void execute() throws AccountNotFoundException
- {
- final ScramAuthUser authUser = getUser(user);
- if(authUser != null)
- {
- authUser.setState(State.DELETED);
- }
- else
- {
- throw new AccountNotFoundException("No such user: '" + user + "'");
- }
- }
- });
- }
-
- @Override
- public void setPassword(final String username, final String password) throws AccountNotFoundException
+ protected String getMechanismName()
{
- runTask(new VoidTaskWithException<AccountNotFoundException>()
- {
- @Override
- public void execute() throws AccountNotFoundException
- {
-
- final ScramAuthUser authUser = getUser(username);
- if (authUser != null)
- {
- authUser.setPassword(password);
- }
- else
- {
- throw new AccountNotFoundException("No such user: '" + username + "'");
- }
- }
- });
-
- }
-
- @Override
- public Map<String, Map<String, String>> getUsers()
- {
- return runTask(new Task<Map<String, Map<String, String>>>()
- {
- @Override
- public Map<String, Map<String, String>> execute()
- {
-
- Map<String, Map<String, String>> users = new HashMap<String, Map<String, String>>();
- for (String user : _users.keySet())
- {
- users.put(user, Collections.<String, String>emptyMap());
- }
- return users;
- }
- });
- }
-
- @Override
- public void reload() throws IOException
- {
-
+ return MECHANISM;
}
@Override
- public void recoverUser(final User user)
- {
- _users.put(user.getName(), (ScramAuthUser) user);
- }
-
- protected String createStoredPassword(final String password) throws SaslException
+ protected String getDigestName()
{
- byte[] salt = new byte[32];
- _random.nextBytes(salt);
- byte[] passwordBytes = createSaltedPassword(salt, password);
- return DatatypeConverter.printBase64Binary(salt) + "," + DatatypeConverter.printBase64Binary(passwordBytes);
+ return DIGEST_NAME;
}
@Override
- public <C extends ConfiguredObject> C addChild(final Class<C> childClass,
- final Map<String, Object> attributes,
- final ConfiguredObject... otherParents)
+ protected String getHmacName()
{
- if(childClass == User.class)
- {
- String username = (String) attributes.get("name");
- String password = (String) attributes.get("password");
-
- if(createUser(username, password,null))
- {
- @SuppressWarnings("unchecked")
- C user = (C) _users.get(username);
- return user;
- }
- else
- {
- return null;
-
- }
- }
- return super.addChild(childClass, attributes, otherParents);
+ return HMAC_NAME;
}
- void doDeleted()
- {
- deleted();
- }
-
- Map<String, ScramAuthUser> getUserMap()
- {
- return _users;
- }
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA256AuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA256AuthenticationManager.java
new file mode 100644
index 0000000000..ea5b82fdd5
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA256AuthenticationManager.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.server.security.auth.manager;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+
+@ManagedObject( category = false, type = "SCRAM-SHA-256" )
+public class ScramSHA256AuthenticationManager
+ extends AbstractScramAuthenticationManager<ScramSHA256AuthenticationManager>
+{
+ public static final String PROVIDER_TYPE = "SCRAM-SHA-256";
+ private static final String HMAC_NAME = "HmacSHA256";
+
+ static final Charset ASCII = Charset.forName("ASCII");
+ private static final String MECHANISM = "SCRAM-SHA-256";
+ private static final String DIGEST_NAME = "SHA-256";
+
+
+ @ManagedObjectFactoryConstructor
+ protected ScramSHA256AuthenticationManager(final Map<String, Object> attributes, final Broker broker)
+ {
+ super(attributes, broker);
+ }
+
+ @Override
+ protected String getMechanismName()
+ {
+ return MECHANISM;
+ }
+
+ @Override
+ protected String getDigestName()
+ {
+ return DIGEST_NAME;
+ }
+
+ @Override
+ protected String getHmacName()
+ {
+ return HMAC_NAME;
+ }
+
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
index 71ef386e3e..f510ec32d8 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
@@ -20,13 +20,6 @@
*/
package org.apache.qpid.server.security.auth.sasl.scram;
-import org.apache.qpid.server.security.auth.manager.ScramSHA1AuthenticationManager;
-
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
@@ -35,13 +28,23 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.UUID;
-public class ScramSHA1SaslServer implements SaslServer
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.qpid.server.security.auth.manager.AbstractScramAuthenticationManager;
+
+public class ScramSaslServer implements SaslServer
{
- public static final String MECHANISM = "SCRAM-SHA-1";
+ public final String _mechanism;
+ public final String _hmacName;
+ public final String _digestName;
private static final Charset ASCII = Charset.forName("ASCII");
- private final ScramSHA1AuthenticationManager _authManager;
+ private final AbstractScramAuthenticationManager _authManager;
private State _state = State.INITIAL;
private String _nonce;
private String _username;
@@ -50,9 +53,15 @@ public class ScramSHA1SaslServer implements SaslServer
private String _clientFirstMessageBare;
private byte[] _serverSignature;
- public ScramSHA1SaslServer(final ScramSHA1AuthenticationManager authenticationManager)
+ public ScramSaslServer(final AbstractScramAuthenticationManager authenticationManager,
+ final String mechanism,
+ final String hmacName,
+ final String digestName)
{
_authManager = authenticationManager;
+ _mechanism = mechanism;
+ _hmacName = hmacName;
+ _digestName = digestName;
}
enum State
@@ -65,7 +74,7 @@ public class ScramSHA1SaslServer implements SaslServer
@Override
public String getMechanismName()
{
- return MECHANISM;
+ return _mechanism;
}
@Override
@@ -174,11 +183,11 @@ public class ScramSHA1SaslServer implements SaslServer
byte[] saltedPassword = _authManager.getSaltedPassword(_username);
- byte[] clientKey = computeHmacSHA1(saltedPassword, "Client Key");
+ byte[] clientKey = computeHmac(saltedPassword, "Client Key");
- byte[] storedKey = MessageDigest.getInstance("SHA1").digest(clientKey);
+ byte[] storedKey = MessageDigest.getInstance(_digestName).digest(clientKey);
- byte[] clientSignature = computeHmacSHA1(storedKey, authMessage);
+ byte[] clientSignature = computeHmac(storedKey, authMessage);
byte[] clientProof = clientKey.clone();
for(int i = 0 ; i < clientProof.length; i++)
@@ -190,8 +199,8 @@ public class ScramSHA1SaslServer implements SaslServer
{
throw new SaslException("Authentication failed");
}
- byte[] serverKey = computeHmacSHA1(saltedPassword, "Server Key");
- String finalResponse = "v=" + DatatypeConverter.printBase64Binary(computeHmacSHA1(serverKey, authMessage));
+ byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+ String finalResponse = "v=" + DatatypeConverter.printBase64Binary(computeHmac(serverKey, authMessage));
return finalResponse.getBytes(ASCII);
}
@@ -241,7 +250,7 @@ public class ScramSHA1SaslServer implements SaslServer
}
- private byte[] computeHmacSHA1(final byte[] key, final String string)
+ private byte[] computeHmac(final byte[] key, final String string)
throws SaslException, UnsupportedEncodingException
{
Mac mac = createSha1Hmac(key);
@@ -255,8 +264,8 @@ public class ScramSHA1SaslServer implements SaslServer
{
try
{
- SecretKeySpec key = new SecretKeySpec(keyBytes, "HmacSHA1");
- Mac mac = Mac.getInstance("HmacSHA1");
+ SecretKeySpec key = new SecretKeySpec(keyBytes, _hmacName);
+ Mac mac = Mac.getInstance(_hmacName);
mac.init(key);
return mac;
}