You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2017/08/08 17:34:03 UTC
[4/5] activemq-artemis git commit: [ARTEMIS-1310] add amqp sasl
gssapi mechanism support
[ARTEMIS-1310] add amqp sasl gssapi mechanism support
delegate to the jdk saslServer. Allow acceptor configuration of supported mechanismis; saslMechanisms=<a,b>
and allow login config scope for krb5 to be configured via saslLoginConfigScope=x
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/ca7197b5
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/ca7197b5
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/ca7197b5
Branch: refs/heads/master
Commit: ca7197b5c3b1a1d945ee8c00967f33cf37d0cfbe
Parents: 766f412
Author: gtully <ga...@gmail.com>
Authored: Fri Jul 28 16:02:32 2017 +0100
Committer: Clebert Suconic <cl...@apache.org>
Committed: Tue Aug 8 13:28:50 2017 -0400
----------------------------------------------------------------------
.../artemis/core/remoting/CertificateUtil.java | 31 ++--
.../protocol/AbstractRemotingConnection.java | 7 +
.../spi/core/protocol/RemotingConnection.java | 8 +
.../amqp/broker/AMQPConnectionCallback.java | 36 +++--
.../ActiveMQProtonRemotingConnection.java | 12 ++
.../amqp/broker/ProtonProtocolManager.java | 33 ++++
.../amqp/proton/AMQPConnectionContext.java | 14 +-
.../amqp/proton/handler/EventHandler.java | 2 +
.../amqp/proton/handler/ProtonHandler.java | 67 +++++---
.../protocol/amqp/sasl/AnonymousServerSASL.java | 16 +-
.../protocol/amqp/sasl/GSSAPISASLResult.java | 51 +++++++
.../protocol/amqp/sasl/GSSAPIServerSASL.java | 114 ++++++++++++++
.../protocol/amqp/sasl/MechanismFinder.java | 27 ++++
.../protocol/amqp/sasl/PlainSASLResult.java | 8 +
.../artemis/protocol/amqp/sasl/SASLResult.java | 4 +
.../artemis/protocol/amqp/sasl/ServerSASL.java | 6 +-
.../protocol/amqp/sasl/ServerSASLPlain.java | 16 +-
.../protocol/amqp/sasl/PlainSASLTest.java | 3 +-
.../core/protocol/mqtt/MQTTConnection.java | 7 +
.../openwire/OpenWireProtocolManager.java | 2 +-
.../core/protocol/stomp/StompConnection.java | 9 +-
.../protocol/stomp/StompProtocolManager.java | 6 +-
.../stomp/v10/StompFrameHandlerV10.java | 2 +-
.../stomp/v11/StompFrameHandlerV11.java | 2 +-
.../artemis/core/security/SecurityStore.java | 4 +-
.../core/security/impl/SecurityStoreImpl.java | 6 +-
.../core/server/impl/ActiveMQServerImpl.java | 2 +-
.../security/ActiveMQJAASSecurityManager.java | 18 +--
.../core/security/ActiveMQSecurityManager3.java | 9 +-
.../core/security/jaas/JaasCallbackHandler.java | 27 +++-
.../spi/core/security/jaas/Krb5Callback.java | 46 ++++++
.../spi/core/security/jaas/Krb5LoginModule.java | 112 ++++++++++++++
.../spi/core/security/jaas/Krb5SslCallback.java | 46 ------
.../core/security/jaas/Krb5SslLoginModule.java | 112 --------------
docs/user-manual/en/security.md | 19 +++
.../amqp/JMSConnectionWithSecurityTest.java | 5 +
.../integration/amqp/JMSSaslGssapiTest.java | 151 +++++++++++++++++++
.../integration/security/SecurityTest.java | 7 +-
.../src/test/resources/login.config | 16 +-
39 files changed, 813 insertions(+), 250 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/CertificateUtil.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/CertificateUtil.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/CertificateUtil.java
index 598fcf3..57c2309 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/CertificateUtil.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/CertificateUtil.java
@@ -20,6 +20,7 @@ package org.apache.activemq.artemis.core.remoting;
import io.netty.channel.ChannelHandler;
import io.netty.handler.ssl.SslHandler;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import javax.net.ssl.SSLPeerUnverifiedException;
@@ -28,24 +29,30 @@ import java.security.Principal;
public class CertificateUtil {
- public static X509Certificate[] getCertsFromConnection(Connection connection) {
+ public static X509Certificate[] getCertsFromConnection(RemotingConnection remotingConnection) {
X509Certificate[] certificates = null;
- if (connection instanceof NettyConnection) {
- certificates = org.apache.activemq.artemis.utils.CertificateUtil.getCertsFromChannel(((NettyConnection) connection).getChannel());
+ if (remotingConnection != null) {
+ Connection transportConnection = remotingConnection.getTransportConnection();
+ if (transportConnection instanceof NettyConnection) {
+ certificates = org.apache.activemq.artemis.utils.CertificateUtil.getCertsFromChannel(((NettyConnection) transportConnection).getChannel());
+ }
}
return certificates;
}
- public static Principal getPeerPrincipalFromConnection(Connection connection) {
+ public static Principal getPeerPrincipalFromConnection(RemotingConnection remotingConnection) {
Principal result = null;
- if (connection instanceof NettyConnection) {
- NettyConnection nettyConnection = (NettyConnection) connection;
- ChannelHandler channelHandler = nettyConnection.getChannel().pipeline().get("ssl");
- if (channelHandler != null && channelHandler instanceof SslHandler) {
- SslHandler sslHandler = (SslHandler) channelHandler;
- try {
- result = sslHandler.engine().getSession().getPeerPrincipal();
- } catch (SSLPeerUnverifiedException ignored) {
+ if (remotingConnection != null) {
+ Connection transportConnection = remotingConnection.getTransportConnection();
+ if (transportConnection instanceof NettyConnection) {
+ NettyConnection nettyConnection = (NettyConnection) transportConnection;
+ ChannelHandler channelHandler = nettyConnection.getChannel().pipeline().get("ssl");
+ if (channelHandler != null && channelHandler instanceof SslHandler) {
+ SslHandler sslHandler = (SslHandler) channelHandler;
+ try {
+ result = sslHandler.engine().getSession().getPeerPrincipal();
+ } catch (SSLPeerUnverifiedException ignored) {
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java
index a9e12aa..3893902 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java
@@ -32,6 +32,8 @@ import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
import org.jboss.logging.Logger;
+import javax.security.auth.Subject;
+
public abstract class AbstractRemotingConnection implements RemotingConnection {
private static final Logger logger = Logger.getLogger(AbstractRemotingConnection.class);
@@ -219,4 +221,9 @@ public abstract class AbstractRemotingConnection implements RemotingConnection {
public boolean isSupportsFlowControl() {
return true;
}
+
+ @Override
+ public Subject getSubject() {
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java
index 39ecdf6..4cda8c0 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java
@@ -27,6 +27,8 @@ import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
+import javax.security.auth.Subject;
+
/**
* A RemotingConnection is a connection between a client and a server.
*
@@ -206,4 +208,10 @@ public interface RemotingConnection extends BufferHandler {
* @return
*/
boolean isSupportsFlowControl();
+
+ /**
+ * the possibly null identity associated with this connection
+ * @return
+ */
+ Subject getSubject();
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallback.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallback.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallback.java
index a5ed973..47b5f69 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallback.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallback.java
@@ -43,6 +43,7 @@ import org.apache.activemq.artemis.protocol.amqp.proton.AmqpSupport;
import org.apache.activemq.artemis.protocol.amqp.proton.transaction.ProtonTransactionImpl;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ExtCapability;
import org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASL;
+import org.apache.activemq.artemis.protocol.amqp.sasl.GSSAPIServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.PlainSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
@@ -76,6 +77,8 @@ public class AMQPConnectionCallback implements FailureListener, CloseListener {
private ActiveMQServer server;
+ private final String[] saslMechanisms;
+
public AMQPConnectionCallback(ProtonProtocolManager manager,
Connection connection,
Executor closeExecutor,
@@ -84,25 +87,40 @@ public class AMQPConnectionCallback implements FailureListener, CloseListener {
this.connection = connection;
this.closeExecutor = closeExecutor;
this.server = server;
+ saslMechanisms = manager.getSaslMechanisms();
}
- public ServerSASL[] getSASLMechnisms() {
-
- ServerSASL[] result;
+ public String[] getSaslMechanisms() {
+ return saslMechanisms;
+ }
- if (isSupportsAnonymous()) {
- result = new ServerSASL[]{new PlainSASL(manager.getServer().getSecurityStore()), new AnonymousServerSASL()};
- } else {
- result = new ServerSASL[]{new PlainSASL(manager.getServer().getSecurityStore())};
+ public ServerSASL getServerSASL(final String mechanism) {
+ ServerSASL result = null;
+ switch (mechanism) {
+ case PlainSASL.NAME:
+ result = new PlainSASL(server.getSecurityStore());
+ break;
+
+ case AnonymousServerSASL.NAME:
+ result = new AnonymousServerSASL();
+ break;
+
+ case GSSAPIServerSASL.NAME:
+ GSSAPIServerSASL gssapiServerSASL = new GSSAPIServerSASL();
+ gssapiServerSASL.setLoginConfigScope(manager.getSaslLoginConfigScope());
+ result = gssapiServerSASL;
+ break;
+
+ default:
+ break;
}
-
return result;
}
public boolean isSupportsAnonymous() {
boolean supportsAnonymous = false;
try {
- manager.getServer().getSecurityStore().authenticate(null, null, null);
+ server.getSecurityStore().authenticate(null, null, null);
supportsAnonymous = true;
} catch (Exception e) {
// authentication failed so no anonymous support
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java
index 4a1fe80..1441b96 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java
@@ -25,10 +25,13 @@ import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.proton.AmqpSupport;
+import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.spi.core.protocol.AbstractRemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
+import javax.security.auth.Subject;
+
/**
* This is a Server's Connection representation used by ActiveMQ Artemis.
*/
@@ -148,4 +151,13 @@ public class ActiveMQProtonRemotingConnection extends AbstractRemotingConnection
public void killMessage(SimpleString nodeID) {
//unsupported
}
+
+ @Override
+ public Subject getSubject() {
+ SASLResult saslResult = amqpConnection.getSASLResult();
+ if (saslResult != null) {
+ return saslResult.getSubject();
+ }
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java
index d36f18e..8f88d8f 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManager.java
@@ -36,6 +36,7 @@ import org.apache.activemq.artemis.core.server.management.NotificationListener;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConstants;
+import org.apache.activemq.artemis.protocol.amqp.sasl.MechanismFinder;
import org.apache.activemq.artemis.spi.core.protocol.AbstractProtocolManager;
import org.apache.activemq.artemis.spi.core.protocol.ConnectionEntry;
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory;
@@ -63,6 +64,12 @@ public class ProtonProtocolManager extends AbstractProtocolManager<AMQPMessage,
private int amqpLowCredits = 30;
+ private int initialRemoteMaxFrameSize = 4 * 1024;
+
+ private String[] saslMechanisms = MechanismFinder.getKnownMechanisms();
+
+ private String saslLoginConfigScope = "amqp-sasl-gssapi";
+
/*
* used when you want to treat senders as a subscription on an address rather than consuming from the actual queue for
* the address. This can be changed on the acceptor.
@@ -197,6 +204,23 @@ public class ProtonProtocolManager extends AbstractProtocolManager<AMQPMessage,
this.maxFrameSize = maxFrameSize;
}
+ public String[] getSaslMechanisms() {
+ return saslMechanisms;
+ }
+
+ public void setSaslMechanisms(String[] saslMechanisms) {
+ this.saslMechanisms = saslMechanisms;
+ }
+
+ public String getSaslLoginConfigScope() {
+ return saslLoginConfigScope;
+ }
+
+ public void setSaslLoginConfigScope(String saslLoginConfigScope) {
+ this.saslLoginConfigScope = saslLoginConfigScope;
+ }
+
+
@Override
public void setAnycastPrefix(String anycastPrefix) {
for (String prefix : anycastPrefix.split(",")) {
@@ -223,4 +247,13 @@ public class ProtonProtocolManager extends AbstractProtocolManager<AMQPMessage,
public void invokeOutgoing(AMQPMessage message, ActiveMQProtonRemotingConnection connection) {
super.invokeInterceptors(this.outgoingInterceptors, message, connection);
}
+
+ public int getInitialRemoteMaxFrameSize() {
+ return initialRemoteMaxFrameSize;
+ }
+
+ public void setInitialRemoteMaxFrameSize(int initialRemoteMaxFrameSize) {
+ this.initialRemoteMaxFrameSize = initialRemoteMaxFrameSize;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPConnectionContext.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPConnectionContext.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPConnectionContext.java
index 0ab4171..47cb11d 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPConnectionContext.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPConnectionContext.java
@@ -34,6 +34,7 @@ import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPExceptio
import org.apache.activemq.artemis.protocol.amqp.proton.handler.EventHandler;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ExtCapability;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ProtonHandler;
+import org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
import org.apache.activemq.artemis.utils.ByteUtil;
@@ -103,6 +104,7 @@ public class AMQPConnectionContext extends ProtonInitializable implements EventH
transport.setIdleTimeout(idleTimeout);
}
transport.setChannelMax(channelMax);
+ transport.setInitialRemoteMaxFrameSize(protocolManager.getInitialRemoteMaxFrameSize());
transport.setMaxFrameSize(maxFrameSize);
}
@@ -321,7 +323,12 @@ public class AMQPConnectionContext extends ProtonInitializable implements EventH
@Override
public void onAuthInit(ProtonHandler handler, Connection connection, boolean sasl) {
if (sasl) {
- handler.createServerSASL(connectionCallback.getSASLMechnisms());
+ // configured mech in decreasing order of preference
+ String[] mechanisms = connectionCallback.getSaslMechanisms();
+ if (mechanisms == null || mechanisms.length == 0) {
+ mechanisms = AnonymousServerSASL.ANONYMOUS_MECH;
+ }
+ handler.createServerSASL(mechanisms);
} else {
if (!connectionCallback.isSupportsAnonymous()) {
connectionCallback.sendSASLSupported();
@@ -332,6 +339,11 @@ public class AMQPConnectionContext extends ProtonInitializable implements EventH
}
@Override
+ public void onSaslRemoteMechanismChosen(ProtonHandler handler, String mech) {
+ handler.setChosenMechanism(connectionCallback.getServerSASL(mech));
+ }
+
+ @Override
public void onTransport(Transport transport) {
handler.flushBytes();
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/EventHandler.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/EventHandler.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/EventHandler.java
index c8ba136..8b99284 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/EventHandler.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/EventHandler.java
@@ -31,6 +31,8 @@ public interface EventHandler {
void onAuthInit(ProtonHandler handler, Connection connection, boolean sasl);
+ void onSaslRemoteMechanismChosen(ProtonHandler handler, String mech);
+
void onInit(Connection connection) throws Exception;
void onLocalOpen(Connection connection) throws Exception;
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java
index eb95dec..918b383 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java
@@ -18,7 +18,6 @@ package org.apache.activemq.artemis.protocol.amqp.proton.handler;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
@@ -63,12 +62,12 @@ public class ProtonHandler extends ProtonInitializable {
private Sasl serverSasl;
+ private ServerSASL chosenMechanism;
+
private final ReentrantLock lock = new ReentrantLock();
private final long creationTime;
- private Map<String, ServerSASL> saslHandlers;
-
private SASLResult saslResult;
protected volatile boolean dataReceived;
@@ -157,17 +156,10 @@ public class ProtonHandler extends ProtonInitializable {
return this;
}
- public void createServerSASL(ServerSASL[] handlers) {
+ public void createServerSASL(String[] mechanisms) {
this.serverSasl = transport.sasl();
- saslHandlers = new HashMap<>();
- String[] names = new String[handlers.length];
- int count = 0;
- for (ServerSASL handler : handlers) {
- saslHandlers.put(handler.getName(), handler);
- names[count++] = handler.getName();
- }
this.serverSasl.server();
- serverSasl.setMechanisms(names);
+ serverSasl.setMechanisms(mechanisms);
}
public void flushBytes() {
@@ -292,9 +284,14 @@ public class ProtonHandler extends ProtonInitializable {
protected void checkServerSASL() {
if (serverSasl != null && serverSasl.getRemoteMechanisms().length > 0) {
- // TODO: should we look at the first only?
- ServerSASL mechanism = saslHandlers.get(serverSasl.getRemoteMechanisms()[0]);
- if (mechanism != null) {
+
+ if (chosenMechanism == null) {
+ if (log.isTraceEnabled()) {
+ log.trace("SASL chosenMechanism: " + serverSasl.getRemoteMechanisms()[0]);
+ }
+ dispatchRemoteMechanismChosen(serverSasl.getRemoteMechanisms()[0]);
+ }
+ if (chosenMechanism != null) {
byte[] dataSASL = new byte[serverSasl.pending()];
serverSasl.recv(dataSASL, 0, dataSASL.length);
@@ -303,30 +300,46 @@ public class ProtonHandler extends ProtonInitializable {
log.trace("Working on sasl::" + (dataSASL != null && dataSASL.length > 0 ? ByteUtil.bytesToHex(dataSASL, 2) : "Anonymous"));
}
- saslResult = mechanism.processSASL(dataSASL);
+ byte[] response = chosenMechanism.processSASL(dataSASL);
+ if (response != null) {
+ serverSasl.send(response, 0, response.length);
+ }
+ saslResult = chosenMechanism.result();
- if (saslResult != null && saslResult.isSuccess()) {
- serverSasl.done(Sasl.SaslOutcome.PN_SASL_OK);
- serverSasl = null;
- saslHandlers.clear();
- saslHandlers = null;
- } else {
- serverSasl.done(Sasl.SaslOutcome.PN_SASL_AUTH);
+ if (saslResult != null) {
+ if (saslResult.isSuccess()) {
+ saslComplete(Sasl.SaslOutcome.PN_SASL_OK);
+ } else {
+ saslComplete(Sasl.SaslOutcome.PN_SASL_AUTH);
+ }
}
- serverSasl = null;
} else {
// no auth available, system error
- serverSasl.done(Sasl.SaslOutcome.PN_SASL_SYS);
+ saslComplete(Sasl.SaslOutcome.PN_SASL_SYS);
}
}
}
+ private void saslComplete(Sasl.SaslOutcome saslOutcome) {
+ serverSasl.done(saslOutcome);
+ serverSasl = null;
+ if (chosenMechanism != null) {
+ chosenMechanism.done();
+ }
+ }
+
private void dispatchAuth(boolean sasl) {
for (EventHandler h : handlers) {
h.onAuthInit(this, getConnection(), sasl);
}
}
+ private void dispatchRemoteMechanismChosen(final String mech) {
+ for (EventHandler h : handlers) {
+ h.onSaslRemoteMechanismChosen(this, mech);
+ }
+ }
+
private void dispatch() {
Event ev;
@@ -376,4 +389,8 @@ public class ProtonHandler extends ProtonInitializable {
this.connection.open();
flush();
}
+
+ public void setChosenMechanism(ServerSASL chosenMechanism) {
+ this.chosenMechanism = chosenMechanism;
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/AnonymousServerSASL.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/AnonymousServerSASL.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/AnonymousServerSASL.java
index 013b73b..63f320d 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/AnonymousServerSASL.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/AnonymousServerSASL.java
@@ -18,17 +18,29 @@ package org.apache.activemq.artemis.protocol.amqp.sasl;
public class AnonymousServerSASL implements ServerSASL {
+ public static final String NAME = "ANONYMOUS";
+ public static final String[] ANONYMOUS_MECH = new String[] {NAME};
+
public AnonymousServerSASL() {
}
@Override
public String getName() {
- return "ANONYMOUS";
+ return NAME;
+ }
+
+ @Override
+ public byte[] processSASL(byte[] bytes) {
+ return null;
}
@Override
- public SASLResult processSASL(byte[] bytes) {
+ public SASLResult result() {
return new PlainSASLResult(true, null, null);
}
+
+ @Override
+ public void done() {
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPISASLResult.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPISASLResult.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPISASLResult.java
new file mode 100644
index 0000000..0b6e378
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPISASLResult.java
@@ -0,0 +1,51 @@
+/*
+ * 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.activemq.artemis.protocol.amqp.sasl;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+
+public class GSSAPISASLResult implements SASLResult {
+
+ private final boolean success;
+ private final Subject identity = new Subject();
+ private String user;
+
+
+ public GSSAPISASLResult(boolean success, Principal peer) {
+ this.success = success;
+ if (success) {
+ this.identity.getPrivateCredentials().add(peer);
+ this.user = peer.getName();
+ }
+ }
+
+ @Override
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public Subject getSubject() {
+ return identity;
+ }
+
+ @Override
+ public boolean isSuccess() {
+ return success;
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPIServerSASL.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPIServerSASL.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPIServerSASL.java
new file mode 100644
index 0000000..e89d548
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/GSSAPIServerSASL.java
@@ -0,0 +1,114 @@
+/*
+ * 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.activemq.artemis.protocol.amqp.sasl;
+
+import org.jboss.logging.Logger;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.login.LoginContext;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+
+/*
+ * delegate the the jdk GSSAPI support
+ */
+public class GSSAPIServerSASL implements ServerSASL {
+ private static final Logger log = Logger.getLogger(GSSAPIServerSASL.class);
+
+ public static final String NAME = "GSSAPI";
+ private String loginConfigScope;
+ private SaslServer saslServer;
+ private Subject jaasId;
+ private SASLResult result;
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public byte[] processSASL(byte[] bytes) {
+ try {
+ if (jaasId == null) {
+ // populate subject with acceptor private credentials
+ LoginContext loginContext = new LoginContext(loginConfigScope);
+ loginContext.login();
+ jaasId = loginContext.getSubject();
+ }
+
+ if (saslServer == null) {
+ saslServer = Subject.doAs(jaasId, (PrivilegedExceptionAction<SaslServer>) () -> Sasl.createSaslServer(NAME, null, null, new HashMap<String, String>(), new CallbackHandler() {
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (Callback callback : callbacks) {
+ if (callback instanceof AuthorizeCallback) {
+ AuthorizeCallback authorizeCallback = (AuthorizeCallback) callback;
+ // only ok to authenticate as self
+ authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals(authorizeCallback.getAuthorizationID()));
+ }
+ }
+ }
+ }));
+ }
+
+ byte[] challenge = Subject.doAs(jaasId, (PrivilegedExceptionAction<byte[]>) () -> saslServer.evaluateResponse(bytes));
+ if (saslServer.isComplete()) {
+ result = new GSSAPISASLResult(true, new KerberosPrincipal(saslServer.getAuthorizationID()));
+ }
+ return challenge;
+
+ } catch (Exception outOfHere) {
+ log.info("Error on sasl input: " + outOfHere.toString(), outOfHere);
+ result = new GSSAPISASLResult(false, null);
+ }
+ return null;
+ }
+
+ @Override
+ public SASLResult result() {
+ return result;
+ }
+
+ @Override
+ public void done() {
+ if (saslServer != null) {
+ try {
+ saslServer.dispose();
+ } catch (SaslException error) {
+ log.debug("Exception on sasl dispose", error);
+ }
+ }
+ }
+
+ public String getLoginConfigScope() {
+ return loginConfigScope;
+ }
+
+ public void setLoginConfigScope(String loginConfigScope) {
+ this.loginConfigScope = loginConfigScope;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/MechanismFinder.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/MechanismFinder.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/MechanismFinder.java
new file mode 100644
index 0000000..4a8b420
--- /dev/null
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/MechanismFinder.java
@@ -0,0 +1,27 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.activemq.artemis.protocol.amqp.sasl;
+
+public class MechanismFinder {
+
+ public static String[] KNOWN_MECHANISMS = new String[]{PlainSASL.NAME, GSSAPIServerSASL.NAME, AnonymousServerSASL.NAME};
+
+ public static String[] getKnownMechanisms() {
+ return KNOWN_MECHANISMS;
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLResult.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLResult.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLResult.java
index f138ae3..47683b3 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLResult.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLResult.java
@@ -16,6 +16,8 @@
*/
package org.apache.activemq.artemis.protocol.amqp.sasl;
+import javax.security.auth.Subject;
+
public class PlainSASLResult implements SASLResult {
private boolean success;
@@ -29,6 +31,11 @@ public class PlainSASLResult implements SASLResult {
}
@Override
+ public Subject getSubject() {
+ return null;
+ }
+
+ @Override
public String getUser() {
return user;
}
@@ -41,4 +48,5 @@ public class PlainSASLResult implements SASLResult {
public boolean isSuccess() {
return success;
}
+
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/SASLResult.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/SASLResult.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/SASLResult.java
index f8c4297..37324a4 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/SASLResult.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/SASLResult.java
@@ -16,9 +16,13 @@
*/
package org.apache.activemq.artemis.protocol.amqp.sasl;
+import javax.security.auth.Subject;
+
public interface SASLResult {
String getUser();
+ Subject getSubject();
+
boolean isSuccess();
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASL.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASL.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASL.java
index 43d57d0..f62b730 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASL.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASL.java
@@ -20,5 +20,9 @@ public interface ServerSASL {
String getName();
- SASLResult processSASL(byte[] bytes);
+ byte[] processSASL(byte[] bytes);
+
+ SASLResult result();
+
+ void done();
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java
index 177334c..42d9f94 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/ServerSASLPlain.java
@@ -19,6 +19,7 @@ package org.apache.activemq.artemis.protocol.amqp.sasl;
public class ServerSASLPlain implements ServerSASL {
public static final String NAME = "PLAIN";
+ private SASLResult result = null;
@Override
public String getName() {
@@ -26,7 +27,7 @@ public class ServerSASLPlain implements ServerSASL {
}
@Override
- public SASLResult processSASL(byte[] data) {
+ public byte[] processSASL(byte[] data) {
String username = null;
String password = null;
String bytes = new String(data);
@@ -47,7 +48,18 @@ public class ServerSASLPlain implements ServerSASL {
boolean success = authenticate(username, password);
- return new PlainSASLResult(success, username, password);
+ result = new PlainSASLResult(success, username, password);
+
+ return null;
+ }
+
+ @Override
+ public SASLResult result() {
+ return result;
+ }
+
+ @Override
+ public void done() {
}
/**
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLTest.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLTest.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLTest.java
index d259de2..9a2a0a2 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLTest.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/sasl/PlainSASLTest.java
@@ -27,7 +27,8 @@ public class PlainSASLTest {
byte[] bytesResult = plainSASL.getBytes();
ServerSASLPlain serverSASLPlain = new ServerSASLPlain();
- PlainSASLResult result = (PlainSASLResult) serverSASLPlain.processSASL(bytesResult);
+ serverSASLPlain.processSASL(bytesResult);
+ PlainSASLResult result = (PlainSASLResult) serverSASLPlain.result();
Assert.assertEquals("user-me", result.getUser());
Assert.assertEquals("password-secret", result.getPassword());
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java
index 446e362..e1afcb0 100644
--- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java
+++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java
@@ -31,6 +31,8 @@ import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
+import javax.security.auth.Subject;
+
public class MQTTConnection implements RemotingConnection {
private final Connection transportConnection;
@@ -226,4 +228,9 @@ public class MQTTConnection implements RemotingConnection {
public boolean isSupportsFlowControl() {
return false;
}
+
+ @Override
+ public Subject getSubject() {
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java
index a4acdeb..237789f 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java
@@ -459,7 +459,7 @@ public class OpenWireProtocolManager implements ProtocolManager<Interceptor>, Cl
}
public void validateUser(String login, String passcode, OpenWireConnection connection) throws Exception {
- server.getSecurityStore().authenticate(login, passcode, connection.getTransportConnection());
+ server.getSecurityStore().authenticate(login, passcode, connection);
}
public void sendBrokerInfo(OpenWireConnection connection) throws Exception {
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java
index db5dfd6..3bf2b1e 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java
@@ -51,6 +51,8 @@ import org.apache.activemq.artemis.utils.ConfigurationHelper;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.VersionLoader;
+import javax.security.auth.Subject;
+
import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProtocolMessageBundle.BUNDLE;
public final class StompConnection implements RemotingConnection {
@@ -560,7 +562,7 @@ public final class StompConnection implements RemotingConnection {
manager.sendReply(this, frame);
}
- public boolean validateUser(final String login, final String pass, final Connection connection) {
+ public boolean validateUser(final String login, final String pass, final RemotingConnection connection) {
this.valid = manager.validateUser(login, pass, connection);
if (valid) {
this.login = login;
@@ -779,4 +781,9 @@ public final class StompConnection implements RemotingConnection {
public boolean isSupportsFlowControl() {
return false;
}
+
+ @Override
+ public Subject getSubject() {
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
index fb60847..84c78c2 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
@@ -320,16 +320,16 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
return "activemq";
}
- public boolean validateUser(String login, String passcode, Connection connection) {
+ public boolean validateUser(String login, String passcode, RemotingConnection remotingConnection) {
boolean validated = true;
ActiveMQSecurityManager sm = server.getSecurityManager();
if (sm != null && server.getConfiguration().isSecurityEnabled()) {
if (sm instanceof ActiveMQSecurityManager3) {
- validated = ((ActiveMQSecurityManager3) sm).validateUser(login, passcode, connection) != null;
+ validated = ((ActiveMQSecurityManager3) sm).validateUser(login, passcode, remotingConnection) != null;
} else if (sm instanceof ActiveMQSecurityManager2) {
- validated = ((ActiveMQSecurityManager2) sm).validateUser(login, passcode, CertificateUtil.getCertsFromConnection(connection));
+ validated = ((ActiveMQSecurityManager2) sm).validateUser(login, passcode, CertificateUtil.getCertsFromConnection(remotingConnection));
} else {
validated = sm.validateUser(login, passcode);
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v10/StompFrameHandlerV10.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v10/StompFrameHandlerV10.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v10/StompFrameHandlerV10.java
index 51abf50..5633987 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v10/StompFrameHandlerV10.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v10/StompFrameHandlerV10.java
@@ -52,7 +52,7 @@ public class StompFrameHandlerV10 extends VersionedStompFrameHandler implements
String clientID = headers.get(Stomp.Headers.Connect.CLIENT_ID);
String requestID = headers.get(Stomp.Headers.Connect.REQUEST_ID);
- if (connection.validateUser(login, passcode, connection.getTransportConnection())) {
+ if (connection.validateUser(login, passcode, connection)) {
connection.setClientID(clientID);
connection.setValid(true);
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java
index 9e013f8..f9af9f2 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java
@@ -68,7 +68,7 @@ public class StompFrameHandlerV11 extends VersionedStompFrameHandler implements
String requestID = headers.get(Stomp.Headers.Connect.REQUEST_ID);
try {
- if (connection.validateUser(login, passcode, connection.getTransportConnection())) {
+ if (connection.validateUser(login, passcode, connection)) {
connection.setClientID(clientID);
connection.setValid(true);
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java
index 1f65443..987faad 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java
@@ -17,11 +17,11 @@
package org.apache.activemq.artemis.core.security;
import org.apache.activemq.artemis.api.core.SimpleString;
-import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
public interface SecurityStore {
- String authenticate(String user, String password, Connection transportConnection) throws Exception;
+ String authenticate(String user, String password, RemotingConnection remotingConnection) throws Exception;
void check(SimpleString address, CheckType checkType, SecurityAuth session) throws Exception;
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
index 9d769db..f4a7013 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
@@ -34,7 +34,7 @@ import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.core.server.management.NotificationService;
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
import org.apache.activemq.artemis.core.settings.HierarchicalRepositoryChangeListener;
-import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager2;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3;
@@ -104,7 +104,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
@Override
public String authenticate(final String user,
final String password,
- Connection connection) throws Exception {
+ RemotingConnection connection) throws Exception {
if (securityEnabled) {
if (managementClusterUser.equals(user)) {
@@ -185,7 +185,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
final boolean validated;
if (securityManager instanceof ActiveMQSecurityManager3) {
final ActiveMQSecurityManager3 securityManager3 = (ActiveMQSecurityManager3) securityManager;
- validated = securityManager3.validateUserAndRole(user, session.getPassword(), roles, checkType, saddress, session.getRemotingConnection().getTransportConnection()) != null;
+ validated = securityManager3.validateUserAndRole(user, session.getPassword(), roles, checkType, saddress, session.getRemotingConnection()) != null;
} else if (securityManager instanceof ActiveMQSecurityManager2) {
final ActiveMQSecurityManager2 securityManager2 = (ActiveMQSecurityManager2) securityManager;
validated = securityManager2.validateUserAndRole(user, session.getPassword(), roles, checkType, saddress, session.getRemotingConnection());
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
index 4856d8b..8d9ce99 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
@@ -1394,7 +1394,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
String validatedUser = "";
if (securityStore != null) {
- validatedUser = securityStore.authenticate(username, password, connection.getTransportConnection());
+ validatedUser = securityStore.authenticate(username, password, connection);
}
checkSessionLimit(validatedUser);
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQJAASSecurityManager.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQJAASSecurityManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQJAASSecurityManager.java
index dc4e3a8..aaaec82 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQJAASSecurityManager.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQJAASSecurityManager.java
@@ -29,7 +29,7 @@ import java.util.Set;
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
import org.apache.activemq.artemis.core.security.CheckType;
import org.apache.activemq.artemis.core.security.Role;
-import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.security.jaas.JaasCallbackHandler;
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal;
import org.apache.activemq.artemis.spi.core.security.jaas.UserPrincipal;
@@ -88,9 +88,9 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager3 {
}
@Override
- public String validateUser(final String user, final String password, Connection connection) {
+ public String validateUser(final String user, final String password, RemotingConnection remotingConnection) {
try {
- return getUserFromSubject(getAuthenticatedSubject(user, password, connection));
+ return getUserFromSubject(getAuthenticatedSubject(user, password, remotingConnection));
} catch (LoginException e) {
if (logger.isDebugEnabled()) {
logger.debug("Couldn't validate user", e);
@@ -121,10 +121,10 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager3 {
final Set<Role> roles,
final CheckType checkType,
final String address,
- final Connection connection) {
+ final RemotingConnection remotingConnection) {
Subject localSubject;
try {
- localSubject = getAuthenticatedSubject(user, password, connection);
+ localSubject = getAuthenticatedSubject(user, password, remotingConnection);
} catch (LoginException e) {
if (logger.isDebugEnabled()) {
logger.debug("Couldn't validate user", e);
@@ -170,7 +170,7 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager3 {
private Subject getAuthenticatedSubject(final String user,
final String password,
- final Connection connection) throws LoginException {
+ final RemotingConnection remotingConnection) throws LoginException {
LoginContext lc;
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
ClassLoader thisLoader = this.getClass().getClassLoader();
@@ -178,10 +178,10 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager3 {
if (thisLoader != currentLoader) {
Thread.currentThread().setContextClassLoader(thisLoader);
}
- if (certificateConfigurationName != null && certificateConfigurationName.length() > 0 && getCertsFromConnection(connection) != null) {
- lc = new LoginContext(certificateConfigurationName, null, new JaasCallbackHandler(user, password, connection), certificateConfiguration);
+ if (certificateConfigurationName != null && certificateConfigurationName.length() > 0 && getCertsFromConnection(remotingConnection) != null) {
+ lc = new LoginContext(certificateConfigurationName, null, new JaasCallbackHandler(user, password, remotingConnection), certificateConfiguration);
} else {
- lc = new LoginContext(configurationName, null, new JaasCallbackHandler(user, password, connection), configuration);
+ lc = new LoginContext(configurationName, null, new JaasCallbackHandler(user, password, remotingConnection), configuration);
}
lc.login();
return lc.getSubject();
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQSecurityManager3.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQSecurityManager3.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQSecurityManager3.java
index 336e812..3a42fc1 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQSecurityManager3.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/ActiveMQSecurityManager3.java
@@ -20,7 +20,7 @@ import java.util.Set;
import org.apache.activemq.artemis.core.security.CheckType;
import org.apache.activemq.artemis.core.security.Role;
-import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
/**
* Used to validate whether a user is authorized to connect to the
@@ -40,9 +40,10 @@ public interface ActiveMQSecurityManager3 extends ActiveMQSecurityManager {
*
* @param user the user
* @param password the users password
+ * @param remotingConnection
* @return the name of the validated user or null if the user isn't validated
*/
- String validateUser(String user, String password, Connection connection);
+ String validateUser(String user, String password, RemotingConnection remotingConnection);
/**
* Determine whether the given user is valid and whether they have
@@ -56,7 +57,7 @@ public interface ActiveMQSecurityManager3 extends ActiveMQSecurityManager {
* @param roles the user's roles
* @param checkType which permission to validate
* @param address the address for which to perform authorization
- * @param connection the user's connection
+ * @param remotingConnection the user's connection
* @return the name of the validated user or null if the user isn't validated
*/
String validateUserAndRole(String user,
@@ -64,5 +65,5 @@ public interface ActiveMQSecurityManager3 extends ActiveMQSecurityManager {
Set<Role> roles,
CheckType checkType,
String address,
- Connection connection);
+ RemotingConnection remotingConnection);
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java
index a02d237..a765f45 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/JaasCallbackHandler.java
@@ -16,14 +16,17 @@
*/
package org.apache.activemq.artemis.spi.core.security.jaas;
-import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.kerberos.KerberosPrincipal;
import java.io.IOException;
+import java.security.Principal;
import static org.apache.activemq.artemis.core.remoting.CertificateUtil.getCertsFromConnection;
import static org.apache.activemq.artemis.core.remoting.CertificateUtil.getPeerPrincipalFromConnection;
@@ -35,12 +38,12 @@ public class JaasCallbackHandler implements CallbackHandler {
private final String username;
private final String password;
- final Connection connection;
+ final RemotingConnection remotingConnection;
- public JaasCallbackHandler(String username, String password, Connection connection) {
+ public JaasCallbackHandler(String username, String password, RemotingConnection remotingConnection) {
this.username = username;
this.password = password;
- this.connection = connection;
+ this.remotingConnection = remotingConnection;
}
@Override
@@ -63,11 +66,19 @@ public class JaasCallbackHandler implements CallbackHandler {
} else if (callback instanceof CertificateCallback) {
CertificateCallback certCallback = (CertificateCallback) callback;
- certCallback.setCertificates(getCertsFromConnection(connection));
- } else if (callback instanceof Krb5SslCallback) {
- Krb5SslCallback krb5SslCallback = (Krb5SslCallback) callback;
+ certCallback.setCertificates(getCertsFromConnection(remotingConnection));
+ } else if (callback instanceof Krb5Callback) {
+ Krb5Callback krb5Callback = (Krb5Callback) callback;
- krb5SslCallback.setPeerPrincipal(getPeerPrincipalFromConnection(connection));
+ Subject peerSubject = remotingConnection.getSubject();
+ if (peerSubject != null) {
+ for (Principal principal : peerSubject.getPrivateCredentials(KerberosPrincipal.class)) {
+ krb5Callback.setPeerPrincipal(principal);
+ return;
+ }
+ }
+
+ krb5Callback.setPeerPrincipal(getPeerPrincipalFromConnection(remotingConnection));
} else {
throw new UnsupportedCallbackException(callback);
}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5Callback.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5Callback.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5Callback.java
new file mode 100644
index 0000000..9306d5f
--- /dev/null
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5Callback.java
@@ -0,0 +1,46 @@
+/*
+ * 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.activemq.artemis.spi.core.security.jaas;
+
+import javax.security.auth.callback.Callback;
+import java.security.Principal;
+
+/**
+ * A Callback for kerberos peer principal.
+ */
+public class Krb5Callback implements Callback {
+
+ Principal peerPrincipal;
+
+ /**
+ * Setter for peer Principal.
+ *
+ * @param principal The certificates to be returned.
+ */
+ public void setPeerPrincipal(Principal principal) {
+ peerPrincipal = principal;
+ }
+
+ /**
+ * Getter for peer Principal.
+ *
+ * @return The principal being carried.
+ */
+ public Principal getPeerPrincipal() {
+ return peerPrincipal;
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5LoginModule.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5LoginModule.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5LoginModule.java
new file mode 100644
index 0000000..3396c81
--- /dev/null
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5LoginModule.java
@@ -0,0 +1,112 @@
+/*
+ * 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.activemq.artemis.spi.core.security.jaas;
+
+import org.jboss.logging.Logger;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * populate a subject with kerberos credential from the handler
+ */
+public class Krb5LoginModule implements LoginModule {
+
+ private static final Logger logger = Logger.getLogger(Krb5LoginModule.class);
+
+ private Subject subject;
+ private final List<Principal> principals = new LinkedList<>();
+ private CallbackHandler callbackHandler;
+ private boolean loginSucceeded;
+
+ @Override
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String, ?> sharedState,
+ Map<String, ?> options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ Callback[] callbacks = new Callback[1];
+
+ callbacks[0] = new Krb5Callback();
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioe) {
+ throw new LoginException(ioe.getMessage());
+ } catch (UnsupportedCallbackException uce) {
+ throw new LoginException(uce.getMessage() + " not available to obtain information from user");
+ }
+ principals.add(((Krb5Callback)callbacks[0]).getPeerPrincipal());
+ if (!principals.isEmpty()) {
+ loginSucceeded = true;
+ }
+ logger.debug("login " + principals);
+ return loginSucceeded;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ boolean result = loginSucceeded;
+ if (result) {
+ principals.add(new UserPrincipal(principals.get(0).getName()));
+ subject.getPrincipals().addAll(principals);
+ }
+
+ clear();
+
+ logger.debug("commit, result: " + result);
+
+ return result;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ clear();
+
+ logger.debug("abort");
+
+ return true;
+ }
+
+ private void clear() {
+ loginSucceeded = false;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ subject.getPrincipals().removeAll(principals);
+ principals.clear();
+ clear();
+
+ logger.debug("logout");
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslCallback.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslCallback.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslCallback.java
deleted file mode 100644
index 62c80db..0000000
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslCallback.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.activemq.artemis.spi.core.security.jaas;
-
-import javax.security.auth.callback.Callback;
-import java.security.Principal;
-
-/**
- * A Callback for SSL kerberos peer principal.
- */
-public class Krb5SslCallback implements Callback {
-
- Principal peerPrincipal;
-
- /**
- * Setter for peer Principal.
- *
- * @param principal The certificates to be returned.
- */
- public void setPeerPrincipal(Principal principal) {
- peerPrincipal = principal;
- }
-
- /**
- * Getter for peer Principal.
- *
- * @return The principal being carried.
- */
- public Principal getPeerPrincipal() {
- return peerPrincipal;
- }
-}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslLoginModule.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslLoginModule.java b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslLoginModule.java
deleted file mode 100644
index 1f6b5b1..0000000
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5SslLoginModule.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.activemq.artemis.spi.core.security.jaas;
-
-import org.jboss.logging.Logger;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
-import java.io.IOException;
-import java.security.Principal;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * populate a subject with kerberos and UserPrincipal from SSLContext peerPrincipal
- */
-public class Krb5SslLoginModule implements LoginModule {
-
- private static final Logger logger = Logger.getLogger(Krb5SslLoginModule.class);
-
- private Subject subject;
- private final List<Principal> principals = new LinkedList<>();
- private CallbackHandler callbackHandler;
- private boolean loginSucceeded;
-
- @Override
- public void initialize(Subject subject,
- CallbackHandler callbackHandler,
- Map<String, ?> sharedState,
- Map<String, ?> options) {
- this.subject = subject;
- this.callbackHandler = callbackHandler;
- }
-
- @Override
- public boolean login() throws LoginException {
- Callback[] callbacks = new Callback[1];
-
- callbacks[0] = new Krb5SslCallback();
- try {
- callbackHandler.handle(callbacks);
- } catch (IOException ioe) {
- throw new LoginException(ioe.getMessage());
- } catch (UnsupportedCallbackException uce) {
- throw new LoginException(uce.getMessage() + " not available to obtain information from user");
- }
- principals.add(((Krb5SslCallback)callbacks[0]).getPeerPrincipal());
- if (!principals.isEmpty()) {
- loginSucceeded = true;
- }
- logger.debug("login " + principals);
- return loginSucceeded;
- }
-
- @Override
- public boolean commit() throws LoginException {
- boolean result = loginSucceeded;
- if (result) {
- principals.add(new UserPrincipal(principals.get(0).getName()));
- subject.getPrincipals().addAll(principals);
- }
-
- clear();
-
- logger.debug("commit, result: " + result);
-
- return result;
- }
-
- @Override
- public boolean abort() throws LoginException {
- clear();
-
- logger.debug("abort");
-
- return true;
- }
-
- private void clear() {
- loginSucceeded = false;
- }
-
- @Override
- public boolean logout() throws LoginException {
- subject.getPrincipals().removeAll(principals);
- principals.clear();
- clear();
-
- logger.debug("logout");
-
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/docs/user-manual/en/security.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/security.md b/docs/user-manual/en/security.md
index f744c92..9173f2f 100644
--- a/docs/user-manual/en/security.md
+++ b/docs/user-manual/en/security.md
@@ -649,6 +649,25 @@ like the following:
The simplest way to make the login configuration available to JAAS is to add the directory containing the file,
`login.config`, to your CLASSPATH.
+### Kerberos Authentication
+
+The [https://docs.oracle.com/javase/7/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html]
+can be used with JAAS on both the client and server to authenticate with Kerberos.
+
+Using SASL over AMQP, Kerberos authentication is supported using the `GSSAPI` SASL mechanism. By default the server will use a
+JAAS login configuration scope named `amqp-sasl-gssapi` to obtain it acceptor Kerberos credentials. The config scope can be
+specified explicitly on the amqp acceptor url using the parameter: `saslLoginConfigScope=<some other scope>`.
+
+On the server, the Kerberos authenticated peer Principal can be extracted from the calling context as a UserPrincipal
+using a dedicated login module:
+
+ org.apache.activemq.artemis.spi.core.security.jaas.Krb5LoginModule
+
+The legacy [http://www.ietf.org/rfc/rfc2712.txt] defines TLS Kerberos cipher suites that can be used by TLS to negotiate
+Kerberos authentication. The cypher suites offered by rfc2712 are dated and insecure and rfc2712 has been superseded by
+SASL GSSAPI. However, for clients that don't support SASL (core client), using TLS can provide Kerberos authentication
+over an *unsecure* channel.
+
## Changing the username/password for clustering
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/ca7197b5/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSConnectionWithSecurityTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSConnectionWithSecurityTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSConnectionWithSecurityTest.java
index ee82e3d..3bc2354 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSConnectionWithSecurityTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSConnectionWithSecurityTest.java
@@ -36,6 +36,11 @@ public class JMSConnectionWithSecurityTest extends JMSClientTestSupport {
return true;
}
+ @Override
+ protected String getJmsConnectionURIOptions() {
+ return "amqp.saslMechanisms=PLAIN";
+ }
+
@Test(timeout = 10000)
public void testNoUserOrPassword() throws Exception {
Connection connection = null;