diff options
author | Martin Ritchie <ritchiem@apache.org> | 2007-02-14 15:40:47 +0000 |
---|---|---|
committer | Martin Ritchie <ritchiem@apache.org> | 2007-02-14 15:40:47 +0000 |
commit | c206a9ed35ac489ffc86b47fb6c8df69266a73fa (patch) | |
tree | 2f657e59ffa3072817b1820d5672dc7480222c09 | |
parent | 80e9cae3e7fd6bb8216c0b0ddf74a51c48784814 (diff) | |
download | qpid-python-c206a9ed35ac489ffc86b47fb6c8df69266a73fa.tar.gz |
Applied QPID-6 SSL Options patch from Kevin Smith
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@507584 13f79535-47bb-0310-9956-ffa450edef68
18 files changed, 408 insertions, 607 deletions
diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml index 779a434332..0b4091efa5 100644 --- a/java/broker/etc/config.xml +++ b/java/broker/etc/config.xml @@ -24,8 +24,13 @@ <work>${QPID_WORK}</work> <conf>${prefix}/etc</conf> <connector> - <ssl>false</ssl> - <nonssl>true</nonssl> + <!-- Uncomment out this block and edit the keystorePath and keystorePassword + to enable SSL support + <ssl> + <enabled>true</enabled> + <keystorePath>/path/to/keystore.ks</keystorePath> + <keystorePassword>keystorepass</keystorePassword> + </ssl>--> <qpidnio>true</qpidnio> <transport>nio</transport> <port>5672</port> diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java index 55009bbf49..37ac7b8b44 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -327,7 +327,7 @@ public class Main implements ProtocolVersionList sconfig.setThreadModel(ReadWriteThreadModel.getInstance()); } - if (connectorConfig.enableNonSSL) + if (!connectorConfig.enableSSL) { AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler(); InetSocketAddress bindAddress; @@ -343,10 +343,9 @@ public class Main implements ProtocolVersionList _logger.info("Qpid.AMQP listening on non-SSL address " + bindAddress); } - if (connectorConfig.enableSSL) + else { AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler(); - handler.setUseSSL(true); try { acceptor.bind(new InetSocketAddress(connectorConfig.sslPort), diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java index d7e6af0c29..76a293c161 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java @@ -20,15 +20,8 @@ */ package org.apache.qpid.server.protocol; -import org.apache.qpid.AMQException; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.framing.*; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.transport.ConnectorConfiguration; -import org.apache.qpid.ssl.BogusSSLContextFactory; +import java.io.IOException; + import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IdleStatus; @@ -37,8 +30,19 @@ import org.apache.mina.common.IoSession; import org.apache.mina.filter.SSLFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.util.SessionUtil; - -import java.io.IOException; +import org.apache.qpid.AMQException; +import org.apache.qpid.codec.AMQCodecFactory; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQProtocolHeaderException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.framing.ProtocolVersionList; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.transport.ConnectorConfiguration; +import org.apache.qpid.ssl.SSLContextFactory; /** @@ -56,17 +60,14 @@ public class AMQPFastProtocolHandler extends IoHandlerAdapter implements Protoco private final IApplicationRegistry _applicationRegistry; - private boolean _useSSL; - public AMQPFastProtocolHandler(Integer applicationRegistryInstance) { - this(ApplicationRegistry.getInstance(applicationRegistryInstance)); + this(ApplicationRegistry.getInstance(applicationRegistryInstance)); } public AMQPFastProtocolHandler(IApplicationRegistry applicationRegistry) { _applicationRegistry = applicationRegistry; - _logger.debug("AMQPFastProtocolHandler created"); } @@ -89,16 +90,30 @@ public class AMQPFastProtocolHandler extends IoHandlerAdapter implements Protoco getConfiguredObject(ConnectorConfiguration.class); if (connectorConfig.enableExecutorPool) { - if (_useSSL) + if (connectorConfig.enableSSL) { + String keystorePath = connectorConfig.keystorePath; + String keystorePassword = connectorConfig.keystorePassword; + String certType = connectorConfig.certType; + SSLContextFactory sslContextFactory = new SSLContextFactory(keystorePath, keystorePassword, certType); protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter", - new SSLFilter(BogusSSLContextFactory.getInstance(true))); + new SSLFilter(sslContextFactory.buildServerContext())); } protocolSession.getFilterChain().addBefore("AsynchronousWriteFilter", "protocolFilter", pcf); } else { - protocolSession.getFilterChain().addLast("protocolFilter", pcf); + protocolSession.getFilterChain().addLast("protocolFilter", pcf); + if (connectorConfig.enableSSL) + { + String keystorePath = connectorConfig.keystorePath; + String keystorePassword = connectorConfig.keystorePassword; + String certType = connectorConfig.certType; + SSLContextFactory sslContextFactory = new SSLContextFactory(keystorePath, keystorePassword, certType); + protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter", + new SSLFilter(sslContextFactory.buildServerContext())); + } + } } @@ -216,14 +231,4 @@ public class AMQPFastProtocolHandler extends IoHandlerAdapter implements Protoco _logger.debug("Message sent: " + object); } } - - public boolean isUseSSL() - { - return _useSSL; - } - - public void setUseSSL(boolean useSSL) - { - _useSSL = useSSL; - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java index ac164f0cab..12489ad70e 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java @@ -70,13 +70,21 @@ public class ConnectorConfiguration defaultValue = "false") public boolean enableDirectBuffers; - @Configured(path = "connector.ssl", + @Configured(path = "connector.ssl.enabled", defaultValue = "false") public boolean enableSSL; - - @Configured(path = "connector.nonssl", - defaultValue = "true") - public boolean enableNonSSL; + + @Configured(path = "connector.ssl.keystorePath", + defaultValue = "none") + public String keystorePath; + + @Configured(path = "connector.ssl.keystorePassword", + defaultValue = "none") + public String keystorePassword; + + @Configured(path = "connector.ssl.certType", + defaultValue = "SunX509") + public String certType; public IoAcceptor createAcceptor() { diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java index 8fb87f9e64..5492bd91e7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java @@ -35,6 +35,8 @@ public class AMQBrokerDetails implements BrokerDetails private String _transport; private HashMap<String, String> _options; + + private SSLConfiguration _sslConfiguration; public AMQBrokerDetails() { @@ -174,15 +176,11 @@ public class AMQBrokerDetails implements BrokerDetails } } - public AMQBrokerDetails(String host, int port, boolean useSSL) + public AMQBrokerDetails(String host, int port, SSLConfiguration sslConfiguration) { _host = host; _port = port; - - if (useSSL) - { - setOption(OPTIONS_SSL, "true"); - } + _sslConfiguration = sslConfiguration; } public String getHost() @@ -247,6 +245,16 @@ public class AMQBrokerDetails implements BrokerDetails { setOption(OPTIONS_CONNECT_TIMEOUT, Long.toString(timeout)); } + + public SSLConfiguration getSSLConfiguration() + { + return _sslConfiguration; + } + + public void setSSLConfiguration(SSLConfiguration sslConfig) + { + _sslConfiguration = sslConfig; + } public String toString() { @@ -280,8 +288,7 @@ public class AMQBrokerDetails implements BrokerDetails return _host.equalsIgnoreCase(bd.getHost()) && (_port == bd.getPort()) && _transport.equalsIgnoreCase(bd.getTransport()) && - (useSSL() == bd.useSSL()); - + compareSSLConfigurations(bd.getSSLConfiguration()); //todo do we need to compare all the options as well? } @@ -313,27 +320,25 @@ public class AMQBrokerDetails implements BrokerDetails return optionsURL.toString(); } - - public boolean useSSL() + + // Do we need to do a more in-depth comparison? + private boolean compareSSLConfigurations(SSLConfiguration other) { - // To be friendly to users we should be case insensitive. - // or simply force users to conform to OPTIONS_SSL - // todo make case insensitive by trying ssl Ssl sSl ssL SSl SsL sSL SSL - - if (_options.containsKey(OPTIONS_SSL)) - { - return _options.get(OPTIONS_SSL).equalsIgnoreCase("true"); - } - - return USE_SSL_DEFAULT; + boolean retval = false; + if (_sslConfiguration == null && + other == null) + { + retval = true; + } + else if (_sslConfiguration != null && + other != null) + { + retval = true; + } + + return retval; } - public void useSSL(boolean ssl) - { - setOption(OPTIONS_SSL, Boolean.toString(ssl)); - } - - public static String checkTransport(String broker) { if ((!broker.contains("://"))) diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 50299fa9d5..fbf9e3c4f7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -141,6 +141,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect * The connection meta data */ private QpidConnectionMetaData _connectionMetaData; + + /** + * Configuration info for SSL + */ + private SSLConfiguration _sslConfiguration; /** * @param broker brokerdetails @@ -157,17 +162,43 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect this(new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" + (clientName == null ? "" : clientName) + "/" + - virtualHost + "?brokerlist='" + AMQBrokerDetails.checkTransport(broker) + "'")); + virtualHost + "?brokerlist='" + AMQBrokerDetails.checkTransport(broker) + "'"), null); } + + /** + * @param broker brokerdetails + * @param username username + * @param password password + * @param clientName clientid + * @param virtualHost virtualhost + * @throws AMQException + * @throws URLSyntaxException + */ + public AMQConnection(String broker, String username, String password, + String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + { + this(new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL + "://" + + username + ":" + password + "@" + + (clientName == null ? "" : clientName) + "/" + + virtualHost + "?brokerlist='" + AMQBrokerDetails.checkTransport(broker) + "'"), sslConfig); + } + public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost) throws AMQException, URLSyntaxException { - this(host, port, false, username, password, clientName, virtualHost); + this(host, port, false, username, password, clientName, virtualHost, null); } + + public AMQConnection(String host, int port, String username, String password, + String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + { + this(host, port, false, username, password, clientName, virtualHost, sslConfig); + } + public AMQConnection(String host, int port, boolean useSSL, String username, String password, - String clientName, String virtualHost) throws AMQException, URLSyntaxException + String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException { this(new AMQConnectionURL(useSSL ? ConnectionURL.AMQ_PROTOCOL + "://" + @@ -180,18 +211,24 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect (clientName == null ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port + "'" + "," + ConnectionURL.OPTIONS_SSL + "='false'" - )); + ), sslConfig); } public AMQConnection(String connection) throws AMQException, URLSyntaxException { - this(new AMQConnectionURL(connection)); + this(new AMQConnectionURL(connection), null); } + + public AMQConnection(String connection, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + { + this(new AMQConnectionURL(connection), sslConfig); + } + - public AMQConnection(ConnectionURL connectionURL) throws AMQException + public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException { _logger.info("Connection:" + connectionURL); - + _sslConfiguration = sslConfig; if (connectionURL == null) { throw new IllegalArgumentException("Connection must be specified"); @@ -319,9 +356,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } } - public boolean attemptReconnection(String host, int port, boolean useSSL) + public boolean attemptReconnection(String host, int port) { - BrokerDetails bd = new AMQBrokerDetails(host, port, useSSL); + BrokerDetails bd = new AMQBrokerDetails(host, port, _sslConfiguration); _failoverPolicy.setBroker(bd); @@ -1017,5 +1054,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect AMQConnectionFactory.class.getName(), null); // factory location } - + + public SSLConfiguration getSSLConfiguration() + { + return _sslConfiguration; + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java index 17af3702a4..608f0a028d 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java @@ -42,7 +42,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF private String _virtualPath; private ConnectionURL _connectionDetails; - + private SSLConfiguration _sslConfig; public AMQConnectionFactory() { @@ -113,6 +113,22 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF } _defaultPassword = password; } + + /** + * Getter for SSLConfiguration + * @return SSLConfiguration if set, otherwise null + */ + public final SSLConfiguration getSSLConfiguration() { + return _sslConfig; + } + + /** + * Setter for SSLConfiguration + * @param sslConfig config to store + */ + public final void setSSLConfiguration(SSLConfiguration sslConfig) { + _sslConfig = sslConfig; + } /** * @return The _defaultPassword. @@ -229,7 +245,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF { _connectionDetails.setClientName(getUniqueClientID()); } - return new AMQConnection(_connectionDetails); + return new AMQConnection(_connectionDetails, _sslConfig); } else { @@ -260,7 +276,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF { _connectionDetails.setClientName(getUniqueClientID()); } - return new AMQConnection(_connectionDetails); + return new AMQConnection(_connectionDetails, _sslConfig); } else { diff --git a/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java b/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java new file mode 100644 index 0000000000..2280cc9870 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java @@ -0,0 +1,61 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.client; + +public class SSLConfiguration { + + private String _keystorePath; + + private String _keystorePassword; + + private String _certType = "SunX509"; + + public void setKeystorePath(String path) + { + _keystorePath = path; + } + + public String getKeystorePath() + { + return _keystorePath; + } + + public void setKeystorePassword(String password) + { + _keystorePassword = password; + } + + public String getKeystorePassword() + { + return _keystorePassword; + } + + public void setCertType(String type) + { + _certType = type; + } + + public String getCertType() + { + return _certType; + } +} diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java index 7b789aa09d..1af7905b3b 100644 --- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java @@ -115,7 +115,7 @@ public class FailoverHandler implements Runnable // if _host has value then we are performing a redirect. if (_host != null) { - failoverSucceeded = _amqProtocolHandler.getConnection().attemptReconnection(_host, _port, _amqProtocolHandler.isUseSSL()); + failoverSucceeded = _amqProtocolHandler.getConnection().attemptReconnection(_host, _port); } else { diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 1f83ce67c3..988a12ee78 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -20,35 +20,44 @@ */ package org.apache.qpid.client.protocol; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; + import org.apache.log4j.Logger; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoSession; -import org.apache.mina.common.IoServiceConfig; import org.apache.mina.filter.SSLFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQTimeoutException; -import org.apache.qpid.pool.ReadWriteThreadModel; -import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.SSLConfiguration; import org.apache.qpid.client.failover.FailoverHandler; import org.apache.qpid.client.failover.FailoverState; import org.apache.qpid.client.state.AMQState; import org.apache.qpid.client.state.AMQStateManager; import org.apache.qpid.client.state.listener.SpecificMethodFrameListener; import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.framing.*; +import org.apache.qpid.framing.AMQBody; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ConnectionCloseOkBody; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.pool.ReadWriteThreadModel; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; -import org.apache.qpid.ssl.BogusSSLContextFactory; - -import java.util.Iterator; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.CountDownLatch; +import org.apache.qpid.ssl.SSLContextFactory; public class AMQProtocolHandler extends IoHandlerAdapter @@ -62,12 +71,6 @@ public class AMQProtocolHandler extends IoHandlerAdapter private AMQConnection _connection; /** - * Used only when determining whether to add the SSL filter or not. This should be made more - * generic in future since we will potentially have many transport layer options - */ - private boolean _useSSL; - - /** * Our wrapper for a protocol session that provides access to session values * in a typesafe manner. */ @@ -99,16 +102,6 @@ public class AMQProtocolHandler extends IoHandlerAdapter _connection = con; } - public boolean isUseSSL() - { - return _useSSL; - } - - public void setUseSSL(boolean useSSL) - { - _useSSL = useSSL; - } - public void sessionCreated(IoSession session) throws Exception { _logger.debug("Protocol session created for session " + System.identityHashCode(session)); @@ -125,10 +118,11 @@ public class AMQProtocolHandler extends IoHandlerAdapter session.getFilterChain().addLast("protocolFilter", pcf); } // we only add the SSL filter where we have an SSL connection - if (_useSSL) + if (_connection.getSSLConfiguration() != null) { - //FIXME: Bogus context cannot be used in production. - SSLFilter sslFilter = new SSLFilter(BogusSSLContextFactory.getInstance(false)); + SSLConfiguration sslConfig = _connection.getSSLConfiguration(); + SSLContextFactory sslFactory = new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType()); + SSLFilter sslFilter = new SSLFilter(sslFactory.buildClientContext()); sslFilter.setUseClientMode(true); session.getFilterChain().addBefore("protocolFilter", "ssl", sslFilter); } diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java index 5e6244d7cc..9342e93ec6 100644 --- a/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java @@ -81,7 +81,6 @@ public class SocketTransportConnection implements ITransportConnection scfg.setReceiveBufferSize(Integer.getInteger("amqj.receiveBufferSize", DEFAULT_BUFFER_SIZE)); _logger.info("recv-buffer-size = " + scfg.getReceiveBufferSize()); final InetSocketAddress address = new InetSocketAddress(brokerDetail.getHost(), brokerDetail.getPort()); - protocolHandler.setUseSSL(brokerDetail.useSSL()); _logger.info("Attempting connection to " + address); ConnectFuture future = ioConnector.connect(address, protocolHandler); diff --git a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java index 293ce5e82e..91f7710025 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.jms; +import org.apache.qpid.client.SSLConfiguration; + public interface BrokerDetails { @@ -28,7 +30,6 @@ public interface BrokerDetails * @see ConnectionURL */ public static final String OPTIONS_RETRY = "retries"; - public static final String OPTIONS_SSL = ConnectionURL.OPTIONS_SSL; public static final String OPTIONS_CONNECT_TIMEOUT = "connecttimeout"; public static final int DEFAULT_PORT = 5672; @@ -55,10 +56,6 @@ public interface BrokerDetails void setTransport(String transport); - boolean useSSL(); - - void useSSL(boolean ssl); - String getOption(String key); void setOption(String key, String value); @@ -66,6 +63,10 @@ public interface BrokerDetails long getTimeout(); void setTimeout(long timeout); + + SSLConfiguration getSSLConfiguration(); + + void setSSLConfiguration(SSLConfiguration sslConfiguration); String toString(); diff --git a/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java b/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java index 5746a32c26..15752353d1 100644 --- a/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java +++ b/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java @@ -44,9 +44,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; /** - * TODO: This is a cut-and-paste from the original broker Main class. Would be preferrable - * to make that class more reuseable to avoid all this duplication. - * + * TODO: This is a cut-and-paste from the original broker Main class. Would be preferrable to make that class more + * reuseable to avoid all this duplication. */ public class Main extends org.apache.qpid.server.Main { @@ -88,18 +87,16 @@ public class Main extends org.apache.qpid.server.Main String host = InetAddress.getLocalHost().getHostName(); ClusteredProtocolHandler handler = new ClusteredProtocolHandler(new InetSocketAddress(host, port)); - if (connectorConfig.enableNonSSL) + if (!connectorConfig.enableSSL) { acceptor.bind(new InetSocketAddress(port), handler, sconfig); _logger.info("Qpid.AMQP listening on non-SSL port " + port); handler.connect(commandLine.getOptionValue("j")); } - - if (connectorConfig.enableSSL) + else { ClusteredProtocolHandler sslHandler = new ClusteredProtocolHandler(handler); - sslHandler.setUseSSL(true); - acceptor.bind(new InetSocketAddress(connectorConfig.sslPort), handler, sconfig); + acceptor.bind(new InetSocketAddress(connectorConfig.sslPort), sslHandler, sconfig); _logger.info("Qpid.AMQP listening on SSL port " + connectorConfig.sslPort); } } diff --git a/java/common/src/main/java/org/apache/qpid/ssl/BogusSSLContextFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/BogusSSLContextFactory.java deleted file mode 100644 index fee02c9d93..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ssl/BogusSSLContextFactory.java +++ /dev/null @@ -1,159 +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.qpid.ssl; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.KeyStore; - -/** - * Factory to create a bogus SSLContext. This means that it is easy to test SSL but this - * cannot be used in a production environment. - * <p/> - * This is based on the sample that comes with MINA, written by Trustin Lee - */ -public class BogusSSLContextFactory -{ - /** - * Protocol to use. - */ - private static final String PROTOCOL = "TLS"; - - /** - * Bougus Server certificate keystore file name. - */ - private static final String BOGUS_KEYSTORE = "qpid.cert"; - - // NOTE: The keystore was generated using keytool: - // keytool -genkey -alias qpid -keysize 512 -validity 3650 - // -keyalg RSA -dname "CN=amqp.org" -keypass qpidpw - // -storepass qpidpw -keystore qpid.cert - - private static final char[] BOGUS_KEYSTORE_PASSWORD = {'q', 'p', 'i', 'd', 'p', 'w'}; - - private static SSLContext serverInstance = null; - - private static SSLContext clientInstance = null; - - /** - * Get SSLContext singleton. - * - * @return SSLContext - * @throws java.security.GeneralSecurityException - */ - public static SSLContext getInstance(boolean server) - throws GeneralSecurityException - { - SSLContext retInstance; - if (server) - { - // FIXME: looks like double-checking locking - if (serverInstance == null) - { - synchronized (BogusSSLContextFactory.class) - { - if (serverInstance == null) - { - try - { - serverInstance = createBougusServerSSLContext(); - } - catch (Exception ioe) - { - throw new GeneralSecurityException( - "Can't create Server SSLContext:" + ioe); - } - } - } - } - retInstance = serverInstance; - } - else - { - // FIXME: looks like double-checking locking - if (clientInstance == null) - { - synchronized (BogusSSLContextFactory.class) - { - if (clientInstance == null) - { - clientInstance = createBougusClientSSLContext(); - } - } - } - retInstance = clientInstance; - } - return retInstance; - } - - private static SSLContext createBougusServerSSLContext() - throws GeneralSecurityException, IOException - { - // Create keystore - KeyStore ks = KeyStore.getInstance("JKS"); - InputStream in = null; - try - { - in = BogusSSLContextFactory.class.getResourceAsStream(BOGUS_KEYSTORE); - if (in == null) - { - throw new IOException("Unable to load keystore resource: " + BOGUS_KEYSTORE); - } - ks.load(in, BOGUS_KEYSTORE_PASSWORD); - } - finally - { - if (in != null) - { - //noinspection EmptyCatchBlock - try - { - in.close(); - } - catch (IOException ignored) - { - } - } - } - - // Set up key manager factory to use our key store - KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, BOGUS_KEYSTORE_PASSWORD); - - // Initialize the SSLContext to work with our key managers. - SSLContext sslContext = SSLContext.getInstance(PROTOCOL); - sslContext.init(kmf.getKeyManagers(), BogusTrustManagerFactory.X509_MANAGERS, null); - - return sslContext; - } - - private static SSLContext createBougusClientSSLContext() - throws GeneralSecurityException - { - SSLContext context = SSLContext.getInstance(PROTOCOL); - context.init(null, BogusTrustManagerFactory.X509_MANAGERS, null); - return context; - } - -} diff --git a/java/common/src/main/java/org/apache/qpid/ssl/BogusTrustManagerFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/BogusTrustManagerFactory.java deleted file mode 100644 index 4fb6f75b8d..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ssl/BogusTrustManagerFactory.java +++ /dev/null @@ -1,82 +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.qpid.ssl; - -import javax.net.ssl.ManagerFactoryParameters; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactorySpi; -import javax.net.ssl.X509TrustManager; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -/** - * Bogus trust manager factory. Used to make testing SSL simpler - i.e no need to - * mess about with keystores. - * <p/> - * This is based on the example that comes with MINA, written by Trustin Lee. - */ -class BogusTrustManagerFactory extends TrustManagerFactorySpi -{ - - static final X509TrustManager X509 = new X509TrustManager() - { - public void checkClientTrusted(X509Certificate[] x509Certificates, - String s) throws CertificateException - { - } - - public void checkServerTrusted(X509Certificate[] x509Certificates, - String s) throws CertificateException - { - } - - public X509Certificate[] getAcceptedIssuers() - { - return new X509Certificate[ 0 ]; - } - }; - - static final TrustManager[] X509_MANAGERS = new TrustManager[]{X509}; - - public BogusTrustManagerFactory() - { - } - - protected TrustManager[] engineGetTrustManagers() - { - return X509_MANAGERS; - } - - protected void engineInit(KeyStore keystore) throws KeyStoreException - { - // noop - } - - protected void engineInit( - ManagerFactoryParameters managerFactoryParameters) - throws InvalidAlgorithmParameterException - { - // noop - } -} diff --git a/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java new file mode 100644 index 0000000000..950279fff1 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java @@ -0,0 +1,157 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.ssl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyStore; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +/** + * Factory used to create SSLContexts. SSL needs to be configured + * before this will work. + * + */ +public class SSLContextFactory { + + /** + * Path to the Java keystore file + */ + private String _keystorePath; + + /** + * Password for the keystore + */ + private String _keystorePassword; + + /** + * Cert type to use + */ + private String _certType; + + /** + * Create a factory instance + * @param keystorePath path to the Java keystore file + * @param keystorePassword password for the Java keystore + * @param certType certificate type + */ + public SSLContextFactory(String keystorePath, String keystorePassword, + String certType) + { + _keystorePath = keystorePath; + _keystorePassword = keystorePassword; + if (_keystorePassword.equals("none")) + { + _keystorePassword = null; + } + _certType = certType; + if (keystorePath == null) { + throw new IllegalArgumentException("Keystore path must be specified"); + } + if (certType == null) { + throw new IllegalArgumentException("Cert type must be specified"); + } + } + + /** + * Builds a SSLContext appropriate for use with a server + * @return SSLContext + * @throws GeneralSecurityException + * @throws IOException + */ + public SSLContext buildServerContext() throws GeneralSecurityException, IOException + { + // Create keystore + KeyStore ks = getInitializedKeyStore(); + + // Set up key manager factory to use our key store + KeyManagerFactory kmf = KeyManagerFactory.getInstance(_certType); + kmf.init(ks, _keystorePassword.toCharArray()); + + // Initialize the SSLContext to work with our key managers. + SSLContext sslContext = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(_certType); + tmf.init(ks); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + return sslContext; + } + + /** + * Creates a SSLContext factory appropriate for use with a client + * @return SSLContext + * @throws GeneralSecurityException + * @throws IOException + */ + public SSLContext buildClientContext() throws GeneralSecurityException, IOException + { + KeyStore ks = getInitializedKeyStore(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(_certType); + tmf.init(ks); + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, tmf.getTrustManagers(), null); + return context; + } + + private KeyStore getInitializedKeyStore() throws GeneralSecurityException, IOException + { + KeyStore ks = KeyStore.getInstance("JKS"); + InputStream in = null; + try + { + File f = new File(_keystorePath); + if (f.exists()) + { + in = new FileInputStream(f); + } + else + { + in = Thread.currentThread().getContextClassLoader().getResourceAsStream(_keystorePath); + } + if (in == null) + { + throw new IOException("Unable to load keystore resource: " + _keystorePath); + } + ks.load(in, _keystorePassword.toCharArray()); + } + finally + { + if (in != null) + { + //noinspection EmptyCatchBlock + try + { + in.close(); + } + catch (IOException ignored) + { + } + } + } + return ks; + } +} diff --git a/java/common/src/main/java/org/apache/qpid/ssl/SSLServerSocketFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/SSLServerSocketFactory.java deleted file mode 100644 index 90b3589752..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ssl/SSLServerSocketFactory.java +++ /dev/null @@ -1,108 +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.qpid.ssl; - -import javax.net.ServerSocketFactory; -import java.io.IOException; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.security.GeneralSecurityException; - -/** - * Simple Server Socket factory to create sockets with or without SSL enabled. - * If SSL enabled a "bogus" SSL Context is used (suitable for test purposes) - * <p/> - * This is based on the example that comes with MINA, written by Trustin Lee. - */ -public class SSLServerSocketFactory extends javax.net.ServerSocketFactory -{ - private static boolean sslEnabled = false; - - private static javax.net.ServerSocketFactory sslFactory = null; - - private static ServerSocketFactory factory = null; - - public SSLServerSocketFactory() - { - super(); - } - - public ServerSocket createServerSocket(int port) throws IOException - { - return new ServerSocket(port); - } - - public ServerSocket createServerSocket(int port, int backlog) - throws IOException - { - return new ServerSocket(port, backlog); - } - - public ServerSocket createServerSocket(int port, int backlog, - InetAddress ifAddress) - throws IOException - { - return new ServerSocket(port, backlog, ifAddress); - } - - public static javax.net.ServerSocketFactory getServerSocketFactory() - throws IOException - { - if (isSslEnabled()) - { - if (sslFactory == null) - { - try - { - sslFactory = BogusSSLContextFactory.getInstance(true) - .getServerSocketFactory(); - } - catch (GeneralSecurityException e) - { - IOException ioe = new IOException( - "could not create SSL socket"); - ioe.initCause(e); - throw ioe; - } - } - return sslFactory; - } - else - { - if (factory == null) - { - factory = new SSLServerSocketFactory(); - } - return factory; - } - - } - - public static boolean isSslEnabled() - { - return sslEnabled; - } - - public static void setSslEnabled(boolean newSslEnabled) - { - sslEnabled = newSslEnabled; - } -} diff --git a/java/common/src/main/java/org/apache/qpid/ssl/SSLSocketFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/SSLSocketFactory.java deleted file mode 100644 index ef9820f067..0000000000 --- a/java/common/src/main/java/org/apache/qpid/ssl/SSLSocketFactory.java +++ /dev/null @@ -1,138 +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.qpid.ssl; - -import javax.net.SocketFactory; -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.security.GeneralSecurityException; - -/** - * Simple Socket factory to create sockets with or without SSL enabled. - * If SSL enabled a "bogus" SSL Context is used (suitable for test purposes). - * <p/> - * This is based on an example that comes with MINA, written by Trustin Lee. - */ -public class SSLSocketFactory extends SocketFactory -{ - private static boolean sslEnabled = false; - - private static javax.net.ssl.SSLSocketFactory sslFactory = null; - - private static javax.net.SocketFactory factory = null; - - public SSLSocketFactory() - { - super(); - } - - public Socket createSocket(String arg1, int arg2) throws IOException, - UnknownHostException - { - if (isSslEnabled()) - { - return getSSLFactory().createSocket(arg1, arg2); - } - else - { - return new Socket(arg1, arg2); - } - } - - public Socket createSocket(String arg1, int arg2, InetAddress arg3, - int arg4) throws IOException, - UnknownHostException - { - if (isSslEnabled()) - { - return getSSLFactory().createSocket(arg1, arg2, arg3, arg4); - } - else - { - return new Socket(arg1, arg2, arg3, arg4); - } - } - - public Socket createSocket(InetAddress arg1, int arg2) - throws IOException - { - if (isSslEnabled()) - { - return getSSLFactory().createSocket(arg1, arg2); - } - else - { - return new Socket(arg1, arg2); - } - } - - public Socket createSocket(InetAddress arg1, int arg2, InetAddress arg3, - int arg4) throws IOException - { - if (isSslEnabled()) - { - return getSSLFactory().createSocket(arg1, arg2, arg3, arg4); - } - else - { - return new Socket(arg1, arg2, arg3, arg4); - } - } - - public static javax.net.SocketFactory getSocketFactory() - { - if (factory == null) - { - factory = new SSLSocketFactory(); - } - return factory; - } - - private javax.net.ssl.SSLSocketFactory getSSLFactory() - { - if (sslFactory == null) - { - try - { - sslFactory = BogusSSLContextFactory.getInstance(false) - .getSocketFactory(); - } - catch (GeneralSecurityException e) - { - throw new RuntimeException("could not create SSL socket", e); - } - } - return sslFactory; - } - - public static boolean isSslEnabled() - { - return sslEnabled; - } - - public static void setSslEnabled(boolean newSslEnabled) - { - sslEnabled = newSslEnabled; - } - -} |