- Add support for client SSL certificates (issue #1608).
- Remember OnCertificateError approvals (issue #1590).
This commit is contained in:
parent
2a308f2a05
commit
0d905e3744
2
cef.gyp
2
cef.gyp
|
@ -1018,6 +1018,8 @@
|
|||
'libcef/browser/speech_recognition_manager_delegate.h',
|
||||
'libcef/browser/ssl_cert_principal_impl.cc',
|
||||
'libcef/browser/ssl_cert_principal_impl.h',
|
||||
'libcef/browser/ssl_host_state_delegate.cc',
|
||||
'libcef/browser/ssl_host_state_delegate.h',
|
||||
'libcef/browser/ssl_info_impl.cc',
|
||||
'libcef/browser/ssl_info_impl.h',
|
||||
'libcef/browser/stream_impl.cc',
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/download_manager_delegate.h"
|
||||
#include "libcef/browser/permission_manager.h"
|
||||
#include "libcef/browser/ssl_host_state_delegate.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
|
@ -195,7 +196,9 @@ content::PushMessagingService*
|
|||
|
||||
content::SSLHostStateDelegate*
|
||||
CefBrowserContextImpl::GetSSLHostStateDelegate() {
|
||||
return NULL;
|
||||
if (!ssl_host_state_delegate_.get())
|
||||
ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate());
|
||||
return ssl_host_state_delegate_.get();
|
||||
}
|
||||
|
||||
content::PermissionManager* CefBrowserContextImpl::GetPermissionManager() {
|
||||
|
|
|
@ -21,6 +21,7 @@ class SpeechRecognitionPreferences;
|
|||
}
|
||||
|
||||
class CefDownloadManagerDelegate;
|
||||
class CefSSLHostStateDelegate;
|
||||
|
||||
// Isolated BrowserContext implementation. Life span is controlled by
|
||||
// CefRequestContextImpl and (for the main context) CefBrowserMainParts. Only
|
||||
|
@ -97,6 +98,7 @@ class CefBrowserContextImpl : public CefBrowserContext {
|
|||
scoped_ptr<CefDownloadManagerDelegate> download_manager_delegate_;
|
||||
scoped_refptr<CefURLRequestContextGetterImpl> url_request_getter_;
|
||||
scoped_ptr<content::PermissionManager> permission_manager_;
|
||||
scoped_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefBrowserContextImpl);
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "content/public/browser/access_token_store.h"
|
||||
#include "content/public/browser/browser_url_handler.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/plugin_service_filter.h"
|
||||
#include "content/public/browser/quota_permission_context.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "content/public/common/storage_quota_params.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
#include "url/gurl.h"
|
||||
|
@ -755,6 +757,16 @@ void CefContentBrowserClient::AllowCertificateError(
|
|||
content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
|
||||
}
|
||||
|
||||
void CefContentBrowserClient::SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
if (!cert_request_info->client_certs.empty()) {
|
||||
// Use the first certificate.
|
||||
delegate->ContinueWithCertificate(cert_request_info->client_certs[0].get());
|
||||
}
|
||||
}
|
||||
|
||||
content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
|
||||
return new CefAccessTokenStore(
|
||||
browser_main_parts_->browser_context()->request_context().get());
|
||||
|
|
|
@ -105,6 +105,10 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
|||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* result) override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
content::AccessTokenStore* CreateAccessTokenStore() override;
|
||||
bool CanCreateWindow(const GURL& opener_url,
|
||||
const GURL& opener_top_level_frame_url,
|
||||
|
|
|
@ -8,6 +8,18 @@
|
|||
#include "base/logging.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
#include "net/ssl/client_cert_store_nss.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "net/ssl/client_cert_store_win.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "net/ssl/client_cert_store_mac.h"
|
||||
#endif
|
||||
|
||||
CefResourceContext::CefResourceContext() {
|
||||
}
|
||||
|
||||
|
@ -35,6 +47,24 @@ net::URLRequestContext* CefResourceContext::GetRequestContext() {
|
|||
return getter_->GetURLRequestContext();
|
||||
}
|
||||
|
||||
scoped_ptr<net::ClientCertStore> CefResourceContext::CreateClientCertStore() {
|
||||
#if defined(USE_NSS_CERTS)
|
||||
return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
|
||||
net::ClientCertStoreNSS::PasswordDelegateFactory()));
|
||||
#elif defined(OS_WIN)
|
||||
return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
|
||||
#elif defined(OS_MACOSX)
|
||||
return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
|
||||
#elif defined(USE_OPENSSL)
|
||||
// OpenSSL does not use the ClientCertStore infrastructure. On Android client
|
||||
// cert matching is done by the OS as part of the call to show the cert
|
||||
// selection dialog.
|
||||
return scoped_ptr<net::ClientCertStore>();
|
||||
#else
|
||||
#error Unknown platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
void CefResourceContext::set_url_request_context_getter(
|
||||
scoped_refptr<CefURLRequestContextGetter> getter) {
|
||||
DCHECK(!getter_.get());
|
||||
|
|
|
@ -26,6 +26,7 @@ class CefResourceContext : public content::ResourceContext {
|
|||
// ResourceContext implementation.
|
||||
net::HostResolver* GetHostResolver() override;
|
||||
net::URLRequestContext* GetRequestContext() override;
|
||||
scoped_ptr<net::ClientCertStore> CreateClientCertStore() override;
|
||||
|
||||
void set_url_request_context_getter(
|
||||
scoped_refptr<CefURLRequestContextGetter> getter);
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2014 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 "libcef/browser/ssl_host_state_delegate.h"
|
||||
|
||||
#include "net/base/hash_value.h"
|
||||
|
||||
using content::SSLHostStateDelegate;
|
||||
|
||||
namespace internal {
|
||||
|
||||
net::SHA256HashValue getChainFingerprint256(const net::X509Certificate& cert) {
|
||||
net::SHA256HashValue fingerprint =
|
||||
net::X509Certificate::CalculateChainFingerprint256(
|
||||
cert.os_cert_handle(), cert.GetIntermediateCertificates());
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
CertPolicy::CertPolicy() {
|
||||
}
|
||||
CertPolicy::~CertPolicy() {
|
||||
}
|
||||
|
||||
// For an allowance, we consider a given |cert| to be a match to a saved
|
||||
// allowed cert if the |error| is an exact match to or subset of the errors
|
||||
// in the saved CertStatus.
|
||||
bool CertPolicy::Check(const net::X509Certificate& cert,
|
||||
net::CertStatus error) const {
|
||||
net::SHA256HashValue fingerprint = getChainFingerprint256(cert);
|
||||
std::map<net::SHA256HashValue, net::CertStatus,
|
||||
net::SHA256HashValueLessThan>::const_iterator allowed_iter =
|
||||
allowed_.find(fingerprint);
|
||||
if ((allowed_iter != allowed_.end()) && (allowed_iter->second & error) &&
|
||||
((allowed_iter->second & error) == error)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CertPolicy::Allow(const net::X509Certificate& cert,
|
||||
net::CertStatus error) {
|
||||
// If this same cert had already been saved with a different error status,
|
||||
// this will replace it with the new error status.
|
||||
net::SHA256HashValue fingerprint = getChainFingerprint256(cert);
|
||||
allowed_[fingerprint] = error;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
CefSSLHostStateDelegate::CefSSLHostStateDelegate() {
|
||||
}
|
||||
|
||||
CefSSLHostStateDelegate::~CefSSLHostStateDelegate() {
|
||||
}
|
||||
|
||||
void CefSSLHostStateDelegate::HostRanInsecureContent(const std::string& host,
|
||||
int pid) {
|
||||
// Intentional no-op.
|
||||
}
|
||||
|
||||
bool CefSSLHostStateDelegate::DidHostRunInsecureContent(const std::string& host,
|
||||
int pid) const {
|
||||
// Intentional no-op.
|
||||
return false;
|
||||
}
|
||||
|
||||
void CefSSLHostStateDelegate::AllowCert(const std::string& host,
|
||||
const net::X509Certificate& cert,
|
||||
net::CertStatus error) {
|
||||
cert_policy_for_host_[host].Allow(cert, error);
|
||||
}
|
||||
|
||||
void CefSSLHostStateDelegate::Clear() {
|
||||
cert_policy_for_host_.clear();
|
||||
}
|
||||
|
||||
SSLHostStateDelegate::CertJudgment CefSSLHostStateDelegate::QueryPolicy(
|
||||
const std::string& host,
|
||||
const net::X509Certificate& cert,
|
||||
net::CertStatus error,
|
||||
bool* expired_previous_decision) {
|
||||
return cert_policy_for_host_[host].Check(cert, error)
|
||||
? SSLHostStateDelegate::ALLOWED
|
||||
: SSLHostStateDelegate::DENIED;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2014 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 CEF_LIBCEF_BROWSER_SSL_HOST_STATE_DELEGATE_H_
|
||||
#define CEF_LIBCEF_BROWSER_SSL_HOST_STATE_DELEGATE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/ssl_host_state_delegate.h"
|
||||
#include "net/base/hash_value.h"
|
||||
#include "net/cert/cert_status_flags.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
|
||||
namespace internal {
|
||||
|
||||
// This class maintains the policy for storing actions on certificate errors.
|
||||
class CertPolicy {
|
||||
public:
|
||||
CertPolicy();
|
||||
~CertPolicy();
|
||||
// Returns true if the user has decided to proceed through the ssl error
|
||||
// before. For a certificate to be allowed, it must not have any
|
||||
// *additional* errors from when it was allowed.
|
||||
bool Check(const net::X509Certificate& cert, net::CertStatus error) const;
|
||||
|
||||
// Causes the policy to allow this certificate for a given |error|. And
|
||||
// remember the user's choice.
|
||||
void Allow(const net::X509Certificate& cert, net::CertStatus error);
|
||||
|
||||
private:
|
||||
// The set of fingerprints of allowed certificates.
|
||||
std::map<net::SHA256HashValue, net::CertStatus, net::SHA256HashValueLessThan>
|
||||
allowed_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
class CefSSLHostStateDelegate : public content::SSLHostStateDelegate {
|
||||
public:
|
||||
CefSSLHostStateDelegate();
|
||||
~CefSSLHostStateDelegate() override;
|
||||
|
||||
// Records that |cert| is permitted to be used for |host| in the future, for
|
||||
// a specified |error| type.
|
||||
void AllowCert(const std::string& host,
|
||||
const net::X509Certificate& cert,
|
||||
net::CertStatus error) override;
|
||||
|
||||
void Clear() override;
|
||||
|
||||
// Queries whether |cert| is allowed or denied for |host| and |error|.
|
||||
content::SSLHostStateDelegate::CertJudgment QueryPolicy(
|
||||
const std::string& host,
|
||||
const net::X509Certificate& cert,
|
||||
net::CertStatus error,
|
||||
bool* expired_previous_decision) override;
|
||||
|
||||
// Records that a host has run insecure content.
|
||||
void HostRanInsecureContent(const std::string& host, int pid) override;
|
||||
|
||||
// Returns whether the specified host ran insecure content.
|
||||
bool DidHostRunInsecureContent(const std::string& host,
|
||||
int pid) const override;
|
||||
|
||||
private:
|
||||
// Certificate policies for each host.
|
||||
std::map<std::string, internal::CertPolicy> cert_policy_for_host_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefSSLHostStateDelegate);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_SSL_HOST_STATE_DELEGATE_H_
|
Loading…
Reference in New Issue