Search in sources :

Example 11 with HandshakeCertificates

use of okhttp3.tls.HandshakeCertificates in project okhttp by square.

the class CertificateChainCleanerTest method equalsFromTrustManager.

@Test
public void equalsFromTrustManager() {
    HandshakeCertificates handshakeCertificates = new HandshakeCertificates.Builder().build();
    X509TrustManager x509TrustManager = handshakeCertificates.trustManager();
    assertThat(CertificateChainCleaner.Companion.get(x509TrustManager)).isEqualTo(CertificateChainCleaner.Companion.get(x509TrustManager));
}
Also used : HandshakeCertificates(okhttp3.tls.HandshakeCertificates) X509TrustManager(javax.net.ssl.X509TrustManager) Test(org.junit.jupiter.api.Test)

Example 12 with HandshakeCertificates

use of okhttp3.tls.HandshakeCertificates in project okhttp by square.

the class MockWebServerTest method httpsWithClientAuth.

@Test
public void httpsWithClientAuth() throws Exception {
    assumeFalse(getPlatform().equals("conscrypt"));
    HeldCertificate clientCa = new HeldCertificate.Builder().certificateAuthority(0).build();
    HeldCertificate serverCa = new HeldCertificate.Builder().certificateAuthority(0).build();
    HeldCertificate serverCertificate = new HeldCertificate.Builder().signedBy(serverCa).addSubjectAlternativeName(server.getHostName()).build();
    HandshakeCertificates serverHandshakeCertificates = new HandshakeCertificates.Builder().addTrustedCertificate(clientCa.certificate()).heldCertificate(serverCertificate).build();
    server.useHttps(serverHandshakeCertificates.sslSocketFactory(), false);
    server.enqueue(new MockResponse().setBody("abc"));
    server.requestClientAuth();
    HeldCertificate clientCertificate = new HeldCertificate.Builder().signedBy(clientCa).build();
    HandshakeCertificates clientHandshakeCertificates = new HandshakeCertificates.Builder().addTrustedCertificate(serverCa.certificate()).heldCertificate(clientCertificate).build();
    HttpUrl url = server.url("/");
    HttpsURLConnection connection = (HttpsURLConnection) url.url().openConnection();
    connection.setSSLSocketFactory(clientHandshakeCertificates.sslSocketFactory());
    connection.setHostnameVerifier(new RecordingHostnameVerifier());
    assertThat(connection.getResponseCode()).isEqualTo(HttpURLConnection.HTTP_OK);
    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF_8));
    assertThat(reader.readLine()).isEqualTo("abc");
    RecordedRequest request = server.takeRequest();
    assertThat(request.getRequestUrl().scheme()).isEqualTo("https");
    Handshake handshake = request.getHandshake();
    assertThat(handshake.tlsVersion()).isNotNull();
    assertThat(handshake.cipherSuite()).isNotNull();
    assertThat(handshake.localPrincipal()).isNotNull();
    assertThat(handshake.localCertificates().size()).isEqualTo(1);
    assertThat(handshake.peerPrincipal()).isNotNull();
    assertThat(handshake.peerCertificates().size()).isEqualTo(1);
}
Also used : InputStreamReader(java.io.InputStreamReader) HandshakeCertificates(okhttp3.tls.HandshakeCertificates) HeldCertificate(okhttp3.tls.HeldCertificate) HttpUrl(okhttp3.HttpUrl) BufferedReader(java.io.BufferedReader) HttpsURLConnection(javax.net.ssl.HttpsURLConnection) RecordingHostnameVerifier(okhttp3.RecordingHostnameVerifier) Handshake(okhttp3.Handshake) Test(org.junit.jupiter.api.Test)

Example 13 with HandshakeCertificates

use of okhttp3.tls.HandshakeCertificates in project okhttp by square.

the class MockWebServerTest method https.

@Test
public void https() throws Exception {
    HandshakeCertificates handshakeCertificates = localhost();
    server.useHttps(handshakeCertificates.sslSocketFactory(), false);
    server.enqueue(new MockResponse().setBody("abc"));
    HttpUrl url = server.url("/");
    HttpsURLConnection connection = (HttpsURLConnection) url.url().openConnection();
    connection.setSSLSocketFactory(handshakeCertificates.sslSocketFactory());
    connection.setHostnameVerifier(new RecordingHostnameVerifier());
    assertThat(connection.getResponseCode()).isEqualTo(HttpURLConnection.HTTP_OK);
    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF_8));
    assertThat(reader.readLine()).isEqualTo("abc");
    RecordedRequest request = server.takeRequest();
    assertThat(request.getRequestUrl().scheme()).isEqualTo("https");
    Handshake handshake = request.getHandshake();
    assertThat(handshake.tlsVersion()).isNotNull();
    assertThat(handshake.cipherSuite()).isNotNull();
    assertThat(handshake.localPrincipal()).isNotNull();
    assertThat(handshake.localCertificates().size()).isEqualTo(1);
    assertThat(handshake.peerPrincipal()).isNull();
    assertThat(handshake.peerCertificates().size()).isEqualTo(0);
}
Also used : InputStreamReader(java.io.InputStreamReader) HandshakeCertificates(okhttp3.tls.HandshakeCertificates) BufferedReader(java.io.BufferedReader) HttpUrl(okhttp3.HttpUrl) HttpsURLConnection(javax.net.ssl.HttpsURLConnection) RecordingHostnameVerifier(okhttp3.RecordingHostnameVerifier) Handshake(okhttp3.Handshake) Test(org.junit.jupiter.api.Test)

