diff --git a/.gitmodules b/.gitmodules
index ca1aa6458..eeaf305bc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,9 @@
path = extern/Universal-Image-Loader
url = https://github.com/nostra13/Android-Universal-Image-Loader
ignore = dirty
+[submodule "extern/MemorizingTrustManager"]
+ path = extern/MemorizingTrustManager
+ url = https://github.com/ge0rg/MemorizingTrustManager.git
+[submodule "extern/AndroidPinning"]
+ path = extern/AndroidPinning
+ url = https://github.com/binaryparadox/AndroidPinning.git
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e6366d4ca..0118acdf9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -200,6 +200,9 @@
android:name="android.app.searchable"
android:resource="@xml/searchable" />
+
+
+
diff --git a/README.md b/README.md
index 718c54b73..cf4b657a3 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,10 @@ The only required tools are the Android SDK and Apache Ant.
```
git submodule update --init
-android update project -p .
-android update project -p extern/Universal-Image-Loader/library
+android update project -p . --name F-droid
+android update lib-project -p extern/Universal-Image-Loader/library
+android update lib-project -p extern/AndroidPinning
+android update lib-project -p extern/MemorizingTrustManager
ant clean release
```
diff --git a/extern/AndroidPinning b/extern/AndroidPinning
new file mode 160000
index 000000000..526654e1b
--- /dev/null
+++ b/extern/AndroidPinning
@@ -0,0 +1 @@
+Subproject commit 526654e1b9997b32e513d58d9094d4c1102a6cb3
diff --git a/extern/MemorizingTrustManager b/extern/MemorizingTrustManager
new file mode 160000
index 000000000..49452f67a
--- /dev/null
+++ b/extern/MemorizingTrustManager
@@ -0,0 +1 @@
+Subproject commit 49452f67a760dfef77ddaa7e0b7d88c713c4a195
diff --git a/project.properties b/project.properties
index 9d03d0bbe..6da907dd2 100644
--- a/project.properties
+++ b/project.properties
@@ -3,3 +3,5 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.
target=android-19
android.library.reference.1=extern/Universal-Image-Loader/library
+android.library.reference.2=extern/MemorizingTrustManager
+android.library.reference.3=extern/AndroidPinning
diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java
index 7523c5245..0558d1f25 100644
--- a/src/org/fdroid/fdroid/FDroidApp.java
+++ b/src/org/fdroid/fdroid/FDroidApp.java
@@ -19,26 +19,45 @@
package org.fdroid.fdroid;
import java.io.File;
-import java.lang.Runtime;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
-import android.app.Application;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
import android.app.Activity;
-import android.preference.PreferenceManager;
-import android.util.Log;
+import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import org.fdroid.fdroid.Utils;
+import android.graphics.Bitmap;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache;
+import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
+import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
+import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.utils.StorageUtils;
+import de.duenndns.ssl.MemorizingTrustManager;
+
+import org.thoughtcrime.ssl.pinning.PinningTrustManager;
+import org.thoughtcrime.ssl.pinning.SystemKeyStore;
+
public class FDroidApp extends Application {
private static enum Theme {
@@ -117,6 +136,44 @@ public class FDroidApp extends Application {
.threadPoolSize(Runtime.getRuntime().availableProcessors() * 2)
.build();
ImageLoader.getInstance().init(config);
+
+ try {
+ SSLContext sc = SSLContext.getInstance("TLS");
+ X509TrustManager defaultTrustManager = null;
+
+ /*
+ * init a trust manager factory with a null keystore to access the system trust managers
+ */
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore ks = null;
+ tmf.init(ks);
+ TrustManager[] mgrs = tmf.getTrustManagers();
+
+ if(mgrs.length > 0 && mgrs[0] instanceof X509TrustManager)
+ defaultTrustManager = (X509TrustManager) mgrs[0];
+
+ /*
+ * compose a chain of trust managers as follows:
+ * MemorizingTrustManager -> Pinning Trust Manager -> System Trust Manager
+ */
+ PinningTrustManager pinMgr = new PinningTrustManager(SystemKeyStore.getInstance(ctx),FDroidCertPins.getPinList(), 0);
+ MemorizingTrustManager memMgr = new MemorizingTrustManager(ctx, pinMgr, defaultTrustManager);
+
+ /*
+ * initialize a SSLContext with the outermost trust manager, use this
+ * context to set the default SSL socket factory for the HTTPSURLConnection
+ * class.
+ */
+ sc.init(null, new TrustManager[] {memMgr}, new java.security.SecureRandom());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+ } catch (KeyManagementException e) {
+ Log.e("FDroid", "Unable to set up trust manager chain. KeyManagementException");
+ } catch (NoSuchAlgorithmException e) {
+ Log.e("FDroid", "Unable to set up trust manager chain. NoSuchAlgorithmException");
+ } catch (KeyStoreException e) {
+ Log.e("FDroid", "Unable to set up trust manager chain. KeyStoreException");
+ }
}
private Context ctx;
diff --git a/src/org/fdroid/fdroid/FDroidCertPins.java b/src/org/fdroid/fdroid/FDroidCertPins.java
new file mode 100644
index 000000000..09627a0fc
--- /dev/null
+++ b/src/org/fdroid/fdroid/FDroidCertPins.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.fdroid.fdroid;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class FDroidCertPins {
+ public static final String[] DEFAULT_PINS =
+ {
+ /*
+ * SubjectDN: CN=f-droid.org, OU=PositiveSSL, OU=Domain Control Validated
+ * IssuerDN: CN=PositiveSSL CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
+ * Fingerprint: 84B91CDF2312CB9BA7F3BE803783302F8D8C299F
+ * SPKI Pin: 638F93856E1F5EDFCBD40C46D4160CFF21B0713A
+ */
+ "638F93856E1F5EDFCBD40C46D4160CFF21B0713A",
+
+ /*
+ * SubjectDN: CN=guardianproject.info, OU=Gandi Standard SSL, OU=Domain Control Validated
+ * IssuerDN: CN=Gandi Standard SSL CA, O=GANDI SAS, C=FR
+ * Fingerprint: 187C2573E924DFCBFF2A781A2F99D71C6E031828
+ * SPKI Pin: EB6BBC6C6BAEEA20CB0F3357720D86E0F3A526F4
+ */
+ "EB6BBC6C6BAEEA20CB0F3357720D86E0F3A526F4",
+ };
+
+ public static ArrayList PINLIST = null;
+
+ public static String[] getPinList()
+ {
+ if(PINLIST == null)
+ {
+ PINLIST = new ArrayList();
+ PINLIST.addAll(Arrays.asList(DEFAULT_PINS));
+ }
+
+ return PINLIST.toArray(new String[PINLIST.size()]);
+ }
+}