org.apache.commons.ssl.TrustMaterial Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of not-going-to-be-commons-ssl Show documentation
Show all versions of not-going-to-be-commons-ssl Show documentation
A Java 9+ compliant fork of Not-Yet-Commons-SSL
/*
* $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.log4j.Logger;
/**
* @author Credit Union Central of British Columbia
* @author www.cucbc.com
* @author [email protected]
* @since 27-Feb-2006
*/
public class TrustMaterial extends TrustChain {
private final static Logger logger = Logger.getLogger(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;
}
}