summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2011-06-02 01:05:19 -0700
committerBrian Carlstrom <bdc@google.com>2011-06-09 05:01:42 -0700
commiteec5cd31a627a9d05aefe27fe25ff9df92ad1a53 (patch)
tree8f54a7ac85da125d790de91c90c38bedacf9454b
parent12b73c856f825f0819e61834cb0bc76353b261d4 (diff)
downloadexternal_webkit-eec5cd31a627a9d05aefe27fe25ff9df92ad1a53.zip
external_webkit-eec5cd31a627a9d05aefe27fe25ff9df92ad1a53.tar.gz
external_webkit-eec5cd31a627a9d05aefe27fe25ff9df92ad1a53.tar.bz2
Implement net::URLRequest::Delegate::OnCertificateRequested
Following the example of OnSSLCertificateError, implement OnCertificateRequested ERROR CASE CLIENT CERT CASE net::URLRequest::Delegate::OnSSLCertificateError net::URLRequest::Delegate::OnCertificateRequested WebRequest::OnSSLCertificateError WebRequest::OnCertificateRequested WebUrlLoaderClient::reportSslCertError WebUrlLoaderClient::requestClientCert WebFrame::reportSslCertError WebFrame::requestClientCert android.webkit.BrowserFrame.reportSslCertError android.webkit.BrowserFrame.requestClientCert <... See frameworks/base ...> <... See frameworks/base ...> android.webkit.BrowserFrame.nativeSslCertErrorProceed android.webkit.BrowserFrame.nativeSslClientCert WebCoreFrameBridge::SslCertErrorProceed WebCoreFrameBridge::SslClientCert WebUrlLoaderClient::proceedSslCertError WebUrlLoaderClient::sslClientCert WebRequest::proceedSslCertError WebRequest::sslClientCert net::URLRequest::ContinueDespiteLastError net::URLRequest::ContinueWithCertificate Change-Id: I6513678a3c553bf329640119ff96df9a39a41e49
-rw-r--r--Source/WebKit/Android.mk10
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h3
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebRequest.cpp21
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebRequest.h2
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp18
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h2
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.cpp109
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.h2
8 files changed, 164 insertions, 3 deletions
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk
index d02557e..7a5fabf 100644
--- a/Source/WebKit/Android.mk
+++ b/Source/WebKit/Android.mk
@@ -34,7 +34,7 @@ LOCAL_SRC_FILES := \
android/WebCoreSupport/V8Counters.cpp
ifeq ($(HTTP_STACK),chrome)
-LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+LOCAL_SRC_FILES += \
android/WebCoreSupport/ChromiumInit.cpp \
android/WebCoreSupport/CacheResult.cpp \
android/WebCoreSupport/WebCache.cpp \
@@ -48,7 +48,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
android/WebCoreSupport/WebViewClientError.cpp
endif # HTTP_STACK == chrome
-LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+LOCAL_SRC_FILES += \
android/RenderSkinAndroid.cpp \
android/RenderSkinButton.cpp \
android/RenderSkinCombo.cpp \
@@ -121,11 +121,15 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
android/wds/Connection.cpp \
android/wds/DebugServer.cpp
+LOCAL_C_INCLUDES += \
+ external/openssl/include \
+ libcore/include
+
# Needed for autofill.
ifeq ($(ENABLE_AUTOFILL),true)
LOCAL_CFLAGS += -DENABLE_WEB_AUTOFILL
-LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
+LOCAL_SRC_FILES += \
android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp \
android/WebCoreSupport/autofill/FormFieldAndroid.cpp \
android/WebCoreSupport/autofill/FormManagerAndroid.cpp \
diff --git a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
index e467218..8a17656 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
+++ b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
@@ -49,6 +49,7 @@
#include <base/callback.h>
#include <base/lock.h>
#include <base/message_loop_proxy.h>
+#include <base/openssl_util.h>
#include <base/ref_counted.h>
#include <base/string_util.h>
#include <base/synchronization/condition_variable.h>
@@ -67,6 +68,8 @@
#include <net/base/load_flags.h>
#include <net/base/net_errors.h>
#include <net/base/mime_util.h>
+#include <net/base/openssl_private_key_store.h>
+#include <net/base/ssl_cert_request_info.h>
#include <net/base/ssl_config_service.h>
#include <net/disk_cache/disk_cache.h>
#include <net/http/http_auth_handler_factory.h>
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
index 7c6b9ea..85460bd 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
@@ -36,6 +36,7 @@
#include "jni.h"
#include <cutils/log.h>
+#include <openssl/x509.h>
#include <string>
#include <utils/AssetManager.h>
@@ -407,6 +408,14 @@ void WebRequest::OnSSLCertificateError(net::URLRequest* request, int cert_error,
m_urlLoader.get(), &WebUrlLoaderClient::reportSslCertError, cert_error, scoped_cert));
}
+void WebRequest::OnCertificateRequested(net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info)
+{
+ scoped_refptr<net::SSLCertRequestInfo> scoped_cert_request_info = cert_request_info;
+ m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
+ m_urlLoader.get(), &WebUrlLoaderClient::requestClientCert, scoped_cert_request_info));
+}
+
+
// After calling Start(), the delegate will receive an OnResponseStarted
// callback when the request has completed. If an error occurred, the
// request->status() will be set. On success, all redirects have been
@@ -461,6 +470,18 @@ void WebRequest::cancelSslCertError(int cert_error)
m_request->SimulateError(cert_error);
}
+void WebRequest::sslClientCert(EVP_PKEY* pkey, scoped_refptr<net::X509Certificate> chain)
+{
+ base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(pkey);
+ if (privateKey.get() == NULL || chain.get() == NULL) {
+ m_request->ContinueWithCertificate(NULL);
+ return;
+ }
+ GURL gurl(m_url);
+ net::OpenSSLPrivateKeyStore::GetInstance()->StorePrivateKey(gurl, privateKey.release());
+ m_request->ContinueWithCertificate(chain.release());
+}
+
void WebRequest::startReading()
{
ASSERT(m_networkBuffer == 0, "startReading called with a nonzero buffer");
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.h b/Source/WebKit/android/WebCoreSupport/WebRequest.h
index 4d18599..285e577 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.h
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.h
@@ -77,6 +77,7 @@ public:
virtual void OnReadCompleted(net::URLRequest*, int bytesRead);
virtual void OnAuthRequired(net::URLRequest*, net::AuthChallengeInfo*);
virtual void OnSSLCertificateError(net::URLRequest* request, int cert_error, net::X509Certificate* cert);
+ virtual void OnCertificateRequested(net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info);
// Methods called during a request by the UI code (via WebUrlLoaderClient).
void setAuth(const string16& username, const string16& password);
@@ -84,6 +85,7 @@ public:
void followDeferredRedirect();
void proceedSslCertError();
void cancelSslCertError(int cert_error);
+ void sslClientCert(EVP_PKEY* pkey, scoped_refptr<net::X509Certificate> chain);
const std::string& getUrl() const;
const std::string& getUserAgent() const;
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
index b22ae26..b047379 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
@@ -320,6 +320,15 @@ void WebUrlLoaderClient::cancelSslCertError(int cert_error)
this->Release();
}
+void WebUrlLoaderClient::sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain)
+{
+ base::Thread* thread = ioThread();
+ scoped_refptr<net::X509Certificate> scopedChain(chain);
+ if (isActive() && thread)
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request.get(), &WebRequest::sslClientCert, pkey, scopedChain));
+ this->Release();
+}
+
void WebUrlLoaderClient::finish()
{
@@ -479,4 +488,13 @@ void WebUrlLoaderClient::reportSslCertError(int cert_error, net::X509Certificate
m_webFrame->reportSslCertError(this, cert_error, chain_bytes[0]);
}
+void WebUrlLoaderClient::requestClientCert(net::SSLCertRequestInfo* cert_request_info)
+{
+ if (!isActive())
+ return;
+
+ std::string host_and_port = cert_request_info->host_and_port;
+ m_webFrame->requestClientCert(this, host_and_port);
+}
+
} // namespace android
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
index 224fa65..dc7e8d5 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
@@ -74,6 +74,7 @@ public:
void cancelAuth();
void proceedSslCertError();
void cancelSslCertError(int cert_error);
+ void sslClientCert(EVP_PKEY* pkey, net::X509Certificate* chain);
typedef void CallbackFunction(void*);
@@ -91,6 +92,7 @@ public:
void willSendRequest(PassOwnPtr<WebResponse>);
void authRequired(scoped_refptr<net::AuthChallengeInfo>, bool firstTime);
void reportSslCertError(int cert_error, net::X509Certificate* cert);
+ void requestClientCert(net::SSLCertRequestInfo* cert);
// Handle to the chrome IO thread
static base::Thread* ioThread();
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)
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h
index 2e2468c..d74948f 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h
@@ -119,6 +119,8 @@ class WebFrame : public WebCoreRefObject {
void reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert);
+ void requestClientCert(WebUrlLoaderClient* client, const std::string& host_and_port);
+
void downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength);
void didReceiveData(const char* data, int size);