diff options
author | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 14:35:15 +0000 |
---|---|---|
committer | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 14:35:15 +0000 |
commit | 18c360a66717dd9d818d0331e2c687475f117af0 (patch) | |
tree | 00536531832727c9379d96c494f74cdebceb44a1 /net/android | |
parent | f2026eb8850367e0a993cac3e32fcae2f0afcdc0 (diff) | |
download | chromium_src-18c360a66717dd9d818d0331e2c687475f117af0.zip chromium_src-18c360a66717dd9d818d0331e2c687475f117af0.tar.gz chromium_src-18c360a66717dd9d818d0331e2c687475f117af0.tar.bz2 |
Listen for new system certificates.
Android use the system certificate database. This CL ensure that a
modification of the system certificates is received by services that
listen for those.
BUG=149426
Review URL: https://codereview.chromium.org/27500004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230126 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/android')
-rw-r--r-- | net/android/java/src/org/chromium/net/X509Util.java | 69 | ||||
-rw-r--r-- | net/android/javatests/src/org/chromium/net/X509UtilTest.java | 5 | ||||
-rw-r--r-- | net/android/net_jni_registrar.cc | 2 | ||||
-rw-r--r-- | net/android/x509_util.cc | 25 | ||||
-rw-r--r-- | net/android/x509_util.h | 16 |
5 files changed, 117 insertions, 0 deletions
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java index 30007ca..4358f2b 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(); + } diff --git a/net/android/javatests/src/org/chromium/net/X509UtilTest.java b/net/android/javatests/src/org/chromium/net/X509UtilTest.java index 7dcbc68..e5c3f6f 100644 --- a/net/android/javatests/src/org/chromium/net/X509UtilTest.java +++ b/net/android/javatests/src/org/chromium/net/X509UtilTest.java @@ -71,6 +71,11 @@ public class X509UtilTest extends InstrumentationTestCase { return bytes; } + @Override + public void setUp() { + X509Util.setDisableCertificateObservationForTest(true); + } + @MediumTest public void testEkusVerified() throws GeneralSecurityException, IOException { X509Util.addTestRootCertificate(pemToDer(CERTS_DIRECTORY + BAD_EKU_TEST_ROOT)); diff --git a/net/android/net_jni_registrar.cc b/net/android/net_jni_registrar.cc index a6e09b6..ab99725 100644 --- a/net/android/net_jni_registrar.cc +++ b/net/android/net_jni_registrar.cc @@ -11,6 +11,7 @@ #include "net/android/keystore.h" #include "net/android/network_change_notifier_android.h" #include "net/android/network_library.h" +#include "net/android/x509_util.h" #include "net/proxy/proxy_config_service_android.h" namespace net { @@ -23,6 +24,7 @@ static base::android::RegistrationMethod kNetRegisteredMethods[] = { { "NetworkChangeNotifierAndroid", net::NetworkChangeNotifierAndroid::Register }, { "ProxyConfigService", net::ProxyConfigServiceAndroid::Register }, + { "X509Util", net::RegisterX509Util }, }; bool RegisterJni(JNIEnv* env) { diff --git a/net/android/x509_util.cc b/net/android/x509_util.cc new file mode 100644 index 0000000..9f3491f --- /dev/null +++ b/net/android/x509_util.cc @@ -0,0 +1,25 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/android/x509_util.h" + +#include "base/android/jni_android.h" +#include "jni/X509Util_jni.h" +#include "net/cert/cert_database.h" + +namespace net { + +void NotifyKeyChainChanged(JNIEnv* env, jclass clazz) { + CertDatabase::GetInstance()->OnAndroidKeyChainChanged(); +} + +jobject GetApplicationContext(JNIEnv* env, jclass clazz) { + return base::android::GetApplicationContext(); +} + +bool RegisterX509Util(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // net namespace diff --git a/net/android/x509_util.h b/net/android/x509_util.h new file mode 100644 index 0000000..963dd23 --- /dev/null +++ b/net/android/x509_util.h @@ -0,0 +1,16 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_ANDROID_X509_UTIL_H_ +#define NET_ANDROID_X509_UTIL_H_ + +#include <jni.h> + +namespace net { + +bool RegisterX509Util(JNIEnv* env); + +} // net namespace + +#endif // NET_ANDROID_X509_UTIL_H_ |