Author: rgodfrey
Date: Tue Jan 12 16:58:26 2016
New Revision: 1724286

URL: http://svn.apache.org/viewvc?rev=1724286&view=rev
Log:
QPID-6993 : Merged to 6.0.x

Modified:
    qpid/java/branches/6.0.x/   (props changed)
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java
    
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java
    
qpid/java/branches/6.0.x/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java

Propchange: qpid/java/branches/6.0.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jan 12 16:58:26 2016
@@ -9,5 +9,5 @@
 /qpid/branches/java-broker-vhost-refactor/java:1493674-1494547
 /qpid/branches/java-network-refactor/qpid/java:805429-821809
 /qpid/branches/qpid-2935/qpid/java:1061302-1072333
-/qpid/java/trunk:1715445-1715447,1715586,1715940,1716086-1716087,1716127-1716128,1716141,1716153,1716155,1716194,1716204,1716209,1716227,1716277,1716357,1716368,1716370,1716374,1716432,1716444-1716445,1716455,1716461,1716474,1716489,1716497,1716515,1716555,1716602,1716606-1716610,1716619,1716636,1717269,1717299,1717401,1717446,1717449,1717626,1717691,1717735,1717780,1718744,1719047,1719051,1720664,1721151,1721198,1722339,1723064,1724257
+/qpid/java/trunk:1715445-1715447,1715586,1715940,1716086-1716087,1716127-1716128,1716141,1716153,1716155,1716194,1716204,1716209,1716227,1716277,1716357,1716368,1716370,1716374,1716432,1716444-1716445,1716455,1716461,1716474,1716489,1716497,1716515,1716555,1716602,1716606-1716610,1716619,1716636,1717269,1717299,1717401,1717446,1717449,1717626,1717691,1717735,1717780,1718744,1719047,1719051,1720664,1721151,1721198,1722339,1723064,1724251,1724257
 /qpid/trunk/qpid:796646-796653

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
 Tue Jan 12 16:58:26 2016
@@ -87,8 +87,8 @@ public class PlainPasswordFilePrincipalD
                     }
                 };
 
-        _scramSha1Adapter = new ScramSaslServerSourceAdapter(4096, "HmacSHA1", 
passwordSource);
-        _scramSha256Adapter = new ScramSaslServerSourceAdapter(4096, 
"HmacSHA256", passwordSource);
+        _scramSha1Adapter = new ScramSaslServerSourceAdapter(4096, "HmacSHA1", 
"SHA-1", passwordSource);
+        _scramSha256Adapter = new ScramSaslServerSourceAdapter(4096, 
"HmacSHA256", "SHA-256", passwordSource);
 
 
     }

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
 Tue Jan 12 16:58:26 2016
@@ -20,7 +20,9 @@
  */
 package org.apache.qpid.server.security.auth.manager;
 
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.security.SecureRandom;
@@ -35,8 +37,12 @@ import javax.security.sasl.SaslException
 import javax.security.sasl.SaslServer;
 import javax.xml.bind.DatatypeConverter;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.Broker;
 import 
org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer;
@@ -59,6 +65,16 @@ public abstract class AbstractScramAuthe
         super(attributes, broker);
     }
 
+    @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, 
State.QUIESCED }, desiredState = State.ACTIVE )
+    protected ListenableFuture<Void> activate()
+    {
+        for(ManagedUser user : getUserMap().values())
+        {
+            updateStoredPasswordFormatIfNecessary(user);
+        }
+        return super.activate();
+    }
+
     @Override
     public List<String> getMechanisms()
     {
@@ -95,17 +111,26 @@ public abstract class AbstractScramAuthe
         ManagedUser user = getUser(username);
         if(user != null)
         {
-            final String[] usernamePassword = user.getPassword().split(",");
+            updateStoredPasswordFormatIfNecessary(user);
+            String[] usernamePassword = user.getPassword().split(",");
             byte[] salt = 
DatatypeConverter.parseBase64Binary(usernamePassword[0]);
             try
             {
-                
if(Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[1]),
-                                 createSaltedPassword(salt, password)))
+                byte[] saltedPassword = createSaltedPassword(salt, password);
+                byte[] clientKey = computeHmac(saltedPassword, "Client Key");
+
+                byte[] storedKey = 
MessageDigest.getInstance(getDigestName()).digest(clientKey);
+
+                byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+
+                
if(Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[2]), 
storedKey)
+                   && 
Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[3]), 
serverKey))
+
                 {
                     return new AuthenticationResult(new 
UsernamePrincipal(username));
                 }
             }
-            catch (IllegalArgumentException e)
+            catch (IllegalArgumentException | NoSuchAlgorithmException e)
             {
                 return new 
AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
             }
@@ -144,7 +169,21 @@ public abstract class AbstractScramAuthe
 
     private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
 
-    public byte[] getSaltedPassword(final String username) throws SaslException
+    private byte[] getStoredKey(final String username) throws SaslException
+    {
+        ManagedUser user = getUser(username);
+        if(user == null)
+        {
+            throw new SaslException("Authentication Failed");
+        }
+        else
+        {
+            updateStoredPasswordFormatIfNecessary(user);
+            return 
DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[2]);
+        }
+    }
+
+    private byte[] getServerKey(final String username) throws SaslException
     {
         ManagedUser user = getUser(username);
         if(user == null)
@@ -153,7 +192,36 @@ public abstract class AbstractScramAuthe
         }
         else
         {
-            return 
DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[1]);
+            updateStoredPasswordFormatIfNecessary(user);
+            return 
DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[2]);
+        }
+    }
+
+
+    private void updateStoredPasswordFormatIfNecessary(final ManagedUser user)
+    {
+        if(user.getPassword().split(",").length<4)
+        {
+            byte[] saltedPassword = 
DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[1]);
+
+            try
+            {
+                byte[] clientKey = computeHmac(saltedPassword, "Client Key");
+
+                byte[] storedKey = 
MessageDigest.getInstance(getDigestName()).digest(clientKey);
+
+                byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+
+                String password = user.getPassword().split(",")[0] + ",,"
+                                  + 
DatatypeConverter.printBase64Binary(storedKey) + ","
+                                  + 
DatatypeConverter.printBase64Binary(serverKey);
+
+                user.setPassword(password);
+            }
+            catch (NoSuchAlgorithmException e)
+            {
+                throw new IllegalArgumentException(e);
+            }
         }
     }
 
@@ -180,6 +248,13 @@ public abstract class AbstractScramAuthe
 
     }
 
+    private byte[] computeHmac(final byte[] key, final String string)
+    {
+        Mac mac = createShaHmac(key);
+        mac.update(string.getBytes(StandardCharsets.US_ASCII));
+        return mac.doFinal();
+    }
+
     private Mac createShaHmac(final byte[] keyBytes)
     {
         try
@@ -200,10 +275,24 @@ public abstract class AbstractScramAuthe
     @Override
     protected String createStoredPassword(final String password)
     {
-        byte[] salt = new byte[32];
-        _random.nextBytes(salt);
-        byte[] passwordBytes = createSaltedPassword(salt, password);
-        return DatatypeConverter.printBase64Binary(salt) + "," + 
DatatypeConverter.printBase64Binary(passwordBytes);
+        try
+        {
+            byte[] salt = new byte[32];
+            _random.nextBytes(salt);
+            byte[] saltedPassword = createSaltedPassword(salt, password);
+            byte[] clientKey = computeHmac(saltedPassword, "Client Key");
+
+            byte[] storedKey = 
MessageDigest.getInstance(getDigestName()).digest(clientKey);
+            byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+
+            return DatatypeConverter.printBase64Binary(salt) + ",,"
+                   + DatatypeConverter.printBase64Binary(storedKey) + ","
+                   + DatatypeConverter.printBase64Binary(serverKey);
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new IllegalArgumentException(e);
+        }
     }
 
     @Override
@@ -219,19 +308,23 @@ public abstract class AbstractScramAuthe
     public SaltAndSaltedPassword getSaltAndSaltedPassword(final String 
username)
     {
         final byte[] salt = getSalt(username);
-        byte[] tmpPassword = null;
         SaslException tmpException = null;
 
+        byte[] tmpStoredKey = null;
+        byte[] tmpServerKey = null;
+
         try
         {
-            tmpPassword = getSaltedPassword(username);
+            tmpStoredKey = getStoredKey(username);
+            tmpServerKey = getServerKey(username);
         }
         catch (SaslException e)
         {
             tmpException = e;
         }
 
-        final byte[] saltedPassword = tmpPassword;
+        final byte[] storedKey = tmpStoredKey;
+        final byte[] serverKey = tmpServerKey;
         final SaslException exception = tmpException;
 
         return new SaltAndSaltedPassword()
@@ -242,17 +335,25 @@ public abstract class AbstractScramAuthe
                 return salt;
             }
 
+
             @Override
-            public byte[] getSaltedPassword() throws SaslException
+            public byte[] getStoredKey() throws SaslException
             {
-                if(exception == null)
+                if(storedKey == null)
                 {
-                    return saltedPassword;
+                    throw exception;
                 }
-                else
+                return storedKey;
+            }
+
+            @Override
+            public byte[] getServerKey() throws SaslException
+            {
+                if(serverKey == null)
                 {
                     throw exception;
                 }
+                return serverKey;
             }
         };
     }

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java
 Tue Jan 12 16:58:26 2016
@@ -47,19 +47,43 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
+import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer;
+import 
org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServerSourceAdapter;
 
 @ManagedObject( category = false, type = "Plain" )
 public class PlainAuthenticationProvider
         extends 
ConfigModelPasswordManagingAuthenticationProvider<PlainAuthenticationProvider>
 {
     private final List<String> _mechanisms = 
Collections.unmodifiableList(Arrays.asList(PlainSaslServer.MECHANISM,
-                                                                               
         CRAMMD5Initialiser.MECHANISM));
+                                                                               
         CRAMMD5Initialiser.MECHANISM,
+                                                                               
         ScramSHA1AuthenticationManager.MECHANISM,
+                                                                               
         ScramSHA256AuthenticationManager.MECHANISM));
+    private final ScramSaslServerSourceAdapter _scramSha1Adapter;
+    private final ScramSaslServerSourceAdapter _scramSha256Adapter;
 
 
     @ManagedObjectFactoryConstructor
     protected PlainAuthenticationProvider(final Map<String, Object> 
attributes, final Broker broker)
     {
         super(attributes, broker);
+
+        ScramSaslServerSourceAdapter.PasswordSource passwordSource =
+                new ScramSaslServerSourceAdapter.PasswordSource()
+                {
+                    @Override
+                    public char[] getPassword(final String username)
+                    {
+                        ManagedUser user = getUser(username);
+
+                        return user == null ? null : 
user.getPassword().toCharArray();
+                    }
+                };
+
+
+
+        _scramSha1Adapter = new ScramSaslServerSourceAdapter(4096, "HmacSHA1", 
"SHA-1", passwordSource);
+        _scramSha256Adapter = new ScramSaslServerSourceAdapter(4096, 
"HmacSHA256", "SHA-256", passwordSource);
+
     }
 
     @Override
@@ -95,6 +119,14 @@ public class PlainAuthenticationProvider
             //simply delegate to the built in CRAM-MD5 SaslServer
             return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, 
new ServerCallbackHandler());
         }
+        else if (ScramSHA1AuthenticationManager.MECHANISM.equals(mechanism))
+        {
+            return new ScramSaslServer(_scramSha1Adapter, mechanism, 
"HmacSHA1", "SHA-1");
+        }
+        else if(ScramSHA256AuthenticationManager.MECHANISM.equals(mechanism))
+        {
+            return new ScramSaslServer(_scramSha256Adapter, mechanism, 
"HmacSHA256", "SHA-256");
+        }
         else
         {
             throw new SaslException("Unsupported mechanism: " + mechanism);

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
 Tue Jan 12 16:58:26 2016
@@ -47,6 +47,8 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
+import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer;
+import 
org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServerSourceAdapter;
 
 @ManagedObject( category = false, type = "Simple", register = false )
 public class SimpleAuthenticationManager extends 
AbstractAuthenticationManager<SimpleAuthenticationManager> implements 
PreferencesSupportingAuthenticationProvider
@@ -55,12 +57,30 @@ public class SimpleAuthenticationManager
 
     private static final String PLAIN_MECHANISM = "PLAIN";
     private static final String CRAM_MD5_MECHANISM = "CRAM-MD5";
+    private static final String SCRAM_SHA1_MECHANISM = 
ScramSHA1AuthenticationManager.MECHANISM;
+    private static final String SCRAM_SHA256_MECHANISM = 
ScramSHA256AuthenticationManager.MECHANISM;
 
     private final Map<String, String> _users = Collections.synchronizedMap(new 
HashMap<String, String>());
+    private final ScramSaslServerSourceAdapter _scramSha1Adapter;
+    private final ScramSaslServerSourceAdapter _scramSha256Adapter;
 
     public SimpleAuthenticationManager(final Map<String, Object> attributes, 
final Broker broker)
     {
         super(attributes, broker);
+        ScramSaslServerSourceAdapter.PasswordSource passwordSource =
+                new ScramSaslServerSourceAdapter.PasswordSource()
+                {
+                    @Override
+                    public char[] getPassword(final String username)
+                    {
+                        String password = _users.get(username);
+                        return password == null ? null : 
password.toCharArray();
+                    }
+                };
+
+        _scramSha1Adapter = new ScramSaslServerSourceAdapter(4096, "HmacSHA1", 
"SHA-1", passwordSource);
+        _scramSha256Adapter = new ScramSaslServerSourceAdapter(4096, 
"HmacSHA256", "SHA-256", passwordSource);
+
     }
 
 
@@ -72,7 +92,7 @@ public class SimpleAuthenticationManager
     @Override
     public List<String> getMechanisms()
     {
-        return Collections.unmodifiableList(Arrays.asList(PLAIN_MECHANISM, 
CRAM_MD5_MECHANISM));
+        return Collections.unmodifiableList(Arrays.asList(PLAIN_MECHANISM, 
CRAM_MD5_MECHANISM, SCRAM_SHA1_MECHANISM, SCRAM_SHA256_MECHANISM));
     }
 
     @Override
@@ -86,6 +106,14 @@ public class SimpleAuthenticationManager
         {
             return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, 
new SimpleCramMd5CallbackHandler());
         }
