package com.intrbiz.bergamot.crypto.util; import java.io.InputStream; import java.net.Socket; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedTrustManager; import javax.net.ssl.X509TrustManager; import org.apache.log4j.Logger; /** * A customised trust manager which by default uses the Mozilla trust * store and permits the suppression of invalid certificate errors */ public class BergamotTrustManager extends X509ExtendedTrustManager implements X509TrustManager { private static final X509ExtendedTrustManager MOZILLA_TRUST_STORE = loadMozillaTrustStore(); public static final X509ExtendedTrustManager getMozillaTrustStore() { return MOZILLA_TRUST_STORE; } /* * Load the Mozilla trust store that we bundle */ private static final X509ExtendedTrustManager loadMozillaTrustStore() { try { InputStream trustStoreStream = BergamotTrustManager.class.getResourceAsStream("trust_store.jks"); // Create our trust key store KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(trustStoreStream, "bergamot".toCharArray()); // Create the trust manager TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustFactory.init(trustStore); // fecking obscured types are not helpful TrustManager[] managers = trustFactory.getTrustManagers(); return (X509ExtendedTrustManager) managers[0]; } catch (Exception e) { throw new RuntimeException("Failed to load bundled Mozilla trust store!"); } } private Logger logger = Logger.getLogger(BergamotTrustManager.class); private final X509ExtendedTrustManager parent; private final boolean permitInvalid; public BergamotTrustManager(X509ExtendedTrustManager parent, boolean permitInvalid) { super(); this.parent = parent; this.permitInvalid = permitInvalid; } public BergamotTrustManager(boolean permitInvalid) { this(getMozillaTrustStore(), permitInvalid); } public BergamotTrustManager() { this(false); } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { try { this.parent.checkClientTrusted(certs, authType); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public void checkClientTrusted(X509Certificate[] certs, String authType, Socket socket) throws CertificateException { try { this.parent.checkClientTrusted(certs, authType, socket); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public void checkClientTrusted(X509Certificate[] certs, String authType, SSLEngine engine) throws CertificateException { try { this.parent.checkClientTrusted(certs, authType, engine); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { try { this.parent.checkServerTrusted(certs, authType); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public void checkServerTrusted(X509Certificate[] certs, String authType, Socket socket) throws CertificateException { try { this.parent.checkServerTrusted(certs, authType, socket); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public void checkServerTrusted(X509Certificate[] certs, String authType, SSLEngine engine) throws CertificateException { try { this.parent.checkServerTrusted(certs, authType, engine); } catch (CertificateException ce) { if (this.permitInvalid) logger.warn("Suppressing invalid certificate: " + ce.getMessage()); else throw ce; } } @Override public X509Certificate[] getAcceptedIssuers() { return this.parent == null ? new X509Certificate[0] : this.parent.getAcceptedIssuers(); } }