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

org.apache.commons.ssl.TrustMaterial Maven / Gradle / Ivy

The newest version!
/*
 * $HeadURL: file:///opt/dev/not-yet-commons-ssl-SVN-repo/tags/commons-ssl-0.3.17/src/java/org/apache/commons/ssl/TrustMaterial.java $
 * $Revision: 171 $
 * $Date: 2014-05-09 08:15:26 -0700 (Fri, 09 May 2014) $
 *
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * .
 *
 *
 * ----------------------------------------------------------------------
 *
 * This file has been modified as part of the Not-Going-To-Be-Commons-SSL
 * project. The following modifications have been made:
 *
 *     Replacing direct printStackTrace calls with Logger calls.
 *
 * These modifications are Copyright (c) 2018 Nick Rupley and licensed
 * under the Apache License, Version 2.0.
 */

package org.apache.commons.ssl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Credit Union Central of British Columbia
 * @author www.cucbc.com
 * @author [email protected]
 * @since 27-Feb-2006
 */
public class TrustMaterial extends TrustChain {

    private static final Log logger = LogFactory.getLog(TrustMaterial.class);

    final static int SIMPLE_TRUST_TYPE_TRUST_ALL = 1;
    final static int SIMPLE_TRUST_TYPE_TRUST_THIS_JVM = 2;

    /**
     * Might be null if "$JAVA_HOME/jre/lib/security/cacerts" doesn't exist.
     */
    public final static TrustMaterial CACERTS;

    /**
     * Might be null if "$JAVA_HOME/jre/lib/security/jssecacerts" doesn't exist.
     */
    public final static TrustMaterial JSSE_CACERTS;

    /**
     * Should never be null (unless both CACERTS and JSSE_CACERTS are not
     * present???).  Is either CACERTS or JSSE_CACERTS.  Priority given to
     * JSSE_CACERTS, but 99.9% of the time it's CACERTS, since JSSE_CACERTS
     * is almost never present.
     */
    public final static TrustMaterial DEFAULT;

    /**
     * System property to specify a password used for opening trust stores for CACERTS and
     * JSSE_CACERTS.
     */
    public static final String TRUST_STORE_PASSWORD_PROPERTY = "org.apache.commons.ssl.trustStorePassword";

    static {
        JavaImpl.load();
        String javaHome = System.getProperty("java.home");
        String pathToCacerts = javaHome + "/lib/security/cacerts";
        String pathToJSSECacerts = javaHome + "/lib/security/jssecacerts";
        char [] trustStorePassword = getTrustStorePassword();
        CACERTS = loadCerts(pathToCacerts, trustStorePassword);
        JSSE_CACERTS = loadCerts(pathToJSSECacerts, trustStorePassword);
        if (JSSE_CACERTS != null) {
            DEFAULT = JSSE_CACERTS;
        } else {
            DEFAULT = CACERTS;
        }
    }

    /**
     * Load certificates from trust store.
     * @param pathToCerts Path to trust store.
     * @param trustStorePassword Password of the keystore or null.
     * @return trust material or null, if the certificates could not be loaded.
     */
    static TrustMaterial loadCerts(String pathToCerts, char[] trustStorePassword) {
        TrustMaterial cacerts = null;
        try {
            File f = new File(pathToCerts);
            if (f.exists()) {
                cacerts = new TrustMaterial(pathToCerts, trustStorePassword);
            }
        }
        catch (Exception e) {
            logger.warn(e);
        }
        return cacerts;
    }

    /**
     * Get trust store password from system property {@value #TRUST_STORE_PASSWORD_PROPERTY}
     * if set.
     * @return a password set via the system properties or null if no password is specified.
     */
    static char[] getTrustStorePassword() {
        String trustStorePassword = System.getProperty(TRUST_STORE_PASSWORD_PROPERTY);
        if (trustStorePassword != null) {
            return trustStorePassword.toCharArray();
        }
        return null;
    }

    public final static TrustMaterial TRUST_ALL =
        new TrustMaterial(SIMPLE_TRUST_TYPE_TRUST_ALL);

    public final static TrustMaterial TRUST_THIS_JVM =
        new TrustMaterial(SIMPLE_TRUST_TYPE_TRUST_THIS_JVM);

    public final int simpleTrustType;
    private final KeyStore jks;

    private TrustMaterial(int simpleTrustType) {
        this(null, simpleTrustType);
    }

