mirror of
https://github.com/square/okhttp.git
synced 2025-08-08 23:42:08 +03:00
OpenJSSE Platform support (#5369)
Adds support for OpenJSSE when registered as the first security provider.
This commit is contained in:
@@ -140,6 +140,20 @@ jobs:
|
||||
- runtests:
|
||||
platform: jdk8alpn
|
||||
|
||||
testopenjsse:
|
||||
docker:
|
||||
- image: circleci/openjdk:8u171-jdk
|
||||
|
||||
environment:
|
||||
JVM_OPTS: -Xmx1g
|
||||
TERM: dumb
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- runtests:
|
||||
platform: openjsse
|
||||
|
||||
testjdk11:
|
||||
docker:
|
||||
- image: circleci/openjdk:11.0.3-jdk-stretch
|
||||
@@ -205,6 +219,11 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- testopenjsse:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages
|
||||
- testjdk11:
|
||||
filters:
|
||||
branches:
|
||||
@@ -236,6 +255,9 @@ workflows:
|
||||
- testjdk8alpn:
|
||||
requires:
|
||||
- compile
|
||||
- testopenjsse:
|
||||
requires:
|
||||
- compile
|
||||
- testjdk11:
|
||||
requires:
|
||||
- compile
|
||||
|
@@ -159,6 +159,10 @@ subprojects { project ->
|
||||
dependencies {
|
||||
testRuntime "org.conscrypt:conscrypt-openjdk-uber:${versions.conscrypt}"
|
||||
}
|
||||
} else if (platform == "openjsse") {
|
||||
dependencies {
|
||||
testRuntime deps.openjsse
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@@ -3,6 +3,7 @@ dependencies {
|
||||
api deps.junit
|
||||
api deps.assertj
|
||||
api deps.conscrypt
|
||||
api deps.openjsse
|
||||
|
||||
compileOnly deps.jsr305
|
||||
}
|
||||
|
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package okhttp3;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import okhttp3.internal.http2.Header;
|
||||
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
|
||||
public final class TestUtil {
|
||||
public static final InetSocketAddress UNREACHABLE_ADDRESS
|
||||
= new InetSocketAddress("198.51.100.1", 8080);
|
||||
@@ -52,4 +56,12 @@ public final class TestUtil {
|
||||
Thread.sleep(100);
|
||||
System.runFinalization();
|
||||
}
|
||||
|
||||
public static void assumeNetwork() {
|
||||
try {
|
||||
InetAddress.getByName("www.google.com");
|
||||
} catch (UnknownHostException uhe) {
|
||||
assumeNoException(uhe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package okhttp3.testing
|
||||
import okhttp3.internal.platform.ConscryptPlatform
|
||||
import okhttp3.internal.platform.Jdk8WithJettyBootPlatform
|
||||
import okhttp3.internal.platform.Jdk9Platform
|
||||
import okhttp3.internal.platform.OpenJSSEPlatform
|
||||
import okhttp3.internal.platform.Platform
|
||||
import org.conscrypt.Conscrypt
|
||||
import org.hamcrest.BaseMatcher
|
||||
@@ -34,6 +35,7 @@ import org.junit.Assume.assumeTrue
|
||||
import org.junit.AssumptionViolatedException
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runners.model.Statement
|
||||
import org.openjsse.net.ssl.OpenJSSE
|
||||
import java.security.Security
|
||||
|
||||
/**
|
||||
@@ -57,6 +59,8 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
try {
|
||||
setupPlatform()
|
||||
|
||||
System.err.println("Running with ${Platform.get().javaClass.simpleName}")
|
||||
|
||||
base.evaluate()
|
||||
} catch (e: AssumptionViolatedException) {
|
||||
throw e
|
||||
@@ -95,6 +99,10 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
expectFailure(platformMatches(CONSCRYPT_PROPERTY))
|
||||
}
|
||||
|
||||
fun expectFailureOnOpenJSSEPlatform() {
|
||||
expectFailure(platformMatches(OPENJSSE_PROPERTY))
|
||||
}
|
||||
|
||||
fun expectFailureFromJdkVersion(majorVersion: Int) {
|
||||
expectFailure(fromMajor(majorVersion))
|
||||
}
|
||||
@@ -118,7 +126,7 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
|
||||
fun fromMajor(version: Int): Matcher<PlatformVersion> {
|
||||
return object : TypeSafeMatcher<PlatformVersion>() {
|
||||
override fun describeTo(description: org.hamcrest.Description) {
|
||||
override fun describeTo(description: Description) {
|
||||
description.appendText("JDK with version from $version")
|
||||
}
|
||||
|
||||
@@ -171,6 +179,11 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
JDK9_PROPERTY))
|
||||
}
|
||||
|
||||
fun assumeOpenJSSE() {
|
||||
assumeThat(getPlatformSystemProperty(), equalTo(
|
||||
OPENJSSE_PROPERTY))
|
||||
}
|
||||
|
||||
fun assumeJdk8() {
|
||||
assumeThat(getPlatformSystemProperty(), equalTo(
|
||||
JDK8_PROPERTY))
|
||||
@@ -206,6 +219,11 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
JDK8_ALPN_PROPERTY))
|
||||
}
|
||||
|
||||
fun assumeNotOpenJSSE() {
|
||||
assumeThat(getPlatformSystemProperty(), not(
|
||||
OPENJSSE_PROPERTY))
|
||||
}
|
||||
|
||||
fun assumeNotHttp2Support() {
|
||||
assumeThat(getPlatformSystemProperty(), equalTo(
|
||||
JDK8_PROPERTY))
|
||||
@@ -221,6 +239,7 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
const val JDK9_PROPERTY = "jdk9"
|
||||
const val JDK8_ALPN_PROPERTY = "jdk8alpn"
|
||||
const val JDK8_PROPERTY = "jdk8"
|
||||
const val OPENJSSE_PROPERTY = "openjsse"
|
||||
|
||||
init {
|
||||
if (getPlatformSystemProperty() == CONSCRYPT_PROPERTY && Security.getProviders()[0].name != "Conscrypt") {
|
||||
@@ -238,7 +257,15 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
if (isAlpnBootEnabled()) {
|
||||
System.err.println("Warning: ALPN Boot enabled unintentionally")
|
||||
}
|
||||
} else if (getPlatformSystemProperty() == OPENJSSE_PROPERTY && Security.getProviders()[0].name != "OpenJSSE") {
|
||||
if (!OpenJSSEPlatform.isSupported) {
|
||||
System.err.println("Warning: OpenJSSE not available")
|
||||
}
|
||||
|
||||
Security.insertProviderAt(OpenJSSE(), 1)
|
||||
}
|
||||
|
||||
Platform.resetForTests()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -249,6 +276,7 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
if (property == null) {
|
||||
property = when (Platform.get()) {
|
||||
is ConscryptPlatform -> CONSCRYPT_PROPERTY
|
||||
is OpenJSSEPlatform -> OPENJSSE_PROPERTY
|
||||
is Jdk8WithJettyBootPlatform -> CONSCRYPT_PROPERTY
|
||||
is Jdk9Platform -> JDK9_PROPERTY
|
||||
else -> JDK8_PROPERTY
|
||||
@@ -261,6 +289,9 @@ open class PlatformRule @JvmOverloads constructor(
|
||||
@JvmStatic
|
||||
fun conscrypt() = PlatformRule(CONSCRYPT_PROPERTY)
|
||||
|
||||
@JvmStatic
|
||||
fun openjsse() = PlatformRule(OPENJSSE_PROPERTY)
|
||||
|
||||
@JvmStatic
|
||||
fun jdk9() = PlatformRule(JDK9_PROPERTY)
|
||||
|
||||
|
@@ -26,6 +26,7 @@ dependencies {
|
||||
api deps.okio
|
||||
api deps.kotlinStdlib
|
||||
compileOnly deps.conscrypt
|
||||
compileOnly deps.openjsse
|
||||
compileOnly deps.android
|
||||
compileOnly deps.jsr305
|
||||
compileOnly deps.animalSniffer
|
||||
|
@@ -542,3 +542,27 @@ inline fun Any.notify() = (this as Object).notify()
|
||||
|
||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "NOTHING_TO_INLINE")
|
||||
inline fun Any.notifyAll() = (this as Object).notifyAll()
|
||||
|
||||
fun <T> readFieldOrNull(instance: Any, fieldType: Class<T>, fieldName: String): T? {
|
||||
var c: Class<*> = instance.javaClass
|
||||
while (c != Any::class.java) {
|
||||
try {
|
||||
val field = c.getDeclaredField(fieldName)
|
||||
field.isAccessible = true
|
||||
val value = field.get(instance)
|
||||
return if (!fieldType.isInstance(value)) null else fieldType.cast(value)
|
||||
} catch (_: NoSuchFieldException) {
|
||||
}
|
||||
|
||||
c = c.superclass
|
||||
}
|
||||
|
||||
// Didn't find the field we wanted. As a last gasp attempt,
|
||||
// try to find the value on a delegate.
|
||||
if (fieldName != "delegate") {
|
||||
val delegate = readFieldOrNull(instance, Any::class.java, "delegate")
|
||||
if (delegate != null) return readFieldOrNull(delegate, fieldType, fieldName)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package okhttp3.internal.platform
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.internal.platform.android.CloseGuard
|
||||
@@ -225,7 +224,6 @@ class AndroidPlatform : Platform() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
@SuppressLint("PrivateApi")
|
||||
val isSupported: Boolean = try {
|
||||
// Trigger an early exception over a fatal error, prefer a RuntimeException over Error.
|
||||
Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl")
|
||||
|
@@ -16,6 +16,7 @@
|
||||
package okhttp3.internal.platform
|
||||
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.internal.readFieldOrNull
|
||||
import org.conscrypt.Conscrypt
|
||||
import java.security.Provider
|
||||
import javax.net.ssl.SSLContext
|
||||
@@ -29,13 +30,9 @@ import javax.net.ssl.X509TrustManager
|
||||
* Requires org.conscrypt:conscrypt-openjdk-uber >= 2.1.0 on the classpath.
|
||||
*/
|
||||
class ConscryptPlatform private constructor() : Platform() {
|
||||
private val provider: Provider
|
||||
get() {
|
||||
// n.b. We should consider defaulting to OpenJDK 11 trust manager
|
||||
// https://groups.google.com/forum/#!topic/conscrypt/3vYzbesjOb4
|
||||
|
||||
return Conscrypt.newProviderBuilder().provideTrustManager(true).build()
|
||||
}
|
||||
private val provider: Provider = Conscrypt.newProviderBuilder().provideTrustManager(true).build()
|
||||
|
||||
// See release notes https://groups.google.com/forum/#!forum/conscrypt
|
||||
// for version differences
|
||||
|
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.internal.platform
|
||||
|
||||
import okhttp3.Protocol
|
||||
import java.security.KeyStore
|
||||
import java.security.Provider
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.SSLSocket
|
||||
import javax.net.ssl.SSLSocketFactory
|
||||
import javax.net.ssl.TrustManagerFactory
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* Platform using OpenJSSE (https://github.com/openjsse/openjsse) if installed as the first
|
||||
* Security Provider.
|
||||
*
|
||||
* Requires org.openjsse:openjsse >= 1.1.0 on the classpath.
|
||||
*/
|
||||
class OpenJSSEPlatform private constructor() : Platform() {
|
||||
private val provider: Provider = org.openjsse.net.ssl.OpenJSSE()
|
||||
|
||||
// Selects TLSv1.3 so we are specific about our intended version ranges (not just 1.3)
|
||||
// and because it's a common pattern for VMs to have differences between supported and
|
||||
// defaulted versions for TLS based on what is requested.
|
||||
override fun newSSLContext(): SSLContext =
|
||||
SSLContext.getInstance("TLSv1.3", provider)
|
||||
|
||||
override fun platformTrustManager(): X509TrustManager {
|
||||
val factory = TrustManagerFactory.getInstance(
|
||||
TrustManagerFactory.getDefaultAlgorithm(), provider)
|
||||
factory.init(null as KeyStore?)
|
||||
val trustManagers = factory.trustManagers!!
|
||||
check(trustManagers.size == 1 && trustManagers[0] is X509TrustManager) {
|
||||
"Unexpected default trust managers: ${trustManagers.contentToString()}"
|
||||
}
|
||||
return trustManagers[0] as X509TrustManager
|
||||
}
|
||||
|
||||
public override fun trustManager(sslSocketFactory: SSLSocketFactory): X509TrustManager? =
|
||||
throw UnsupportedOperationException(
|
||||
"clientBuilder.sslSocketFactory(SSLSocketFactory) not supported with OpenJSSE")
|
||||
|
||||
override fun configureTlsExtensions(
|
||||
sslSocket: SSLSocket,
|
||||
hostname: String?,
|
||||
protocols: List<Protocol>
|
||||
) {
|
||||
if (sslSocket is org.openjsse.javax.net.ssl.SSLSocket) {
|
||||
val sslParameters = sslSocket.sslParameters
|
||||
|
||||
if (sslParameters is org.openjsse.javax.net.ssl.SSLParameters) {
|
||||
// Enable ALPN.
|
||||
val names = alpnProtocolNames(protocols)
|
||||
sslParameters.applicationProtocols = names.toTypedArray()
|
||||
|
||||
sslSocket.sslParameters = sslParameters
|
||||
}
|
||||
} else {
|
||||
super.configureTlsExtensions(sslSocket, hostname, protocols)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectedProtocol(sslSocket: SSLSocket): String? =
|
||||
if (sslSocket is org.openjsse.javax.net.ssl.SSLSocket) {
|
||||
when (val protocol = sslSocket.applicationProtocol) {
|
||||
// Handles both un-configured and none selected.
|
||||
null, "" -> null
|
||||
else -> protocol
|
||||
}
|
||||
} else {
|
||||
super.getSelectedProtocol(sslSocket)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val isSupported: Boolean = try {
|
||||
// Trigger an early exception over a fatal error, prefer a RuntimeException over Error.
|
||||
Class.forName("org.openjsse.net.ssl.OpenJSSE")
|
||||
|
||||
true
|
||||
} catch (_: ClassNotFoundException) {
|
||||
false
|
||||
}
|
||||
|
||||
fun buildIfSupported(): OpenJSSEPlatform? = if (isSupported) OpenJSSEPlatform() else null
|
||||
}
|
||||
}
|
@@ -18,6 +18,7 @@ package okhttp3.internal.platform
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.internal.readFieldOrNull
|
||||
import okhttp3.internal.tls.BasicCertificateChainCleaner
|
||||
import okhttp3.internal.tls.BasicTrustRootIndex
|
||||
import okhttp3.internal.tls.CertificateChainCleaner
|
||||
@@ -193,12 +194,18 @@ open class Platform {
|
||||
fun alpnProtocolNames(protocols: List<Protocol>) =
|
||||
protocols.filter { it != Protocol.HTTP_1_0 }.map { it.toString() }
|
||||
|
||||
val isConscryptPreferred: Boolean
|
||||
private val isConscryptPreferred: Boolean
|
||||
get() {
|
||||
val preferredProvider = Security.getProviders()[0].name
|
||||
return "Conscrypt" == preferredProvider
|
||||
}
|
||||
|
||||
private val isOpenJSSEPreferred: Boolean
|
||||
get() {
|
||||
val preferredProvider = Security.getProviders()[0].name
|
||||
return "OpenJSSE" == preferredProvider
|
||||
}
|
||||
|
||||
/** Attempt to match the host runtime to a capable Platform implementation. */
|
||||
private fun findPlatform(): Platform {
|
||||
val android = AndroidPlatform.buildIfSupported()
|
||||
@@ -215,6 +222,14 @@ open class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
if (isOpenJSSEPreferred) {
|
||||
val openJSSE = OpenJSSEPlatform.buildIfSupported()
|
||||
|
||||
if (openJSSE != null) {
|
||||
return openJSSE
|
||||
}
|
||||
}
|
||||
|
||||
val jdk9 = Jdk9Platform.buildIfSupported()
|
||||
|
||||
if (jdk9 != null) {
|
||||
@@ -239,29 +254,5 @@ open class Platform {
|
||||
}
|
||||
return result.readByteArray()
|
||||
}
|
||||
|
||||
fun <T> readFieldOrNull(instance: Any, fieldType: Class<T>, fieldName: String): T? {
|
||||
var c: Class<*> = instance.javaClass
|
||||
while (c != Any::class.java) {
|
||||
try {
|
||||
val field = c.getDeclaredField(fieldName)
|
||||
field.isAccessible = true
|
||||
val value = field.get(instance)
|
||||
return if (!fieldType.isInstance(value)) null else fieldType.cast(value)
|
||||
} catch (_: NoSuchFieldException) {
|
||||
}
|
||||
|
||||
c = c.superclass
|
||||
}
|
||||
|
||||
// Didn't find the field we wanted. As a last gasp attempt,
|
||||
// try to find the value on a delegate.
|
||||
if (fieldName != "delegate") {
|
||||
val delegate = readFieldOrNull(instance, Any::class.java, "delegate")
|
||||
if (delegate != null) return readFieldOrNull(delegate, fieldType, fieldName)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
package okhttp3.internal.platform.android
|
||||
|
||||
import okhttp3.internal.platform.Platform
|
||||
import okhttp3.internal.readFieldOrNull
|
||||
import javax.net.ssl.SSLSocket
|
||||
import javax.net.ssl.SSLSocketFactory
|
||||
import javax.net.ssl.X509TrustManager
|
||||
@@ -35,11 +36,11 @@ class StandardAndroidSocketAdapter(
|
||||
|
||||
override fun trustManager(sslSocketFactory: SSLSocketFactory): X509TrustManager? {
|
||||
val context: Any? =
|
||||
Platform.readFieldOrNull(sslSocketFactory, paramClass,
|
||||
readFieldOrNull(sslSocketFactory, paramClass,
|
||||
"sslParameters")
|
||||
val x509TrustManager = Platform.readFieldOrNull(
|
||||
val x509TrustManager = readFieldOrNull(
|
||||
context!!, X509TrustManager::class.java, "x509TrustManager")
|
||||
return x509TrustManager ?: Platform.readFieldOrNull(context,
|
||||
return x509TrustManager ?: readFieldOrNull(context,
|
||||
X509TrustManager::class.java,
|
||||
"trustManager")
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ import okhttp3.internal.platform.Platform;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import okhttp3.testing.PlatformRule;
|
||||
import okhttp3.tls.HandshakeCertificates;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
@@ -65,6 +66,7 @@ public final class CacheTest {
|
||||
@Rule public MockWebServer server2 = new MockWebServer();
|
||||
@Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem();
|
||||
@Rule public final OkHttpClientTestRule clientTestRule = new OkHttpClientTestRule();
|
||||
@Rule public final PlatformRule platform = new PlatformRule();
|
||||
|
||||
private final HandshakeCertificates handshakeCertificates = localhost();
|
||||
private OkHttpClient client;
|
||||
@@ -72,6 +74,8 @@ public final class CacheTest {
|
||||
private final CookieManager cookieManager = new CookieManager();
|
||||
|
||||
@Before public void setUp() throws Exception {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
server.setProtocolNegotiationEnabled(false);
|
||||
cache = new Cache(new File("/cache/"), Integer.MAX_VALUE, fileSystem);
|
||||
client = clientTestRule.newClientBuilder()
|
||||
@@ -82,8 +86,11 @@ public final class CacheTest {
|
||||
|
||||
@After public void tearDown() throws Exception {
|
||||
ResponseCache.setDefault(null);
|
||||
|
||||
if (cache != null) {
|
||||
cache.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that response caching is consistent with the RI and the spec.
|
||||
|
@@ -117,6 +117,8 @@ public final class CallTest {
|
||||
private Logger logger = Logger.getLogger(OkHttpClient.class.getName());
|
||||
|
||||
@Before public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
logger.addHandler(logHandler);
|
||||
client = clientTestRule.newClientBuilder()
|
||||
.eventListener(listener)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package okhttp3
|
||||
|
||||
import okhttp3.TestUtil.assumeNetwork
|
||||
import okhttp3.internal.platform.ConscryptPlatform
|
||||
import okhttp3.internal.platform.Platform
|
||||
import okhttp3.testing.PlatformRule
|
||||
@@ -22,13 +23,10 @@ import org.assertj.core.api.Assertions.assertThat
|
||||
import org.conscrypt.Conscrypt
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.net.InetAddress
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class ConscryptTest {
|
||||
@Suppress("RedundantVisibilityModifier")
|
||||
@@ -49,14 +47,6 @@ class ConscryptTest {
|
||||
assertThat(Conscrypt.isConscrypt(Platform.get().platformTrustManager())).isTrue()
|
||||
}
|
||||
|
||||
private fun assumeNetwork() {
|
||||
try {
|
||||
InetAddress.getByName("www.google.com")
|
||||
} catch (uhe: UnknownHostException) {
|
||||
Assume.assumeNoException(uhe)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
fun testMozilla() {
|
||||
|
@@ -54,6 +54,7 @@ public final class DuplexTest {
|
||||
private OkHttpClient client;
|
||||
|
||||
@Before public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
platform.assumeHttp2Support();
|
||||
client = clientTestRule.newClientBuilder()
|
||||
.eventListener(listener)
|
||||
|
@@ -86,6 +86,8 @@ public final class EventListenerTest {
|
||||
private SocksProxy socksProxy;
|
||||
|
||||
@Before public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
client = clientTestRule.newClientBuilder()
|
||||
.eventListener(listener)
|
||||
.build();
|
||||
|
@@ -15,23 +15,22 @@
|
||||
*/
|
||||
package okhttp3
|
||||
|
||||
import okhttp3.Protocol.HTTP_2
|
||||
import okhttp3.TestUtil.assumeNetwork
|
||||
import okhttp3.internal.platform.OpenJSSEPlatform
|
||||
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.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.openjsse.net.ssl.OpenJSSE
|
||||
import org.openjsse.sun.security.ssl.SSLSocketFactoryImpl
|
||||
import org.openjsse.sun.security.ssl.SSLSocketImpl
|
||||
import java.net.InetAddress
|
||||
import java.security.Security
|
||||
|
||||
class OpenJSSETest {
|
||||
@JvmField @Rule var platform = PlatformRule()
|
||||
@@ -41,17 +40,11 @@ class OpenJSSETest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
platform.assumeJdk8()
|
||||
platform.assumeOpenJSSE()
|
||||
|
||||
Security.insertProviderAt(OpenJSSE(), 1)
|
||||
client = clientTestRule.newClient()
|
||||
}
|
||||
|
||||
@After
|
||||
fun cleanup() {
|
||||
Security.removeProvider("OpenJSSE")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTlsv13Works() {
|
||||
enableTls()
|
||||
@@ -65,7 +58,7 @@ class OpenJSSETest {
|
||||
response.use {
|
||||
assertEquals(200, response.code)
|
||||
assertEquals(TlsVersion.TLS_1_3, response.handshake?.tlsVersion)
|
||||
assertEquals(Protocol.HTTP_1_1, response.protocol)
|
||||
assertEquals(Protocol.HTTP_2, response.protocol)
|
||||
|
||||
assertThat(response.exchange?.connection()?.socket()).isInstanceOf(SSLSocketImpl::class.java)
|
||||
}
|
||||
@@ -76,14 +69,31 @@ class OpenJSSETest {
|
||||
val factory = SSLSocketFactoryImpl()
|
||||
val s = factory.createSocket() as SSLSocketImpl
|
||||
|
||||
// A Public API available is available to use in a custom Platform
|
||||
s.setHandshakeApplicationProtocolSelector { _, _ -> HTTP_2.toString() }
|
||||
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_2)
|
||||
assertThat(it.handshake!!.tlsVersion).isEqualTo(TlsVersion.TLS_1_3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBuildIfSupported() {
|
||||
val actual = OpenJSSEPlatform.buildIfSupported()
|
||||
assertThat(actual).isNotNull
|
||||
}
|
||||
|
||||
private fun enableTls() {
|
||||
// Generate a self-signed cert for the server to serve and the client to trust.
|
||||
// can't use localhost with a non OpenJSSE trust manager
|
||||
// can't use TlsUtil.localhost with a non OpenJSSE trust manager
|
||||
val heldCertificate = HeldCertificate.Builder()
|
||||
.commonName("localhost")
|
||||
.addSubjectAlternativeName(InetAddress.getByName("localhost").canonicalHostName)
|
||||
|
@@ -129,6 +129,8 @@ public final class HttpOverHttp2Test {
|
||||
}
|
||||
|
||||
@Before public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
if (protocol == Protocol.HTTP_2) {
|
||||
platform.assumeHttp2Support();
|
||||
server.useHttps(handshakeCertificates.sslSocketFactory(), false);
|
||||
|
@@ -65,6 +65,8 @@ public final class ClientAuthTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
serverRootCa = new HeldCertificate.Builder()
|
||||
.serialNumber(1L)
|
||||
.certificateAuthority(1)
|
||||
|
@@ -42,6 +42,7 @@ import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import okhttp3.mockwebserver.SocketPolicy;
|
||||
import okhttp3.testing.Flaky;
|
||||
import okhttp3.testing.PlatformRule;
|
||||
import okhttp3.tls.HandshakeCertificates;
|
||||
import okio.Buffer;
|
||||
import okio.ByteString;
|
||||
@@ -65,6 +66,7 @@ public final class WebSocketHttpTest {
|
||||
|
||||
@Rule public final MockWebServer webServer = new MockWebServer();
|
||||
@Rule public final OkHttpClientTestRule clientTestRule = new OkHttpClientTestRule();
|
||||
@Rule public final PlatformRule platform = new PlatformRule();
|
||||
|
||||
private final HandshakeCertificates handshakeCertificates = localhost();
|
||||
private final WebSocketRecorder clientListener = new WebSocketRecorder("client");
|
||||
@@ -73,6 +75,8 @@ public final class WebSocketHttpTest {
|
||||
private OkHttpClient client;
|
||||
|
||||
@Before public void setUp() {
|
||||
platform.assumeNotOpenJSSE();
|
||||
|
||||
client = clientTestRule.newClientBuilder()
|
||||
.writeTimeout(500, TimeUnit.MILLISECONDS)
|
||||
.readTimeout(500, TimeUnit.MILLISECONDS)
|
||||
|
Reference in New Issue
Block a user