You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2011/06/09 12:38:21 UTC

svn commit: r1133781 - in /qpid/trunk/qpid/java: broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/ broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/ broker/etc/ broker/src/main/java/org/apache/qpid/server/...

Author: robbie
Date: Thu Jun  9 10:38:20 2011
New Revision: 1133781

URL: http://svn.apache.org/viewvc?rev=1133781&view=rev
Log:
QPID-3296: update RMIPasswordAuthenticator to authenticate users via AuthenticationManager instead of a PrincipalDatabase

Applied patch from Keith Wall <ke...@gmail.com>

Added:
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
Modified:
    qpid/trunk/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
    qpid/trunk/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
    qpid/trunk/qpid/java/broker/etc/config.xml
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
    qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
    qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
    qpid/trunk/qpid/java/systests/etc/config-systests-firewall-2.xml
    qpid/trunk/qpid/java/systests/etc/config-systests-firewall-3.xml

Modified: qpid/trunk/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java (original)
+++ qpid/trunk/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java Thu Jun  9 10:38:20 2011
@@ -74,8 +74,6 @@ public class AppInfo
                 appInfoMap.put("port", sc.getPorts().toString());
                 appInfoMap.put("version", QpidProperties.getReleaseVersion());
                 appInfoMap.put("vhosts", "standalone");
-                appInfoMap.put("JMXPrincipalDatabase", sc
-                        .getJMXPrincipalDatabase());
                 appInfoMap.put("KeystorePath", sc.getKeystorePath());
                 appInfoMap.put("PluginDirectory", sc.getPluginDirectory());
                 appInfoMap.put("CertType", sc.getCertType());

Modified: qpid/trunk/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java (original)
+++ qpid/trunk/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java Thu Jun  9 10:38:20 2011
@@ -92,9 +92,6 @@ public class FirewallConfigurationTest e
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<xml fileName=\"" + fileB.getAbsolutePath() + "\"/>");
         out.write("\t\t</firewall>\n");
@@ -192,9 +189,6 @@ public class FirewallConfigurationTest e
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<xml fileName=\"" + fileB.getAbsolutePath() + "\"/>");
         out.write("\t\t</firewall>\n");
@@ -301,9 +295,6 @@ public class FirewallConfigurationTest e
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<rule access=\""+ ((allow) ? "allow" : "deny") +"\" network=\"127.0.0.1\"/>");
         out.write("\t\t</firewall>\n");

Modified: qpid/trunk/qpid/java/broker/etc/config.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/etc/config.xml?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/etc/config.xml (original)
+++ qpid/trunk/qpid/java/broker/etc/config.xml Thu Jun  9 10:38:20 2011
@@ -86,10 +86,6 @@
         <allow-all />
         
         <msg-auth>false</msg-auth>
-        
-        <jmx>
-            <principal-database>passwordfile</principal-database>
-        </jmx>
     </security>
 
     <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java Thu Jun  9 10:38:20 2011
@@ -214,6 +214,13 @@ public class ServerConfiguration extends
                     + (_configFile == null ? "" : " Configuration file : " + _configFile);
             throw new ConfigurationException(message);
         }
+
+        if (getListValue("security.jmx.principal-database").size() > 0)
+        {
+            String message = "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml."
+                    + (_configFile == null ? "" : " Configuration file : " + _configFile);
+            throw new ConfigurationException(message);
+        }
     }
 
     /*
@@ -533,11 +540,6 @@ public class ServerConfiguration extends
         return getListValue(name);
     }
 
-    public List<String> getManagementPrincipalDBs()
-    {
-        return getListValue("security.jmx.principal-database");
-    }
-
     public int getFrameSize()
     {
         return getIntValue("advanced.framesize", DEFAULT_FRAME_SIZE);
@@ -568,11 +570,6 @@ public class ServerConfiguration extends
         return getBooleanValue("security.msg-auth");
     }
 
-    public String getJMXPrincipalDatabase()
-    {
-        return getStringValue("security.jmx.principal-database");
-    }
-
     public String getManagementKeyStorePath()
     {
         return getStringValue("management.ssl.keyStorePath");

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java Thu Jun  9 10:38:20 2011
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.server.handler;
 
+
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
@@ -68,7 +69,7 @@ public class ConnectionSecureOkMethodHan
         }
         MethodRegistry methodRegistry = session.getMethodRegistry();
         AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
-        switch (authResult.status)
+        switch (authResult.getStatus())
         {
             case ERROR:
                 Exception cause = authResult.getCause();
@@ -96,13 +97,14 @@ public class ConnectionSecureOkMethodHan
                                                                 ConnectionStartOkMethodHandler.getConfiguredFrameSize(),
                                                                 ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
                 session.writeFrame(tuneBody.generateFrame(0));
-                session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
+                final UsernamePrincipal principal = UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject());
+                session.setAuthorizedID(principal);
                 disposeSaslServer(session);                
                 break;
             case CONTINUE:
                 stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
 
-                ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
+                ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
                 session.writeFrame(secureBody.generateFrame(0));
         }
     }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java Thu Jun  9 10:38:20 2011
@@ -88,7 +88,7 @@ public class ConnectionStartOkMethodHand
 
             MethodRegistry methodRegistry = session.getMethodRegistry();
 
-            switch (authResult.status)
+            switch (authResult.getStatus())
             {
                 case ERROR:
                     Exception cause = authResult.getCause();
@@ -121,7 +121,7 @@ public class ConnectionStartOkMethodHand
                 case CONTINUE:
                     stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
 
-                    ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
+                    ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
                     session.writeFrame(secureBody.generateFrame(0));
             }
         }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java Thu Jun  9 10:38:20 2011
@@ -20,32 +20,6 @@
  */
 package org.apache.qpid.server.management;
 
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-
-import javax.management.JMException;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
-import javax.management.ObjectName;
-import javax.management.NotificationListener;
-import javax.management.NotificationFilterSupport;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.rmi.RMIConnectorServer;
-import javax.management.remote.rmi.RMIJRMPServerImpl;
-import javax.management.remote.rmi.RMIServerImpl;
-import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.rmi.ssl.SslRMIServerSocketFactory;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -64,7 +38,31 @@ import java.rmi.server.RMIClientSocketFa
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.UnicastRemoteObject;
 import java.util.HashMap;
