summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Gemmell <robbie@apache.org>2011-06-09 10:38:20 +0000
committerRobert Gemmell <robbie@apache.org>2011-06-09 10:38:20 +0000
commitb83ba1c0bc269d2b9dddd73dfe8a90d4d3723e58 (patch)
tree8d674ad91fbf4b4dff1a7610c76f63a1cc6a6259
parent46af35ba4c7867098a1c5e1cea9bd24275cbad40 (diff)
downloadqpid-python-b83ba1c0bc269d2b9dddd73dfe8a90d4d3723e58.tar.gz
QPID-3296: update RMIPasswordAuthenticator to authenticate users via AuthenticationManager instead of a PrincipalDatabase
Applied patch from Keith Wall <keith.wall@gmail.com> git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1133781 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java2
-rw-r--r--qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java9
-rw-r--r--qpid/java/broker/etc/config.xml4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java17
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java61
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java77
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java34
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java35
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java54
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java58
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java56
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java47
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java264
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java124
-rw-r--r--qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml4
-rw-r--r--qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml3
-rw-r--r--qpid/java/systests/etc/config-systests-firewall-2.xml4
-rw-r--r--qpid/java/systests/etc/config-systests-firewall-3.xml4
22 files changed, 572 insertions, 313 deletions
diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
index a5d267282b..9bdd4b9d17 100644
--- a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
+++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
@@ -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());
diff --git a/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java b/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
index ebede414f4..c0cb4aedce 100644
--- a/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
+++ b/qpid/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
@@ -92,9 +92,6 @@ public class FirewallConfigurationTest extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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");
diff --git a/qpid/java/broker/etc/config.xml b/qpid/java/broker/etc/config.xml
index ec386ab669..c0f9b4df61 100644
--- a/qpid/java/broker/etc/config.xml
+++ b/qpid/java/broker/etc/config.xml
@@ -86,10 +86,6 @@
<allow-all />
<msg-auth>false</msg-auth>
-
- <jmx>
- <principal-database>passwordfile</principal-database>
- </jmx>
</security>
<virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
index 297f7abdb8..f152865a27 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
@@ -214,6 +214,13 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
+ (_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 ConfigurationPlugin implements SignalHa
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 ConfigurationPlugin implements SignalHa
return getBooleanValue("security.msg-auth");
}
- public String getJMXPrincipalDatabase()
- {
- return getStringValue("security.jmx.principal-database");
- }
-
public String getManagementKeyStorePath()
{
return getStringValue("management.ssl.keyStorePath");
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
index d4b79134a2..79de0678f0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
@@ -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 ConnectionSecureOkMethodHandler implements StateAwareMethodListener
}
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 ConnectionSecureOkMethodHandler implements StateAwareMethodListener
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));
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
index 4442f969c4..544bd62ed8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
@@ -88,7 +88,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
MethodRegistry methodRegistry = session.getMethodRegistry();
- switch (authResult.status)
+ switch (authResult.getStatus())
{
case ERROR:
Exception cause = authResult.getCause();
@@ -121,7 +121,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
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));
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
index 0334a856c1..6a34ff4a26 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
@@ -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.RMIClientSocketFactory;
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 implements ManagedObjectRegistry
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 implements ManagedObjectRegistry
//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);
/*
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
index 380f51e308..ce6bd3ee33 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
@@ -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 implements InvocationHandler, Notificati
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()
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
index 62967ef7eb..8c2d60a660 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
@@ -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;
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
index e9276e1b0e..a22c66c73d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.security.auth.database;
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 ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
{
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();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
index 39e1e07c57..c1ef4c8ff5 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
@@ -32,9 +32,43 @@ import org.apache.qpid.server.security.auth.AuthenticationResult;
*/
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);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index d10ad2c170..d36bbc4f46 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -23,12 +23,16 @@ package org.apache.qpid.server.security.auth.manager;
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 PrincipalDatabaseAuthenticationManager implements AuthenticationMan
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 PrincipalDatabaseAuthenticationManager implements AuthenticationMan
_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);
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
index 0cbbccb3b8..b7985ad972 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
@@ -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 implements JMXAuthenticator
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 implements JMXAuthenticator
}
}
- // 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
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
index d7c8383690..b4ee13fe6b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
@@ -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 implements Principal
{
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();
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
index 43540c88a1..494003c8a0 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
@@ -23,24 +23,18 @@ package org.apache.qpid.server.configuration;
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 extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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 extends InternalBrokerBaseCase
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());
+ }
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
index f51ce0b6c6..5a9026cb64 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
@@ -23,11 +23,13 @@ package org.apache.qpid.server.security.auth.manager;
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 PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
}
/**
- *
* 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 PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
* 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 PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
* 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 PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
@Override
public String getAuthorizationID()
{
- return null;
+ return complete ? "guest" : null;
}
@Override
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
index e8c24da68d..eb713e3712 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
@@ -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.
+ _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null));
- // 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");
+ _rmipa.authenticate(_credentials);
+ fail("Exception not thrown");
}
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
- }
-
- // 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");
- }
- 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 RMIPasswordAuthenticatorTest extends TestCase
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 RMIPasswordAuthenticatorTest extends TestCase
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 RMIPasswordAuthenticatorTest extends TestCase
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 RMIPasswordAuthenticatorTest extends TestCase
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 RMIPasswordAuthenticatorTest extends TestCase
}
}
+ 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);
+ }
+ }
+ };
+ }
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
new file mode 100644
index 0000000000..8bff22115e
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
@@ -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
+ }
+ }
+
+}
diff --git a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
index 39805cbc48..1c7c7bb60f 100644
--- a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
+++ b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
@@ -57,10 +57,6 @@
</attributes>
</principal-database>
</principal-databases>
-
- <jmx>
- <principal-database>passwordfile</principal-database>
- </jmx>
</security>
<virtualhosts>${conf}/virtualhosts-ServerConfigurationTest-New.xml</virtualhosts>
diff --git a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
index e87be87154..56eaced9f7 100644
--- a/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
+++ b/qpid/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
@@ -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>
diff --git a/qpid/java/systests/etc/config-systests-firewall-2.xml b/qpid/java/systests/etc/config-systests-firewall-2.xml
index 05c3eaff9f..4c1bf9a800 100644
--- a/qpid/java/systests/etc/config-systests-firewall-2.xml
+++ b/qpid/java/systests/etc/config-systests-firewall-2.xml
@@ -84,10 +84,6 @@
<msg-auth>false</msg-auth>
- <jmx>
- <principal-database>passwordfile</principal-database>
- </jmx>
-
<firewall default-action="deny"/>
</security>
diff --git a/qpid/java/systests/etc/config-systests-firewall-3.xml b/qpid/java/systests/etc/config-systests-firewall-3.xml
index 861a3b33a3..19aaec9e54 100644
--- a/qpid/java/systests/etc/config-systests-firewall-3.xml
+++ b/qpid/java/systests/etc/config-systests-firewall-3.xml
@@ -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>