tls config changes

This commit is contained in:
Jonathan Fisher 2020-11-11 12:22:48 +00:00
parent 50cf425a5b
commit ab6635af69
3 changed files with 112 additions and 53 deletions

View File

@ -11,24 +11,27 @@ object DummyTrustManager {
fun get(): Array<TrustManager> {
return arrayOf(
object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(
chain: Array<X509Certificate?>?,
chain: Array<out X509Certificate>?,
authType: String?
) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(
chain: Array<X509Certificate?>?,
chain: Array<out X509Certificate>?,
authType: String?
) {
println("checkServerTrusted()")
println("checkServerTrusted() authType: $authType")
chain?.forEach { cert ->
println("checkServerTrusted() cert: ${cert.subjectDN}")
}
}
override fun getAcceptedIssuers(): Array<X509Certificate?>? {
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
}
)
})
}
}

View File

@ -22,7 +22,8 @@ const val GEMINI_SCHEME = "gemini"
*
*/
class GeminiDatasource(
private val context: Context): Datasource {
private val context: Context
): Datasource {
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
private var last: URI? = null
@ -38,7 +39,7 @@ class GeminiDatasource(
when (uri.scheme) {
GEMINI_SCHEME -> {
val cached = RuntimeCache.get(uri)
if(cached != null){
if (cached != null) {
last = uri
onUpdate(
GemState.ResponseGemtext(
@ -48,7 +49,7 @@ class GeminiDatasource(
)
)
return
}else{
} else {
onUpdate(GemState.Requesting(uri))
GlobalScope.launch {
@ -71,7 +72,10 @@ class GeminiDatasource(
!address.contains("://") -> {
//looks like a relative link
val lastAddress = last.toString()
val relAddress = "${lastAddress.substring(0, lastAddress.lastIndexOf("/") + 1)}$address"
val relAddress = "${lastAddress.substring(
0,
lastAddress.lastIndexOf("/") + 1
)}$address"
URI.create(relAddress)
}
else -> {
@ -104,26 +108,6 @@ class GeminiDatasource(
https://framagit.org/waweic/gemini-client/-/blob/master/app/src/main/java/rocks/ism/decentral/geminiclient/GeminiConnection.kt
*
*/
private val trustAllCerts: Array<TrustManager> = arrayOf(object : X509TrustManager {
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
println("checkServerTrusted()")
println("checkServerTrusted() authType: $authType")
chain?.forEach { cert ->
println("checkServerTrusted() cert: ${cert.subjectDN}")
}
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
})
private fun geminiRequest(uri: URI, onUpdate: (state: GemState) -> Unit){
last = uri
val port = if(uri.port == -1) 1965 else uri.port
@ -132,23 +116,28 @@ class GeminiDatasource(
println("REQ_PROTOCOL: $protocol")
val sslContext = SSLContext.getInstance(protocol)
sslContext.init(null, trustAllCerts, SecureRandom())
//todo - extract and reuse this
val sslContext = if(protocol == "TLS_ALL"){
SSLContext.getInstance("TLS")
}else{
SSLContext.getInstance(protocol)
}
sslContext.init(null, DummyTrustManager.get(), null)
val factory: SSLSocketFactory = sslContext.socketFactory
val socket: SSLSocket?
try {
socket = factory.createSocket(uri.host, port) as SSLSocket
socket.enabledCipherSuites = factory.supportedCipherSuites
when (protocol) {
"TLS" -> socket.enabledProtocols = socket.supportedProtocols
"TLS" -> {}//Use default enabled protocols
"TLS_ALL" -> socket.enabledProtocols = socket.supportedProtocols
else -> socket.enabledProtocols = arrayOf(protocol)
}
socket.startHandshake()
}catch(ce: ConnectException){
}catch (ce: ConnectException){
println("socket error: $ce")
onUpdate(
GemState.ResponseError(
@ -159,7 +148,7 @@ class GeminiDatasource(
)
)
return
}catch(she: SSLHandshakeException){
}catch (she: SSLHandshakeException){
println("socket error: $she")
onUpdate(
GemState.ResponseError(
@ -209,7 +198,12 @@ class GeminiDatasource(
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
header.code == GeminiResponse.REDIRECT -> request(URI.create(header.meta), onUpdate)
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
header.meta.startsWith("text/gemini") -> getGemtext(bufferedReader, uri, header, onUpdate)
header.meta.startsWith("text/gemini") -> getGemtext(
bufferedReader,
uri,
header,
onUpdate
)
header.meta.startsWith("text/") -> getString(socket, uri, header, onUpdate)
header.meta.startsWith("image/") -> getBinary(socket, uri, header, onUpdate)
header.meta.startsWith("audio/") -> getBinary(socket, uri, header, onUpdate)
@ -228,7 +222,12 @@ class GeminiDatasource(
socket.close()
}
private fun getGemtext(reader: BufferedReader, uri: URI, header: GeminiResponse.Header, onUpdate: (state: GemState) -> Unit){
private fun getGemtext(
reader: BufferedReader,
uri: URI,
header: GeminiResponse.Header,
onUpdate: (state: GemState) -> Unit
){
val lines = mutableListOf<String>()
@ -243,22 +242,53 @@ class GeminiDatasource(
onUpdate(GemState.ResponseGemtext(uri, header, processed))
}
private fun getString(socket: SSLSocket?, uri: URI, header: GeminiResponse.Header, onUpdate: (state: GemState) -> Unit){
private fun getString(
socket: SSLSocket?,
uri: URI,
header: GeminiResponse.Header,
onUpdate: (state: GemState) -> Unit
){
val content = socket?.inputStream?.bufferedReader().use { reader -> reader?.readText() }
socket?.close()
onUpdate(GemState.ResponseText(uri, header, content ?: "Error fetching content"))
}
private fun getBinary(socket: SSLSocket?, uri: URI, header: GeminiResponse.Header, onUpdate: (state: GemState) -> Unit){
private fun getBinary(
socket: SSLSocket?,
uri: URI,
header: GeminiResponse.Header,
onUpdate: (state: GemState) -> Unit
){
val filenameRegex = Regex("[^A-Za-z0-9]")
val cacheFile = File(context.cacheDir, filenameRegex.replace(uri.path, "_"))
var filename: String? = null
val fileSegmentIndex: Int = uri.path.lastIndexOf('/')
if (fileSegmentIndex != -1) {
filename = uri.path.substring(fileSegmentIndex + 1)
}
val host = uri.host.replace(".", "_")
val cacheName = "${host}_$filename"
println("Caching file: $filename from uri: $uri, cacheName: $cacheName")
val cacheFile = File(context.cacheDir, cacheName)
when {
cacheFile.exists() -> {
when {
header.meta.startsWith("image/") -> onUpdate(GemState.ResponseImage(uri, header, cacheFile.toUri()))
header.meta.startsWith("audio/") -> onUpdate(GemState.ResponseAudio(uri, header, cacheFile.toUri()))
header.meta.startsWith("image/") -> onUpdate(
GemState.ResponseImage(
uri,
header,
cacheFile.toUri()
)
)
header.meta.startsWith("audio/") -> onUpdate(
GemState.ResponseAudio(
uri,
header,
cacheFile.toUri()
)
)
}
}
@ -270,8 +300,20 @@ class GeminiDatasource(
}
when {
header.meta.startsWith("image/") -> onUpdate(GemState.ResponseImage(uri, header, cacheFile.toUri()))
header.meta.startsWith("audio/") -> onUpdate(GemState.ResponseAudio(uri, header, cacheFile.toUri()))
header.meta.startsWith("image/") -> onUpdate(
GemState.ResponseImage(
uri,
header,
cacheFile.toUri()
)
)
header.meta.startsWith("audio/") -> onUpdate(
GemState.ResponseAudio(
uri,
header,
cacheFile.toUri()
)
)
}
}
}

View File

@ -19,6 +19,9 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
val context = preferenceManager.context
val screen = preferenceManager.createPreferenceScreen(context)
/**
* TLS Settings
*/
val tlsCategory = PreferenceCategory(context)
tlsCategory.key = "tls_category"
tlsCategory.title = "TLS Config"
@ -30,6 +33,12 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
tlsDefaultPreference.onPreferenceChangeListener = this
tlsCategory.addPreference(tlsDefaultPreference)
val tlsAllSupportedPreference = SwitchPreferenceCompat(context)
tlsAllSupportedPreference.key = "tls_All_Supported"
tlsAllSupportedPreference.title = "TLS Enable all supported"
tlsAllSupportedPreference.onPreferenceChangeListener = this
tlsCategory.addPreference(tlsAllSupportedPreference)
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, null, SecureRandom())
val factory: SSLSocketFactory = sslContext.socketFactory
@ -55,6 +64,10 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
val default = preferenceScreen.findPreference<SwitchPreferenceCompat>("tls_Default")
default?.isChecked = false
}
if(key != "tls_All_Supported"){
val default = preferenceScreen.findPreference<SwitchPreferenceCompat>("tls_All_Supported")
default?.isChecked = false
}
protocols.forEach { protocol ->
val tlsSwitchKey = "tls_${protocol.toLowerCase(Locale.getDefault())}"
if (tlsSwitchKey != key) {
@ -66,12 +79,13 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
}
}
val prefTitle = preference.title.toString()
if(prefTitle.toLowerCase().contains("default")){
setTLSProtocol("TLS")
}else{
setTLSProtocol(prefTitle)
when (preference.key) {
"tls_Default" -> setTLSProtocol("TLS")
"tls_All_Supported" -> setTLSProtocol("TLS_ALL")
else -> {
val prefTitle = preference.title.toString()
setTLSProtocol(prefTitle)
}
}
return true