Example 14 with HandshakeCertificates

use of okhttp3.tls.HandshakeCertificates in project okhttp by square.

the class LetsEncryptTest method getPassesAdditionalCert.

@Test
public void getPassesAdditionalCert() throws IOException, CertificateException {
    boolean androidMorEarlier = Build.VERSION.SDK_INT <= 23;
    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    if (androidMorEarlier) {
        String isgCert = "-----BEGIN CERTIFICATE-----\n" + "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\n" + "-----END CERTIFICATE-----";
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate isgCertificate = cf.generateCertificate(new ByteArrayInputStream(isgCert.getBytes("UTF-8")));
        HandshakeCertificates certificates = new HandshakeCertificates.Builder().addTrustedCertificate((X509Certificate) isgCertificate).build();
        builder.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager());
    }
    OkHttpClient client = builder.build();
    sendRequest(client, "https://valid-isrgrootx1.letsencrypt.org/robots.txt");
    try {
        sendRequest(client, "https://google.com/robots.txt");
        if (androidMorEarlier) {
            // will pass with default CAs on N or later
            fail();
        }
    } catch (SSLHandshakeException sslhe) {
        assertTrue(androidMorEarlier);
    }
}
Also used : OkHttpClient(okhttp3.OkHttpClient) ByteArrayInputStream(java.io.ByteArrayInputStream) HandshakeCertificates(okhttp3.tls.HandshakeCertificates) CertificateFactory(java.security.cert.CertificateFactory) X509Certificate(java.security.cert.X509Certificate) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate) Test(org.junit.Test)

Example 15 with HandshakeCertificates

use of okhttp3.tls.HandshakeCertificates in project okhttp by square.

the class CertificatePinnerChainValidationTest method signersMustHaveCaBitSet.

/**
 * Not checking the CA bit created a vulnerability in old OkHttp releases. It is exploited by
 * triggering different chains to be discovered by the TLS engine and our chain cleaner. In this
 * attack there's several different chains.
 *
 * <p>The victim's gets a non-CA certificate signed by a CA, and pins the CA root and/or
 * intermediate. This is business as usual.
 *
 * <pre>{@code
 *
 *   pinnedRoot (trusted by CertificatePinner)
 *     -> pinnedIntermediate (trusted by CertificatePinner)
 *       -> realVictim
 *
 * }</pre>
 *
 * <p>The attacker compromises a CA. They take the public key from an intermediate certificate
 * signed by the compromised CA's certificate and uses it in a non-CA certificate. They ask the
 * pinned CA above to sign it for non-certificate-authority uses:
 *
 * <pre>{@code
 *
 *   pinnedRoot (trusted by CertificatePinner)
 *     -> pinnedIntermediate (trusted by CertificatePinner)
 *         -> attackerSwitch
 *
 * }</pre>
 *
 * <p>The attacker serves a set of certificates that yields a too-long chain in our certificate
 * pinner. The served certificates (incorrectly) formed a single chain to the pinner:
 *
 * <pre>{@code
 *
 *   attackerCa
 *     -> attackerIntermediate
 *         -> pinnedRoot (trusted by CertificatePinner)
 *             -> pinnedIntermediate (trusted by CertificatePinner)
 *                 -> attackerSwitch (not a CA certificate!)
 *                     -> phonyVictim
 *
 * }</pre>
 *
 * But this chain is wrong because the attackerSwitch certificate is being used in a CA role even
 * though it is not a CA certificate. There are pinned certificates in the chain! The correct
 * chain is much shorter because it skips the non-CA certificate.
 *
 * <pre>{@code
 *
 *   attackerCa
 *     -> attackerIntermediate
 *         -> phonyVictim
 *
 * }</pre>
 *
 * Some implementations fail the TLS handshake when they see the long chain, and don't give
 * CertificatePinner the opportunity to produce a different chain from their own. This includes
 * the OpenJDK 11 TLS implementation, which itself fails the handshake when it encounters a non-CA
 * certificate.
 */
