diff --git a/mockwebserver/src/test/java/okhttp3/mockwebserver/MockWebServerTest.java b/mockwebserver/src/test/java/okhttp3/mockwebserver/MockWebServerTest.java index 72332f89d..cb4577b4f 100644 --- a/mockwebserver/src/test/java/okhttp3/mockwebserver/MockWebServerTest.java +++ b/mockwebserver/src/test/java/okhttp3/mockwebserver/MockWebServerTest.java @@ -530,7 +530,7 @@ public final class MockWebServerTest { .certificateAuthority(0) .build(); HeldCertificate serverCertificate = new HeldCertificate.Builder() - .issuedBy(serverCa) + .signedBy(serverCa) .addSubjectAlternativeName(server.getHostName()) .build(); HandshakeCertificates serverHandshakeCertificates = new HandshakeCertificates.Builder() @@ -543,7 +543,7 @@ public final class MockWebServerTest { server.requestClientAuth(); HeldCertificate clientCertificate = new HeldCertificate.Builder() - .issuedBy(clientCa) + .signedBy(clientCa) .build(); HandshakeCertificates clientHandshakeCertificates = new HandshakeCertificates.Builder() .addTrustedCertificate(serverCa.certificate()) diff --git a/okhttp-tests/src/test/java/okhttp3/CertificateChainCleanerTest.java b/okhttp-tests/src/test/java/okhttp3/CertificateChainCleanerTest.java index 522131200..e61cb9f29 100644 --- a/okhttp-tests/src/test/java/okhttp3/CertificateChainCleanerTest.java +++ b/okhttp-tests/src/test/java/okhttp3/CertificateChainCleanerTest.java @@ -77,11 +77,11 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(certA) + .signedBy(certA) .build(); CertificateChainCleaner cleaner = CertificateChainCleaner.get(root.certificate()); @@ -94,11 +94,11 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(certA) + .signedBy(certA) .build(); CertificateChainCleaner cleaner = CertificateChainCleaner.get(root.certificate()); @@ -112,15 +112,15 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(certA) + .signedBy(certA) .build(); HeldCertificate certC = new HeldCertificate.Builder() .serialNumber(4L) - .issuedBy(certB) + .signedBy(certB) .build(); CertificateChainCleaner cleaner = CertificateChainCleaner.get(root.certificate()); @@ -134,15 +134,15 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(certA) + .signedBy(certA) .build(); HeldCertificate certC = new HeldCertificate.Builder() .serialNumber(4L) - .issuedBy(certB) + .signedBy(certB) .build(); CertificateChainCleaner cleaner = CertificateChainCleaner.get(root.certificate()); @@ -156,11 +156,11 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(certA) + .signedBy(certA) .build(); HeldCertificate certUnnecessary = new HeldCertificate.Builder() .serialNumber(4L) @@ -177,15 +177,15 @@ public final class CertificateChainCleanerTest { .build(); HeldCertificate trusted = new HeldCertificate.Builder() .serialNumber(2L) - .issuedBy(selfSigned) + .signedBy(selfSigned) .build(); HeldCertificate certA = new HeldCertificate.Builder() .serialNumber(3L) - .issuedBy(trusted) + .signedBy(trusted) .build(); HeldCertificate certB = new HeldCertificate.Builder() .serialNumber(4L) - .issuedBy(certA) + .signedBy(certA) .build(); CertificateChainCleaner cleaner = CertificateChainCleaner.get( @@ -203,15 +203,15 @@ public final class CertificateChainCleanerTest { .serialNumber(1L) .build(); HeldCertificate trusted = new HeldCertificate.Builder() - .issuedBy(unknownSigner) + .signedBy(unknownSigner) .serialNumber(2L) .build(); HeldCertificate intermediateCa = new HeldCertificate.Builder() - .issuedBy(trusted) + .signedBy(trusted) .serialNumber(3L) .build(); HeldCertificate certificate = new HeldCertificate.Builder() - .issuedBy(intermediateCa) + .signedBy(intermediateCa) .serialNumber(4L) .build(); @@ -256,7 +256,7 @@ public final class CertificateChainCleanerTest { List result = new ArrayList<>(); for (int i = 1; i <= length; i++) { result.add(0, new HeldCertificate.Builder() - .issuedBy(!result.isEmpty() ? result.get(0) : null) + .signedBy(!result.isEmpty() ? result.get(0) : null) .serialNumber(i) .build()); } diff --git a/okhttp-tests/src/test/java/okhttp3/ConnectionCoalescingTest.java b/okhttp-tests/src/test/java/okhttp3/ConnectionCoalescingTest.java index 3c1a00bef..be741a0b5 100644 --- a/okhttp-tests/src/test/java/okhttp3/ConnectionCoalescingTest.java +++ b/okhttp-tests/src/test/java/okhttp3/ConnectionCoalescingTest.java @@ -56,7 +56,7 @@ public final class ConnectionCoalescingTest { .commonName("root") .build(); certificate = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .serialNumber(2L) .commonName(server.getHostName()) .addSubjectAlternativeName(server.getHostName()) diff --git a/okhttp-tests/src/test/java/okhttp3/internal/tls/CertificatePinnerChainValidationTest.java b/okhttp-tests/src/test/java/okhttp3/internal/tls/CertificatePinnerChainValidationTest.java index d64f609b9..ffb116eea 100644 --- a/okhttp-tests/src/test/java/okhttp3/internal/tls/CertificatePinnerChainValidationTest.java +++ b/okhttp-tests/src/test/java/okhttp3/internal/tls/CertificatePinnerChainValidationTest.java @@ -61,13 +61,13 @@ public final class CertificatePinnerChainValidationTest { .commonName("root") .build(); HeldCertificate intermediateCa = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .certificateAuthority(0) .serialNumber(2L) .commonName("intermediate_ca") .build(); HeldCertificate certificate = new HeldCertificate.Builder() - .issuedBy(intermediateCa) + .signedBy(intermediateCa) .serialNumber(3L) .commonName(server.getHostName()) .build(); @@ -118,13 +118,13 @@ public final class CertificatePinnerChainValidationTest { .commonName("root") .build(); HeldCertificate intermediateCa = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .certificateAuthority(0) .serialNumber(2L) .commonName("intermediate_ca") .build(); HeldCertificate certificate = new HeldCertificate.Builder() - .issuedBy(intermediateCa) + .signedBy(intermediateCa) .serialNumber(3L) .commonName(server.getHostName()) .build(); @@ -184,13 +184,13 @@ public final class CertificatePinnerChainValidationTest { // SSL context for an HTTP client under attack. It includes the trusted CA and a pinned // certificate. HeldCertificate goodIntermediateCa = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .certificateAuthority(0) .serialNumber(2L) .commonName("good_intermediate_ca") .build(); HeldCertificate goodCertificate = new HeldCertificate.Builder() - .issuedBy(goodIntermediateCa) + .signedBy(goodIntermediateCa) .serialNumber(3L) .commonName(server.getHostName()) .build(); @@ -212,14 +212,14 @@ public final class CertificatePinnerChainValidationTest { // trusted good certificate above. The attack is that by including the good certificate in the // chain, we may trick the certificate pinner into accepting the rouge certificate. HeldCertificate compromisedIntermediateCa = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .certificateAuthority(0) .serialNumber(4L) .commonName("bad_intermediate_ca") .build(); HeldCertificate rogueCertificate = new HeldCertificate.Builder() .serialNumber(5L) - .issuedBy(compromisedIntermediateCa) + .signedBy(compromisedIntermediateCa) .commonName(server.getHostName()) .build(); @@ -264,7 +264,7 @@ public final class CertificatePinnerChainValidationTest { // SSL context for an HTTP client under attack. It includes the trusted CA and a pinned // certificate. HeldCertificate goodIntermediateCa = new HeldCertificate.Builder() - .issuedBy(rootCa) + .signedBy(rootCa) .certificateAuthority(0) .serialNumber(3L) .commonName("intermediate_ca") @@ -288,14 +288,14 @@ public final class CertificatePinnerChainValidationTest { // serves the good CAs certificate in the chain, which means the certificate pinner sees a // different set of certificates than the SSL verifier. HeldCertificate compromisedIntermediateCa = new HeldCertificate.Builder() - .issuedBy(compromisedRootCa) + .signedBy(compromisedRootCa) .certificateAuthority(0) .serialNumber(4L) .commonName("intermediate_ca") .build(); HeldCertificate rogueCertificate = new HeldCertificate.Builder() .serialNumber(5L) - .issuedBy(compromisedIntermediateCa) + .signedBy(compromisedIntermediateCa) .commonName(server.getHostName()) .build(); diff --git a/okhttp-tests/src/test/java/okhttp3/internal/tls/ClientAuthTest.java b/okhttp-tests/src/test/java/okhttp3/internal/tls/ClientAuthTest.java index c6c931df9..9bed15eff 100644 --- a/okhttp-tests/src/test/java/okhttp3/internal/tls/ClientAuthTest.java +++ b/okhttp-tests/src/test/java/okhttp3/internal/tls/ClientAuthTest.java @@ -67,7 +67,7 @@ public final class ClientAuthTest { .addSubjectAlternativeName("root_ca.com") .build(); serverIntermediateCa = new HeldCertificate.Builder() - .issuedBy(serverRootCa) + .signedBy(serverRootCa) .certificateAuthority(0) .serialNumber(2L) .commonName("intermediate_ca") @@ -75,7 +75,7 @@ public final class ClientAuthTest { .build(); serverCert = new HeldCertificate.Builder() - .issuedBy(serverIntermediateCa) + .signedBy(serverIntermediateCa) .serialNumber(3L) .commonName("Local Host") .addSubjectAlternativeName(server.getHostName()) @@ -88,7 +88,7 @@ public final class ClientAuthTest { .addSubjectAlternativeName("root_ca.com") .build(); clientIntermediateCa = new HeldCertificate.Builder() - .issuedBy(serverRootCa) + .signedBy(serverRootCa) .certificateAuthority(0) .serialNumber(2L) .commonName("intermediate_ca") @@ -96,7 +96,7 @@ public final class ClientAuthTest { .build(); clientCert = new HeldCertificate.Builder() - .issuedBy(clientIntermediateCa) + .signedBy(clientIntermediateCa) .serialNumber(4L) .commonName("Jethro Willis") .addSubjectAlternativeName("jethrowillis.com") @@ -188,7 +188,7 @@ public final class ClientAuthTest { @Test public void commonNameIsNotTrusted() throws Exception { serverCert = new HeldCertificate.Builder() - .issuedBy(serverIntermediateCa) + .signedBy(serverIntermediateCa) .serialNumber(3L) .commonName(server.getHostName()) .addSubjectAlternativeName("different-host.com") diff --git a/okhttp-tls/src/main/java/okhttp3/tls/HandshakeCertificates.java b/okhttp-tls/src/main/java/okhttp3/tls/HandshakeCertificates.java index 017668ce8..015eb81ed 100644 --- a/okhttp-tls/src/main/java/okhttp3/tls/HandshakeCertificates.java +++ b/okhttp-tls/src/main/java/okhttp3/tls/HandshakeCertificates.java @@ -20,6 +20,7 @@ import java.security.KeyManagementException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; @@ -27,6 +28,8 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; +import okhttp3.CertificatePinner; +import okhttp3.internal.Util; import okhttp3.internal.platform.Platform; import static okhttp3.tls.internal.TlsUtil.newKeyManager; @@ -137,6 +140,24 @@ public final class HandshakeCertificates { return this; } + /** + * Add all of the host platform's trusted root certificates. This set varies by platform + * (Android vs. Java), by platform release (Android 4.4 vs. Android 9), and with user + * customizations. + * + *

Most TLS clients that connect to hosts on the public Internet should call this method. + * Otherwise it is necessary to manually prepare a comprehensive set of trusted roots. + * + *

If the host platform is compromised or misconfigured this may contain untrustworthy root + * certificates. Applications that connect to a known set of servers may be able to mitigate + * this problem with {@linkplain CertificatePinner certificate pinning}. + */ + public Builder addPlatformTrustedCertificates() { + X509TrustManager platformTrustManager = Util.platformTrustManager(); + Collections.addAll(trustedCertificates, platformTrustManager.getAcceptedIssuers()); + return this; + } + public HandshakeCertificates build() { try { X509KeyManager keyManager = newKeyManager(null, heldCertificate, intermediates); diff --git a/okhttp-tls/src/main/java/okhttp3/tls/HeldCertificate.java b/okhttp-tls/src/main/java/okhttp3/tls/HeldCertificate.java index 16820d388..68f16db23 100644 --- a/okhttp-tls/src/main/java/okhttp3/tls/HeldCertificate.java +++ b/okhttp-tls/src/main/java/okhttp3/tls/HeldCertificate.java @@ -208,7 +208,7 @@ public final class HeldCertificate { private final List altNames = new ArrayList<>(); private BigInteger serialNumber; private KeyPair keyPair; - private HeldCertificate issuedBy; + private HeldCertificate signedBy; private int maxIntermediateCas = -1; private String keyAlgorithm; private int keySize; @@ -298,11 +298,11 @@ public final class HeldCertificate { } /** - * Set the certificate that will sign this certificate. If unset the certificate will be + * Set the certificate that will issue this certificate. If unset the certificate will be * self-signed. */ - public Builder issuedBy(HeldCertificate issuedBy) { - this.issuedBy = issuedBy; + public Builder signedBy(HeldCertificate signedBy) { + this.signedBy = signedBy; return this; } @@ -357,9 +357,9 @@ public final class HeldCertificate { // Subject, public & private keys for this certificate's signer. It may be self signed! KeyPair signedByKeyPair; X500Principal signedByPrincipal; - if (issuedBy != null) { - signedByKeyPair = issuedBy.keyPair; - signedByPrincipal = issuedBy.certificate.getSubjectX500Principal(); + if (signedBy != null) { + signedByKeyPair = signedBy.keyPair; + signedByPrincipal = signedBy.certificate.getSubjectX500Principal(); } else { signedByKeyPair = heldKeyPair; signedByPrincipal = subject; diff --git a/okhttp-tls/src/test/java/okhttp3/tls/HandshakeCertificatesTest.java b/okhttp-tls/src/test/java/okhttp3/tls/HandshakeCertificatesTest.java index 5e6bfc3ea..c2e4f3a45 100644 --- a/okhttp-tls/src/test/java/okhttp3/tls/HandshakeCertificatesTest.java +++ b/okhttp-tls/src/test/java/okhttp3/tls/HandshakeCertificatesTest.java @@ -21,7 +21,10 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.security.PrivateKey; +import java.security.cert.X509Certificate; import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -37,6 +40,7 @@ import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public final class HandshakeCertificatesTest { private ExecutorService executorService; @@ -57,10 +61,10 @@ public final class HandshakeCertificatesTest { .build(); HeldCertificate clientIntermediate = new HeldCertificate.Builder() .certificateAuthority(0) - .issuedBy(clientRoot) + .signedBy(clientRoot) .build(); HeldCertificate clientCertificate = new HeldCertificate.Builder() - .issuedBy(clientIntermediate) + .signedBy(clientIntermediate) .build(); HeldCertificate serverRoot = new HeldCertificate.Builder() @@ -68,10 +72,10 @@ public final class HandshakeCertificatesTest { .build(); HeldCertificate serverIntermediate = new HeldCertificate.Builder() .certificateAuthority(0) - .issuedBy(serverRoot) + .signedBy(serverRoot) .build(); HeldCertificate serverCertificate = new HeldCertificate.Builder() - .issuedBy(serverIntermediate) + .signedBy(serverIntermediate) .build(); HandshakeCertificates server = new HandshakeCertificates.Builder() @@ -108,10 +112,10 @@ public final class HandshakeCertificatesTest { .build(); HeldCertificate intermediate = new HeldCertificate.Builder() .certificateAuthority(0) - .issuedBy(root) + .signedBy(root) .build(); HeldCertificate certificate = new HeldCertificate.Builder() - .issuedBy(intermediate) + .signedBy(intermediate) .build(); HandshakeCertificates handshakeCertificates = new HandshakeCertificates.Builder() @@ -123,6 +127,20 @@ public final class HandshakeCertificatesTest { Arrays.asList(handshakeCertificates.keyManager().getCertificateChain("private"))); } + @Test public void platformTrustedCertificates() { + HandshakeCertificates handshakeCertificates = new HandshakeCertificates.Builder() + .addPlatformTrustedCertificates() + .build(); + Set names = new LinkedHashSet<>(); + for (X509Certificate certificate : handshakeCertificates.trustManager().getAcceptedIssuers()) { + // Abbreviate a long name like "CN=Entrust Root Certification Authority - G2, OU=..." + String name = certificate.getSubjectDN().getName(); + names.add(name.substring(0, name.indexOf(" "))); + } + // It's safe to assume all platforms will have a major Internet certificate issuer. + assertTrue(names.toString(), names.contains("CN=Entrust")); + } + private InetSocketAddress startTlsServer() throws IOException { ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault(); serverSocket = serverSocketFactory.createServerSocket(); diff --git a/okhttp-tls/src/test/java/okhttp3/tls/HeldCertificateTest.java b/okhttp-tls/src/test/java/okhttp3/tls/HeldCertificateTest.java index ef61700d3..96c8601b2 100644 --- a/okhttp-tls/src/test/java/okhttp3/tls/HeldCertificateTest.java +++ b/okhttp-tls/src/test/java/okhttp3/tls/HeldCertificateTest.java @@ -202,7 +202,7 @@ public final class HeldCertificateTest { HeldCertificate leaf = new HeldCertificate.Builder() .certificateAuthority(0) .ecdsa256() - .issuedBy(root) + .signedBy(root) .build(); assertEquals("SHA256WITHRSA", root.certificate().getSigAlgName()); @@ -217,7 +217,7 @@ public final class HeldCertificateTest { HeldCertificate leaf = new HeldCertificate.Builder() .certificateAuthority(0) .rsa2048() - .issuedBy(root) + .signedBy(root) .build(); assertEquals("SHA256WITHECDSA", root.certificate().getSigAlgName()); diff --git a/okhttp/src/main/java/okhttp3/OkHttpClient.java b/okhttp/src/main/java/okhttp3/OkHttpClient.java index eaae6575d..460c8058c 100644 --- a/okhttp/src/main/java/okhttp3/OkHttpClient.java +++ b/okhttp/src/main/java/okhttp3/OkHttpClient.java @@ -19,9 +19,7 @@ import java.net.Proxy; import java.net.ProxySelector; import java.net.Socket; import java.security.GeneralSecurityException; -import java.security.KeyStore; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; @@ -34,7 +32,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import okhttp3.internal.Internal; import okhttp3.internal.Util; @@ -248,8 +245,8 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory this.sslSocketFactory = builder.sslSocketFactory; this.certificateChainCleaner = builder.certificateChainCleaner; } else { - X509TrustManager trustManager = systemDefaultTrustManager(); - this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager); + X509TrustManager trustManager = Util.platformTrustManager(); + this.sslSocketFactory = newSslSocketFactory(trustManager); this.certificateChainCleaner = CertificateChainCleaner.get(trustManager); } @@ -280,23 +277,7 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory } } - private X509TrustManager systemDefaultTrustManager() { - try { - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( - TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init((KeyStore) null); - TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); - if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { - throw new IllegalStateException("Unexpected default trust managers:" - + Arrays.toString(trustManagers)); - } - return (X509TrustManager) trustManagers[0]; - } catch (GeneralSecurityException e) { - throw assertionError("No System TLS", e); // The system has no TLS. Just give up. - } - } - - private SSLSocketFactory systemDefaultSslSocketFactory(X509TrustManager trustManager) { + private static SSLSocketFactory newSslSocketFactory(X509TrustManager trustManager) { try { SSLContext sslContext = Platform.get().getSSLContext(); sslContext.init(null, new TrustManager[] { trustManager }, null); diff --git a/okhttp/src/main/java/okhttp3/internal/Util.java b/okhttp/src/main/java/okhttp3/internal/Util.java index c41b34ea9..869eeafcf 100644 --- a/okhttp/src/main/java/okhttp3/internal/Util.java +++ b/okhttp/src/main/java/okhttp3/internal/Util.java @@ -26,6 +26,8 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.nio.charset.Charset; +import java.security.GeneralSecurityException; +import java.security.KeyStore; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -37,6 +39,9 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import javax.annotation.Nullable; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import okhttp3.HttpUrl; import okhttp3.RequestBody; import okhttp3.ResponseBody; @@ -642,4 +647,20 @@ public final class Util { } return result.readUtf8(); } + + public static X509TrustManager platformTrustManager() { + try { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init((KeyStore) null); + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { + throw new IllegalStateException("Unexpected default trust managers:" + + Arrays.toString(trustManagers)); + } + return (X509TrustManager) trustManagers[0]; + } catch (GeneralSecurityException e) { + throw assertionError("No System TLS", e); // The system has no TLS. Just give up. + } + } }