mirror of https://github.com/apache/activemq.git
Applied patch for https://issues.apache.org/activemq/browse/AMQ-2449
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@825008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
43bd686a2c
commit
f866f770e3
|
@ -361,7 +361,11 @@ public class ProtocolConverter {
|
||||||
}
|
}
|
||||||
for (Iterator<StompSubscription> iter = subscriptionsByConsumerId.values().iterator(); iter.hasNext();) {
|
for (Iterator<StompSubscription> iter = subscriptionsByConsumerId.values().iterator(); iter.hasNext();) {
|
||||||
StompSubscription sub = iter.next();
|
StompSubscription sub = iter.next();
|
||||||
sub.onStompAbort(activemqTx);
|
try {
|
||||||
|
sub.onStompAbort(activemqTx);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProtocolException("Transaction abort failed", false, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo tx = new TransactionInfo();
|
TransactionInfo tx = new TransactionInfo();
|
||||||
|
@ -483,6 +487,7 @@ public class ProtocolConverter {
|
||||||
connectionInfo.setResponseRequired(true);
|
connectionInfo.setResponseRequired(true);
|
||||||
connectionInfo.setUserName(login);
|
connectionInfo.setUserName(login);
|
||||||
connectionInfo.setPassword(passcode);
|
connectionInfo.setPassword(passcode);
|
||||||
|
connectionInfo.setTransportContext(transportFilter.getPeerCertificates());
|
||||||
|
|
||||||
sendToActiveMQ(connectionInfo, new ResponseHandler() {
|
sendToActiveMQ(connectionInfo, new ResponseHandler() {
|
||||||
public void onResponse(ProtocolConverter converter, Response response) throws IOException {
|
public void onResponse(ProtocolConverter converter, Response response) throws IOException {
|
||||||
|
|
|
@ -17,13 +17,16 @@
|
||||||
package org.apache.activemq.transport.stomp;
|
package org.apache.activemq.transport.stomp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
|
|
||||||
import org.apache.activemq.command.Command;
|
import org.apache.activemq.command.Command;
|
||||||
|
|
||||||
import org.apache.activemq.transport.Transport;
|
import org.apache.activemq.transport.Transport;
|
||||||
import org.apache.activemq.transport.TransportFilter;
|
import org.apache.activemq.transport.TransportFilter;
|
||||||
import org.apache.activemq.transport.TransportListener;
|
import org.apache.activemq.transport.TransportListener;
|
||||||
|
import org.apache.activemq.transport.tcp.SslTransport;
|
||||||
import org.apache.activemq.util.IOExceptionSupport;
|
import org.apache.activemq.util.IOExceptionSupport;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -64,6 +67,7 @@ public class StompTransportFilter extends TransportFilter {
|
||||||
if (trace) {
|
if (trace) {
|
||||||
LOG.trace("Received: \n" + command);
|
LOG.trace("Received: \n" + command);
|
||||||
}
|
}
|
||||||
|
|
||||||
protocolConverter.onStompCommand((StompFrame)command);
|
protocolConverter.onStompCommand((StompFrame)command);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
onException(e);
|
onException(e);
|
||||||
|
@ -93,6 +97,17 @@ public class StompTransportFilter extends TransportFilter {
|
||||||
return frameTranslator;
|
return frameTranslator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public X509Certificate[] getPeerCertificates() {
|
||||||
|
if(next instanceof SslTransport) {
|
||||||
|
X509Certificate[] peerCerts = ((SslTransport)next).getPeerCertificates();
|
||||||
|
if (trace && peerCerts != null) {
|
||||||
|
LOG.debug("Peer Identity has been verified\n");
|
||||||
|
}
|
||||||
|
return peerCerts;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isTrace() {
|
public boolean isTrace() {
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ import javax.net.ssl.SSLSession;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
|
||||||
import org.apache.activemq.command.Command;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
import org.apache.activemq.command.ConnectionInfo;
|
||||||
|
|
||||||
import org.apache.activemq.wireformat.WireFormat;
|
import org.apache.activemq.wireformat.WireFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,23 +86,29 @@ public class SslTransport extends TcpTransport {
|
||||||
// now.
|
// now.
|
||||||
if (command instanceof ConnectionInfo) {
|
if (command instanceof ConnectionInfo) {
|
||||||
ConnectionInfo connectionInfo = (ConnectionInfo)command;
|
ConnectionInfo connectionInfo = (ConnectionInfo)command;
|
||||||
|
connectionInfo.setTransportContext(getPeerCertificates());
|
||||||
SSLSocket sslSocket = (SSLSocket)this.socket;
|
}
|
||||||
|
|
||||||
SSLSession sslSession = sslSocket.getSession();
|
|
||||||
|
|
||||||
X509Certificate[] clientCertChain;
|
|
||||||
try {
|
|
||||||
clientCertChain = (X509Certificate[])sslSession.getPeerCertificates();
|
|
||||||
} catch (SSLPeerUnverifiedException e) {
|
|
||||||
clientCertChain = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
connectionInfo.setTransportContext(clientCertChain);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.doConsume(command);
|
super.doConsume(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return peer certificate chain associated with the ssl socket
|
||||||
|
*/
|
||||||
|
public X509Certificate[] getPeerCertificates() {
|
||||||
|
|
||||||
|
SSLSocket sslSocket = (SSLSocket)this.socket;
|
||||||
|
|
||||||
|
SSLSession sslSession = sslSocket.getSession();
|
||||||
|
|
||||||
|
X509Certificate[] clientCertChain;
|
||||||
|
try {
|
||||||
|
clientCertChain = (X509Certificate[])sslSession.getPeerCertificates();
|
||||||
|
} catch (SSLPeerUnverifiedException e) {
|
||||||
|
clientCertChain = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientCertChain;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return pretty print of 'this'
|
* @return pretty print of 'this'
|
||||||
|
|
|
@ -22,6 +22,8 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
@XStreamAlias("pojo")
|
@XStreamAlias("pojo")
|
||||||
public class SamplePojo implements Serializable {
|
public class SamplePojo implements Serializable {
|
||||||
|
private static final long serialVersionUID = 9118938642100015088L;
|
||||||
|
|
||||||
@XStreamAlias("name")
|
@XStreamAlias("name")
|
||||||
private String name;
|
private String name;
|
||||||
@XStreamAlias("city")
|
@XStreamAlias("city")
|
||||||
|
|
|
@ -16,12 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.transport.stomp;
|
package org.apache.activemq.transport.stomp;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Revision: 732672 $
|
* @version $Revision: 732672 $
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* 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.transport.stomp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version $Revision: 1461 $
|
||||||
|
*/
|
||||||
|
public class StompSslAuthTest extends StompTest {
|
||||||
|
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
|
||||||
|
// Test mutual authentication on both stomp and standard ssl transports
|
||||||
|
bindAddress = "stomp+ssl://localhost:61612";
|
||||||
|
confUri = "xbean:org/apache/activemq/transport/stomp/sslstomp-mutual-auth-broker.xml";
|
||||||
|
jmsUri="ssl://localhost:61617";
|
||||||
|
|
||||||
|
System.setProperty("javax.net.ssl.trustStore", "src/test/resources/client.keystore");
|
||||||
|
System.setProperty("javax.net.ssl.trustStorePassword", "password");
|
||||||
|
System.setProperty("javax.net.ssl.trustStoreType", "jks");
|
||||||
|
System.setProperty("javax.net.ssl.keyStore", "src/test/resources/server.keystore");
|
||||||
|
System.setProperty("javax.net.ssl.keyStorePassword", "password");
|
||||||
|
System.setProperty("javax.net.ssl.keyStoreType", "jks");
|
||||||
|
//System.setProperty("javax.net.debug","ssl,handshake");
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Socket createSocket(URI connectUri) throws IOException {
|
||||||
|
SocketFactory factory = SSLSocketFactory.getDefault();
|
||||||
|
return factory.createSocket("127.0.0.1", connectUri.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOOP - These operations handled by jaas cert login module
|
||||||
|
public void testConnectNotAuthenticatedWrongUser() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConnectNotAuthenticatedWrongPassword() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSendNotAuthorized() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSubscribeNotAuthorized() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -50,6 +50,8 @@ public class StompTest extends CombinationTestSupport {
|
||||||
|
|
||||||
protected String bindAddress = "stomp://localhost:61613";
|
protected String bindAddress = "stomp://localhost:61613";
|
||||||
protected String confUri = "xbean:org/apache/activemq/transport/stomp/stomp-auth-broker.xml";
|
protected String confUri = "xbean:org/apache/activemq/transport/stomp/stomp-auth-broker.xml";
|
||||||
|
protected String jmsUri = "vm://localhost";
|
||||||
|
|
||||||
|
|
||||||
private BrokerService broker;
|
private BrokerService broker;
|
||||||
private StompConnection stompConnection = new StompConnection();
|
private StompConnection stompConnection = new StompConnection();
|
||||||
|
@ -110,7 +112,7 @@ public class StompTest extends CombinationTestSupport {
|
||||||
|
|
||||||
stompConnect();
|
stompConnect();
|
||||||
|
|
||||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost");
|
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(jmsUri);
|
||||||
connection = cf.createConnection("system", "manager");
|
connection = cf.createConnection("system", "manager");
|
||||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
queue = new ActiveMQQueue(getQueueName());
|
queue = new ActiveMQQueue(getQueueName());
|
||||||
|
@ -131,9 +133,14 @@ public class StompTest extends CombinationTestSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
connection.close();
|
try {
|
||||||
stompDisconnect();
|
connection.close();
|
||||||
broker.stop();
|
stompDisconnect();
|
||||||
|
} catch(Exception e) {
|
||||||
|
// Some tests explicitly disconnect from stomp so can ignore
|
||||||
|
} finally {
|
||||||
|
broker.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stompDisconnect() throws IOException {
|
private void stompDisconnect() throws IOException {
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
#
|
#
|
||||||
# The logging properties used during tests..
|
# The logging properties used during tests..
|
||||||
#
|
#
|
||||||
log4j.rootLogger=INFO, out, stdout
|
log4j.rootLogger=DEBUG, out, stdout
|
||||||
|
|
||||||
log4j.logger.org.apache.activemq.spring=WARN
|
log4j.logger.org.apache.activemq=DEBUG
|
||||||
|
|
||||||
# CONSOLE appender not used by default
|
# CONSOLE appender not used by default
|
||||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||||
|
|
|
@ -20,3 +20,12 @@ activemq-domain {
|
||||||
org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties"
|
org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties"
|
||||||
org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties";
|
org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cert-login {
|
||||||
|
org.apache.activemq.jaas.TextFileCertificateLoginModule required
|
||||||
|
debug=true
|
||||||
|
org.apache.activemq.jaas.textfiledn.user="org/apache/activemq/security/users.properties"
|
||||||
|
org.apache.activemq.jaas.textfiledn.group="org/apache/activemq/security/groups.properties";
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
## limitations under the License.
|
## limitations under the License.
|
||||||
## ---------------------------------------------------------------------------
|
## ---------------------------------------------------------------------------
|
||||||
|
|
||||||
admins=system
|
admins=system,sslclient
|
||||||
tempDestinationAdmins=system,user
|
tempDestinationAdmins=system,user,sslclient
|
||||||
users=system,user
|
users=system,user,sslclient
|
||||||
guests=guest
|
guests=guest
|
||||||
|
|
|
@ -18,3 +18,4 @@
|
||||||
system=manager
|
system=manager
|
||||||
user=password
|
user=password
|
||||||
guest=password
|
guest=password
|
||||||
|
sslclient=CN=localhost, OU=activemq.org, O=activemq.org, L=LA, ST=CA, C=US
|
|
@ -25,7 +25,7 @@
|
||||||
<property name="annotatedClass"><value>org.apache.activemq.transport.stomp.SamplePojo</value></property>
|
<property name="annotatedClass"><value>org.apache.activemq.transport.stomp.SamplePojo</value></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<broker useJmx="true" persistent="false" xmlns="http://activemq.apache.org/schema/core" populateJMSXUserID="true">
|
<broker start="false" useJmx="true" persistent="false" xmlns="http://activemq.apache.org/schema/core" populateJMSXUserID="true">
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector name="stomp+ssl" uri="stomp+ssl://localhost:61612"/>
|
<transportConnector name="stomp+ssl" uri="stomp+ssl://localhost:61612"/>
|
||||||
|
@ -65,3 +65,4 @@
|
||||||
</broker>
|
</broker>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- this file can only be parsed using the xbean-spring library -->
|
||||||
|
<!-- START SNIPPET: example -->
|
||||||
|
<beans
|
||||||
|
xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||||
|
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
||||||
|
|
||||||
|
<bean class="org.apache.activemq.util.XStreamFactoryBean" name="xstream">
|
||||||
|
<property name="annotatedClass"><value>org.apache.activemq.transport.stomp.SamplePojo</value></property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- lets create an embedded ActiveMQ Broker -->
|
||||||
|
<amq:broker useJmx="true" persistent="false" start="false">
|
||||||
|
|
||||||
|
<amq:sslContext>
|
||||||
|
<amq:sslContext
|
||||||
|
keyStore="server.keystore" keyStorePassword="password"
|
||||||
|
trustStore="client.keystore" trustStorePassword="password"/>
|
||||||
|
</amq:sslContext>
|
||||||
|
|
||||||
|
<amq:transportConnectors>
|
||||||
|
<amq:transportConnector name="stomp+ssl" uri="stomp+ssl://localhost:61612?needClientAuth=true"/>
|
||||||
|
<amq:transportConnector name="ssl" uri="ssl://localhost:61617?needClientAuth=true"/>
|
||||||
|
</amq:transportConnectors>
|
||||||
|
|
||||||
|
<amq:plugins>
|
||||||
|
<amq:jaasCertificateAuthenticationPlugin configuration="cert-login"/>
|
||||||
|
|
||||||
|
<!-- lets configure a destination based authorization mechanism -->
|
||||||
|
<amq:authorizationPlugin>
|
||||||
|
<amq:map>
|
||||||
|
<amq:authorizationMap>
|
||||||
|
<amq:authorizationEntries>
|
||||||
|
<amq:authorizationEntry queue=">" read="admins" write="admins" admin="admins" />
|
||||||
|
<amq:authorizationEntry queue="USERS.>" read="users" write="users" admin="users" />
|
||||||
|
<amq:authorizationEntry queue="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||||
|
|
||||||
|
<amq:authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
|
||||||
|
<amq:authorizationEntry topic="USERS.>" read="users" write="users" admin="users" />
|
||||||
|
<amq:authorizationEntry topic="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||||
|
|
||||||
|
<amq:authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/>
|
||||||
|
</amq:authorizationEntries>
|
||||||
|
|
||||||
|
<!-- let's assign roles to temporary destinations. comment this entry if we don't want any roles assigned to temp destinations -->
|
||||||
|
<amq:tempDestinationAuthorizationEntry>
|
||||||
|
<amq:tempDestinationAuthorizationEntry read="tempDestinationAdmins" write="tempDestinationAdmins" admin="tempDestinationAdmins"/>
|
||||||
|
</amq:tempDestinationAuthorizationEntry>
|
||||||
|
</amq:authorizationMap>
|
||||||
|
</amq:map>
|
||||||
|
</amq:authorizationPlugin>
|
||||||
|
</amq:plugins>
|
||||||
|
|
||||||
|
</amq:broker>
|
||||||
|
|
||||||
|
</beans>
|
Loading…
Reference in New Issue