You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2016/12/02 15:47:52 UTC

svn commit: r1772364 [2/4] - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/model/ broker-core/src/main/java/org/apache/qpid/server/security/ broker-core/src/main/java/org/apache/qpid/server/security/auth/database/ broker-core/sr...

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java Fri Dec  2 15:47:52 2016
@@ -20,24 +20,13 @@
 package org.apache.qpid.server.security.auth.manager;
 
 import java.io.IOException;
-import java.security.Principal;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.AccountNotFoundException;
-import javax.security.sasl.AuthorizeCallback;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,9 +36,12 @@ import org.apache.qpid.server.model.Mana
 import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
 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.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.PasswordSource;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+import org.apache.qpid.server.security.auth.sasl.SaslSettings;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CramMd5Negotiator;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainNegotiator;
+import org.apache.qpid.server.security.auth.sasl.scram.ScramNegotiator;
 import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServerSourceAdapter;
 
 @ManagedObject( category = false, type = "Simple", register = false )
@@ -76,24 +68,19 @@ public class SimpleAuthenticationManager
     protected void postResolveChildren()
     {
         super.postResolveChildren();
-        ScramSaslServerSourceAdapter.PasswordSource passwordSource =
-                new ScramSaslServerSourceAdapter.PasswordSource()
-                {
-                    @Override
-                    public char[] getPassword(final String username)
-                    {
-                        String password = _users.get(username);
-                        return password == null ? null : password.toCharArray();
-                    }
-                };
+        PasswordSource passwordSource = getPasswordSource();
 
         final int scramIterationCount = getContextValue(Integer.class, AbstractScramAuthenticationManager.QPID_AUTHMANAGER_SCRAM_ITERATION_COUNT);
-        _scramSha1Adapter = new ScramSaslServerSourceAdapter(scramIterationCount, "HmacSHA1", "SHA-1", passwordSource);
-        _scramSha256Adapter = new ScramSaslServerSourceAdapter(scramIterationCount, "HmacSHA256", "SHA-256", passwordSource);
-
+        _scramSha1Adapter = new ScramSaslServerSourceAdapter(scramIterationCount,
+                                                             ScramSHA1AuthenticationManager.HMAC_NAME,
+                                                             ScramSHA1AuthenticationManager.DIGEST_NAME,
+                                                             passwordSource);
+        _scramSha256Adapter = new ScramSaslServerSourceAdapter(scramIterationCount,
+                                                               ScramSHA256AuthenticationManager.HMAC_NAME,
+                                                               ScramSHA256AuthenticationManager.DIGEST_NAME,
+                                                               passwordSource);
     }
 
-
     public void addUser(String username, String password)
     {
         createUser(username, password, Collections.EMPTY_MAP);
@@ -106,53 +93,29 @@ public class SimpleAuthenticationManager
     }
 
     @Override
-    public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+    public SaslNegotiator createSaslNegotiator(final String mechanism, final SaslSettings saslSettings)
     {
-        if (PLAIN_MECHANISM.equals(mechanism))
+        if (PlainNegotiator.MECHANISM.equals(mechanism))
         {
-            return new PlainSaslServer(new SimplePlainCallbackHandler());
+            return new PlainNegotiator(this);
         }
-        else if (CRAM_MD5_MECHANISM.equals(mechanism))
+        else if (CramMd5Negotiator.MECHANISM.equals(mechanism))
         {
-            return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new SimpleCramMd5CallbackHandler());
+            return new CramMd5Negotiator(this,
+                                         saslSettings.getLocalFQDN(),
+                                         getPasswordSource());
         }
-        else if (SCRAM_SHA1_MECHANISM.equals(mechanism))
+        else if (ScramSHA1AuthenticationManager.MECHANISM.equals(mechanism))
         {
-            return new ScramSaslServer(_scramSha1Adapter, mechanism, "HmacSHA1", "SHA-1");
+            return new ScramNegotiator(this, _scramSha1Adapter, ScramSHA1AuthenticationManager.MECHANISM);
         }
-        else if(ScramSHA256AuthenticationManager.MECHANISM.equals(mechanism))
+        else if (ScramSHA256AuthenticationManager.MECHANISM.equals(mechanism))
         {
-            return new ScramSaslServer(_scramSha256Adapter, mechanism, "HmacSHA256", "SHA-256");
+            return new ScramNegotiator(this, _scramSha256Adapter, ScramSHA256AuthenticationManager.MECHANISM);
         }
         else
         {
-            throw new SaslException("Unknown mechanism: " + mechanism);
-        }
-    }
-
-    @Override
-    public AuthenticationResult authenticate(SaslServer server, byte[] response)
-    {
-        try
-        {
-            // Process response from the client
-            byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
-
-            if (server.isComplete())
-            {
-                String authorizationID = server.getAuthorizationID();
-                _logger.debug("Authenticated as " + authorizationID);
-
-                return new AuthenticationResult(new UsernamePrincipal(authorizationID, this), challenge);
-            }
-            else
-            {
-                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
-            }
-        }
-        catch (SaslException e)
-        {
-            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+            return null;
         }
     }
 
@@ -215,70 +178,16 @@ public class SimpleAuthenticationManager
     {
     }
 
