From c8067b3e11d18eb975efd49676d27174df8beef5 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Tue, 11 Jul 2017 15:02:44 -0400 Subject: [PATCH] Add support for loading certificate revocation lists (issue #2213) --- BUILD.gn | 1 + include/capi/cef_file_util_capi.h | 12 +++- include/cef_file_util.h | 11 ++++ libcef/browser/net/crlset_file_util_impl.cc | 61 +++++++++++++++++++++ libcef_dll/libcef_dll.cc | 14 ++++- libcef_dll/wrapper/libcef_dll_wrapper.cc | 14 ++++- tests/cefclient/browser/client_browser.cc | 11 ++++ tests/shared/common/client_switches.cc | 1 + tests/shared/common/client_switches.h | 1 + 9 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 libcef/browser/net/crlset_file_util_impl.cc diff --git a/BUILD.gn b/BUILD.gn index dbff79f1e..c8af02593 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -348,6 +348,7 @@ static_library("libcef_static") { "libcef/browser/net/chrome_scheme_handler.h", "libcef/browser/net/cookie_store_proxy.cc", "libcef/browser/net/cookie_store_proxy.h", + "libcef/browser/net/crlset_file_util_impl.cc", "libcef/browser/net/devtools_scheme_handler.cc", "libcef/browser/net/devtools_scheme_handler.h", "libcef/browser/net/internal_scheme_handler.cc", diff --git a/include/capi/cef_file_util_capi.h b/include/capi/cef_file_util_capi.h index 4602492fb..a7e38e5ee 100644 --- a/include/capi/cef_file_util_capi.h +++ b/include/capi/cef_file_util_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=4601edefadfafea031f2c5df498262fc2142252b$ +// $hash=1c02b57893a3f78c436bc2ab66c63753edfb174a$ // #ifndef CEF_INCLUDE_CAPI_CEF_FILE_UTIL_CAPI_H_ @@ -114,6 +114,16 @@ CEF_EXPORT int cef_zip_directory(const cef_string_t* src_dir, const cef_string_t* dest_file, int include_hidden_files); +/// +// Loads the existing "Certificate Revocation Lists" file that is managed by +// Google Chrome. This file can generally be found in Chrome's User Data +// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on +// Windows) and is updated periodically by Chrome's component updater service. +// Must be called in the browser process after the context has been initialized. +// See https://dev.chromium.org/Home/chromium-security/crlsets for background. +/// +CEF_EXPORT void cef_load_crlsets_file(const cef_string_t* path); + #ifdef __cplusplus } #endif diff --git a/include/cef_file_util.h b/include/cef_file_util.h index d18f886ca..8dd1ff644 100644 --- a/include/cef_file_util.h +++ b/include/cef_file_util.h @@ -115,4 +115,15 @@ bool CefZipDirectory(const CefString& src_dir, const CefString& dest_file, bool include_hidden_files); +/// +// Loads the existing "Certificate Revocation Lists" file that is managed by +// Google Chrome. This file can generally be found in Chrome's User Data +// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on +// Windows) and is updated periodically by Chrome's component updater service. +// Must be called in the browser process after the context has been initialized. +// See https://dev.chromium.org/Home/chromium-security/crlsets for background. +/// +/*--cef()--*/ +void CefLoadCRLSetsFile(const CefString& path); + #endif // CEF_INCLUDE_CEF_FILE_UTIL_H_ diff --git a/libcef/browser/net/crlset_file_util_impl.cc b/libcef/browser/net/crlset_file_util_impl.cc new file mode 100644 index 000000000..8e5b44bdd --- /dev/null +++ b/libcef/browser/net/crlset_file_util_impl.cc @@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Embedded Framework 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 "include/cef_file_util.h" + +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" + +#include "base/files/file_util.h" +#include "base/logging.h" +#include "net/cert/crl_set.h" +#include "net/cert/crl_set_storage.h" +#include "net/ssl/ssl_config_service.h" + +namespace { + +// Based on chrome/browser/net/crl_set_fetcher.cc. + +void SetCRLSetIfNewer(scoped_refptr crl_set) { + CEF_REQUIRE_IOT(); + + scoped_refptr old_crl_set(net::SSLConfigService::GetCRLSet()); + if (old_crl_set.get() && old_crl_set->sequence() > crl_set->sequence()) { + LOG(WARNING) << "Refusing to downgrade CRL set from #" + << old_crl_set->sequence() << "to #" << crl_set->sequence(); + } else { + net::SSLConfigService::SetCRLSet(crl_set); + VLOG(1) << "Installed CRL set #" << crl_set->sequence(); + } +} + +void LoadFromDisk(const base::FilePath& path) { + CEF_REQUIRE_FILET(); + + std::string crl_set_bytes; + if (!base::ReadFileToString(path, &crl_set_bytes)) { + LOG(WARNING) << "Failed to read CRL set from " << path.MaybeAsASCII(); + return; + } + + scoped_refptr crl_set; + if (!net::CRLSetStorage::Parse(crl_set_bytes, &crl_set)) { + LOG(WARNING) << "Failed to parse CRL set from " << path.MaybeAsASCII(); + return; + } + + VLOG(1) << "Loaded " << crl_set_bytes.size() << " bytes of CRL set from disk"; + CEF_POST_TASK(CEF_IOT, base::BindOnce(&SetCRLSetIfNewer, crl_set)); +} + +} // namespace + +void CefLoadCRLSetsFile(const CefString& path) { + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + CEF_POST_TASK(CEF_FILET, base::BindOnce(&LoadFromDisk, path)); +} diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 167bee558..b8efdeac3 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=1713327e819a8a3e44808a4415926326886efdf7$ +// $hash=a3b7d128aa7c1d9c78b416978e944da4eafaf14a$ // #include "include/capi/cef_app_capi.h" @@ -582,6 +582,18 @@ CEF_EXPORT int cef_zip_directory(const cef_string_t* src_dir, return _retval; } +CEF_EXPORT void cef_load_crlsets_file(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefLoadCRLSetsFile(CefString(path)); +} + CEF_EXPORT int cef_get_geolocation( struct _cef_get_geolocation_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index 084b26425..2b0fa0776 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=62ad3894d1548a39b032798d25a7a9b157f8a7bc$ +// $hash=b9a497935b8b0378d130ba55a92d188025df7350$ // #include "include/capi/cef_app_capi.h" @@ -551,6 +551,18 @@ CEF_GLOBAL bool CefZipDirectory(const CefString& src_dir, return _retval ? true : false; } +CEF_GLOBAL void CefLoadCRLSetsFile(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_load_crlsets_file(path.GetStruct()); +} + CEF_GLOBAL bool CefGetGeolocation( CefRefPtr callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING diff --git a/tests/cefclient/browser/client_browser.cc b/tests/cefclient/browser/client_browser.cc index f446dc83e..008c85444 100644 --- a/tests/cefclient/browser/client_browser.cc +++ b/tests/cefclient/browser/client_browser.cc @@ -4,7 +4,10 @@ #include "tests/cefclient/browser/client_browser.h" +#include "include/cef_command_line.h" #include "include/cef_crash_util.h" +#include "include/cef_file_util.h" +#include "tests/shared/common/client_switches.h" namespace client { namespace browser { @@ -23,6 +26,14 @@ class ClientBrowserDelegate : public ClientAppBrowser::Delegate { CefSetCrashKeyValue("testkey2", "value2_browser"); CefSetCrashKeyValue("testkey3", "value3_browser"); } + + const std::string& crl_sets_path = + CefCommandLine::GetGlobalCommandLine()->GetSwitchValue( + switches::kCRLSetsPath); + if (!crl_sets_path.empty()) { + // Load the CRLSets file from the specified path. + CefLoadCRLSetsFile(crl_sets_path); + } } private: diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index 910eaadda..101a84574 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -37,6 +37,7 @@ const char kHideControls[] = "hide-controls"; const char kHideTopMenu[] = "hide-top-menu"; const char kWidevineCdmPath[] = "widevine-cdm-path"; const char kSslClientCertificate[] = "ssl-client-certificate"; +const char kCRLSetsPath[] = "crl-sets-path"; } // namespace switches } // namespace client diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index 7c656d9d4..65e02cfd8 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -31,6 +31,7 @@ extern const char kHideControls[]; extern const char kHideTopMenu[]; extern const char kWidevineCdmPath[]; extern const char kSslClientCertificate[]; +extern const char kCRLSetsPath[]; } // namespace switches } // namespace client