Skip to content
Closed
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
77 changes: 5 additions & 72 deletions app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package org.schabi.newpipe;

import android.content.Context;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;

import org.schabi.newpipe.error.ReCaptchaActivity;
import org.schabi.newpipe.extractor.downloader.Downloader;
Expand All @@ -14,33 +9,22 @@
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.util.CookieUtils;
import org.schabi.newpipe.util.InfoCache;
import org.schabi.newpipe.util.TLSSocketFactoryCompat;
import org.schabi.newpipe.util.OkHttpTlsHelper;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

import static org.schabi.newpipe.MainActivity.DEBUG;

public final class DownloaderImpl extends Downloader {
public static final String USER_AGENT
= "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0";
Expand All @@ -54,9 +38,7 @@ public final class DownloaderImpl extends Downloader {
private final OkHttpClient client;

private DownloaderImpl(final OkHttpClient.Builder builder) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
enableModernTLS(builder);
}
OkHttpTlsHelper.enableModernTLS(builder);
this.client = builder
.readTimeout(30, TimeUnit.SECONDS)
// .cache(new Cache(new File(context.getExternalCacheDir(), "okhttp"),
Expand All @@ -81,55 +63,6 @@ public static DownloaderImpl getInstance() {
return instance;
}

/**
* Enable TLS 1.2 and 1.1 on Android Kitkat. This function is mostly taken
* from the documentation of OkHttpClient.Builder.sslSocketFactory(_,_).
* <p>
* If there is an error, the function will safely fall back to doing nothing
* and printing the error to the console.
* </p>
*
* @param builder The HTTPClient Builder on which TLS is enabled on (will be modified in-place)
*/
private static void enableModernTLS(final OkHttpClient.Builder builder) {
try {
// get the default TrustManager
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
final X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

// insert our own TLSSocketFactory
final SSLSocketFactory sslSocketFactory = TLSSocketFactoryCompat.getInstance();

builder.sslSocketFactory(sslSocketFactory, trustManager);

// This will try to enable all modern CipherSuites(+2 more)
// that are supported on the device.
// Necessary because some servers (e.g. Framatube.org)
// don't support the old cipher suites.
// https://github.com/square/okhttp/issues/4053#issuecomment-402579554
final List<CipherSuite> cipherSuites =
new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
final ConnectionSpec legacyTLS = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
.build();

builder.connectionSpecs(Arrays.asList(legacyTLS, ConnectionSpec.CLEARTEXT));
} catch (final KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
if (DEBUG) {
e.printStackTrace();
}
}
}

public String getCookies(final String url) {
final List<String> resultCookies = new ArrayList<>();
if (url.contains(YOUTUBE_DOMAIN)) {
Expand Down
84 changes: 84 additions & 0 deletions app/src/main/java/org/schabi/newpipe/util/OkHttpTlsHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.schabi.newpipe.util;

import android.os.Build;

import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;

import static org.schabi.newpipe.MainActivity.DEBUG;

public final class OkHttpTlsHelper {

private OkHttpTlsHelper() {
}

/**
* Enable TLS 1.2 and 1.1 on Android Kitkat. This function is mostly taken
* from the documentation of OkHttpClient.Builder.sslSocketFactory(_,_).
* <p>
* If there is an error, the function will safely fall back to doing nothing
* and printing the error to the console.
* </p>
*
* @param builder The HTTPClient Builder on which TLS is enabled on (will be modified in-place)
* @return the same builder that was supplied. So the method can be chained.
*/
public static OkHttpClient.Builder enableModernTLS(final OkHttpClient.Builder builder) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
try {
// get the default TrustManager
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
final X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

// insert our own TLSSocketFactory
final SSLSocketFactory sslSocketFactory = TLSSocketFactoryCompat.getInstance();

builder.sslSocketFactory(sslSocketFactory, trustManager);

// This will try to enable all modern CipherSuites(+2 more)
// that are supported on the device.
// Necessary because some servers (e.g. Framatube.org)
// don't support the old cipher suites.
// https://github.com/square/okhttp/issues/4053#issuecomment-402579554
final List<CipherSuite> cipherSuites =
new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
final ConnectionSpec legacyTLS =
new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
.build();

builder.connectionSpecs(Arrays.asList(legacyTLS, ConnectionSpec.CLEARTEXT));
} catch (final KeyManagementException | NoSuchAlgorithmException
| KeyStoreException e) {
if (DEBUG) {
e.printStackTrace();
}
}
}

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private PicassoHelper() {

public static void init(final Context context) {
picassoCache = new LruCache(10 * 1024 * 1024);
picassoDownloaderClient = new OkHttpClient.Builder()
picassoDownloaderClient = OkHttpTlsHelper.enableModernTLS(new OkHttpClient.Builder())
.cache(new okhttp3.Cache(new File(context.getExternalCacheDir(), "picasso"),
50 * 1024 * 1024))
// this should already be the default timeout in OkHttp3, but just to be sure...
Expand Down