From 6782227037711f1a5d79e94cf30d611d49a1610a Mon Sep 17 00:00:00 2001
From: ssrlive <30760636+ssrlive@users.noreply.github.com>
Date: Thu, 30 May 2024 21:21:57 +0800
Subject: [PATCH] self-signed certificate
---
.../3.json | 8 +++++++-
.../github/shadowsocks/database/Profile.kt | 20 +++++++++++++++++--
.../com/github/shadowsocks/utils/Constants.kt | 1 +
core/src/main/res/values-zh-rCN/strings.xml | 2 ++
core/src/main/res/values/strings.xml | 2 ++
.../shadowsocks/ProfileConfigFragment.kt | 4 ++++
.../github/shadowsocks/ProfilesFragment.kt | 6 +++++-
mobile/src/main/res/xml/pref_profile.xml | 6 ++++++
8 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/core/schemas/com.github.shadowsocks.database.PrivateDatabase/3.json b/core/schemas/com.github.shadowsocks.database.PrivateDatabase/3.json
index 38d3abf40..13c9af883 100644
--- a/core/schemas/com.github.shadowsocks.database.PrivateDatabase/3.json
+++ b/core/schemas/com.github.shadowsocks.database.PrivateDatabase/3.json
@@ -6,7 +6,7 @@
"entities": [
{
"tableName": "Profile",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `remotePort` INTEGER NOT NULL, `password` TEXT NOT NULL, `protocol` TEXT NOT NULL, `protocol_param` TEXT NOT NULL, `obfs` TEXT NOT NULL, `obfs_param` TEXT NOT NULL, `method` TEXT NOT NULL, `over_tls_enable` INTEGER NOT NULL, `over_tls_server_domain` TEXT NOT NULL, `over_tls_path` TEXT NOT NULL, `route` TEXT NOT NULL, `remoteDns` TEXT NOT NULL, `proxyApps` INTEGER NOT NULL, `bypass` INTEGER NOT NULL, `udpdns` INTEGER NOT NULL, `url_group` TEXT NOT NULL, `ipv6` INTEGER NOT NULL, `metered` INTEGER NOT NULL, `individual` TEXT NOT NULL, `plugin` TEXT, `udpFallback` INTEGER, `subscription` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `elapsed` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL)",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `remotePort` INTEGER NOT NULL, `password` TEXT NOT NULL, `protocol` TEXT NOT NULL, `protocol_param` TEXT NOT NULL, `obfs` TEXT NOT NULL, `obfs_param` TEXT NOT NULL, `method` TEXT NOT NULL, `over_tls_enable` INTEGER NOT NULL, `over_tls_server_domain` TEXT NOT NULL, `over_tls_path` TEXT NOT NULL, `over_tls_cafile` TEXT NOT NULL, `route` TEXT NOT NULL, `remoteDns` TEXT NOT NULL, `proxyApps` INTEGER NOT NULL, `bypass` INTEGER NOT NULL, `udpdns` INTEGER NOT NULL, `url_group` TEXT NOT NULL, `ipv6` INTEGER NOT NULL, `metered` INTEGER NOT NULL, `individual` TEXT NOT NULL, `plugin` TEXT, `udpFallback` INTEGER, `subscription` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `elapsed` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
@@ -86,6 +86,12 @@
"affinity": "TEXT",
"notNull": true
},
+ {
+ "fieldPath": "over_tls_cafile",
+ "columnName": "over_tls_cafile",
+ "affinity": "TEXT",
+ "notNull": true
+ },
{
"fieldPath": "route",
"columnName": "route",
diff --git a/core/src/main/java/com/github/shadowsocks/database/Profile.kt b/core/src/main/java/com/github/shadowsocks/database/Profile.kt
index a9ca50c20..348f539fc 100644
--- a/core/src/main/java/com/github/shadowsocks/database/Profile.kt
+++ b/core/src/main/java/com/github/shadowsocks/database/Profile.kt
@@ -60,6 +60,7 @@ data class Profile(
var over_tls_enable: Boolean = false,
var over_tls_server_domain: String = "",
var over_tls_path: String = "",
+ var over_tls_cafile: String = "",
var route: String = "all",
var remoteDns: String = "8.8.8.8:53",
@@ -120,6 +121,7 @@ data class Profile(
private val decodedPattern_ssr_over_tls_enable = "(?i)(.*)[?&]ot_enable=([0-9_=-]*)(.*)".toRegex()
private val decodedPattern_ssr_over_tls_server_domain = "(?i)(.*)[?&]ot_domain=([A-Za-z0-9_=-]*)(.*)".toRegex()
private val decodedPattern_ssr_over_tls_path = "(?i)(.*)[?&]ot_path=([A-Za-z0-9_=-]*)(.*)".toRegex()
+ private val decodedPattern_ssr_over_tls_cafile = "(?i)(.*)[?&]ot_cert=([A-Za-z0-9_=-]*)(.*)".toRegex()
private fun base64Decode(data: String) = String(Base64.decode(data.replace("=", ""), Base64.URL_SAFE), Charsets.UTF_8)
@@ -159,6 +161,9 @@ data class Profile(
val match7 = decodedPattern_ssr_over_tls_path.matchEntire(match.groupValues[8])
if (match7 != null) profile.over_tls_path = base64Decode(match7.groupValues[2])
+ val match8 = decodedPattern_ssr_over_tls_cafile.matchEntire(match.groupValues[8])
+ if (match8 != null) profile.over_tls_cafile = base64Decode(match8.groupValues[2])
+
profile
} else {
null
@@ -257,6 +262,7 @@ data class Profile(
val over_tls_enable = json["over_tls_enable"]?.optBoolean
val over_tls_server_domain = json["over_tls_server_domain"].optString ?: return null
val over_tls_path = json["over_tls_path"].optString ?: return null
+ val over_tls_cafile = json["over_tls_cafile"].optString ?: return null
val method = json["method"].optString
if (method.isNullOrEmpty()) return null
@@ -272,6 +278,7 @@ data class Profile(
it.over_tls_enable = if (over_tls_enable != null && over_tls_enable == true) true else false
it.over_tls_server_domain = over_tls_server_domain
it.over_tls_path = over_tls_path
+ it.over_tls_cafile = over_tls_cafile
}.apply {
feature?.copyFeatureSettingsTo(this)
name = json["remarks"].optString.toString()
@@ -314,6 +321,7 @@ data class Profile(
fallback.over_tls_enable == it.over_tls_enable &&
fallback.over_tls_server_domain == it.over_tls_server_domain &&
fallback.over_tls_path == it.over_tls_path &&
+ fallback.over_tls_cafile == it.over_tls_cafile &&
it.plugin.isNullOrEmpty()
}
@@ -396,6 +404,7 @@ data class Profile(
profile.over_tls_enable = over_tls_enable
profile.over_tls_server_domain = over_tls_server_domain
profile.over_tls_path = over_tls_path
+ profile.over_tls_cafile = over_tls_cafile
profile.method = method
}
}
@@ -407,6 +416,7 @@ data class Profile(
other.over_tls_enable == over_tls_enable &&
other.over_tls_server_domain == over_tls_server_domain &&
other.over_tls_path == over_tls_path &&
+ other.over_tls_cafile == over_tls_cafile &&
other.name == name && other.url_group == url_group
override fun toString(): String {
@@ -421,6 +431,7 @@ data class Profile(
val b64url_group = Base64.encodeToString("%s".format(Locale.ENGLISH, url_group).toByteArray(), flags)
val b64over_tls_server_domain = Base64.encodeToString("%s".format(Locale.ENGLISH, over_tls_server_domain).toByteArray(), flags)
val b64over_tls_path = Base64.encodeToString("%s".format(Locale.ENGLISH, over_tls_path).toByteArray(), flags)
+ val b64over_tls_cafile = Base64.encodeToString("%s".format(Locale.ENGLISH, over_tls_cafile).toByteArray(), flags)
if (!over_tls_enable && obfs == "plain" && protocol == "origin") {
return "ss://" + b64userinfo + "@" + host + ":" + remotePort + "#" + URLEncoder.encode(name, "utf-8")
@@ -428,11 +439,12 @@ data class Profile(
if (over_tls_enable) {
return "ssr://" + Base64.encodeToString(
- "%s:%d:%s:%s:%s:%s/?obfsparam=%s&protoparam=%s&remarks=%s&group=%s&ot_enable=%d&ot_domain=%s&ot_path=%s"
+ "%s:%d:%s:%s:%s:%s/?obfsparam=%s&protoparam=%s&remarks=%s&group=%s&ot_enable=%d&ot_domain=%s&ot_path=%s%s"
.format(
Locale.ENGLISH, host, remotePort, protocol, method, obfs, b64password,
b64obfs_param, b64protocol_param, b64name, b64url_group,
- 1, b64over_tls_server_domain, b64over_tls_path
+ 1, b64over_tls_server_domain, b64over_tls_path,
+ if (b64over_tls_cafile.isEmpty()) "" else "&ot_cert=${b64over_tls_cafile}"
).toByteArray(), flags
)
} else {
@@ -460,6 +472,7 @@ data class Profile(
put("server_domain", over_tls_server_domain)
put("listen_host", DataStore.listenAddress)
put("listen_port", DataStore.portProxy)
+ put("cafile", over_tls_cafile)
})
}
@@ -481,6 +494,7 @@ data class Profile(
put("enable", over_tls_enable)
put("server_domain", over_tls_server_domain)
put("path", over_tls_path)
+ put("root_cert_file", over_tls_cafile)
})
}
@@ -521,6 +535,7 @@ data class Profile(
DataStore.privateStore.putBoolean(Key.over_tls_enable, over_tls_enable)
DataStore.privateStore.putString(Key.over_tls_server_domain, over_tls_server_domain)
DataStore.privateStore.putString(Key.over_tls_path, over_tls_path)
+ DataStore.privateStore.putString(Key.over_tls_cafile, over_tls_cafile)
DataStore.proxyApps = proxyApps
DataStore.bypass = bypass
@@ -551,6 +566,7 @@ data class Profile(
over_tls_enable = (DataStore.privateStore.getBoolean(Key.over_tls_enable) == true)
over_tls_server_domain = DataStore.privateStore.getString(Key.over_tls_server_domain) ?: ""
over_tls_path = DataStore.privateStore.getString(Key.over_tls_path) ?: ""
+ over_tls_cafile = DataStore.privateStore.getString(Key.over_tls_cafile) ?: ""
method = DataStore.privateStore.getString(Key.method) ?: ""
route = DataStore.privateStore.getString(Key.route) ?: ""
diff --git a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt
index 984e39569..04e5d42d3 100644
--- a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt
+++ b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt
@@ -64,6 +64,7 @@ object Key {
const val over_tls_enable = "over_tls_enable"
const val over_tls_server_domain = "over_tls_server_domain"
const val over_tls_path = "over_tls_path"
+ const val over_tls_cafile = "over_tls_cafile"
const val remotePort = "remotePortNum"
const val remoteDns = "remoteDns"
diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml
index 1029cee26..956966560 100644
--- a/core/src/main/res/values-zh-rCN/strings.xml
+++ b/core/src/main/res/values-zh-rCN/strings.xml
@@ -40,6 +40,8 @@
"SSRoT 啓用"
"SSRoT 服務器域名"
"SSRoT 祕密入口路徑"
+ "over_tls CA 憑證文件"
+ 這個節點不支持二維碼因爲它含有自簽名證書
"IPv6 路由"
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 5db355b3b..c37a5ca47 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -40,6 +40,8 @@
SSRoT enable
SSRoT domain name
SSRoT secret path
+ over_tls CA file
+ QR code not supported because of this node contains self-signed certificate
IPv6 Route
diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
index c45384428..3e77f6615 100644
--- a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
@@ -73,6 +73,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), OnPreferenceDataStoreC
private lateinit var over_tls_enable: SwitchPreference
private lateinit var over_tls_server_domain: EditTextPreference
private lateinit var over_tls_path: EditTextPreference
+ private lateinit var over_tls_cafile: EditTextPreference
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore.privateStore
@@ -104,6 +105,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), OnPreferenceDataStoreC
over_tls_server_domain = findPreference(Key.over_tls_server_domain)!!
over_tls_path = findPreference(Key.over_tls_path)!!
+ over_tls_cafile = findPreference(Key.over_tls_cafile)!!
over_tls_enable = findPreference(Key.over_tls_enable)!!
over_tls_enable.setOnPreferenceChangeListener { _, newValue ->
@@ -130,6 +132,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), OnPreferenceDataStoreC
findPreference(Key.over_tls_enable)!!.isEnabled = false
findPreference(Key.over_tls_server_domain)!!.isEnabled = false
findPreference(Key.over_tls_path)!!.isEnabled = false
+ findPreference(Key.over_tls_cafile)!!.isEnabled = false
} else findPreference(Key.group)!!.isEnabled = false
}
@@ -142,6 +145,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), OnPreferenceDataStoreC
over_tls_enable.isChecked = enable
over_tls_server_domain.isEnabled = enable
over_tls_path.isEnabled = enable
+ over_tls_cafile.isEnabled = enable
}
private fun saveAndExit() {
diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
index bffb14935..e3a88eb26 100644
--- a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
@@ -203,7 +203,11 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, Sea
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_qr_code -> {
- QRCodeDialog(this.item.toString()).showAllowingStateLoss(parentFragmentManager)
+ if (this.item.over_tls_cafile.length > 0) {
+ (activity as MainActivity).snackbar().setText(R.string.qr_code_not_support).setDuration(4000).show()
+ } else {
+ QRCodeDialog(this.item.toString()).showAllowingStateLoss(parentFragmentManager)
+ }
true
}
R.id.action_export_clipboard -> {
diff --git a/mobile/src/main/res/xml/pref_profile.xml b/mobile/src/main/res/xml/pref_profile.xml
index eb33a41f5..5699ac5f4 100644
--- a/mobile/src/main/res/xml/pref_profile.xml
+++ b/mobile/src/main/res/xml/pref_profile.xml
@@ -85,6 +85,12 @@
app:title="@string/over_tls_path"
app:useSimpleSummaryProvider="true" />
+
+