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);