You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2013/03/14 18:19:21 UTC

svn commit: r1456554 - in /qpid/trunk/qpid/java: broker/src/main/java/org/apache/qpid/server/model/ broker/src/main/java/org/apache/qpid/server/model/adapter/ common/src/main/java/org/apache/qpid/ssl/ common/src/main/java/org/apache/qpid/transport/netw...

Author: robbie
Date: Thu Mar 14 17:19:20 2013
New Revision: 1456554

URL: http://svn.apache.org/r1456554
Log:
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

Added:
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java
Modified:
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java Thu Mar 14 17:19:20 2013
@@ -87,6 +87,8 @@ public interface Broker extends Configur
     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 Configur
                               KEY_STORE_CERT_ALIAS,
                               TRUST_STORE_PATH,
                               TRUST_STORE_PASSWORD,
+                              PEER_STORE_PATH,
+                              PEER_STORE_PASSWORD,
                               GROUP_FILE
                               ));
 

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java Thu Mar 14 17:19:20 2013
@@ -38,6 +38,7 @@ public interface TrustStore extends Conf
 
     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 Conf
                               DESCRIPTION,
                               PATH,
                               PASSWORD,
+                              PEERS_ONLY,
                               TYPE,
                               KEY_MANAGER_FACTORY_ALGORITHM
                               ));

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java Thu Mar 14 17:19:20 2013
@@ -47,6 +47,7 @@ public abstract class AbstractKeyStoreAd
         _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 AbstractKeyStoreAd
 
     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));
+            }
         }
     }
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java Thu Mar 14 17:19:20 2013
@@ -24,6 +24,7 @@ import static org.apache.qpid.transport.
 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 Por
                     + 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 Por
         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
             {

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java Thu Mar 14 17:19:20 2013
@@ -101,6 +101,8 @@ public class BrokerAdapter extends Abstr
         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 Abstr
             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()

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java?rev=1456554&r1=1456553&r2=1456554&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java Thu Mar 14 17:19:20 2013
@@ -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)
         {

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java?rev=1456554&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidMultipleTrustManager.java Thu Mar 14 17:19:20 2013
@@ -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()]);
+    }
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java?rev=1456554&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidPeersOnlyTrustManager.java Thu Mar 14 17:19:20 2013
@@ -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];
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org