Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove conscrypt lib, use own trust manager, refine networking #1319

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ dependencies {
implementation("org.mozilla:rhino:1.7.15") // run JavaScript
implementation("me.xdrop:fuzzywuzzy:1.4.0") // Library/Ext Searching with Levenshtein Distance
implementation("com.github.LagradOst:SafeFile:0.0.6") // To Prevent the URI File Fu*kery
implementation("org.conscrypt:conscrypt-android:2.5.2") // To Fix SSL Fu*kery on Android 9
implementation("com.uwetrottmann.tmdb2:tmdb-java:2.11.0") // TMDB API v3 Wrapper Made with RetroFit
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4") //nio flavor needed for NewPipeExtractor
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1") /* JSON Parser
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
android:banner="@mipmap/ic_banner"
android:fullBackupContent="@xml/backup_descriptor"
android:dataExtractionRules="@xml/data_extraction_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import okhttp3.Request
import okhttp3.Response
import java.net.URI


@AnyThread
class CloudflareKiller : Interceptor {
companion object {
Expand Down Expand Up @@ -45,10 +44,10 @@ class CloudflareKiller : Interceptor {
* */
fun getCookieHeaders(url: String): Headers {
val userAgentHeaders = WebViewResolver.webViewUserAgent?.let {
mapOf("user-agent" to it)
hashMapOf("User-Agent" to it)
} ?: emptyMap()

return getHeaders(userAgentHeaders, savedCookies[URI(url).host] ?: emptyMap())
return getHeaders(HashMap(userAgentHeaders), HashMap(savedCookies[URI(url).host] ?: emptyMap()))
}

override fun intercept(chain: Interceptor.Chain): Response = runBlocking {
Expand Down Expand Up @@ -97,11 +96,10 @@ class CloudflareKiller : Interceptor {

private suspend fun proceed(request: Request, cookies: Map<String, String>): Response {
val userAgentMap = WebViewResolver.getWebViewUserAgent()?.let {
mapOf("user-agent" to it)
hashMapOf("User-Agent" to it)
} ?: emptyMap()

val headers =
getHeaders(request.headers.toMap() + userAgentMap, cookies + request.cookies)
val headers = getHeaders(HashMap(request.headers.toMap() + userAgentMap), HashMap(cookies + request.cookies))
return app.baseClient.newCall(
request.newBuilder()
.headers(headers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
}
}

val headers = getHeaders(request.headers.toMap(), cookies + request.cookies)
val headers = getHeaders(HashMap(request.headers.toMap()), HashMap(cookies + request.cookies))
return app.baseClient.newCall(
request.newBuilder()
.headers(headers)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,64 +1,109 @@
package com.lagradost.cloudstream3.network

import android.annotation.SuppressLint
import android.content.Context
import androidx.preference.PreferenceManager
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.nicehttp.Requests
import com.lagradost.nicehttp.ignoreAllSSLErrors
import okhttp3.Cache
import okhttp3.ConnectionSpec
import okhttp3.Headers
import okhttp3.Headers.Companion.toHeaders
import okhttp3.OkHttpClient
import org.conscrypt.Conscrypt
import java.io.File
import java.security.Security
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

fun Requests.initClient(context: Context): OkHttpClient {
normalSafeApiCall { Security.insertProviderAt(Conscrypt.newProvider(), 1) }

// see trust manager function below, this lib was used earlier
// normalSafeApiCall { Security.insertProviderAt(Conscrypt.newProvider(), 1) }
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
baseClient = OkHttpClient.Builder()

val builder = OkHttpClient.Builder()
.ignoreAllSSLErrors()
.sslSocketFactory(getUnsafeSSLSocketFactory(), TrustAllCerts())
.hostnameVerifier { _, _ -> true }
.connectionSpecs(listOf(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.followRedirects(true)
.followSslRedirects(true)
.ignoreAllSSLErrors()
.cache(
// Note that you need to add a ResponseInterceptor to make this 100% active.
// The server response dictates if and when stuff should be cached.
Cache(
directory = File(context.cacheDir, "http_cache"),
maxSize = 50L * 1024L * 1024L // 50 MiB
)
).apply {
when (dns) {
1 -> addGoogleDns()
2 -> addCloudFlareDns()
// 3 -> addOpenDns()
4 -> addAdGuardDns()
5 -> addDNSWatchDns()
6 -> addQuad9Dns()
}
}
// Needs to be build as otherwise the other builders will change this object
.build()
)
when (dns) {
1 -> builder.addGoogleDns()
2 -> builder.addCloudFlareDns()
// 3 -> builder.addOpenDns()
4 -> builder.addAdGuardDns()
5 -> builder.addDNSWatchDns()
6 -> builder.addQuad9Dns()
}

baseClient = builder.build()
return baseClient
}

//val Request.cookies: Map<String, String>
// get() {
// return this.headers.getCookies("Cookie")
// }
// Trust is an expensive thing, Cheap people can't afford it, lol;
/** So what happens in older android versions like 9 is that their network security provider is
* not much robust, and some extensions store data in non protected cheap servers and urls, thus
* the app rejects connection, We used google conscrypt provider lib earlier but its version 5.2.3
* broke and crashed the app without resolving certs, so we removed it and implemented own trust
* manager that trust all certificates + network_security_config.xml especially for Android 9 =-below
**/
@SuppressLint("CustomX509TrustManager")
class TrustAllCerts : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
override fun checkClientTrusted(
chain: Array<java.security.cert.X509Certificate>,
authType: String
) {
// Trust all client certificates
}

@SuppressLint("TrustAllX509TrustManager")
override fun checkServerTrusted(
chain: Array<java.security.cert.X509Certificate>,
authType: String
) {
// Trust all server certificates
}

@SuppressLint("TrustAllX509TrustManager")
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
return arrayOf()
}
}

/**
* Creates an SSLSocketFactory that uses a TrustManager which trusts all certificates.
* @return A custom SSLSocketFactory for bypassing SSL verification.
*/
fun getUnsafeSSLSocketFactory(): SSLSocketFactory {
val trustAllCerts = arrayOf<TrustManager>(TrustAllCerts())

val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
return sslContext.socketFactory
}

private val DEFAULT_HEADERS = mapOf("user-agent" to USER_AGENT)
private val DEFAULT_HEADERS = hashMapOf("User-Agent" to USER_AGENT)

/**
* Set headers > Set cookies > Default headers > Default Cookies
* TODO REMOVE AND REPLACE WITH NICEHTTP
*/
fun getHeaders(
headers: Map<String, String>,
cookie: Map<String, String>
headers: HashMap<String, String>,
cookie: HashMap<String, String>
): Headers {
val cookieMap =
if (cookie.isNotEmpty()) mapOf(
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<!-- Allow all domains, including subdomains -->
<domain includeSubdomains="true">.</domain>

<!-- Allow any certificate, including those with errors -->
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</domain-config>

<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>