https://issues.apache.org/jira/browse/AMQ-3785 - ActiveMQSslConnectionFactory does not detect ssl request in failover URIs when creating transports. factory was bypassing the protocol selection, fixed by making use of the sslcontext thread local, which is used when set by the ssltransport factory

git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1361984 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gary Tully 2012-07-16 12:11:13 +00:00
parent ee17789e48
commit c4cdd516a1
2 changed files with 67 additions and 37 deletions

View File

@ -19,7 +19,6 @@ package org.apache.activemq;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.KeyStore; import java.security.KeyStore;
@ -34,10 +33,8 @@ import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.SslContext; import org.apache.activemq.broker.SslContext;
import org.apache.activemq.transport.Transport; import org.apache.activemq.transport.Transport;
import org.apache.activemq.transport.tcp.SslTransportFactory;
import org.apache.activemq.util.JMSExceptionSupport; import org.apache.activemq.util.JMSExceptionSupport;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -104,23 +101,20 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
* @author sepandm@gmail.com * @author sepandm@gmail.com
*/ */
protected Transport createTransport() throws JMSException { protected Transport createTransport() throws JMSException {
// If the given URI is non-ssl, let superclass handle it. SslContext existing = SslContext.getCurrentSslContext();
if (!brokerURL.getScheme().equals("ssl")) {
return super.createTransport();
}
try { try {
if (keyManager == null || trustManager == null) { if (keyStore != null || trustStore != null) {
trustManager = createTrustManager();
keyManager = createKeyManager(); keyManager = createKeyManager();
// secureRandom can be left as null trustManager = createTrustManager();
if (keyManager != null || trustManager != null) {
SslContext.setCurrentSslContext(new SslContext(keyManager, trustManager, secureRandom));
}
} }
SslTransportFactory sslFactory = new SslTransportFactory(); return super.createTransport();
SslContext ctx = new SslContext(keyManager, trustManager, secureRandom);
SslContext.setCurrentSslContext(ctx);
return sslFactory.doConnect(brokerURL);
} catch (Exception e) { } catch (Exception e) {
throw JMSExceptionSupport.create("Could not create Transport. Reason: " + e, e); throw JMSExceptionSupport.create("Could not create Transport. Reason: " + e, e);
} finally {
SslContext.setCurrentSslContext(existing);
} }
} }
@ -128,14 +122,16 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
TrustManager[] trustStoreManagers = null; TrustManager[] trustStoreManagers = null;
KeyStore trustedCertStore = KeyStore.getInstance("jks"); KeyStore trustedCertStore = KeyStore.getInstance("jks");
InputStream tsStream = getUrlOrResourceAsStream(trustStore); if (trustStore != null) {
InputStream tsStream = getUrlOrResourceAsStream(trustStore);
trustedCertStore.load(tsStream, trustStorePassword.toCharArray()); trustedCertStore.load(tsStream, trustStorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustedCertStore); tmf.init(trustedCertStore);
trustStoreManagers = tmf.getTrustManagers(); trustStoreManagers = tmf.getTrustManagers();
}
return trustStoreManagers; return trustStoreManagers;
} }
@ -144,15 +140,15 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("jks"); KeyStore ks = KeyStore.getInstance("jks");
KeyManager[] keystoreManagers = null; KeyManager[] keystoreManagers = null;
if (keyStore != null) {
byte[] sslCert = loadClientCredential(keyStore);
byte[] sslCert = loadClientCredential(keyStore); if (sslCert != null && sslCert.length > 0) {
ByteArrayInputStream bin = new ByteArrayInputStream(sslCert);
ks.load(bin, keyStorePassword.toCharArray());
if (sslCert != null && sslCert.length > 0) { kmf.init(ks, keyStorePassword.toCharArray());
ByteArrayInputStream bin = new ByteArrayInputStream(sslCert); keystoreManagers = kmf.getKeyManagers();
ks.load(bin, keyStorePassword.toCharArray()); }
kmf.init(ks, keyStorePassword.toCharArray());
keystoreManagers = kmf.getKeyManagers();
} }
return keystoreManagers; return keystoreManagers;
} }
@ -162,7 +158,6 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
return null; return null;
} }
InputStream in = getUrlOrResourceAsStream(fileName); InputStream in = getUrlOrResourceAsStream(fileName);
//FileInputStream in = new FileInputStream(fileName);
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[512]; byte[] buf = new byte[512];
int i = in.read(buf); int i = in.read(buf);
@ -206,7 +201,7 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
* *
* @param trustStore If specified with a scheme, treat as a URL, otherwise treat as a classpath resource. * @param trustStore If specified with a scheme, treat as a URL, otherwise treat as a classpath resource.
*/ */
public void setTrustStore(String trustStore) { public void setTrustStore(String trustStore) throws Exception {
this.trustStore = trustStore; this.trustStore = trustStore;
trustManager = null; trustManager = null;
} }
@ -234,7 +229,7 @@ public class ActiveMQSslConnectionFactory extends ActiveMQConnectionFactory {
* *
* @param keyStore If specified with a scheme, treat as a URL, otherwise treat as a classpath resource. * @param keyStore If specified with a scheme, treat as a URL, otherwise treat as a classpath resource.
*/ */
public void setKeyStore(String keyStore) { public void setKeyStore(String keyStore) throws Exception {
this.keyStore = keyStore; this.keyStore = keyStore;
keyManager = null; keyManager = null;
} }

View File

@ -74,8 +74,22 @@ public class ActiveMQSslConnectionFactoryTest extends CombinationTestSupport {
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true"); ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
connection = (ActiveMQConnection)cf.createConnection(); connection = (ActiveMQConnection)cf.createConnection();
assertNotNull(connection); assertNotNull(connection);
connection.start();
connection.stop();
brokerStop();
}
brokerStop(); public void testCreateFailoverTcpConnectionUsingKnownPort() throws Exception {
// Control case: check that the factory can create an ordinary (non-ssl) connection.
broker = createBroker("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
// This should create the connection.
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("failover:(tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true)");
connection = (ActiveMQConnection)cf.createConnection();
assertNotNull(connection);
connection.start();
connection.stop();
brokerStop();
} }
public void testCreateSslConnection() throws Exception { public void testCreateSslConnection() throws Exception {
@ -91,6 +105,26 @@ public class ActiveMQSslConnectionFactoryTest extends CombinationTestSupport {
connection = (ActiveMQConnection)cf.createConnection(); connection = (ActiveMQConnection)cf.createConnection();
LOG.info("Created client connection"); LOG.info("Created client connection");
assertNotNull(connection); assertNotNull(connection);
connection.start();
connection.stop();
brokerStop();
}
public void testFailoverSslConnection() throws Exception {
// Create SSL/TLS connection with trusted cert from truststore.
String sslUri = "ssl://localhost:61611";
broker = createSslBroker(sslUri);
assertNotNull(broker);
// This should create the connection.
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("failover:(" + sslUri + ")?maxReconnectAttempts=4");
cf.setTrustStore("server.keystore");
cf.setTrustStorePassword("password");
connection = (ActiveMQConnection)cf.createConnection();
LOG.info("Created client connection");
assertNotNull(connection);
connection.start();
connection.stop();
brokerStop(); brokerStop();
} }
@ -143,6 +177,7 @@ public class ActiveMQSslConnectionFactoryTest extends CombinationTestSupport {
// Start up a broker with a tcp connector. // Start up a broker with a tcp connector.
BrokerService service = new BrokerService(); BrokerService service = new BrokerService();
service.setPersistent(false); service.setPersistent(false);
service.setUseJmx(false);
connector = service.addConnector(uri); connector = service.addConnector(uri);
service.start(); service.start();