-    private class SimpleCramMd5CallbackHandler implements CallbackHandler
-    {
-        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
-        {
-            String username = null;
-            for (Callback callback : callbacks)
-            {
-                if (callback instanceof NameCallback)
-                {
-                    username = ((NameCallback) callback).getDefaultName();
-                }
-                else if (callback instanceof PasswordCallback)
-                {
-                    if (_users.containsKey(username))
-                    {
-                        String password = _users.get(username);
-                        ((PasswordCallback) callback).setPassword(password.toCharArray());
-                    }
-                    else
-                    {
-                        throw new SaslException("Authentication failed");
-                    }
-                }
-                else if (callback instanceof AuthorizeCallback)
-                {
-                    ((AuthorizeCallback) callback).setAuthorized(true);
-                }
-                else
-                {
-                    throw new UnsupportedCallbackException(callback);
-                }
-            }
-        }
-    }
-
-    private class SimplePlainCallbackHandler implements CallbackHandler
+    private PasswordSource getPasswordSource()
     {
-        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+        return new PasswordSource()
         {
-            String username = null;
-             for (Callback callback : callbacks)
+            @Override
+            public char[] getPassword(final String username)
             {
-                if (callback instanceof NameCallback)
-                {
-                    username = ((NameCallback) callback).getDefaultName();
-                }
-                else if (callback instanceof PlainPasswordCallback)
-                {
-                    if (_users.containsKey(username))
-                    {
-                        PlainPasswordCallback plainPasswordCallback = (PlainPasswordCallback) callback;
-                        String password = plainPasswordCallback.getPlainPassword();
-                        plainPasswordCallback.setAuthenticated(password.equals(_users.get(username)));
-                    }
-                }
-                else if (callback instanceof AuthorizeCallback)
-                {
-                    ((AuthorizeCallback) callback).setAuthorized(true);
-                }
-                else
-                {
-                    throw new UnsupportedCallbackException(callback);
-                }
+                String password = _users.get(username);
+                return password == null ? null : password.toCharArray();
             }
-        }
+        };
     }
 }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java Fri Dec  2 15:47:52 2016
@@ -23,7 +23,6 @@ import static java.util.Collections.disj
 import static java.util.Collections.singletonList;
 import static java.util.Collections.unmodifiableList;
 
-import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.Principal;
 import java.util.Arrays;
@@ -48,13 +47,6 @@ import javax.naming.directory.SearchResu
 import javax.net.SocketFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.AuthorizeCallback;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.slf4j.Logger;
@@ -72,8 +64,9 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.manager.ldap.AbstractLDAPSSLSocketFactory;
 import org.apache.qpid.server.security.auth.manager.ldap.LDAPSSLSocketFactoryGenerator;
-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.SaslNegotiator;
+import org.apache.qpid.server.security.auth.sasl.SaslSettings;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainNegotiator;
 import org.apache.qpid.server.security.group.GroupPrincipal;
 import org.apache.qpid.server.util.CipherSuiteAndProtocolRestrictingSSLSocketFactory;
 import org.apache.qpid.server.util.ParameterizedTypes;
@@ -287,50 +280,19 @@ public class SimpleLDAPAuthenticationMan
     @Override
     public List<String> getMechanisms()
     {
-        return singletonList(PlainSaslServer.MECHANISM);
+        return singletonList(PlainNegotiator.MECHANISM);
     }
 
     @Override
-    public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+    public SaslNegotiator createSaslNegotiator(final String mechanism, final SaslSettings saslSettings)
     {
-        if(PlainSaslServer.MECHANISM.equals(mechanism))
+        if(PlainNegotiator.MECHANISM.equals(mechanism))
         {
-            return new PlainSaslServer(new SimpleLDAPPlainCallbackHandler());
+            return new PlainNegotiator(this);
         }
         else
         {
-            throw new SaslException("Unknown mechanism: " + mechanism);
-        }
-    }
-
-    @Override
-    public AuthenticationResult authenticate(SaslServer server, byte[] response)
-    {
-        try
-        {
-            // Process response from the client
-            byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
-
-            if (server.isComplete())
-            {
-                String authorizationID = server.getAuthorizationID();
-                _logger.debug("Authenticated as {}", authorizationID);
-
-                AuthenticationResult result = (AuthenticationResult)server.getNegotiatedProperty(PlainSaslServer.AUTHENTICATION_RESULT);
-                if (result == null)
-                {
-                    return new AuthenticationResult(AuthenticationStatus.ERROR);
-                }
-                return new AuthenticationResult(result.getMainPrincipal(), result.getPrincipals(), challenge);
-            }
-            else
-            {
-                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
-            }
-        }
-        catch (SaslException e)
-        {
-            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+            return null;
         }
     }
 
@@ -356,7 +318,7 @@ public class SimpleLDAPAuthenticationMan
         if(name == null)
         {
             //The search didn't return anything, class as not-authenticated before it NPEs below
-            return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+            return new AuthenticationResult(AuthenticationStatus.ERROR);
         }
 
         String providerAuthUrl = isSpecified(getProviderAuthUrl()) ? getProviderAuthUrl() : getProviderUrl();
@@ -388,7 +350,7 @@ public class SimpleLDAPAuthenticationMan
         catch(AuthenticationException ae)
         {
             //Authentication failed
-            return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+            return new AuthenticationResult(AuthenticationStatus.ERROR);
         }
         catch (NamingException e)
         {
@@ -642,53 +604,6 @@ public class SimpleLDAPAuthenticationMan
         }
     }
 
