diff --git a/extern/MemorizingTrustManager b/extern/MemorizingTrustManager
index a705441ac..cd9bbf8f7 160000
--- a/extern/MemorizingTrustManager
+++ b/extern/MemorizingTrustManager
@@ -1 +1 @@
-Subproject commit a705441ac53b9e1aba9f00f3f59aab81da6fbc9e
+Subproject commit cd9bbf8f7cc3cffa1abe1a7a2c775f345e7c489f
diff --git a/lint.xml b/lint.xml
index d8c98cba9..6e7f54486 100644
--- a/lint.xml
+++ b/lint.xml
@@ -1,11 +1,12 @@
-
+
-
+
+
-
+
\ No newline at end of file
diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java
index 54111e958..ac6bd08bb 100644
--- a/src/org/fdroid/fdroid/FDroidApp.java
+++ b/src/org/fdroid/fdroid/FDroidApp.java
@@ -23,21 +23,34 @@ import android.app.Activity;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
-import android.content.*;
-import android.content.pm.*;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
-import android.os.*;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
+
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.utils.StorageUtils;
+
import de.duenndns.ssl.MemorizingTrustManager;
+
import org.fdroid.fdroid.Preferences.ChangeListener;
import org.fdroid.fdroid.compat.PRNGFixes;
import org.fdroid.fdroid.data.AppProvider;
@@ -49,16 +62,14 @@ import org.fdroid.fdroid.net.WifiStateChangeService;
import org.thoughtcrime.ssl.pinning.PinningTrustManager;
import org.thoughtcrime.ssl.pinning.SystemKeyStore;
+import java.io.File;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Set;
+
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 java.io.File;
-import java.security.*;
-import java.util.Set;
-
-import javax.net.ssl.*;
public class FDroidApp extends Application {
@@ -179,31 +190,27 @@ public class FDroidApp extends Application {
try {
SSLContext sc = SSLContext.getInstance("TLS");
- X509TrustManager defaultTrustManager = null;
+ // MemorizingTrustManager -> PinningTrustManager -> Prompt User
/*
- * init a trust manager factory with a null keystore to access the system trust managers
+ * The current HTTPS trust model is to first check if a site's key
+ * is TOFUed, then check if it is pinned and valid with the CA, then
+ * prompt the user. There is currently no way to only check the CA
+ * for validity. Ultimately, that should probably not be needed if
+ * the repo URLs can include the HTTPS pin info in the same way that
+ * the repo fingerprint is specified. Then it can be added to the
+ * TOFU/POP keystore when the user accepts the Add Repo dialog
*/
- 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];
+ PinningTrustManager pinMgr = new PinningTrustManager(
+ SystemKeyStore.getInstance(getApplicationContext()),
+ FDroidCertPins.getPinList(),
+ 0);
+ MemorizingTrustManager memMgr = new MemorizingTrustManager(getApplicationContext(), pinMgr);
/*
- * compose a chain of trust managers as follows:
- * MemorizingTrustManager -> Pinning Trust Manager -> System Trust Manager
- */
- PinningTrustManager pinMgr = new PinningTrustManager(SystemKeyStore.getInstance(getApplicationContext()),FDroidCertPins.getPinList(), 0);
- MemorizingTrustManager memMgr = new MemorizingTrustManager(getApplicationContext(), pinMgr, defaultTrustManager);
-
- /*
- * initialize a SSLContext with the outermost trust manager, use this
- * context to set the default SSL socket factory for the HTTPSURLConnection
- * class.
+ * 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());
@@ -211,8 +218,6 @@ public class FDroidApp extends Application {
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");
}
// initialized the local repo information
diff --git a/src/org/fdroid/fdroid/FDroidCertPins.java b/src/org/fdroid/fdroid/FDroidCertPins.java
index 646a792b2..d91563edb 100644
--- a/src/org/fdroid/fdroid/FDroidCertPins.java
+++ b/src/org/fdroid/fdroid/FDroidCertPins.java
@@ -23,21 +23,31 @@ 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",
+
+ // OU=PositiveSSL, CN=f-droid.org
+ // Fingerprint: 84B91CDF2312CB9BA7F3BE803783302F8D8C299F
+ "638F93856E1F5EDFCBD40C46D4160CFF21B0713A",
+
+ // OU=Gandi Standard SSL, CN=guardianproject.info
+ "cf2f8e226027599a1a933701418c58ec688a8305",
+
+ // C=US, ST=Washington, L=Seattle, O=Amazon.com Inc., CN=s3.amazonaws.com
+ "5e77905babb66ca7082979435afbe4edf3f5af12",
+
+ // OU=Domain Control Validated - RapidSSL(R), CN=www.psiphon.ca
+ "3aa1726e64d54bf58bf68fe23208928fd0d9cf8a",
+
+ // OU=EssentialSSL Wildcard, CN=*.panicbutton.io
+ "cdae8cc70af09a55a7642d13f84241cba1c3a3e6",
};
public static ArrayList PINLIST = null;
public static String[] getPinList() {
if (PINLIST == null) {
- PINLIST = new ArrayList();
- PINLIST.addAll(Arrays.asList(DEFAULT_PINS));
+ ArrayList pinlist = new ArrayList();
+ pinlist.addAll(Arrays.asList(DEFAULT_PINS));
+ PINLIST = pinlist;
}
return PINLIST.toArray(new String[PINLIST.size()]);
diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java
index 0638806c9..c7455047e 100644
--- a/src/org/fdroid/fdroid/UpdateService.java
+++ b/src/org/fdroid/fdroid/UpdateService.java
@@ -180,7 +180,7 @@ public class UpdateService extends IntentService implements ProgressListener {
if (finished) {
forwardEvent(EVENT_FINISHED);
- if (dialog.isShowing()) {
+ if (dialog != null && dialog.isShowing()) {
try {
dialog.dismiss();
} catch (IllegalArgumentException e) {
diff --git a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java
index 6d43781b5..e8325ecd4 100644
--- a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java
+++ b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java
@@ -6,10 +6,13 @@ import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.preference.PreferenceManager;
import android.support.v4.app.LoaderManager;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -97,8 +100,7 @@ public class AvailableAppsFragment extends AppListFragment implements
// attempt to translate category names with fallback to default name
List translatedCategories = new ArrayList(categories.size());
Resources res = getResources();
- for (String category : categories)
- {
+ for (String category : categories) {
int id = res.getIdentifier(category.replace(" & ", "_"), "string", getActivity().getPackageName());
translatedCategories.add(id == 0 ? category : getString(id));
}
@@ -108,8 +110,15 @@ public class AvailableAppsFragment extends AppListFragment implements
// functionality do its stuff.
categorySpinner.setId(R.id.categorySpinner);
// with holo, the menu gets lost since it looks the same as an app list item
- if (Build.VERSION.SDK_INT >= 14)
- categorySpinner.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.btn_dropdown));
+ if (Build.VERSION.SDK_INT >= 14) {
+ Drawable menuButton = getResources().getDrawable(android.R.drawable.btn_dropdown);
+ if (TextUtils.equals("dark",
+ PreferenceManager.getDefaultSharedPreferences(getActivity())
+ .getString(Preferences.PREF_THEME, "dark"))) {
+ menuButton.setAlpha(32); // make it darker via alpha
+ }
+ categorySpinner.setBackgroundDrawable(menuButton);
+ }
ArrayAdapter adapter = new ArrayAdapter(
getActivity(), android.R.layout.simple_spinner_item, translatedCategories);