mirror of https://git.sr.ht/~oppen/ariane
tls config changes
This commit is contained in:
parent
50cf425a5b
commit
ab6635af69
|
@ -11,24 +11,27 @@ object DummyTrustManager {
|
||||||
fun get(): Array<TrustManager> {
|
fun get(): Array<TrustManager> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
object : X509TrustManager {
|
object : X509TrustManager {
|
||||||
@Throws(CertificateException::class)
|
|
||||||
override fun checkClientTrusted(
|
override fun checkClientTrusted(
|
||||||
chain: Array<X509Certificate?>?,
|
chain: Array<out X509Certificate>?,
|
||||||
authType: String?
|
authType: String?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CertificateException::class)
|
|
||||||
override fun checkServerTrusted(
|
override fun checkServerTrusted(
|
||||||
chain: Array<X509Certificate?>?,
|
chain: Array<out X509Certificate>?,
|
||||||
authType: String?
|
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()
|
return arrayOf()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,8 @@ const val GEMINI_SCHEME = "gemini"
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class GeminiDatasource(
|
class GeminiDatasource(
|
||||||
private val context: Context): Datasource {
|
private val context: Context
|
||||||
|
): Datasource {
|
||||||
|
|
||||||
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
private var last: URI? = null
|
private var last: URI? = null
|
||||||
|
@ -38,7 +39,7 @@ class GeminiDatasource(
|
||||||
when (uri.scheme) {
|
when (uri.scheme) {
|
||||||
GEMINI_SCHEME -> {
|
GEMINI_SCHEME -> {
|
||||||
val cached = RuntimeCache.get(uri)
|
val cached = RuntimeCache.get(uri)
|
||||||
if(cached != null){
|
if (cached != null) {
|
||||||
last = uri
|
last = uri
|
||||||
onUpdate(
|
onUpdate(
|
||||||
GemState.ResponseGemtext(
|
GemState.ResponseGemtext(
|
||||||
|
@ -48,7 +49,7 @@ class GeminiDatasource(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}else{
|
} else {
|
||||||
onUpdate(GemState.Requesting(uri))
|
onUpdate(GemState.Requesting(uri))
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
|
@ -71,7 +72,10 @@ class GeminiDatasource(
|
||||||
!address.contains("://") -> {
|
!address.contains("://") -> {
|
||||||
//looks like a relative link
|
//looks like a relative link
|
||||||
val lastAddress = last.toString()
|
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)
|
URI.create(relAddress)
|
||||||
}
|
}
|
||||||
else -> {
|
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
|
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){
|
private fun geminiRequest(uri: URI, onUpdate: (state: GemState) -> Unit){
|
||||||
last = uri
|
last = uri
|
||||||
val port = if(uri.port == -1) 1965 else uri.port
|
val port = if(uri.port == -1) 1965 else uri.port
|
||||||
|
@ -132,23 +116,28 @@ class GeminiDatasource(
|
||||||
|
|
||||||
println("REQ_PROTOCOL: $protocol")
|
println("REQ_PROTOCOL: $protocol")
|
||||||
|
|
||||||
val sslContext = SSLContext.getInstance(protocol)
|
//todo - extract and reuse this
|
||||||
sslContext.init(null, trustAllCerts, SecureRandom())
|
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 factory: SSLSocketFactory = sslContext.socketFactory
|
||||||
|
|
||||||
val socket: SSLSocket?
|
val socket: SSLSocket?
|
||||||
try {
|
try {
|
||||||
socket = factory.createSocket(uri.host, port) as SSLSocket
|
socket = factory.createSocket(uri.host, port) as SSLSocket
|
||||||
socket.enabledCipherSuites = factory.supportedCipherSuites
|
|
||||||
|
|
||||||
when (protocol) {
|
when (protocol) {
|
||||||
"TLS" -> socket.enabledProtocols = socket.supportedProtocols
|
"TLS" -> {}//Use default enabled protocols
|
||||||
|
"TLS_ALL" -> socket.enabledProtocols = socket.supportedProtocols
|
||||||
else -> socket.enabledProtocols = arrayOf(protocol)
|
else -> socket.enabledProtocols = arrayOf(protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.startHandshake()
|
socket.startHandshake()
|
||||||
}catch(ce: ConnectException){
|
}catch (ce: ConnectException){
|
||||||
println("socket error: $ce")
|
println("socket error: $ce")
|
||||||
onUpdate(
|
onUpdate(
|
||||||
GemState.ResponseError(
|
GemState.ResponseError(
|
||||||
|
@ -159,7 +148,7 @@ class GeminiDatasource(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}catch(she: SSLHandshakeException){
|
}catch (she: SSLHandshakeException){
|
||||||
println("socket error: $she")
|
println("socket error: $she")
|
||||||
onUpdate(
|
onUpdate(
|
||||||
GemState.ResponseError(
|
GemState.ResponseError(
|
||||||
|
@ -209,7 +198,12 @@ class GeminiDatasource(
|
||||||
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
|
header.code == GeminiResponse.INPUT -> onUpdate(GemState.ResponseInput(uri, header))
|
||||||
header.code == GeminiResponse.REDIRECT -> request(URI.create(header.meta), onUpdate)
|
header.code == GeminiResponse.REDIRECT -> request(URI.create(header.meta), onUpdate)
|
||||||
header.code != GeminiResponse.SUCCESS -> onUpdate(GemState.ResponseError(header))
|
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("text/") -> getString(socket, uri, header, onUpdate)
|
||||||
header.meta.startsWith("image/") -> getBinary(socket, uri, header, onUpdate)
|
header.meta.startsWith("image/") -> getBinary(socket, uri, header, onUpdate)
|
||||||
header.meta.startsWith("audio/") -> getBinary(socket, uri, header, onUpdate)
|
header.meta.startsWith("audio/") -> getBinary(socket, uri, header, onUpdate)
|
||||||
|
@ -228,7 +222,12 @@ class GeminiDatasource(
|
||||||
socket.close()
|
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>()
|
val lines = mutableListOf<String>()
|
||||||
|
|
||||||
|
@ -243,22 +242,53 @@ class GeminiDatasource(
|
||||||
onUpdate(GemState.ResponseGemtext(uri, header, processed))
|
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() }
|
val content = socket?.inputStream?.bufferedReader().use { reader -> reader?.readText() }
|
||||||
socket?.close()
|
socket?.close()
|
||||||
onUpdate(GemState.ResponseText(uri, header, content ?: "Error fetching content"))
|
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]")
|
var filename: String? = null
|
||||||
val cacheFile = File(context.cacheDir, filenameRegex.replace(uri.path, "_"))
|
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 {
|
when {
|
||||||
cacheFile.exists() -> {
|
cacheFile.exists() -> {
|
||||||
when {
|
when {
|
||||||
header.meta.startsWith("image/") -> onUpdate(GemState.ResponseImage(uri, header, cacheFile.toUri()))
|
header.meta.startsWith("image/") -> onUpdate(
|
||||||
header.meta.startsWith("audio/") -> onUpdate(GemState.ResponseAudio(uri, header, cacheFile.toUri()))
|
GemState.ResponseImage(
|
||||||
|
uri,
|
||||||
|
header,
|
||||||
|
cacheFile.toUri()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
header.meta.startsWith("audio/") -> onUpdate(
|
||||||
|
GemState.ResponseAudio(
|
||||||
|
uri,
|
||||||
|
header,
|
||||||
|
cacheFile.toUri()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -270,8 +300,20 @@ class GeminiDatasource(
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
header.meta.startsWith("image/") -> onUpdate(GemState.ResponseImage(uri, header, cacheFile.toUri()))
|
header.meta.startsWith("image/") -> onUpdate(
|
||||||
header.meta.startsWith("audio/") -> onUpdate(GemState.ResponseAudio(uri, header, cacheFile.toUri()))
|
GemState.ResponseImage(
|
||||||
|
uri,
|
||||||
|
header,
|
||||||
|
cacheFile.toUri()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
header.meta.startsWith("audio/") -> onUpdate(
|
||||||
|
GemState.ResponseAudio(
|
||||||
|
uri,
|
||||||
|
header,
|
||||||
|
cacheFile.toUri()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
|
||||||
val context = preferenceManager.context
|
val context = preferenceManager.context
|
||||||
val screen = preferenceManager.createPreferenceScreen(context)
|
val screen = preferenceManager.createPreferenceScreen(context)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLS Settings
|
||||||
|
*/
|
||||||
val tlsCategory = PreferenceCategory(context)
|
val tlsCategory = PreferenceCategory(context)
|
||||||
tlsCategory.key = "tls_category"
|
tlsCategory.key = "tls_category"
|
||||||
tlsCategory.title = "TLS Config"
|
tlsCategory.title = "TLS Config"
|
||||||
|
@ -30,6 +33,12 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
|
||||||
tlsDefaultPreference.onPreferenceChangeListener = this
|
tlsDefaultPreference.onPreferenceChangeListener = this
|
||||||
tlsCategory.addPreference(tlsDefaultPreference)
|
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")
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
sslContext.init(null, null, SecureRandom())
|
sslContext.init(null, null, SecureRandom())
|
||||||
val factory: SSLSocketFactory = sslContext.socketFactory
|
val factory: SSLSocketFactory = sslContext.socketFactory
|
||||||
|
@ -55,6 +64,10 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
|
||||||
val default = preferenceScreen.findPreference<SwitchPreferenceCompat>("tls_Default")
|
val default = preferenceScreen.findPreference<SwitchPreferenceCompat>("tls_Default")
|
||||||
default?.isChecked = false
|
default?.isChecked = false
|
||||||
}
|
}
|
||||||
|
if(key != "tls_All_Supported"){
|
||||||
|
val default = preferenceScreen.findPreference<SwitchPreferenceCompat>("tls_All_Supported")
|
||||||
|
default?.isChecked = false
|
||||||
|
}
|
||||||
protocols.forEach { protocol ->
|
protocols.forEach { protocol ->
|
||||||
val tlsSwitchKey = "tls_${protocol.toLowerCase(Locale.getDefault())}"
|
val tlsSwitchKey = "tls_${protocol.toLowerCase(Locale.getDefault())}"
|
||||||
if (tlsSwitchKey != key) {
|
if (tlsSwitchKey != key) {
|
||||||
|
@ -66,12 +79,13 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val prefTitle = preference.title.toString()
|
when (preference.key) {
|
||||||
|
"tls_Default" -> setTLSProtocol("TLS")
|
||||||
if(prefTitle.toLowerCase().contains("default")){
|
"tls_All_Supported" -> setTLSProtocol("TLS_ALL")
|
||||||
setTLSProtocol("TLS")
|
else -> {
|
||||||
}else{
|
val prefTitle = preference.title.toString()
|
||||||
setTLSProtocol(prefTitle)
|
setTLSProtocol(prefTitle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue