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

org.cesecore.util.provider.EkuPKIXCertPathChecker Maven / Gradle / Ivy

/*************************************************************************
 *                                                                       *
 *  CESeCore: CE Security Core                                           *
 *                                                                       *
 *  This software is free software; you can redistribute it and/or       *
 *  modify it under the terms of the GNU Lesser General Public           *
 *  License as published by the Free Software Foundation; either         *
 *  version 2.1 of the License, or any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/
package org.cesecore.util.provider;

import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.bouncycastle.asn1.x509.Extension;
import org.cesecore.util.CertTools;

/**
 * Validate the EKUs of a leaf certificate.
 * 
 * If a EKU extension exists and is marked as critical, this PKIXCertPathChecker will ensure that
 * at least the specified extended key usages are present. Additional EKUs will be ignored as long
 * as the required ones are there. 
 * 
 * @version $Id: EkuPKIXCertPathChecker.java 21415 2015-05-29 14:00:56Z anatom $
 */
public class EkuPKIXCertPathChecker extends PKIXCertPathChecker {
    
    private static final Logger log = Logger.getLogger(EkuPKIXCertPathChecker.class);
    private static final List EMPTY = new ArrayList(0);
    private final List requiredKeyPurposeOids;

    /**
     * Create a new instance that will check a critical EKU of the leaf certificate.
     * 
     * Parameters OIDs could be supplied using org.bouncycastle.asn1.x509.KeyPurposeId.id_kp_*.getId()
     * 
     * @param requiredKeyPurposeOids a list of EKUs that at a minimum must be present if the EKU exists and is critical.
     */
    public EkuPKIXCertPathChecker(final String...requiredKeyPurposeOids) {
        super();
        if (requiredKeyPurposeOids==null) {
            this.requiredKeyPurposeOids = EMPTY;
        } else {
            this.requiredKeyPurposeOids = Arrays.asList(requiredKeyPurposeOids);
        }
    }

    /**
     * Create a new instance that will check a critical EKU of the leaf certificate.
     * 
     * Parameters OIDs could be supplied using org.bouncycastle.asn1.x509.KeyPurposeId.id_kp_*.getId()
     * 
     * @param requiredKeyPurposeOids a list of EKUs that at a minimum must be present if the EKU exists and is critical.
     */
    public EkuPKIXCertPathChecker(final List requiredKeyPurposeOids) {
        super();
        if (requiredKeyPurposeOids==null) {
            this.requiredKeyPurposeOids = EMPTY;
        } else {
            this.requiredKeyPurposeOids = requiredKeyPurposeOids;
        }
    }

    @Override
    public void check(final Certificate cert, final Collection unresolvedCritExts) throws CertPathValidatorException {
        if (!CertTools.isCA(cert) && cert instanceof X509Certificate) {
            final X509Certificate x509Certificate = (X509Certificate) cert;
            try {
                List ekus = x509Certificate.getExtendedKeyUsage();
                if (ekus==null) {
                    ekus = EMPTY;
                }
                if (ekus.containsAll(requiredKeyPurposeOids)) {
                    // All the required EKUs are present, so mark the EKU extension as processed
                    unresolvedCritExts.remove(Extension.extendedKeyUsage.getId());
                } else {
                    final List ekusMissing = new ArrayList(requiredKeyPurposeOids);
                    ekusMissing.removeAll(ekus);
                    if (log.isDebugEnabled()) {
                        log.debug("EKUs in certificate: " +Arrays.toString(ekus.toArray()) + " EKUs required: " +Arrays.toString(requiredKeyPurposeOids.toArray()));
                    }
                    log.info("Validation of certificate with subject " + CertTools.getSubjectDN(cert) + " failed critical EKU validation. The missing EKUs were: " + Arrays.toString(ekusMissing.toArray()));
                    return;
                }
            } catch (CertificateParsingException e) {
                throw new CertPathValidatorException(e);
            }
        }
    }

    @Override
    public Set getSupportedExtensions() {
        return Collections.singleton(Extension.extendedKeyUsage.getId());
    }

    @Override
    public void init(final boolean forward) throws CertPathValidatorException {
        // NOOP: We don't care about the order, we handle EKUs for non-CA certs 
    }

    @Override
    public boolean isForwardCheckingSupported() {
        // We don't care about the order, we handle EKUs for non-CA certs 
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy