summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc2
-rw-r--r--chrome/browser/profile.cc18
-rw-r--r--chrome/browser/profile.h10
-rw-r--r--chrome/browser/ssl/ssl_policy.cc14
-rw-r--r--chrome/browser/ssl/ssl_policy_backend.cc8
-rw-r--r--chrome/browser/ssl/ssl_policy_backend.h10
-rw-r--r--chrome/test/testing_profile.h3
-rw-r--r--net/base/force_tls_state.cc34
-rw-r--r--net/base/force_tls_state.h50
-rw-r--r--net/net.gyp2
-rw-r--r--net/url_request/url_request_context.h7
-rw-r--r--net/url_request/url_request_http_job.cc57
-rw-r--r--net/url_request/url_request_http_job.h5
13 files changed, 210 insertions, 10 deletions
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index 06b3739..3ea9cc1 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -292,6 +292,8 @@ ChromeURLRequestContext::ChromeURLRequestContext(Profile* profile)
cookie_policy_.SetType(net::CookiePolicy::FromInt(
prefs_->GetInteger(prefs::kCookieBehavior)));
+ force_tls_state_ = profile->GetForceTLSState();
+
if (profile->GetExtensionsService()) {
const ExtensionList* extensions =
profile->GetExtensionsService()->extensions();
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 1c76c49..cdb7c00 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -39,6 +39,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "grit/locale_settings.h"
+#include "net/base/force_tls_state.h"
using base::Time;
using base::TimeDelta;
@@ -171,6 +172,13 @@ class OffTheRecordProfileImpl : public Profile,
return ssl_host_state_.get();
}
+ virtual net::ForceTLSState* GetForceTLSState() {
+ if (!force_tls_state_.get())
+ force_tls_state_.reset(new net::ForceTLSState());
+
+ return force_tls_state_.get();
+ }
+
virtual HistoryService* GetHistoryService(ServiceAccessType sat) {
if (sat == EXPLICIT_ACCESS) {
return profile_->GetHistoryService(sat);
@@ -389,6 +397,9 @@ class OffTheRecordProfileImpl : public Profile,
// the user visited while OTR.
scoped_ptr<SSLHostState> ssl_host_state_;
+ // The ForceTLSState that only stores enabled sites in memory.
+ scoped_ptr<net::ForceTLSState> force_tls_state_;
+
// Extensions run in a different context in incognito mode.
scoped_ptr<ExtensionProcessManager> extension_process_manager_;
@@ -627,6 +638,13 @@ SSLHostState* ProfileImpl::GetSSLHostState() {
return ssl_host_state_.get();
}
+net::ForceTLSState* ProfileImpl::GetForceTLSState() {
+ if (!force_tls_state_.get())
+ force_tls_state_.reset(new net::ForceTLSState());
+
+ return force_tls_state_.get();
+}
+
PrefService* ProfileImpl::GetPrefs() {
if (!prefs_.get()) {
prefs_.reset(new PrefService(GetPrefFilePath(),
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 6ec129c..be775c2 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -20,6 +20,9 @@
#endif
#include "chrome/common/notification_observer.h"
+namespace net {
+class ForceTLSState;
+}
class BookmarkModel;
class ChromeURLRequestContext;
class DownloadManager;
@@ -128,6 +131,11 @@ class Profile {
// called.
virtual SSLHostState* GetSSLHostState() = 0;
+ // Retrieves a pointer to the ForceTLStSate associated with this profile.
+ // The ForceTLSState is lazily created the first time that this method is
+ // called.
+ virtual net::ForceTLSState* GetForceTLSState() = 0;
+
// Retrieves a pointer to the HistoryService associated with this
// profile. The HistoryService is lazily created the first time
// that this method is called.
@@ -301,6 +309,7 @@ class ProfileImpl : public Profile,
virtual VisitedLinkMaster* GetVisitedLinkMaster();
virtual UserScriptMaster* GetUserScriptMaster();
virtual SSLHostState* GetSSLHostState();
+ virtual net::ForceTLSState* GetForceTLSState();
virtual ExtensionsService* GetExtensionsService();
virtual ExtensionProcessManager* GetExtensionProcessManager();
virtual HistoryService* GetHistoryService(ServiceAccessType sat);
@@ -371,6 +380,7 @@ class ProfileImpl : public Profile,
scoped_refptr<UserScriptMaster> user_script_master_;
scoped_ptr<ExtensionProcessManager> extension_process_manager_;
scoped_ptr<SSLHostState> ssl_host_state_;
+ scoped_ptr<net::ForceTLSState> force_tls_state_;
scoped_ptr<PrefService> prefs_;
scoped_ptr<TemplateURLFetcher> template_url_fetcher_;
scoped_ptr<TemplateURLModel> template_url_model_;
diff --git a/chrome/browser/ssl/ssl_policy.cc b/chrome/browser/ssl/ssl_policy.cc
index 7004da7..3bf64e5 100644
--- a/chrome/browser/ssl/ssl_policy.cc
+++ b/chrome/browser/ssl/ssl_policy.cc
@@ -6,6 +6,8 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/string_util.h"
@@ -117,11 +119,15 @@ void SSLPolicy::OnMixedContent(SSLMixedContentHandler* handler) {
// If the user has added an exception, doctor the |filter_policy|.
std::string host = GURL(handler->main_frame_origin()).host();
- if (backend_->DidAllowMixedContentForHost(host) ||
- backend_->DidMarkHostAsBroken(host, handler->pid()))
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS) &&
+ backend_->IsForceTLSEnabledForHost(host)) {
+ // We're supposed to block all mixed content for this host.
+ filter_policy = FilterPolicy::FILTER_ALL;
+ } else if (backend_->DidAllowMixedContentForHost(host) ||
+ backend_->DidMarkHostAsBroken(host, handler->pid())) {
+ // Let the mixed content through.
filter_policy = FilterPolicy::DONT_FILTER;
-
- if (filter_policy != FilterPolicy::DONT_FILTER) {
+ } else if (filter_policy != FilterPolicy::DONT_FILTER) {
backend_->ShowMessageWithLink(
l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT),
l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT),
diff --git a/chrome/browser/ssl/ssl_policy_backend.cc b/chrome/browser/ssl/ssl_policy_backend.cc
index 9b1eed8..8852190 100644
--- a/chrome/browser/ssl/ssl_policy_backend.cc
+++ b/chrome/browser/ssl/ssl_policy_backend.cc
@@ -13,6 +13,7 @@
#include "chrome/common/notification_service.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "net/base/force_tls_state.h"
using WebKit::WebConsoleMessage;
@@ -67,7 +68,8 @@ class SSLInfoBarDelegate : public ConfirmInfoBarDelegate {
SSLPolicyBackend::SSLPolicyBackend(NavigationController* controller)
: controller_(controller),
- ssl_host_state_(controller->profile()->GetSSLHostState()) {
+ ssl_host_state_(controller->profile()->GetSSLHostState()),
+ force_tls_state_(controller->profile()->GetForceTLSState()) {
DCHECK(controller_);
}
@@ -159,6 +161,10 @@ bool SSLPolicyBackend::DidAllowMixedContentForHost(
return ssl_host_state_->DidAllowMixedContentForHost(host);
}
+bool SSLPolicyBackend::IsForceTLSEnabledForHost(const std::string& host) const {
+ return force_tls_state_->IsEnabledForHost(host);
+}
+
void SSLPolicyBackend::Reload() {
controller_->Reload(true);
}
diff --git a/chrome/browser/ssl/ssl_policy_backend.h b/chrome/browser/ssl/ssl_policy_backend.h
index f8a829c..2d84232 100644
--- a/chrome/browser/ssl/ssl_policy_backend.h
+++ b/chrome/browser/ssl/ssl_policy_backend.h
@@ -13,6 +13,9 @@
#include "net/base/x509_certificate.h"
#include "webkit/api/public/WebConsoleMessage.h"
+namespace net {
+class ForceTLSState;
+}
class NavigationController;
class SSLHostState;
class Task;
@@ -68,6 +71,9 @@ class SSLPolicyBackend {
// Returns whether the specified host is allowed to show mixed content.
bool DidAllowMixedContentForHost(const std::string& host) const;
+ // Returns whether ForceTLS is enabled for |host|.
+ bool IsForceTLSEnabledForHost(const std::string& host) const;
+
// Reloads the tab.
void Reload();
@@ -112,6 +118,10 @@ class SSLPolicyBackend {
// SSL state specific for each host.
SSLHostState* ssl_host_state_;
+ // ForceTLS state.
+ // TODO(abarth): Consider combining with SSLHostState?
+ net::ForceTLSState* force_tls_state_;
+
// The list of messages that should be displayed (in info bars) when the page
// currently loading had loaded.
std::vector<SSLMessageInfo> pending_messages_;
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index f83e5e4..974d31d 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -90,6 +90,9 @@ class TestingProfile : public Profile {
virtual SSLHostState* GetSSLHostState() {
return NULL;
}
+ virtual net::ForceTLSState* GetForceTLSState() {
+ return NULL;
+ }
virtual HistoryService* GetHistoryService(ServiceAccessType access) {
return history_service_.get();
}
diff --git a/net/base/force_tls_state.cc b/net/base/force_tls_state.cc
new file mode 100644
index 0000000..4be33f5
--- /dev/null
+++ b/net/base/force_tls_state.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/force_tls_state.h"
+
+#include "base/logging.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/registry_controlled_domain.h"
+
+namespace net {
+
+ForceTLSState::ForceTLSState() {
+}
+
+void ForceTLSState::DidReceiveHeader(const GURL& url,
+ const std::string& value) {
+ // TODO(abarth): Actually parse |value| once the spec settles down.
+ EnableHost(url.host());
+}
+
+void ForceTLSState::EnableHost(const std::string& host) {
+ // TODO(abarth): Canonicalize host.
+ AutoLock lock(lock_);
+ enabled_hosts_.insert(host);
+}
+
+bool ForceTLSState::IsEnabledForHost(const std::string& host) {
+ // TODO(abarth): Canonicalize host.
+ AutoLock lock(lock_);
+ return enabled_hosts_.find(host) != enabled_hosts_.end();
+}
+
+} // namespace
diff --git a/net/base/force_tls_state.h b/net/base/force_tls_state.h
new file mode 100644
index 0000000..988e9c07
--- /dev/null
+++ b/net/base/force_tls_state.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_FORCE_TLS_STATE_H_
+#define NET_BASE_FORCE_TLS_STATE_H_
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/lock.h"
+
+class GURL;
+
+namespace net {
+
+// ForceTLSState
+//
+// Tracks which hosts have enabled ForceTLS. After a host enables ForceTLS,
+// then we refuse to talk to the host over HTTP, treat all certificate errors as
+// fatal, and refuses to load any mixed content.
+//
+class ForceTLSState {
+ public:
+ ForceTLSState();
+
+ // Called when we see an X-Force-TLS header that we should process. Modifies
+ // our state as instructed by the header.
+ void DidReceiveHeader(const GURL& url, const std::string& value);
+
+ // Enable ForceTLS for |host|.
+ void EnableHost(const std::string& host);
+
+ // Returns whether |host| has had ForceTLS enabled.
+ bool IsEnabledForHost(const std::string& host);
+
+ private:
+ // The set of hosts that have enabled ForceTLS.
+ std::set<std::string> enabled_hosts_;
+
+ // Protect access to our data members with this lock.
+ Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForceTLSState);
+};
+
+} // namespace net
+
+#endif // NET_BASE_FORCE_TLS_STATE_H_
diff --git a/net/net.gyp b/net/net.gyp
index 8c11266..778f2da 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -75,6 +75,8 @@
'base/file_stream_win.cc',
'base/filter.cc',
'base/filter.h',
+ 'base/force_tls_state.cc',
+ 'base/force_tls_state.h',
'base/gzip_filter.cc',
'base/gzip_filter.h',
'base/gzip_header.cc',
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 29735ac..8e32c97 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -17,6 +17,7 @@
namespace net {
class CookieMonster;
+class ForceTLSState;
class FtpTransactionFactory;
class HttpTransactionFactory;
class ProxyService;
@@ -30,7 +31,8 @@ class URLRequestContext :
: proxy_service_(NULL),
http_transaction_factory_(NULL),
ftp_transaction_factory_(NULL),
- cookie_store_(NULL) {
+ cookie_store_(NULL),
+ force_tls_state_(NULL) {
}
// Get the proxy service for this context.
@@ -54,6 +56,8 @@ class URLRequestContext :
// Gets the cookie policy for this context.
net::CookiePolicy* cookie_policy() { return &cookie_policy_; }
+ net::ForceTLSState* force_tls_state() { return force_tls_state_; }
+
// Gets the FTP authentication cache for this context.
net::FtpAuthCache* ftp_auth_cache() { return &ftp_auth_cache_; }
@@ -89,6 +93,7 @@ class URLRequestContext :
net::FtpTransactionFactory* ftp_transaction_factory_;
net::CookieMonster* cookie_store_;
net::CookiePolicy cookie_policy_;
+ net::ForceTLSState* force_tls_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 a86edbd..eff2344 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -12,8 +12,10 @@
#include "base/message_loop.h"
#include "base/rand_util.h"
#include "base/string_util.h"
+#include "net/base/cert_status_flags.h"
#include "net/base/cookie_monster.h"
#include "net/base/filter.h"
+#include "net/base/force_tls_state.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
@@ -47,7 +49,10 @@ URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
// network request.
static const bool kForceHTTPS =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS);
- if (kForceHTTPS && scheme != "https")
+ if (kForceHTTPS && scheme == "http" &&
+ request->context()->force_tls_state() &&
+ request->context()->force_tls_state()->IsEnabledForHost(
+ request->url().host()))
return new URLRequestErrorJob(request, net::ERR_DISALLOWED_URL_SCHEME);
return new URLRequestHttpJob(request);
@@ -441,9 +446,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
if (result == net::OK) {
NotifyHeadersComplete();
- } else if (net::IsCertificateError(result) &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceHTTPS)) {
+ } else if (ShouldTreatAsCertificateError(result)) {
// We encountered an SSL certificate error. Ask our delegate to decide
// what we should do.
// TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
@@ -470,6 +473,22 @@ void URLRequestHttpJob::OnReadCompleted(int result) {
NotifyReadComplete(result);
}
+bool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
+ if (!net::IsCertificateError(result))
+ return false;
+
+ // Hide the fancy processing behind a command line switch.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS))
+ return true;
+
+ // Check whether our context is using ForceTLS.
+ if (!context_->force_tls_state())
+ return true;
+
+ return !context_->force_tls_state()->IsEnabledForHost(
+ request_info_.url.host());
+}
+
void URLRequestHttpJob::NotifyHeadersComplete() {
DCHECK(!response_info_);
@@ -494,6 +513,8 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
}
}
+ ProcessForceTLSHeader();
+
if (SdchManager::Global() &&
SdchManager::Global()->IsInSupportedDomain(request_->url())) {
static const std::string name = "Get-Dictionary";
@@ -657,3 +678,31 @@ void URLRequestHttpJob::FetchResponseCookies() {
while (response_info_->headers->EnumerateHeader(&iter, name, &value))
response_cookies_.push_back(value);
}
+
+
+void URLRequestHttpJob::ProcessForceTLSHeader() {
+ DCHECK(response_info_);
+
+ // Hide processing behind a command line flag.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceHTTPS))
+ return;
+
+ // Only process X-Force-TLS from HTTPS responses.
+ if (request_info_.url.scheme() != "https")
+ return;
+
+ // Only process X-Force-TLS from responses with valid certificates.
+ if (response_info_->ssl_info.cert_status & net::CERT_STATUS_ALL_ERRORS)
+ return;
+
+ URLRequestContext* ctx = request_->context();
+ if (!ctx || !ctx->force_tls_state())
+ return;
+
+ std::string name = "X-Force-TLS";
+ std::string value;
+
+ void* iter = NULL;
+ while (response_info_->headers->EnumerateHeader(&iter, name, &value))
+ ctx->force_tls_state()->DidReceiveHeader(request_info_.url, value);
+}
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index a946f62..7853f83 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -67,9 +67,14 @@ class URLRequestHttpJob : public URLRequestJob {
std::string AssembleRequestCookies();
void FetchResponseCookies();
+ // Process the X-Force-TLS header, if one exists.
+ void ProcessForceTLSHeader();
+
void OnStartCompleted(int result);
void OnReadCompleted(int result);
+ bool ShouldTreatAsCertificateError(int result);
+
void RestartTransactionWithAuth(const std::wstring& username,
const std::wstring& password);