diff options
Diffstat (limited to 'Source/WebKit/android/jni/WebCoreFrameBridge.cpp')
-rw-r--r-- | Source/WebKit/android/jni/WebCoreFrameBridge.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index be38a16..5f30ab4 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -93,8 +93,11 @@ #include <JNIUtility.h> #include <JNIHelp.h> +#include <ScopedPrimitiveArray.h> +#include <ScopedLocalRef.h> #include <SkGraphics.h> #include <android_runtime/android_util_AssetManager.h> +#include <openssl/x509.h> #include <utils/misc.h> #include <utils/AssetManager.h> #include <wtf/CurrentTime.h> @@ -212,6 +215,7 @@ struct WebFrame::JavaBrowserFrame jmethodID mGetFile; jmethodID mDidReceiveAuthenticationChallenge; jmethodID mReportSslCertError; + jmethodID mRequestClientCert; jmethodID mDownloadStart; jmethodID mDidReceiveData; jmethodID mDidFinishLoading; @@ -285,6 +289,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mDidReceiveAuthenticationChallenge = env->GetMethodID(clazz, "didReceiveAuthenticationChallenge", "(ILjava/lang/String;Ljava/lang/String;Z)V"); mJavaFrame->mReportSslCertError = env->GetMethodID(clazz, "reportSslCertError", "(II[B)V"); + mJavaFrame->mRequestClientCert = env->GetMethodID(clazz, "requestClientCert", "(I[B)V"); mJavaFrame->mDownloadStart = env->GetMethodID(clazz, "downloadStart", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V"); mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V"); @@ -320,6 +325,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile"); LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge"); LOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError"); + LOG_ASSERT(mJavaFrame->mRequestClientCert, "Could not find method requestClientCert"); LOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart"); LOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData"); LOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading"); @@ -981,6 +987,25 @@ WebFrame::reportSslCertError(WebUrlLoaderClient* client, int cert_error, const s checkException(env); } +void +WebFrame::requestClientCert(WebUrlLoaderClient* client, const std::string& host_and_port) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); +#endif + JNIEnv* env = getJNIEnv(); + int jHandle = reinterpret_cast<int>(client); + + int len = host_and_port.length(); + jbyteArray jHostAndPort = env->NewByteArray(len); + jbyte* bytes = env->GetByteArrayElements(jHostAndPort, NULL); + host_and_port.copy(reinterpret_cast<char*>(bytes), len); + + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mRequestClientCert, jHandle, jHostAndPort); + env->DeleteLocalRef(jHostAndPort); + checkException(env); +} + #if USE(CHROME_NETWORK_STACK) void WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength) @@ -2107,6 +2132,84 @@ static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_er client->cancelSslCertError(cert_error); } +static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray pkey, jobjectArray chain) +{ + WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle); + if (pkey == NULL || chain == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + + // Based on Android's NativeCrypto_SSL_use_PrivateKey + ScopedByteArrayRO pkeyBytes(env, pkey); + if (pkeyBytes.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + + base::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8; + const unsigned char* pkeyChars = reinterpret_cast<const unsigned char*>(pkeyBytes.get()); + pkcs8.reset(d2i_PKCS8_PRIV_KEY_INFO(NULL, &pkeyChars, pkeyBytes.size())); + if (!pkcs8.get()) { + client->sslClientCert(NULL, NULL); + return; + } + base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(EVP_PKCS82PKEY(pkcs8.get())); + if (!privateKey.get()) { + client->sslClientCert(NULL, NULL); + return; + } + + // Based on Android's NativeCrypto_SSL_use_certificate + int length = env->GetArrayLength(chain); + if (length == 0) { + client->sslClientCert(NULL, NULL); + return; + } + + base::ScopedOpenSSL<X509, X509_free> first; + ScopedVector<base::ScopedOpenSSL<X509, X509_free> > rest; + for (int i = 0; i < length; i++) { + ScopedLocalRef<jbyteArray> cert(env, + reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(chain, i))); + if (cert.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + ScopedByteArrayRO certBytes(env, cert.get()); + if (certBytes.get() == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + const char* data = reinterpret_cast<const char*>(certBytes.get()); + int length = certBytes.size(); + X509* x509 = net::X509Certificate::CreateOSCertHandleFromBytes(data, length); + if (x509 == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + if (i == 0) { + first.reset(x509); + } else { + rest.push_back(new base::ScopedOpenSSL<X509, X509_free>(x509)); + } + } + + std::vector<X509*> certChain(rest.size()); + for (size_t i = 0; i < rest.size(); i++) { + certChain[i] = rest[i]->get(); + } + net::X509Certificate* certificate + = net::X509Certificate::CreateFromHandle(first.get(), + net::X509Certificate::SOURCE_FROM_NETWORK, + certChain); + if (certificate == NULL) { + client->sslClientCert(NULL, NULL); + return; + } + client->sslClientCert(privateKey.release(), certificate); +} + #else static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword) @@ -2129,6 +2232,10 @@ static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_er LOGW("Chromium SSL API called, but libchromium is not available"); } +static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray privateKey, jobjectArray chain) +{ + LOGW("Chromium SSL API called, but libchromium is not available"); +} #endif // USE(CHROME_NETWORK_STACK) // ---------------------------------------------------------------------------- @@ -2193,6 +2300,8 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { (void*) SslCertErrorProceed }, { "nativeSslCertErrorCancel", "(II)V", (void*) SslCertErrorCancel }, + { "nativeSslClientCert", "(I[B[[B)V", + (void*) SslClientCert }, }; int registerWebFrame(JNIEnv* env) |