-
-    private class SimpleLDAPPlainCallbackHandler implements CallbackHandler
-    {
-        @Override
-        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
-        {
-            String userId = null;
-            String password = null;
-            AuthenticationResult authenticated = null;
-            for(Callback callback : callbacks)
-            {
-                if (callback instanceof NameCallback)
-                {
-                    userId = ((NameCallback) callback).getDefaultName();
-                    if(password != null)
-                    {
-                        authenticated = getOrLoadAuthenticationResult(userId, password);
-                    }
-                }
-                else if (callback instanceof PlainPasswordCallback)
-                {
-                    password = ((PlainPasswordCallback)callback).getPlainPassword();
-                    if (userId != null)
-                    {
-                        authenticated = getOrLoadAuthenticationResult(userId, password);
-                        if(authenticated.getStatus()== AuthenticationResult.AuthenticationStatus.SUCCESS)
-                        {
-                            ((PlainPasswordCallback)callback).setAuthenticated(true);
-                        }
-                    }
-                }
-                else if (callback instanceof AuthorizeCallback)
-                {
-                    ((AuthorizeCallback) callback).setAuthorized(authenticated != null && authenticated.getStatus() == AuthenticationResult.AuthenticationStatus.SUCCESS);
-                    if (callback instanceof PlainSaslServer.AuthenticationResultPreservingAuthorizeCallback)
-                    {
-                        ((PlainSaslServer.AuthenticationResultPreservingAuthorizeCallback)callback).setAuthenticationResult(authenticated);
-                    }
-                }
-                else
-                {
-                    throw new UnsupportedCallbackException(callback);
-                }
-            }
-        }
-    }
-
     private String getNameFromId(String id) throws NamingException
     {
         if(!isBindWithoutSearch())

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java Fri Dec  2 15:47:52 2016
@@ -36,8 +36,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
 import javax.xml.bind.DatatypeConverter;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -56,6 +54,9 @@ import org.apache.qpid.server.plugin.Qpi
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.security.auth.manager.AbstractAuthenticationManager;
 import org.apache.qpid.server.security.auth.manager.AuthenticationResultCacher;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+import org.apache.qpid.server.security.auth.sasl.SaslSettings;
+import org.apache.qpid.server.security.auth.sasl.oauth2.OAuth2Negotiator;
 import org.apache.qpid.server.util.ConnectionBuilder;
 import org.apache.qpid.server.util.ParameterizedTypes;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -213,47 +214,13 @@ public class OAuth2AuthenticationProvide
     @Override
     public List<String> getMechanisms()
     {
-        return Collections.singletonList(OAuth2SaslServer.MECHANISM);
+        return Collections.singletonList(OAuth2Negotiator.MECHANISM);
     }
 
     @Override
-    public SaslServer createSaslServer(final String mechanism,
-                                       final String localFQDN,
-                                       final Principal externalPrincipal)
-            throws SaslException
+    public SaslNegotiator createSaslNegotiator(final String mechanism, final SaslSettings saslSettings)
     {
-        if(OAuth2SaslServer.MECHANISM.equals(mechanism))
-        {
-            return new OAuth2SaslServer();
-        }
-        else
-        {
-            throw new SaslException("Unknown mechanism: " + mechanism);
-        }
-    }
-
-    @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())
-            {
-                String accessToken = (String) server.getNegotiatedProperty(OAuth2SaslServer.ACCESS_TOKEN_PROPERTY);
-                return authenticateViaAccessToken(accessToken);
-            }
-            else
-            {
-                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
-            }
-        }
-        catch (SaslException e)
-        {
-            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
-        }
+        return new OAuth2Negotiator(this);
     }
 
     @Override

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/AbstractSaslServerNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/AbstractSaslServerNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/AbstractSaslServerNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/AbstractSaslServerNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,90 @@
+/*
+ * 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.sasl;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+
+public abstract class AbstractSaslServerNegotiator implements SaslNegotiator
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSaslServerNegotiator.class);
+
+    @Override
+    public void dispose()
+    {
+        SaslServer saslServer = getSaslServer();
+        if (saslServer != null)
+        {
+            try
+            {
+                saslServer.dispose();
+            }
+            catch (SaslException e)
+            {
+                LOGGER.warn("Disposing of SaslServer failed", e);
+            }
+        }
+    }
+
+    @Override
+    public AuthenticationResult handleResponse(final byte[] response)
+    {
+        SaslServer saslServer = getSaslServer();
+        if (saslServer == null)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, getSaslServerCreationException());
+        }
+        try
+        {
+
+            byte[] challenge = saslServer.evaluateResponse(response != null ? response : new byte[0]);
+
+            if (saslServer.isComplete())
+            {
+                final String userId = saslServer.getAuthorizationID();
+                return new AuthenticationResult(new UsernamePrincipal(userId, getAuthenticationProvider()),
+                                                challenge);
+            }
+            else
+            {
+                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+            }
+        }
+        catch (SaslException | IllegalStateException e)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+        }
+    }
+
+    protected abstract Exception getSaslServerCreationException();
+
+    protected abstract SaslServer getSaslServer();
+
+    protected abstract AuthenticationProvider<?> getAuthenticationProvider();
+}

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/PasswordSource.java (from r1772329, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainInitialiser.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/PasswordSource.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/PasswordSource.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainInitialiser.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainInitialiser.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/PasswordSource.java Fri Dec  2 15:47:52 2016
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -7,9 +6,9 @@
  * 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
@@ -18,14 +17,10 @@
  * under the License.
  *
  */
-package org.apache.qpid.server.security.auth.sasl.plain;
 
-import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+package org.apache.qpid.server.security.auth.sasl;
 
