summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Gemmell <robbie@apache.org>2013-03-14 17:19:20 +0000
committerRobert Gemmell <robbie@apache.org>2013-03-14 17:19:20 +0000
commit7d3e03d5035e13fd8acc147a0e5d741ebd37b4fa (patch)
tree7d71c54b1755f060bd405ec4158ed1703180c344
parent098f65fa6eca15ee673392681bcaabcbb049bd04 (diff)
downloadqpid-python-7d3e03d5035e13fd8acc147a0e5d741ebd37b4fa.tar.gz
QPID-4636: add support for a broker 'peerStore' that can be used to perform SSL client auth based on specific 'trusted peer' certs existing in it, rather than via use of a trusted CA cert.
Applied patch from Michal Zerola git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1456554 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java16
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java111
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java103
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java81
8 files changed, 324 insertions, 37 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
index c2b8b9886f..1d2fdd0452 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -87,6 +87,8 @@ public interface Broker extends ConfiguredObject
String KEY_STORE_CERT_ALIAS = "keyStoreCertAlias";
String TRUST_STORE_PATH = "trustStorePath";
String TRUST_STORE_PASSWORD = "trustStorePassword";
+ String PEER_STORE_PATH = "peerStorePath";
+ String PEER_STORE_PASSWORD = "peerStorePassword";
/*
* A temporary attributes to set the broker group file.
@@ -136,6 +138,8 @@ public interface Broker extends ConfiguredObject
KEY_STORE_CERT_ALIAS,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
+ PEER_STORE_PATH,
+ PEER_STORE_PASSWORD,
GROUP_FILE
));
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 0c322ae02f..53498ab431 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
@@ -38,6 +38,7 @@ public interface TrustStore extends ConfiguredObject
String PATH = "path";
String PASSWORD = "password";
+ String PEERS_ONLY = "peersOnly";
String TYPE = "type";
String KEY_MANAGER_FACTORY_ALGORITHM = "keyManagerFactoryAlgorithm";
@@ -55,6 +56,7 @@ public interface TrustStore extends ConfiguredObject
DESCRIPTION,
PATH,
PASSWORD,
+ PEERS_ONLY,
TYPE,
KEY_MANAGER_FACTORY_ALGORITHM
));
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
index ebd98f915d..80196c395e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
@@ -47,6 +47,7 @@ public abstract class AbstractKeyStoreAdapter extends AbstractAdapter
_name = MapValueConverter.getStringAttribute(TrustStore.NAME, attributes);
_password = MapValueConverter.getStringAttribute(TrustStore.PASSWORD, attributes);
setMandatoryAttribute(TrustStore.PATH, attributes);
+ setOptionalAttribute(TrustStore.PEERS_ONLY, attributes);
setOptionalAttribute(TrustStore.TYPE, attributes);
setOptionalAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, attributes);
setOptionalAttribute(TrustStore.DESCRIPTION, attributes);
@@ -190,9 +191,17 @@ public abstract class AbstractKeyStoreAdapter extends AbstractAdapter
private void setOptionalAttribute(String name, Map<String, Object> attributeValues)
{
- if (attributeValues.get(name) != null)
+ Object attrValue = attributeValues.get(name);
+ if (attrValue != null)
{
- changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues));
+ if (attrValue instanceof Boolean)
+ {
+ changeAttribute(name, null, MapValueConverter.getBooleanAttribute(name, attributeValues));
+ }
+ else
+ {
+ changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues));
+ }
}
}
}
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 95aafa9ceb..e7057f89d3 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
@@ -24,6 +24,7 @@ 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.Collection;
import java.util.HashSet;
import java.util.Map;
@@ -139,8 +140,8 @@ public class AmqpPortAdapter extends PortAdapter
+ this.getName() + "' but no key store defined");
}
- TrustStore trustStore = _broker.getDefaultTrustStore();
- if (((Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH)) && trustStore == null)
+ Collection<TrustStore> trustStores = _broker.getTrustStores();
+ if (((Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH)) && trustStores.isEmpty())
{
throw new IllegalConfigurationException("Client certificate authentication is enabled on AMQP port '"
+ this.getName() + "' but no trust store defined");
@@ -155,20 +156,20 @@ public class AmqpPortAdapter extends PortAdapter
final SSLContext sslContext;
try
{
- if(trustStore != null)
+ if(! trustStores.isEmpty())
{
- String trustStorePassword = trustStore.getPassword();
- String trustStoreType = (String)trustStore.getAttribute(TrustStore.TYPE);
- String trustManagerFactoryAlgorithm = (String)trustStore.getAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM);
- String trustStorePath = (String)trustStore.getAttribute(TrustStore.PATH);
-
- sslContext = SSLContextFactory.buildClientContext(trustStorePath,
- trustStorePassword,
- trustStoreType,
- trustManagerFactoryAlgorithm,
- keystorePath,
- keystorePassword, keystoreType, keyManagerFactoryAlgorithm,
- certAlias);
+ 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.KEY_MANAGER_FACTORY_ALGORITHM)));
+ }
+ sslContext = SSLContextFactory.buildClientContext(trstWrappers, keystorePath,
+ keystorePassword, keystoreType,
+ keyManagerFactoryAlgorithm, certAlias);
}
else
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index 291f751a5c..8c0ac06fdd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -101,6 +101,8 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
put(KEY_STORE_CERT_ALIAS, String.class);
put(TRUST_STORE_PATH, String.class);
put(TRUST_STORE_PASSWORD, String.class);
+ put(PEER_STORE_PATH, String.class);
+ put(PEER_STORE_PASSWORD, String.class);
put(GROUP_FILE, String.class);
}});
@@ -231,6 +233,20 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
TrustStoreAdapter trustStore = new TrustStoreAdapter(_defaultTrustStoreId, this, trsustStoreAttributes);
addTrustStore(trustStore);
}
+ String peerStorePath = (String) getAttribute(PEER_STORE_PATH);
+ if (peerStorePath != null)
+ {
+ Map<String, Object> peerStoreAttributes = new HashMap<String, Object>();
+ UUID peerStoreId = UUID.randomUUID();
+ peerStoreAttributes.put(TrustStore.NAME, peerStoreId.toString());
+ peerStoreAttributes.put(TrustStore.PATH, peerStorePath);
+ peerStoreAttributes.put(TrustStore.PEERS_ONLY, Boolean.TRUE);
+ peerStoreAttributes.put(TrustStore.PASSWORD, (String) actualAttributes.get(PEER_STORE_PASSWORD));
+ peerStoreAttributes.put(TrustStore.TYPE, java.security.KeyStore.getDefaultType());
+ peerStoreAttributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
+ TrustStoreAdapter trustStore = new TrustStoreAdapter(peerStoreId, this, peerStoreAttributes);
+ addTrustStore(trustStore);
+ }
}
public Collection<VirtualHost> getVirtualHosts()
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
index b2967bb0bb..01381ad23f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
@@ -21,6 +21,8 @@
package org.apache.qpid.ssl;
import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager;
+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;
import javax.net.ssl.KeyManager;
@@ -28,9 +30,16 @@ import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.X509Certificate;
+
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
/**
* Factory used to create SSLContexts. SSL needs to be configured
@@ -40,6 +49,26 @@ import java.security.KeyStore;
public class SSLContextFactory
{
public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS";
+
+ public static class TrustStoreWrapper
+ {
+ private final String trustStorePath;
+ private final String trustStorePassword;
+ private final String trustStoreType;
+ private final Boolean trustStorePeersOnly;
+ private String trustManagerFactoryAlgorithm;
+
+ public TrustStoreWrapper(final String trustStorePath, final String trustStorePassword,
+ final String trustStoreType, final Boolean trustStorePeersOnly,
+ final String trustManagerFactoryAlgorithm)
+ {
+ this.trustStorePath = trustStorePath;
+ this.trustStorePassword = trustStorePassword;
+ this.trustStoreType = trustStoreType;
+ this.trustStorePeersOnly = trustStorePeersOnly;
+ this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm;
+ }
+ }
private SSLContextFactory()
{
@@ -51,25 +80,34 @@ public class SSLContextFactory
final String keyManagerFactoryAlgorithm)
throws GeneralSecurityException, IOException
{
- return buildContext(null, null, null, null, keyStorePath, keyStorePassword, keyStoreType,
- keyManagerFactoryAlgorithm, null);
+ return buildContext(Collections.<TrustStoreWrapper>emptyList(), keyStorePath,
+ keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm, null);
+ }
+
+ public static SSLContext buildClientContext(Collection<TrustStoreWrapper> trustStores,
+ final String keyStorePath, final String keyStorePassword,
+ final String keyStoreType, final String keyManagerFactoryAlgorithm,
+ final String certAlias) throws GeneralSecurityException, IOException
+ {
+ return buildContext(trustStores, keyStorePath, keyStorePassword, keyStoreType,
+ keyManagerFactoryAlgorithm, certAlias);
}
public static SSLContext buildClientContext(final String trustStorePath,
final String trustStorePassword, final String trustStoreType,
- final String trustManagerFactoryAlgorithm, final String keyStorePath,
- final String keyStorePassword, final String keyStoreType,
+ final String trustManagerFactoryAlgorithm, final String keyStorePath,
+ final String keyStorePassword, final String keyStoreType,
final String keyManagerFactoryAlgorithm, final String certAlias)
throws GeneralSecurityException, IOException
{
- return buildContext(trustStorePath, trustStorePassword, trustStoreType,
- trustManagerFactoryAlgorithm, keyStorePath, keyStorePassword, keyStoreType,
- keyManagerFactoryAlgorithm, certAlias);
+ TrustStoreWrapper trstWrapper = new TrustStoreWrapper(trustStorePath, trustStorePassword,
+ trustStoreType, Boolean.FALSE,
+ trustManagerFactoryAlgorithm);
+ return buildContext(Collections.singletonList(trstWrapper), keyStorePath,
+ keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm, certAlias);
}
- private static SSLContext buildContext(final String trustStorePath,
- final String trustStorePassword, final String trustStoreType,
- final String trustManagerFactoryAlgorithm,
+ private static SSLContext buildContext(final Collection<TrustStoreWrapper> trstWrappers,
final String keyStorePath, final String keyStorePassword,
final String keyStoreType, final String keyManagerFactoryAlgorithm,
final String certAlias)
@@ -81,21 +119,54 @@ public class SSLContextFactory
final TrustManager[] trustManagers;
final KeyManager[] keyManagers;
-
- if (trustStorePath != null)
+
+ final Collection<TrustManager> trustManagersCol = new ArrayList<TrustManager>();
+ final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
+ for (TrustStoreWrapper tsw : trstWrappers)
{
- final KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath,
- trustStorePassword, trustStoreType);
- final TrustManagerFactory tmf = TrustManagerFactory
- .getInstance(trustManagerFactoryAlgorithm);
- tmf.init(ts);
-
- trustManagers = tmf.getTrustManagers();
+ if (tsw.trustStorePath != null)
+ {
+ final KeyStore ts = SSLUtil.getInitializedKeyStore(tsw.trustStorePath,
+ tsw.trustStorePassword, tsw.trustStoreType);
+ final TrustManagerFactory tmf = TrustManagerFactory
+ .getInstance(tsw.trustManagerFactoryAlgorithm);
+ tmf.init(ts);
+ TrustManager[] delegateManagers = tmf.getTrustManagers();
+ for (TrustManager tm : delegateManagers)
+ {
+ if (tm instanceof X509TrustManager)
+ {
+ if (Boolean.TRUE.equals(tsw.trustStorePeersOnly))
+ {
+ // 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);
+ }
+ }
+ }
}
- else
+ if (! mulTrustManager.isEmpty())
+ {
+ trustManagersCol.add(mulTrustManager);
+ }
+
+ if (trustManagersCol.isEmpty())
{
trustManagers = null;
}
+ else
+ {
+ trustManagers = trustManagersCol.toArray(new TrustManager[trustManagersCol.size()]);
+ }
if (keyStorePath != null)
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java
new file mode 100644
index 0000000000..0705f31fcb
--- /dev/null
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java
@@ -0,0 +1,103 @@
+/*
+*
+* 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.transport.network.security.ssl;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Supports multiple X509TrustManager(s). Check succeeds if any of the
+ * underlying managers succeeds.
+ */
+public class QpidMultipleTrustManager implements X509TrustManager {
+
+ private List<X509TrustManager> trustManagers;
+
+ public QpidMultipleTrustManager() {
+ this.trustManagers = new ArrayList<X509TrustManager>();
+ }
+
+ public boolean isEmpty()
+ {
+ return trustManagers.isEmpty();
+ }
+
+ public void addTrustManager(final X509TrustManager trustManager)
+ {
+ this.trustManagers.add(trustManager);
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ for (X509TrustManager trustManager : this.trustManagers)
+ {
+ try
+ {
+ trustManager.checkClientTrusted(chain, authType);
+ // this trustManager check succeeded, no need to check another one
+ return;
+ }
+ catch(CertificateException ex)
+ {
+ // do nothing, try another one in a loop
+ }
+ }
+ // no trustManager call succeeded, throw an exception
+ throw new CertificateException();
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ for (X509TrustManager trustManager : this.trustManagers)
+ {
+ try
+ {
+ trustManager.checkServerTrusted(chain, authType);
+ // this trustManager check succeeded, no need to check another one
+ return;
+ }
+ catch(CertificateException ex)
+ {
+ // do nothing, try another one in a loop
+ }
+ }
+ // no trustManager call succeeded, throw an exception
+ throw new CertificateException();
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ final Collection<X509Certificate> accIssuersCol = new ArrayList<X509Certificate>();
+ for (X509TrustManager trustManager : this.trustManagers)
+ {
+ accIssuersCol.addAll(Arrays.asList(trustManager.getAcceptedIssuers()));
+ }
+ return accIssuersCol.toArray(new X509Certificate[accIssuersCol.size()]);
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java
new file mode 100644
index 0000000000..c988ff8d69
--- /dev/null
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java
@@ -0,0 +1,81 @@
+/*
+*
+* 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.transport.network.security.ssl;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * TrustManager implementation which accepts the client certificate
+ * only if the underlying check by the delegate pass through and
+ * the certificate is physically saved in the truststore.
+ */
+public class QpidPeersOnlyTrustManager implements X509TrustManager {
+
+ final private KeyStore ts;
+ final private X509TrustManager delegate;
+ final List<Certificate> trustedCerts = new ArrayList<Certificate>();
+
+ public QpidPeersOnlyTrustManager(KeyStore ts, X509TrustManager trustManager) throws KeyStoreException {
+ this.ts = ts;
+ this.delegate = trustManager;
+ Enumeration<String> aliases = this.ts.aliases();
+ while (aliases.hasMoreElements())
+ {
+ trustedCerts.add(ts.getCertificate(aliases.nextElement()));
+ }
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ this.delegate.checkClientTrusted(chain, authType);
+ for (Certificate serverTrustedCert : this.trustedCerts)
+ {
+ // first position in the chain contains the peer's own certificate
+ if (chain[0].equals(serverTrustedCert))
+ return; // peer's certificate found in the store
+ }
+ // peer's certificate was not found in the store, do not trust the client
+ throw new CertificateException();
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ this.delegate.checkServerTrusted(chain, authType);
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ // return empty array since this implementation of TrustManager doesn't
+ // rely on certification authorities
+ return new X509Certificate[0];
+ }
+}