-import java.util.Map;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.NotificationFilterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServerImpl;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
 
 /**
  * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no 
@@ -113,12 +111,6 @@ public class JMXManagedObjectRegistry im
         IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
         int port = appRegistry.getConfiguration().getJMXManagementPort();
 
-        //retrieve the Principal Database assigned to JMX authentication duties
-        String jmxDatabaseName = appRegistry.getConfiguration().getJMXPrincipalDatabase();
-        Map<String, PrincipalDatabase> map = appRegistry.getDatabaseManager().getDatabases();        
-        PrincipalDatabase db = map.get(jmxDatabaseName);
-
-        HashMap<String,Object> env = new HashMap<String,Object>();
 
         //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration
         RMIClientSocketFactory csf;
@@ -200,7 +192,8 @@ public class JMXManagedObjectRegistry im
 
         //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
         RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator();
-        rmipa.setPrincipalDatabase(db);
+        rmipa.setAuthenticationManager(appRegistry.getAuthenticationManager());
+        HashMap<String,Object> env = new HashMap<String,Object>();
         env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
 
         /*

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java Thu Jun  9 10:38:20 2011
@@ -27,7 +27,6 @@ import java.lang.reflect.Proxy;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.Principal;
-import java.util.Properties;
 import java.util.Set;
 
 import javax.management.Attribute;
@@ -65,7 +64,6 @@ public class MBeanInvocationHandlerImpl 
     public final static String READONLY = "readonly";
     private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
     private MBeanServer _mbs;
-    private static Properties _userRoles = new Properties();
     private static ManagementActor  _logActor;
     
     public static MBeanServerForwarder newProxyInstance()

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java Thu Jun  9 10:38:20 2011
@@ -20,42 +20,93 @@
  */
 package org.apache.qpid.server.security.auth;
 
+import javax.security.auth.Subject;
+
+/**
+ * Encapsulates the result of an attempt to authenticate.
+ * <p>
+ * The authentication status describes the overall outcome.
+ * <p>
+ * <ol>
+ *  <li>If authentication status is SUCCESS, the subject will be populated.
+ *  </li>
+ *  <li>If authentication status is CONTINUE, the authentication has failed because the user
+ *      supplied incorrect credentials (etc).  If the authentication requires it, the next challenge
+ *      is made available.
+ *  </li>
+ *  <li>If authentication status is ERROR , the authentication decision could not be made due
+ *      to a failure (such as an external system), the {@link AuthenticationResult#getCause()}
+ *      will provide the underlying exception.
+ *  </li>
+ * </ol>
+ *
+ */
 public class AuthenticationResult
 {
     public enum AuthenticationStatus
     {
-        SUCCESS, CONTINUE, ERROR
+        /** Authentication successful */
+        SUCCESS,
+        /** Authentication not successful due to credentials problem etc */
+        CONTINUE,
+        /** Problem prevented the authentication from being made e.g. failure of an external system */
+        ERROR
     }
 
-    public AuthenticationStatus status;
-    public byte[] challenge;
-    
-    private Exception cause;
+    public final AuthenticationStatus _status;
+    public final byte[] _challenge;
+    private final Exception _cause;
+    private final Subject _subject;
 
-    public AuthenticationResult(AuthenticationStatus status)
+    public AuthenticationResult(final AuthenticationStatus status)
     {
         this(null, status, null);
     }
 
-    public AuthenticationResult(byte[] challenge, AuthenticationStatus status)
+    public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status)
     {
         this(challenge, status, null);
     }
 
-    public AuthenticationResult(AuthenticationStatus error, Exception cause)
+    public AuthenticationResult(final AuthenticationStatus error, final Exception cause)
     {
         this(null, error, cause);
     }
 
