diff options
author | Ben Murdoch <benm@google.com> | 2010-11-19 12:37:23 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-11-19 16:52:35 +0000 |
commit | 76a88e2c298122bfdfc498a5df61aab702184639 (patch) | |
tree | 755358c235b4d839842b272e1462a26e68d8c159 /android | |
parent | 34b5a0345856ab7743b6daa5a1fea1dcbe0c3394 (diff) | |
download | external_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.cc | 18 | ||||
-rw-r--r-- | android/jni/jni_utils.h | 6 | ||||
-rw-r--r-- | android/net/android_network_library_impl.cc | 142 | ||||
-rw-r--r-- | android/net/android_network_library_impl.h | 35 |
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_ |