summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorTom Hennen <TomHennen@users.noreply.github.com>2015-03-09 20:52:35 -0400
committerTom Hennen <TomHennen@users.noreply.github.com>2015-03-09 20:52:35 -0400
commitd312f883fef287501e33e59dfd36bb9f1ef6244f (patch)
tree1796128f23dfff3fd8e87550f0c0ed74082462d1 /core
parent4a789221806f316a64f81ca5fe50a22c4b920a2a (diff)
parent11412e611ecf89a1f525e1430f23c6eb4d396708 (diff)
downloadAntennaPod-d312f883fef287501e33e59dfd36bb9f1ef6244f.zip
Merge pull request #667 from mfietz/issue-576
make gpodder service usable for older devices again
Diffstat (limited to 'core')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java95
1 files changed, 93 insertions, 2 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java
index 5ee40186f..791ccd5ec 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java
@@ -1,5 +1,8 @@
package de.danoeh.antennapod.core.gpoddernet;
+import android.os.Build;
+import android.util.Log;
+
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
@@ -18,16 +21,27 @@ import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.CookieManager;
-import java.net.CookiePolicy;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.security.KeyStore;
+import java.security.Principal;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import javax.security.auth.x500.X500Principal;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;
@@ -43,6 +57,8 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
*/
public class GpodnetService {
+ private static final String TAG = "GpodnetService";
+
private static final String BASE_SCHEME = "https";
public static final String DEFAULT_BASE_HOST = "gpodder.net";
@@ -56,9 +72,84 @@ public class GpodnetService {
public GpodnetService() {
httpClient = AntennapodHttpClient.getHttpClient();
+ if (Build.VERSION.SDK_INT <= 10) {
+ Log.d(TAG, "Use custom SSL factory");
+ SSLSocketFactory factory = getCustomSslSocketFactory();
+ httpClient.setSslSocketFactory(factory);
+ }
BASE_HOST = GpodnetPreferences.getHostname();
}
+ private synchronized static SSLSocketFactory getCustomSslSocketFactory() {
+ try {
+ TrustManagerFactory defaultTrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ defaultTrustManagerFactory.init((KeyStore) null); // use system keystore
+ final X509TrustManager defaultTrustManager = (X509TrustManager) defaultTrustManagerFactory.getTrustManagers()[0];
+ TrustManager[] customTrustManagers = new TrustManager[]{new X509TrustManager() {
+ @Override
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ @Override
+ public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ // chain may out of order - construct data structures to walk from server certificate to root certificate
+ Map<Principal, X509Certificate> certificates = new HashMap<Principal, X509Certificate>(chain.length - 1);
+ X509Certificate subject = null;
+ for (X509Certificate cert : chain) {
+ cert.checkValidity();
+ if (cert.getSubjectDN().toString().startsWith("CN=" + DEFAULT_BASE_HOST)) {
+ subject = cert;
+ } else {
+ certificates.put(cert.getSubjectDN(), cert);
+ }
+ }
+ if (subject == null) {
+ throw new CertificateException("Chain does not contain a certificate for " + DEFAULT_BASE_HOST);
+ }
+ // follow chain to root CA
+ while (certificates.get(subject.getIssuerDN()) != null) {
+ subject.checkValidity();
+ X509Certificate issuer = certificates.get(subject.getIssuerDN());
+ try {
+ subject.verify(issuer.getPublicKey());
+ } catch (Exception e) {
+ Log.d(TAG, "failed: " + issuer.getSubjectDN() + " -> " + subject.getSubjectDN());
+ throw new CertificateException("Could not verify certificate");
+ }
+ subject = issuer;
+ }
+ X500Principal rootAuthority = subject.getIssuerX500Principal();
+ boolean accepted = false;
+ for (X509Certificate cert :
+ defaultTrustManager.getAcceptedIssuers()) {
+ if (cert.getSubjectX500Principal().equals(rootAuthority)) {
+ try {
+ subject.verify(cert.getPublicKey());
+ accepted = true;
+ } catch (Exception e) {
+ Log.d(TAG, "failed: " + cert.getSubjectDN() + " -> " + subject.getSubjectDN());
+ throw new CertificateException("Could not verify root certificate");
+ }
+ }
+ }
+ if (accepted == false) {
+ throw new CertificateException("Could not verify root certificate");
+ }
+ }
+ }};
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, customTrustManagers, null);
+ return sslContext.getSocketFactory();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
/**
* Returns the [count] most used tags.
*/