summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrch <rch@chromium.org>2016-01-11 22:53:01 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-12 06:54:10 +0000
commit1ad82bbc44d87669926c9cffe2ba77564df420a3 (patch)
tree82a26c5bb072a2bafddec2665ebfbec3e10f1716
parentd39e5f75823eae74b92ac8dd3b39a0ee740f8cc5 (diff)
downloadchromium_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.cc22
-rw-r--r--chrome/browser/io_thread.h7
-rw-r--r--chrome/browser/io_thread_unittest.cc27
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--net/http/http_network_session.h4
-rw-r--r--net/http/http_stream_factory_impl.cc17
-rw-r--r--net/http/http_stream_factory_impl.h4
-rw-r--r--net/http/transport_security_state.cc19
-rw-r--r--net/http/transport_security_state.h6
-rw-r--r--net/quic/quic_network_transaction_unittest.cc6
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(
&params->quic_idle_connection_timeout_seconds);
globals.quic_disable_preconnect_if_0rtt.CopyToIfSet(
&params->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(
&params->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(&params);
+ 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(&params);
+ 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_);