@Test
public void signersMustHaveCaBitSet() throws Exception {
    HeldCertificate attackerCa = new HeldCertificate.Builder().serialNumber(1L).certificateAuthority(4).commonName("attacker ca").build();
    HeldCertificate attackerIntermediate = new HeldCertificate.Builder().serialNumber(2L).certificateAuthority(3).commonName("attacker").signedBy(attackerCa).build();
    HeldCertificate pinnedRoot = new HeldCertificate.Builder().serialNumber(3L).certificateAuthority(2).commonName("pinned root").signedBy(attackerIntermediate).build();
    HeldCertificate pinnedIntermediate = new HeldCertificate.Builder().serialNumber(4L).certificateAuthority(1).commonName("pinned intermediate").signedBy(pinnedRoot).build();
    HeldCertificate attackerSwitch = new HeldCertificate.Builder().serialNumber(5L).keyPair(// share keys between compromised CA and leaf!
    attackerIntermediate.keyPair()).commonName("attacker").addSubjectAlternativeName("attacker.com").signedBy(pinnedIntermediate).build();
    HeldCertificate phonyVictim = new HeldCertificate.Builder().serialNumber(6L).signedBy(attackerSwitch).addSubjectAlternativeName("victim.com").commonName("victim").build();
    CertificatePinner certificatePinner = new CertificatePinner.Builder().add(server.getHostName(), CertificatePinner.pin(pinnedRoot.certificate())).build();
    HandshakeCertificates handshakeCertificates = new HandshakeCertificates.Builder().addTrustedCertificate(pinnedRoot.certificate()).addTrustedCertificate(attackerCa.certificate()).build();
    OkHttpClient client = clientTestRule.newClientBuilder().sslSocketFactory(handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager()).hostnameVerifier(new RecordingHostnameVerifier()).certificatePinner(certificatePinner).build();
    HandshakeCertificates serverHandshakeCertificates = new HandshakeCertificates.Builder().heldCertificate(phonyVictim, attackerSwitch.certificate(), pinnedIntermediate.certificate(), pinnedRoot.certificate(), attackerIntermediate.certificate()).build();
    server.useHttps(serverHandshakeCertificates.sslSocketFactory(), false);
    server.enqueue(new MockResponse());
    // Make a request from client to server. It should succeed certificate checks (unfortunately the
    // rogue CA is trusted) but it should fail certificate pinning.
    Request request = new Request.Builder().url(server.url("/")).build();
    Call call = client.newCall(request);
    try (Response response = call.execute()) {
        fail("expected connection failure but got " + response);
    } catch (SSLPeerUnverifiedException expected) {
        // Certificate pinning fails!
        String message = expected.getMessage();
        assertThat(message).startsWith("Certificate pinning failure!");
    } catch (SSLHandshakeException expected) {
        // We didn't have the opportunity to do certificate pinning because the handshake failed.
        assertThat(expected).hasMessageContaining("this is not a CA certificate");
    }
}
Also used : MockResponse(mockwebserver3.MockResponse) Call(okhttp3.Call) OkHttpClient(okhttp3.OkHttpClient) HandshakeCertificates(okhttp3.tls.HandshakeCertificates) CertificatePinner(okhttp3.CertificatePinner) SSLPeerUnverifiedException(javax.net.ssl.SSLPeerUnverifiedException) HeldCertificate(okhttp3.tls.HeldCertificate) Request(okhttp3.Request) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) Response(okhttp3.Response) MockResponse(mockwebserver3.MockResponse) RecordingHostnameVerifier(okhttp3.RecordingHostnameVerifier) Test(org.junit.jupiter.api.Test)

Aggregations

HandshakeCertificates (okhttp3.tls.HandshakeCertificates)17 Test (org.junit.jupiter.api.Test)12 RecordingHostnameVerifier (okhttp3.RecordingHostnameVerifier)11 HeldCertificate (okhttp3.tls.HeldCertificate)11 OkHttpClient (okhttp3.OkHttpClient)9 Call (okhttp3.Call)8 Request (okhttp3.Request)8 MockResponse (mockwebserver3.MockResponse)7 CertificatePinner (okhttp3.CertificatePinner)7 Response (okhttp3.Response)6 BufferedReader (java.io.BufferedReader)4 InputStreamReader (java.io.InputStreamReader)4 HttpsURLConnection (javax.net.ssl.HttpsURLConnection)4 SSLHandshakeException (javax.net.ssl.SSLHandshakeException)4 Handshake (okhttp3.Handshake)4 HttpUrl (okhttp3.HttpUrl)4 SSLPeerUnverifiedException (javax.net.ssl.SSLPeerUnverifiedException)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 Certificate (java.security.cert.Certificate)2 CertificateFactory (java.security.cert.CertificateFactory)2