summaryrefslogtreecommitdiffstats
path: root/net/android
diff options
context:
space:
mode:
authorqsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-22 14:35:15 +0000
committerqsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-22 14:35:15 +0000
commit18c360a66717dd9d818d0331e2c687475f117af0 (patch)
tree00536531832727c9379d96c494f74cdebceb44a1 /net/android
parentf2026eb8850367e0a993cac3e32fcae2f0afcdc0 (diff)
downloadchromium_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.java69
-rw-r--r--net/android/javatests/src/org/chromium/net/X509UtilTest.java5
-rw-r--r--net/android/net_jni_registrar.cc2
-rw-r--r--net/android/x509_util.cc25
-rw-r--r--net/android/x509_util.h16
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_