NetworkService: Add HTTPS URL path stripping for PACs and quick check.
Also adds an integration test for path stripping, but not for
quick check.
Bug: 715695
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: I45d37089d305c5a6683afbac762ef767b910fb0f
Reviewed-on: https://chromium-review.googlesource.com/1028177
Commit-Queue: Matt Menke <[email protected]>
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Gabriel Charette <[email protected]>
Reviewed-by: Maksim Ivanov <[email protected]>
Reviewed-by: Eric Roman <[email protected]>
Cr-Commit-Position: refs/heads/master@{#555769}
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 29195217..f6918c5e 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -419,14 +419,6 @@
ntlm_v2_enabled_.MoveToThread(io_thread_proxy);
#endif
- quick_check_enabled_.Init(prefs::kQuickCheckEnabled,
- local_state);
- quick_check_enabled_.MoveToThread(io_thread_proxy);
-
- pac_https_url_stripping_enabled_.Init(prefs::kPacHttpsUrlStrippingEnabled,
- local_state);
- pac_https_url_stripping_enabled_.MoveToThread(io_thread_proxy);
-
chrome_browser_net::SetGlobalSTHDistributor(
std::make_unique<certificate_transparency::STHDistributor>());
@@ -624,8 +616,6 @@
registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
registry->RegisterListPref(prefs::kDnsOverHttpsServers);
registry->RegisterListPref(prefs::kDnsOverHttpsServerMethods);
- registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true);
- registry->RegisterBooleanPref(prefs::kPacHttpsUrlStrippingEnabled, true);
#if defined(OS_POSIX)
registry->RegisterBooleanPref(prefs::kNtlmV2Enabled, true);
#endif
@@ -754,26 +744,12 @@
chrome_browser_net::GetGlobalSTHDistributor()->UnregisterObserver(observer);
}
-bool IOThread::WpadQuickCheckEnabled() const {
- return quick_check_enabled_.GetValue();
-}
-
-bool IOThread::PacHttpsUrlStrippingEnabled() const {
- return pac_https_url_stripping_enabled_.GetValue();
-}
-
void IOThread::SetUpProxyService(
network::URLRequestContextBuilderMojo* builder) const {
#if defined(OS_CHROMEOS)
builder->SetDhcpFetcherFactory(
std::make_unique<chromeos::DhcpPacFileFetcherFactoryChromeos>());
#endif
-
- builder->set_pac_quick_check_enabled(WpadQuickCheckEnabled());
- builder->set_pac_sanitize_url_policy(
- PacHttpsUrlStrippingEnabled()
- ? net::ProxyResolutionService::SanitizeUrlPolicy::SAFE
- : net::ProxyResolutionService::SanitizeUrlPolicy::UNSAFE);
}
certificate_transparency::TreeStateTracker* IOThread::ct_tree_tracker() const {
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index f9724e8..b4c7a49 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -199,17 +199,6 @@
// Un-registers the |observer|.
void UnregisterSTHObserver(certificate_transparency::STHObserver* observer);
- // Returns true if the indicated proxy resolution features are
- // enabled. These features are controlled through
- // preferences/policy/commandline.
- //
- // For a description of what these features are, and how they are
- // configured, see the comments in pref_names.cc for
- // |kQuickCheckEnabled| and |kPacHttpsUrlStrippingEnabled
- // respectively.
- bool WpadQuickCheckEnabled() const;
- bool PacHttpsUrlStrippingEnabled() const;
-
// Configures |builder|'s ProxyResolutionService based on prefs and policies.
void SetUpProxyService(network::URLRequestContextBuilderMojo* builder) const;
@@ -275,10 +264,6 @@
BooleanPrefMember dns_client_enabled_;
- BooleanPrefMember quick_check_enabled_;
-
- BooleanPrefMember pac_https_url_stripping_enabled_;
-
StringListPrefMember dns_over_https_servers_;
StringListPrefMember dns_over_https_server_methods_;
diff --git a/chrome/browser/net/default_network_context_params.cc b/chrome/browser/net/default_network_context_params.cc
index aec0ef0..332c063 100644
--- a/chrome/browser/net/default_network_context_params.cc
+++ b/chrome/browser/net/default_network_context_params.cc
@@ -15,9 +15,12 @@
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -59,6 +62,12 @@
}
}
+ PrefService* local_state = g_browser_process->local_state();
+ network_context_params->pac_quick_check_enabled =
+ local_state->GetBoolean(prefs::kQuickCheckEnabled);
+ network_context_params->dangerously_allow_pac_access_to_secure_urls =
+ !local_state->GetBoolean(prefs::kPacHttpsUrlStrippingEnabled);
+
bool http_09_on_non_default_ports_enabled = false;
const base::Value* value =
g_browser_process->policy_service()
@@ -72,3 +81,8 @@
return network_context_params;
}
+
+void RegisterNetworkContextCreationPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true);
+ registry->RegisterBooleanPref(prefs::kPacHttpsUrlStrippingEnabled, true);
+}
diff --git a/chrome/browser/net/default_network_context_params.h b/chrome/browser/net/default_network_context_params.h
index 09c3028..27b7701 100644
--- a/chrome/browser/net/default_network_context_params.h
+++ b/chrome/browser/net/default_network_context_params.h
@@ -7,7 +7,12 @@
#include "services/network/public/mojom/network_service.mojom.h"
+class PrefRegistrySimple;
+
// Returns default set of parameters for configuring the network service.
network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams();
+// Registers prefs used in creating the default NetworkContextParams.
+void RegisterNetworkContextCreationPrefs(PrefRegistrySimple* registry);
+
#endif // CHROME_BROWSER_NET_DEFAULT_NETWORK_CONTEXT_PARAMS_H_
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index 7fc1392b..c7a37262 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -4,11 +4,13 @@
#include <string>
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
+#include "base/location.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -16,6 +18,7 @@
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/default_network_context_params.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
@@ -30,6 +33,7 @@
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
@@ -40,9 +44,11 @@
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
@@ -125,6 +131,9 @@
}
void SetUpOnMainThread() override {
+ // Used in a bunch of proxy tests. Should not resolve.
+ host_resolver()->AddSimulatedFailure("does.not.resolve.test");
+
controllable_http_response_ =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), kControllablePath);
@@ -151,7 +160,7 @@
// a proxy.
std::string GetPacScript() const {
return base::StringPrintf(
- "function FindProxyForURL(url, host){ return 'PROXY %s;'; }",
+ "function FindProxyForURL(url, host){ return 'PROXY %s;' }",
net::HostPortPair::FromURL(embedded_test_server()->base_url())
.ToString()
.c_str());
@@ -259,7 +268,7 @@
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the test server because of the proxy.
- request->url = GURL("http://jabberwocky.test:1872/echo");
+ request->url = GURL("http://does.not.resolve.test:1872/echo");
content::SimpleURLLoaderTestHelper simple_loader_helper;
std::unique_ptr<network::SimpleURLLoader> simple_loader =
@@ -820,7 +829,7 @@
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the test server because of the proxy.
- request->url = GURL("http://jabberwocky.test:1872/echo");
+ request->url = GURL("http://does.not.resolve.test:1872/echo");
content::SimpleURLLoaderTestHelper simple_loader_helper;
std::unique_ptr<network::SimpleURLLoader> simple_loader =
@@ -834,6 +843,113 @@
EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError());
}
+// Used to test that PAC HTTPS URL stripping works. A different test server is
+// used as the "proxy" based on whether the PAC script sees the full path or
+// not. The servers aren't correctly set up to mimic HTTP proxies that tunnel
+// to an HTTPS test server, so the test fixture just watches for any incoming
+// connection.
+class NetworkContextConfigurationHttpsStrippingPacBrowserTest
+ : public NetworkContextConfigurationBrowserTest {
+ public:
+ NetworkContextConfigurationHttpsStrippingPacBrowserTest() {}
+
+ ~NetworkContextConfigurationHttpsStrippingPacBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Test server HostPortPair, as a string.
+ std::string test_server_host_port_pair =
+ net::HostPortPair::FromURL(embedded_test_server()->base_url())
+ .ToString();
+ // Set up a PAC file that directs to different servers based on the URL it
+ // sees.
+ std::string pac_script = base::StringPrintf(
+ "function FindProxyForURL(url, host) {"
+ // With the test URL stripped of the path, try to use the embedded test
+ // server to establish a an SSL tunnel over an HTTP proxy. The request
+ // will fail with ERR_TUNNEL_CONNECTION_FAILED.
+ " if (url == 'https://does.not.resolve.test:1872/')"
+ " return 'PROXY %s';"
+ // With the full test URL, try to use a domain that does not resolve as
+ // a proxy. Errors connecting to the proxy result in
+ // ERR_PROXY_CONNECTION_FAILED.
+ " if (url == 'https://does.not.resolve.test:1872/foo')"
+ " return 'PROXY does.not.resolve.test';"
+ // Otherwise, use direct. If a connection to "does.not.resolve.test"
+ // tries to use a direction connection, it will fail with
+ // ERR_NAME_NOT_RESOLVED. This path will also
+ // be used by the initial request in NetworkServiceState::kRestarted
+ // tests to make sure the network service process is fully started
+ // before it's crashed and restarted. Using direct in this case avoids
+ // that request failing with an unexpeced error when being directed to a
+ // bogus proxy.
+ " return 'DIRECT';"
+ "}",
+ test_server_host_port_pair.c_str());
+
+ command_line->AppendSwitchASCII(switches::kProxyPacUrl,
+ "data:," + pac_script);
+ }
+};
+
+// Start Chrome and check that PAC HTTPS path stripping is enabled.
+IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpsStrippingPacBrowserTest,
+ PRE_PacHttpsUrlStripping) {
+ ASSERT_FALSE(CreateDefaultNetworkContextParams()
+ ->dangerously_allow_pac_access_to_secure_urls);
+
+ std::unique_ptr<network::ResourceRequest> request =
+ std::make_unique<network::ResourceRequest>();
+ // This URL should be directed to the proxy that fails with
+ // ERR_TUNNEL_CONNECTION_FAILED.
+ request->url = GURL("https://does.not.resolve.test:1872/foo");
+
+ content::SimpleURLLoaderTestHelper simple_loader_helper;
+ std::unique_ptr<network::SimpleURLLoader> simple_loader =
+ network::SimpleURLLoader::Create(std::move(request),
+ TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ loader_factory(), simple_loader_helper.GetCallback());
+ simple_loader_helper.WaitForCallback();
+ EXPECT_FALSE(simple_loader_helper.response_body());
+ EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, simple_loader->NetError());
+
+ // Disable stripping paths from HTTPS PAC URLs for the next test.
+ g_browser_process->local_state()->SetBoolean(
+ prefs::kPacHttpsUrlStrippingEnabled, false);
+ // Check that the changed setting is reflected in the network context params.
+ // The changes aren't applied to existing URLRequestContexts, however, so have
+ // to restart to see the setting change respected.
+ EXPECT_TRUE(CreateDefaultNetworkContextParams()
+ ->dangerously_allow_pac_access_to_secure_urls);
+}
+
+// Restart Chrome and check the case where PAC HTTPS path stripping is disabled.
+// Have to restart Chrome because the setting is only checked on NetworkContext
+// creation.
+IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpsStrippingPacBrowserTest,
+ PacHttpsUrlStripping) {
+ ASSERT_TRUE(CreateDefaultNetworkContextParams()
+ ->dangerously_allow_pac_access_to_secure_urls);
+
+ std::unique_ptr<network::ResourceRequest> request =
+ std::make_unique<network::ResourceRequest>();
+ // This URL should be directed to the proxy that fails with
+ // ERR_PROXY_CONNECTION_FAILED.
+ request->url = GURL("https://does.not.resolve.test:1872/foo");
+
+ content::SimpleURLLoaderTestHelper simple_loader_helper;
+ std::unique_ptr<network::SimpleURLLoader> simple_loader =
+ network::SimpleURLLoader::Create(std::move(request),
+ TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ loader_factory(), simple_loader_helper.GetCallback());
+ simple_loader_helper.WaitForCallback();
+ EXPECT_FALSE(simple_loader_helper.response_body());
+ EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError());
+}
+
// |NetworkServiceTestHelper| doesn't work on browser_tests on OSX.
#if defined(OS_MACOSX)
// Instiates tests with a prefix indicating which NetworkContext is being
@@ -907,5 +1023,7 @@
NetworkContextConfigurationDataPacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationFtpPacBrowserTest);
+INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
+ NetworkContextConfigurationHttpsStrippingPacBrowserTest);
} // namespace
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 8973309..63e05dfa 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -64,6 +64,7 @@
#include "chrome/browser/media/router/media_router_feature.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
+#include "chrome/browser/net/default_network_context_params.h"
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/permissions/permission_request_manager.h"
@@ -212,6 +213,7 @@
#include "net/url_request/url_request_interceptor.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -1341,24 +1343,10 @@
namespace {
-// The following helpers retrieve whether https:// URL stripping is
-// enabled for PAC scripts. It needs to run on the IO thread.
-void GetPacHttpsUrlStrippingEnabledOnIOThread(IOThread* io_thread,
- bool* enabled) {
- *enabled = io_thread->PacHttpsUrlStrippingEnabled();
-}
-
bool GetPacHttpsUrlStrippingEnabled() {
- bool enabled;
- base::RunLoop loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&GetPacHttpsUrlStrippingEnabledOnIOThread,
- g_browser_process->io_thread(),
- base::Unretained(&enabled)),
- loop.QuitClosure());
- loop.Run();
- return enabled;
+ network::mojom::NetworkContextParamsPtr network_context_params =
+ CreateDefaultNetworkContextParams();
+ return !network_context_params->dangerously_allow_pac_access_to_secure_urls;
}
} // namespace
@@ -1368,6 +1356,8 @@
// default.
IN_PROC_BROWSER_TEST_F(PolicyTest, DisablePacHttpsUrlStripping) {
// Stripping is enabled by default.
+ EXPECT_TRUE(g_browser_process->local_state()->GetBoolean(
+ prefs::kPacHttpsUrlStrippingEnabled));
EXPECT_TRUE(GetPacHttpsUrlStrippingEnabled());
// Disable it via a policy.
@@ -1379,6 +1369,8 @@
content::RunAllPendingInMessageLoop();
// It should now reflect as disabled.
+ EXPECT_FALSE(g_browser_process->local_state()->GetBoolean(
+ prefs::kPacHttpsUrlStrippingEnabled));
EXPECT_FALSE(GetPacHttpsUrlStrippingEnabled());
}
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index d0e4d8e..b7ba0b7 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
#include "chrome/browser/metrics/chrome_metrics_service_client.h"
+#include "chrome/browser/net/default_network_context_params.h"
#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h"
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/net/predictor.h"
@@ -353,6 +354,7 @@
ProfileInfoCache::RegisterPrefs(registry);
profiles::RegisterPrefs(registry);
rappor::RapporServiceImpl::RegisterPrefs(registry);
+ RegisterNetworkContextCreationPrefs(registry);
RegisterScreenshotPrefs(registry);
SigninManagerFactory::RegisterPrefs(registry);
SSLConfigServiceManager::RegisterPrefs(registry);