Bug 316382 certificate validator class for use in multiple places in jetty, pulling this in now from michael's sandbox as its generally useful for his client and server work and my current policy changes

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2748 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Jesse McConnell 2011-02-08 23:01:44 +00:00
parent 4bd3f1b6b0
commit 51d0e347e7
1 changed files with 193 additions and 0 deletions

View File

@ -0,0 +1,193 @@
package org.eclipse.jetty.util.security;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.CRL;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderResult;
import java.security.cert.CertPathValidator;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import org.eclipse.jetty.util.log.Log;
/**
* Convenience class to handle validation of certificates, aliases and keystores
*
* Currently handles certificate revocation lists, should evolve to handle ocsp as well
*
* TODO: consider the case of a null trust store, is that important?
* TODO: add what support for ocsp is needed, if any
*/
public class CertificateValidator
{
private KeyStore _trustStore;
private Collection<? extends CRL> _crls;
private int _maxCertPathLength = -1;
/**
* creates an instance of the certificate validator
*
* @param trustStore
* @param crls
*/
public CertificateValidator(KeyStore trustStore, Collection<? extends CRL> crls)
{
_trustStore = trustStore;
_crls = crls;
}
/**
* validates all aliases inside of a given keystore
*
* @param keyStore
* @throws CertificateException
*/
public void validate( KeyStore keyStore ) throws CertificateException
{
try
{
Enumeration<String> aliases = keyStore.aliases();
for ( ; aliases.hasMoreElements(); )
{
String alias = aliases.nextElement();
validate(keyStore,alias);
}
}
catch ( KeyStoreException kse )
{
throw new CertificateException("error obtaining aliases", kse);
}
}
/**
* validates a specific alias inside of the keystore being passed in
*
* @param keyStore
* @param keyAlias
* @return
* @throws CertificateException
*/
public String validate(KeyStore keyStore, String keyAlias) throws CertificateException
{
String result = null;
if (keyAlias != null)
{
try
{
validate(keyStore, keyStore.getCertificate(keyAlias));
}
catch (KeyStoreException ex)
{
Log.debug(ex);
throw new CertificateException("Unable to validate certificate for alias [" +
keyAlias + "]: " + ex.getMessage());
}
result = keyAlias;
}
return result;
}
/**
* validates a specific certificate inside of the keystore being passed in
*
* @param keyStore
* @param cert
* @throws CertificateException
*/
public void validate(KeyStore keyStore, Certificate cert) throws CertificateException
{
if (cert != null && cert instanceof X509Certificate)
{
((X509Certificate)cert).checkValidity();
String certAlias = "[none]";
try
{
certAlias = keyStore.getCertificateAlias((X509Certificate)cert);
Certificate[] certChain = keyStore.getCertificateChain(certAlias);
ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
for (Certificate item : certChain)
{
if (!(item instanceof X509Certificate))
{
throw new CertificateException("Invalid certificate type in chain");
}
certList.add((X509Certificate)item);
}
if (certList.isEmpty())
{
throw new CertificateException("Invalid certificate chain");
}
X509CertSelector certSelect = new X509CertSelector();
certSelect.setCertificate(certList.get(0));
// Configure certification path builder parameters
PKIXBuilderParameters pbParams = new PKIXBuilderParameters(_trustStore, certSelect);
pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList)));
// Set static Certificate Revocation List
if (_crls != null && !_crls.isEmpty())
{
pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls)));
}
// Enable revocation checking
pbParams.setRevocationEnabled(true);
// Set maximum certification path length
pbParams.setMaxPathLength(_maxCertPathLength);
// Build certification path
CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams);
// Validate certification path
CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams);
}
catch (Exception ex)
{
Log.debug(ex);
throw new CertificateException("Unable to validate certificate for alias [" +
certAlias + "]: " + ex.getMessage());
}
}
}
public int getMaxCertPathLength()
{
return _maxCertPathLength;
}
public void setMaxCertPathLength(int maxCertPathLength)
{
_maxCertPathLength = maxCertPathLength;
}
public KeyStore getTrustStore()
{
return _trustStore;
}
public Collection<? extends CRL> getCrls()
{
return _crls;
}
}