Skip to content
CertificateUtil.java 9.56 KiB
Newer Older
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
package dk.gov.oiosi.security.oces;

import dk.gov.oiosi.common.OutVariable;
import dk.gov.oiosi.common.cache.ICache;
import dk.gov.oiosi.configuration.CacheFactory;
import dk.gov.oiosi.security.CertificateIssuerSubject;
import dk.gov.oiosi.security.CertificateSubject;
dlk-truelink's avatar
dlk-truelink committed
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.jce.provider.AnnotatedException;
import org.bouncycastle.x509.extension.X509ExtensionUtil;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;

Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
/**
 * @since OIORASP 1.3.0
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
 */
public class CertificateUtil {
    public CertificateUtil() {
    }
    public List<URL> getOcspUrls(X509Certificate cert) throws Exception {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
        List<URL> urls = new LinkedList<URL>();

        AuthorityInformationAccess authInfoAccess = null;
        try {
            ASN1Primitive auth_info_acc = getExtensionValue(cert, Extension.authorityInfoAccess.getId());
            if (auth_info_acc != null) {
                authInfoAccess = AuthorityInformationAccess.getInstance(auth_info_acc);
        } catch (AnnotatedException ae) {
            //throw new  Exception();
            //ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlAuthInfoAccError");
            //addError(msg,index);
        }
        if (authInfoAccess != null) {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
            AccessDescription[] ads = authInfoAccess.getAccessDescriptions();
            for (AccessDescription ad : ads) {
                if (ad.getAccessMethod().equals(AccessDescription.id_ad_ocsp)) {
                    GeneralName name = ad.getAccessLocation();
                    if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
                        String url = ((DERIA5String) name.getName()).getString();
                        urls.add(new URL(url));
                    }
                }
            }
        }

        return urls;
    }

    public List<URL> getIssuerUrls(X509Certificate cert) throws Exception {
        List<URL> urls = new LinkedList<URL>();

        AuthorityInformationAccess authInfoAccess = null;
        try {
            ASN1Primitive auth_info_acc = getExtensionValue(cert, Extension.authorityInfoAccess.getId());
            if (auth_info_acc != null) {
                authInfoAccess = AuthorityInformationAccess.getInstance(auth_info_acc);
            }
        } catch (AnnotatedException ae) {
            //throw new  Exception();
            //ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlAuthInfoAccError");
            //addError(msg,index);
        }

        if (authInfoAccess != null) {
            AccessDescription[] ads = authInfoAccess.getAccessDescriptions();
            for (AccessDescription ad : ads) {
                if (ad.getAccessMethod().equals(AccessDescription.id_ad_caIssuers)) {
                    GeneralName name = ad.getAccessLocation();
                    if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
                        String url = ((DERIA5String) name.getName()).getString();
                        urls.add(new URL(url));
                    }
                }
            }
        }

        return urls;
    }

Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
    public List<URL> getCrlURLs(X509Certificate cert) {
        List<URL> urls = new LinkedList<URL>();

        // Retrieves the raw ASN1 data of the CRL Dist Points X509 extension
        byte[] cdp = cert.getExtensionValue(X509Extension.cRLDistributionPoints.getId());
        if (cdp != null) {
            try {
                // Wraps the raw data in a container class
                CRLDistPoint crldp = CRLDistPoint.getInstance(X509ExtensionUtil.fromExtensionValue(cdp));

                DistributionPoint[] distPoints = crldp.getDistributionPoints();

                for (DistributionPoint dp : distPoints) {
                    // Only use the "General name" data in the distribution point entry.
                    GeneralNames gns = (GeneralNames) dp.getDistributionPoint().getName();
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
                    DERIA5String uri;
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
                    for (GeneralName name : gns.getNames()) {
                        // Only retrieve URLs
                        if (name.getTagNo() == GeneralName.uniformResourceIdentifier) {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
                            uri = (DERIA5String) name.getName();
                            urls.add(new URL(uri.getString()));
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
                        }
                    }
                }
            } catch (IOException e) {
                // Could not retrieve the CRLDistPoint object. Just return empty url list.
                /*
                     * Hmm... So there is no possibility to see what happened when certificate is checked against CRL - such error is just hidden.
                     *
                     * TODO DLK: Think at least about logging such exception, throwing excpetion is preferred.
                     */
     * Get the url to the issueing certificate
     * @param cert A Oces2 certificate
     * @return The url for the issueing cetificate, if exist
     */
    public URL getIssuerUrl(X509Certificate cert) {
        URL url = null;
        try {
            List<URL> list = this.getIssuerUrls(cert);
            if(list.size() == 1){
                // the url must be located on the 1. index
                url = list.get(0);
            }
        }
        catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        return url;
    }

     /**
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
     * Extract the value of the given extension, if it exists.
     *
     * @param ext The extension object.
     * @param oid The object identifier to obtain.
     * @throws AnnotatedException if the extension cannot be read.
     */
    protected static ASN1Primitive getExtensionValue(
            java.security.cert.X509Extension ext,
            String oid)
            throws Exception {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
        byte[] bytes = ext.getExtensionValue(oid);
        if (bytes == null) {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
            return null;
        }

        return getObject(oid, bytes);
    }

    private static ASN1Primitive getObject(
            String oid,
            byte[] ext)
            throws Exception {
        try {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
            ASN1InputStream aIn = new ASN1InputStream(ext);
            ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed

            aIn = new ASN1InputStream(octs.getOctets());
            return aIn.readObject();
        } catch (Exception e) {
Jacob Lund Mogensen's avatar
Jacob Lund Mogensen committed
            throw new Exception("exception processing extension " + oid, e);
        }
    }
    public X509Certificate downloadIssuerCert(X509Certificate certificate)
    {
        ICache<CertificateSubject, X509Certificate> cache = CacheFactory.getInstance().getCertificateCache();
        CertificateIssuerSubject certificateIssuerSubject = new CertificateIssuerSubject(certificate);
dlk-truelink's avatar
 
dlk-truelink committed
		/*
		 * TODO: Shouldn't this variable be initialized?
		 * 
		 * You will get NullPointerException if cache.tryGetValue returns
		 * true... Actually, if cache contains such certificate, you will get it
		 * inside cache implementation...
		 */
        OutVariable<X509Certificate> issuerCertificateOutVariable = null;
        X509Certificate downloadedX509Certificate = null;

        if(cache.tryGetValue(certificateIssuerSubject, issuerCertificateOutVariable)){
            // cartificate already retrived - using the cached version
            downloadedX509Certificate = issuerCertificateOutVariable.getVariable();
        }
        else
        {
            // download the certificate, and add it to the cache
            InputStream inputStream = null;
            CertificateUtil certificateUtil = new CertificateUtil();
            URL issuerCertificateURL = certificateUtil.getIssuerUrl(certificate);

            if(issuerCertificateURL != null){
                // url is not null - try to download the certificate
                try {
                    inputStream = issuerCertificateURL.openStream();
                    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                    downloadedX509Certificate = (X509Certificate)certificateFactory.generateCertificate(inputStream);
                    cache.add(certificateIssuerSubject, downloadedX509Certificate);
                }
                catch (IOException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
                catch (CertificateException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
                finally {
                    // remember to close the inputstream
                    if(inputStream != null) {
                        try {
                            inputStream.close();
                        }
                        catch (IOException e) {
                            // intentionel left empty
                        }

                    }
                }
            }
        }

        return downloadedX509Certificate;
    }