-    public AuthenticationResult(byte[] challenge, AuthenticationStatus status, Exception cause)
+    public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status, final Exception cause)
+    {
+        this._status = status;
+        this._challenge = challenge;
+        this._cause = cause;
+        this._subject = null;
+    }
+
+    public AuthenticationResult(final Subject subject)
     {
-        this.status = status;
-        this.challenge = challenge;
-        this.cause = cause;
+        this._status = AuthenticationStatus.SUCCESS;
+        this._challenge = null;
+        this._cause = null;
+        this._subject = subject;
     }
 
     public Exception getCause()
     {
-        return cause;
+        return _cause;
+    }
+
+    public AuthenticationStatus getStatus()
+    {
+        return _status;
     }
+
+    public byte[] getChallenge()
+    {
+        return _challenge;
+    }
+
+    public Subject getSubject()
+    {
+        return _subject;
+    }
+
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java Thu Jun  9 10:38:20 2011
@@ -23,6 +23,7 @@ package org.apache.qpid.server.security.
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -170,18 +171,13 @@ public class ConfigurationFilePrincipalD
         {
             AMQUserManagementMBean _mbean = new AMQUserManagementMBean();
 
-            List<String> principalDBs = config.getManagementPrincipalDBs();
-            if (principalDBs.isEmpty())
-            {
-                throw new ConfigurationException("No principal-database specified for jmx security");
-            }
 
-            String databaseName = principalDBs.get(0);
-            PrincipalDatabase database = getDatabases().get(databaseName);
-            if (database == null)
+            final Collection<PrincipalDatabase> dbs = getDatabases().values();
+            if (dbs.size() == 0)
             {
-                throw new ConfigurationException("Principal-database '" + databaseName + "' not found");
+                throw new ConfigurationException("Principal-database not found");
             }
+            final PrincipalDatabase database = dbs.iterator().next();
 
             _mbean.setPrincipalDatabase(database);
             _mbean.register();

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java Thu Jun  9 10:38:20 2011
@@ -32,9 +32,43 @@ import org.apache.qpid.server.security.a
  */
 public interface AuthenticationManager extends Closeable
 {
+
+   /**
+    * Gets the SASL mechanisms known to this manager.
+    *
+    * @return SASL mechanism names, space separated.
+    */
     String getMechanisms();
 
+    /**
+     * Creates a SASL server for the specified mechanism name for the given
+     * fully qualified domain name.
+     *
+     * @param mechanism mechanism name
+     * @param localFQDN domain name
+     *
+     * @return SASL server
+     * @throws SaslException
+     */
     SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
 
+    /**
+     * Authenticates a user using SASL negotiation.
+     *
+     * @param server SASL server
+     * @param response SASL response to process
+     *
+     * @return authentication result
+     */
     AuthenticationResult authenticate(SaslServer server, byte[] response);
+
+    /**
+     * Authenticates a user using their username and password.
+     *
+     * @param username username
+     * @param password password
+     *
+     * @return authentication result
+     */
+    AuthenticationResult authenticate(String username, String password);
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java Thu Jun  9 10:38:20 2011
@@ -23,12 +23,16 @@ package org.apache.qpid.server.security.
 import org.apache.log4j.Logger;
 import org.apache.qpid.server.registry.ApplicationRegistry;
 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
 import org.apache.qpid.server.security.auth.sasl.JCAProvider;
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 
+import javax.security.auth.Subject;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.AccountNotFoundException;
 import javax.security.sasl.SaslServerFactory;
 import javax.security.sasl.SaslServer;
 import javax.security.sasl.SaslException;
@@ -163,7 +167,9 @@ public class PrincipalDatabaseAuthentica
 
             if (server.isComplete())
             {
-                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.SUCCESS);
+                final Subject subject = new Subject();
+                subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
+                return new AuthenticationResult(subject);
             }
             else
             {
@@ -181,4 +187,31 @@ public class PrincipalDatabaseAuthentica
         _mechanisms = null;
         Security.removeProvider(PROVIDER_NAME);
     }
+
+    /**
+     * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
+     */
+    @Override
+    public AuthenticationResult authenticate(final String username, final String password)
+    {
+        final PrincipalDatabase db = ApplicationRegistry.getInstance().getDatabaseManager().getDatabases().values().iterator().next();
+
+        try
+        {
+            if (db.verifyPassword(username, password.toCharArray()))
+            {
+                final Subject subject = new Subject();
+                subject.getPrincipals().add(new UsernamePrincipal(username));
+                return new AuthenticationResult(subject);
+            }
+            else
+            {
+                return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+            }
+        }
+        catch (AccountNotFoundException e)
+        {
+            return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+        }
+    }
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java Thu Jun  9 10:38:20 2011
@@ -20,14 +20,13 @@
  */
 package org.apache.qpid.server.security.auth.rmi;
 
-import java.util.Collections;
-
 import javax.management.remote.JMXAuthenticator;
 import javax.management.remote.JMXPrincipal;
 import javax.security.auth.Subject;
-import javax.security.auth.login.AccountNotFoundException;
 
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 
 public class RMIPasswordAuthenticator implements JMXAuthenticator
 {
@@ -39,15 +38,15 @@ public class RMIPasswordAuthenticator im
     static final String CREDENTIALS_REQUIRED = "User details are required. " +
     		            "Please ensure you are using an up to date management console to connect.";
     
-    private PrincipalDatabase _db = null;
+    private AuthenticationManager _authenticationManager = null;
 
     public RMIPasswordAuthenticator()
     {
     }
-    
-    public void setPrincipalDatabase(PrincipalDatabase pd)
+
+    public void setAuthenticationManager(final AuthenticationManager authenticationManager)
     {
-        this._db = pd;
+        _authenticationManager = authenticationManager;
     }
 
     public Subject authenticate(Object credentials) throws SecurityException
@@ -65,50 +64,39 @@ public class RMIPasswordAuthenticator im
             }
         }
 
-        // Verify that required number of credential's.
+        // Verify that required number of credentials.
         final String[] userCredentials = (String[]) credentials;
         if (userCredentials.length != 2)
         {
             throw new SecurityException(SHOULD_HAVE_2_ELEMENTS);
         }
 
-        String username = (String) userCredentials[0];
-        String password = (String) userCredentials[1];
+        final String username = (String) userCredentials[0];
+        final String password = (String) userCredentials[1];
 
-        // Verify that all required credential's are actually present.
+        // Verify that all required credentials are actually present.
         if (username == null || password == null)
         {
             throw new SecurityException(SHOULD_BE_NON_NULL);
         }
         
-        // Verify that a PD has been set.
-        if (_db == null)
+        // Verify that an AuthenticationManager has been set.
+        if (_authenticationManager == null)
         {
             throw new SecurityException(UNABLE_TO_LOOKUP);
         }
-        
-        boolean authenticated = false;
+        final AuthenticationResult result = _authenticationManager.authenticate(username, password);
 
-        // Perform authentication
-        try
+        if (AuthenticationStatus.ERROR.equals(result.getStatus()))
         {
-            if (_db.verifyPassword(username, password.toCharArray()))
-            {            
-                authenticated = true;
-            }
-        }
-        catch (AccountNotFoundException e)
-        {
-            throw new SecurityException(INVALID_CREDENTIALS); // XXX
+            throw new SecurityException("Authentication manager failed", result.getCause());
         }
