feat: ignore tls certificate #66
9 changed files with 69 additions and 10 deletions
|
@ -42,7 +42,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha
|
||||||
port,
|
port,
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow
|
||||||
),
|
),
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow,
|
||||||
|
context.preferenceRepository.ignoreTLSCertificateFlow,
|
||||||
).also {
|
).also {
|
||||||
Log.i(DefaultEuiccChannelManager.TAG, "Is OMAPI channel, setting MSS to 60")
|
Log.i(DefaultEuiccChannelManager.TAG, "Is OMAPI channel, setting MSS to 60")
|
||||||
it.lpa.setEs10xMss(60)
|
it.lpa.setEs10xMss(60)
|
||||||
|
@ -72,7 +73,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha
|
||||||
bulkOut,
|
bulkOut,
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow
|
||||||
),
|
),
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow,
|
||||||
|
context.preferenceRepository.ignoreTLSCertificateFlow,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,15 @@ class EuiccChannelImpl(
|
||||||
override val type: String,
|
override val type: String,
|
||||||
override val port: UiccPortInfoCompat,
|
override val port: UiccPortInfoCompat,
|
||||||
apduInterface: ApduInterface,
|
apduInterface: ApduInterface,
|
||||||
verboseLoggingFlow: Flow<Boolean>
|
verboseLoggingFlow: Flow<Boolean>,
|
||||||
|
ignoreTLSCertificateFlow: Flow<Boolean>
|
||||||
) : EuiccChannel {
|
) : EuiccChannel {
|
||||||
override val slotId = port.card.physicalSlotIndex
|
override val slotId = port.card.physicalSlotIndex
|
||||||
override val logicalSlotId = port.logicalSlotIndex
|
override val logicalSlotId = port.logicalSlotIndex
|
||||||
override val portId = port.portIndex
|
override val portId = port.portIndex
|
||||||
|
|
||||||
override val lpa: LocalProfileAssistant =
|
override val lpa: LocalProfileAssistant =
|
||||||
LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow))
|
LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow, ignoreTLSCertificateFlow))
|
||||||
|
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = lpa.valid
|
get() = lpa.valid
|
||||||
|
|
|
@ -75,6 +75,9 @@ class SettingsFragment: PreferenceFragmentCompat() {
|
||||||
|
|
||||||
findPreference<CheckBoxPreference>("pref_developer_experimental_download_wizard")
|
findPreference<CheckBoxPreference>("pref_developer_experimental_download_wizard")
|
||||||
?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD)
|
?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD)
|
||||||
|
|
||||||
|
findPreference<CheckBoxPreference>("pref_ignore_tls_certificate")
|
||||||
|
?.bindBooleanFlow(preferenceRepository.ignoreTLSCertificateFlow, PreferenceKeys.IGNORE_TLS_CERTIFICATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
|
|
@ -20,13 +20,19 @@ val Fragment.preferenceRepository: PreferenceRepository
|
||||||
get() = requireContext().preferenceRepository
|
get() = requireContext().preferenceRepository
|
||||||
|
|
||||||
object PreferenceKeys {
|
object PreferenceKeys {
|
||||||
|
// ---- Profile Notifications ----
|
||||||
val NOTIFICATION_DOWNLOAD = booleanPreferencesKey("notification_download")
|
val NOTIFICATION_DOWNLOAD = booleanPreferencesKey("notification_download")
|
||||||
val NOTIFICATION_DELETE = booleanPreferencesKey("notification_delete")
|
val NOTIFICATION_DELETE = booleanPreferencesKey("notification_delete")
|
||||||
val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch")
|
val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch")
|
||||||
|
|
||||||
|
// ---- Advanced ----
|
||||||
val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim")
|
val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim")
|
||||||
val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging")
|
val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging")
|
||||||
|
|
||||||
|
// ---- Developer Options ----
|
||||||
val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled")
|
val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled")
|
||||||
val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard")
|
val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard")
|
||||||
|
val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate")
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreferenceRepository(context: Context) {
|
class PreferenceRepository(context: Context) {
|
||||||
|
@ -57,6 +63,9 @@ class PreferenceRepository(context: Context) {
|
||||||
val experimentalDownloadWizardFlow: Flow<Boolean> =
|
val experimentalDownloadWizardFlow: Flow<Boolean> =
|
||||||
dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false }
|
dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false }
|
||||||
|
|
||||||
|
val ignoreTLSCertificateFlow: Flow<Boolean> =
|
||||||
|
dataStore.data.map { it[PreferenceKeys.IGNORE_TLS_CERTIFICATE] ?: false }
|
||||||
|
|
||||||
suspend fun <T> updatePreference(key: Preferences.Key<T>, value: T) {
|
suspend fun <T> updatePreference(key: Preferences.Key<T>, value: T) {
|
||||||
dataStore.edit {
|
dataStore.edit {
|
||||||
it[key] = value
|
it[key] = value
|
||||||
|
|
|
@ -123,6 +123,8 @@
|
||||||
<string name="pref_developer">Developer Options</string>
|
<string name="pref_developer">Developer Options</string>
|
||||||
<string name="pref_developer_experimental_download_wizard">Experimental Download Wizard</string>
|
<string name="pref_developer_experimental_download_wizard">Experimental Download Wizard</string>
|
||||||
<string name="pref_developer_experimental_download_wizard_desc">Enable the experimental new download wizard. Note that it is not fully working yet.</string>
|
<string name="pref_developer_experimental_download_wizard_desc">Enable the experimental new download wizard. Note that it is not fully working yet.</string>
|
||||||
|
<string name="pref_developer_ignore_tls_certificate">Ignore SM-DP+ TLS certificate</string>
|
||||||
|
<string name="pref_developer_ignore_tls_certificate_desc">Ignore SM-DP+ TLS certificate, allow any RSP</string>
|
||||||
<string name="pref_info">Info</string>
|
<string name="pref_info">Info</string>
|
||||||
<string name="pref_info_app_version">App Version</string>
|
<string name="pref_info_app_version">App Version</string>
|
||||||
<string name="pref_info_source_code">Source Code</string>
|
<string name="pref_info_source_code">Source Code</string>
|
||||||
|
|
|
@ -55,6 +55,12 @@
|
||||||
app:title="@string/pref_developer_experimental_download_wizard"
|
app:title="@string/pref_developer_experimental_download_wizard"
|
||||||
app:summary="@string/pref_developer_experimental_download_wizard_desc" />
|
app:summary="@string/pref_developer_experimental_download_wizard_desc" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:key="pref_developer_ignore_tls_certificate"
|
||||||
|
app:summary="@string/pref_developer_ignore_tls_certificate_desc"
|
||||||
|
app:title="@string/pref_developer_ignore_tls_certificate" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
|
@ -35,7 +35,8 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto
|
||||||
tm,
|
tm,
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow
|
||||||
),
|
),
|
||||||
context.preferenceRepository.verboseLoggingFlow
|
context.preferenceRepository.verboseLoggingFlow,
|
||||||
|
context.preferenceRepository.ignoreTLSCertificateFlow,
|
||||||
)
|
)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
// Failed
|
// Failed
|
||||||
|
|
|
@ -9,10 +9,14 @@ import java.net.URL
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import javax.net.ssl.SSLContext
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.SSLSocketFactory
|
||||||
import javax.net.ssl.TrustManager
|
import javax.net.ssl.TrustManager
|
||||||
import javax.net.ssl.TrustManagerFactory
|
import javax.net.ssl.TrustManagerFactory
|
||||||
|
|
||||||
class HttpInterfaceImpl(private val verboseLoggingFlow: Flow<Boolean>) : HttpInterface {
|
class HttpInterfaceImpl(
|
||||||
|
private val verboseLoggingFlow: Flow<Boolean>,
|
||||||
|
private val ignoreTLSCertificateFlow: Flow<Boolean>
|
||||||
|
) : HttpInterface {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "HttpInterfaceImpl"
|
private const val TAG = "HttpInterfaceImpl"
|
||||||
}
|
}
|
||||||
|
@ -36,9 +40,6 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow<Boolean>) : HttpInt
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val sslContext = SSLContext.getInstance("TLS")
|
|
||||||
sslContext.init(null, trustManagers, SecureRandom())
|
|
||||||
|
|
||||||
val conn = parsedUrl.openConnection() as HttpsURLConnection
|
val conn = parsedUrl.openConnection() as HttpsURLConnection
|
||||||
conn.connectTimeout = 2000
|
conn.connectTimeout = 2000
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow<Boolean>) : HttpInt
|
||||||
conn.readTimeout = 1000
|
conn.readTimeout = 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sslSocketFactory = sslContext.socketFactory
|
conn.sslSocketFactory = getSocketFactory()
|
||||||
conn.requestMethod = "POST"
|
conn.requestMethod = "POST"
|
||||||
conn.doInput = true
|
conn.doInput = true
|
||||||
conn.doOutput = true
|
conn.doOutput = true
|
||||||
|
@ -79,6 +80,18 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow<Boolean>) : HttpInt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSocketFactory(): SSLSocketFactory {
|
||||||
|
val trustManagers =
|
||||||
|
if (runBlocking { ignoreTLSCertificateFlow.first() }) {
|
||||||
|
arrayOf(IgnoreTLSCertificate())
|
||||||
|
} else {
|
||||||
|
this.trustManagers
|
||||||
|
}
|
||||||
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
|
sslContext.init(null, trustManagers, SecureRandom())
|
||||||
|
return sslContext.socketFactory
|
||||||
|
}
|
||||||
|
|
||||||
override fun usePublicKeyIds(pkids: Array<String>) {
|
override fun usePublicKeyIds(pkids: Array<String>) {
|
||||||
val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply {
|
val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply {
|
||||||
init(keyIdToKeystore(pkids))
|
init(keyIdToKeystore(pkids))
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package net.typeblog.lpac_jni.impl
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
|
@SuppressLint("CustomX509TrustManager")
|
||||||
|
class IgnoreTLSCertificate : X509TrustManager {
|
||||||
|
@SuppressLint("TrustAllX509TrustManager")
|
||||||
|
override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("TrustAllX509TrustManager")
|
||||||
|
override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAcceptedIssuers(): Array<X509Certificate> {
|
||||||
|
return emptyArray()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue