summaryrefslogtreecommitdiffstats
path: root/net/url_request
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 21:04:42 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 21:04:42 +0000
commit326e67907033c1e8db115327d59482b1ae6db3ec (patch)
tree2940d88e6de6ce6ba528c4671b6574b4ff6bd1bd /net/url_request
parent5973945e4c3d2baf2b92d11be55c1692a09b12e3 (diff)
downloadchromium_src-326e67907033c1e8db115327d59482b1ae6db3ec.zip
chromium_src-326e67907033c1e8db115327d59482b1ae6db3ec.tar.gz
chromium_src-326e67907033c1e8db115327d59482b1ae6db3ec.tar.bz2
SPDY: augment Strict Transport Security with the beginnings of SPDY upgrade.
This adds an opportunistic flag to the information that we store in the Strict Transport Security State. Given this, STSS might be misnamed now, but renaming it in this patch would add huge amounts of noise. We process the 'X-Bodge-Transport-Security' header which has the same format as the STS header. When we see this on an HTTP connection, we'll probe for a clean HTTPS path to the host and then remember it. This header should be considered mutually exclusive with STS, although this isn't enforced in the code. The remembered flag is currently ignored by the rest of the code. This will be addressed in a future patch. The header should be called 'Opportunistic-Transport-Security' in the future, but we have some issues to work out before we take that name. http://codereview.chromium.org/456011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34380 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request')
-rw-r--r--net/url_request/url_request_context.h11
-rw-r--r--net/url_request/url_request_http_job.cc160
2 files changed, 140 insertions, 31 deletions
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index f02bc43..5eac06e 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -16,7 +16,7 @@
#include "net/base/cookie_store.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_config_service.h"
-#include "net/base/strict_transport_security_state.h"
+#include "net/base/transport_security_state.h"
#include "net/ftp/ftp_auth_cache.h"
#include "net/proxy/proxy_service.h"
#include "net/url_request/request_tracker.h"
@@ -36,7 +36,7 @@ class URLRequestContext :
: http_transaction_factory_(NULL),
ftp_transaction_factory_(NULL),
cookie_store_(NULL),
- strict_transport_security_state_(NULL) {
+ transport_security_state_(NULL) {
}
net::HostResolver* host_resolver() const {
@@ -69,8 +69,8 @@ class URLRequestContext :
// Gets the cookie policy for this context.
net::CookiePolicy* cookie_policy() { return &cookie_policy_; }
- net::StrictTransportSecurityState* strict_transport_security_state() {
- return strict_transport_security_state_; }
+ net::TransportSecurityState* transport_security_state() {
+ return transport_security_state_; }
// Gets the FTP authentication cache for this context.
net::FtpAuthCache* ftp_auth_cache() { return &ftp_auth_cache_; }
@@ -132,8 +132,7 @@ class URLRequestContext :
net::FtpTransactionFactory* ftp_transaction_factory_;
scoped_refptr<net::CookieStore> cookie_store_;
net::CookiePolicy cookie_policy_;
- scoped_refptr<net::StrictTransportSecurityState>
- strict_transport_security_state_;
+ scoped_refptr<net::TransportSecurityState> transport_security_state_;
net::FtpAuthCache ftp_auth_cache_;
std::string accept_language_;
std::string accept_charset_;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 84d5709..755bfa7 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -14,7 +14,8 @@
#include "base/string_util.h"
#include "net/base/cert_status_flags.h"
#include "net/base/filter.h"
-#include "net/base/strict_transport_security_state.h"
+#include "net/base/https_prober.h"
+#include "net/base/transport_security_state.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
@@ -46,17 +47,24 @@ URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
return new URLRequestErrorJob(request, net::ERR_INVALID_ARGUMENT);
}
+ net::TransportSecurityState::DomainState domain_state;
if (scheme == "http" &&
- request->context()->strict_transport_security_state() &&
- request->context()->strict_transport_security_state()->IsEnabledForHost(
- request->url().host())) {
- DCHECK_EQ(request->url().scheme(), "http");
- url_canon::Replacements<char> replacements;
- static const char kNewScheme[] = "https";
- replacements.SetScheme(kNewScheme,
- url_parse::Component(0, strlen(kNewScheme)));
- GURL new_location = request->url().ReplaceComponents(replacements);
- return new URLRequestRedirectJob(request, new_location);
+ (request->url().port().empty() || port == 80) &&
+ request->context()->transport_security_state() &&
+ request->context()->transport_security_state()->IsEnabledForHost(
+ &domain_state, request->url().host())) {
+ if (domain_state.mode ==
+ net::TransportSecurityState::DomainState::MODE_STRICT) {
+ DCHECK_EQ(request->url().scheme(), "http");
+ url_canon::Replacements<char> replacements;
+ static const char kNewScheme[] = "https";
+ replacements.SetScheme(kNewScheme,
+ url_parse::Component(0, strlen(kNewScheme)));
+ GURL new_location = request->url().ReplaceComponents(replacements);
+ return new URLRequestRedirectJob(request, new_location);
+ } else {
+ // TODO(agl): implement opportunistic HTTPS upgrade.
+ }
}
return new URLRequestHttpJob(request);
@@ -483,11 +491,16 @@ bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
return false;
// Check whether our context is using Strict-Transport-Security.
- if (!context_->strict_transport_security_state())
+ if (!context_->transport_security_state())
return true;
- return !context_->strict_transport_security_state()->IsEnabledForHost(
- request_info_.url.host());
+ net::TransportSecurityState::DomainState domain_state;
+ // TODO(agl): don't ignore opportunistic mode.
+ const bool r = context_->transport_security_state()->IsEnabledForHost(
+ &domain_state, request_info_.url.host());
+
+ return !r || domain_state.mode ==
+ net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
}
void URLRequestHttpJob::NotifyHeadersComplete() {
@@ -686,28 +699,125 @@ void URLRequestHttpJob::FetchResponseCookies() {
response_cookies_.push_back(value);
}
+class HTTPSProberDelegate : public net::HTTPSProberDelegate {
+ public:
+ HTTPSProberDelegate(const std::string& host, int max_age,
+ bool include_subdomains,
+ net::TransportSecurityState* sts)
+ : host_(host),
+ max_age_(max_age),
+ include_subdomains_(include_subdomains),
+ sts_(sts) { }
+
+ virtual void ProbeComplete(bool result) {
+ if (result) {
+ base::Time current_time(base::Time::Now());
+ base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age_);
+
+ net::TransportSecurityState::DomainState domain_state;
+ domain_state.expiry = current_time + max_age_delta;
+ domain_state.mode =
+ net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
+ domain_state.include_subdomains = include_subdomains_;
+
+ sts_->EnableHost(host_, domain_state);
+ }
-void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
- DCHECK(response_info_);
+ delete this;
+ }
- // Only process Strict-Transport-Security from HTTPS responses.
- if (request_info_.url.scheme() != "https")
- return;
+ private:
+ const std::string host_;
+ const int max_age_;
+ const bool include_subdomains_;
+ scoped_refptr<net::TransportSecurityState> sts_;
+};
- // Only process Strict-Transport-Security from responses with valid certificates.
- if (response_info_->ssl_info.cert_status & net::CERT_STATUS_ALL_ERRORS)
- return;
+void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
+ DCHECK(response_info_);
URLRequestContext* ctx = request_->context();
- if (!ctx || !ctx->strict_transport_security_state())
+ if (!ctx || !ctx->transport_security_state())
return;
+ const bool https = response_info_->ssl_info.is_valid();
+ const bool valid_https =
+ https &&
+ !(response_info_->ssl_info.cert_status & net::CERT_STATUS_ALL_ERRORS);
+
std::string name = "Strict-Transport-Security";
std::string value;
+ int max_age;
+ bool include_subdomains;
+
void* iter = NULL;
while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
- ctx->strict_transport_security_state()->DidReceiveHeader(
- request_info_.url, value);
+ const bool ok = net::TransportSecurityState::ParseHeader(
+ value, &max_age, &include_subdomains);
+ if (!ok)
+ continue;
+ // We will only accept strict mode if we saw the header from an HTTPS
+ // connection with no certificate problems.
+ if (!valid_https)
+ continue;
+ base::Time current_time(base::Time::Now());
+ base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
+
+ net::TransportSecurityState::DomainState domain_state;
+ domain_state.expiry = current_time + max_age_delta;
+ domain_state.mode = net::TransportSecurityState::DomainState::MODE_STRICT;
+ domain_state.include_subdomains = include_subdomains;
+
+ ctx->transport_security_state()->EnableHost(request_info_.url.host(),
+ domain_state);
+ }
+
+ // TODO(agl): change this over when we have fixed things at the server end.
+ // The string should be "Opportunistic-Transport-Security";
+ name = "X-Bodge-Transport-Security";
+
+ while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
+ const bool ok = net::TransportSecurityState::ParseHeader(
+ value, &max_age, &include_subdomains);
+ if (!ok)
+ continue;
+ // If we saw an opportunistic request over HTTPS, then clearly we can make
+ // HTTPS connections to the host so we should remember this.
+ if (https) {
+ base::Time current_time(base::Time::Now());
+ base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
+
+ net::TransportSecurityState::DomainState domain_state;
+ domain_state.expiry = current_time + max_age_delta;
+ domain_state.mode =
+ net::TransportSecurityState::DomainState::MODE_SPDY_ONLY;
+ domain_state.include_subdomains = include_subdomains;
+
+ ctx->transport_security_state()->EnableHost(request_info_.url.host(),
+ domain_state);
+ continue;
+ }
+
+ if (!request())
+ break;
+
+ // At this point, we have a request for opportunistic encryption over HTTP.
+ // In this case we need to probe to check that we can make HTTPS
+ // connections to that host.
+ net::HTTPSProber* const prober = Singleton<net::HTTPSProber>::get();
+ if (prober->HaveProbed(request_info_.url.host()) ||
+ prober->InFlight(request_info_.url.host())) {
+ continue;
+ }
+
+ net::HTTPSProberDelegate* delegate =
+ new HTTPSProberDelegate(request_info_.url.host(), max_age,
+ include_subdomains,
+ ctx->transport_security_state());
+ if (!prober->ProbeHost(request_info_.url.host(), request()->context(),
+ delegate)) {
+ delete delegate;
+ }
}
}