org.bouncycastle.jsse.provider.ProvTrustManagerFactorySpi Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of impersonator Show documentation
Show all versions of impersonator Show documentation
Spoof TLS/JA3/JA4 and HTTP/2 fingerprints in Java
package org.bouncycastle.jsse.provider;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchProviderException;
import java.security.cert.CertPathParameters;
import java.security.cert.Certificate;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.tls.TlsUtils;
class ProvTrustManagerFactorySpi
extends TrustManagerFactorySpi
{
private static final Logger LOG = Logger.getLogger(ProvTrustManagerFactorySpi.class.getName());
private static final boolean provKeyStoreTypeCompat = PropertyUtils
.getBooleanSecurityProperty("keystore.type.compat", false);
static KeyStore getDefaultTrustStore() throws Exception
{
String defaultType = KeyStore.getDefaultType();
boolean defaultCacertsToJKS = provKeyStoreTypeCompat && "pkcs12".equalsIgnoreCase(defaultType);
String tsPath = null;
char[] tsPassword = null;
String tsPathProp = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStore");
if ("NONE".equals(tsPathProp))
{
// Do not try to load any file
}
else if (null != tsPathProp)
{
if (new File(tsPathProp).exists())
{
tsPath = tsPathProp;
}
}
else
{
String javaHome = PropertyUtils.getStringSystemProperty("java.home");
if (null != javaHome)
{
String jsseCacertsPath = javaHome + "/lib/security/jssecacerts".replace("/", File.separator);
if (new File(jsseCacertsPath).exists())
{
if (defaultCacertsToJKS)
{
defaultType = "jks";
}
tsPath = jsseCacertsPath;
}
else
{
String cacertsPath = javaHome + "/lib/security/cacerts".replace("/", File.separator);
if (new File(cacertsPath).exists())
{
if (defaultCacertsToJKS)
{
defaultType = "jks";
}
tsPath = cacertsPath;
}
}
}
}
KeyStore ks = createTrustStore(defaultType);
String tsPasswordProp = PropertyUtils.getSensitiveStringSystemProperty("javax.net.ssl.trustStorePassword");
if (null != tsPasswordProp)
{
tsPassword = tsPasswordProp.toCharArray();
}
InputStream tsInput = null;
try
{
if (null == tsPath)
{
LOG.config("Initializing default trust store as empty");
}
else
{
LOG.config("Initializing default trust store from path: " + tsPath);
tsInput = new BufferedInputStream(new FileInputStream(tsPath));
}
try
{
ks.load(tsInput, tsPassword);
}
catch (NullPointerException e)
{
// work around for NPE in FIPS KeyStore
ks = KeyStore.getInstance("BCFKS");
ks.load(null, null);
}
}
finally
{
if (null != tsInput)
{
tsInput.close();
}
}
return ks;
}
protected final boolean isInFipsMode;
protected final JcaJceHelper helper;
protected ProvX509TrustManager x509TrustManager;
ProvTrustManagerFactorySpi(boolean isInFipsMode, JcaJceHelper helper)
{
this.isInFipsMode = isInFipsMode;
this.helper = helper;
}
@Override
protected TrustManager[] engineGetTrustManagers()
{
if (null == x509TrustManager)
{
throw new IllegalStateException("TrustManagerFactory not initialized");
}
return new TrustManager[]{ x509TrustManager.getExportX509TrustManager() };
}
@Override
protected void engineInit(KeyStore ks)
throws KeyStoreException
{
if (null == ks)
{
try
{
ks = getDefaultTrustStore();
}
catch (SecurityException e)
{
LOG.log(Level.WARNING, "Skipped default trust store", e);
// Ignore
}
catch (Error e)
{
LOG.log(Level.WARNING, "Skipped default trust store", e);
throw e;
}
catch (RuntimeException e)
{
LOG.log(Level.WARNING, "Skipped default trust store", e);
throw e;
}
catch (Exception e)
{
LOG.log(Level.WARNING, "Skipped default trust store", e);
throw new KeyStoreException("Failed to load default trust store", e);
}
}
Set trustAnchors = getTrustAnchors(ks);
try
{
this.x509TrustManager = new ProvX509TrustManager(isInFipsMode, helper, trustAnchors);
}
catch (InvalidAlgorithmParameterException e)
{
throw new KeyStoreException("Failed to create trust manager", e);
}
}
@Override
protected void engineInit(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException
{
if (spec instanceof CertPathTrustManagerParameters)
{
CertPathParameters certPathParameters = ((CertPathTrustManagerParameters)spec).getParameters();
if (!(certPathParameters instanceof PKIXParameters))
{
throw new InvalidAlgorithmParameterException("parameters must inherit from PKIXParameters");
}
this.x509TrustManager = new ProvX509TrustManager(isInFipsMode, helper, (PKIXParameters)certPathParameters);
}
else if (null == spec)
{
throw new InvalidAlgorithmParameterException("spec cannot be null");
}
else
{
throw new InvalidAlgorithmParameterException("unknown spec: " + spec.getClass().getName());
}
}
private static void collectTrustAnchor(Set trustAnchors, Certificate certificate)
{
if (certificate instanceof X509Certificate)
{
trustAnchors.add(new TrustAnchor((X509Certificate)certificate, null));
}
}
private static KeyStore createTrustStore(String defaultType)
throws NoSuchProviderException, KeyStoreException
{
String tsType = getTrustStoreType(defaultType);
String tsProv = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStoreProvider");
return TlsUtils.isNullOrEmpty(tsProv)
? KeyStore.getInstance(tsType)
: KeyStore.getInstance(tsType, tsProv);
}
private static Set getTrustAnchors(KeyStore trustStore)
throws KeyStoreException
{
if (null == trustStore)
{
return Collections.emptySet();
}
Set trustAnchors = new HashSet();
for (Enumeration en = trustStore.aliases(); en.hasMoreElements();)
{
String alias = (String)en.nextElement();
if (trustStore.isCertificateEntry(alias))
{
collectTrustAnchor(trustAnchors, trustStore.getCertificate(alias));
}
else if (trustStore.isKeyEntry(alias))
{
Certificate[] chain = trustStore.getCertificateChain(alias);
if (null != chain && chain.length > 0)
{
collectTrustAnchor(trustAnchors, chain[0]);
}
}
}
return trustAnchors;
}
private static String getTrustStoreType(String defaultType)
{
String tsType = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStoreType");
return (null == tsType) ? defaultType : tsType;
}
}