-public class PlainInitialiser extends UsernamePasswordInitialiser
+public interface PasswordSource
 {
-    public String getMechanismName()
-    {
-        return "PLAIN";
-    }
+    char[] getPassword(String username);
 }

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslNegotiator.java (from r1772329, qpid/java/trunk/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SaslServerProvider.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslNegotiator.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslNegotiator.java&p1=qpid/java/trunk/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SaslServerProvider.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SaslServerProvider.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslNegotiator.java Fri Dec  2 15:47:52 2016
@@ -15,15 +15,16 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
+ *
  */
 
-package org.apache.qpid.server.protocol.v1_0;
+package org.apache.qpid.server.security.auth.sasl;
 
+import org.apache.qpid.server.security.auth.AuthenticationResult;
 
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
-public interface SaslServerProvider
+public interface SaslNegotiator
 {
-    SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException;
+    AuthenticationResult handleResponse(byte[] response);
+
+    void dispose();
 }

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslSettings.java (from r1772329, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5Initialiser.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslSettings.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslSettings.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5Initialiser.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5Initialiser.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/SaslSettings.java Fri Dec  2 15:47:52 2016
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -7,9 +6,9 @@
  * 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
@@ -18,16 +17,15 @@
  * under the License.
  *
  */
-package org.apache.qpid.server.security.auth.sasl.crammd5;
 
-import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+package org.apache.qpid.server.security.auth.sasl;
+
+
+import java.security.Principal;
 
-public class CRAMMD5Initialiser extends UsernamePasswordInitialiser
+public interface SaslSettings
 {
-    public static final String MECHANISM = "CRAM-MD5";
+    String getLocalFQDN();
 
-    public String getMechanismName()
-    {
-        return MECHANISM;
-    }
+    Principal getExternalPrincipal();
 }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,57 @@
+/*
+ * 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.sasl.anonymous;
+
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+
+public class AnonymousNegotiator implements SaslNegotiator
+{
+    private final AuthenticationResult _anonymousAuthenticationResult;
+    private volatile boolean _isComplete;
+
+    public AnonymousNegotiator(final AuthenticationResult anonymousAuthenticationResult)
+    {
+        _anonymousAuthenticationResult = anonymousAuthenticationResult;
+    }
+
+    @Override
+    public AuthenticationResult handleResponse(final byte[] response)
+    {
+        if (_isComplete)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalStateException(
+                                                    "Multiple Authentications not permitted."));
+        }
+        else
+        {
+            _isComplete = true;
+        }
+        return _anonymousAuthenticationResult;
+    }
+
+    @Override
+    public void dispose()
+    {
+
+    }
+}

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/AbstractCramMd5Negotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/AbstractCramMd5Negotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/AbstractCramMd5Negotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/AbstractCramMd5Negotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,179 @@
+/*
+ * 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.sasl.crammd5;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+import org.apache.qpid.server.security.auth.sasl.AbstractSaslServerNegotiator;
+
+public class AbstractCramMd5Negotiator extends AbstractSaslServerNegotiator implements SaslNegotiator
+{
+    protected static final PasswordTransformer PLAIN_PASSWORD_TRANSFORMER =
+            new PasswordTransformer()
+            {
+                @Override
+                public char[] transform(final char[] passwordData)
+                {
+                    return passwordData;
+                }
+            };
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCramMd5Negotiator.class);
+
+    private final SaslServer _saslServer;
+    private final SaslException _exception;
+    private final PasswordCredentialManagingAuthenticationProvider<?> _authenticationProvider;
+
+    AbstractCramMd5Negotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                              String localFQDN,
+                              final PasswordSource passwordSource,
+                              final PasswordTransformer passwordTransformer)
+    {
+        _authenticationProvider = authenticationProvider;
+        SaslServer saslServer = null;
+        SaslException exception = null;
+        try
+        {
+            saslServer = Sasl.createSaslServer("CRAM-MD5",
+                                               "AMQP",
+                                               localFQDN,
+                                               null,
+                                               new ServerCallbackHandler(passwordSource, passwordTransformer));
+        }
+        catch (SaslException e)
+        {
+            exception = e;
+            LOGGER.warn("Creation of SASL server for mechanism '{}' failed.", "CRAM-MD5", e);
+        }
+        _saslServer = saslServer;
+        _exception = exception;
+    }
+
+    @Override
+    protected Exception getSaslServerCreationException()
+    {
+        return _exception;
+    }
+
+    @Override
+    protected SaslServer getSaslServer()
+    {
+        return _saslServer;
+    }
+
+    @Override
+    protected AuthenticationProvider<?> getAuthenticationProvider()
+    {
+        return _authenticationProvider;
+    }
+
+    private static class ServerCallbackHandler implements CallbackHandler
+    {
+        private final PasswordSource _passwordSource;
+        private final PasswordTransformer _passwordTransformer;
+
+        private String _username;
+
+        private ServerCallbackHandler(PasswordSource passwordSource, PasswordTransformer passwordTransformer)
+        {
+            _passwordTransformer = passwordTransformer;
+            _passwordSource = passwordSource;
+        }
+
+        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+        {
+            List<Callback> callbackList = new ArrayList<>(Arrays.asList(callbacks));
+            Iterator<Callback> iter = callbackList.iterator();
+            while (iter.hasNext())
+            {
+                Callback callback = iter.next();
+                if (callback instanceof NameCallback)
+                {
+                    _username = ((NameCallback) callback).getDefaultName();
+                    iter.remove();
+                    break;
+                }
+            }
+
+            if (_username != null)
+            {
+                iter = callbackList.iterator();
+                while (iter.hasNext())
+                {
+                    Callback callback = iter.next();
+                    if (callback instanceof PasswordCallback)
+                    {
+                        iter.remove();
+                        char[] passwordData = _passwordSource.getPassword(_username);
+                        if (passwordData != null)
+                        {
+                            ((PasswordCallback) callback).setPassword(_passwordTransformer.transform(passwordData));
+                        }
+                        else
+                        {
+                            ((PasswordCallback) callback).setPassword(null);
+                        }
+                        break;
+                    }
+                }
+            }
+
+            for (Callback callback : callbackList)
+            {
+
+                if (callback instanceof AuthorizeCallback)
+                {
+                    ((AuthorizeCallback) callback).setAuthorized(true);
+                }
+                else
+                {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        }
+    }
+
+    interface PasswordTransformer
+    {
+        char[] transform(char[] passwordData);
+    }
+}

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,52 @@
+/*
+ * 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.sasl.crammd5;
+
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
+import org.apache.qpid.util.Strings;
+
+public class CramMd5Base64HashedNegotiator extends AbstractCramMd5Negotiator
+{
+    public static final String MECHANISM = "CRAM-MD5-HASHED";
+    private static final PasswordTransformer BASE64_PASSWORD_TRANSFORMER =
+            new PasswordTransformer()
+            {
+                @Override
+                public char[] transform(final char[] passwordData)
+                {
+                    byte[] passwordBytes = Strings.decodeBase64(new String(passwordData));
+                    char[] password = new char[passwordBytes.length];
+                    for (int i = 0; i < passwordBytes.length; i++)
+                    {
+                        password[i] = (char) passwordBytes[i];
+                    }
+                    return password;
+                }
+            };
+
+    public CramMd5Base64HashedNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                                         final String localFQDN,
+                                         final PasswordSource passwordSource)
+    {
+        super(authenticationProvider, localFQDN, passwordSource, BASE64_PASSWORD_TRANSFORMER);
+    }
+}

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,57 @@
+/*
+ * 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.sasl.crammd5;
+
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
+import org.apache.qpid.util.Strings;
+
+public class CramMd5Base64HexNegotiator extends AbstractCramMd5Negotiator
+{
+    public static final String MECHANISM = "CRAM-MD5-HEX";
+    private static final PasswordTransformer BASE64_HEX_PASSWORD_TRANSFORMER =
+            new PasswordTransformer()
+            {
+                private final char[] HEX_CHARACTERS =
+                        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+                @Override
+                public char[] transform(final char[] passwordData)
+                {
+                    byte[] passwordBytes = Strings.decodeBase64(new String(passwordData));
+                    char[] password = new char[passwordBytes.length * 2];
+
+                    for (int i = 0; i < passwordBytes.length; i++)
+                    {
+                        password[2 * i] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0xf0) >> 4];
+                        password[(2 * i) + 1] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0x0f)];
+                    }
+                    return password;
+                }
+            };
+
+    public CramMd5Base64HexNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                                      final String localFQDN,
+                                      final PasswordSource passwordSource)
+    {
+        super(authenticationProvider, localFQDN, passwordSource, BASE64_HEX_PASSWORD_TRANSFORMER);
+    }
+}

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HashedNegotiator.java (from r1772329, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HashedNegotiator.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HashedNegotiator.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HashedNegotiator.java Fri Dec  2 15:47:52 2016
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -7,9 +6,9 @@
  * 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
@@ -18,20 +17,20 @@
  * under the License.
  *
  */
+
 package org.apache.qpid.server.security.auth.sasl.crammd5;
 
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
 
-public class CRAMMD5HashedInitialiser extends UsernamePasswordInitialiser
+public class CramMd5HashedNegotiator extends AbstractCramMd5Negotiator
 {
-    public String getMechanismName()
-    {
-        return CRAMMD5HashedSaslServer.MECHANISM;
-    }
+    public static final String MECHANISM = "CRAM-MD5-HASHED";
 
-    public void initialise(PrincipalDatabase passwordFile)
+    public CramMd5HashedNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                                   final String localFQDN,
+                                   final PasswordSource passwordSource)
     {
-        super.initialise(passwordFile);
+        super(authenticationProvider, localFQDN, passwordSource, PLAIN_PASSWORD_TRANSFORMER);
     }
 }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HexNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HexNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HexNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5HexNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,63 @@
+/*
+ * 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.sasl.crammd5;
+
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
+
+public class CramMd5HexNegotiator extends AbstractCramMd5Negotiator
+{
+    public static final String MECHANISM = "CRAM-MD5-HEX";
+    private static final PasswordTransformer HEX_PASSWORD_TRANSFORMER =
+            new PasswordTransformer()
+            {
+
+                @Override
+                public char[] transform(final char[] password)
+                {
+                    StringBuilder sb = new StringBuilder();
+                    for (char c : password)
+                    {
+                        //toHexString does not prepend 0 so we have to
+                        if (((byte) c > -1) && (byte) c < 0x10)
+                        {
+                            sb.append(0);
+                        }
+
+                        sb.append(Integer.toHexString(c & 0xFF));
+                    }
+
+                    //Extract the hex string as char[]
+                    char[] hex = new char[sb.length()];
+
+                    sb.getChars(0, sb.length(), hex, 0);
+
+                    return hex;
+                }
+            };
+
+    public CramMd5HexNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                                final String localFQDN,
+                                final PasswordSource passwordSource)
+    {
+        super(authenticationProvider, localFQDN, passwordSource, HEX_PASSWORD_TRANSFORMER);
+    }
+}

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Negotiator.java (from r1772329, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Negotiator.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Negotiator.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Negotiator.java Fri Dec  2 15:47:52 2016
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -7,9 +6,9 @@
  * 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
@@ -18,20 +17,20 @@
  * under the License.
  *
  */
+
 package org.apache.qpid.server.security.auth.sasl.crammd5;
 
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
 
-public class CRAMMD5HashedInitialiser extends UsernamePasswordInitialiser
+public class CramMd5Negotiator extends AbstractCramMd5Negotiator
 {
-    public String getMechanismName()
-    {
-        return CRAMMD5HashedSaslServer.MECHANISM;
-    }
+    public static final String MECHANISM = "CRAM-MD5";
 
-    public void initialise(PrincipalDatabase passwordFile)
+    public CramMd5Negotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
+                             final String localFQDN,
+                             final PasswordSource passwordSource)
     {
-        super.initialise(passwordFile);
+        super(authenticationProvider, localFQDN, passwordSource, PLAIN_PASSWORD_TRANSFORMER);
     }
 }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,109 @@
+/*
+ * 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.sasl.external;
+
+import java.security.Principal;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerImpl;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+
+public class ExternalNegotiator implements SaslNegotiator
+{
+    private final static Logger LOGGER = LoggerFactory.getLogger(ExternalNegotiator.class);
+    private final AuthenticationResult _result;
+    private volatile boolean _isComplete;
+
+    public ExternalNegotiator(final ExternalAuthenticationManager externalAuthenticationManager,
+                              final Principal externalPrincipal)
+    {
+        boolean useFullDN = externalAuthenticationManager.getUseFullDN();
+        final Principal principal;
+        if (externalPrincipal instanceof X500Principal && !useFullDN)
+        {
+            // Construct username as <CN>@<DC1>.<DC2>.<DC3>....<DCN>
+            String username;
+            String dn = ((X500Principal) externalPrincipal).getName(X500Principal.RFC2253);
+
+            LOGGER.debug("Parsing username from Principal DN: {}", dn);
+
+            username = SSLUtil.getIdFromSubjectDN(dn);
+            if (username.isEmpty())
+            {
+                // CN is empty => Cannot construct username => Authentication failed => return null
+                LOGGER.debug("CN value was empty in Principal name, unable to construct username");
+
+                principal =  null;
+            }
+            else
+            {
+                LOGGER.debug("Constructing Principal with username: {}", username);
+
+                principal = new UsernamePrincipal(username, externalAuthenticationManager);
+            }
+        }
+        else
+        {
+            LOGGER.debug("Using external Principal: {}", externalPrincipal);
+
+            principal = externalPrincipal;
+        }
+
+        if (principal == null)
+        {
+            _result = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, new IllegalArgumentException("CN value was empty in Principal name, unable to construct username"));
+        }
+        else
+        {
+            _result = new AuthenticationResult(principal);
+        }
+    }
+
+    @Override
+    public AuthenticationResult handleResponse(final byte[] response)
+    {
+        if (_isComplete)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalStateException(
+                                                    "Multiple Authentications not permitted."));
+        }
+        else
+        {
+            _isComplete = true;
+        }
+        return _result;
+    }
+
+    @Override
+    public void dispose()
+    {
+
+    }
+}

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/kerberos/KerberosNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/kerberos/KerberosNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/kerberos/KerberosNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/kerberos/KerberosNegotiator.java Fri Dec  2 15:47:52 2016
@@ -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.server.security.auth.sasl.kerberos;
+
+import static org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager.GSSAPI_MECHANISM;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.AbstractSaslServerNegotiator;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+
+public class KerberosNegotiator extends AbstractSaslServerNegotiator implements SaslNegotiator
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(KerberosNegotiator.class);
+    private final SaslServer _saslServer;
+    private final AuthenticationProvider<?> _authenticationProvider;
+    private final SaslException _exception;
+
+    public KerberosNegotiator(final AuthenticationProvider<?> authenticationProvider, final String localFQDN)
+    {
+        _authenticationProvider = authenticationProvider;
+        SaslServer saslServer = null;
+        SaslException exception = null;
+        try
+        {
+            saslServer = Sasl.createSaslServer(GSSAPI_MECHANISM, "AMQP", localFQDN,
+                                               null, new GssApiCallbackHandler());
+        }
+        catch (SaslException e)
+        {
+            exception = e;
+            LOGGER.warn("Creation of SASL server for mechanism '{}' failed.", GSSAPI_MECHANISM, e);
+        }
+        _exception = exception;
+        _saslServer = saslServer;
+    }
+
+    @Override
+    protected Exception getSaslServerCreationException()
+    {
+        return _exception;
+    }
+
+    @Override
+    protected SaslServer getSaslServer()
+    {
+        return _saslServer;
+    }
+
+    @Override
+    protected AuthenticationProvider<?> getAuthenticationProvider()
+    {
+        return _authenticationProvider;
+    }
+
+    private static class GssApiCallbackHandler implements CallbackHandler
+    {
+        @Override
+        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+        {
+            for(Callback callback : callbacks)
+            {
+                if (callback instanceof AuthorizeCallback)
+                {
+                    ((AuthorizeCallback) callback).setAuthorized(true);
+                }
+                else
+                {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        }
+    }
+}

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/oauth2/OAuth2Negotiator.java (from r1772329, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2SaslServer.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/oauth2/OAuth2Negotiator.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/oauth2/OAuth2Negotiator.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2SaslServer.java&r1=1772329&r2=1772364&rev=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2SaslServer.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/oauth2/OAuth2Negotiator.java Fri Dec  2 15:47:52 2016
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -19,37 +18,42 @@
  *
  */
 
-package org.apache.qpid.server.security.auth.manager.oauth2;
+package org.apache.qpid.server.security.auth.sasl.oauth2;
 
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.manager.oauth2.OAuth2AuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
 
-/**
- * https://developers.google.com/gmail/xoauth2_protocol
- */
-class OAuth2SaslServer implements SaslServer
+public class OAuth2Negotiator implements SaslNegotiator
 {
-    public static final String MECHANISM = "XOAUTH2";
-    public static final String ACCESS_TOKEN_PROPERTY = "accessToken";
 
+    public static final String MECHANISM = "XOAUTH2";
     private static final String BEARER_PREFIX = "Bearer ";
+    private OAuth2AuthenticationProvider<?> _authenticationProvider;
+    private volatile boolean _isComplete;
 
-    private String _accessToken;
-    private boolean _isComplete;
-
-    @Override
-    public String getMechanismName()
+    public OAuth2Negotiator(OAuth2AuthenticationProvider<?> authenticationProvider)
     {
-        return MECHANISM;
+        _authenticationProvider = authenticationProvider;
     }
 
     @Override
-    public byte[] evaluateResponse(final byte[] response) throws SaslException
+    public AuthenticationResult handleResponse(final byte[] response)
     {
+        if (_isComplete)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalStateException(
+                                                    "Multiple Authentications not permitted."));
+        }
+        else
+        {
+            _isComplete = true;
+        }
         Map<String, String> responsePairs = splitResponse(response);
 
         String auth = responsePairs.get("auth");
@@ -57,67 +61,23 @@ class OAuth2SaslServer implements SaslSe
         {
             if (auth.startsWith(BEARER_PREFIX))
             {
-                _accessToken = auth.substring(BEARER_PREFIX.length());
-                _isComplete = true;
+                return _authenticationProvider.authenticateViaAccessToken(auth.substring(BEARER_PREFIX.length()));
             }
             else
             {
-                throw new SaslException("The 'auth' part of response does not not begin with the expected prefix");
+                return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, new IllegalArgumentException("The 'auth' part of response does not not begin with the expected prefix"));
             }
         }
         else
         {
-            throw new SaslException("The mandatory 'auth' part of the response was absent.");
-        }
-
-        return new byte[0];
-    }
-
-    @Override
-    public boolean isComplete()
-    {
-        return _isComplete;
-    }
-
-    @Override
-    public String getAuthorizationID()
-    {
-        return null;
-    }
-
-    @Override
-    public Object getNegotiatedProperty(final String propName)
-    {
-        if (!_isComplete)
-        {
-            throw new IllegalStateException("authentication exchange has not completed");
-        }
-        if (ACCESS_TOKEN_PROPERTY.equals(propName))
-        {
-            return _accessToken;
-        }
-        else
-        {
-            return null;
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, new IllegalArgumentException("The mandatory 'auth' part of the response was absent."));
         }
     }
 
     @Override
-    public byte[] unwrap(final byte[] incoming, final int offset, final int len) throws SaslException
+    public void dispose()
     {
-        throw new SaslException("");
-    }
 
