All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.globus.gsi.trustmanager.TrustedCertPathFinder Maven / Gradle / Ivy

/*
 * Copyright 1999-2010 University of Chicago
 *
 * Licensed 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.globus.gsi.trustmanager;

import org.globus.gsi.util.CertificateUtil;
import org.globus.gsi.util.KeyStoreUtil;

import java.util.Iterator;

import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Created by IntelliJ IDEA.
 * User: turtlebender
 * Date: Jan 20, 2010
 * Time: 4:51:38 PM
 * To change this template use File | Settings | File Templates.
 */
public final class TrustedCertPathFinder {
    private static Log logger = LogFactory.getLog(TrustedCertPathFinder.class.getCanonicalName());

    private TrustedCertPathFinder() {
        //this should not be instantiated.
    }

    private static CertPath isTrustedCert(KeyStore keyStore, X509Certificate x509Certificate, List trustedCertPath) throws CertPathValidatorException {
        X509CertSelector certSelector = new X509CertSelector();
        certSelector.setCertificate(x509Certificate);
        Collection caCerts;
        try {
            caCerts = KeyStoreUtil.getTrustedCertificates(keyStore, certSelector);
        } catch (KeyStoreException e) {
            throw new CertPathValidatorException(
                    "Error accessing trusted certificate store", e);
        }
        if ((caCerts.size() > 0)&&(x509Certificate.getBasicConstraints() != -1)) {

            trustedCertPath.add(x509Certificate);
            // JGLOBUS-92
            try {
                CertificateFactory certFac = CertificateFactory.getInstance("X.509");
                return certFac.generateCertPath(trustedCertPath);
            } catch (CertificateException e) {
                throw new CertPathValidatorException(
                        "Error generating trusted certificate path", e);
            }
        }
        return null;
    }

    /**
     * Method that validates the provided cert path to find a trusted certificate in the certificate store.
     * 

* For each certificate i in certPath, it is expected that the i+1 certificate is the issuer of the certificate * path. See CertPath. *

* For each certificate i in certpath, validate signature of certificate i get issuer of certificate i get * certificate i+i ensure that the certificate i+1 is issuer of certificate i If not, throw an exception for * illegal argument validate signature of i+1 Throw exception if it does not validate check if i+1 is a trusted * certificate in the trust store. If so return certpath until i+1 If not, continue; If all certificates in the * certpath have been checked and none exisits in trust store, check if trust store has certificate of issuer of * last certificate in CertPath. If so, return certPath + trusted certificate from trust store If not, throw * an exception for lack of valid trust root. * * @param keyStore The key store containing CA trust root certificates * @param certPath The certpath from which to extract a valid cert path to a trusted certificate. * @return The valid CertPath. * @throws CertPathValidatorException If the CertPath is invalid. */ public static CertPath findTrustedCertPath(KeyStore keyStore, CertPath certPath) throws CertPathValidatorException { // This will be the cert path to return List trustedCertPath = new ArrayList(); // This is the certs to validate List certs = certPath.getCertificates(); X509Certificate x509Certificate; int index = 0; int certsSize = certs.size(); Certificate certificate = certs.get(index); if (!(certificate instanceof X509Certificate)) { throw new CertPathValidatorException("Certificate of type " + X509Certificate.class.getName() + " required"); } x509Certificate = (X509Certificate) certificate; while (index < certsSize) { CertPath finalCertPath = isTrustedCert(keyStore, x509Certificate, trustedCertPath); if (finalCertPath != null) { return finalCertPath; } if (index + 1 >= certsSize) { break; } index++; Certificate issuerCertificate = certs.get(index); x509Certificate = checkCertificate(trustedCertPath, x509Certificate, issuerCertificate); } X509CertSelector selector = new X509CertSelector(); selector.setSubject(x509Certificate.getIssuerX500Principal()); Collection caCerts; try { caCerts = KeyStoreUtil.getTrustedCertificates(keyStore, selector); } catch (KeyStoreException e) { throw new CertPathValidatorException(e); } if (caCerts.size() < 1) { throw new CertPathValidatorException("No trusted path can be constructed"); } boolean foundTrustRoot = false; for (Certificate caCert : caCerts) { if (! (caCert instanceof X509Certificate)) { logger.warn("Skipped a certificate: not an X509Certificate"); continue; } try { trustedCertPath.add(checkCertificate(trustedCertPath, x509Certificate, caCert)); // currently the caCert self-signature is not checked // to be consistent with the isTrustedCert() method foundTrustRoot = true; // we found a CA cert that signed the certificate // so we don't need to check any more break; } catch (CertPathValidatorException e) { // fine, just move on to check the next potential CA cert // after the loop we'll check whether any were successful logger.warn("Failed to validate signature of certificate with " + "subject DN '" + x509Certificate.getSubjectDN() + "' against a CA certificate with issuer DN '" + ((X509Certificate)caCert).getSubjectDN() + "'"); } } if (! foundTrustRoot) { throw new CertPathValidatorException( "No trusted path can be constructed"); } try { CertificateFactory certFac = CertificateFactory.getInstance("X.509"); return certFac.generateCertPath(trustedCertPath); } catch (CertificateException e) { throw new CertPathValidatorException("Error generating trusted certificate path", e); } } private static X509Certificate checkCertificate(List trustedCertPath, X509Certificate x509Certificate, Certificate issuerCertificate) throws CertPathValidatorException { X509Certificate x509IssuerCertificate = (X509Certificate) issuerCertificate; // check that the next one is indeed issuer, normalizing to Globus DN format String issuerDN = CertificateUtil.toGlobusID( x509Certificate.getIssuerX500Principal()); String issuerCertDN = CertificateUtil.toGlobusID( x509IssuerCertificate.getSubjectX500Principal()); if (!(issuerDN.equals(issuerCertDN))) { throw new IllegalArgumentException("Incorrect certificate path, certificate in chain can only " + "be issuer of previous certificate"); } // validate integrity of signature PublicKey publicKey = x509IssuerCertificate.getPublicKey(); try { x509Certificate.verify(publicKey); } catch (CertificateException e) { throw new CertPathValidatorException( "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e); } catch (NoSuchAlgorithmException e) { throw new CertPathValidatorException( "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e); } catch (InvalidKeyException e) { throw new CertPathValidatorException( "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e); } catch (NoSuchProviderException e) { throw new CertPathValidatorException( "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e); } catch (SignatureException e) { throw new CertPathValidatorException( "Signature validation on the certificate " + x509Certificate.getSubjectDN(), e); } trustedCertPath.add(x509Certificate); return x509IssuerCertificate; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy