Skip to content

Instantly share code, notes, and snippets.

@gabin8
Created February 13, 2019 20:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabin8/9459d0a00ffdf40ed023a0cf85a5d58e to your computer and use it in GitHub Desktop.
Save gabin8/9459d0a00ffdf40ed023a0cf85a5d58e to your computer and use it in GitHub Desktop.
package com.example.android.kotlincoroutines.ktor
import android.os.Build
import android.util.Log
import okhttp3.OkHttpClient
import okhttp3.TlsVersion
import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.net.UnknownHostException
import java.security.KeyStore
import javax.net.ssl.*
/**
* Extension function for TLS Support on pre-lollipop.
*/
private val trustManager by lazy {
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(null as KeyStore?)
trustManagerFactory.trustManagers
.first { it is X509TrustManager } as X509TrustManager
}
fun OkHttpClient.Builder.enableTlsOnPreLollipop() = apply {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
try {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf(trustManager), null)
sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManager)
} catch (e: Exception) {
Log.e("Tls12SocketFactory", "Error while setting TLS compatibility")
}
}
}
class Tls12SocketFactory(private val delegate: SSLSocketFactory) : SSLSocketFactory() {
/**
* Forcefully adds [TlsVersion.TLS_1_2] as an enabled protocol if called on an [SSLSocket]
*
* @return the (potentially modified) [Socket]
*/
private fun Socket.patchForTls12(): Socket {
return (this as? SSLSocket)?.apply {
enabledProtocols += TlsVersion.TLS_1_1.javaName()
enabledProtocols += TlsVersion.TLS_1_2.javaName()
} ?: this
}
override fun getDefaultCipherSuites(): Array<String> {
return delegate.defaultCipherSuites
}
override fun getSupportedCipherSuites(): Array<String> {
return delegate.supportedCipherSuites
}
@Throws(IOException::class)
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? {
return delegate.createSocket(s, host, port, autoClose)
.patchForTls12()
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int): Socket? {
return delegate.createSocket(host, port)
.patchForTls12()
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? {
return delegate.createSocket(host, port, localHost, localPort)
.patchForTls12()
}
@Throws(IOException::class)
override fun createSocket(host: InetAddress, port: Int): Socket? {
return delegate.createSocket(host, port)
.patchForTls12()
}
@Throws(IOException::class)
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? {
return delegate.createSocket(address, port, localAddress, localPort)
.patchForTls12()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment