From 27ea3fc06968c8654506ae315180108dae6930d0 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 23 Sep 2020 13:22:10 -0700 Subject: [PATCH] feat: allow setting SSL config (#25461) * feat: allow setting SSL config * lint * configure system network context with min TLS1.2 * fix * note defaults --- docs/api/session.md | 14 +++++ shell/browser/api/electron_api_session.cc | 55 +++++++++++++++++++ shell/browser/api/electron_api_session.h | 2 + shell/browser/electron_browser_context.cc | 17 ++++++ shell/browser/electron_browser_context.h | 7 +++ shell/browser/net/network_context_service.cc | 9 +++ .../net/system_network_context_manager.cc | 4 ++ 7 files changed, 108 insertions(+) diff --git a/docs/api/session.md b/docs/api/session.md index 42030a1112eb..0e77b2e754a6 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -492,6 +492,20 @@ will be temporary. Returns `String` - The user agent for this session. +#### `ses.setSSLConfig(config)` + +* `config` Object + * `minVersion` String - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The + minimum SSL version to allow when connecting to remote servers. Defaults to + `tls1`. + * `maxVersion` String - Can be `tls1.2` or `tls1.3`. The maximum SSL version + to allow when connecting to remote servers. Defaults to `tls1.3`. + +Sets the SSL configuration for the session. All subsequent network requests +will use the new configuration. Existing network connections (such as WebSocket +connections) will not be terminated, but old sockets in the pool will not be +reused for new connections. + #### `ses.getBlobData(identifier)` * `identifier` String - Valid UUID. diff --git a/shell/browser/api/electron_api_session.cc b/shell/browser/api/electron_api_session.cc index cac71b7ee197..365dff41ec1f 100644 --- a/shell/browser/api/electron_api_session.cc +++ b/shell/browser/api/electron_api_session.cc @@ -19,6 +19,7 @@ #include "base/strings/string_util.h" #include "base/task/post_task.h" #include "chrome/browser/browser_process.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_url_parameters.h" @@ -180,6 +181,55 @@ struct Converter { } }; +bool SSLProtocolVersionFromString(const std::string& version_str, + network::mojom::SSLVersion* version) { + if (version_str == switches::kSSLVersionTLSv1) { + *version = network::mojom::SSLVersion::kTLS1; + return true; + } + if (version_str == switches::kSSLVersionTLSv11) { + *version = network::mojom::SSLVersion::kTLS11; + return true; + } + if (version_str == switches::kSSLVersionTLSv12) { + *version = network::mojom::SSLVersion::kTLS12; + return true; + } + if (version_str == switches::kSSLVersionTLSv13) { + *version = network::mojom::SSLVersion::kTLS13; + return true; + } + return false; +} + +template <> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + network::mojom::SSLConfigPtr* out) { + gin_helper::Dictionary options; + if (!ConvertFromV8(isolate, val, &options)) + return false; + *out = network::mojom::SSLConfig::New(); + std::string version_min_str; + if (options.Get("minVersion", &version_min_str)) { + if (!SSLProtocolVersionFromString(version_min_str, &(*out)->version_min)) + return false; + } + std::string version_max_str; + if (options.Get("maxVersion", &version_max_str)) { + if (!SSLProtocolVersionFromString(version_max_str, + &(*out)->version_max) || + (*out)->version_max < network::mojom::SSLVersion::kTLS12) + return false; + } + + // TODO(nornagon): also support client_cert_pooling_policy and + // disabled_cipher_suites. Maybe other SSLConfig properties too? + return true; + } +}; + } // namespace gin namespace electron { @@ -617,6 +667,10 @@ std::string Session::GetUserAgent() { return browser_context_->GetUserAgent(); } +void Session::SetSSLConfig(network::mojom::SSLConfigPtr config) { + browser_context_->SetSSLConfig(std::move(config)); +} + bool Session::IsPersistent() { return !browser_context_->IsOffTheRecord(); } @@ -1024,6 +1078,7 @@ gin::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("isPersistent", &Session::IsPersistent) .SetMethod("setUserAgent", &Session::SetUserAgent) .SetMethod("getUserAgent", &Session::GetUserAgent) + .SetMethod("setSSLConfig", &Session::SetSSLConfig) .SetMethod("getBlobData", &Session::GetBlobData) .SetMethod("downloadURL", &Session::DownloadURL) .SetMethod("createInterruptedDownload", diff --git a/shell/browser/api/electron_api_session.h b/shell/browser/api/electron_api_session.h index cde9dd3fb543..cdb5cb3192ac 100644 --- a/shell/browser/api/electron_api_session.h +++ b/shell/browser/api/electron_api_session.h @@ -13,6 +13,7 @@ #include "electron/buildflags/buildflags.h" #include "gin/handle.h" #include "gin/wrappable.h" +#include "services/network/public/mojom/ssl_config.mojom.h" #include "shell/browser/event_emitter_mixin.h" #include "shell/browser/net/resolve_proxy_helper.h" #include "shell/common/gin_helper/cleaned_up_at_exit.h" @@ -107,6 +108,7 @@ class Session : public gin::Wrappable, void AllowNTLMCredentialsForDomains(const std::string& domains); void SetUserAgent(const std::string& user_agent, gin::Arguments* args); std::string GetUserAgent(); + void SetSSLConfig(network::mojom::SSLConfigPtr config); bool IsPersistent(); v8::Local GetBlobData(v8::Isolate* isolate, const std::string& uuid); diff --git a/shell/browser/electron_browser_context.cc b/shell/browser/electron_browser_context.cc index 1eb2a4a9591d..a186de555868 100644 --- a/shell/browser/electron_browser_context.cc +++ b/shell/browser/electron_browser_context.cc @@ -106,6 +106,7 @@ ElectronBrowserContext::ElectronBrowserContext(const std::string& partition, storage_policy_(new SpecialStoragePolicy), protocol_registry_(new ProtocolRegistry), in_memory_(in_memory), + ssl_config_(network::mojom::SSLConfig::New()), weak_factory_(this) { // TODO(nornagon): remove once https://crbug.com/1048822 is fixed. base::ScopedAllowBlockingForTesting allow_blocking; @@ -446,6 +447,22 @@ ResolveProxyHelper* ElectronBrowserContext::GetResolveProxyHelper() { return resolve_proxy_helper_.get(); } +network::mojom::SSLConfigPtr ElectronBrowserContext::GetSSLConfig() { + return ssl_config_.Clone(); +} + +void ElectronBrowserContext::SetSSLConfig(network::mojom::SSLConfigPtr config) { + ssl_config_ = std::move(config); + if (ssl_config_client_) { + ssl_config_client_->OnSSLConfigUpdated(ssl_config_.Clone()); + } +} + +void ElectronBrowserContext::SetSSLConfigClient( + mojo::Remote client) { + ssl_config_client_ = std::move(client); +} + // static ElectronBrowserContext* ElectronBrowserContext::From( const std::string& partition, diff --git a/shell/browser/electron_browser_context.h b/shell/browser/electron_browser_context.h index fd5d1d84fedc..b2520a2734aa 100644 --- a/shell/browser/electron_browser_context.h +++ b/shell/browser/electron_browser_context.h @@ -147,6 +147,10 @@ class ElectronBrowserContext return protocol_registry_.get(); } + void SetSSLConfig(network::mojom::SSLConfigPtr config); + network::mojom::SSLConfigPtr GetSSLConfig(); + void SetSSLConfigClient(mojo::Remote client); + ~ElectronBrowserContext() override; private: @@ -190,6 +194,9 @@ class ElectronBrowserContext scoped_refptr url_loader_factory_; mojo::Receiver auth_client_{this}; + network::mojom::SSLConfigPtr ssl_config_; + mojo::Remote ssl_config_client_; + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(ElectronBrowserContext); diff --git a/shell/browser/net/network_context_service.cc b/shell/browser/net/network_context_service.cc index bf9177217f00..53689a8d2d42 100644 --- a/shell/browser/net/network_context_service.cc +++ b/shell/browser/net/network_context_service.cc @@ -4,6 +4,8 @@ #include "shell/browser/net/network_context_service.h" +#include + #include "chrome/common/chrome_constants.h" #include "content/public/browser/network_service_instance.h" #include "net/net_buildflags.h" @@ -29,6 +31,13 @@ void NetworkContextService::ConfigureNetworkContextParams( g_browser_process->system_network_context_manager() ->ConfigureDefaultNetworkContextParams(network_context_params); + mojo::Remote ssl_config_client; + network_context_params->ssl_config_client_receiver = + ssl_config_client.BindNewPipeAndPassReceiver(); + browser_context_->SetSSLConfigClient(std::move(ssl_config_client)); + + network_context_params->initial_ssl_config = browser_context_->GetSSLConfig(); + network_context_params->user_agent = browser_context_->GetUserAgent(); network_context_params->accept_language = diff --git a/shell/browser/net/system_network_context_manager.cc b/shell/browser/net/system_network_context_manager.cc index 189774d071b0..99217f36f9d2 100644 --- a/shell/browser/net/system_network_context_manager.cc +++ b/shell/browser/net/system_network_context_manager.cc @@ -229,6 +229,10 @@ SystemNetworkContextManager::CreateNetworkContextParams() { network_context_params->http_cache_enabled = false; + auto ssl_config = network::mojom::SSLConfig::New(); + ssl_config->version_min = network::mojom::SSLVersion::kTLS12; + network_context_params->initial_ssl_config = std::move(ssl_config); + proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); return network_context_params;