diff options
author | rch <rch@chromium.org> | 2016-01-11 22:53:01 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-12 06:54:10 +0000 |
commit | 1ad82bbc44d87669926c9cffe2ba77564df420a3 (patch) | |
tree | 82a26c5bb072a2bafddec2665ebfbec3e10f1716 | |
parent | d39e5f75823eae74b92ac8dd3b39a0ee740f8cc5 (diff) | |
download | chromium_src-1ad82bbc44d87669926c9cffe2ba77564df420a3.zip chromium_src-1ad82bbc44d87669926c9cffe2ba77564df420a3.tar.gz chromium_src-1ad82bbc44d87669926c9cffe2ba77564df420a3.tar.bz2 |
Add a whitelist for QUIC hosts.
BUG=576402
Review URL: https://codereview.chromium.org/1580583002
Cr-Commit-Position: refs/heads/master@{#368810}
-rw-r--r-- | chrome/browser/io_thread.cc | 22 | ||||
-rw-r--r-- | chrome/browser/io_thread.h | 7 | ||||
-rw-r--r-- | chrome/browser/io_thread_unittest.cc | 27 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rw-r--r-- | net/http/http_network_session.h | 4 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl.cc | 17 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl.h | 4 | ||||
-rw-r--r-- | net/http/transport_security_state.cc | 19 | ||||
-rw-r--r-- | net/http/transport_security_state.h | 6 | ||||
-rw-r--r-- | net/quic/quic_network_transaction_unittest.cc | 6 |
11 files changed, 116 insertions, 0 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index cc7872f..cf17f98 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -1178,6 +1178,8 @@ void IOThread::InitializeNetworkSessionParamsFromGlobals( ¶ms->quic_idle_connection_timeout_seconds); globals.quic_disable_preconnect_if_0rtt.CopyToIfSet( ¶ms->quic_disable_preconnect_if_0rtt); + if (!globals.quic_host_whitelist.empty()) + params->quic_host_whitelist = globals.quic_host_whitelist; globals.origin_to_force_quic_on.CopyToIfSet( ¶ms->origin_to_force_quic_on); @@ -1317,6 +1319,8 @@ void IOThread::ConfigureQuicGlobals( } globals->quic_disable_preconnect_if_0rtt.set( ShouldQuicDisablePreConnectIfZeroRtt(quic_trial_params)); + globals->quic_host_whitelist = + GetQuicHostWhitelist(command_line, quic_trial_params); } size_t max_packet_length = GetQuicMaxPacketLength(command_line, @@ -1576,6 +1580,24 @@ bool IOThread::ShouldQuicDisablePreConnectIfZeroRtt( "true"); } +std::unordered_set<std::string> IOThread::GetQuicHostWhitelist( + const base::CommandLine& command_line, + const VariationParameters& quic_trial_params) { + std::string whitelist; + if (command_line.HasSwitch(switches::kQuicHostWhitelist)) { + whitelist = command_line.GetSwitchValueASCII(switches::kQuicHostWhitelist); + } else { + whitelist = GetVariationParam(quic_trial_params, "quic_host_whitelist"); + } + std::unordered_set<std::string> hosts; + for (const std::string& host :base::SplitString(whitelist, ",", + base::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL)) { + hosts.insert(host); + } + return hosts; +} + size_t IOThread::GetQuicMaxPacketLength( const base::CommandLine& command_line, const VariationParameters& quic_trial_params) { diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index b7ca041..763273f 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h @@ -11,6 +11,7 @@ #include <map> #include <set> #include <string> +#include <unordered_set> #include <vector> #include "base/compiler_specific.h" @@ -239,6 +240,7 @@ class IOThread : public content::BrowserThreadDelegate { Optional<bool> quic_close_sessions_on_ip_change; Optional<int> quic_idle_connection_timeout_seconds; Optional<bool> quic_disable_preconnect_if_0rtt; + std::unordered_set<std::string> quic_host_whitelist; bool enable_user_alternate_protocol_ports; // NetErrorTabHelper uses |dns_probe_service| to send DNS probes when a // main frame load fails with a DNS error in order to provide more useful @@ -461,6 +463,11 @@ class IOThread : public content::BrowserThreadDelegate { static bool ShouldQuicDisablePreConnectIfZeroRtt( const VariationParameters& quic_trial_params); + // Returns the set of hosts to whitelist for QUIC. + static std::unordered_set<std::string> GetQuicHostWhitelist( + const base::CommandLine& command_line, + const VariationParameters& quic_trial_params); + // Returns the maximum length for QUIC packets, based on any flags in // |command_line| or the field trial. Returns 0 if there is an error // parsing any of the options, or if the default value should be used. diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc index f3321ee..4511749 100644 --- a/chrome/browser/io_thread_unittest.cc +++ b/chrome/browser/io_thread_unittest.cc @@ -238,6 +238,7 @@ TEST_F(IOThreadTest, EnableQuicFromFieldTrialGroup) { params.quic_idle_connection_timeout_seconds); EXPECT_FALSE(params.quic_disable_preconnect_if_0rtt); EXPECT_FALSE(IOThread::ShouldEnableQuicForDataReductionProxy()); + EXPECT_TRUE(params.quic_host_whitelist.empty()); } TEST_F(IOThreadTest, EnableQuicFromQuicProxyFieldTrialGroup) { @@ -571,6 +572,32 @@ TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromParams) { EXPECT_EQ(.5, params.alternative_service_probability_threshold); } +TEST_F(IOThreadTest, QuicWhitelistFromCommandLinet) { + command_line_.AppendSwitch("enable-quic"); + command_line_.AppendSwitchASCII("quic-host-whitelist", + "www.example.org, www.example.com"); + + ConfigureQuicGlobals(); + net::HttpNetworkSession::Params params; + InitializeNetworkSessionParams(¶ms); + EXPECT_EQ(2u, params.quic_host_whitelist.size()); + EXPECT_TRUE(ContainsKey(params.quic_host_whitelist, "www.example.org")); + EXPECT_TRUE(ContainsKey(params.quic_host_whitelist, "www.example.com")); +} + +TEST_F(IOThreadTest, QuicWhitelistFromParams) { + field_trial_group_ = "Enabled"; + field_trial_params_["quic_host_whitelist"] = + "www.example.org, www.example.com"; + + ConfigureQuicGlobals(); + net::HttpNetworkSession::Params params; + InitializeNetworkSessionParams(¶ms); + EXPECT_EQ(2u, params.quic_host_whitelist.size()); + EXPECT_TRUE(ContainsKey(params.quic_host_whitelist, "www.example.org")); + EXPECT_TRUE(ContainsKey(params.quic_host_whitelist, "www.example.com")); +} + TEST_F(IOThreadTest, QuicDisallowedByPolicy) { command_line_.AppendSwitch(switches::kEnableQuic); is_quic_allowed_by_policy_ = false; diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 809f382..a667134 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -884,6 +884,9 @@ const char kProxyServer[] = "proxy-server"; // the server. const char kQuicConnectionOptions[] = "quic-connection-options"; +// Specifies a comma separated list of hosts to whitelist QUIC for. +const char kQuicHostWhitelist[] = "quic-host-whitelist"; + // Specifies the maximum length for a QUIC packet. const char kQuicMaxPacketLength[] = "quic-max-packet-length"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f53b0be..64cf8a4 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -238,6 +238,7 @@ extern const char kProxyBypassList[]; extern const char kProxyPacUrl[]; extern const char kProxyServer[]; extern const char kQuicConnectionOptions[]; +extern const char kQuicHostWhitelist[]; extern const char kQuicMaxPacketLength[]; extern const char kQuicVersion[]; extern const char kRemoteDebuggingTargets[]; diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 1c3d6a9..d5acd6f 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -10,6 +10,7 @@ #include <set> #include <string> +#include <unordered_set> #include <vector> #include "base/memory/ref_counted.h" @@ -181,6 +182,9 @@ class NET_EXPORT HttpNetworkSession int quic_idle_connection_timeout_seconds; // If true, disable preconnections if QUIC can do 0RTT. bool quic_disable_preconnect_if_0rtt; + // List of hosts for which QUIC is explicitly whitelisted. + std::unordered_set<std::string> quic_host_whitelist; + ProxyDelegate* proxy_delegate; }; diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc index 913eeea..c9272a83 100644 --- a/net/http/http_stream_factory_impl.cc +++ b/net/http/http_stream_factory_impl.cc @@ -8,11 +8,13 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "base/strings/string_util.h" #include "net/base/net_util.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties.h" #include "net/http/http_stream_factory_impl_job.h" #include "net/http/http_stream_factory_impl_request.h" +#include "net/http/transport_security_state.h" #include "net/log/net_log.h" #include "net/net_features.h" #include "net/quic/quic_server_id.h" @@ -286,6 +288,9 @@ AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor( server_id, request_info.privacy_mode, origin_host)) return alternative_service; + if (!IsQuicWhitelistedForHost(destination.host())) + continue; + // Cache this entry if we don't have a non-broken Alt-Svc yet. if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) first_alternative_service = alternative_service; @@ -366,4 +371,16 @@ void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { OnPreconnectsCompleteInternal(); } +bool HttpStreamFactoryImpl::IsQuicWhitelistedForHost(const std::string& host) { + if (session_->params().transport_security_state->IsGooglePinnedHost(host)) + return true; + + std::string lower_host = base::ToLowerASCII(host); + if (ContainsKey(session_->params().quic_host_whitelist, lower_host)) + return true; + + return base::EndsWith(lower_host, ".snapchat.com", + base::CompareCase::SENSITIVE); +} + } // namespace net diff --git a/net/http/http_stream_factory_impl.h b/net/http/http_stream_factory_impl.h index 5d8a206..799398f53 100644 --- a/net/http/http_stream_factory_impl.h +++ b/net/http/http_stream_factory_impl.h @@ -118,6 +118,10 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory { // Called when the Preconnect completes. Used for testing. virtual void OnPreconnectsCompleteInternal() {} + // Returns true if QUIC is whitelisted for |host|, which should be + // the result of calling ApplyHostMappingRules(). + bool IsQuicWhitelistedForHost(const std::string& host); + HttpNetworkSession* const session_; // All Requests are handed out to clients. By the time HttpStreamFactoryImpl diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index e77c8c5..8eb2943 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc @@ -1100,6 +1100,25 @@ bool TransportSecurityState::GetStaticDomainState(const std::string& host, return true; } +bool TransportSecurityState::IsGooglePinnedHost(const std::string& host) const { + DCHECK(CalledOnValidThread()); + + if (!IsBuildTimely()) + return false; + + PreloadResult result; + if (!DecodeHSTSPreload(host, &result)) + return false; + + if (!result.has_pins) + return false; + + if (result.pinset_id >= arraysize(kPinsets)) + return false; + + return kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts; +} + bool TransportSecurityState::GetStaticExpectCTState( const std::string& host, ExpectCTState* expect_ct_state) const { diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h index afdf6c3..a4c52e7 100644 --- a/net/http/transport_security_state.h +++ b/net/http/transport_security_state.h @@ -282,6 +282,12 @@ class NET_EXPORT TransportSecurityState STSState* sts_result, PKPState* pkp_result) const; + // Returns true iff there is static (built-in) state for |host| that + // references the Google pins. + // TODO(rch): Remove this temporary gross layering violation once QUIC 32 is + // deployed. + bool IsGooglePinnedHost(const std::string& host) const; + // Returns true and updates |*expect_ct_result| iff there is a static // (built-in) state for |host| with expect_ct=true. bool GetStaticExpectCTState(const std::string& host, diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index b67d646..e4ccdc71 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc @@ -431,6 +431,12 @@ class QuicNetworkTransactionTest params_.http_auth_handler_factory = auth_handler_factory_.get(); params_.http_server_properties = http_server_properties_.GetWeakPtr(); params_.quic_supported_versions = SupportedVersions(GetParam()); + for (const char* host : + {kDefaultServerHostName, "www.example.com", "news.example.com", + "bar.example.com", "foo.example.com", "www.example.org", + "invalid.example.org", "docs.example.org"}) { + params_.quic_host_whitelist.insert(host); + } test_network_quality_estimator_->AddRTTObserver(&rtt_observer_); |