diff options
| author | Robert Godfrey <rgodfrey@apache.org> | 2013-08-08 15:05:58 +0000 |
|---|---|---|
| committer | Robert Godfrey <rgodfrey@apache.org> | 2013-08-08 15:05:58 +0000 |
| commit | 414074d9fcec48fe395a061d3d31c255c4bbc13f (patch) | |
| tree | 1e7f921c6606c23518f67795bc8955a565692e68 /qpid/java/broker | |
| parent | e33c4e5c33768233282b69c9cb14dd515d191bb7 (diff) | |
| download | qpid-python-414074d9fcec48fe395a061d3d31c255c4bbc13f.tar.gz | |
QPID-5056 : [Java Broker] Change configuration model to allow for KeyStores/TrustStores which are not JKS files on the filesystem
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1511825 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker')
5 files changed, 161 insertions, 30 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java index 74a7469ffb..ab909390bd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java @@ -20,9 +20,11 @@ */ package org.apache.qpid.server.model; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import javax.net.ssl.KeyManager; public interface KeyStore extends ConfiguredObject { @@ -64,4 +66,7 @@ public interface KeyStore extends ConfiguredObject public String getPassword(); public void setPassword(String password); + + public KeyManager[] getKeyManagers() throws GeneralSecurityException; + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java index c686e7bd50..d313e1832f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java @@ -20,9 +20,11 @@ */ package org.apache.qpid.server.model; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import javax.net.ssl.TrustManager; public interface TrustStore extends ConfiguredObject { @@ -64,4 +66,8 @@ public interface TrustStore extends ConfiguredObject public String getPassword(); public void setPassword(String password); + + public TrustManager[] getTrustManagers() throws GeneralSecurityException; + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java index 02ff98fb0e..a4ce95e5aa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java @@ -21,18 +21,21 @@ package org.apache.qpid.server.model.adapter; import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; -import java.io.IOException; import java.net.InetSocketAddress; import java.security.GeneralSecurityException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -46,10 +49,9 @@ import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; -import org.apache.qpid.server.util.MapValueConverter; -import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.NetworkTransportConfiguration; import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; public class AmqpPortAdapter extends PortAdapter { @@ -136,8 +138,8 @@ public class AmqpPortAdapter extends PortAdapter private SSLContext createSslContext() { KeyStore keyStore = getKeyStore(); - Collection<TrustStore> trustStores = getTrustStores(); + boolean needClientCert = (Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH); if (needClientCert && trustStores.isEmpty()) { @@ -145,44 +147,58 @@ public class AmqpPortAdapter extends PortAdapter + this.getName() + "' but no trust store defined"); } - String keystorePath = (String)keyStore.getAttribute(KeyStore.PATH); - String keystorePassword = keyStore.getPassword(); - String keystoreType = (String)keyStore.getAttribute(KeyStore.TYPE); - String keyManagerFactoryAlgorithm = (String)keyStore.getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); - String certAlias = (String)keyStore.getAttribute(KeyStore.CERTIFICATE_ALIAS); - - final SSLContext sslContext; try { - if(! trustStores.isEmpty()) + SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManager[] keyManagers = keyStore.getKeyManagers(); + + TrustManager[] trustManagers; + if(trustStores == null || trustStores.isEmpty()) { - Collection<SSLContextFactory.TrustStoreWrapper> trstWrappers = new ArrayList<SSLContextFactory.TrustStoreWrapper>(); - for (TrustStore trustStore : trustStores) - { - trstWrappers.add(new SSLContextFactory.TrustStoreWrapper((String)trustStore.getAttribute(TrustStore.PATH), - trustStore.getPassword(), - (String)trustStore.getAttribute(TrustStore.TYPE), - (Boolean) trustStore.getAttribute(TrustStore.PEERS_ONLY), - (String)trustStore.getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM))); - } - sslContext = SSLContextFactory.buildClientContext(trstWrappers, keystorePath, - keystorePassword, keystoreType, - keyManagerFactoryAlgorithm, certAlias); + trustManagers = null; + } + else if(trustStores.size() == 1) + { + trustManagers = trustStores.iterator().next().getTrustManagers(); } else { - sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm); + Collection<TrustManager> trustManagerList = new ArrayList<TrustManager>(); + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + + for(TrustStore ts : trustStores) + { + TrustManager[] managers = ts.getTrustManagers(); + if(managers != null) + { + for(TrustManager manager : managers) + { + if(manager instanceof X509TrustManager) + { + mulTrustManager.addTrustManager((X509TrustManager)manager); + } + else + { + trustManagerList.add(manager); + } + } + } + } + if(!mulTrustManager.isEmpty()) + { + trustManagerList.add(mulTrustManager); + } + trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]); } + sslContext.init(keyManagers, trustManagers, null); + + return sslContext; + } catch (GeneralSecurityException e) { throw new RuntimeException("Unable to create SSLContext for key or trust store", e); } - catch (IOException e) - { - throw new RuntimeException("Unable to create SSLContext - unable to load key/trust store", e); - } - return sslContext; } private AmqpProtocolVersion getDefaultAmqpSupportedReply() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java index 4d4d3bb31d..1101232c96 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java @@ -20,8 +20,10 @@ */ package org.apache.qpid.server.model.adapter; +import java.io.IOException; import java.lang.reflect.Type; import java.security.AccessControlException; +import java.security.GeneralSecurityException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; @@ -32,6 +34,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -42,6 +45,7 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore @@ -210,4 +214,41 @@ public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore + keyManagerFactoryAlgorithm); } } + + public KeyManager[] getKeyManagers() throws GeneralSecurityException + { + String keyStorePath = (String)getAttribute(KeyStore.PATH); + String keyStorePassword = getPassword(); + String keyStoreType = (String)getAttribute(KeyStore.TYPE); + String keyManagerFactoryAlgorithm = (String)getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); + String certAlias = (String)getAttribute(KeyStore.CERTIFICATE_ALIAS); + + try + { + if (certAlias != null) + { + return new KeyManager[] { + new QpidClientX509KeyManager( certAlias, keyStorePath, keyStoreType, keyStorePassword, + keyManagerFactoryAlgorithm) + }; + + } + else + { + final java.security.KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath, keyStorePassword, keyStoreType); + + char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray(); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithm); + + kmf.init(ks, keyStoreCharPassword); + + return kmf.getKeyManagers(); + } + } + catch (IOException e) + { + throw new GeneralSecurityException(e); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java index 06089e43c6..5e7bfff4de 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java @@ -20,8 +20,11 @@ */ package org.apache.qpid.server.model.adapter; +import java.io.IOException; import java.lang.reflect.Type; import java.security.AccessControlException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; @@ -30,8 +33,10 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.IntegrityViolationException; @@ -40,6 +45,8 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; +import org.apache.qpid.transport.network.security.ssl.QpidPeersOnlyTrustManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustStore @@ -189,4 +196,60 @@ public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustS throw new IllegalConfigurationException("Unknown trustManagerFactoryAlgorithm: " + trustManagerFactoryAlgorithm); } } + + public TrustManager[] getTrustManagers() throws GeneralSecurityException + { + String trustStorePath = (String)getAttribute(TrustStore.PATH); + String trustStorePassword = getPassword(); + String trustStoreType = (String)getAttribute(TrustStore.TYPE); + String trustManagerFactoryAlgorithm = (String)getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM); + + try + { + KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath, trustStorePassword, trustStoreType); + final TrustManagerFactory tmf = TrustManagerFactory + .getInstance(trustManagerFactoryAlgorithm); + tmf.init(ts); + final Collection<TrustManager> trustManagersCol = new ArrayList<TrustManager>(); + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + TrustManager[] delegateManagers = tmf.getTrustManagers(); + for (TrustManager tm : delegateManagers) + { + if (tm instanceof X509TrustManager) + { + if (Boolean.TRUE.equals(getAttribute(PEERS_ONLY))) + { + // truststore is supposed to trust only clients which peers certificates + // are directly in the store. CA signing will not be considered. + mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ts, (X509TrustManager) tm)); + } + else + { + mulTrustManager.addTrustManager((X509TrustManager) tm); + } + } + else + { + trustManagersCol.add(tm); + } + } + if (! mulTrustManager.isEmpty()) + { + trustManagersCol.add(mulTrustManager); + } + + if (trustManagersCol.isEmpty()) + { + return null; + } + else + { + return trustManagersCol.toArray(new TrustManager[trustManagersCol.size()]); + } + } + catch (IOException e) + { + throw new GeneralSecurityException(e); + } + } } |
