blob: f152796375214dda003da9c52460ad2a3c1479bc [file] [log] [blame]
/* 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.server.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.test.utils.TestSSLConstants;
import org.apache.qpid.server.transport.network.security.ssl.QpidMultipleTrustManager;
import org.apache.qpid.server.transport.network.security.ssl.QpidPeersOnlyTrustManager;
import org.apache.qpid.server.transport.network.security.ssl.SSLUtil;
public class TrustManagerTest extends QpidTestCase
{
private static final String STORE_TYPE = "JKS";
private static final String DEFAULT_TRUST_MANAGER_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm();
// retrieves the client certificate's chain from store and returns it as an array
private X509Certificate[] getClientChain(final String storePath, final String alias) throws Exception
{
final KeyStore ks = SSLUtil.getInitializedKeyStore(storePath, TestSSLConstants.KEYSTORE_PASSWORD, STORE_TYPE);
final Certificate[] chain = ks.getCertificateChain(alias);
return Arrays.copyOf(chain, chain.length, X509Certificate[].class);
}
// verifies that peer store is loaded only with client's (peer's) app1 certificate (no CA)
private void noCAinPeerStore(final KeyStore ps) throws KeyStoreException
{
final Enumeration<String> aliases = ps.aliases();
while (aliases.hasMoreElements())
{
final String alias = aliases.nextElement();
if (!alias.equalsIgnoreCase(TestSSLConstants.CERT_ALIAS_APP1))
{
fail("Broker's peer store contains other certificate than client's app1 public key");
}
}
}
/**
* Tests that the QpidPeersOnlyTrustManager gives the expected behaviour when loaded separately
* with the broker peerstore and truststore.
*/
public void testQpidPeersOnlyTrustManager() throws Exception
{
// first let's check that peer manager loaded with the PEERstore succeeds
final KeyStore ps = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_PEERSTORE, TestSSLConstants.BROKER_PEERSTORE_PASSWORD, STORE_TYPE);
this.noCAinPeerStore(ps);
final TrustManagerFactory pmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
pmf.init(ps);
final TrustManager[] delegatePeerManagers = pmf.getTrustManagers();
X509TrustManager peerManager = null;
for (final TrustManager tm : delegatePeerManagers)
{
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.
peerManager = new QpidPeersOnlyTrustManager(ps, (X509TrustManager) tm);
}
}
try
{
// since broker's peerstore contains the client's app1 certificate, the check should succeed
peerManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE, TestSSLConstants.CERT_ALIAS_APP1), "RSA");
}
catch (CertificateException e)
{
fail("Trusted client's validation against the broker's peer store manager failed.");
}
try
{
// since broker's peerstore does not contain the client's app2 certificate, the check should fail
peerManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE, TestSSLConstants.CERT_ALIAS_APP2), "RSA");
fail("Untrusted client's validation against the broker's peer store manager succeeded.");
}
catch (CertificateException e)
{
//expected
}
// now let's check that peer manager loaded with the brokers TRUSTstore fails because
// it does not have the clients certificate in it (though it does have a CA-cert that
// would otherwise trust the client cert when using the regular trust manager).
final KeyStore ts = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_TRUSTSTORE, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, STORE_TYPE);
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
tmf.init(ts);
final TrustManager[] delegateTrustManagers = tmf.getTrustManagers();
peerManager = null;
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.
peerManager = new QpidPeersOnlyTrustManager(ts, (X509TrustManager) tm);
}
}
try
{
// since broker's truststore doesn't contain the client's app1 certificate, the check should fail
// despite the fact that the truststore does have a CA that would otherwise trust the cert
peerManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE, TestSSLConstants.CERT_ALIAS_APP1), "RSA");
fail("Client's validation against the broker's peer store manager didn't fail.");
}
catch (CertificateException e)
{
// expected
}
try
{
// since broker's truststore doesn't contain the client's app2 certificate, the check should fail
// despite the fact that the truststore does have a CA that would otherwise trust the cert
peerManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE, TestSSLConstants.CERT_ALIAS_APP2), "RSA");
fail("Client's validation against the broker's peer store manager didn't fail.");
}
catch (CertificateException e)
{
// expected
}
}
/**
* Tests that the QpidMultipleTrustManager gives the expected behaviour when wrapping a
* regular TrustManager against the broker truststore.
*/
public void testQpidMultipleTrustManagerWithRegularTrustStore() throws Exception
{
final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
final KeyStore ts = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_TRUSTSTORE, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, STORE_TYPE);
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
tmf.init(ts);
final TrustManager[] delegateTrustManagers = tmf.getTrustManagers();
boolean trustManagerAdded = false;
for (final TrustManager tm : delegateTrustManagers)
{
if (tm instanceof X509TrustManager)
{
// add broker's trust manager
mulTrustManager.addTrustManager((X509TrustManager) tm);
trustManagerAdded = true;
}
}
assertTrue("The regular trust manager for the trust store was not added", trustManagerAdded);
try
{
// verify the CA-trusted app1 cert (should succeed)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP1), "RSA");
}
catch (CertificateException ex)
{
fail("Trusted client's validation against the broker's multi store manager failed.");
}
try
{
// verify the CA-trusted app2 cert (should succeed)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP2), "RSA");
}
catch (CertificateException ex)
{
fail("Trusted client's validation against the broker's multi store manager failed.");
}
try
{
// verify the untrusted cert (should fail)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.UNTRUSTED_KEYSTORE,
TestSSLConstants.CERT_ALIAS_UNTRUSTED_CLIENT), "RSA");
fail("Untrusted client's validation against the broker's multi store manager unexpectedly passed.");
}
catch (CertificateException ex)
{
// expected
}
}
/**
* Tests that the QpidMultipleTrustManager gives the expected behaviour when wrapping a
* QpidPeersOnlyTrustManager against the broker peerstore.
*/
public void testQpidMultipleTrustManagerWithPeerStore() throws Exception
{
final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
final KeyStore ps = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_PEERSTORE, TestSSLConstants.BROKER_PEERSTORE_PASSWORD, STORE_TYPE);
final TrustManagerFactory pmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
pmf.init(ps);
final TrustManager[] delegatePeerManagers = pmf.getTrustManagers();
boolean peerManagerAdded = false;
for (final TrustManager tm : delegatePeerManagers)
{
if (tm instanceof X509TrustManager)
{
// add broker's peer manager
mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ps, (X509TrustManager) tm));
peerManagerAdded = true;
}
}
assertTrue("The QpidPeersOnlyTrustManager for the peerstore was not added", peerManagerAdded);
try
{
// verify the trusted app1 cert (should succeed as the key is in the peerstore)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP1), "RSA");
}
catch (CertificateException ex)
{
fail("Trusted client's validation against the broker's multi store manager failed.");
}
try
{
// verify the untrusted app2 cert (should fail as the key is not in the peerstore)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP2), "RSA");
fail("Untrusted client's validation against the broker's multi store manager unexpectedly passed.");
}
catch (CertificateException ex)
{
// expected
}
try
{
// verify the untrusted cert (should fail as the key is not in the peerstore)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.UNTRUSTED_KEYSTORE,
TestSSLConstants.CERT_ALIAS_UNTRUSTED_CLIENT), "RSA");
fail("Untrusted client's validation against the broker's multi store manager unexpectedly passed.");
}
catch (CertificateException ex)
{
// expected
}
}
/**
* Tests that the QpidMultipleTrustManager gives the expected behaviour when wrapping a
* QpidPeersOnlyTrustManager against the broker peerstore, a regular TrustManager
* against the broker truststore.
*/
public void testQpidMultipleTrustManagerWithTrustAndPeerStores() throws Exception
{
final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
final KeyStore ts = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_TRUSTSTORE, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, STORE_TYPE);
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
tmf.init(ts);
final TrustManager[] delegateTrustManagers = tmf.getTrustManagers();
boolean trustManagerAdded = false;
for (final TrustManager tm : delegateTrustManagers)
{
if (tm instanceof X509TrustManager)
{
// add broker's trust manager
mulTrustManager.addTrustManager((X509TrustManager) tm);
trustManagerAdded = true;
}
}
assertTrue("The regular trust manager for the trust store was not added", trustManagerAdded);
final KeyStore ps = SSLUtil.getInitializedKeyStore(TestSSLConstants.BROKER_PEERSTORE, TestSSLConstants.BROKER_PEERSTORE_PASSWORD, STORE_TYPE);
final TrustManagerFactory pmf = TrustManagerFactory.getInstance(DEFAULT_TRUST_MANAGER_ALGORITHM);
pmf.init(ps);
final TrustManager[] delegatePeerManagers = pmf.getTrustManagers();
boolean peerManagerAdded = false;
for (final TrustManager tm : delegatePeerManagers)
{
if (tm instanceof X509TrustManager)
{
// add broker's peer manager
mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ps, (X509TrustManager) tm));
peerManagerAdded = true;
}
}
assertTrue("The QpidPeersOnlyTrustManager for the peerstore was not added", peerManagerAdded);
try
{
// verify the CA-trusted app1 cert (should succeed)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP1), "RSA");
}
catch (CertificateException ex)
{
fail("Trusted client's validation against the broker's multi store manager failed.");
}
try
{
// verify the CA-trusted app2 cert (should succeed)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.KEYSTORE,
TestSSLConstants.CERT_ALIAS_APP2), "RSA");
}
catch (CertificateException ex)
{
fail("Trusted client's validation against the broker's multi store manager failed.");
}
try
{
// verify the untrusted cert (should fail)
mulTrustManager.checkClientTrusted(this.getClientChain(TestSSLConstants.UNTRUSTED_KEYSTORE,
TestSSLConstants.CERT_ALIAS_UNTRUSTED_CLIENT), "RSA");
fail("Untrusted client's validation against the broker's multi store manager unexpectedly passed.");
}
catch (CertificateException ex)
{
// expected
}
}
}