From a83ac2221fb695217f6f2f8cc09e6153dc2578a6 Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Thu, 14 Mar 2013 17:19:43 +0000 Subject: QPID-4636: add unit tests for new TrustManagers Applied patch from Michal Zerola git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1456555 13f79535-47bb-0310-9956-ffa450edef68 --- .../startup/TrustStoreRecovererTest.java | 1 + .../java/org/apache/qpid/ssl/TrustManagerTest.java | 162 +++++++++++++++++++++ .../test_resources/ssl/java_broker_peerstore.jks | Bin 0 -> 1246 bytes 3 files changed, 163 insertions(+) create mode 100644 qpid/java/common/src/test/java/org/apache/qpid/ssl/TrustManagerTest.java create mode 100644 qpid/java/test-profiles/test_resources/ssl/java_broker_peerstore.jks diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java index 3b64f45c80..5e7784bc06 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java @@ -71,6 +71,7 @@ public class TrustStoreRecovererTest extends QpidTestCase attributes.put(TrustStore.PASSWORD, "my-secret-password"); attributes.put(TrustStore.TYPE, "NON-JKS"); attributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(TrustStore.PEERS_ONLY, Boolean.TRUE); attributes.put(TrustStore.DESCRIPTION, "Description"); return attributes; } diff --git a/qpid/java/common/src/test/java/org/apache/qpid/ssl/TrustManagerTest.java b/qpid/java/common/src/test/java/org/apache/qpid/ssl/TrustManagerTest.java new file mode 100644 index 0000000000..34ca4e0e03 --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/ssl/TrustManagerTest.java @@ -0,0 +1,162 @@ +/* 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.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Enumeration; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import org.apache.qpid.test.utils.QpidTestCase; +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 TrustManagerTest extends QpidTestCase +{ + private static final String BROKER_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_broker_keystore.jks"; + private static final String BROKER_PEERSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_broker_peerstore.jks"; + private static final String CLIENT_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_client_keystore.jks"; + private static final String STORE_PASSWORD = "password"; + private static final String STORE_TYPE = "JKS"; + private static final String DEFAULT_TRUST_MANAGER_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm(); + private static final String CERT_ALIAS_APP1 = "app1"; + private static final String CERT_ALIAS_APP2 = "app2"; + + // retrieves the client certificate's chain from store and returns it as an array + private X509Certificate[] getClientChain() throws Exception + { + final KeyStore ks = SSLUtil.getInitializedKeyStore(CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE); + final Certificate[] chain = ks.getCertificateChain(CERT_ALIAS_APP1); + return Arrays.copyOf(chain, chain.length, X509Certificate[].class); + } + + // verifies that peer store is loaded only with client's (peer's) certificates (no CA) + private void noCAinPeerStore(final KeyStore ps) throws KeyStoreException + { + final Enumeration aliases = ps.aliases(); + while (aliases.hasMoreElements()) + { + final String alias = aliases.nextElement(); + if (!alias.equalsIgnoreCase(CERT_ALIAS_APP1) && !alias.equalsIgnoreCase(CERT_ALIAS_APP2)) + { + fail("Broker's peer store contains other certificate than client's public keys"); + } + } + } + + public void testPeerStoreClientAuthentication() throws Exception + { + // first let's check that peer manager loaded with proper store succeeds + final KeyStore ps = SSLUtil.getInitializedKeyStore(BROKER_PEERSTORE_PATH, STORE_PASSWORD, STORE_TYPE); + this.noCAinPeerStore(ps); + final TrustManagerFactory pmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM); + pmf.init(ps); + final TrustManager[] delegatePeerManagers = pmf.getTrustManagers(); + boolean peerManagerTested = false; + for (final TrustManager tm : delegatePeerManagers) + { + if (tm instanceof X509TrustManager) + { + peerManagerTested = true; + // peer manager is supposed to trust only clients which peers certificates + // are directly in the store. CA signing will not be considered. + X509TrustManager peerManager = new QpidPeersOnlyTrustManager(ps, (X509TrustManager) tm); + // since broker's peerstore contains the client's certificate, the check should succeed + try + { + peerManager.checkClientTrusted(this.getClientChain(), "RSA"); + } + catch (CertificateException e) + { + fail("Client's validation against the broker's peer store manager failed."); + } + } + } + assertEquals("No QpidPeersOnlyTrustManager(s) were created from the peer store.", true, peerManagerTested); + // now let's check that peer manager loaded with improper store fails + final KeyStore ts = SSLUtil.getInitializedKeyStore(BROKER_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE); + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM); + tmf.init(ts); + final TrustManager[] delegateTrustManagers = tmf.getTrustManagers(); + for (final TrustManager tm : delegateTrustManagers) + { + if (tm instanceof X509TrustManager) + { + // peer manager is supposed to trust only clients which peers certificates + // are directly in the store. CA signing will not be considered. + X509TrustManager peerManager = new QpidPeersOnlyTrustManager(ts, (X509TrustManager) tm); + // since broker's truststore doesn't contain the client's certificate, the check should fail + try + { + peerManager.checkClientTrusted(this.getClientChain(), "RSA"); + fail("Client's validation against the broker's peer store manager didn't fail."); + } + catch (CertificateException e) + { + // expected + } + } + } + } + + public void testMultipleStoreClientAuthentication() throws Exception + { + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + final KeyStore ts = SSLUtil.getInitializedKeyStore(BROKER_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE); + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM); + tmf.init(ts); + final TrustManager[] delegateTrustManagers = tmf.getTrustManagers(); + for (final TrustManager tm : delegateTrustManagers) + { + if (tm instanceof X509TrustManager) + { + // add broker's trust manager + mulTrustManager.addTrustManager((X509TrustManager) tm); + } + } + final KeyStore ps = SSLUtil.getInitializedKeyStore(BROKER_PEERSTORE_PATH, STORE_PASSWORD, STORE_TYPE); + final TrustManagerFactory pmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM); + pmf.init(ps); + final TrustManager[] delegatePeerManagers = pmf.getTrustManagers(); + for (final TrustManager tm : delegatePeerManagers) + { + if (tm instanceof X509TrustManager) + { + // add broker's peer manager + mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ps, (X509TrustManager) tm)); + } + } + try + { + mulTrustManager.checkClientTrusted(this.getClientChain(), "RSA"); + } + catch (CertificateException ex) + { + fail("Client's validation against the broker's multi store manager failed."); + } + } +} diff --git a/qpid/java/test-profiles/test_resources/ssl/java_broker_peerstore.jks b/qpid/java/test-profiles/test_resources/ssl/java_broker_peerstore.jks new file mode 100644 index 0000000000..52027cae06 Binary files /dev/null and b/qpid/java/test-profiles/test_resources/ssl/java_broker_peerstore.jks differ -- cgit v1.2.1