diff --git a/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt b/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt index 410cccc..a8fa1d5 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelFactory.kt @@ -42,7 +42,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha port, context.preferenceRepository.verboseLoggingFlow ), - context.preferenceRepository.verboseLoggingFlow + context.preferenceRepository.verboseLoggingFlow, + context.preferenceRepository.ignoreTLSCertificateFlow, ).also { Log.i(DefaultEuiccChannelManager.TAG, "Is OMAPI channel, setting MSS to 60") it.lpa.setEs10xMss(60) @@ -72,7 +73,8 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha bulkOut, context.preferenceRepository.verboseLoggingFlow ), - context.preferenceRepository.verboseLoggingFlow + context.preferenceRepository.verboseLoggingFlow, + context.preferenceRepository.ignoreTLSCertificateFlow, ) } diff --git a/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt b/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt index 9bccbff..79dec34 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelImpl.kt @@ -11,14 +11,15 @@ class EuiccChannelImpl( override val type: String, override val port: UiccPortInfoCompat, apduInterface: ApduInterface, - verboseLoggingFlow: Flow + verboseLoggingFlow: Flow, + ignoreTLSCertificateFlow: Flow ) : EuiccChannel { override val slotId = port.card.physicalSlotIndex override val logicalSlotId = port.logicalSlotIndex override val portId = port.portIndex override val lpa: LocalProfileAssistant = - LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow)) + LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow, ignoreTLSCertificateFlow)) override val valid: Boolean get() = lpa.valid diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt index f368732..89963cb 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt @@ -75,6 +75,9 @@ class SettingsFragment: PreferenceFragmentCompat() { findPreference("pref_developer_experimental_download_wizard") ?.bindBooleanFlow(preferenceRepository.experimentalDownloadWizardFlow, PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD) + + findPreference("pref_ignore_tls_certificate") + ?.bindBooleanFlow(preferenceRepository.ignoreTLSCertificateFlow, PreferenceKeys.IGNORE_TLS_CERTIFICATE) } override fun onStart() { diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt index 700c4cd..505630e 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt @@ -20,13 +20,19 @@ val Fragment.preferenceRepository: PreferenceRepository get() = requireContext().preferenceRepository object PreferenceKeys { + // ---- Profile Notifications ---- val NOTIFICATION_DOWNLOAD = booleanPreferencesKey("notification_download") val NOTIFICATION_DELETE = booleanPreferencesKey("notification_delete") val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch") + + // ---- Advanced ---- val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim") val VERBOSE_LOGGING = booleanPreferencesKey("verbose_logging") + + // ---- Developer Options ---- val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled") val EXPERIMENTAL_DOWNLOAD_WIZARD = booleanPreferencesKey("experimental_download_wizard") + val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate") } class PreferenceRepository(context: Context) { @@ -57,6 +63,9 @@ class PreferenceRepository(context: Context) { val experimentalDownloadWizardFlow: Flow = dataStore.data.map { it[PreferenceKeys.EXPERIMENTAL_DOWNLOAD_WIZARD] ?: false } + val ignoreTLSCertificateFlow: Flow = + dataStore.data.map { it[PreferenceKeys.IGNORE_TLS_CERTIFICATE] ?: false } + suspend fun updatePreference(key: Preferences.Key, value: T) { dataStore.edit { it[key] = value diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 062a5c0..bdb89ca 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -123,6 +123,8 @@ Developer Options Experimental Download Wizard Enable the experimental new download wizard. Note that it is not fully working yet. + Ignore SM-DP+ TLS certificate + Ignore SM-DP+ TLS certificate, allow any RSP Info App Version Source Code diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 150aca5..d43c84b 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -55,6 +55,12 @@ app:title="@string/pref_developer_experimental_download_wizard" app:summary="@string/pref_developer_experimental_download_wizard_desc" /> + + ) : HttpInterface { +class HttpInterfaceImpl( + private val verboseLoggingFlow: Flow, + private val ignoreTLSCertificateFlow: Flow +) : HttpInterface { companion object { private const val TAG = "HttpInterfaceImpl" } @@ -36,9 +40,6 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : HttpInt } try { - val sslContext = SSLContext.getInstance("TLS") - sslContext.init(null, trustManagers, SecureRandom()) - val conn = parsedUrl.openConnection() as HttpsURLConnection conn.connectTimeout = 2000 @@ -47,7 +48,7 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : HttpInt conn.readTimeout = 1000 } - conn.sslSocketFactory = sslContext.socketFactory + conn.sslSocketFactory = getSocketFactory() conn.requestMethod = "POST" conn.doInput = true conn.doOutput = true @@ -79,6 +80,18 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow) : 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) { val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply { init(keyIdToKeystore(pkids)) diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt new file mode 100644 index 0000000..7b13282 --- /dev/null +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt @@ -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?, p1: String?) { + return + } + + @SuppressLint("TrustAllX509TrustManager") + override fun checkServerTrusted(p0: Array?, p1: String?) { + return + } + + override fun getAcceptedIssuers(): Array { + return emptyArray() + } +} \ No newline at end of file