1
0
mirror of https://github.com/etesync/android synced 2024-11-22 07:58:09 +00:00

SSLSocketFactory: import newer settings from DAVDroid.

This commit is contained in:
Tom Hacohen 2019-01-05 16:52:15 +00:00
parent 1901cf1bb1
commit f46bccab8e

View File

@ -8,17 +8,12 @@
package com.etesync.syncadapter package com.etesync.syncadapter
import android.text.TextUtils import android.os.Build
import java.io.IOException import java.io.IOException
import java.net.InetAddress import java.net.InetAddress
import java.net.Socket import java.net.Socket
import java.security.GeneralSecurityException import java.security.GeneralSecurityException
import java.util.Arrays import java.util.*
import java.util.HashSet
import java.util.LinkedList
import java.util.Locale
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory import javax.net.ssl.SSLSocketFactory
@ -97,75 +92,77 @@ class SSLSocketFactoryCompat(trustManager: X509TrustManager) : SSLSocketFactory(
} }
companion object { companion object {
// Android 5.0+ (API level 21) provides reasonable default settings
// Android 5.0+ (API level21) provides reasonable default settings
// but it still allows SSLv3 // but it still allows SSLv3
// https://developer.android.com/reference/javax/net/ssl/SSLSocket.html // https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
internal var protocols: Array<String>? = null var protocols: Array<String>? = null
internal var cipherSuites: Array<String>? = null var cipherSuites: Array<String>? = null
init { init {
try { if (Build.VERSION.SDK_INT >= 23) {
val socket = SSLSocketFactory.getDefault().createSocket() as SSLSocket // Since Android 6.0 (API level 23),
if (socket != null) { // - TLSv1.1 and TLSv1.2 is enabled by default
/* set reasonable protocol versions */ // - SSLv3 is disabled by default
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) // - all modern ciphers are activated by default
// - remove all SSL versions (especially SSLv3) because they're insecure now protocols = null
val protocols = LinkedList<String>() cipherSuites = null
for (protocol in socket.supportedProtocols) App.log.fine("Using device default TLS protocols/ciphers")
if (!protocol.toUpperCase(Locale.US).contains("SSL")) } else {
protocols.add(protocol) (SSLSocketFactory.getDefault().createSocket() as? SSLSocket)?.use { socket ->
App.log.info("Setting allowed TLS protocols: " + TextUtils.join(", ", protocols)) try {
SSLSocketFactoryCompat.protocols = protocols.toTypedArray() /* set reasonable protocol versions */
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
// - remove all SSL versions (especially SSLv3) because they're insecure now
val whichProtocols = LinkedList<String>()
for (protocol in socket.supportedProtocols.filterNot { it.contains("SSL", true) })
whichProtocols += protocol
App.log.info("Enabling (only) these TLS protocols: ${whichProtocols.joinToString(", ")}")
protocols = whichProtocols.toTypedArray()
/* set up reasonable cipher suites */ /* set up reasonable cipher suites */
// choose known secure cipher suites val knownCiphers = arrayOf(
val allowedCiphers = Arrays.asList( // TLS 1.2
// first priority "TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", // maximum interoperability
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
// second priority "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", // additionally
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
// compat "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", )
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" val availableCiphers = socket.supportedCipherSuites
) App.log.info("Available cipher suites: ${availableCiphers.joinToString(", ")}")
val availableCiphers = Arrays.asList(*socket.supportedCipherSuites)
App.log.info("Available cipher suites: " + TextUtils.join(", ", availableCiphers))
/* For maximum security, preferredCiphers should *replace* enabled ciphers (thus /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus
* disabling ciphers which are enabled by default, but have become unsecure), but for * disabling ciphers which are enabled by default, but have become unsecure), but for
* the security level of DAVdroid and maximum compatibility, disabling of insecure * the security level of DAVx5 and maximum compatibility, disabling of insecure
* ciphers should be a server-side task */ * ciphers should be a server-side task */
// for the final set of enabled ciphers, take the ciphers enabled by default, ... // for the final set of enabled ciphers, take the ciphers enabled by default, ...
val enabledCiphers = HashSet(Arrays.asList(*socket.enabledCipherSuites)) val whichCiphers = LinkedList<String>()
App.log.info("Cipher suites enabled by default: " + TextUtils.join(", ", enabledCiphers)) whichCiphers.addAll(socket.enabledCipherSuites)
// ... add explicitly allowed ciphers ... App.log.fine("Cipher suites enabled by default: ${whichCiphers.joinToString(", ")}")
enabledCiphers.addAll(allowedCiphers) // ... add explicitly allowed ciphers ...
// ... and keep only those which are actually available whichCiphers.addAll(knownCiphers)
enabledCiphers.retainAll(availableCiphers) // ... and keep only those which are actually available
whichCiphers.retainAll(availableCiphers)
App.log.info("Enabling (only) those TLS ciphers: " + TextUtils.join(", ", enabledCiphers)) App.log.info("Enabling (only) these TLS ciphers: " + whichCiphers.joinToString(", "))
SSLSocketFactoryCompat.cipherSuites = enabledCiphers.toTypedArray() cipherSuites = whichCiphers.toTypedArray()
socket.close() } catch (e: IOException) {
App.log.severe("Couldn't determine default TLS settings")
}
} }
} catch (e: IOException) {
App.log.severe("Couldn't determine default TLS settings")
} }
} }
} }
} }