1
0
mirror of https://github.com/square/okhttp.git synced 2025-11-24 18:41:06 +03:00

Add bouncy castle platform for tests (#5695)

* Add basic bouncy castle test

* Remove other tests

* Activate platform for TLS tests
This commit is contained in:
Yuri Schimke
2020-01-11 15:29:17 +00:00
committed by Jesse Wilson
parent 04b4fbb6b5
commit 604e2705e7
6 changed files with 139 additions and 1 deletions

View File

@@ -4,7 +4,7 @@ buildscript {
ext.versions = [ ext.versions = [
'animalSniffer': '1.17', 'animalSniffer': '1.17',
'assertj': '3.11.0', 'assertj': '3.11.0',
'bouncycastle': '1.62', 'bouncycastle': '1.64',
'brotli': '0.1.2', 'brotli': '0.1.2',
'checkstyle': '8.15', 'checkstyle': '8.15',
'conscrypt': '2.2.1', 'conscrypt': '2.2.1',
@@ -29,6 +29,7 @@ buildscript {
'animalSniffer': "org.codehaus.mojo:animal-sniffer-annotations:${versions.animalSniffer}", 'animalSniffer': "org.codehaus.mojo:animal-sniffer-annotations:${versions.animalSniffer}",
'assertj': "org.assertj:assertj-core:${versions.assertj}", 'assertj': "org.assertj:assertj-core:${versions.assertj}",
'bouncycastle': "org.bouncycastle:bcprov-jdk15on:${versions.bouncycastle}", 'bouncycastle': "org.bouncycastle:bcprov-jdk15on:${versions.bouncycastle}",
'bouncycastletls': "org.bouncycastle:bctls-jdk15on:${versions.bouncycastle}",
'brotli': "org.brotli:dec:${versions.brotli}", 'brotli': "org.brotli:dec:${versions.brotli}",
'conscrypt': "org.conscrypt:conscrypt-openjdk-uber:${versions.conscrypt}", 'conscrypt': "org.conscrypt:conscrypt-openjdk-uber:${versions.conscrypt}",
'corretto': "software.amazon.cryptools:AmazonCorrettoCryptoProvider:${versions.corretto}:linux-x86_64", 'corretto': "software.amazon.cryptools:AmazonCorrettoCryptoProvider:${versions.corretto}:linux-x86_64",

View File

@@ -2,6 +2,8 @@ dependencies {
api project(':okhttp') api project(':okhttp')
api deps.junit api deps.junit
api deps.assertj api deps.assertj
api deps.bouncycastle
api deps.bouncycastletls
api deps.conscrypt api deps.conscrypt
api deps.corretto api deps.corretto
api deps.openjsse api deps.openjsse

View File

@@ -22,6 +22,8 @@ import okhttp3.internal.platform.OpenJSSEPlatform
import com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider import com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider
import com.amazon.corretto.crypto.provider.SelfTestStatus import com.amazon.corretto.crypto.provider.SelfTestStatus
import okhttp3.internal.platform.Platform import okhttp3.internal.platform.Platform
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
import org.conscrypt.Conscrypt import org.conscrypt.Conscrypt
import org.hamcrest.BaseMatcher import org.hamcrest.BaseMatcher
import org.hamcrest.CoreMatchers import org.hamcrest.CoreMatchers
@@ -221,6 +223,11 @@ open class PlatformRule @JvmOverloads constructor(
CORRETTO_PROPERTY)) CORRETTO_PROPERTY))
} }
fun assumeBouncyCastle() {
assumeThat(getPlatformSystemProperty(), equalTo(
BOUNCYCASTLE_PROPERTY))
}
fun assumeHttp2Support() { fun assumeHttp2Support() {
assumeThat(getPlatformSystemProperty(), not( assumeThat(getPlatformSystemProperty(), not(
JDK8_PROPERTY)) JDK8_PROPERTY))
@@ -256,6 +263,11 @@ open class PlatformRule @JvmOverloads constructor(
CORRETTO_PROPERTY)) CORRETTO_PROPERTY))
} }
fun assumeNotBouncyCastle() {
assumeThat(getPlatformSystemProperty(), not(
BOUNCYCASTLE_PROPERTY))
}
fun assumeNotHttp2Support() { fun assumeNotHttp2Support() {
assumeThat(getPlatformSystemProperty(), equalTo( assumeThat(getPlatformSystemProperty(), equalTo(
JDK8_PROPERTY)) JDK8_PROPERTY))
@@ -273,6 +285,7 @@ open class PlatformRule @JvmOverloads constructor(
const val JDK8_ALPN_PROPERTY = "jdk8alpn" const val JDK8_ALPN_PROPERTY = "jdk8alpn"
const val JDK8_PROPERTY = "jdk8" const val JDK8_PROPERTY = "jdk8"
const val OPENJSSE_PROPERTY = "openjsse" const val OPENJSSE_PROPERTY = "openjsse"
const val BOUNCYCASTLE_PROPERTY = "bouncycastle"
init { init {
if (getPlatformSystemProperty() == CONSCRYPT_PROPERTY && Security.getProviders()[0].name != "Conscrypt") { if (getPlatformSystemProperty() == CONSCRYPT_PROPERTY && Security.getProviders()[0].name != "Conscrypt") {
@@ -296,6 +309,9 @@ open class PlatformRule @JvmOverloads constructor(
} }
Security.insertProviderAt(OpenJSSE(), 1) Security.insertProviderAt(OpenJSSE(), 1)
} else if (getPlatformSystemProperty() == BOUNCYCASTLE_PROPERTY && Security.getProviders()[0].name != "BC") {
Security.insertProviderAt(BouncyCastleProvider(), 1)
Security.insertProviderAt(BouncyCastleJsseProvider(), 2)
} else if (getPlatformSystemProperty() == CORRETTO_PROPERTY) { } else if (getPlatformSystemProperty() == CORRETTO_PROPERTY) {
AmazonCorrettoCryptoProvider.install() AmazonCorrettoCryptoProvider.install()
@@ -340,6 +356,9 @@ open class PlatformRule @JvmOverloads constructor(
@JvmStatic @JvmStatic
fun jdk8alpn() = PlatformRule(JDK8_ALPN_PROPERTY) fun jdk8alpn() = PlatformRule(JDK8_ALPN_PROPERTY)
@JvmStatic
fun bouncycastle() = PlatformRule(BOUNCYCASTLE_PROPERTY)
@JvmStatic @JvmStatic
fun isAlpnBootEnabled(): Boolean = try { fun isAlpnBootEnabled(): Boolean = try {
Class.forName("org.eclipse.jetty.alpn.ALPN", true, null) Class.forName("org.eclipse.jetty.alpn.ALPN", true, null)

View File

@@ -31,9 +31,11 @@ import javax.net.ServerSocketFactory;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import okhttp3.Handshake; import okhttp3.Handshake;
import okhttp3.testing.PlatformRule;
import okio.ByteString; import okio.ByteString;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@@ -42,6 +44,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeFalse;
public final class HandshakeCertificatesTest { public final class HandshakeCertificatesTest {
@Rule
public PlatformRule platform = new PlatformRule();
private ExecutorService executorService; private ExecutorService executorService;
private ServerSocket serverSocket; private ServerSocket serverSocket;

View File

@@ -24,8 +24,11 @@ import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import okhttp3.testing.PlatformRule;
import okio.ByteString; import okio.ByteString;
import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralName;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@@ -34,6 +37,9 @@ import static org.assertj.core.data.Offset.offset;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public final class HeldCertificateTest { public final class HeldCertificateTest {
@Rule
public PlatformRule platform = new PlatformRule();
@Test public void defaultCertificate() throws CertificateParsingException { @Test public void defaultCertificate() throws CertificateParsingException {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
HeldCertificate heldCertificate = new HeldCertificate.Builder().build(); HeldCertificate heldCertificate = new HeldCertificate.Builder().build();

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2019 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3
import okhttp3.TestUtil.assumeNetwork
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.testing.PlatformRule
import okhttp3.tls.HandshakeCertificates
import okhttp3.tls.HeldCertificate
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.openjsse.sun.security.ssl.SSLSocketFactoryImpl
import org.openjsse.sun.security.ssl.SSLSocketImpl
import java.net.InetAddress
class BouncyCastleTest {
@JvmField @Rule var platform = PlatformRule()
@JvmField @Rule val clientTestRule = OkHttpClientTestRule()
@JvmField @Rule val server = MockWebServer()
var client = clientTestRule.newClient()
@Before
fun setUp() {
platform.assumeBouncyCastle()
}
@Test
fun testTlsv13Works() {
platform.expectFailureOnJdkVersion(8)
enableTls()
server.enqueue(MockResponse().setBody("abc"))
val request = Request.Builder().url(server.url("/")).build()
val response = client.newCall(request).execute()
response.use {
assertEquals(200, response.code)
assertEquals(TlsVersion.TLS_1_3, response.handshake?.tlsVersion)
assertEquals(Protocol.HTTP_2, response.protocol)
assertThat(response.exchange?.connection()?.socket()).isInstanceOf(SSLSocketImpl::class.java)
}
}
@Test
fun testSupportedProtocols() {
val factory = SSLSocketFactoryImpl()
val s = factory.createSocket() as SSLSocketImpl
assertEquals(listOf("TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"), s.enabledProtocols.toList())
}
@Test
@Ignore
fun testMozilla() {
assumeNetwork()
val request = Request.Builder().url("https://mozilla.org/robots.txt").build()
client.newCall(request).execute().use {
assertThat(it.protocol).isEqualTo(Protocol.HTTP_1_1)
assertThat(it.handshake!!.tlsVersion).isEqualTo(TlsVersion.TLS_1_3)
}
}
private fun enableTls() {
// Generate a self-signed cert for the server to serve and the client to trust.
// can't use TlsUtil.localhost with a non OpenJSSE trust manager
val heldCertificate = HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName(InetAddress.getByName("localhost").canonicalHostName)
.build()
val handshakeCertificates = HandshakeCertificates.Builder()
.heldCertificate(heldCertificate)
.addTrustedCertificate(heldCertificate.certificate)
.build()
client = client.newBuilder()
.sslSocketFactory(
handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager)
.build()
server.useHttps(handshakeCertificates.sslSocketFactory(), false)
}
}