I need to crawl internal company site that has expired/self-signed certificate. Noone is ever going to configure valid certificate for that host, so I have to use insecure connection.
curl
has --insecure
flag for that purpose,
Scala finagle library has .tlsWithoutValidation()
mode.
QUESTION: Is there a Kotlin library that has similar option?
UPD: so far I am using Fuel with the javish workaround found here but still searching for better ways..
fun useInsecureSSL() {
// Create a trust manager that does not validate certificate chains
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate>? = null
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) = Unit
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) = Unit
})
val sc = SSLContext.getInstance("SSL")
sc.init(null, trustAllCerts, java.security.SecureRandom())
HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)
// Create all-trusting host name verifier
val allHostsValid = HostnameVerifier { _, _ -> true }
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid)
}
The above workaround works however it is too verbose and seems to set insecure mode for every connection made by my app, not only for the particular one.
Fuel allows you to create your own instance of the Fuel client through the FuelManager
class. The manager lets you can set your own HostnameVerifier
and SSLSocketFactory
and then creates a client with those configured. See https://github.com/kittinunf/Fuel/blob/1.16.0/fuel/src/main/kotlin/com/github/kittinunf/fuel/core/FuelManager.kt#L31-L43
val manager : FuelManager = FuelManager().apply {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate>? = null
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) = Unit
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) = Unit
})
socketFactory = SSLContext.getInstance("SSL").apply {
init(null, trustAllCerts, java.security.SecureRandom())
}.socketFactory
hostnameVerifier = HostnameVerifier { _, _ -> true }
}
Then to check that only connections that goes through this custom FuelManager
is untrusted and connections that don't are trusted, we do this:
val (_, untrustedResp, untrustedResult) = manager.request(Method.GET, "https://internal/company/site").response()
assert(untrustedResp.statusCode == 200)
val (bytes, _) = untrustedResult
assert(bytes != null)
val (_, trustedResp, trustedResult) = "https://internal/company/site".httpGet().response()
assert(trustedResp.statusCode != 200)
val (bytes, error) = trustedResult
assert(bytes == null)
println(error) // javax.net.ssl.SSLHandshakeException: PKIX path building failed: ...
The custom FuelManager
was able to make the request successfully because it trusts all certs but for the connection that didn't use the custom manager, we can see that it returns with javax.net.ssl.SSLHandshakeException
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With