Skip to content

Commit 53fa31a

Browse files
authored
KTOR-6229 Fix hostname verification in CIO (#3746)
1 parent 2fa5881 commit 53fa31a

File tree

25 files changed

+535
-308
lines changed

25 files changed

+535
-308
lines changed

buildSrc/src/main/kotlin/test/server/TestServer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ internal fun startServer(): Closeable {
2828
tests()
2929
}.start()
3030

31-
scope.use(Closeable { server.stop(0L, 0L, TimeUnit.MILLISECONDS) })
31+
scope.use { server.stop(0L, 0L, TimeUnit.MILLISECONDS) }
3232

3333
val tlsServer = setupTLSServer()
3434
tlsServer.start()
35-
scope.use(Closeable { tlsServer.stop(0L, 0L, TimeUnit.MILLISECONDS) })
35+
scope.use { tlsServer.stop(0L, 0L, TimeUnit.MILLISECONDS) }
3636

3737
Thread.sleep(1000)
3838
} catch (cause: Throwable) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.client.engine.android
6+
7+
import io.ktor.client.tests.*
8+
9+
class AndroidHttpClientTest : HttpClientTest(Android)

ktor-client/ktor-client-android/jvm/test/io/ktor/client/engine/android/AndroidHttpsTest.kt

Lines changed: 10 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,102 +4,23 @@
44

55
package io.ktor.client.engine.android
66

7-
import io.ktor.client.*
8-
import io.ktor.client.call.*
9-
import io.ktor.client.engine.*
10-
import io.ktor.client.request.*
11-
import io.ktor.client.tests.utils.*
12-
import io.ktor.network.tls.certificates.*
13-
import io.ktor.network.tls.extensions.*
14-
import io.ktor.server.application.*
15-
import io.ktor.server.engine.*
16-
import io.ktor.server.netty.*
17-
import io.ktor.server.response.*
18-
import io.ktor.server.routing.*
19-
import io.ktor.util.*
20-
import kotlinx.coroutines.*
21-
import org.junit.*
22-
import java.io.*
23-
import java.security.*
7+
import io.ktor.client.tests.*
248
import javax.net.ssl.*
259
import kotlin.test.*
26-
import kotlin.test.Test
2710

28-
class AndroidHttpsTest : TestWithKtor() {
29-
override val server: ApplicationEngine = embeddedServer(
30-
Netty,
31-
applicationEngineEnvironment {
32-
sslConnector(keyStore, "sha256ecdsa", { "changeit".toCharArray() }, { "changeit".toCharArray() }) {
33-
port = serverPort
34-
keyStorePath = keyStoreFile.absoluteFile
11+
class AndroidHttpsTest : HttpsTest<AndroidEngineConfig>(Android) {
3512

36-
module {
37-
routing {
38-
get("/") {
39-
call.respondText("Hello, world")
40-
}
41-
}
42-
}
43-
}
44-
}
45-
)
46-
47-
companion object {
48-
val keyStoreFile = File("build/temp.jks")
49-
lateinit var keyStore: KeyStore
50-
lateinit var sslContext: SSLContext
51-
private lateinit var x509TrustManager: X509TrustManager
13+
private var defaultSslSocketFactory: SSLSocketFactory? = null
5214

53-
@BeforeClass
54-
@JvmStatic
55-
fun setupAll() {
56-
keyStore = buildKeyStore {
57-
certificate("sha384ecdsa") {
58-
hash = HashAlgorithm.SHA384
59-
sign = SignatureAlgorithm.ECDSA
60-
keySizeInBits = 384
61-
password = "changeit"
62-
}
63-
certificate("sha256ecdsa") {
64-
hash = HashAlgorithm.SHA256
65-
sign = SignatureAlgorithm.ECDSA
66-
keySizeInBits = 256
67-
password = "changeit"
68-
}
69-
certificate("sha384rsa") {
70-
hash = HashAlgorithm.SHA384
71-
sign = SignatureAlgorithm.RSA
72-
keySizeInBits = 1024
73-
password = "changeit"
74-
}
75-
certificate("sha1rsa") {
76-
hash = HashAlgorithm.SHA1
77-
sign = SignatureAlgorithm.RSA
78-
keySizeInBits = 1024
79-
password = "changeit"
80-
}
81-
}
82-
83-
keyStore.saveToFile(keyStoreFile, "changeit")
84-
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
85-
tmf.init(keyStore)
86-
sslContext = SSLContext.getInstance("TLS")
87-
sslContext.init(null, tmf.trustManagers, null)
88-
x509TrustManager = tmf.trustManagers.first { it is X509TrustManager } as X509TrustManager
89-
}
15+
override fun AndroidEngineConfig.disableCertificatePinning() {
16+
defaultSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory()
17+
HttpsURLConnection.setDefaultSSLSocketFactory(unsafeSslContext.socketFactory)
9018
}
9119

92-
@Test
93-
fun hello(): Unit = runBlocking {
94-
HttpClient(
95-
Android.config {
96-
sslManager = { conn ->
97-
conn.sslSocketFactory = sslContext.socketFactory
98-
}
99-
}
100-
).use { client ->
101-
val actual = client.get("https://127.0.0.1:$serverPort/").body<String>()
102-
assertEquals("Hello, world", actual)
20+
@AfterTest
21+
fun tearDown() {
22+
defaultSslSocketFactory?.let {
23+
HttpsURLConnection.setDefaultSSLSocketFactory(it)
10324
}
10425
}
10526
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2014-2023 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.client.engine.android
6+
7+
import io.ktor.client.*
8+
import io.ktor.client.call.*
9+
import io.ktor.client.engine.*
10+
import io.ktor.client.request.*
11+
import io.ktor.client.tests.utils.*
12+
import io.ktor.network.tls.certificates.*
13+
import io.ktor.network.tls.extensions.*
14+
import io.ktor.server.engine.*
15+
import io.ktor.server.netty.*
16+
import io.ktor.server.response.*
17+
import io.ktor.server.routing.*
18+
import kotlinx.coroutines.*
19+
import org.junit.*
20+
import java.io.*
21+
import java.security.*
22+
import javax.net.ssl.*
23+
import kotlin.test.*
24+
import kotlin.test.Test
25+
26+
class AndroidSpecificHttpsTest : TestWithKtor() {
27+
override val server: ApplicationEngine = embeddedServer(
28+
Netty,
29+
applicationEngineEnvironment {
30+
sslConnector(keyStore, "sha256ecdsa", { "changeit".toCharArray() }, { "changeit".toCharArray() }) {
31+
port = serverPort
32+
keyStorePath = keyStoreFile.absoluteFile
33+
34+
module {
35+
routing {
36+
get("/") {
37+
call.respondText("Hello, world")
38+
}
39+
}
40+
}
41+
}
42+
}
43+
)
44+
45+
companion object {
46+
val keyStoreFile = File("build/temp.jks")
47+
lateinit var keyStore: KeyStore
48+
lateinit var sslContext: SSLContext
49+
private lateinit var x509TrustManager: X509TrustManager
50+
51+
@BeforeClass
52+
@JvmStatic
53+
fun setupAll() {
54+
keyStore = buildKeyStore {
55+
certificate("sha384ecdsa") {
56+
hash = HashAlgorithm.SHA384
57+
sign = SignatureAlgorithm.ECDSA
58+
keySizeInBits = 384
59+
password = "changeit"
60+
}
61+
certificate("sha256ecdsa") {
62+
hash = HashAlgorithm.SHA256
63+
sign = SignatureAlgorithm.ECDSA
64+
keySizeInBits = 256
65+
password = "changeit"
66+
}
67+
certificate("sha384rsa") {
68+
hash = HashAlgorithm.SHA384
69+
sign = SignatureAlgorithm.RSA
70+
keySizeInBits = 1024
71+
password = "changeit"
72+
}
73+
certificate("sha1rsa") {
74+
hash = HashAlgorithm.SHA1
75+
sign = SignatureAlgorithm.RSA
76+
keySizeInBits = 1024
77+
password = "changeit"
78+
}
79+
}
80+
81+
keyStore.saveToFile(keyStoreFile, "changeit")
82+
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
83+
tmf.init(keyStore)
84+
sslContext = SSLContext.getInstance("TLS")
85+
sslContext.init(null, tmf.trustManagers, null)
86+
x509TrustManager = tmf.trustManagers.first { it is X509TrustManager } as X509TrustManager
87+
}
88+
}
89+
90+
@Test
91+
fun hello(): Unit = runBlocking {
92+
HttpClient(
93+
Android.config {
94+
sslManager = { conn ->
95+
conn.sslSocketFactory = sslContext.socketFactory
96+
}
97+
}
98+
).use { client ->
99+
val actual = client.get("https://127.0.0.1:$serverPort/").body<String>()
100+
assertEquals("Hello, world", actual)
101+
}
102+
}
103+
}

ktor-client/ktor-client-android/jvm/test/io/ktor/client/engine/android/CommonTests.kt

Lines changed: 0 additions & 26 deletions
This file was deleted.

ktor-client/ktor-client-apache/jvm/test/io/ktor/client/engine/apache/CommonTests.kt renamed to ktor-client/ktor-client-apache/jvm/test/io/ktor/client/engine/apache/ApacheHttpClientTest.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,3 @@ package io.ktor.client.engine.apache
77
import io.ktor.client.tests.*
88

99
class ApacheHttpClientTest : HttpClientTest(Apache)
10-
11-
class ApacheSslOverProxyTest : SslOverProxyTest<ApacheEngineConfig>(Apache) {
12-
13-
override fun ApacheEngineConfig.disableCertificatePinning() {
14-
this.sslContext = this@ApacheSslOverProxyTest.unsafeSslContext
15-
}
16-
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2014-2023 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.client.engine.apache
6+
7+
import io.ktor.client.tests.*
8+
9+
class ApacheHttpsTest : HttpsTest<ApacheEngineConfig>(Apache) {
10+
11+
override fun ApacheEngineConfig.disableCertificatePinning() {
12+
this.sslContext = this@ApacheHttpsTest.unsafeSslContext
13+
}
14+
}

ktor-client/ktor-client-apache5/jvm/test/io/ktor/client/engine/apache5/CommonTests.kt renamed to ktor-client/ktor-client-apache5/jvm/test/io/ktor/client/engine/apache5/Apache5HttpClientTest.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,3 @@ package io.ktor.client.engine.apache5
77
import io.ktor.client.tests.*
88

99
class Apache5HttpClientTest : HttpClientTest(Apache5)
10-
11-
class Apache5SslOverProxyTest : SslOverProxyTest<Apache5EngineConfig>(Apache5) {
12-
13-
override fun Apache5EngineConfig.disableCertificatePinning() {
14-
this.sslContext = this@Apache5SslOverProxyTest.unsafeSslContext
15-
}
16-
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2014-2023 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.client.engine.apache5
6+
7+
import io.ktor.client.tests.*
8+
9+
class Apache5HttpsTest : HttpsTest<Apache5EngineConfig>(Apache5) {
10+
11+
override fun Apache5EngineConfig.disableCertificatePinning() {
12+
this.sslContext = this@Apache5HttpsTest.unsafeSslContext
13+
}
14+
}

ktor-client/ktor-client-cio/jvm/test/io/ktor/client/engine/cio/CommonTests.kt renamed to ktor-client/ktor-client-cio/jvm/test/io/ktor/client/engine/cio/CIOHttpClientTest.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,3 @@ package io.ktor.client.engine.cio
77
import io.ktor.client.tests.*
88

99
class CIOHttpClientTest : HttpClientTest(CIO)
10-
11-
class CIOSslOverProxyTest : SslOverProxyTest<CIOEngineConfig>(CIO) {
12-
13-
override fun CIOEngineConfig.disableCertificatePinning() {
14-
https {
15-
trustManager = trustAllCertificates[0]
16-
}
17-
}
18-
}

0 commit comments

Comments
 (0)