    TrustMaterial(KeyStore jks, int simpleTrustType) {
        if (jks == null && simpleTrustType != 0) {
            // Just use CACERTS as a place holder, since Java 5 and 6 seem to get
            // upset when we hand SSLContext null TrustManagers.  See
            // Java14.initSSL(), which despite its name, is also used
            // with Java5 and Java6.
            this.jks = CACERTS != null ? CACERTS.jks : JSSE_CACERTS.jks;
        } else {
            this.jks = jks;
        }
        addTrustMaterial(this);
        this.simpleTrustType = simpleTrustType;
    }

    public TrustMaterial(Collection x509Certs)
        throws GeneralSecurityException, IOException {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        loadCerts(ks, x509Certs);
        this.jks = ks;
        addTrustMaterial(this);

        // We're not a simple trust type, so set value to 0.
        // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types.
        this.simpleTrustType = 0;
    }

    public TrustMaterial(X509Certificate x509Cert)
        throws GeneralSecurityException, IOException {
        this(Collections.singleton(x509Cert));
    }

    public TrustMaterial(X509Certificate[] x509Certs)
        throws GeneralSecurityException, IOException {
        this(Arrays.asList(x509Certs));
    }

    public TrustMaterial(byte[] pemBase64)
        throws GeneralSecurityException, IOException {
        this(pemBase64, null);
    }

    public TrustMaterial(InputStream pemBase64)
        throws GeneralSecurityException, IOException {
        this(Util.streamToBytes(pemBase64));
    }

    public TrustMaterial(String pathToPemFile)
        throws GeneralSecurityException, IOException {
        this(new FileInputStream(pathToPemFile));
    }

    public TrustMaterial(File pemFile)
        throws GeneralSecurityException, IOException {
        this(new FileInputStream(pemFile));
    }

    public TrustMaterial(URL urlToPemFile)
        throws GeneralSecurityException, IOException {
        this(urlToPemFile.openStream());
    }

    public TrustMaterial(String pathToJksFile, char[] password)
        throws GeneralSecurityException, IOException {
        this(new File(pathToJksFile), password);
    }

    public TrustMaterial(File jksFile, char[] password)
        throws GeneralSecurityException, IOException {
        this(new FileInputStream(jksFile), password);
    }

    public TrustMaterial(URL urlToJKS, char[] password)
        throws GeneralSecurityException, IOException {
        this(urlToJKS.openStream(), password);
    }

    public TrustMaterial(InputStream jks, char[] password)
        throws GeneralSecurityException, IOException {
        this(Util.streamToBytes(jks), password);
    }

    public TrustMaterial(byte[] jks, char[] password)
        throws GeneralSecurityException, IOException {

        KeyStoreBuilder.BuildResult br;
        br = KeyStoreBuilder.parse(jks, password, null, true);
        if (br.jks != null) {
            // If we've been given a keystore, just use that.
            this.jks = br.jks;
        } else {
            // Otherwise we need to build a keystore from what we were given.
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            if (br.chains != null && !br.chains.isEmpty()) {
                Certificate[] c = (Certificate[]) br.chains.get(0);
                if (c.length > 0) {
                    ks.load(null, password);
                    loadCerts(ks, Arrays.asList(c));
                }
            }
            this.jks = ks;
        }

        // Should validate our keystore to make sure it has at least ONE
        // certificate entry:
        KeyStore ks = this.jks;
        boolean hasCertificates = false;
        Enumeration en = ks.aliases();
        while (en.hasMoreElements()) {
            String alias = (String) en.nextElement();
            if (ks.isCertificateEntry(alias)) {
                hasCertificates = true;
                break;
            }
        }
        if (!hasCertificates) {
            throw new KeyStoreException("TrustMaterial couldn't load any certificates to trust!");
        }

        addTrustMaterial(this);

        // We're not a simple trust type, so set value to 0.
        // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types.
        this.simpleTrustType = 0;
    }

    public KeyStore getKeyStore() {
        return jks;
    }

    private static void loadCerts(KeyStore ks, Collection certs)
        throws KeyStoreException {
        Iterator it = certs.iterator();
        int count = 0;
        while (it.hasNext()) {
            X509Certificate cert = (X509Certificate) it.next();

            // I could be fancy and parse out the CN field from the
            // certificate's subject, but these names don't actually matter
            // at all - I think they just have to be unique.
            String cn = Certificates.getCN(cert);
            String alias = cn + "_" + count;
            ks.setCertificateEntry(alias, cert);
            count++;
        }
    }

    protected boolean containsTrustAll() {
        boolean yes = this.simpleTrustType == SIMPLE_TRUST_TYPE_TRUST_ALL;
        if ( !yes ) {
            yes = super.containsTrustAll();
        }
        return yes;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy