From 37b8ab59682dd846594e3252982c33a727d4ef9f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 13 Oct 2014 15:52:09 +0200 Subject: [PATCH] IDEA-130604 (include system certificates into EA reporter trust manager) Allows to post exceptions via corporate HTTPS-intercepting proxies. --- .../intellij/errorreport/itn/ITNProxy.java | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java index 4339b36cbf22..ad030b0c9e7f 100644 --- a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java +++ b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java @@ -49,9 +49,11 @@ import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Calendar; +import java.util.List; import java.util.Map; import java.util.Set; @@ -216,7 +218,7 @@ public class ITNProxy { HttpsURLConnection connection = (HttpsURLConnection)url.openConnection(); connection.setSSLSocketFactory(ourSslContext.getSocketFactory()); - if (!SystemInfo.isJavaVersionAtLeast("1.7") || !SystemProperties.getBooleanProperty("jsse.enableSNIExtension", true)) { + if (!(SystemInfo.isJavaVersionAtLeast("1.7") && SystemProperties.getBooleanProperty("jsse.enableSNIExtension", true))) { connection.setHostnameVerifier(new EaHostnameVerifier(url.getHost(), "ftp.intellij.net")); } @@ -243,10 +245,15 @@ public class ITNProxy { KeyStore ks = KeyStore.getInstance(CertificateUtil.JKS); ks.load(null, null); ks.setCertificateEntry("JetBrains CA", ca); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(CertificateUtil.X509); - tmf.init(ks); + TrustManagerFactory jbTmf = TrustManagerFactory.getInstance(CertificateUtil.X509); + jbTmf.init(ks); + + TrustManagerFactory sysTmf = TrustManagerFactory.getInstance(CertificateUtil.X509); + sysTmf.init((KeyStore)null); + SSLContext ctx = SSLContext.getInstance("TLS"); - ctx.init(null, tmf.getTrustManagers(), null); + TrustManager composite = new CompositeX509TrustManager(jbTmf.getTrustManagers(), sysTmf.getTrustManagers()); + ctx.init(null, new TrustManager[]{composite}, null); return ctx; } @@ -274,6 +281,46 @@ public class ITNProxy { } } + private static class CompositeX509TrustManager implements X509TrustManager { + private final List myManagers = ContainerUtil.newArrayList(); + + public CompositeX509TrustManager(TrustManager[]... managerSets) { + for (TrustManager[] set : managerSets) { + for (TrustManager manager : set) { + if (manager instanceof X509TrustManager) { + myManagers.add((X509TrustManager)manager); + } + } + } + } + + @Override + public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] certificates, String s) throws CertificateException { + for (X509TrustManager manager : myManagers) { + try { + manager.checkServerTrusted(certificates, s); + return; + } + catch (CertificateException ignored) { } + } + throw new CertificateException("No trusting managers found for " + s); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + List result = ContainerUtil.newArrayList(); + for (X509TrustManager manager : myManagers) { + ContainerUtil.addAll(result, manager.getAcceptedIssuers()); + } + return result.toArray(new X509Certificate[result.size()]); + } + } + @SuppressWarnings("SpellCheckingInspection") private static final String JB_CA_CERT = "-----BEGIN CERTIFICATE-----\n" + "MIIFvjCCA6agAwIBAgIQMYHnK1dpIZVCoitWqBwhXjANBgkqhkiG9w0BAQsFADBn\n" +