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

org.cesecore.keybind.impl.AuthenticationKeyBinding Maven / Gradle / Ivy

/*************************************************************************
 *                                                                       *
 *  EJBCA Community: The OpenSource Certificate Authority                *
 *                                                                       *
 *  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.keybind.impl;

import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;

import org.apache.log4j.Logger;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.cesecore.config.AvailableExtendedKeyUsagesConfiguration;
import org.cesecore.config.CesecoreConfiguration;
import org.cesecore.keybind.CertificateImportException;
import org.cesecore.keybind.InternalKeyBindingBase;
import org.cesecore.util.CertTools;
import org.cesecore.util.ui.DynamicUiProperty;

/**
 * Used when this EJBCA instance authenticates to other instances.
 * 
 * @version $Id: AuthenticationKeyBinding.java 26192 2017-08-02 07:59:40Z anatom $
 */
public class AuthenticationKeyBinding extends InternalKeyBindingBase {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger(AuthenticationKeyBinding.class);

    public static final String IMPLEMENTATION_ALIAS = "AuthenticationKeyBinding"; // This should not change, even if we rename the class in EJBCA 5.3+..
    public static final String PROPERTY_PROTOCOL_AND_CIPHER_SUITE = "protocolAndCipherSuite";

    {
        final String[] CIPHER_SUITES_SUBSET = CesecoreConfiguration.getAvailableCipherSuites();
        addProperty(new DynamicUiProperty(PROPERTY_PROTOCOL_AND_CIPHER_SUITE, CIPHER_SUITES_SUBSET[0], Arrays.asList(CIPHER_SUITES_SUBSET)));
    }

    /** @return an array of supported protocols named according to JSSE */
    public String[] getSupportedProtocols() {
        return getSelectedProtocolOrSuite(0);
    }

    /** @return an array of supported cipher suites named according to JSSE */
    public String[] getSupportedCipherTextSuites() {
        return getSelectedProtocolOrSuite(1);
    }

    private String[] getSelectedProtocolOrSuite(final int pos) {
        final String value = (String) getProperty(PROPERTY_PROTOCOL_AND_CIPHER_SUITE).getValue();
        final String[] values = value.split(CesecoreConfiguration.AVAILABLE_CIPHER_SUITES_SPLIT_CHAR);
        if (log.isDebugEnabled() && pos==0) {
            log.debug("Configured cipher suite for this AuthenticationKeyBinding: " + value);
        }
        if (values.length==2) {
            return new String[] { values[pos] };
        }
        return new String[0];
    }

    @Override
    public String getImplementationAlias() {
        return IMPLEMENTATION_ALIAS;
    }

    @Override
    public float getLatestVersion() {
        return serialVersionUID;
    }

    @Override
    public void assertCertificateCompatability(Certificate certificate, final AvailableExtendedKeyUsagesConfiguration ekuConfig) throws CertificateImportException {
        if (!isClientSSLCertificate(certificate, ekuConfig)) {
            throw new CertificateImportException("Not a valid Client SSL authentication certificate.");
        }
    }

    @Override
    protected void upgrade(float latestVersion, float currentVersion) {
        // Nothing to do   
    }

    public static boolean isClientSSLCertificate(Certificate certificate, final AvailableExtendedKeyUsagesConfiguration ekuConfig) {
        if (certificate == null) {
            log.debug("No certificate provided.");
            return false;
        }
        if (!(certificate instanceof X509Certificate)) {
            log.debug("Only X509 supported.");
            return false;
        }
        try {
            final X509Certificate x509Certificate = (X509Certificate) certificate;
            if (log.isDebugEnabled()) {
                log.debug("SubjectDN: " + CertTools.getSubjectDN(x509Certificate) + " IssuerDN: " + CertTools.getIssuerDN(x509Certificate));
            }
            final boolean[] ku = x509Certificate.getKeyUsage();
            if (ku != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Key usages: " + Arrays.toString(ku));
                    log.debug("Key usage (digitalSignature): " + ku[0]);
                    log.debug("Key usage (keyEncipherment): " + ku[2]);
                }
            } else {
                log.debug("No Key Usage to verify.");
                return false;            	
            }
            if (x509Certificate.getExtendedKeyUsage() == null) {
                log.debug("No EKU to verify.");
                return false;
            }
            for (String extendedKeyUsage : x509Certificate.getExtendedKeyUsage()) {
                log.debug("EKU: " + extendedKeyUsage + " (" +
                        ekuConfig.getAllEKUOidsAndNames().get(extendedKeyUsage) + ")");
            }
            if (!x509Certificate.getExtendedKeyUsage().contains(KeyPurposeId.id_kp_clientAuth.getId())) {
                log.debug("Extended Key Usage 1.3.6.1.5.5.7.3.2 (EKU_PKIX_CLIENTAUTH) is required.");
                return false;
            }
            // For TLS _client_ certificates you can actually be without KU completely, but we take the safe route here and require digitalSignature
            // for TLS _server_ certificates also keyEncipherment is required, but not for client (it doesn't hurt it it's there for clients as well though)
            if (!ku[0]) {
                log.debug("Key usage digitalSignature is required.");
                return false;
            }
        } catch (CertificateParsingException e) {
            log.debug(e.getMessage());
            return false;
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy