diff --git a/kmp-socketio/src/appleMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt b/kmp-socketio/src/appleMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt index e3ed715..ff16810 100644 --- a/kmp-socketio/src/appleMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt +++ b/kmp-socketio/src/appleMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt @@ -1,9 +1,28 @@ package com.piasy.kmp.socketio.engineio.transports -import io.ktor.client.HttpClientConfig import io.ktor.client.HttpClient +import io.ktor.client.HttpClientConfig import io.ktor.client.engine.darwin.Darwin +import platform.Foundation.NSURLCredential +import platform.Foundation.NSURLSessionAuthChallengePerformDefaultHandling +import platform.Foundation.NSURLSessionAuthChallengeUseCredential +import platform.Foundation.create +import platform.Foundation.serverTrust +import platform.Security.SecTrustRef -actual fun httpClient(config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Darwin) { +actual fun httpClient(trustAllCerts: Boolean, config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Darwin) { config(this) + engine { + if (trustAllCerts) { + handleChallenge { session, task, challenge, completionHandler -> + val serverTrust: SecTrustRef? = challenge.protectionSpace.serverTrust + if (serverTrust != null) { + val credential = NSURLCredential.create(trust = serverTrust) + completionHandler(NSURLSessionAuthChallengeUseCredential.toLong(), credential) + } else { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling.toLong(), null) + } + } + } + } } diff --git a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/EngineSocket.kt b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/EngineSocket.kt index de60b0c..9d12fd3 100644 --- a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/EngineSocket.kt +++ b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/EngineSocket.kt @@ -217,6 +217,7 @@ class EngineSocket( opts.timestampRequests = options?.timestampRequests ?: opt.timestampRequests opts.timestampParam = options?.timestampParam ?: opt.timestampParam opts.extraHeaders = opt.extraHeaders + opts.trustAllCerts = opt.trustAllCerts val transport = factory.create(name, opts, scope, rawMessage) emit(EVENT_TRANSPORT, transport) diff --git a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/Transport.kt b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/Transport.kt index 9ce32a7..51770c4 100644 --- a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/Transport.kt +++ b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/Transport.kt @@ -39,6 +39,9 @@ abstract class Transport( @JvmField var extraHeaders: Map> = emptyMap() + + @JvmField + var trustAllCerts: Boolean = false } protected var state = State.INIT diff --git a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/PollingXHR.kt b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/PollingXHR.kt index ef0b31e..6978134 100644 --- a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/PollingXHR.kt +++ b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/PollingXHR.kt @@ -17,7 +17,7 @@ open class PollingXHR( opt: Options, scope: CoroutineScope, private val ioScope: CoroutineScope = CoroutineScope(Dispatchers.Default), - private val factory: HttpClientFactory = DefaultHttpClientFactory, + private val factory: HttpClientFactory = DefaultHttpClientFactory(trustAllCerts = opt.trustAllCerts), rawMessage: Boolean, ) : Transport(opt, scope, NAME, rawMessage) { private var polling = false diff --git a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/WebSocket.kt b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/WebSocket.kt index e97e325..f24a23c 100644 --- a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/WebSocket.kt +++ b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/WebSocket.kt @@ -23,7 +23,7 @@ open class WebSocket( opt: Options, scope: CoroutineScope, private val ioScope: CoroutineScope = CoroutineScope(Dispatchers.Default), - private val factory: HttpClientFactory = DefaultHttpClientFactory, + private val factory: HttpClientFactory = DefaultHttpClientFactory(trustAllCerts = opt.trustAllCerts), rawMessage: Boolean, ) : Transport(opt, scope, NAME, rawMessage) { private var ws: DefaultClientWebSocketSession? = null diff --git a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport.kt b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport.kt index c0869be..c117bb5 100644 --- a/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport.kt +++ b/kmp-socketio/src/commonMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport.kt @@ -11,7 +11,7 @@ import io.ktor.client.statement.* import io.ktor.http.* import kotlinx.coroutines.CoroutineScope -expect fun httpClient(config: HttpClientConfig<*>.() -> Unit = {}): HttpClient +expect fun httpClient(trustAllCerts: Boolean = false, config: HttpClientConfig<*>.() -> Unit = {}): HttpClient internal fun putHeaders( builder: HeadersBuilder, @@ -59,8 +59,12 @@ interface HttpClientFactory { ): HttpResponse } -object DefaultHttpClientFactory : HttpClientFactory { - private val wsClient = httpClient { +class DefaultHttpClientFactory( + trustAllCerts: Boolean = false, +): HttpClientFactory { + private val wsClient = httpClient( + trustAllCerts = trustAllCerts, + ) { install(Logging) { logger = object : Logger { override fun log(message: String) { @@ -76,7 +80,9 @@ object DefaultHttpClientFactory : HttpClientFactory { // Linux curl engine doesn't work for simultaneous websocket and http request. // see https://youtrack.jetbrains.com/issue/KTOR-8259/ // Use two http client could work around it. - private val httpClient: HttpClient = if (!Platform.isLinux) wsClient else httpClient { + private val httpClient: HttpClient = if (!Platform.isLinux) wsClient else httpClient( + trustAllCerts = trustAllCerts, + ) { install(Logging) { logger = object : Logger { override fun log(message: String) { diff --git a/kmp-socketio/src/jsMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt b/kmp-socketio/src/jsMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt index 85a59f7..1f79d3c 100644 --- a/kmp-socketio/src/jsMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt +++ b/kmp-socketio/src/jsMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt @@ -4,6 +4,7 @@ import io.ktor.client.HttpClientConfig import io.ktor.client.HttpClient import io.ktor.client.engine.js.Js -actual fun httpClient(config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Js) { +actual fun httpClient(trustAllCerts: Boolean, config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Js) { config(this) + /** Ignore `unsafeClient` variable */ } diff --git a/kmp-socketio/src/jvmMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt b/kmp-socketio/src/jvmMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt index c5485c1..251b2ab 100644 --- a/kmp-socketio/src/jvmMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt +++ b/kmp-socketio/src/jvmMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt @@ -3,7 +3,22 @@ package com.piasy.kmp.socketio.engineio.transports import io.ktor.client.HttpClientConfig import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO +import java.security.cert.X509Certificate +import javax.net.ssl.X509TrustManager -actual fun httpClient(config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(CIO) { +actual fun httpClient(trustAllCerts: Boolean, config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(CIO) { config(this) + if (trustAllCerts) { + engine { + https { + trustManager = object: X509TrustManager { + override fun checkClientTrusted(p0: Array?, p1: String?) { } + + override fun checkServerTrusted(p0: Array?, p1: String?) { } + + override fun getAcceptedIssuers(): Array? = null + } + } + } + } } diff --git a/kmp-socketio/src/jvmTest/kotlin/com/piasy/kmp/socketio/engineio/TestUtil.kt b/kmp-socketio/src/jvmTest/kotlin/com/piasy/kmp/socketio/engineio/TestUtil.kt index 579a3ba..9aecddc 100644 --- a/kmp-socketio/src/jvmTest/kotlin/com/piasy/kmp/socketio/engineio/TestUtil.kt +++ b/kmp-socketio/src/jvmTest/kotlin/com/piasy/kmp/socketio/engineio/TestUtil.kt @@ -17,7 +17,7 @@ object TestUtil { fun transportFactory() = DefaultTransportFactory @JvmStatic - fun httpFactory() = DefaultHttpClientFactory + fun httpFactory() = DefaultHttpClientFactory() @JvmStatic fun getOpt(socket: EngineSocket) = socket.opt diff --git a/kmp-socketio/src/linuxMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt b/kmp-socketio/src/linuxMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt index 8fcdd99..4ec1c7d 100644 --- a/kmp-socketio/src/linuxMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt +++ b/kmp-socketio/src/linuxMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt @@ -4,6 +4,11 @@ import io.ktor.client.HttpClientConfig import io.ktor.client.HttpClient import io.ktor.client.engine.curl.Curl -actual fun httpClient(config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Curl) { +actual fun httpClient(trustAllCerts: Boolean, config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(Curl) { config(this) + if (trustAllCerts) { + engine { + sslVerify = false + } + } } diff --git a/kmp-socketio/src/mingwMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt b/kmp-socketio/src/mingwMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt index 3664d50..7a719d9 100644 --- a/kmp-socketio/src/mingwMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt +++ b/kmp-socketio/src/mingwMain/kotlin/com/piasy/kmp/socketio/engineio/transports/transport_impl.kt @@ -4,6 +4,11 @@ import io.ktor.client.HttpClientConfig import io.ktor.client.HttpClient import io.ktor.client.engine.winhttp.WinHttp -actual fun httpClient(config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(WinHttp) { +actual fun httpClient(trustAllCerts: Boolean, config: HttpClientConfig<*>.() -> Unit): HttpClient = HttpClient(WinHttp) { config(this) + if (trustAllCerts) { + engine { + sslVerify = false + } + } }