+        else if (SCRAM_SHA1_MECHANISM.equals(mechanism))
+        {
+            return new ScramSaslServer(_scramSha1Adapter, mechanism, 
"HmacSHA1", "SHA-1");
+        }
+        else if(ScramSHA256AuthenticationManager.MECHANISM.equals(mechanism))
+        {
+            return new ScramSaslServer(_scramSha256Adapter, mechanism, 
"HmacSHA256", "SHA-256");
+        }
         else
         {
             throw new SaslException("Unknown mechanism: " + mechanism);

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
 Tue Jan 12 16:58:26 2016
@@ -34,8 +34,6 @@ 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 final String _mechanism;
@@ -188,25 +186,24 @@ public class ScramSaslServer implements
 
             String authMessage = _clientFirstMessageBare + "," + 
_serverFirstMessage + "," + clientFinalMessageWithoutProof;
 
-            byte[] saltedPassword = _saltAndPassword.getSaltedPassword();
-
-            byte[] clientKey = computeHmac(saltedPassword, "Client Key");
 
-            byte[] storedKey = 
MessageDigest.getInstance(_digestName).digest(clientKey);
+            byte[] storedKey = _saltAndPassword.getStoredKey();
 
             byte[] clientSignature = computeHmac(storedKey, authMessage);
 
-            byte[] clientProof = clientKey.clone();
-            for(int i = 0 ; i < clientProof.length; i++)
+            for(int i = 0 ; i < proofBytes.length; i++)
             {
-                clientProof[i] ^= clientSignature[i];
+                proofBytes[i] ^= clientSignature[i];
             }
 
-            if(!Arrays.equals(clientProof, proofBytes))
+            final byte[] storedKeyFromClient = 
MessageDigest.getInstance(_digestName).digest(proofBytes);
+
+            if(!Arrays.equals(storedKeyFromClient, storedKey))
             {
                 throw new SaslException("Authentication failed");
             }
-            byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+
+            byte[] serverKey = _saltAndPassword.getServerKey();
             String finalResponse = "v=" + 
DatatypeConverter.printBase64Binary(computeHmac(serverKey, authMessage));
 
             return finalResponse.getBytes(ASCII);
@@ -260,13 +257,13 @@ public class ScramSaslServer implements
     private byte[] computeHmac(final byte[] key, final String string)
             throws SaslException, UnsupportedEncodingException
     {
-        Mac mac = createSha1Hmac(key);
+        Mac mac = createShaHmac(key);
         mac.update(string.getBytes(ASCII));
         return mac.doFinal();
     }
 
 
-    private Mac createSha1Hmac(final byte[] keyBytes)
+    private Mac createShaHmac(final byte[] keyBytes)
             throws SaslException
     {
         try

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java
 Tue Jan 12 16:58:26 2016
@@ -30,7 +30,9 @@ public interface ScramSaslServerSource
     {
         byte[] getSalt();
 
-        byte[] getSaltedPassword() throws SaslException;
+        byte[] getStoredKey() throws SaslException;
+
+        byte[] getServerKey() throws SaslException;
     }
 
     SaltAndSaltedPassword getSaltAndSaltedPassword(String username);

Modified: 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java
 Tue Jan 12 16:58:26 2016
@@ -20,7 +20,9 @@
  */
 package org.apache.qpid.server.security.auth.sasl.scram;
 
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 
@@ -28,8 +30,6 @@ import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 import javax.security.sasl.SaslException;
 
-import 
org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
-
 public class ScramSaslServerSourceAdapter implements ScramSaslServerSource
 {
     private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
@@ -38,6 +38,7 @@ public class ScramSaslServerSourceAdapte
     private final String _hmacName;
     private final SecureRandom _random = new SecureRandom();
     private final PasswordSource _passwordSource;
+    private final String _digestName;
 
     public interface PasswordSource
     {
@@ -46,11 +47,13 @@ public class ScramSaslServerSourceAdapte
 
     public ScramSaslServerSourceAdapter(final int iterationCount,
                                         final String hmacName,
+                                        final String digestName,
                                         final PasswordSource passwordSource)
     {
         _iterationCount = iterationCount;
         _hmacName = hmacName;
         _passwordSource = passwordSource;
+        _digestName = digestName;
     }
 
     @Override
@@ -59,69 +62,112 @@ public class ScramSaslServerSourceAdapte
         return _iterationCount;
     }
 
+    private Mac createShaHmac(final byte[] keyBytes)
+    {
+        try
+        {
+            SecretKeySpec key = new SecretKeySpec(keyBytes, _hmacName);
+            Mac mac = Mac.getInstance(_hmacName);
+            mac.init(key);
+            return mac;
+        }
+        catch (NoSuchAlgorithmException | InvalidKeyException e)
+        {
+            throw new IllegalArgumentException(e.getMessage(), e);
+        }
+    }
+
+    private byte[] computeHmac(final byte[] key, final String string)
+    {
+        Mac mac = createShaHmac(key);
+        mac.update(string.getBytes(StandardCharsets.US_ASCII));
+        return mac.doFinal();
+    }
+
     @Override
     public SaltAndSaltedPassword getSaltAndSaltedPassword(final String 
username)
     {
         final char[] password = _passwordSource.getPassword(username);
-
+        final byte[] storedKey;
+        final byte[] serverKey;
         final byte[] salt = new byte[32];
         _random.nextBytes(salt);
-        return new SaltAndSaltedPassword()
-        {
-            @Override
-            public byte[] getSalt()
-            {
-                return salt;
-            }
 
-            @Override
-            public byte[] getSaltedPassword() throws SaslException
+        if(password != null)
+        {
+            try
             {
-                if(password == null)
-                {
-                    throw new SaslException("Authentication Failed");
-                }
                 byte[] passwordAsBytes = new byte[password.length];
-                for(int i = 0; i< password.length; i++)
+                for (int i = 0; i < password.length; i++)
                 {
                     passwordAsBytes[i] = (byte) password[i];
                 }
+
                 Mac mac = createShaHmac(passwordAsBytes);
 
                 mac.update(salt);
                 mac.update(INT_1);
-                byte[] result = mac.doFinal();
+                byte[] saltedPassword = mac.doFinal();
 
                 byte[] previous = null;
-                for(int i = 1; i < getIterationCount(); i++)
+                for (int i = 1; i < getIterationCount(); i++)
                 {
-                    mac.update(previous != null? previous: result);
+                    mac.update(previous != null ? previous : saltedPassword);
                     previous = mac.doFinal();
-                    for(int x = 0; x < result.length; x++)
+                    for (int x = 0; x < saltedPassword.length; x++)
                     {
-                        result[x] ^= previous[x];
+                        saltedPassword[x] ^= previous[x];
                     }
                 }
 
-                return result;
+                byte[] clientKey = computeHmac(saltedPassword, "Client Key");
 
+                storedKey = 
MessageDigest.getInstance(_digestName).digest(clientKey);
+
+                serverKey = computeHmac(saltedPassword, "Server Key");
+            }
+            catch (NoSuchAlgorithmException e)
+            {
+                throw new IllegalArgumentException(e);
+            }
+
+        }
+        else
+        {
+            storedKey = null;
+            serverKey = null;
+        }
+
+        return new SaltAndSaltedPassword()
+        {
+            @Override
+            public byte[] getSalt()
+            {
+                return salt;
             }
 
-            private Mac createShaHmac(final byte[] keyBytes)
+            @Override
+            public byte[] getStoredKey() throws SaslException
             {
-                try
+                if(storedKey == null)
                 {
-                    SecretKeySpec key = new SecretKeySpec(keyBytes, _hmacName);
-                    Mac mac = Mac.getInstance(_hmacName);
-                    mac.init(key);
-                    return mac;
+                    throw new SaslException("Authentication Failed");
                 }
-                catch (NoSuchAlgorithmException | InvalidKeyException e)
+                return storedKey;
+            }
+
+            @Override
+            public byte[] getServerKey() throws SaslException
+            {
+
+                if(serverKey == null)
                 {
-                    throw new IllegalArgumentException(e.getMessage(), e);
+                    throw new SaslException("Authentication Failed");
                 }
+                return serverKey;
             }
 
+
         };
     }
 }

Modified: 
qpid/java/branches/6.0.x/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java
URL: 
http://svn.apache.org/viewvc/qpid/java/branches/6.0.x/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java?rev=1724286&r1=1724285&r2=1724286&view=diff
==============================================================================
--- 
qpid/java/branches/6.0.x/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java
 (original)
+++ 
qpid/java/branches/6.0.x/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java
 Tue Jan 12 16:58:26 2016
@@ -60,9 +60,11 @@ public class SimpleAuthenticationManager
     public void testGetMechanisms()
     {
         List<String> mechanisms = _authenticationManager.getMechanisms();
-        assertEquals("Unexpected number of mechanisms", 2, mechanisms.size());
-        assertTrue("PLAIN was not present", mechanisms.contains("PLAIN"));
-        assertTrue("CRAM-MD5 was not present", 
mechanisms.contains("CRAM-MD5"));
+        assertEquals("Unexpected number of mechanisms", 4, mechanisms.size());
+        assertTrue("PLAIN was not present: " + mechanisms, 
mechanisms.contains("PLAIN"));
+        assertTrue("CRAM-MD5 was not present: " + mechanisms, 
mechanisms.contains("CRAM-MD5"));
+        assertTrue("SCRAM-SHA-1 was not present: " + mechanisms, 
mechanisms.contains("SCRAM-SHA-1"));
+        assertTrue("SCRAM-SHA-256 was not present: " + mechanisms, 
mechanisms.contains("SCRAM-SHA-256"));
     }
 
     public void testCreateSaslServerForUnsupportedMechanisms() throws Exception



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to