feat: ignore tls certificate #66

Merged
PeterCxy merged 4 commits from septs/OpenEUICC:ignore-tls-certificate into master 2024-11-17 03:43:40 +01:00
9 changed files with 69 additions and 10 deletions

View file

@ -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,
) )
} }

View file

@ -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

View file

@ -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() {

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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()
}
}