浏览代码

feat: ignore tls certificate (#66)

Reviewed-on: https://gitea.angry.im/PeterCxy/OpenEUICC/pulls/66
Co-authored-by: septs <github@septs.pw>
Co-committed-by: septs <github@septs.pw>
septs 1 年之前
父节点
当前提交
a3d59a0761

+ 4 - 2
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,
         )
     }
 

+ 3 - 2
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<Boolean>
+    verboseLoggingFlow: Flow<Boolean>,
+    ignoreTLSCertificateFlow: Flow<Boolean>
 ) : 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

+ 3 - 0
app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt

@@ -75,6 +75,9 @@ class SettingsFragment: PreferenceFragmentCompat() {
 
         findPreference<CheckBoxPreference>("pref_developer_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() {

+ 9 - 0
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<Boolean> =
         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) {
         dataStore.edit {
             it[key] = value

+ 2 - 0
app-common/src/main/res/values/strings.xml

@@ -123,6 +123,8 @@
     <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_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_app_version">App Version</string>
     <string name="pref_info_source_code">Source Code</string>

+ 6 - 0
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" />
 
+        <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

+ 2 - 1
app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt

@@ -35,7 +35,8 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto
                         tm,
                         context.preferenceRepository.verboseLoggingFlow
                     ),
-                    context.preferenceRepository.verboseLoggingFlow
+                    context.preferenceRepository.verboseLoggingFlow,
+                    context.preferenceRepository.ignoreTLSCertificateFlow,
                 )
             } catch (e: IllegalArgumentException) {
                 // Failed

+ 18 - 5
libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt

@@ -9,10 +9,14 @@ import java.net.URL
 import java.security.SecureRandom
 import javax.net.ssl.HttpsURLConnection
 import javax.net.ssl.SSLContext
+import javax.net.ssl.SSLSocketFactory
 import javax.net.ssl.TrustManager
 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 {
         private const val TAG = "HttpInterfaceImpl"
     }
@@ -36,9 +40,6 @@ class HttpInterfaceImpl(private val verboseLoggingFlow: Flow<Boolean>) : 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<Boolean>) : 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<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>) {
         val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply {
             init(keyIdToKeystore(pkids))

+ 22 - 0
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<out X509Certificate>?, p1: String?) {
+        return
+    }
+
+    @SuppressLint("TrustAllX509TrustManager")
+    override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) {
+        return
+    }
+
+    override fun getAcceptedIssuers(): Array<X509Certificate> {
+        return emptyArray()
+    }
+}