-    @Override
-    public byte[] wrap(final byte[] outgoing, final int offset, final int len) throws SaslException
-    {
-        throw new SaslException("");
-    }
-
-    @Override
-    public void dispose() throws SaslException
-    {
-        _accessToken = null;
     }
 
     private Map<String, String> splitResponse(final byte[] response)

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.security.auth.sasl.plain;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.manager.UsernamePasswordAuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+
+public class PlainNegotiator implements SaslNegotiator
+{
+    public static final String MECHANISM = "PLAIN";
+    private static final String UTF8 = StandardCharsets.UTF_8.name();
+
+    private UsernamePasswordAuthenticationProvider _usernamePasswordAuthenticationProvider;
+    private volatile boolean _isComplete;
+
+    public PlainNegotiator(final UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider)
+    {
+        _usernamePasswordAuthenticationProvider = usernamePasswordAuthenticationProvider;
+    }
+
+    @Override
+    public AuthenticationResult handleResponse(final byte[] response)
+    {
+        if (_isComplete)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalStateException(
+                                                    "Multiple Authentications not permitted."));
+        }
+        else
+        {
+            _isComplete = true;
+        }
+        int authzidNullPosition = findNullPosition(response, 0);
+        if (authzidNullPosition < 0)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalArgumentException(
+                                                    "Invalid PLAIN encoding, authzid null terminator not found"));
+        }
+        int authcidNullPosition = findNullPosition(response, authzidNullPosition + 1);
+        if (authcidNullPosition < 0)
+        {
+            return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,
+                                            new IllegalArgumentException(
+                                                    "Invalid PLAIN encoding, authcid null terminator not found"));
+        }
+
+        String username;
+        String password;
+        try
+        {
+            username = new String(response, authzidNullPosition + 1, authcidNullPosition - authzidNullPosition - 1, UTF8);
+            // TODO: should not get pwd as a String but as a char array...
+            int passwordLen = response.length - authcidNullPosition - 1;
+            password = new String(response, authcidNullPosition + 1, passwordLen, UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            throw new RuntimeException("JVM does not support UTF8", e);
+        }
+        return _usernamePasswordAuthenticationProvider.authenticate(username, password);
+    }
+
+    @Override
+    public void dispose()
+    {
+
+    }
+
+    private int findNullPosition(byte[] response, int startPosition)
+    {
+        int position = startPosition;
+        while (position < response.length)
+        {
+            if (response[position] == (byte) 0)
+            {
+                return position;
+            }
+            position++;
+        }
+        return -1;
+    }
+}

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramNegotiator.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramNegotiator.java?rev=1772364&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramNegotiator.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramNegotiator.java Fri Dec  2 15:47:52 2016
@@ -0,0 +1,55 @@
+/*
+ * 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.sasl.scram;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
+import org.apache.qpid.server.security.auth.sasl.AbstractSaslServerNegotiator;
+
+public class ScramNegotiator extends AbstractSaslServerNegotiator implements SaslNegotiator
+{
+    private final ScramSaslServer _saslServer;
+    private AuthenticationProvider<?> _authenticationProvider;
+
+    public ScramNegotiator(final AuthenticationProvider<?> authenticationProvider,
+                           final ScramSaslServerSource scramSaslServerSource,
+                           final String mechanism)
+    {
+        _authenticationProvider = authenticationProvider;
+        _saslServer = new ScramSaslServer(scramSaslServerSource, mechanism);
+    }
+
+    protected AuthenticationProvider<?> getAuthenticationProvider()
+    {
+        return _authenticationProvider;
+    }
+
+    @Override
+    protected Exception getSaslServerCreationException()
+    {
+        return null;
+    }
+
+    protected ScramSaslServer getSaslServer()
+    {
+        return _saslServer;
+    }
+}

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java Fri Dec  2 15:47:52 2016
@@ -55,14 +55,12 @@ public class ScramSaslServer implements
     private ScramSaslServerSource.SaltAndPasswordKeys _saltAndPassword;
 
     public ScramSaslServer(final ScramSaslServerSource authenticationManager,
-                           final String mechanism,
-                           final String hmacName,
-                           final String digestName)
+                           final String mechanism)
     {
         _authManager = authenticationManager;
         _mechanism = mechanism;
-        _hmacName = hmacName;
-        _digestName = digestName;
+        _hmacName = authenticationManager.getHmacName();
+        _digestName = authenticationManager.getDigestName();
     }
 
     enum State

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSource.java Fri Dec  2 15:47:52 2016
@@ -26,6 +26,10 @@ public interface ScramSaslServerSource
 {
     int getIterationCount();
 
+    String getDigestName();
+
+    String getHmacName();
+
     interface SaltAndPasswordKeys
     {
         byte[] getSalt();

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServerSourceAdapter.java Fri Dec  2 15:47:52 2016
@@ -30,6 +30,8 @@ import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 import javax.security.sasl.SaslException;
 
+import org.apache.qpid.server.security.auth.sasl.PasswordSource;
+
 public class ScramSaslServerSourceAdapter implements ScramSaslServerSource
 {
     private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
@@ -40,11 +42,6 @@ public class ScramSaslServerSourceAdapte
     private final PasswordSource _passwordSource;
     private final String _digestName;
 
-    public interface PasswordSource
-    {
-        char[] getPassword(String username);
-    }
-
     public ScramSaslServerSourceAdapter(final int iterationCount,
                                         final String hmacName,
                                         final String digestName,
@@ -62,6 +59,18 @@ public class ScramSaslServerSourceAdapte
         return _iterationCount;
     }
 
+    @Override
+    public String getDigestName()
+    {
+        return _digestName;
+    }
+
+    @Override
+    public String getHmacName()
+    {
+        return _hmacName;
+    }
+
     private Mac createShaHmac(final byte[] keyBytes)
     {
         try

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java Fri Dec  2 15:47:52 2016
@@ -68,6 +68,7 @@ import org.apache.qpid.server.model.adap
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.protocol.AMQSessionModel;
 import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.sasl.SaslSettings;
 import org.apache.qpid.server.stats.StatisticsCounter;
 import org.apache.qpid.server.stats.StatisticsGatherer;
 import org.apache.qpid.server.util.Action;
@@ -77,7 +78,7 @@ import org.apache.qpid.transport.network
 
 public abstract class AbstractAMQPConnection<C extends AbstractAMQPConnection<C,T>, T>
         extends AbstractConfiguredObject<C>
-        implements ProtocolEngine, AMQPConnection<C>, EventLoggerProvider
+        implements ProtocolEngine, AMQPConnection<C>, EventLoggerProvider, SaslSettings
 
 {
     public static final FixedKeyMapCreator PUBLISH_ACTION_MAP_CREATOR = new FixedKeyMapCreator("routingKey", "immediate");
@@ -915,4 +916,25 @@ public abstract class AbstractAMQPConnec
     {
         getEventLogger().message(ConnectionMessages.OPERATION(operation));
     }
+
+    @Override
+    public String getLocalFQDN()
+    {
+        SocketAddress address = getNetwork().getLocalAddress();
+        if (address instanceof InetSocketAddress)
+        {
+            return ((InetSocketAddress) address).getHostName();
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported socket address class: " + address);
+        }
+    }
+
+    @Override
+    public Principal getExternalPrincipal()
+    {
+        return getNetwork().getPeerPrincipal();
+    }
+
 }

Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java?rev=1772364&r1=1772363&r2=1772364&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java Fri Dec  2 15:47:52 2016
@@ -28,7 +28,6 @@ import java.util.HashSet;
 import java.util.Set;
 
 import javax.security.auth.Subject;
-import javax.security.sasl.SaslServer;
 
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.GroupProvider;
@@ -37,6 +36,7 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
 import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
 import org.apache.qpid.test.utils.QpidTestCase;
 
 public class SubjectCreatorTest extends QpidTestCase
@@ -54,7 +54,7 @@ public class SubjectCreatorTest extends
 
     private SubjectCreator _subjectCreator;
     private AuthenticationResult _authenticationResult;
-    private SaslServer _testSaslServer = mock(SaslServer.class);
+    private SaslNegotiator _testSaslNegotiator = mock(SaslNegotiator.class);
     private byte[] _saslResponseBytes = PASSWORD.getBytes();
 
     @Override
@@ -70,11 +70,9 @@ public class SubjectCreatorTest extends
 
     public void testSaslAuthenticationSuccessReturnsSubjectWithUserAndGroupPrincipals() throws Exception
     {
-        when(_authenticationProvider.authenticate(_testSaslServer, _saslResponseBytes)).thenReturn(_authenticationResult);
-        when(_testSaslServer.isComplete()).thenReturn(true);
-        when(_testSaslServer.getAuthorizationID()).thenReturn(USERNAME_PRINCIPAL.getName());
+        when(_testSaslNegotiator.handleResponse(_saslResponseBytes)).thenReturn(_authenticationResult);
 
-        SubjectAuthenticationResult result = _subjectCreator.authenticate(_testSaslServer, _saslResponseBytes);
+        SubjectAuthenticationResult result = _subjectCreator.authenticate(_testSaslNegotiator, _saslResponseBytes);
 
         final Subject actualSubject = result.getSubject();
         assertEquals("Should contain one user principal and two groups ", 3, actualSubject.getPrincipals().size());
@@ -96,11 +94,9 @@ public class SubjectCreatorTest extends
     {
         AuthenticationResult failedAuthenticationResult = new AuthenticationResult(expectedStatus);
 
-        when(_authenticationProvider.authenticate(_testSaslServer, _saslResponseBytes)).thenReturn(
-                failedAuthenticationResult);
-        when(_testSaslServer.isComplete()).thenReturn(false);
+        when(_testSaslNegotiator.handleResponse(_saslResponseBytes)).thenReturn(failedAuthenticationResult);
 
-        SubjectAuthenticationResult subjectAuthenticationResult = _subjectCreator.authenticate(_testSaslServer, _saslResponseBytes);
+        SubjectAuthenticationResult subjectAuthenticationResult = _subjectCreator.authenticate(_testSaslNegotiator, _saslResponseBytes);
 
         assertSame(expectedStatus, subjectAuthenticationResult.getStatus());
         assertNull(subjectAuthenticationResult.getSubject());




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