summaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-11-19 12:37:23 +0000
committerBen Murdoch <benm@google.com>2010-11-19 16:52:35 +0000
commit76a88e2c298122bfdfc498a5df61aab702184639 (patch)
tree755358c235b4d839842b272e1462a26e68d8c159 /android
parent34b5a0345856ab7743b6daa5a1fea1dcbe0c3394 (diff)
downloadexternal_chromium-76a88e2c298122bfdfc498a5df61aab702184639.zip
external_chromium-76a88e2c298122bfdfc498a5df61aab702184639.tar.gz
external_chromium-76a88e2c298122bfdfc498a5df61aab702184639.tar.bz2
Merge Chromium at r65505: OpenSSL support
Import OpenSSL support and tweak for our Chromium port (JNI functions). See https://chromereview.prom.corp.google.com/2010002/ Change-Id: Ia081dd3b1eae5ec05ebb96b66b682f039bfa1b81
Diffstat (limited to 'android')
-rw-r--r--android/jni/jni_utils.cc18
-rw-r--r--android/jni/jni_utils.h6
-rw-r--r--android/net/android_network_library_impl.cc142
-rw-r--r--android/net/android_network_library_impl.h35
4 files changed, 201 insertions, 0 deletions
diff --git a/android/jni/jni_utils.cc b/android/jni/jni_utils.cc
index ceb0777..91e5266 100644
--- a/android/jni/jni_utils.cc
+++ b/android/jni/jni_utils.cc
@@ -14,6 +14,7 @@
namespace JSC {
namespace Bindings {
JNIEnv* getJNIEnv();
+JavaVM* getJavaVM();
}
}
@@ -21,6 +22,7 @@ JNIEnv* getJNIEnv();
namespace android {
std::string jstringToStdString(JNIEnv* env, jstring jstr);
string16 jstringToString16(JNIEnv* env, jstring jstr);
+bool checkException(JNIEnv*);
}
namespace android {
@@ -38,5 +40,21 @@ string16 JstringToString16(JNIEnv* env, jstring jstr)
return jstringToString16(env, jstr);
}
+bool CheckException(JNIEnv* env)
+{
+ return checkException(env);
+}
+
+jstring ConvertUTF8ToJavaString(JNIEnv* env, std::string str)
+{
+ return env->NewStringUTF(str.c_str());
+}
+
+void DetachFromVM()
+{
+ JavaVM* vm = JSC::Bindings::getJavaVM();
+ vm->DetachCurrentThread();
+}
+
} // namespace android
diff --git a/android/jni/jni_utils.h b/android/jni/jni_utils.h
index f45de7a..60d7cde 100644
--- a/android/jni/jni_utils.h
+++ b/android/jni/jni_utils.h
@@ -17,5 +17,11 @@ std::string JstringToStdString(JNIEnv* env, jstring jstr);
string16 JstringToString16(JNIEnv* env, jstring jstr);
+jstring ConvertUTF8ToJavaString(JNIEnv* env, std::string str);
+
+bool CheckException(JNIEnv*);
+
+void DetachFromVM();
+
} // namespace android
diff --git a/android/net/android_network_library_impl.cc b/android/net/android_network_library_impl.cc
new file mode 100644
index 0000000..8e4aa0e
--- /dev/null
+++ b/android/net/android_network_library_impl.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2010 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 "android/net/android_network_library_impl.h"
+
+#include "base/logging.h"
+#include "android/jni/jni_utils.h"
+
+using namespace android;
+
+namespace {
+
+const char* const kClassPathName = "android/net/http/CertificateChainValidator";
+
+// Convert X509 chain to DER format bytes.
+jobjectArray GetCertificateByteArray(
+ JNIEnv* env,
+ const std::vector<std::string> cert_chain) {
+ size_t count = cert_chain.size();
+ DCHECK_GT(count, 0U);
+ // TODO(joth): See if we can centrally cache common classes like this, e.g.
+ // as JniConstants does.
+ jclass byte_array_class = env->FindClass("[B");
+ jobjectArray joa = env->NewObjectArray(count, byte_array_class, NULL);
+ if (joa == NULL)
+ return NULL;
+
+ for (size_t i = 0; i < count; ++i) {
+ size_t len = cert_chain[i].length();
+
+ jbyteArray byte_array = env->NewByteArray(len);
+ if (!byte_array) {
+ env->DeleteLocalRef(joa);
+ return NULL;
+ }
+
+ jbyte* bytes = env->GetByteArrayElements(byte_array, NULL);
+ DCHECK(bytes);
+ size_t copied = cert_chain[i].copy(reinterpret_cast<char*>(bytes), len);
+ DCHECK_EQ(copied, len);
+ env->ReleaseByteArrayElements(byte_array, bytes, 0);
+ env->SetObjectArrayElement(joa, i, byte_array);
+ env->DeleteLocalRef(byte_array);
+ }
+ return joa;
+}
+
+} // namespace
+
+AndroidNetworkLibraryImpl::VerifyResult
+ AndroidNetworkLibraryImpl::VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type) {
+ if (!cert_verifier_class_)
+ return VERIFY_INVOCATION_ERROR;
+
+ JNIEnv* env = GetJNIEnv();
+ DCHECK(env);
+
+ static jmethodID verify_fn = env->GetStaticMethodID(
+ cert_verifier_class_, "verifyServerCertificates",
+ "([[BLjava/lang/String;Ljava/lang/String;)Landroid/net/http/SslError;");
+ if (CheckException(env)) {
+ LOG(ERROR) << "verifyServerCertificates method not found; skipping";
+ return VERIFY_INVOCATION_ERROR;
+ }
+ DCHECK(verify_fn);
+
+ jobjectArray chain_byte_array = GetCertificateByteArray(env, cert_chain);
+ if (!chain_byte_array)
+ return VERIFY_INVOCATION_ERROR;
+
+ jstring host_string = ConvertUTF8ToJavaString(env, hostname);
+ DCHECK(host_string);
+ jstring auth_string = ConvertUTF8ToJavaString(env, auth_type);
+ DCHECK(auth_string);
+
+ jobject error = env->CallStaticObjectMethod(cert_verifier_class_, verify_fn,
+ chain_byte_array, host_string,
+ auth_string);
+ env->DeleteLocalRef(chain_byte_array);
+ env->DeleteLocalRef(host_string);
+ env->DeleteLocalRef(auth_string);
+
+ VerifyResult result = VERIFY_INVOCATION_ERROR;
+ if (!CheckException(env)) {
+ if (!error) {
+ result = VERIFY_OK;
+ } else {
+ jclass error_class = env->GetObjectClass(error);
+ DCHECK(error_class);
+ static jmethodID error_fn = env->GetMethodID(error_class,
+ "getPrimaryError", "()I");
+ if (error_fn) {
+ int code = env->CallIntMethod(error, error_fn);
+ if (!CheckException(env)) {
+ if (code == 2) { // SSL_IDMISMATCH == 2
+ result = VERIFY_BAD_HOSTNAME;
+ } else if (code == 3) { // SSL_UNTRUSTED == 3
+ result = VERIFY_NO_TRUSTED_ROOT;
+ }
+ }
+ }
+ env->DeleteLocalRef(error);
+ }
+ }
+ // TODO(joth): This balances the GetJNIEnv call; we need to detach as
+ // currently this method is called in chrome from a worker pool thread that
+ // may shutdown at anytime. However this assumption should not be baked in
+ // here: another user of the function may not want to have their thread
+ // detached at this point.
+ DetachFromVM();
+ return result;
+}
+
+// static
+void AndroidNetworkLibraryImpl::InitWithApplicationContext(JNIEnv* env,
+ jobject context) {
+ // Currently ignoring |context| as it is not needed (but remains in signature
+ // for API consistency with the equivalent method on class AndroidOS).
+ net::AndroidNetworkLibrary::RegisterSharedInstance(
+ new AndroidNetworkLibraryImpl(env));
+}
+
+AndroidNetworkLibraryImpl::AndroidNetworkLibraryImpl(JNIEnv* env)
+ : cert_verifier_class_(NULL) {
+ jclass cls = env->FindClass(kClassPathName);
+ if (CheckException(env) || !cls) {
+ NOTREACHED() << "Unable to load class " << kClassPathName;
+ } else {
+ cert_verifier_class_ = static_cast<jclass>(env->NewGlobalRef(cls));
+ env->DeleteLocalRef(cls);
+ }
+}
+
+AndroidNetworkLibraryImpl::~AndroidNetworkLibraryImpl() {
+ if (cert_verifier_class_)
+ GetJNIEnv()->DeleteGlobalRef(cert_verifier_class_);
+}
+
diff --git a/android/net/android_network_library_impl.h b/android/net/android_network_library_impl.h
new file mode 100644
index 0000000..8f2e9f7
--- /dev/null
+++ b/android/net/android_network_library_impl.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 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 ANDROID_NET_ANDROID_NETWORK_LIBRARY_IMPL_H_
+#define ANDROID_NET_ANDROID_NETWORK_LIBRARY_IMPL_H_
+
+#pragma once
+
+#include <jni.h>
+
+#include <string>
+#include <vector>
+
+#include "net/base/android_network_library.h"
+
+class AndroidNetworkLibraryImpl : public net::AndroidNetworkLibrary {
+ public:
+ static void InitWithApplicationContext(JNIEnv* env, jobject context);
+
+ virtual VerifyResult VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type);
+
+ private:
+ explicit AndroidNetworkLibraryImpl(JNIEnv* env);
+ virtual ~AndroidNetworkLibraryImpl();
+
+ jclass cert_verifier_class_;
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidNetworkLibraryImpl);
+};
+
+#endif // ANDROID_NET_ANDROID_NETWORK_LIBRARY_IMPL_H_