Search in sources :

Example 21 with HeldCertificate

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

the class CertificateChainCleanerTest method unorderedChainOfCertificatesWithRoot.

@Test
public void unorderedChainOfCertificatesWithRoot() throws Exception {
    HeldCertificate root = new HeldCertificate.Builder().serialNumber(1L).certificateAuthority(2).build();
    HeldCertificate certA = new HeldCertificate.Builder().serialNumber(2L).certificateAuthority(1).signedBy(root).build();
    HeldCertificate certB = new HeldCertificate.Builder().serialNumber(3L).certificateAuthority(0).signedBy(certA).build();
    HeldCertificate certC = new HeldCertificate.Builder().serialNumber(4L).signedBy(certB).build();
    CertificateChainCleaner cleaner = CertificateChainCleaner.Companion.get(root.certificate());
    assertThat(cleaner.clean(list(certC, certA, root, certB), "hostname")).isEqualTo(list(certC, certB, certA, root));
}
Also used : HeldCertificate(okhttp3.tls.HeldCertificate) CertificateChainCleaner(okhttp3.internal.tls.CertificateChainCleaner) Test(org.junit.jupiter.api.Test)

Example 22 with HeldCertificate

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

the class CertificateChainCleanerTest method orderedChainOfCertificatesWithoutRoot.

@Test
public void orderedChainOfCertificatesWithoutRoot() throws Exception {
    HeldCertificate root = new HeldCertificate.Builder().serialNumber(1L).certificateAuthority(1).build();
    HeldCertificate certA = new HeldCertificate.Builder().serialNumber(2L).certificateAuthority(0).signedBy(root).build();
    HeldCertificate certB = new HeldCertificate.Builder().serialNumber(3L).signedBy(certA).build();
    CertificateChainCleaner cleaner = CertificateChainCleaner.Companion.get(root.certificate());
    // Root is added!
    assertThat(cleaner.clean(list(certB, certA), "hostname")).isEqualTo(list(certB, certA, root));
}
Also used : HeldCertificate(okhttp3.tls.HeldCertificate) CertificateChainCleaner(okhttp3.internal.tls.CertificateChainCleaner) Test(org.junit.jupiter.api.Test)

Example 23 with HeldCertificate

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

the class CertificateChainCleanerTest method trustedRootNotSelfSigned.

@Test
public void trustedRootNotSelfSigned() throws Exception {
    HeldCertificate unknownSigner = new HeldCertificate.Builder().serialNumber(1L).certificateAuthority(2).build();
    HeldCertificate trusted = new HeldCertificate.Builder().signedBy(unknownSigner).certificateAuthority(1).serialNumber(2L).build();
    HeldCertificate intermediateCa = new HeldCertificate.Builder().signedBy(trusted).certificateAuthority(0).serialNumber(3L).build();
    HeldCertificate certificate = new HeldCertificate.Builder().signedBy(intermediateCa).serialNumber(4L).build();
    CertificateChainCleaner cleaner = CertificateChainCleaner.Companion.get(trusted.certificate());
    assertThat(cleaner.clean(list(certificate, intermediateCa), "hostname")).isEqualTo(list(certificate, intermediateCa, trusted));
    assertThat(cleaner.clean(list(certificate, intermediateCa, trusted), "hostname")).isEqualTo(list(certificate, intermediateCa, trusted));
}
Also used : HeldCertificate(okhttp3.tls.HeldCertificate) CertificateChainCleaner(okhttp3.internal.tls.CertificateChainCleaner) Test(org.junit.jupiter.api.Test)

Example 24 with HeldCertificate

use of okhttp3.tls.HeldCertificate 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 25 with HeldCertificate

use of okhttp3.tls.HeldCertificate 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

HeldCertificate (okhttp3.tls.HeldCertificate)25 Test (org.junit.jupiter.api.Test)23 HandshakeCertificates (okhttp3.tls.HandshakeCertificates)12 CertificateChainCleaner (okhttp3.internal.tls.CertificateChainCleaner)11 Call (okhttp3.Call)9 OkHttpClient (okhttp3.OkHttpClient)9 RecordingHostnameVerifier (okhttp3.RecordingHostnameVerifier)9 Request (okhttp3.Request)9 MockResponse (mockwebserver3.MockResponse)7 CertificatePinner (okhttp3.CertificatePinner)7 Response (okhttp3.Response)6 SSLPeerUnverifiedException (javax.net.ssl.SSLPeerUnverifiedException)5 SSLHandshakeException (javax.net.ssl.SSLHandshakeException)4 SSLSocketFactory (javax.net.ssl.SSLSocketFactory)3 BufferedReader (java.io.BufferedReader)2 InputStreamReader (java.io.InputStreamReader)2 Certificate (java.security.cert.Certificate)2 X509Certificate (java.security.cert.X509Certificate)2 ArrayList (java.util.ArrayList)2 HttpsURLConnection (javax.net.ssl.HttpsURLConnection)2