Index: net/android/java/src/org/chromium/net/X509Util.java |
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java |
index 30007caab17d9ed60f8237f806d39e641e62634d..4358f2beb7ac44ad719df523feca9638231b28f2 100644 |
--- a/net/android/java/src/org/chromium/net/X509Util.java |
+++ b/net/android/java/src/org/chromium/net/X509Util.java |
@@ -4,8 +4,14 @@ |
package org.chromium.net; |
+import android.content.BroadcastReceiver; |
+import android.content.Context; |
+import android.content.Intent; |
+import android.content.IntentFilter; |
+import android.security.KeyChain; |
import android.util.Log; |
+import org.chromium.base.JNINamespace; |
import org.chromium.net.CertVerifyResultAndroid; |
import java.io.ByteArrayInputStream; |
@@ -25,10 +31,30 @@ import javax.net.ssl.TrustManager; |
import javax.net.ssl.TrustManagerFactory; |
import javax.net.ssl.X509TrustManager; |
+@JNINamespace("net") |
public class X509Util { |
private static final String TAG = "X509Util"; |
+ public static final class TrustStorageListener extends BroadcastReceiver { |
+ @Override public void onReceive(Context context, Intent intent) { |
+ if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { |
+ try { |
+ reloadDefaultTrustManager(); |
+ } |
+ catch (CertificateException e) { |
+ Log.e(TAG, "Unable to reload the default TrustManager", e); |
+ } |
+ catch (KeyStoreException e) { |
+ Log.e(TAG, "Unable to reload the default TrustManager", e); |
+ } |
+ catch (NoSuchAlgorithmException e) { |
+ Log.e(TAG, "Unable to reload the default TrustManager", e); |
+ } |
+ } |
+ } |
+ } |
+ |
private static CertificateFactory sCertificateFactory; |
private static final String OID_TLS_SERVER_AUTH = "1.3.6.1.5.5.7.3.1"; |
@@ -45,6 +71,12 @@ public class X509Util { |
private static X509TrustManager sDefaultTrustManager; |
/** |
+ * BroadcastReceiver that listens to change in the system keystore to invalidate certificate |
+ * caches. |
+ */ |
+ private static TrustStorageListener sTrustStorageListener; |
+ |
+ /** |
* Trust manager backed up by a custom certificate store. We need such manager to plant test |
* root CA to the trust store in testing. |
*/ |
@@ -56,6 +88,13 @@ public class X509Util { |
*/ |
private static final Object sLock = new Object(); |
+ /* |
+ * Allow disabling registering the observer for the certificat changes. Net unit tests do not |
+ * load native libraries which prevent this to succeed. Moreover, the system does not allow to |
+ * interact with the certificate store without user interaction. |
+ */ |
+ private static boolean sDisableCertificateObservationForTest = false; |
+ |
/** |
* Ensures that the trust managers and certificate factory are initialized. |
*/ |
@@ -77,6 +116,12 @@ public class X509Util { |
if (sTestTrustManager == null) { |
sTestTrustManager = X509Util.createTrustManager(sTestKeyStore); |
} |
+ if (!sDisableCertificateObservationForTest && |
+ sTrustStorageListener == null) { |
+ sTrustStorageListener = new TrustStorageListener(); |
+ nativeGetApplicationContext().registerReceiver(sTrustStorageListener, |
+ new IntentFilter(KeyChain.ACTION_STORAGE_CHANGED)); |
+ } |
} |
} |
@@ -108,6 +153,16 @@ public class X509Util { |
} |
/** |
+ * After each modification by the system of the key store, trust manager has to be regenerated. |
+ */ |
+ private static void reloadDefaultTrustManager() throws KeyStoreException, |
+ NoSuchAlgorithmException, CertificateException { |
+ sDefaultTrustManager = null; |
+ nativeNotifyKeyChainChanged(); |
+ ensureInitialized(); |
+ } |
+ |
+ /** |
* Convert a DER encoded certificate to an X509Certificate. |
*/ |
public static X509Certificate createCertificateFromBytes(byte[] derBytes) throws |
@@ -230,4 +285,18 @@ public class X509Util { |
} |
} |
} |
+ |
+ public static void setDisableCertificateObservationForTest(boolean disabled) { |
+ sDisableCertificateObservationForTest = disabled; |
+ } |
+ /** |
+ * Notify the native net::CertDatabase instance that the system database has been updated. |
+ */ |
+ private static native void nativeNotifyKeyChainChanged(); |
+ |
+ /** |
+ * Returns the application context. |
+ */ |
+ private static native Context nativeGetApplicationContext(); |
+ |
} |