-
-        if (authenticated)
+        else if (AuthenticationStatus.SUCCESS.equals(result.getStatus()))
         {
-            //credential's check out, return the appropriate JAAS Subject
-            return new Subject(true,
-                    Collections.singleton(new JMXPrincipal(username)),
-                    Collections.EMPTY_SET,
-                    Collections.EMPTY_SET);
+            final Subject subject = result.getSubject();
+            subject.getPrincipals().add(new JMXPrincipal(username));
+            subject.setReadOnly();
+            return subject;
         }
         else
         {

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java Thu Jun  9 10:38:20 2011
@@ -21,14 +21,21 @@
 package org.apache.qpid.server.security.auth.sasl;
 
 import java.security.Principal;
+import java.util.Set;
+
+import javax.security.auth.Subject;
 
 /** A principal that is just a wrapper for a simple username. */
 public class UsernamePrincipal implements Principal
 {
-    private String _name;
+    private final String _name;
 
     public UsernamePrincipal(String name)
     {
+        if (name == null)
+        {
+            throw new IllegalArgumentException("name cannot be null");
+        }
         _name = name;
     }
 
@@ -41,4 +48,53 @@ public class UsernamePrincipal implement
     {
         return _name;
     }
+
+    /**
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        return prime * _name.hashCode();
+    }
+
+    /**
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+        {
+            return true;
+        }
+        else
+        {
+            if (obj instanceof UsernamePrincipal)
+            {
+                UsernamePrincipal other = (UsernamePrincipal) obj;
+                return _name.equals(other._name);
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+
+    public static UsernamePrincipal getUsernamePrincipalFromSubject(final Subject authSubject)
+    {
+        if (authSubject == null)
+        {
+            throw new IllegalArgumentException("No authenticated subject.");
+        }
+
+        final Set<UsernamePrincipal> principals = authSubject.getPrincipals(UsernamePrincipal.class);
+        if (principals.size() != 1)
+        {
+            throw new IllegalArgumentException("Can't find single UsernamePrincipal in authenticated subject");
+        }
+        return principals.iterator().next();
+    }
 }

Modified: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java (original)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java Thu Jun  9 10:38:20 2011
@@ -23,24 +23,18 @@ package org.apache.qpid.server.configura
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.util.List;
 import java.util.Locale;
 
-import junit.framework.TestCase;
-
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.XMLConfiguration;
 import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolEngine;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
 import org.apache.qpid.server.registry.ApplicationRegistry;
 import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
 import org.apache.qpid.server.util.InternalBrokerBaseCase;
 import org.apache.qpid.server.virtualhost.VirtualHost;
 import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.transport.TestNetworkDriver;
 
 public class ServerConfigurationTest extends InternalBrokerBaseCase
 {
@@ -320,20 +314,6 @@ public class ServerConfigurationTest ext
         assertEquals(true, serverConfig.getMsgAuth());
     }
 
-    public void testGetJMXPrincipalDatabase() throws ConfigurationException
-    {
-        // Check default
-        ServerConfiguration serverConfig = new ServerConfiguration(_config);
-        serverConfig.initialise();
-        assertEquals(null, serverConfig.getJMXPrincipalDatabase());
-
-        // Check value we set
-        _config.setProperty("security.jmx.principal-database", "a");
-        serverConfig = new ServerConfiguration(_config);
-        serverConfig.initialise();
-        assertEquals("a", serverConfig.getJMXPrincipalDatabase());
-    }
-
     public void testGetManagementKeyStorePath() throws ConfigurationException
     {
         // Check default
@@ -831,9 +811,6 @@ public class ServerConfigurationTest ext
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<rule access=\""+ ((allow) ? "allow" : "deny") +"\" network=\"127.0.0.1\"/>");
         out.write("\t\t</firewall>\n");
@@ -881,9 +858,6 @@ public class ServerConfigurationTest ext
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
         out.write("\t\t</firewall>\n");
@@ -986,9 +960,6 @@ public class ServerConfigurationTest ext
         out.write("\t\t\t\t</attributes>\n");
         out.write("\t\t\t</principal-database>\n");
         out.write("\t\t</principal-databases>\n");
-        out.write("\t\t<jmx>\n");
-        out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
-        out.write("\t\t</jmx>\n");
         out.write("\t\t<firewall>\n");
         out.write("\t\t\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
         out.write("\t\t</firewall>\n");
@@ -1489,4 +1460,31 @@ public class ServerConfigurationTest ext
                     ce.getMessage());
         }
     }
+
+    /*
+     * Tests that the old element security.jmx.principal-databases (that used to define the
+     * principal database used for JMX authentication) is rejected.
+     */
+    public void testManagementPrincipalDatabaseRejected() throws ConfigurationException
+    {
+        // Check default
+        ServerConfiguration serverConfig = new ServerConfiguration(_config);
+        serverConfig.initialise();
+
+        // Check value we set
+        _config.setProperty("security.jmx.principal-database(0)", "mydb");
+        serverConfig = new ServerConfiguration(_config);
+
+        try
+        {
+            serverConfig.initialise();
+            fail("Exception not thrown");
+        }
+        catch (ConfigurationException ce)
+        {
+            assertEquals("Incorrect error message",
+                    "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml.",
+                    ce.getMessage());
+        }
+    }
 }

Modified: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java (original)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java Thu Jun  9 10:38:20 2011
@@ -23,11 +23,13 @@ package org.apache.qpid.server.security.
 import java.security.Provider;
 import java.security.Security;
 
+import javax.security.auth.Subject;
 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.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
 import org.apache.qpid.server.util.InternalBrokerBaseCase;
 
 /**
@@ -89,17 +91,18 @@ public class PrincipalDatabaseAuthentica
     }
     
     /**
-     * 
      * Tests that the authenticate method correctly interprets an
      * authentication success.
      * 
      */
-    public void testAuthenticationSuccess() throws Exception
+    public void testSaslAuthenticationSuccess() throws Exception
     {
         SaslServer testServer = createTestSaslServer(true, false);
         
         AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
-        assertEquals(AuthenticationStatus.SUCCESS, result.status);
+        final Subject subject = result.getSubject();
+        assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest")));
+        assertEquals(AuthenticationStatus.SUCCESS, result.getStatus());
     }
 
     /**
@@ -108,12 +111,13 @@ public class PrincipalDatabaseAuthentica
      * authentication not complete.
      * 
      */
-    public void testAuthenticationNotCompleted() throws Exception
+    public void testSaslAuthenticationNotCompleted() throws Exception
     {
         SaslServer testServer = createTestSaslServer(false, false);
         
         AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
-        assertEquals(AuthenticationStatus.CONTINUE, result.status);
+        assertNull(result.getSubject());
+        assertEquals(AuthenticationStatus.CONTINUE, result.getStatus());
     }
 
     /**
@@ -122,12 +126,39 @@ public class PrincipalDatabaseAuthentica
      * authentication error.
      * 
      */
-    public void testAuthenticationError() throws Exception
+    public void testSaslAuthenticationError() throws Exception
     {
         SaslServer testServer = createTestSaslServer(false, true);
         
         AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
-        assertEquals(AuthenticationStatus.ERROR, result.status);
+        assertNull(result.getSubject());
+        assertEquals(AuthenticationStatus.ERROR, result.getStatus());
+    }
+
+    /**
+     * Tests that the authenticate method correctly interprets an
+     * authentication success.
+     *
+     */
+    public void testNonSaslAuthenticationSuccess() throws Exception
+    {
+        AuthenticationResult result = _manager.authenticate("guest", "guest");
+        final Subject subject = result.getSubject();
+        assertFalse("Subject should not be set read-only", subject.isReadOnly());
+        assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest")));
+        assertEquals(AuthenticationStatus.SUCCESS, result.getStatus());
+    }
+
+    /**
+     * Tests that the authenticate method correctly interprets an
+     * authentication success.
+     *
+     */
+    public void testNonSaslAuthenticationNotCompleted() throws Exception
+    {
+        AuthenticationResult result = _manager.authenticate("guest", "wrongpassword");
+        assertNull(result.getSubject());
+        assertEquals(AuthenticationStatus.CONTINUE, result.getStatus());
     }
     
     /**
@@ -179,7 +210,7 @@ public class PrincipalDatabaseAuthentica
             @Override
             public String getAuthorizationID()
             {
-                return null;
+                return complete ? "guest" : null;
             }
 
             @Override

Modified: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java (original)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java Thu Jun  9 10:38:20 2011
@@ -20,188 +20,124 @@
  */
 package org.apache.qpid.server.security.auth.rmi;
 
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.util.Collections;
 
 import javax.management.remote.JMXPrincipal;
 import javax.security.auth.Subject;
-
-import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
 
 import junit.framework.TestCase;
 
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+
+/**
+ * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager.
+ *
+ */
 public class RMIPasswordAuthenticatorTest extends TestCase
 {
     private final String USERNAME = "guest";
     private final String PASSWORD = "guest";
-    private final String B64_MD5HASHED_PASSWORD = "CE4DQ6BIb/BVMN9scFyLtA==";
     private RMIPasswordAuthenticator _rmipa;
-    
-    private Base64MD5PasswordFilePrincipalDatabase _md5Pd;
-    private File _md5PwdFile;
-    
-    private PlainPasswordFilePrincipalDatabase _plainPd;
-    private File _plainPwdFile;
-
-    private Subject testSubject;
+    private String[] _credentials;
 
     protected void setUp() throws Exception
     {
         _rmipa = new RMIPasswordAuthenticator();
         
-        _md5Pd = new Base64MD5PasswordFilePrincipalDatabase();
-        _md5PwdFile = createTempPasswordFile(this.getClass().getName()+"md5pwd", USERNAME, B64_MD5HASHED_PASSWORD);
-        _md5Pd.setPasswordFile(_md5PwdFile.getAbsolutePath());
-        
-        _plainPd = new PlainPasswordFilePrincipalDatabase();
-        _plainPwdFile = createTempPasswordFile(this.getClass().getName()+"plainpwd", USERNAME, PASSWORD);
-        _plainPd.setPasswordFile(_plainPwdFile.getAbsolutePath());
-        
-        testSubject = new Subject(true,
+        _credentials = new String[] {USERNAME, PASSWORD};
+    }
+
+    /**
+     * Tests a successful authentication.  Ensures that a populated read-only subject it returned.
+     */
+    public void testAuthenticationSuccess()
+    {
+        final Subject expectedSubject = new Subject(true,
                 Collections.singleton(new JMXPrincipal(USERNAME)),
                 Collections.EMPTY_SET,
                 Collections.EMPTY_SET);
-    }
-    
-    private File createTempPasswordFile(String filenamePrefix, String user, String password)
-    {
-        try
-        {
-            File testFile = File.createTempFile(filenamePrefix,"tmp");
-            testFile.deleteOnExit();
 
-            BufferedWriter writer = new BufferedWriter(new FileWriter(testFile));
+        _rmipa.setAuthenticationManager(createTestAuthenticationManager(true, null));
 
-            writer.write(user + ":" + password);
-            writer.newLine();
 
-            writer.flush();
-            writer.close();
-
-            return testFile;
-        }
-        catch (IOException e)
-        {
-            fail("Unable to create temporary test password file." + e.getMessage());
-        }
+        Subject newSubject = _rmipa.authenticate(_credentials);
+        assertTrue("Subject must be readonly", newSubject.isReadOnly());
+        assertTrue("Returned subject does not equal expected value",
+                newSubject.equals(expectedSubject));
 
-        return null;
     }
-
-    
-    //********** Test Methods *********//
-    
     
-    public void testAuthenticate()
+    /**
+     * Tests a unsuccessful authentication.
+     */
+    public void testUsernameOrPasswordInvalid()
     {
-        String[] credentials;
-        Subject newSubject;
-
-        // Test when no PD has been set
-        try
-        {
-            credentials = new String[]{USERNAME, PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
-            fail("SecurityException expected due to lack of principal database");
-        }
-        catch (SecurityException se)
-        {
-            assertEquals("Unexpected exception message",
-                    RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
-        }
-
-        //The PrincipalDatabase's are tested primarily by their own tests, but
-        //minimal tests are done here to exercise their usage in this area.
-        
-        // Test correct passwords are verified with an MD5 PD
-        try
-        {
-            _rmipa.setPrincipalDatabase(_md5Pd);
-            credentials = new String[]{USERNAME, PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
-            assertTrue("Returned subject does not equal expected value", 
-                    newSubject.equals(testSubject));
-        }
-        catch (Exception e)
-        {
-            fail("Unexpected Exception:" + e.getMessage());
-        }
-
-        // Test incorrect passwords are not verified with an MD5 PD
-        try
-        {
-            credentials = new String[]{USERNAME, PASSWORD+"incorrect"};
-            newSubject = _rmipa.authenticate(credentials);
-            fail("SecurityException expected due to incorrect password");
-        }
-        catch (SecurityException se)
-        {
-            assertEquals("Unexpected exception message",
-                    RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
-        }
+        _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null));
         
-        // Test non-existent accounts are not verified with an MD5 PD
         try
         {
-            credentials = new String[]{USERNAME+"invalid", PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
-            fail("SecurityException expected due to non-existant account");
+            _rmipa.authenticate(_credentials);
+            fail("Exception not thrown");
         }
         catch (SecurityException se)
         {
             assertEquals("Unexpected exception message",
                     RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
-        }
 
-        // Test correct passwords are verified with a Plain PD
-        try
-        {
-            _rmipa.setPrincipalDatabase(_plainPd);
-            credentials = new String[]{USERNAME, PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
-            assertTrue("Returned subject does not equal expected value", 
-                    newSubject.equals(testSubject));
-        }
-        catch (Exception e)
-        {
-            fail("Unexpected Exception");
         }
+    }
+
+    /**
+     * Tests case where authentication system itself fails.
+     */
+    public void testAuthenticationFailure()
+    {
+        final Exception mockAuthException = new Exception("Mock Auth system failure");
+        _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, mockAuthException));
 
-        // Test incorrect passwords are not verified with a Plain PD
         try
         {
-            credentials = new String[]{USERNAME, PASSWORD+"incorrect"};
-            newSubject = _rmipa.authenticate(credentials);
-            fail("SecurityException expected due to incorrect password");
+            _rmipa.authenticate(_credentials);
+            fail("Exception not thrown");
         }
         catch (SecurityException se)
         {
-            assertEquals("Unexpected exception message",
-                    RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
+            assertEquals("Initial cause not found", mockAuthException, se.getCause());
         }
-        
-        // Test non-existent accounts are not verified with an Plain PD
+    }
+
+
+    /**
+     * Tests case where authentication manager is not set.
+     */
+    public void testNullAuthenticationManager()
+    {
         try
         {
-            credentials = new String[]{USERNAME+"invalid", PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
-            fail("SecurityException expected due to non existant account");
+            _rmipa.authenticate(_credentials);
+            fail("SecurityException expected due to lack of authentication manager");
         }
         catch (SecurityException se)
         {
             assertEquals("Unexpected exception message",
-                    RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
+                    RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
         }
+    }
 
+    /**
+     * Tests case where arguments are non-Strings..
+     */
+    public void testWithNonStringArrayArgument()
+    {
         // Test handling of non-string credential's
+        final Object[] objCredentials = new Object[]{USERNAME, PASSWORD};
         try
         {
-            Object[] objCredentials = new Object[]{USERNAME, PASSWORD};
-            newSubject = _rmipa.authenticate(objCredentials);
+             _rmipa.authenticate(objCredentials);
             fail("SecurityException expected due to non string[] credentials");
         }
         catch (SecurityException se)
@@ -209,12 +145,18 @@ public class RMIPasswordAuthenticatorTes
             assertEquals("Unexpected exception message",
                     RMIPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage());
         }
-        
-        // Test handling of incorrect number of credential's
+    }
+
+    /**
+     * Tests case where there are too many, too few or null arguments.
+     */
+    public void testWithIllegalNumberOfArguments()
+    {
+        // Test handling of incorrect number of credentials
         try
         {
-            credentials = new String[]{USERNAME, PASSWORD, PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
+            _credentials = new String[]{USERNAME, PASSWORD, PASSWORD};
+            _rmipa.authenticate(_credentials);
             fail("SecurityException expected due to supplying wrong number of credentials");
         }
         catch (SecurityException se)
@@ -223,12 +165,12 @@ public class RMIPasswordAuthenticatorTes
                     RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
         }
         
-        // Test handling of null credential's
+        // Test handling of null credentials
         try
         {
             //send a null array
-            credentials = null;
-            newSubject = _rmipa.authenticate(credentials);
+            _credentials = null;
+            _rmipa.authenticate(_credentials);
             fail("SecurityException expected due to not supplying an array of credentials");
         }
         catch (SecurityException se)
@@ -240,8 +182,8 @@ public class RMIPasswordAuthenticatorTes
         try
         {
             //send a null password
-            credentials = new String[]{USERNAME, null};
-            newSubject = _rmipa.authenticate(credentials);
+            _credentials = new String[]{USERNAME, null};
+            _rmipa.authenticate(_credentials);
             fail("SecurityException expected due to sending a null password");
         }
         catch (SecurityException se)
@@ -253,8 +195,8 @@ public class RMIPasswordAuthenticatorTes
         try
         {
             //send a null username
-            credentials = new String[]{null, PASSWORD};
-            newSubject = _rmipa.authenticate(credentials);
+            _credentials = new String[]{null, PASSWORD};
+            _rmipa.authenticate(_credentials);
             fail("SecurityException expected due to sending a null username");
         }
         catch (SecurityException se)
@@ -264,4 +206,50 @@ public class RMIPasswordAuthenticatorTes
         }
     }
 
+    private AuthenticationManager createTestAuthenticationManager(final boolean successfulAuth, final Exception exception)
+    {
+        return new AuthenticationManager()
+        {
+            @Override
+            public void close()
+            {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public String getMechanisms()
+            {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+            {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public AuthenticationResult authenticate(SaslServer server, byte[] response)
+            {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public AuthenticationResult authenticate(String username, String password)
+            {
+                if (exception != null) {
+                    return new AuthenticationResult(AuthenticationStatus.ERROR, exception);
+                }
+                else if (successfulAuth)
+                {
+                    return new AuthenticationResult(new Subject());
+                }
+                else
+                {
+                    return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+                }
+            }
+        };
+    }
+
 }

Added: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java?rev=1133781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java (added)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java Thu Jun  9 10:38:20 2011
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 java.security.Principal;
+import javax.security.auth.Subject;
+import junit.framework.TestCase;
+
+/**
+ * Tests the UsernamePrincipal.
+ *
+ */
+public class UsernamePrincipalTest extends TestCase
+{
+    public void testEqualitySameObject()
+    {
+        final UsernamePrincipal principal = new UsernamePrincipal("string");
+        assertTrue(principal.equals(principal));
+    }
+
+    public void testEqualitySameName()
+    {
+        final String string = "string";
+        final UsernamePrincipal principal1 = new UsernamePrincipal(string);
+        final UsernamePrincipal principal2 = new UsernamePrincipal(string);
+        assertTrue(principal1.equals(principal2));
+    }
+
+    public void testEqualityEqualName()
+    {
+        final UsernamePrincipal principal1 = new UsernamePrincipal(new String("string"));
+        final UsernamePrincipal principal2 = new UsernamePrincipal(new String("string"));
+        assertTrue(principal1.equals(principal2));
+    }
+
+    public void testInequalityDifferentUserPrincipals()
+    {
+        UsernamePrincipal principal1 = new UsernamePrincipal("string1");
+        UsernamePrincipal principal2 = new UsernamePrincipal("string2");
+        assertFalse(principal1.equals(principal2));
+    }
+
+    public void testInequalityNonUserPrincipal()
+    {
+        UsernamePrincipal principal = new UsernamePrincipal("string");
+        assertFalse(principal.equals(new String("string")));
+    }
+
+    public void testInequalityNull()
+    {
+        UsernamePrincipal principal = new UsernamePrincipal("string");
+        assertFalse(principal.equals(null));
+    }
+
+    public void testGetUsernamePrincipalFromSubject()
+    {
+        final UsernamePrincipal expected = new UsernamePrincipal("name");
+        final Principal other = new Principal()
+        {
+
+            @Override
+            public String getName()
+            {
+                return "otherprincipal";
+            }
+        };
+
+        final Subject subject = new Subject();
+        subject.getPrincipals().add(expected);
+        subject.getPrincipals().add(other);
+
+        final UsernamePrincipal actual = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
+        assertSame(expected, actual);
+    }
+
+    public void testUsernamePrincipalNotInSubject()
+    {
+        try
+        {
+            UsernamePrincipal.getUsernamePrincipalFromSubject(new Subject());
+            fail("Exception not thrown");
+        }
+        catch (IllegalArgumentException iae)
+        {
+            // PASS
+        }
+    }
+
+    public void testTooManyUsernamePrincipalInSubject()
+    {
+        final Subject subject = new Subject();
+        subject.getPrincipals().add(new UsernamePrincipal("name1"));
+        subject.getPrincipals().add(new UsernamePrincipal("name2"));
+        try
+        {
+
+            UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
+            fail("Exception not thrown");
+        }
+        catch (IllegalArgumentException iae)
+        {
+            // PASS
+        }
+    }
+
+}

Modified: qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml (original)
+++ qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml Thu Jun  9 10:38:20 2011
@@ -57,10 +57,6 @@
                 </attributes>
             </principal-database>
         </principal-databases>
-
-        <jmx>
-            <principal-database>passwordfile</principal-database>
-        </jmx>
     </security>
 
     <virtualhosts>${conf}/virtualhosts-ServerConfigurationTest-New.xml</virtualhosts>

Modified: qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml (original)
+++ qpid/trunk/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml Thu Jun  9 10:38:20 2011
@@ -56,9 +56,6 @@
 </attributes>
 </principal-database>
 </principal-databases>
-<jmx>
-<principal-database>passwordfile</principal-database>
-</jmx>
 </security>
 <virtualhosts>${conf}/virtualhosts-ServerConfigurationTest-New.xml
 <default>dev-only</default>

Modified: qpid/trunk/qpid/java/systests/etc/config-systests-firewall-2.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/etc/config-systests-firewall-2.xml?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/etc/config-systests-firewall-2.xml (original)
+++ qpid/trunk/qpid/java/systests/etc/config-systests-firewall-2.xml Thu Jun  9 10:38:20 2011
@@ -84,10 +84,6 @@
 
         <msg-auth>false</msg-auth>
         
-        <jmx>
-            <principal-database>passwordfile</principal-database>
-        </jmx>
-
         <firewall default-action="deny"/>
     </security>
 

Modified: qpid/trunk/qpid/java/systests/etc/config-systests-firewall-3.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/etc/config-systests-firewall-3.xml?rev=1133781&r1=1133780&r2=1133781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/etc/config-systests-firewall-3.xml (original)
+++ qpid/trunk/qpid/java/systests/etc/config-systests-firewall-3.xml Thu Jun  9 10:38:20 2011
@@ -84,10 +84,6 @@
 
         <msg-auth>false</msg-auth>
         
-        <jmx>
-            <principal-database>passwordfile</principal-database>
-        </jmx>
-
         <firewall default-action="deny">
             <rule access="allow" network="127.0.0.1"/>
         </firewall>



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org