summaryrefslogtreecommitdiff
path: root/qpid/java
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2012-06-06 10:47:13 +0000
committerRobert Godfrey <rgodfrey@apache.org>2012-06-06 10:47:13 +0000
commit4aa475342fb91840c5539f830c5614bb0da3b061 (patch)
tree2c50708472303d2f5f2ce74b3c2cbf051466dadf /qpid/java
parent419c6a3f0ad577d92462c3cd2c47209e097c0f8c (diff)
downloadqpid-python-4aa475342fb91840c5539f830c5614bb0da3b061.tar.gz
QPID-4042 : [Java Broker] Add SSL Client Auth support
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1346817 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
-rw-r--r--qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java12
-rw-r--r--qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java (renamed from qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java)7
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java90
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java40
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java83
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java13
-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.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java130
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java90
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java26
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java3
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java2
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java18
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java19
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java15
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java20
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java177
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java30
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java82
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java33
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java31
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java6
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java120
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java2
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java18
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java22
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java4
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java10
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java26
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java23
-rw-r--r--qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java12
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java1
-rw-r--r--qpid/java/test-profiles/JavaExcludes3
-rw-r--r--qpid/java/test-profiles/JavaPre010Excludes3
37 files changed, 832 insertions, 391 deletions
diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
index 4ad8b4196e..70e990d92e 100644
--- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
+++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
@@ -106,15 +106,15 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
private UnsignedInteger _desiredMaxFrameSize = UnsignedInteger.valueOf(DEFAULT_MAX_FRAME);
private Runnable _onSaslCompleteTask;
- private CallbackHandlerSource _callbackHandlersource;
+ private SaslServerProvider _saslServerProvider;
private SaslServer _saslServer;
private boolean _authenticated;
private String _remoteHostname;
- public ConnectionEndpoint(Container container, CallbackHandlerSource cbs)
+ public ConnectionEndpoint(Container container, SaslServerProvider cbs)
{
_container = container;
- _callbackHandlersource = cbs;
+ _saslServerProvider = cbs;
_requiresSASLClient = false;
_requiresSASLServer = cbs != null;
}
@@ -700,11 +700,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
try
{
- _saslServer = Sasl.createSaslServer(mechanism.toString(),
- "AMQP",
- "localhost",
- null,
- _callbackHandlersource.getHandler(mechanism.toString()));
+ _saslServer = _saslServerProvider.getSaslServer(mechanism.toString(), "localhost");
// Process response from the client
byte[] challenge = _saslServer.evaluateResponse(response != null ? response : new byte[0]);
diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
index 604279a21f..1b08488673 100644
--- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java
+++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
@@ -20,9 +20,10 @@
package org.apache.qpid.amqp_1_0.transport;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
-public interface CallbackHandlerSource
+public interface SaslServerProvider
{
- CallbackHandler getHandler(String mechanism);
+ SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException;
}
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
index 4d46a32f45..f7cc60543d 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
@@ -40,12 +40,12 @@ import org.apache.qpid.test.utils.QpidTestCase;
/**
* This test checks that the {@link RuleSet} object which forms the core of the access control plugin performs correctly.
- *
+ *
* The ruleset is configured directly rather than using an external file by adding rules individually, calling the
* {@link RuleSet#grant(Integer, String, Permission, Operation, ObjectType, ObjectProperties)} method. Then, the
* access control mechanism is validated by checking whether operations would be authorised by calling the
* {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method.
- *
+ *
* It ensure that permissions can be granted correctly on users directly, ACL groups (that is those
* groups declared directly in the ACL itself), and External groups (that is a group from an External
* Authentication Provider, such as an LDAP).
@@ -82,11 +82,11 @@ public class RuleSetTest extends QpidTestCase
{
assertDenyGrantAllow(subject, operation, objectType, ObjectProperties.EMPTY);
}
-
+
public void assertDenyGrantAllow(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
{
- final Principal identity = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
-
+ final Principal identity = subject.getPrincipals().iterator().next();
+
assertEquals(Result.DENIED, _ruleSet.check(subject, operation, objectType, properties));
_ruleSet.grant(0, identity.getName(), Permission.ALLOW, operation, objectType, properties);
assertEquals(1, _ruleSet.getRuleCount());
@@ -99,7 +99,7 @@ public class RuleSetTest extends QpidTestCase
assertEquals(_ruleSet.getRuleCount(), 0);
assertEquals(_ruleSet.getDefault(), _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
-
+
public void testVirtualHostAccess() throws Exception
{
assertDenyGrantAllow(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST);
@@ -114,7 +114,7 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties properties = new ObjectProperties(_queueName);
properties.put(ObjectProperties.Property.ROUTING_KEY, (String) null);
-
+
assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.QUEUE, properties);
}
@@ -122,7 +122,7 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties properties = new ObjectProperties(_exchangeName);
properties.put(ObjectProperties.Property.TYPE, _exchangeType.asString());
-
+
assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, properties);
}
@@ -144,15 +144,15 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties();
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
ObjectProperties normal = new ObjectProperties();
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
_ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
assertEquals(1, _ruleSet.getRuleCount());
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
-
+
// defer to global if exists, otherwise default answer - this is handled by the security manager
assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
}
@@ -164,17 +164,17 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties(_queueName);
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
// should not matter if the temporary permission is processed first or last
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
_ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
}
@@ -186,17 +186,17 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties(_queueName);
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
// should not matter if the temporary permission is processed first or last
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
_ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
}
@@ -204,7 +204,7 @@ public class RuleSetTest extends QpidTestCase
/*
* Test different rules for temporary queues.
*/
-
+
/**
* The more generic rule first is used, so both requests are allowed.
*/
@@ -213,18 +213,18 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties named = new ObjectProperties(_queueName);
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
_ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
-
+
/**
* The more specific rule is first, so those requests are denied.
*/
@@ -233,18 +233,18 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties named = new ObjectProperties(_queueName);
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
_ruleSet.grant(1, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
-
+
/**
* The more specific rules are first, so those requests are denied.
*/
@@ -255,7 +255,7 @@ public class RuleSetTest extends QpidTestCase
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
ObjectProperties namedDurable = new ObjectProperties(_queueName);
namedDurable.put(ObjectProperties.Property.DURABLE, Boolean.TRUE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedDurable));
@@ -264,48 +264,48 @@ public class RuleSetTest extends QpidTestCase
_ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedDurable);
_ruleSet.grant(3, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(3, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedDurable));
}
-
+
public void testNamedTemporaryQueueAllowed()
{
ObjectProperties named = new ObjectProperties(_queueName);
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
-
+
public void testNamedTemporaryQueueDeniedAllowed()
{
ObjectProperties named = new ObjectProperties(_queueName);
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
- /**
- * Tests support for the {@link Rule#ALL} keyword.
+ /**
+ * Tests support for the {@link Rule#ALL} keyword.
*/
public void testAllowToAll()
{
@@ -316,13 +316,13 @@ public class RuleSetTest extends QpidTestCase
assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
- /**
+ /**
* Tests support for ACL groups (i.e. inline groups declared in the ACL file itself).
*/
public void testAclGroupsSupported()
{
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"})));
-
+ assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"})));
+
_ruleSet.grant(1, "aclgroup", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(1, _ruleSet.getRuleCount());
@@ -331,14 +331,14 @@ public class RuleSetTest extends QpidTestCase
assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("userc"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
- /**
+ /**
* Tests support for nested ACL groups.
*/
public void testNestedAclGroupsSupported()
{
assertTrue(_ruleSet.addGroup("aclgroup1", Arrays.asList(new String[] {"userb"})));
- assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"})));
-
+ assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"})));
+
_ruleSet.grant(1, "aclgroup2", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(1, _ruleSet.getRuleCount());
@@ -346,7 +346,7 @@ public class RuleSetTest extends QpidTestCase
assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
- /**
+ /**
* Tests support for nested External groups (i.e. those groups coming from an external source such as an LDAP).
*/
public void testExternalGroupsSupported()
@@ -358,7 +358,7 @@ public class RuleSetTest extends QpidTestCase
assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", "extgroup1"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", "extgroup2"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
-
+
/**
* Rule order in the ACL determines the outcome of the check. This test ensures that a user who is
* granted explicit permission on an object, is granted that access even although late a group
@@ -367,7 +367,7 @@ public class RuleSetTest extends QpidTestCase
public void testAllowDeterminedByRuleOrder()
{
assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
-
+
_ruleSet.grant(1, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
_ruleSet.grant(2, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(2, _ruleSet.getRuleCount());
@@ -382,10 +382,10 @@ public class RuleSetTest extends QpidTestCase
public void testDenyDeterminedByRuleOrder()
{
assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
-
+
_ruleSet.grant(1, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
_ruleSet.grant(2, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
-
+
assertEquals(2, _ruleSet.getRuleCount());
assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
index 2b43d41c7a..90603777d1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -20,10 +20,20 @@
*/
package org.apache.qpid.server;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import javax.net.ssl.SSLContext;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator;
-
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration;
import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
@@ -46,18 +56,6 @@ import org.apache.qpid.transport.network.Transport;
import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-import javax.net.ssl.SSLContext;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
public class Broker
{
private static final Logger LOGGER = Logger.getLogger(Broker.class);
@@ -271,7 +269,21 @@ public class Broker
final String keystorePassword = serverConfig.getConnectorKeyStorePassword();
final String keystoreType = serverConfig.getConnectorKeyStoreType();
final String keyManagerFactoryAlgorithm = serverConfig.getConnectorKeyManagerFactoryAlgorithm();
- final SSLContext sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm);
+ final SSLContext sslContext;
+ if(serverConfig.getConnectorTrustStorePath()!=null)
+ {
+ sslContext = SSLContextFactory.buildClientContext(serverConfig.getConnectorTrustStorePath(),
+ serverConfig.getConnectorTrustStorePassword(),
+ serverConfig.getConnectorTrustStoreType(),
+ serverConfig.getConnectorTrustManagerFactoryAlgorithm(),
+ keystorePath,
+ keystorePassword, keystoreType, keyManagerFactoryAlgorithm,
+ serverConfig.getCertAlias());
+ }
+ else
+ {
+ sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm);
+ }
for(int sslPort : sslPorts)
{
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 651fd26059..0e538a13a6 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
@@ -20,6 +20,16 @@
package org.apache.qpid.server.configuration;
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
@@ -28,7 +38,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
-
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.DefaultExchangeFactory;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
@@ -40,17 +49,6 @@ import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-import java.io.File;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.net.ssl.KeyManagerFactory;
-
public class ServerConfiguration extends ConfigurationPlugin
{
protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class);
@@ -182,7 +180,7 @@ public class ServerConfiguration extends ConfigurationPlugin
* This has been made a two step process to allow the Plugin Manager and
* Configuration Manager to be initialised in the Application Registry.
* <p>
- * If using this ServerConfiguration via an ApplicationRegistry there is no
+ * If using this ServerConfiguration via an ApplicationRegistry there is no
* need to explicitly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
@@ -204,12 +202,12 @@ public class ServerConfiguration extends ConfigurationPlugin
* Called by {@link ApplicationRegistry#initialise()}.
* <p>
* NOTE: A DEFAULT ApplicationRegistry must exist when using this method
- * or a new ApplicationRegistry will be created.
+ * or a new ApplicationRegistry will be created.
*
* @throws ConfigurationException
*/
public void initialise() throws ConfigurationException
- {
+ {
setConfiguration("", getConfig());
setupVirtualHosts(getConfig());
}
@@ -224,10 +222,10 @@ public class ServerConfiguration extends ConfigurationPlugin
{
// Support for security.jmx.access was removed when JMX access rights were incorporated into the main ACL.
// This ensure that users remove the element from their configuration file.
-
+
if (getListValue("security.jmx.access").size() > 0)
{
- String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml."
+ String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml."
+ (_configFile == null ? "" : " Configuration file : " + _configFile);
throw new ConfigurationException(message);
}
@@ -241,7 +239,7 @@ public class ServerConfiguration extends ConfigurationPlugin
if (getListValue("security.principal-databases.principal-database(0).class").size() > 0)
{
- String message = "Validation error : security/principal-databases is no longer supported within the configuration xml."
+ String message = "Validation error : security/principal-databases is no longer supported within the configuration xml."
+ (_configFile == null ? "" : " Configuration file : " + _configFile);
throw new ConfigurationException(message);
}
@@ -475,7 +473,7 @@ public class ServerConfiguration extends ConfigurationPlugin
Configuration newConfig = parseConfig(_configFile);
setConfiguration("", newConfig);
ApplicationRegistry.getInstance().getSecurityManager().configureHostPlugins(this);
-
+
// Reload virtualhosts from correct location
Configuration newVhosts;
if (_vhostsFile == null)
@@ -500,12 +498,12 @@ public class ServerConfiguration extends ConfigurationPlugin
_logger.warn(SECURITY_CONFIG_RELOADED);
}
}
-
+
public String getQpidWork()
{
return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir"));
}
-
+
public String getQpidHome()
{
return System.getProperty(QPID_HOME);
@@ -550,12 +548,12 @@ public class ServerConfiguration extends ConfigurationPlugin
{
return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]);
}
-
+
public String getPluginDirectory()
{
return getStringValue("plugin-directory");
}
-
+
public String getCacheDirectory()
{
return getStringValue("cache-directory");
@@ -773,7 +771,7 @@ public class ServerConfiguration extends ConfigurationPlugin
{
return getBooleanValue("connector.ssl.sslOnly");
}
-
+
public List getSSLPorts()
{
return getListValue("connector.ssl.port", Collections.<Integer>singletonList(DEFAULT_SSL_PORT));
@@ -804,6 +802,41 @@ public class ServerConfiguration extends ConfigurationPlugin
return getStringValue("connector.ssl.keyManagerFactoryAlgorithm", fallback);
}
+ public String getConnectorTrustStorePath()
+ {
+ return getStringValue("connector.ssl.trustStorePath", null);
+ }
+
+ public String getConnectorTrustStorePassword()
+ {
+ return getStringValue("connector.ssl.trustStorePassword", null);
+ }
+
+ public String getConnectorTrustStoreType()
+ {
+ return getStringValue("connector.ssl.trustStoreType", "JKS");
+ }
+
+ public String getConnectorTrustManagerFactoryAlgorithm()
+ {
+ return getStringValue("connector.ssl.trustManagerFactoryAlgorithm", TrustManagerFactory.getDefaultAlgorithm());
+ }
+
+ public String getCertAlias()
+ {
+ return getStringValue("connector.ssl.certAlias", null);
+ }
+
+ public boolean needClientAuth()
+ {
+ return getConfig().getBoolean("connector.ssl.needClientAuth", false);
+ }
+
+ public boolean wantClientAuth()
+ {
+ return getConfig().getBoolean("connector.ssl.wantClientAuth", false);
+ }
+
public String getDefaultVirtualHost()
{
return getStringValue("virtualhosts.default");
@@ -812,7 +845,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public void setDefaultVirtualHost(String vhost)
{
getConfig().setProperty("virtualhosts.default", vhost);
- }
+ }
public void setHousekeepingCheckPeriod(long value)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
index f6fe47b996..51dcc38c47 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
@@ -28,7 +28,7 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
private final String _transport;
private InetSocketAddress _address;
- public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
+ public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
final InetSocketAddress address,
final String transport)
{
@@ -76,4 +76,15 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
{
return _address;
}
+
+ public boolean needClientAuth()
+ {
+ return _serverConfig.needClientAuth();
+ }
+
+ @Override
+ public boolean wantClientAuth()
+ {
+ return _serverConfig.wantClientAuth();
+ }
}
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 ac322c4e8c..b8c8411c5d 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
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -92,7 +92,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
case SUCCESS:
if (_logger.isInfoEnabled())
{
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ _logger.info("Connected as: " + authResult.getSubject());
}
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
@@ -102,7 +102,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
session.writeFrame(tuneBody.generateFrame(0));
session.setAuthorizedSubject(authResult.getSubject());
- disposeSaslServer(session);
+ disposeSaslServer(session);
break;
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
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 d9979ed2dc..a522b9f60f 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
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -61,15 +61,15 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException
{
AMQProtocolSession session = stateManager.getProtocolSession();
-
+
_logger.info("SASL Mechanism selected: " + body.getMechanism());
_logger.info("Locale selected: " + body.getLocale());
AuthenticationManager authMgr = stateManager.getAuthenticationManager();
SaslServer ss = null;
try
- {
- ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN());
+ {
+ ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal());
if (ss == null)
{
@@ -106,7 +106,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
case SUCCESS:
if (_logger.isInfoEnabled())
{
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ _logger.info("Connected as: " + authResult.getSubject());
}
session.setAuthorizedSubject(authResult.getSubject());
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 116f64a8bf..869a816cf1 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,17 +20,28 @@
*/
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.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;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Proxy;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.NotBoundException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
@@ -49,32 +60,23 @@ import javax.management.remote.rmi.RMIServerImpl;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import javax.security.auth.Subject;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Proxy;
-import java.net.*;
-import java.rmi.AlreadyBoundException;
-import java.rmi.NoSuchObjectException;
-import java.rmi.NotBoundException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+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
+ * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
* security features implemented like user authentication and authorisation.
*/
public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
-
+
private final MBeanServer _mbeanServer;
private JMXConnectorServer _cs;
private Registry _rmiRegistry;
@@ -105,7 +107,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
CurrentActor.get().message(ManagementConsoleMessages.STARTUP());
-
+
//check if system properties are set to use the JVM's out-of-the-box JMXAgent
if (areOutOfTheBoxJMXOptionsSet())
{
@@ -158,10 +160,10 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
if (!ksf.canRead())
{
- throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+ throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+ ksf + ". Check permissions.");
}
-
+
CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath()));
}
@@ -199,9 +201,9 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
/*
- * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
+ * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
* Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI.
- * As a result, only binds made using the object reference will succeed, thus securing it from external change.
+ * As a result, only binds made using the object reference will succeed, thus securing it from external change.
*/
System.setProperty("java.rmi.server.randomIDs", "true");
if(_useCustomSocketFactory)
@@ -212,17 +214,17 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
_rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
}
-
+
CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
/*
- * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
+ * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
* to bind the ConnectorServer to the registry, which will now fail as for security we have
- * locked it from any RMI based modifications, including our own. Instead, we will manually bind
+ * locked it from any RMI based modifications, including our own. Instead, we will manually bind
* the RMIConnectorServer stub to the registry using its object reference, which will still succeed.
- *
+ *
* The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer
- * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
+ * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
*/
final Map<String, String> connectionIdUsernameMap = new ConcurrentHashMap<String, String>();
final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env)
@@ -240,8 +242,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException
{
final RMIConnection makeClient = super.makeClient(connectionId, subject);
- final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
- connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName());
+ final Principal principal = subject.getPrincipals().iterator().next();
+ connectionIdUsernameMap.put(connectionId, principal.getName());
return makeClient;
}
};
@@ -273,32 +275,32 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
_cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
- {
- @Override
+ {
+ @Override
public synchronized void start() throws IOException
- {
+ {
try
- {
- //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
+ {
+ //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
_rmiRegistry.bind("jmxrmi", rmiConnectorServerStub);
}
catch (AlreadyBoundException abe)
- {
+ {
//key was already in use. shouldnt happen here as its a new registry, unbindable by normal means.
//IOExceptions are the only checked type throwable by the method, wrap and rethrow
- IOException ioe = new IOException(abe.getMessage());
- ioe.initCause(abe);
- throw ioe;
+ IOException ioe = new IOException(abe.getMessage());
+ ioe.initCause(abe);
+ throw ioe;
}
//now do the normal tasks
- super.start();
+ super.start();
}
- @Override
+ @Override
public synchronized void stop() throws IOException
- {
+ {
try
{
if (_rmiRegistry != null)
@@ -310,20 +312,20 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
//ignore
}
-
+
//now do the normal tasks
super.stop();
}
-
- @Override
+
+ @Override
public JMXServiceURL getAddress()
{
//must return our pre-crafted url that includes the full details, inc JNDI details
return externalUrl;
- }
+ }
+
+ };
- };
-
//Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer.
MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance();
@@ -359,14 +361,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
/*
- * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
+ * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
* Supplied to the registry at creation, this will prevent RMI-based operations on the
* registry such as attempting to bind a new object, thereby securing it from tampering.
* This is accomplished by always returning null when attempting to determine the address
* of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
* made using the object reference will not be affected and continue to operate normally.
*/
-
+
private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory
{
@@ -444,7 +446,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_log.error("Exception while closing the JMX ConnectorServer: " + e.getMessage());
}
}
-
+
if (_rmiRegistry != null)
{
// Stopping the RMI registry
@@ -458,7 +460,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_log.error("Exception while closing the RMI Registry: " + e.getMessage());
}
}
-
+
//ObjectName query to gather all Qpid related MBeans
ObjectName mbeanNameQuery = null;
try
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
index fe85b9d3e4..74abbccd2b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
@@ -18,20 +18,20 @@
*/
package org.apache.qpid.server.plugins;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.felix.framework.Felix;
import org.apache.felix.framework.util.StringMap;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.osgi.framework.launch.Framework;
-import org.osgi.util.tracker.ServiceTracker;
-
import org.apache.qpid.common.Closeable;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.server.configuration.TopicConfiguration;
@@ -43,24 +43,23 @@ import org.apache.qpid.server.exchange.ExchangeType;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.SecurityPluginFactory;
import org.apache.qpid.server.security.access.plugins.LegacyAccess;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
+import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy;
import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory;
import org.apache.qpid.util.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+import org.osgi.util.tracker.ServiceTracker;
import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP;
import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY;
@@ -103,18 +102,18 @@ public class PluginManager implements Closeable
/** The default name of the OSGI system package list. */
private static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/server/plugins/OsgiSystemPackages.properties";
-
+
/** The name of the override system property that holds the name of the OSGI system package list. */
private static final String FILE_PROPERTY = "qpid.osgisystempackages.properties";
-
+
private static final String OSGI_SYSTEM_PACKAGES;
-
- static
+
+ static
{
final String filename = System.getProperty(FILE_PROPERTY);
final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
PluginManager.class.getClassLoader());
-
+
try
{
Version qpidReleaseVersion;
@@ -126,14 +125,14 @@ public class PluginManager implements Closeable
{
qpidReleaseVersion = null;
}
-
+
final Properties p = new Properties();
p.load(is);
-
+
final OsgiSystemPackageUtil osgiSystemPackageUtil = new OsgiSystemPackageUtil(qpidReleaseVersion, (Map)p);
-
+
OSGI_SYSTEM_PACKAGES = osgiSystemPackageUtil.getFormattedSystemPackageString();
-
+
_logger.debug("List of OSGi system packages to be added: " + OSGI_SYSTEM_PACKAGES);
}
catch (IOException e)
@@ -142,8 +141,8 @@ public class PluginManager implements Closeable
throw new ExceptionInInitializerError(e);
}
}
-
-
+
+
public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception
{
// Store all non-OSGi plugins
@@ -162,7 +161,9 @@ public class PluginManager implements Closeable
PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY,
AnonymousAuthenticationManager.AnonymousAuthenticationManagerConfiguration.FACTORY,
KerberosAuthenticationManager.KerberosAuthenticationManagerConfiguration.FACTORY,
- SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY))
+ SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY,
+ ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY
+ ))
{
_configPlugins.put(configFactory.getParentPaths(), configFactory);
}
@@ -179,7 +180,8 @@ public class PluginManager implements Closeable
for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList(
PrincipalDatabaseAuthenticationManager.FACTORY, AnonymousAuthenticationManager.FACTORY,
- KerberosAuthenticationManager.FACTORY, SimpleLDAPAuthenticationManager.FACTORY))
+ KerberosAuthenticationManager.FACTORY, SimpleLDAPAuthenticationManager.FACTORY,
+ ExternalAuthenticationManager.FACTORY))
{
_authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
}
@@ -272,7 +274,7 @@ public class PluginManager implements Closeable
_virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null);
_virtualHostTracker.open();
_trackers.add(_virtualHostTracker);
-
+
_policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null);
_policyTracker.open();
_trackers.add(_policyTracker);
@@ -285,9 +287,9 @@ public class PluginManager implements Closeable
}
private static <T> Map<String, T> getServices(ServiceTracker tracker)
- {
+ {
Map<String, T> services = new HashMap<String, T>();
-
+
if ((tracker != null) && (tracker.getServices() != null))
{
for (Object service : tracker.getServices())
@@ -307,16 +309,16 @@ public class PluginManager implements Closeable
}
public static <T> Map<String, T> getServices(ServiceTracker tracker, Map<String, T> plugins)
- {
+ {
Map<String, T> services = getServices(tracker);
services.putAll(plugins);
return services;
}
public Map<List<String>, ConfigurationPluginFactory> getConfigurationPlugins()
- {
+ {
Map<List<String>, ConfigurationPluginFactory> services = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();
-
+
if (_configTracker != null && _configTracker.getServices() != null)
{
for (Object service : _configTracker.getServices())
@@ -325,19 +327,19 @@ public class PluginManager implements Closeable
services.put(factory.getParentPaths(), factory);
}
}
-
+
services.putAll(_configPlugins);
return services;
}
public Map<String, VirtualHostPluginFactory> getVirtualHostPlugins()
- {
+ {
return getServices(_virtualHostTracker, _vhostPlugins);
}
public Map<String, SlowConsumerPolicyPluginFactory> getSlowConsumerPlugins()
- {
+ {
return getServices(_policyTracker, _policyPlugins);
}
@@ -345,7 +347,7 @@ public class PluginManager implements Closeable
{
return getServices(_exchangeTracker);
}
-
+
public Map<String, SecurityPluginFactory> getSecurityPlugins()
{
return getServices(_securityTracker, _securityPlugins);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
index 849aa05099..5db336649f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
@@ -43,23 +43,7 @@ import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.codec.AMQCodecFactory;
-import org.apache.qpid.framing.AMQBody;
-import org.apache.qpid.framing.AMQDataBlock;
-import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.framing.AMQProtocolHeaderException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ChannelCloseBody;
-import org.apache.qpid.framing.ChannelCloseOkBody;
-import org.apache.qpid.framing.ConnectionCloseBody;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.HeartbeatBody;
-import org.apache.qpid.framing.MethodDispatcher;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.ProtocolInitiation;
-import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.framing.*;
import org.apache.qpid.properties.ConnectionStartProperties;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
@@ -84,7 +68,6 @@ import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.stats.StatisticsCounter;
@@ -1064,7 +1047,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public Principal getAuthorizedPrincipal()
{
- return _authorizedSubject == null ? null : UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals().iterator().next();
}
public SocketAddress getRemoteAddress()
@@ -1077,6 +1060,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return _network.getLocalAddress();
}
+ public Principal getPeerPrincipal()
+ {
+ return _network.getPeerPrincipal();
+ }
+
public MethodRegistry getMethodRegistry()
{
return _methodRegistry;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
index f9bee93dbf..e833069320 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.protocol;
import java.net.SocketAddress;
+import java.security.Principal;
import java.util.List;
import javax.security.auth.Subject;
@@ -218,4 +219,6 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
void mgmtCloseChannel(int channelId);
+ public Principal getPeerPrincipal();
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
index 182ef1ed82..0312db5dde 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
@@ -88,7 +88,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
_network = network;
_connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE));
-
+ _connection.setPeerPrincipal(_network.getPeerPrincipal());
// FIXME Two log messages to maintain compatibility with earlier protocol versions
_connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false));
_connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false));
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
index 045eafeba2..0b8bdff5c9 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
@@ -26,12 +26,13 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.amqp_1_0.codec.FrameWriter;
import org.apache.qpid.amqp_1_0.framing.AMQFrame;
import org.apache.qpid.amqp_1_0.framing.FrameHandler;
import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
-import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.SaslServerProvider;
import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
import org.apache.qpid.amqp_1_0.transport.Container;
import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
@@ -95,7 +96,7 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
}
private State _state = State.A;
-
+
public ProtocolEngine_1_0_0(final IApplicationRegistry appRegistry, long id)
@@ -143,7 +144,8 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
Container container = new Container(_appRegistry.getBrokerId().toString());
- _conn = new ConnectionEndpoint(container,asCallbackHandlerSource(_appRegistry.getAuthenticationManager(getLocalAddress())));
+ _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getAuthenticationManager(
+ getLocalAddress())));
_conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
_conn.setFrameOutputHandler(this);
_conn.setRemoteAddress(_network.getRemoteAddress());
@@ -155,14 +157,14 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
_sender.flush();
}
- private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
{
- return new CallbackHandlerSource()
+ return new SaslServerProvider()
{
@Override
- public CallbackHandler getHandler(String mechanism)
+ public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
{
- return authenticationManager.getHandler(mechanism);
+ return authenticationManager.createSaslServer(mechanism, fqdn, null);
}
};
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
index 5d03567e03..876a8eb275 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
@@ -26,13 +26,14 @@ import java.nio.ByteBuffer;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.amqp_1_0.codec.FrameWriter;
import org.apache.qpid.amqp_1_0.codec.ProtocolHandler;
import org.apache.qpid.amqp_1_0.framing.AMQFrame;
import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler;
-import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.SaslServerProvider;
import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
import org.apache.qpid.amqp_1_0.transport.Container;
import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
@@ -57,7 +58,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
private long _createTime = System.currentTimeMillis();
private ConnectionEndpoint _conn;
private long _connectionId;
-
+
private static final ByteBuffer HEADER =
ByteBuffer.wrap(new byte[]
{
@@ -163,8 +164,8 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
Container container = new Container(_appRegistry.getBrokerId().toString());
- _conn = new ConnectionEndpoint(container, asCallbackHandlerSource(ApplicationRegistry.getInstance()
- .getAuthenticationManager(getLocalAddress())));
+ _conn = new ConnectionEndpoint(container, asSaslServerProvider(ApplicationRegistry.getInstance()
+ .getAuthenticationManager(getLocalAddress())));
_conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
_conn.setRemoteAddress(getRemoteAddress());
@@ -200,14 +201,14 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
}
- private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
{
- return new CallbackHandlerSource()
+ return new SaslServerProvider()
{
@Override
- public CallbackHandler getHandler(String mechanism)
+ public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
{
- return authenticationManager.getHandler(mechanism);
+ return authenticationManager.createSaslServer(mechanism, fqdn, null);
}
};
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
index 1a6515f71f..0eb3963865 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
@@ -139,7 +139,7 @@ public class AnonymousAuthenticationManager implements AuthenticationManager
}
@Override
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
if(ANONYMOUS.equals(mechanism))
{
@@ -181,19 +181,6 @@ public class AnonymousAuthenticationManager implements AuthenticationManager
}
@Override
- public CallbackHandler getHandler(String mechanism)
- {
- if(ANONYMOUS.equals(mechanism))
- {
- return _callbackHandler;
- }
- else
- {
- return null;
- }
- }
-
- @Override
public void close()
{
}
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 6c1a917d5b..ccddcb7669 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
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,25 +20,24 @@
*/
package org.apache.qpid.server.security.auth.manager;
+import java.security.Principal;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.plugins.Plugin;
import org.apache.qpid.server.security.auth.AuthenticationResult;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
/**
* Implementations of the AuthenticationManager are responsible for determining
* the authenticity of a user's credentials.
- *
+ *
* If the authentication is successful, the manager is responsible for producing a populated
* {@link javax.security.auth.Subject} containing the user's identity and zero or more principals representing
* groups to which the user belongs.
* <p>
* The {@link #initialise()} method is responsible for registering SASL mechanisms required by
* the manager. The {@link #close()} method must reverse this registration.
- *
+ *
*/
public interface AuthenticationManager extends Closeable, Plugin
{
@@ -64,11 +63,11 @@ public interface AuthenticationManager extends Closeable, Plugin
*
* @param mechanism mechanism name
* @param localFQDN domain name
- *
+ * @param externalPrincipal externally authenticated Principal
* @return SASL server
* @throws SaslException
*/
- SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
+ SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException;
/**
* Authenticates a user using SASL negotiation.
@@ -90,5 +89,4 @@ public interface AuthenticationManager extends Closeable, Plugin
*/
AuthenticationResult authenticate(String username, String password);
- CallbackHandler getHandler(String mechanism);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
new file mode 100644
index 0000000000..2d6866b657
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.List;
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.external.ExternalSaslServer;
+
+public class ExternalAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(ExternalAuthenticationManager.class);
+
+ private static final String EXTERNAL = "EXTERNAL";
+
+ static final ExternalAuthenticationManager INSTANCE = new ExternalAuthenticationManager();
+
+ public static class ExternalAuthenticationManagerConfiguration extends ConfigurationPlugin
+ {
+
+ public static final ConfigurationPluginFactory FACTORY =
+ new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.external-auth-manager");
+ }
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ {
+ final ConfigurationPlugin instance = new ExternalAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[0];
+ }
+
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ }
+
+
+ public static final AuthenticationManagerPluginFactory<ExternalAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<ExternalAuthenticationManager>()
+ {
+ public ExternalAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ ExternalAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (ExternalAuthenticationManagerConfiguration) config.getConfiguration(ExternalAuthenticationManagerConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for ExternalAuthenticationManager");
+ return null;
+ }
+ return INSTANCE;
+ }
+
+ public Class<ExternalAuthenticationManager> getPluginClass()
+ {
+ return ExternalAuthenticationManager.class;
+ }
+
+ public String getPluginName()
+ {
+ return ExternalAuthenticationManager.class.getName();
+ }
+ };
+
+
+ private ExternalAuthenticationManager()
+ {
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return EXTERNAL;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if(EXTERNAL.equals(mechanism))
+ {
+ return new ExternalSaslServer(externalPrincipal);
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ // Process response from the client
+ try
+ {
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ Principal principal = ((ExternalSaslServer)server).getAuthenticatedPrincipal();
+
+ if(principal != null)
+ {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(principal);
+ return new AuthenticationResult(subject);
+ }
+ else
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
+ }
+
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void configure(ConfigurationPlugin config) throws ConfigurationException
+ {
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java
index 21c9a85bf7..d735ecb1d4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java
@@ -19,6 +19,7 @@
package org.apache.qpid.server.security.auth.manager;
import java.io.IOException;
+import java.security.Principal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -126,7 +127,7 @@ public class KerberosAuthenticationManager implements AuthenticationManager
}
@Override
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
if(GSSAPI_MECHANISM.equals(mechanism))
{
@@ -181,19 +182,6 @@ public class KerberosAuthenticationManager implements AuthenticationManager
}
@Override
- public CallbackHandler getHandler(String mechanism)
- {
- if(GSSAPI_MECHANISM.equals(mechanism))
- {
- return _callbackHandler;
- }
- else
- {
- return null;
- }
- }
-
- @Override
public void close()
{
}
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 b34e6acc6d..24b365d34c 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
@@ -14,12 +14,13 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.security.auth.manager;
+import java.security.Principal;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -60,9 +61,9 @@ import java.util.TreeMap;
* Concrete implementation of the AuthenticationManager that determines if supplied
* user credentials match those appearing in a PrincipalDatabase. The implementation
* of the PrincipalDatabase is determined from the configuration.
- *
+ *
* This implementation also registers the JMX UserManagemement MBean.
- *
+ *
* This plugin expects configuration such as:
*
* <pre>
@@ -133,7 +134,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
};
public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin {
-
+
public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
{
public List<String> getParentPaths()
@@ -144,7 +145,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
{
final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration();
-
+
instance.setConfiguration(path, config);
return instance;
}
@@ -160,12 +161,12 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
public void validateConfiguration() throws ConfigurationException
{
}
-
+
public String getPrincipalDatabaseClass()
{
return getConfig().getString("principal-database.class");
}
-
+
public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
{
final List<String> argumentNames = (List) getConfig().getList("principal-database.attributes.attribute.name");
@@ -184,7 +185,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
- protected PrincipalDatabaseAuthenticationManager()
+ protected PrincipalDatabaseAuthenticationManager()
{
}
@@ -214,7 +215,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
registerManagement();
}
- private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database)
+ private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database)
{
if (database == null || database.getMechanisms().size() == 0)
{
@@ -262,7 +263,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
_principalDatabase = createPrincipalDatabaseImpl(pdClazz);
- configPrincipalDatabase(_principalDatabase, pdamConfig);
+ configPrincipalDatabase(_principalDatabase, pdamConfig);
}
public String getMechanisms()
@@ -270,7 +271,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
return _mechanisms;
}
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
_callbackHandlerMap.get(mechanism));
@@ -303,11 +304,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
- public CallbackHandler getHandler(String mechanism)
- {
- return _callbackHandlerMap.get(mechanism);
- }
-
/**
* @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
*/
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
index c41e814739..64b24e28bc 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
@@ -20,6 +20,7 @@
package org.apache.qpid.server.security.auth.manager;
import java.io.IOException;
+import java.security.Principal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
@@ -180,7 +181,7 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager
}
@Override
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
if(PLAIN_MECHANISM.equals(mechanism))
{
@@ -254,19 +255,6 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager
}
@Override
- public CallbackHandler getHandler(String mechanism)
- {
- if(PLAIN_MECHANISM.equals(mechanism))
- {
- return new PlainCallbackHandler();
- }
- else
- {
- return null;
- }
- }
-
- @Override
public void close()
{
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
new file mode 100644
index 0000000000..9c2bca2d0b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.auth.sasl.external;
+
+import java.security.Principal;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+
+public class ExternalSaslServer implements SaslServer
+{
+ public static final String MECHANISM = "EXTERNAL";
+
+ private boolean _complete = false;
+ private final Principal _externalPrincipal;
+
+ public ExternalSaslServer(Principal externalPrincipal)
+ {
+ _externalPrincipal = externalPrincipal;
+ }
+
+ public String getMechanismName()
+ {
+ return MECHANISM;
+ }
+
+ public byte[] evaluateResponse(byte[] response) throws SaslException
+ {
+ _complete = true;
+ return null;
+ }
+
+ public boolean isComplete()
+ {
+ return _complete;
+ }
+
+ public String getAuthorizationID()
+ {
+ return null;
+ }
+
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("Unsupported operation");
+ }
+
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("Unsupported operation");
+ }
+
+ public Object getNegotiatedProperty(String propName)
+ {
+ return null;
+ }
+
+ public void dispose() throws SaslException
+ {
+ }
+
+ public Principal getAuthenticatedPrincipal()
+ {
+ return _externalPrincipal;
+ }
+} \ No newline at end of file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
index 77d07e49f3..c9482b9712 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
@@ -20,6 +20,15 @@
*/
package org.apache.qpid.server.transport;
+import java.security.Principal;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.management.JMException;
+import javax.security.auth.Subject;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.configuration.ConnectionConfig;
@@ -33,7 +42,6 @@ import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Connection;
@@ -48,16 +56,6 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTIO
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
-import javax.management.JMException;
-import javax.security.auth.Subject;
-import java.security.Principal;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-
public class ServerConnection extends Connection implements Managable, AMQConnectionModel, LogSubject, AuthorizationHolder
{
private ConnectionConfig _config;
@@ -75,6 +73,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
private VirtualHost _virtualHost;
private AtomicLong _lastIoTime = new AtomicLong();
private boolean _blocking;
+ private Principal _peerPrincipal;
public ServerConnection(final long connectionId)
{
@@ -430,7 +429,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
else
{
_authorizedSubject = authorizedSubject;
- _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ _authorizedPrincipal = authorizedSubject.getPrincipals().iterator().next();
}
}
@@ -539,4 +538,14 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
{
return getConnectionDelegate().getClientVersion();
}
+
+ public Principal getPeerPrincipal()
+ {
+ return _peerPrincipal;
+ }
+
+ public void setPeerPrincipal(Principal peerPrincipal)
+ {
+ _peerPrincipal = peerPrincipal;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
index a55d50cc54..ad59c56878 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -20,14 +20,21 @@
*/
package org.apache.qpid.server.transport;
-import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD;
-
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.common.ServerPropertyNames;
import org.apache.qpid.properties.ConnectionStartProperties;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.AuthenticationResult;
@@ -40,16 +47,7 @@ import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
+import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD;
public class ServerConnectionDelegate extends ServerDelegate
{
@@ -112,17 +110,16 @@ public class ServerConnectionDelegate extends ServerDelegate
return ssn;
}
- protected SaslServer createSaslServer(String mechanism) throws SaslException
+ protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException
{
- return _authManager.createSaslServer(mechanism, _localFQDN);
+ return _authManager.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal());
}
protected void secure(final SaslServer ss, final Connection conn, final byte[] response)
{
- final AuthenticationResult authResult = _authManager.authenticate(ss, response);
final ServerConnection sconn = (ServerConnection) conn;
-
+ final AuthenticationResult authResult = _authManager.authenticate(ss, response);
if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus()))
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java
index eecde964a3..9dcd22c088 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java
@@ -79,13 +79,13 @@ public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase
public void testCreateSaslServer() throws Exception
{
- SaslServer server = _manager.createSaslServer("ANONYMOUS", "example.example.com");
+ SaslServer server = _manager.createSaslServer("ANONYMOUS", "example.example.com", null);
assertEquals("Sasl Server mechanism name is not as expected", "ANONYMOUS", server.getMechanismName());
try
{
- server = _manager.createSaslServer("PLAIN", "example.example.com");
+ server = _manager.createSaslServer("PLAIN", "example.example.com", null);
fail("Expected creating SaslServer with incorrect mechanism to throw an exception");
}
catch (SaslException e)
@@ -96,7 +96,7 @@ public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase
public void testAuthenticate() throws Exception
{
- SaslServer saslServer = _manager.createSaslServer("ANONYMOUS", "example.example.com");
+ SaslServer saslServer = _manager.createSaslServer("ANONYMOUS", "example.example.com", null);
AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]);
assertNotNull(result);
assertEquals("Expected authentication to be successful",
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
new file mode 100644
index 0000000000..c1a55ef2ad
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import javax.security.auth.x500.X500Principal;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+
+public class ExternalAuthenticationManagerTest extends InternalBrokerBaseCase
+{
+
+ private AuthenticationManager _manager = null;
+
+ public void setUp() throws Exception
+ {
+ _manager = ExternalAuthenticationManager.INSTANCE;
+ }
+
+
+ public void tearDown() throws Exception
+ {
+ if(_manager != null)
+ {
+ _manager = null;
+ }
+ }
+
+ private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException
+ {
+ final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration();
+
+ XMLConfiguration xmlconfig = new XMLConfiguration();
+ xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName());
+
+ // Create a CompositeConfiguration as this is what the broker uses
+ CompositeConfiguration composite = new CompositeConfiguration();
+ composite.addConfiguration(xmlconfig);
+ config.setConfiguration("security", xmlconfig);
+ return config;
+ }
+
+
+ public void testConfiguration() throws Exception
+ {
+ AuthenticationManager authenticationManager =
+ ExternalAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig());
+
+ assertNull("ExternalAuthenticationManager unexpectedly created when not in config", authenticationManager);
+ }
+
+ public void testGetMechanisms() throws Exception
+ {
+ assertEquals("EXTERNAL", _manager.getMechanisms());
+ }
+
+ public void testCreateSaslServer() throws Exception
+ {
+ SaslServer server = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
+
+ assertEquals("Sasl Server mechanism name is not as expected", "EXTERNAL", server.getMechanismName());
+
+ try
+ {
+ server = _manager.createSaslServer("PLAIN", "example.example.com", null);
+ fail("Expected creating SaslServer with incorrect mechanism to throw an exception");
+ }
+ catch (SaslException e)
+ {
+ // pass
+ }
+ }
+
+ public void testAuthenticate() throws Exception
+ {
+ X500Principal principal = new X500Principal("CN=person, DC=example, DC=com");
+ SaslServer saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+
+ AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertEquals("Expected principal to be unchanged",
+ principal,
+ result.getSubject().getPrincipals().iterator().next());
+
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+
+ }
+
+
+}
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 1a42fe3886..47c189e4fa 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
@@ -167,7 +167,7 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
*/
public void testSaslMechanismCreation() throws Exception
{
- SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost");
+ SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost", null);
assertNotNull(server);
// Merely tests the creation of the mechanism. Mechanisms themselves are tested
// by their own tests.
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 df3bbb3e8b..f6675e917e 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,6 +20,7 @@
*/
package org.apache.qpid.server.security.auth.rmi;
+import java.security.Principal;
import junit.framework.TestCase;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
@@ -29,7 +30,6 @@ import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import java.util.Collections;
@@ -71,14 +71,14 @@ public class RMIPasswordAuthenticatorTest extends TestCase
newSubject.equals(expectedSubject));
}
-
+
/**
* Tests a unsuccessful authentication.
*/
public void testUsernameOrPasswordInvalid()
{
_rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null));
-
+
try
{
_rmipa.authenticate(_credentials);
@@ -166,7 +166,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
}
-
+
// Test handling of null credentials
try
{
@@ -180,7 +180,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage());
}
-
+
try
{
//send a null password
@@ -193,7 +193,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
}
-
+
try
{
//send a null username
@@ -232,7 +232,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
throw new UnsupportedOperationException();
}
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
throw new UnsupportedOperationException();
}
@@ -257,10 +257,6 @@ public class RMIPasswordAuthenticatorTest extends TestCase
}
}
- public CallbackHandler getHandler(String mechanism)
- {
- return null;
- }
};
}
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
index 472beb6bb1..20d6f98fa6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
@@ -25,17 +25,17 @@ import java.net.InetSocketAddress;
/**
* This interface provides a means for NetworkDrivers to configure TCP options such as incoming and outgoing
* buffer sizes and set particular options on the socket. NetworkDrivers should honour the values returned
- * from here if the underlying implementation supports them.
- */
-public interface NetworkTransportConfiguration
-{
- // Taken from Socket
- Boolean getTcpNoDelay();
+ * from here if the underlying implementation supports them.
+ */
+public interface NetworkTransportConfiguration
+{
+ // Taken from Socket
+ Boolean getTcpNoDelay();
- // The amount of memory in bytes to allocate to the incoming buffer
- Integer getReceiveBufferSize();
+ // The amount of memory in bytes to allocate to the incoming buffer
+ Integer getReceiveBufferSize();
- // The amount of memory in bytes to allocate to the outgoing buffer
+ // The amount of memory in bytes to allocate to the outgoing buffer
Integer getSendBufferSize();
Integer getPort();
@@ -47,4 +47,8 @@ public interface NetworkTransportConfiguration
Integer getConnectorProcessors();
InetSocketAddress getAddress();
+
+ boolean needClientAuth();
+
+ boolean wantClientAuth();
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
index ec409d1c72..e9a7d51456 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
@@ -78,7 +78,7 @@ public class ServerDelegate extends ConnectionDelegate
try
{
- SaslServer ss = createSaslServer(mechanism);
+ SaslServer ss = createSaslServer(conn, mechanism);
if (ss == null)
{
conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED,
@@ -94,7 +94,7 @@ public class ServerDelegate extends ConnectionDelegate
}
}
- protected SaslServer createSaslServer(String mechanism)
+ protected SaslServer createSaslServer(Connection conn, String mechanism)
throws SaslException
{
SaslServer ss = Sasl.createSaslServer(mechanism, "AMQP", "localhost", null, null);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
index 2cc7c14f00..12c42d6643 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.transport.network;
-import org.apache.qpid.transport.Sender;
-
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
+import org.apache.qpid.transport.Sender;
public interface NetworkConnection
{
@@ -46,4 +46,8 @@ public interface NetworkConnection
void setMaxWriteIdle(int sec);
void setMaxReadIdle(int sec);
-} \ No newline at end of file
+
+ void setPeerPrincipal(Principal principal);
+
+ Principal getPeerPrincipal();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
index 4046691779..2658296c5f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
@@ -20,16 +20,15 @@
*/
package org.apache.qpid.transport.network.io;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
-
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.NetworkConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class IoNetworkConnection implements NetworkConnection
{
@@ -38,6 +37,7 @@ public class IoNetworkConnection implements NetworkConnection
private final long _timeout;
private final IoSender _ioSender;
private final IoReceiver _ioReceiver;
+ private Principal _principal;
public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate,
int sendBufferSize, int receiveBufferSize, long timeout)
@@ -97,4 +97,16 @@ public class IoNetworkConnection implements NetworkConnection
// TODO implement support for setting heartbeating config in this way
// Currently a socket timeout is used in IoSender
}
+
+ @Override
+ public void setPeerPrincipal(Principal principal)
+ {
+ _principal = principal;
+ }
+
+ @Override
+ public Principal getPeerPrincipal()
+ {
+ return _principal;
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
index 42c8334a5d..56f6989aae 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
@@ -27,10 +27,12 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
-
+import java.security.Principal;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
-
+import javax.net.ssl.SSLSocket;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.protocol.ProtocolEngineFactory;
import org.apache.qpid.transport.ConnectionSettings;
@@ -167,6 +169,9 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
{
SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
_serverSocket = socketFactory.createServerSocket();
+ ((SSLServerSocket)_serverSocket).setNeedClientAuth(config.needClientAuth());
+ ((SSLServerSocket)_serverSocket).setWantClientAuth(config.wantClientAuth());
+
}
_serverSocket.setReuseAddress(true);
@@ -216,10 +221,24 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
socket.setSendBufferSize(sendBufferSize);
socket.setReceiveBufferSize(receiveBufferSize);
+
ProtocolEngine engine = _factory.newProtocolEngine();
NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout);
+ if(_sslContext != null)
+ {
+ try
+ {
+ Principal peerPrincipal = ((SSLSocket) socket).getSession().getPeerPrincipal();
+ connection.setPeerPrincipal(peerPrincipal);
+ }
+ catch(SSLPeerUnverifiedException e)
+ {
+ // ignore
+ }
+ }
+
engine.setNetworkConnection(connection, connection.getSender());
connection.start();
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
index 548e8dab12..893f66c5ff 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.transport;
+import java.security.Principal;
import org.apache.qpid.protocol.ProtocolEngineFactory;
import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.transport.network.NetworkConnection;
@@ -71,6 +72,17 @@ public class TestNetworkConnection implements NetworkConnection
}
+ @Override
+ public void setPeerPrincipal(Principal principal)
+ {
+ }
+
+ @Override
+ public Principal getPeerPrincipal()
+ {
+ return null;
+ }
+
public void setMaxWriteIdle(int idleTime)
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
index 1cd088b736..39689f5096 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
@@ -46,6 +46,7 @@ public class SSLTest extends QpidBrokerTestCase
setTestClientSystemProperty("profile.use_ssl", "true");
setConfigurationProperty("connector.ssl.enabled", "true");
setConfigurationProperty("connector.ssl.sslOnly", "true");
+ setConfigurationProperty("connector.ssl.wantClientAuth", "true");
}
// set the ssl system properties
diff --git a/qpid/java/test-profiles/JavaExcludes b/qpid/java/test-profiles/JavaExcludes
index 9741eed2e9..738467c60f 100644
--- a/qpid/java/test-profiles/JavaExcludes
+++ b/qpid/java/test-profiles/JavaExcludes
@@ -28,9 +28,6 @@ org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
//Moved from JavaStandaloneExcludes when it was removed
///////////////////////////////////////////////////////
-//The Java broker doesnt support client auth
-org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
-
//QPID-3605 Durable subscriber with no-local true receives messages on re-connection
org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testNoLocalMessagesNotDeliveredAfterReconnection
diff --git a/qpid/java/test-profiles/JavaPre010Excludes b/qpid/java/test-profiles/JavaPre010Excludes
index 363804abcb..3f29dee203 100644
--- a/qpid/java/test-profiles/JavaPre010Excludes
+++ b/qpid/java/test-profiles/JavaPre010Excludes
@@ -37,6 +37,9 @@ org.apache.qpid.server.queue.AddressBasedSortedQueueTest#*
org.apache.qpid.test.unit.message.UTF8Test#*
org.apache.qpid.client.SynchReceiveTest#testReceiveNoWait
+// Makes explicit use of 0-10 connection object
+org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
+
// Tests 0.10 client feature
org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnsupportedSASLMechanism