Mercurial Hosting > luan
diff src/org/eclipse/jetty/util/security/CertificateValidator.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/util/security/CertificateValidator.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,343 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util.security; + +import java.security.GeneralSecurityException; +import java.security.InvalidParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Security; +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 java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * Convenience class to handle validation of certificates, aliases and keystores + * + * Allows specifying Certificate Revocation List (CRL), as well as enabling + * CRL Distribution Points Protocol (CRLDP) certificate extension support, + * and also enabling On-Line Certificate Status Protocol (OCSP) support. + * + * IMPORTANT: at least one of the above mechanisms *MUST* be configured and + * operational, otherwise certificate validation *WILL FAIL* unconditionally. + */ +public class CertificateValidator +{ + private static final Logger LOG = Log.getLogger(CertificateValidator.class); + private static AtomicLong __aliasCount = new AtomicLong(); + + private KeyStore _trustStore; + private Collection<? extends CRL> _crls; + + /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */ + private int _maxCertPathLength = -1; + /** CRL Distribution Points (CRLDP) support */ + private boolean _enableCRLDP = false; + /** On-Line Certificate Status Protocol (OCSP) support */ + private boolean _enableOCSP = false; + /** Location of OCSP Responder */ + private String _ocspResponderURL; + + /** + * creates an instance of the certificate validator + * + * @param trustStore + * @param crls + */ + public CertificateValidator(KeyStore trustStore, Collection<? extends CRL> crls) + { + if (trustStore == null) + { + throw new InvalidParameterException("TrustStore must be specified for CertificateValidator."); + } + + _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("Unable to retrieve aliases from keystore", kse); + } + } + + + /** + * validates a specific alias inside of the keystore being passed in + * + * @param keyStore + * @param keyAlias + * @return the keyAlias if valid + * @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 kse) + { + LOG.debug(kse); + throw new CertificateException("Unable to validate certificate" + + " for alias [" + keyAlias + "]: " + kse.getMessage(), kse); + } + 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 + { + Certificate[] certChain = null; + + if (cert != null && cert instanceof X509Certificate) + { + ((X509Certificate)cert).checkValidity(); + + String certAlias = null; + try + { + if (keyStore == null) + { + throw new InvalidParameterException("Keystore cannot be null"); + } + + certAlias = keyStore.getCertificateAlias((X509Certificate)cert); + if (certAlias == null) + { + certAlias = "JETTY" + String.format("%016X",__aliasCount.incrementAndGet()); + keyStore.setCertificateEntry(certAlias, cert); + } + + certChain = keyStore.getCertificateChain(certAlias); + if (certChain == null || certChain.length == 0) + { + throw new IllegalStateException("Unable to retrieve certificate chain"); + } + } + catch (KeyStoreException kse) + { + LOG.debug(kse); + throw new CertificateException("Unable to validate certificate" + + (certAlias == null ? "":" for alias [" +certAlias + "]") + ": " + kse.getMessage(), kse); + } + + validate(certChain); + } + } + + public void validate(Certificate[] certChain) throws CertificateException + { + try + { + ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); + for (Certificate item : certChain) + { + if (item == null) + continue; + + if (!(item instanceof X509Certificate)) + { + throw new IllegalStateException("Invalid certificate type in chain"); + } + + certList.add((X509Certificate)item); + } + + if (certList.isEmpty()) + { + throw new IllegalStateException("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 maximum certification path length + pbParams.setMaxPathLength(_maxCertPathLength); + + // Enable revocation checking + pbParams.setRevocationEnabled(true); + + // Set static Certificate Revocation List + if (_crls != null && !_crls.isEmpty()) + { + pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls))); + } + + // Enable On-Line Certificate Status Protocol (OCSP) support + if (_enableOCSP) + { + Security.setProperty("ocsp.enable","true"); + } + // Enable Certificate Revocation List Distribution Points (CRLDP) support + if (_enableCRLDP) + { + System.setProperty("com.sun.security.enableCRLDP","true"); + } + + // Build certification path + CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams); + + // Validate certification path + CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams); + } + catch (GeneralSecurityException gse) + { + LOG.debug(gse); + throw new CertificateException("Unable to validate certificate: " + gse.getMessage(), gse); + } + } + + public KeyStore getTrustStore() + { + return _trustStore; + } + + public Collection<? extends CRL> getCrls() + { + return _crls; + } + + /** + * @return Maximum number of intermediate certificates in + * the certification path (-1 for unlimited) + */ + public int getMaxCertPathLength() + { + return _maxCertPathLength; + } + + /* ------------------------------------------------------------ */ + /** + * @param maxCertPathLength + * maximum number of intermediate certificates in + * the certification path (-1 for unlimited) + */ + public void setMaxCertPathLength(int maxCertPathLength) + { + _maxCertPathLength = maxCertPathLength; + } + + /* ------------------------------------------------------------ */ + /** + * @return true if CRL Distribution Points support is enabled + */ + public boolean isEnableCRLDP() + { + return _enableCRLDP; + } + + /* ------------------------------------------------------------ */ + /** Enables CRL Distribution Points Support + * @param enableCRLDP true - turn on, false - turns off + */ + public void setEnableCRLDP(boolean enableCRLDP) + { + _enableCRLDP = enableCRLDP; + } + + /* ------------------------------------------------------------ */ + /** + * @return true if On-Line Certificate Status Protocol support is enabled + */ + public boolean isEnableOCSP() + { + return _enableOCSP; + } + + /* ------------------------------------------------------------ */ + /** Enables On-Line Certificate Status Protocol support + * @param enableOCSP true - turn on, false - turn off + */ + public void setEnableOCSP(boolean enableOCSP) + { + _enableOCSP = enableOCSP; + } + + /* ------------------------------------------------------------ */ + /** + * @return Location of the OCSP Responder + */ + public String getOcspResponderURL() + { + return _ocspResponderURL; + } + + /* ------------------------------------------------------------ */ + /** Set the location of the OCSP Responder. + * @param ocspResponderURL location of the OCSP Responder + */ + public void setOcspResponderURL(String ocspResponderURL) + { + _ocspResponderURL = ocspResponderURL; + } +}