summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-03 21:22:54 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-03 21:22:54 +0000
commit74b962aa204b487dabcdb2fb9e7c7c7c62db1c5f (patch)
treeb657993dd56e264e0f241ee7afca583e1a53a5ab /content
parent6483195d6640a3727cc6e6e717718bd08036154b (diff)
downloadchromium_src-74b962aa204b487dabcdb2fb9e7c7c7c62db1c5f.zip
chromium_src-74b962aa204b487dabcdb2fb9e7c7c7c62db1c5f.tar.gz
chromium_src-74b962aa204b487dabcdb2fb9e7c7c7c62db1c5f.tar.bz2
Move most of the core SSL code from chrome to content. The UI code that's specific to Chrome (i.e. interstitial, dialogs) stays behind. This change just moves code, and so adds a bunch of files to DEPS. I'll add proper interfaces in a follow up cl, but keeping the move simple at first.
BUG=76697 Review URL: http://codereview.chromium.org/7111013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87866 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/DEPS7
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.cc4
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host_request_info.cc2
-rw-r--r--content/browser/ssl/ssl_cert_error_handler.cc39
-rw-r--r--content/browser/ssl/ssl_cert_error_handler.h51
-rw-r--r--content/browser/ssl/ssl_client_auth_handler.cc156
-rw-r--r--content/browser/ssl/ssl_client_auth_handler.h111
-rw-r--r--content/browser/ssl/ssl_client_auth_notification_details.cc21
-rw-r--r--content/browser/ssl/ssl_client_auth_notification_details.h32
-rw-r--r--content/browser/ssl/ssl_error_handler.cc185
-rw-r--r--content/browser/ssl/ssl_error_handler.h144
-rw-r--r--content/browser/ssl/ssl_host_state.cc45
-rw-r--r--content/browser/ssl/ssl_host_state.h63
-rw-r--r--content/browser/ssl/ssl_host_state_unittest.cc154
-rw-r--r--content/browser/ssl/ssl_manager.cc247
-rw-r--r--content/browser/ssl/ssl_manager.h128
-rw-r--r--content/browser/ssl/ssl_policy.cc223
-rw-r--r--content/browser/ssl/ssl_policy.h71
-rw-r--r--content/browser/ssl/ssl_policy_backend.cc39
-rw-r--r--content/browser/ssl/ssl_policy_backend.h46
-rw-r--r--content/browser/ssl/ssl_request_info.cc19
-rw-r--r--content/browser/ssl/ssl_request_info.h46
-rw-r--r--content/browser/tab_contents/navigation_controller.h2
-rw-r--r--content/browser/tab_contents/provisional_load_details.cc2
-rw-r--r--content/content_browser.gypi18
25 files changed, 1848 insertions, 7 deletions
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 2f4ed5e..d6142c6 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -47,8 +47,11 @@ include_rules = [
"+chrome/browser/sessions/session_types.h",
"+chrome/browser/ssl/ssl_add_cert_handler.h",
- "+chrome/browser/ssl/ssl_client_auth_handler.h",
- "+chrome/browser/ssl/ssl_manager.h",
+ "+chrome/browser/ssl/ssl_blocking_page.h",
+ "+chrome/browser/ssl/ssl_error_info.h",
+ "+chrome/browser/tab_contents/tab_contents_ssl_helper.h",
+ "+chrome/browser/tab_contents/tab_util.h",
+ "+chrome/browser/ui/tab_contents/tab_contents_wrapper.h",
"+chrome/browser/tab_contents/render_view_host_delegate_helper.h",
diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc
index 200466a..e6f4191 100644
--- a/content/browser/renderer_host/resource_dispatcher_host.cc
+++ b/content/browser/renderer_host/resource_dispatcher_host.cc
@@ -25,8 +25,6 @@
#include "chrome/browser/download/save_file_manager.h"
#include "chrome/browser/renderer_host/download_resource_handler.h"
#include "chrome/browser/renderer_host/save_file_resource_handler.h"
-#include "chrome/browser/ssl/ssl_client_auth_handler.h"
-#include "chrome/browser/ssl/ssl_manager.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/cert_store.h"
#include "content/browser/child_process_security_policy.h"
@@ -51,6 +49,8 @@
#include "content/browser/renderer_host/resource_queue.h"
#include "content/browser/renderer_host/resource_request_details.h"
#include "content/browser/renderer_host/sync_resource_handler.h"
+#include "content/browser/ssl/ssl_client_auth_handler.h"
+#include "content/browser/ssl/ssl_manager.h"
#include "content/browser/worker_host/worker_service.h"
#include "content/common/content_switches.h"
#include "content/common/notification_service.h"
diff --git a/content/browser/renderer_host/resource_dispatcher_host_request_info.cc b/content/browser/renderer_host/resource_dispatcher_host_request_info.cc
index b1edd29..ec5211d 100644
--- a/content/browser/renderer_host/resource_dispatcher_host_request_info.cc
+++ b/content/browser/renderer_host/resource_dispatcher_host_request_info.cc
@@ -4,9 +4,9 @@
#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
-#include "chrome/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/renderer_host/resource_dispatcher_host_login_delegate.h"
#include "content/browser/renderer_host/resource_handler.h"
+#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "webkit/blob/blob_data.h"
ResourceDispatcherHostRequestInfo::ResourceDispatcherHostRequestInfo(
diff --git a/content/browser/ssl/ssl_cert_error_handler.cc b/content/browser/ssl/ssl_cert_error_handler.cc
new file mode 100644
index 0000000..c668b41
--- /dev/null
+++ b/content/browser/ssl/ssl_cert_error_handler.cc
@@ -0,0 +1,39 @@
+// 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 "content/browser/ssl/ssl_cert_error_handler.h"
+
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "content/browser/ssl/ssl_policy.h"
+#include "net/base/x509_certificate.h"
+
+SSLCertErrorHandler::SSLCertErrorHandler(
+ ResourceDispatcherHost* rdh,
+ net::URLRequest* request,
+ ResourceType::Type resource_type,
+ int cert_error,
+ net::X509Certificate* cert)
+ : SSLErrorHandler(rdh, request, resource_type),
+ cert_error_(cert_error) {
+ DCHECK(request == resource_dispatcher_host_->GetURLRequest(request_id_));
+
+ // We cannot use the request->ssl_info(), it's not been initialized yet, so
+ // we have to set the fields manually.
+ ssl_info_.cert = cert;
+ ssl_info_.SetCertError(cert_error);
+}
+
+SSLCertErrorHandler* SSLCertErrorHandler::AsSSLCertErrorHandler() {
+ return this;
+}
+
+void SSLCertErrorHandler::OnDispatchFailed() {
+ CancelRequest();
+}
+
+void SSLCertErrorHandler::OnDispatched() {
+ manager_->policy()->OnCertError(this);
+}
+
+SSLCertErrorHandler::~SSLCertErrorHandler() {}
diff --git a/content/browser/ssl/ssl_cert_error_handler.h b/content/browser/ssl/ssl_cert_error_handler.h
new file mode 100644
index 0000000..6dcbe0f
--- /dev/null
+++ b/content/browser/ssl/ssl_cert_error_handler.h
@@ -0,0 +1,51 @@
+// 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 CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
+#define CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "content/browser/ssl/ssl_error_handler.h"
+#include "net/base/ssl_info.h"
+
+namespace net {
+class X509Certificate;
+}
+
+// A CertError represents an error that occurred with the certificate in an
+// SSL session. A CertError object exists both on the IO thread and on the UI
+// thread and allows us to cancel/continue a request it is associated with.
+class SSLCertErrorHandler : public SSLErrorHandler {
+ public:
+ // Construct on the IO thread.
+ SSLCertErrorHandler(ResourceDispatcherHost* rdh,
+ net::URLRequest* request,
+ ResourceType::Type resource_type,
+ int cert_error,
+ net::X509Certificate* cert);
+
+ virtual SSLCertErrorHandler* AsSSLCertErrorHandler();
+
+ // These accessors are available on either thread
+ const net::SSLInfo& ssl_info() const { return ssl_info_; }
+ int cert_error() const { return cert_error_; }
+
+ protected:
+ // SSLErrorHandler methods
+ virtual void OnDispatchFailed();
+ virtual void OnDispatched();
+
+ private:
+ virtual ~SSLCertErrorHandler();
+
+ // These read-only members may be accessed on any thread.
+ net::SSLInfo ssl_info_;
+ const int cert_error_; // The error we represent.
+
+ DISALLOW_COPY_AND_ASSIGN(SSLCertErrorHandler);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
diff --git a/content/browser/ssl/ssl_client_auth_handler.cc b/content/browser/ssl/ssl_client_auth_handler.cc
new file mode 100644
index 0000000..02cb174
--- /dev/null
+++ b/content/browser/ssl/ssl_client_auth_handler.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2011 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 "content/browser/ssl/ssl_client_auth_handler.h"
+
+#include "chrome/browser/tab_contents/tab_contents_ssl_helper.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
+#include "content/browser/ssl/ssl_client_auth_notification_details.h"
+#include "content/common/notification_service.h"
+#include "net/url_request/url_request.h"
+
+SSLClientAuthHandler::SSLClientAuthHandler(
+ net::URLRequest* request,
+ net::SSLCertRequestInfo* cert_request_info)
+ : request_(request),
+ cert_request_info_(cert_request_info) {
+}
+
+SSLClientAuthHandler::~SSLClientAuthHandler() {
+ // If we were simply dropped, then act as if we selected no certificate.
+ DoCertificateSelected(NULL);
+}
+
+void SSLClientAuthHandler::OnRequestCancelled() {
+ request_ = NULL;
+}
+
+void SSLClientAuthHandler::SelectCertificate() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ int render_process_host_id;
+ int render_view_host_id;
+ if (!ResourceDispatcherHost::RenderViewForRequest(request_,
+ &render_process_host_id,
+ &render_view_host_id))
+ NOTREACHED();
+
+ // If the RVH does not exist by the time this task gets run, then the task
+ // will be dropped and the scoped_refptr to SSLClientAuthHandler will go
+ // away, so we do not leak anything. The destructor takes care of ensuring
+ // the net::URLRequest always gets a response.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &SSLClientAuthHandler::ShowClientCertificateRequestDialog,
+ render_process_host_id, render_view_host_id));
+}
+
+// Sends an SSL_CLIENT_AUTH_CERT_SELECTED notification and notifies the IO
+// thread that we have selected a cert.
+void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
+ VLOG(1) << this << " CertificateSelected " << cert;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ SSLClientAuthNotificationDetails details(cert_request_info_, cert);
+ NotificationService* service = NotificationService::current();
+ service->Notify(NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED,
+ Source<SSLClientAuthHandler>(this),
+ Details<SSLClientAuthNotificationDetails>(&details));
+
+ CertificateSelectedNoNotify(cert);
+}
+
+// Notifies the IO thread that we have selected a cert.
+void SSLClientAuthHandler::CertificateSelectedNoNotify(
+ net::X509Certificate* cert) {
+ VLOG(1) << this << " CertificateSelectedNoNotify " << cert;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &SSLClientAuthHandler::DoCertificateSelected,
+ make_scoped_refptr(cert)));
+}
+
+void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) {
+ VLOG(1) << this << " DoCertificateSelected " << cert;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // request_ could have been NULLed if the request was cancelled while the
+ // user was choosing a cert, or because we have already responded to the
+ // certificate.
+ if (request_) {
+ request_->ContinueWithCertificate(cert);
+
+ ResourceDispatcherHostRequestInfo* info =
+ ResourceDispatcherHost::InfoForRequest(request_);
+ if (info)
+ info->set_ssl_client_auth_handler(NULL);
+
+ request_ = NULL;
+ }
+}
+
+void SSLClientAuthHandler::ShowClientCertificateRequestDialog(
+ int render_process_host_id, int render_view_host_id) {
+ TabContents* tab = tab_util::GetTabContentsByID(
+ render_process_host_id, render_view_host_id);
+ if (!tab)
+ return;
+
+ TabContentsWrapper* wrapper =
+ TabContentsWrapper::GetCurrentWrapperForContents(tab);
+ wrapper->ssl_helper()->ShowClientCertificateRequestDialog(this);
+}
+
+SSLClientAuthObserver::SSLClientAuthObserver(
+ net::SSLCertRequestInfo* cert_request_info,
+ SSLClientAuthHandler* handler)
+ : cert_request_info_(cert_request_info), handler_(handler) {
+}
+
+SSLClientAuthObserver::~SSLClientAuthObserver() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void SSLClientAuthObserver::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ VLOG(1) << "SSLClientAuthObserver::Observe " << this << " " << handler_.get();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(type == NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED);
+
+ if (Source<SSLClientAuthHandler>(source).ptr() == handler_.get()) {
+ VLOG(1) << "got notification from ourself " << handler_.get();
+ return;
+ }
+
+ SSLClientAuthNotificationDetails* auth_details =
+ Details<SSLClientAuthNotificationDetails>(details).ptr();
+ if (!auth_details->IsSameHost(cert_request_info_))
+ return;
+
+ VLOG(1) << this << " got matching notification for "
+ << handler_.get() << ", selecting cert "
+ << auth_details->selected_cert();
+ StopObserving();
+ handler_->CertificateSelectedNoNotify(auth_details->selected_cert());
+ OnCertSelectedByNotification();
+}
+
+void SSLClientAuthObserver::StartObserving() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ notification_registrar_.Add(this,
+ NotificationType::SSL_CLIENT_AUTH_CERT_SELECTED,
+ NotificationService::AllSources());
+}
+
+void SSLClientAuthObserver::StopObserving() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ notification_registrar_.RemoveAll();
+}
diff --git a/content/browser/ssl/ssl_client_auth_handler.h b/content/browser/ssl/ssl_client_auth_handler.h
new file mode 100644
index 0000000..0b2e9cb
--- /dev/null
+++ b/content/browser/ssl/ssl_client_auth_handler.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_
+#define CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/browser_thread.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
+#include "net/base/ssl_cert_request_info.h"
+
+namespace net {
+class URLRequest;
+class X509Certificate;
+} // namespace net
+
+// This class handles the approval and selection of a certificate for SSL client
+// authentication by the user.
+// It is self-owned and deletes itself when the UI reports the user selection or
+// when the net::URLRequest is cancelled.
+class SSLClientAuthHandler
+ : public base::RefCountedThreadSafe<SSLClientAuthHandler,
+ BrowserThread::DeleteOnIOThread> {
+ public:
+ SSLClientAuthHandler(net::URLRequest* request,
+ net::SSLCertRequestInfo* cert_request_info);
+
+ // Asks the user to select a certificate and resumes the URL request with that
+ // certificate.
+ // Should only be called on the IO thread.
+ void SelectCertificate();
+
+ // Invoked when the request associated with this handler is cancelled.
+ // Should only be called on the IO thread.
+ void OnRequestCancelled();
+
+ // Calls DoCertificateSelected on the I/O thread.
+ // Called on the UI thread after the user has made a selection (which may
+ // be long after DoSelectCertificate returns, if the UI is modeless/async.)
+ void CertificateSelected(net::X509Certificate* cert);
+
+ // Like CertificateSelected, but does not send SSL_CLIENT_AUTH_CERT_SELECTED
+ // notification. Used to avoid notification re-spamming when other
+ // certificate selectors act on a notification matching the same host.
+ void CertificateSelectedNoNotify(net::X509Certificate* cert);
+
+ // Returns the SSLCertRequestInfo for this handler.
+ net::SSLCertRequestInfo* cert_request_info() { return cert_request_info_; }
+
+ private:
+ friend class BrowserThread;
+ friend class DeleteTask<SSLClientAuthHandler>;
+
+ virtual ~SSLClientAuthHandler();
+
+ // Notifies that the user has selected a cert.
+ // Called on the IO thread.
+ void DoCertificateSelected(net::X509Certificate* cert);
+
+ // Calls the SSL helper on the UI thread.
+ void ShowClientCertificateRequestDialog(int render_process_host_id,
+ int render_view_host_id);
+
+ // The net::URLRequest that triggered this client auth.
+ net::URLRequest* request_;
+
+ // The certs to choose from.
+ scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLClientAuthHandler);
+};
+
+class SSLClientAuthObserver : public NotificationObserver {
+ public:
+ SSLClientAuthObserver(net::SSLCertRequestInfo* cert_request_info,
+ SSLClientAuthHandler* handler);
+ virtual ~SSLClientAuthObserver();
+
+ // UI should implement this to close the dialog.
+ virtual void OnCertSelectedByNotification() = 0;
+
+ // NotificationObserver implementation:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Begins observing notifications from other SSLClientAuthHandler instances.
+ // If another instance chooses a cert for a matching SSLCertRequestInfo, we
+ // will also use the same cert and OnCertSelectedByNotification will be called
+ // so that the cert selection UI can be closed.
+ void StartObserving();
+
+ // Stops observing notifications. We will no longer act on client auth
+ // notifications.
+ void StopObserving();
+
+ private:
+ scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
+
+ scoped_refptr<SSLClientAuthHandler> handler_;
+
+ NotificationRegistrar notification_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLClientAuthObserver);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_
diff --git a/content/browser/ssl/ssl_client_auth_notification_details.cc b/content/browser/ssl/ssl_client_auth_notification_details.cc
new file mode 100644
index 0000000..237c909
--- /dev/null
+++ b/content/browser/ssl/ssl_client_auth_notification_details.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2011 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 "content/browser/ssl/ssl_client_auth_notification_details.h"
+
+#include "net/base/ssl_cert_request_info.h"
+
+SSLClientAuthNotificationDetails::SSLClientAuthNotificationDetails(
+ const net::SSLCertRequestInfo* cert_request_info,
+ net::X509Certificate* selected_cert)
+ : cert_request_info_(cert_request_info),
+ selected_cert_(selected_cert) {
+}
+
+bool SSLClientAuthNotificationDetails::IsSameHost(
+ const net::SSLCertRequestInfo* cert_request_info) const {
+ // TODO(mattm): should we also compare the DistinguishedNames, or is just
+ // matching host&port sufficient?
+ return cert_request_info_->host_and_port == cert_request_info->host_and_port;
+}
diff --git a/content/browser/ssl/ssl_client_auth_notification_details.h b/content/browser/ssl/ssl_client_auth_notification_details.h
new file mode 100644
index 0000000..eea3d25
--- /dev/null
+++ b/content/browser/ssl/ssl_client_auth_notification_details.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_NOTIFICATION_DETAILS_H_
+#define CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_NOTIFICATION_DETAILS_H_
+
+#include "base/basictypes.h"
+
+namespace net {
+class X509Certificate;
+class SSLCertRequestInfo;
+}
+
+class SSLClientAuthNotificationDetails {
+ public:
+ SSLClientAuthNotificationDetails(
+ const net::SSLCertRequestInfo* cert_request_info,
+ net::X509Certificate* selected_cert);
+
+ bool IsSameHost(const net::SSLCertRequestInfo* cert_request_info) const;
+ net::X509Certificate* selected_cert() const { return selected_cert_; }
+
+ private:
+ // Notifications are synchronous, so we don't need to hold our own references.
+ const net::SSLCertRequestInfo* cert_request_info_;
+ net::X509Certificate* selected_cert_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLClientAuthNotificationDetails);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_NOTIFICATION_DETAILS_H_
diff --git a/content/browser/ssl/ssl_error_handler.cc b/content/browser/ssl/ssl_error_handler.cc
new file mode 100644
index 0000000..17d1fde
--- /dev/null
+++ b/content/browser/ssl/ssl_error_handler.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2010 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 "content/browser/ssl/ssl_error_handler.h"
+
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
+#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
+
+SSLErrorHandler::SSLErrorHandler(ResourceDispatcherHost* rdh,
+ net::URLRequest* request,
+ ResourceType::Type resource_type)
+ : manager_(NULL),
+ request_id_(0, 0),
+ resource_dispatcher_host_(rdh),
+ request_url_(request->url()),
+ resource_type_(resource_type),
+ request_has_been_notified_(false) {
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ ResourceDispatcherHostRequestInfo* info =
+ ResourceDispatcherHost::InfoForRequest(request);
+ request_id_.child_id = info->child_id();
+ request_id_.request_id = info->request_id();
+
+ if (!ResourceDispatcherHost::RenderViewForRequest(request,
+ &render_process_host_id_,
+ &tab_contents_id_))
+ NOTREACHED();
+
+ // This makes sure we don't disappear on the IO thread until we've given an
+ // answer to the net::URLRequest.
+ //
+ // Release in CompleteCancelRequest, CompleteContinueRequest, or
+ // CompleteTakeNoAction.
+ AddRef();
+}
+
+SSLErrorHandler::~SSLErrorHandler() {}
+
+void SSLErrorHandler::OnDispatchFailed() {
+ TakeNoAction();
+}
+
+void SSLErrorHandler::OnDispatched() {
+ TakeNoAction();
+}
+
+SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() {
+ return NULL;
+}
+
+void SSLErrorHandler::Dispatch() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ TabContents* tab_contents = GetTabContents();
+ if (!tab_contents) {
+ // We arrived on the UI thread, but the tab we're looking for is no longer
+ // here.
+ OnDispatchFailed();
+ return;
+ }
+
+ // Hand ourselves off to the SSLManager.
+ manager_ = tab_contents->controller().ssl_manager();
+ OnDispatched();
+}
+
+TabContents* SSLErrorHandler::GetTabContents() {
+ return tab_util::GetTabContentsByID(render_process_host_id_,
+ tab_contents_id_);
+}
+
+void SSLErrorHandler::CancelRequest() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // We need to complete this task on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &SSLErrorHandler::CompleteCancelRequest, net::ERR_ABORTED));
+}
+
+void SSLErrorHandler::DenyRequest() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // We need to complete this task on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &SSLErrorHandler::CompleteCancelRequest,
+ net::ERR_INSECURE_RESPONSE));
+}
+
+void SSLErrorHandler::ContinueRequest() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // We need to complete this task on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SSLErrorHandler::CompleteContinueRequest));
+}
+
+void SSLErrorHandler::TakeNoAction() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // We need to complete this task on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SSLErrorHandler::CompleteTakeNoAction));
+}
+
+void SSLErrorHandler::CompleteCancelRequest(int error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // It is important that we notify the net::URLRequest only once. If we try
+ // to notify the request twice, it may no longer exist and |this| might have
+ // already have been deleted.
+ DCHECK(!request_has_been_notified_);
+ if (request_has_been_notified_)
+ return;
+
+ net::URLRequest* request =
+ resource_dispatcher_host_->GetURLRequest(request_id_);
+ if (request) {
+ // The request can be NULL if it was cancelled by the renderer (as the
+ // result of the user navigating to a new page from the location bar).
+ DVLOG(1) << "CompleteCancelRequest() url: " << request->url().spec();
+ SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler();
+ if (cert_error)
+ request->SimulateSSLError(error, cert_error->ssl_info());
+ else
+ request->SimulateError(error);
+ }
+ request_has_been_notified_ = true;
+
+ // We're done with this object on the IO thread.
+ Release();
+}
+
+void SSLErrorHandler::CompleteContinueRequest() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // It is important that we notify the net::URLRequest only once. If we try to
+ // notify the request twice, it may no longer exist and |this| might have
+ // already have been deleted.
+ DCHECK(!request_has_been_notified_);
+ if (request_has_been_notified_)
+ return;
+
+ net::URLRequest* request =
+ resource_dispatcher_host_->GetURLRequest(request_id_);
+ if (request) {
+ // The request can be NULL if it was cancelled by the renderer (as the
+ // result of the user navigating to a new page from the location bar).
+ DVLOG(1) << "CompleteContinueRequest() url: " << request->url().spec();
+ request->ContinueDespiteLastError();
+ }
+ request_has_been_notified_ = true;
+
+ // We're done with this object on the IO thread.
+ Release();
+}
+
+void SSLErrorHandler::CompleteTakeNoAction() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // It is important that we notify the net::URLRequest only once. If we try to
+ // notify the request twice, it may no longer exist and |this| might have
+ // already have been deleted.
+ DCHECK(!request_has_been_notified_);
+ if (request_has_been_notified_)
+ return;
+
+ request_has_been_notified_ = true;
+
+ // We're done with this object on the IO thread.
+ Release();
+}
diff --git a/content/browser/ssl/ssl_error_handler.h b/content/browser/ssl/ssl_error_handler.h
new file mode 100644
index 0000000..3fe0dee
--- /dev/null
+++ b/content/browser/ssl/ssl_error_handler.h
@@ -0,0 +1,144 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_SSL_SSL_ERROR_HANDLER_H_
+#define CONTENT_BROWSER_SSL_SSL_ERROR_HANDLER_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/renderer_host/global_request_id.h"
+#include "content/browser/ssl/ssl_manager.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/glue/resource_type.h"
+
+class ResourceDispatcherHost;
+class SSLCertErrorHandler;
+class TabContents;
+
+namespace net {
+class URLRequest;
+} // namespace net
+
+// An SSLErrorHandler carries information from the IO thread to the UI thread
+// and is dispatched to the appropriate SSLManager when it arrives on the
+// UI thread. Subclasses should override the OnDispatched/OnDispatchFailed
+// methods to implement the actions that should be taken on the UI thread.
+// These methods can call the different convenience methods ContinueRequest/
+// CancelRequest to perform any required action on the net::URLRequest the
+// ErrorHandler was created with.
+//
+// IMPORTANT NOTE:
+//
+// If you are not doing anything in OnDispatched/OnDispatchFailed, make sure
+// you call TakeNoAction(). This is necessary for ensuring the instance is
+// not leaked.
+//
+class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
+ public:
+ virtual SSLCertErrorHandler* AsSSLCertErrorHandler();
+
+ // Find the appropriate SSLManager for the net::URLRequest and begin handling
+ // this error.
+ //
+ // Call on UI thread.
+ void Dispatch();
+
+ // Available on either thread.
+ const GURL& request_url() const { return request_url_; }
+
+ // Available on either thread.
+ ResourceType::Type resource_type() const { return resource_type_; }
+
+ // Returns the TabContents this object is associated with. Should be
+ // called from the UI thread.
+ TabContents* GetTabContents();
+
+ // Cancels the associated net::URLRequest.
+ // This method can be called from OnDispatchFailed and OnDispatched.
+ void CancelRequest();
+
+ // Continue the net::URLRequest ignoring any previous errors. Note that some
+ // errors cannot be ignored, in which case this will result in the request
+ // being canceled.
+ // This method can be called from OnDispatchFailed and OnDispatched.
+ void ContinueRequest();
+
+ // Cancels the associated net::URLRequest and mark it as denied. The renderer
+ // processes such request in a special manner, optionally replacing them
+ // with alternate content (typically frames content is replaced with a
+ // warning message).
+ // This method can be called from OnDispatchFailed and OnDispatched.
+ void DenyRequest();
+
+ // Does nothing on the net::URLRequest but ensures the current instance ref
+ // count is decremented appropriately. Subclasses that do not want to
+ // take any specific actions in their OnDispatched/OnDispatchFailed should
+ // call this.
+ void TakeNoAction();
+
+ protected:
+ friend class base::RefCountedThreadSafe<SSLErrorHandler>;
+
+ // Construct on the IO thread.
+ SSLErrorHandler(ResourceDispatcherHost* resource_dispatcher_host,
+ net::URLRequest* request,
+ ResourceType::Type resource_type);
+
+ virtual ~SSLErrorHandler();
+
+ // The following 2 methods are the methods subclasses should implement.
+ virtual void OnDispatchFailed();
+
+ // Can use the manager_ member.
+ virtual void OnDispatched();
+
+ // Should only be accessed on the UI thread.
+ SSLManager* manager_; // Our manager.
+
+ // The id of the net::URLRequest associated with this object.
+ // Should only be accessed from the IO thread.
+ GlobalRequestID request_id_;
+
+ // The ResourceDispatcherHost we are associated with.
+ ResourceDispatcherHost* resource_dispatcher_host_;
+
+ private:
+ // Completes the CancelRequest operation on the IO thread.
+ // Call on the IO thread.
+ void CompleteCancelRequest(int error);
+
+ // Completes the ContinueRequest operation on the IO thread.
+ //
+ // Call on the IO thread.
+ void CompleteContinueRequest();
+
+ // Derefs this instance.
+ // Call on the IO thread.
+ void CompleteTakeNoAction();
+
+ // We use these members to find the correct SSLManager when we arrive on
+ // the UI thread.
+ int render_process_host_id_;
+ int tab_contents_id_;
+
+ // The URL that we requested.
+ // This read-only member can be accessed on any thread.
+ const GURL request_url_;
+
+ // What kind of resource is associated with the requested that generated
+ // that error.
+ // This read-only member can be accessed on any thread.
+ const ResourceType::Type resource_type_;
+
+ // A flag to make sure we notify the net::URLRequest exactly once.
+ // Should only be accessed on the IO thread
+ bool request_has_been_notified_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLErrorHandler);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_ERROR_HANDLER_H_
diff --git a/content/browser/ssl/ssl_host_state.cc b/content/browser/ssl/ssl_host_state.cc
new file mode 100644
index 0000000..7b0deef
--- /dev/null
+++ b/content/browser/ssl/ssl_host_state.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 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 "content/browser/ssl/ssl_host_state.h"
+
+#include "base/logging.h"
+
+SSLHostState::SSLHostState() {
+}
+
+SSLHostState::~SSLHostState() {
+}
+
+void SSLHostState::HostRanInsecureContent(const std::string& host, int pid) {
+ DCHECK(CalledOnValidThread());
+ ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid));
+}
+
+bool SSLHostState::DidHostRunInsecureContent(const std::string& host,
+ int pid) const {
+ DCHECK(CalledOnValidThread());
+ return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid));
+}
+
+void SSLHostState::DenyCertForHost(net::X509Certificate* cert,
+ const std::string& host) {
+ DCHECK(CalledOnValidThread());
+
+ cert_policy_for_host_[host].Deny(cert);
+}
+
+void SSLHostState::AllowCertForHost(net::X509Certificate* cert,
+ const std::string& host) {
+ DCHECK(CalledOnValidThread());
+
+ cert_policy_for_host_[host].Allow(cert);
+}
+
+net::CertPolicy::Judgment SSLHostState::QueryPolicy(
+ net::X509Certificate* cert, const std::string& host) {
+ DCHECK(CalledOnValidThread());
+
+ return cert_policy_for_host_[host].Check(cert);
+}
diff --git a/content/browser/ssl/ssl_host_state.h b/content/browser/ssl/ssl_host_state.h
new file mode 100644
index 0000000..943f44e
--- /dev/null
+++ b/content/browser/ssl/ssl_host_state.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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 CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
+#define CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
+#pragma once
+
+#include <string>
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/threading/non_thread_safe.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/x509_certificate.h"
+
+// SSLHostState
+//
+// The SSLHostState encapulates the host-specific state for SSL errors. For
+// example, SSLHostState remembers whether the user has whitelisted a
+// particular broken cert for use with particular host. We separate this state
+// from the SSLManager because this state is shared across many navigation
+// controllers.
+
+class SSLHostState : public base::NonThreadSafe {
+ public:
+ SSLHostState();
+ ~SSLHostState();
+
+ // Records that a host has run insecure content.
+ void HostRanInsecureContent(const std::string& host, int pid);
+
+ // Returns whether the specified host ran insecure content.
+ bool DidHostRunInsecureContent(const std::string& host, int pid) const;
+
+ // Records that |cert| is permitted to be used for |host| in the future.
+ void DenyCertForHost(net::X509Certificate* cert, const std::string& host);
+
+ // Records that |cert| is not permitted to be used for |host| in the future.
+ void AllowCertForHost(net::X509Certificate* cert, const std::string& host);
+
+ // Queries whether |cert| is allowed or denied for |host|.
+ net::CertPolicy::Judgment QueryPolicy(
+ net::X509Certificate* cert, const std::string& host);
+
+ private:
+ // A BrokenHostEntry is a pair of (host, process_id) that indicates the host
+ // contains insecure content in that renderer process.
+ typedef std::pair<std::string, int> BrokenHostEntry;
+
+ // Hosts which have been contaminated with insecure content in the
+ // specified process. Note that insecure content can travel between
+ // same-origin frames in one processs but cannot jump between processes.
+ std::set<BrokenHostEntry> ran_insecure_content_hosts_;
+
+ // Certificate policies for each host.
+ std::map<std::string, net::CertPolicy> cert_policy_for_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLHostState);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
diff --git a/content/browser/ssl/ssl_host_state_unittest.cc b/content/browser/ssl/ssl_host_state_unittest.cc
new file mode 100644
index 0000000..08a589f
--- /dev/null
+++ b/content/browser/ssl/ssl_host_state_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2010 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 "content/browser/ssl/ssl_host_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Certificates for test data. They're obtained with:
+//
+// $ openssl s_client -connect [host]:443 -showcerts
+// $ openssl x509 -inform PEM -outform DER > /tmp/host.der
+// $ xxd -i /tmp/host.der
+
+// Google's cert.
+
+unsigned char google_der[] = {
+ 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x8a, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x10, 0x3c, 0x8d, 0x3a, 0x64, 0xee, 0x18, 0xdd, 0x1b, 0x73,
+ 0x0b, 0xa1, 0x92, 0xee, 0xf8, 0x98, 0x1b, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a,
+ 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c,
+ 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75,
+ 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20,
+ 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47,
+ 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x35,
+ 0x30, 0x32, 0x31, 0x37, 0x30, 0x32, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x30,
+ 0x39, 0x30, 0x35, 0x30, 0x32, 0x31, 0x37, 0x30, 0x32, 0x35, 0x35, 0x5a,
+ 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61,
+ 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30,
+ 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x77, 0x77, 0x77, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x81,
+ 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0x9b, 0x19, 0xed, 0x5d, 0xa5, 0x56, 0xaf, 0x49, 0x66,
+ 0xdb, 0x79, 0xfd, 0xc2, 0x1c, 0x78, 0x4e, 0x4f, 0x11, 0xa5, 0x8a, 0xac,
+ 0xe2, 0x94, 0xee, 0xe3, 0xe2, 0x4b, 0xc0, 0x03, 0x25, 0xa7, 0x99, 0xcc,
+ 0x65, 0xe1, 0xec, 0x94, 0xae, 0xae, 0xf0, 0xa7, 0x99, 0xbc, 0x10, 0xd7,
+ 0xed, 0x87, 0x30, 0x47, 0xcd, 0x50, 0xf9, 0xaf, 0xd3, 0xd3, 0xf4, 0x0b,
+ 0x8d, 0x47, 0x8a, 0x2e, 0xe2, 0xce, 0x53, 0x9b, 0x91, 0x99, 0x7f, 0x1e,
+ 0x5c, 0xf9, 0x1b, 0xd6, 0xe9, 0x93, 0x67, 0xe3, 0x4a, 0xf8, 0xcf, 0xc4,
+ 0x8c, 0x0c, 0x68, 0xd1, 0x97, 0x54, 0x47, 0x0e, 0x0a, 0x24, 0x30, 0xa7,
+ 0x82, 0x94, 0xae, 0xde, 0xae, 0x3f, 0xbf, 0xba, 0x14, 0xc6, 0xf8, 0xb2,
+ 0x90, 0x8e, 0x36, 0xad, 0xe1, 0xd0, 0xbe, 0x16, 0x9a, 0xb3, 0x5e, 0x72,
+ 0x38, 0x49, 0xda, 0x74, 0xa1, 0x3f, 0xff, 0xd2, 0x87, 0x81, 0xed, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, 0x28,
+ 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86,
+ 0xf8, 0x42, 0x04, 0x01, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04,
+ 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68,
+ 0x61, 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61,
+ 0x77, 0x74, 0x65, 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c,
+ 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
+ 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x79, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x5f, 0x53, 0x47,
+ 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0c, 0x06, 0x03,
+ 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x03, 0x81, 0x81, 0x00, 0x31, 0x0a, 0x6c, 0xa2, 0x9e, 0xe9, 0x54,
+ 0x19, 0x16, 0x68, 0x99, 0x91, 0xd6, 0x43, 0xcb, 0x6b, 0xb4, 0xcc, 0x6c,
+ 0xcc, 0xb0, 0xfb, 0xf1, 0xee, 0x81, 0xbf, 0x00, 0x2b, 0x6f, 0x50, 0x12,
+ 0xc6, 0xaf, 0x02, 0x2a, 0x36, 0xc1, 0x28, 0xde, 0xc5, 0x4c, 0x56, 0x20,
+ 0x6d, 0xf5, 0x3d, 0x42, 0xb9, 0x18, 0x81, 0x20, 0xb2, 0xdd, 0x57, 0x5d,
+ 0xeb, 0xbe, 0x32, 0x84, 0x50, 0x45, 0x51, 0x6e, 0xcd, 0xe4, 0x2e, 0x2a,
+ 0x38, 0x88, 0x9f, 0x52, 0xed, 0x28, 0xff, 0xfc, 0x8d, 0x57, 0xb5, 0xad,
+ 0x64, 0xae, 0x4d, 0x0e, 0x0e, 0xd9, 0x3d, 0xac, 0xb8, 0xfe, 0x66, 0x4c,
+ 0x15, 0x8f, 0x44, 0x52, 0xfa, 0x7c, 0x3c, 0x04, 0xed, 0x7f, 0x37, 0x61,
+ 0x04, 0xfe, 0xd5, 0xe9, 0xb9, 0xb0, 0x9e, 0xfe, 0xa5, 0x11, 0x69, 0xc9,
+ 0x63, 0xd6, 0x46, 0x81, 0x6f, 0x00, 0xd8, 0x72, 0x2f, 0x82, 0x37, 0x44,
+ 0xc1
+};
+
+} // namespace
+
+class SSLHostStateTest : public testing::Test {
+};
+
+TEST_F(SSLHostStateTest, DidHostRunInsecureContent) {
+ SSLHostState state;
+
+ EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 42));
+ EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
+ EXPECT_FALSE(state.DidHostRunInsecureContent("example.com", 42));
+
+ state.HostRanInsecureContent("www.google.com", 42);
+
+ EXPECT_TRUE(state.DidHostRunInsecureContent("www.google.com", 42));
+ EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
+ EXPECT_FALSE(state.DidHostRunInsecureContent("example.com", 42));
+
+ state.HostRanInsecureContent("example.com", 42);
+
+ EXPECT_TRUE(state.DidHostRunInsecureContent("www.google.com", 42));
+ EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
+ EXPECT_TRUE(state.DidHostRunInsecureContent("example.com", 42));
+}
+
+TEST_F(SSLHostStateTest, QueryPolicy) {
+ scoped_refptr<net::X509Certificate> google_cert(
+ net::X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+
+ SSLHostState state;
+
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "www.google.com"),
+ net::CertPolicy::UNKNOWN);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "google.com"),
+ net::CertPolicy::UNKNOWN);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "example.com"),
+ net::CertPolicy::UNKNOWN);
+
+ state.AllowCertForHost(google_cert.get(), "www.google.com");
+
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "www.google.com"),
+ net::CertPolicy::ALLOWED);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "google.com"),
+ net::CertPolicy::UNKNOWN);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "example.com"),
+ net::CertPolicy::UNKNOWN);
+
+ state.AllowCertForHost(google_cert.get(), "example.com");
+
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "www.google.com"),
+ net::CertPolicy::ALLOWED);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "google.com"),
+ net::CertPolicy::UNKNOWN);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "example.com"),
+ net::CertPolicy::ALLOWED);
+
+ state.DenyCertForHost(google_cert.get(), "example.com");
+
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "www.google.com"),
+ net::CertPolicy::ALLOWED);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "google.com"),
+ net::CertPolicy::UNKNOWN);
+ EXPECT_EQ(state.QueryPolicy(google_cert.get(), "example.com"),
+ net::CertPolicy::DENIED);
+}
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc
new file mode 100644
index 0000000..4efe034
--- /dev/null
+++ b/content/browser/ssl/ssl_manager.cc
@@ -0,0 +1,247 @@
+// Copyright (c) 2011 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 "content/browser/ssl/ssl_manager.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/load_from_memory_cache_details.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
+#include "content/browser/renderer_host/resource_request_details.h"
+#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/ssl/ssl_policy.h"
+#include "content/browser/ssl/ssl_request_info.h"
+#include "content/browser/tab_contents/navigation_details.h"
+#include "content/browser/tab_contents/navigation_entry.h"
+#include "content/browser/tab_contents/provisional_load_details.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/common/notification_service.h"
+#include "net/base/cert_status_flags.h"
+
+// static
+void SSLManager::OnSSLCertificateError(ResourceDispatcherHost* rdh,
+ net::URLRequest* request,
+ int cert_error,
+ net::X509Certificate* cert) {
+ DVLOG(1) << "OnSSLCertificateError() cert_error: " << cert_error
+ << " url: " << request->url().spec();
+
+ ResourceDispatcherHostRequestInfo* info =
+ ResourceDispatcherHost::InfoForRequest(request);
+ DCHECK(info);
+
+ // A certificate error occurred. Construct a SSLCertErrorHandler object and
+ // hand it over to the UI thread for processing.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(new SSLCertErrorHandler(rdh,
+ request,
+ info->resource_type(),
+ cert_error,
+ cert),
+ &SSLCertErrorHandler::Dispatch));
+}
+
+// static
+void SSLManager::NotifySSLInternalStateChanged() {
+ NotificationService::current()->Notify(
+ NotificationType::SSL_INTERNAL_STATE_CHANGED,
+ NotificationService::AllSources(),
+ NotificationService::NoDetails());
+}
+
+// static
+std::string SSLManager::SerializeSecurityInfo(int cert_id,
+ int cert_status,
+ int security_bits,
+ int ssl_connection_status) {
+ Pickle pickle;
+ pickle.WriteInt(cert_id);
+ pickle.WriteInt(cert_status);
+ pickle.WriteInt(security_bits);
+ pickle.WriteInt(ssl_connection_status);
+ return std::string(static_cast<const char*>(pickle.data()), pickle.size());
+}
+
+// static
+bool SSLManager::DeserializeSecurityInfo(const std::string& state,
+ int* cert_id,
+ int* cert_status,
+ int* security_bits,
+ int* ssl_connection_status) {
+ DCHECK(cert_id && cert_status && security_bits && ssl_connection_status);
+ if (state.empty()) {
+ // No SSL used.
+ *cert_id = 0;
+ // The following are not applicable and are set to the default values.
+ *cert_status = 0;
+ *security_bits = -1;
+ *ssl_connection_status = 0;
+ return false;
+ }
+
+ Pickle pickle(state.data(), static_cast<int>(state.size()));
+ void * iter = NULL;
+ return pickle.ReadInt(&iter, cert_id) &&
+ pickle.ReadInt(&iter, cert_status) &&
+ pickle.ReadInt(&iter, security_bits) &&
+ pickle.ReadInt(&iter, ssl_connection_status);
+}
+
+SSLManager::SSLManager(NavigationController* controller)
+ : backend_(controller),
+ policy_(new SSLPolicy(&backend_)),
+ controller_(controller) {
+ DCHECK(controller_);
+
+ // Subscribe to various notifications.
+ registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
+ Source<NavigationController>(controller_));
+ registrar_.Add(this, NotificationType::RESOURCE_RESPONSE_STARTED,
+ Source<RenderViewHostDelegate>(controller_->tab_contents()));
+ registrar_.Add(this, NotificationType::RESOURCE_RECEIVED_REDIRECT,
+ Source<RenderViewHostDelegate>(controller_->tab_contents()));
+ registrar_.Add(this, NotificationType::LOAD_FROM_MEMORY_CACHE,
+ Source<NavigationController>(controller_));
+ registrar_.Add(this, NotificationType::SSL_INTERNAL_STATE_CHANGED,
+ NotificationService::AllSources());
+}
+
+SSLManager::~SSLManager() {
+}
+
+void SSLManager::DidCommitProvisionalLoad(
+ const NotificationDetails& in_details) {
+ content::LoadCommittedDetails* details =
+ Details<content::LoadCommittedDetails>(in_details).ptr();
+
+ NavigationEntry* entry = controller_->GetActiveEntry();
+
+ if (details->is_main_frame) {
+ if (entry) {
+ // Decode the security details.
+ int ssl_cert_id, ssl_cert_status, ssl_security_bits,
+ ssl_connection_status;
+ DeserializeSecurityInfo(details->serialized_security_info,
+ &ssl_cert_id,
+ &ssl_cert_status,
+ &ssl_security_bits,
+ &ssl_connection_status);
+
+ // We may not have an entry if this is a navigation to an initial blank
+ // page. Reset the SSL information and add the new data we have.
+ entry->ssl() = NavigationEntry::SSLStatus();
+ entry->ssl().set_cert_id(ssl_cert_id);
+ entry->ssl().set_cert_status(ssl_cert_status);
+ entry->ssl().set_security_bits(ssl_security_bits);
+ entry->ssl().set_connection_status(ssl_connection_status);
+ }
+ }
+
+ UpdateEntry(entry);
+}
+
+void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
+ policy()->DidRunInsecureContent(controller_->GetActiveEntry(),
+ security_origin);
+}
+
+bool SSLManager::ProcessedSSLErrorFromRequest() const {
+ NavigationEntry* entry = controller_->GetActiveEntry();
+ if (!entry) {
+ NOTREACHED();
+ return false;
+ }
+
+ return net::IsCertStatusError(entry->ssl().cert_status());
+}
+
+void SSLManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ // Dispatch by type.
+ switch (type.value) {
+ case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR:
+ // Do nothing.
+ break;
+ case NotificationType::RESOURCE_RESPONSE_STARTED:
+ DidStartResourceResponse(Details<ResourceRequestDetails>(details).ptr());
+ break;
+ case NotificationType::RESOURCE_RECEIVED_REDIRECT:
+ DidReceiveResourceRedirect(
+ Details<ResourceRedirectDetails>(details).ptr());
+ break;
+ case NotificationType::LOAD_FROM_MEMORY_CACHE:
+ DidLoadFromMemoryCache(
+ Details<LoadFromMemoryCacheDetails>(details).ptr());
+ break;
+ case NotificationType::SSL_INTERNAL_STATE_CHANGED:
+ DidChangeSSLInternalState();
+ break;
+ default:
+ NOTREACHED() << "The SSLManager received an unexpected notification.";
+ }
+}
+
+void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) {
+ // Simulate loading this resource through the usual path.
+ // Note that we specify SUB_RESOURCE as the resource type as WebCore only
+ // caches sub-resources.
+ // This resource must have been loaded with no filtering because filtered
+ // resouces aren't cachable.
+ scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
+ details->url(),
+ ResourceType::SUB_RESOURCE,
+ details->pid(),
+ details->ssl_cert_id(),
+ details->ssl_cert_status()));
+
+ // Simulate loading this resource through the usual path.
+ policy()->OnRequestStarted(info.get());
+}
+
+void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) {
+ scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
+ details->url(),
+ details->resource_type(),
+ details->origin_child_id(),
+ details->ssl_cert_id(),
+ details->ssl_cert_status()));
+
+ // Notify our policy that we started a resource request. Ideally, the
+ // policy should have the ability to cancel the request, but we can't do
+ // that yet.
+ policy()->OnRequestStarted(info.get());
+}
+
+void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) {
+ // TODO(abarth): Make sure our redirect behavior is correct. If we ever see a
+ // non-HTTPS resource in the redirect chain, we want to trigger
+ // insecure content, even if the redirect chain goes back to
+ // HTTPS. This is because the network attacker can redirect the
+ // HTTP request to https://attacker.com/payload.js.
+}
+
+void SSLManager::DidChangeSSLInternalState() {
+ UpdateEntry(controller_->GetActiveEntry());
+}
+
+void SSLManager::UpdateEntry(NavigationEntry* entry) {
+ // We don't always have a navigation entry to update, for example in the
+ // case of the Web Inspector.
+ if (!entry)
+ return;
+
+ NavigationEntry::SSLStatus original_ssl_status = entry->ssl(); // Copy!
+
+ policy()->UpdateEntry(entry, controller_->tab_contents());
+
+ if (!entry->ssl().Equals(original_ssl_status)) {
+ NotificationService::current()->Notify(
+ NotificationType::SSL_VISIBLE_STATE_CHANGED,
+ Source<NavigationController>(controller_),
+ NotificationService::NoDetails());
+ }
+}
diff --git a/content/browser/ssl/ssl_manager.h b/content/browser/ssl/ssl_manager.h
new file mode 100644
index 0000000..8ceeddf
--- /dev/null
+++ b/content/browser/ssl/ssl_manager.h
@@ -0,0 +1,128 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_SSL_SSL_MANAGER_H_
+#define CONTENT_BROWSER_SSL_SSL_MANAGER_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/ssl/ssl_policy_backend.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+
+class LoadFromMemoryCacheDetails;
+class NavigationController;
+class NavigationEntry;
+class ProvisionalLoadDetails;
+class ResourceDispatcherHost;
+class ResourceRedirectDetails;
+class ResourceRequestDetails;
+class SSLPolicy;
+
+namespace net {
+class URLRequest;
+} // namespace net
+
+// The SSLManager SSLManager controls the SSL UI elements in a TabContents. It
+// listens for various events that influence when these elements should or
+// should not be displayed and adjusts them accordingly.
+//
+// There is one SSLManager per tab.
+// The security state (secure/insecure) is stored in the navigation entry.
+// Along with it are stored any SSL error code and the associated cert.
+
+class SSLManager : public NotificationObserver {
+ public:
+ // Entry point for SSLCertificateErrors. This function begins the process
+ // of resolving a certificate error during an SSL connection. SSLManager
+ // will adjust the security UI and either call |Cancel| or
+ // |ContinueDespiteLastError| on the net::URLRequest.
+ //
+ // Called on the IO thread.
+ static void OnSSLCertificateError(ResourceDispatcherHost* resource_dispatcher,
+ net::URLRequest* request,
+ int cert_error,
+ net::X509Certificate* cert);
+
+ // Called when SSL state for a host or tab changes. Broadcasts the
+ // SSL_INTERNAL_STATE_CHANGED notification.
+ static void NotifySSLInternalStateChanged();
+
+ // Convenience methods for serializing/deserializing the security info.
+ static std::string SerializeSecurityInfo(int cert_id,
+ int cert_status,
+ int security_bits,
+ int connection_status);
+ static bool DeserializeSecurityInfo(const std::string& state,
+ int* cert_id,
+ int* cert_status,
+ int* security_bits,
+ int* connection_status);
+
+ // Construct an SSLManager for the specified tab.
+ // If |delegate| is NULL, SSLPolicy::GetDefaultPolicy() is used.
+ explicit SSLManager(NavigationController* controller);
+ virtual ~SSLManager();
+
+ SSLPolicy* policy() { return policy_.get(); }
+ SSLPolicyBackend* backend() { return &backend_; }
+
+ // The navigation controller associated with this SSLManager. The
+ // NavigationController is guaranteed to outlive the SSLManager.
+ NavigationController* controller() { return controller_; }
+
+ // This entry point is called directly (instead of via the notification
+ // service) because we need more precise control of the order in which folks
+ // are notified of this event.
+ void DidCommitProvisionalLoad(const NotificationDetails& details);
+
+ // Insecure content entry point.
+ void DidRunInsecureContent(const std::string& security_origin);
+
+ // Called to determine if there were any processed SSL errors from request.
+ bool ProcessedSSLErrorFromRequest() const;
+
+ // Entry point for navigation. This function begins the process of updating
+ // the security UI when the main frame navigates to a new URL.
+ //
+ // Called on the UI thread.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ // Entry points for notifications to which we subscribe. Note that
+ // DidCommitProvisionalLoad uses the abstract NotificationDetails type since
+ // the type we need is in NavigationController which would create a circular
+ // header file dependency.
+ void DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details);
+ void DidStartResourceResponse(ResourceRequestDetails* details);
+ void DidReceiveResourceRedirect(ResourceRedirectDetails* details);
+ void DidChangeSSLInternalState();
+
+ // Update the NavigationEntry with our current state.
+ void UpdateEntry(NavigationEntry* entry);
+
+ // The backend for the SSLPolicy to actuate its decisions.
+ SSLPolicyBackend backend_;
+
+ // The SSLPolicy instance for this manager.
+ scoped_ptr<SSLPolicy> policy_;
+
+ // The NavigationController that owns this SSLManager. We are responsible
+ // for the security UI of this tab.
+ NavigationController* controller_;
+
+ // Handles registering notifications with the NotificationService.
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLManager);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_MANAGER_H_
diff --git a/content/browser/ssl/ssl_policy.cc b/content/browser/ssl/ssl_policy.cc
new file mode 100644
index 0000000..9be48a3
--- /dev/null
+++ b/content/browser/ssl/ssl_policy.cc
@@ -0,0 +1,223 @@
+// Copyright (c) 2011 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 "content/browser/ssl/ssl_policy.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/memory/singleton.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "chrome/browser/ssl/ssl_error_info.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/site_instance.h"
+#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/ssl/ssl_request_info.h"
+#include "content/browser/tab_contents/navigation_entry.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/common/url_constants.h"
+#include "net/base/cert_status_flags.h"
+#include "net/base/ssl_info.h"
+#include "webkit/glue/resource_type.h"
+
+namespace {
+
+static const char kDot = '.';
+
+static bool IsIntranetHost(const std::string& host) {
+ const size_t dot = host.find(kDot);
+ return dot == std::string::npos || dot == host.length() - 1;
+}
+
+} // namespace
+
+SSLPolicy::SSLPolicy(SSLPolicyBackend* backend)
+ : backend_(backend) {
+ DCHECK(backend_);
+}
+
+void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
+ // First we check if we know the policy for this error.
+ net::CertPolicy::Judgment judgment =
+ backend_->QueryPolicy(handler->ssl_info().cert,
+ handler->request_url().host());
+
+ if (judgment == net::CertPolicy::ALLOWED) {
+ handler->ContinueRequest();
+ return;
+ }
+
+ // The judgment is either DENIED or UNKNOWN.
+ // For now we handle the DENIED as the UNKNOWN, which means a blocking
+ // page is shown to the user every time he comes back to the page.
+
+ switch (handler->cert_error()) {
+ case net::ERR_CERT_COMMON_NAME_INVALID:
+ case net::ERR_CERT_DATE_INVALID:
+ case net::ERR_CERT_AUTHORITY_INVALID:
+ case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
+ OnCertErrorInternal(handler, SSLBlockingPage::ERROR_OVERRIDABLE);
+ break;
+ case net::ERR_CERT_NO_REVOCATION_MECHANISM:
+ // Ignore this error.
+ handler->ContinueRequest();
+ break;
+ case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
+ // We ignore this error but will show a warning status in the location
+ // bar.
+ handler->ContinueRequest();
+ break;
+ case net::ERR_CERT_CONTAINS_ERRORS:
+ case net::ERR_CERT_REVOKED:
+ case net::ERR_CERT_INVALID:
+ case net::ERR_CERT_NOT_IN_DNS:
+ OnCertErrorInternal(handler, SSLBlockingPage::ERROR_FATAL);
+ break;
+ default:
+ NOTREACHED();
+ handler->CancelRequest();
+ break;
+ }
+}
+
+void SSLPolicy::DidRunInsecureContent(NavigationEntry* entry,
+ const std::string& security_origin) {
+ if (!entry)
+ return;
+
+ SiteInstance* site_instance = entry->site_instance();
+ if (!site_instance)
+ return;
+
+ backend_->HostRanInsecureContent(GURL(security_origin).host(),
+ site_instance->GetProcess()->id());
+}
+
+void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) {
+ // TODO(abarth): This mechanism is wrong. What we should be doing is sending
+ // this information back through WebKit and out some FrameLoaderClient
+ // methods.
+
+ if (net::IsCertStatusError(info->ssl_cert_status()))
+ backend_->HostRanInsecureContent(info->url().host(), info->child_id());
+}
+
+void SSLPolicy::UpdateEntry(NavigationEntry* entry, TabContents* tab_contents) {
+ DCHECK(entry);
+
+ InitializeEntryIfNeeded(entry);
+
+ if (!entry->url().SchemeIsSecure())
+ return;
+
+ // An HTTPS response may not have a certificate for some reason. When that
+ // happens, use the unauthenticated (HTTP) rather than the authentication
+ // broken security style so that we can detect this error condition.
+ if (!entry->ssl().cert_id()) {
+ entry->ssl().set_security_style(SECURITY_STYLE_UNAUTHENTICATED);
+ return;
+ }
+
+ if (!(entry->ssl().cert_status() & net::CERT_STATUS_COMMON_NAME_INVALID)) {
+ // CAs issue certificates for intranet hosts to everyone. Therefore, we
+ // mark intranet hosts as being non-unique.
+ if (IsIntranetHost(entry->url().host())) {
+ entry->ssl().set_cert_status(entry->ssl().cert_status() |
+ net::CERT_STATUS_NON_UNIQUE_NAME);
+ }
+ }
+
+ // If CERT_STATUS_UNABLE_TO_CHECK_REVOCATION is the only certificate error,
+ // don't lower the security style to SECURITY_STYLE_AUTHENTICATION_BROKEN.
+ int cert_errors = entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS;
+ if (cert_errors) {
+ if (cert_errors != net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION)
+ entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
+ return;
+ }
+
+ SiteInstance* site_instance = entry->site_instance();
+ // Note that |site_instance| can be NULL here because NavigationEntries don't
+ // necessarily have site instances. Without a process, the entry can't
+ // possibly have insecure content. See bug http://crbug.com/12423.
+ if (site_instance &&
+ backend_->DidHostRunInsecureContent(entry->url().host(),
+ site_instance->GetProcess()->id())) {
+ entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
+ entry->ssl().set_ran_insecure_content();
+ return;
+ }
+
+ if (tab_contents->displayed_insecure_content())
+ entry->ssl().set_displayed_insecure_content();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SSLBlockingPage::Delegate methods
+
+SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLCertErrorHandler* handler) {
+ return SSLErrorInfo::CreateError(
+ SSLErrorInfo::NetErrorToErrorType(handler->cert_error()),
+ handler->ssl_info().cert, handler->request_url());
+}
+
+void SSLPolicy::OnDenyCertificate(SSLCertErrorHandler* handler) {
+ // Default behavior for rejecting a certificate.
+ //
+ // While DenyCertForHost() executes synchronously on this thread,
+ // CancelRequest() gets posted to a different thread. Calling
+ // DenyCertForHost() first ensures deterministic ordering.
+ backend_->DenyCertForHost(handler->ssl_info().cert,
+ handler->request_url().host());
+ handler->CancelRequest();
+}
+
+void SSLPolicy::OnAllowCertificate(SSLCertErrorHandler* handler) {
+ // Default behavior for accepting a certificate.
+ // Note that we should not call SetMaxSecurityStyle here, because the active
+ // NavigationEntry has just been deleted (in HideInterstitialPage) and the
+ // new NavigationEntry will not be set until DidNavigate. This is ok,
+ // because the new NavigationEntry will have its max security style set
+ // within DidNavigate.
+ //
+ // While AllowCertForHost() executes synchronously on this thread,
+ // ContinueRequest() gets posted to a different thread. Calling
+ // AllowCertForHost() first ensures deterministic ordering.
+ backend_->AllowCertForHost(handler->ssl_info().cert,
+ handler->request_url().host());
+ handler->ContinueRequest();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Certificate Error Routines
+
+void SSLPolicy::OnCertErrorInternal(SSLCertErrorHandler* handler,
+ SSLBlockingPage::ErrorLevel error_level) {
+ if (handler->resource_type() != ResourceType::MAIN_FRAME) {
+ // A sub-resource has a certificate error. The user doesn't really
+ // have a context for making the right decision, so block the
+ // request hard, without an info bar to allow showing the insecure
+ // content.
+ handler->DenyRequest();
+ return;
+ }
+ SSLBlockingPage* blocking_page = new SSLBlockingPage(handler, this,
+ error_level);
+ blocking_page->Show();
+}
+
+void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) {
+ if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN)
+ return;
+
+ entry->ssl().set_security_style(entry->url().SchemeIsSecure() ?
+ SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED);
+}
+
+void SSLPolicy::OriginRanInsecureContent(const std::string& origin, int pid) {
+ GURL parsed_origin(origin);
+ if (parsed_origin.SchemeIsSecure())
+ backend_->HostRanInsecureContent(parsed_origin.host(), pid);
+}
diff --git a/content/browser/ssl/ssl_policy.h b/content/browser/ssl/ssl_policy.h
new file mode 100644
index 0000000..b1bf5a0
--- /dev/null
+++ b/content/browser/ssl/ssl_policy.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2010 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 CONTENT_BROWSER_SSL_SSL_POLICY_H_
+#define CONTENT_BROWSER_SSL_SSL_POLICY_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/browser/ssl/ssl_blocking_page.h"
+#include "webkit/glue/resource_type.h"
+
+class NavigationEntry;
+class SSLCertErrorHandler;
+class SSLPolicyBackend;
+class SSLRequestInfo;
+
+// SSLPolicy
+//
+// This class is responsible for making the security decisions that concern the
+// SSL trust indicators. It relies on the SSLPolicyBackend to actually enact
+// the decisions it reaches.
+//
+class SSLPolicy : public SSLBlockingPage::Delegate {
+ public:
+ explicit SSLPolicy(SSLPolicyBackend* backend);
+
+ // An error occurred with the certificate in an SSL connection.
+ void OnCertError(SSLCertErrorHandler* handler);
+
+ void DidRunInsecureContent(NavigationEntry* entry,
+ const std::string& security_origin);
+
+ // We have started a resource request with the given info.
+ void OnRequestStarted(SSLRequestInfo* info);
+
+ // Update the SSL information in |entry| to match the current state.
+ // |tab_contents| is the TabContents associated with this entry.
+ void UpdateEntry(NavigationEntry* entry, TabContents* tab_contents);
+
+ SSLPolicyBackend* backend() const { return backend_; }
+
+ // SSLBlockingPage::Delegate methods.
+ virtual SSLErrorInfo GetSSLErrorInfo(SSLCertErrorHandler* handler);
+ virtual void OnDenyCertificate(SSLCertErrorHandler* handler);
+ virtual void OnAllowCertificate(SSLCertErrorHandler* handler);
+
+ private:
+ // Helper method for derived classes handling certificate errors.
+ // If the error can be overridden by the user, show a blocking page that
+ // lets the user continue or cancel the request.
+ // For fatal certificate errors, show a blocking page that only lets the
+ // user cancel the request.
+ void OnCertErrorInternal(SSLCertErrorHandler* handler,
+ SSLBlockingPage::ErrorLevel error_level);
+
+ // If the security style of |entry| has not been initialized, then initialize
+ // it with the default style for its URL.
+ void InitializeEntryIfNeeded(NavigationEntry* entry);
+
+ // Mark |origin| as having run insecure content in the process with ID |pid|.
+ void OriginRanInsecureContent(const std::string& origin, int pid);
+
+ // The backend we use to enact our decisions.
+ SSLPolicyBackend* backend_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPolicy);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_POLICY_H_
diff --git a/content/browser/ssl/ssl_policy_backend.cc b/content/browser/ssl/ssl_policy_backend.cc
new file mode 100644
index 0000000..82c4653
--- /dev/null
+++ b/content/browser/ssl/ssl_policy_backend.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 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 "content/browser/ssl/ssl_policy_backend.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "content/browser/ssl/ssl_host_state.h"
+#include "content/browser/tab_contents/navigation_controller.h"
+
+SSLPolicyBackend::SSLPolicyBackend(NavigationController* controller)
+ : ssl_host_state_(controller->profile()->GetSSLHostState()) {
+ DCHECK(controller);
+}
+
+void SSLPolicyBackend::HostRanInsecureContent(const std::string& host, int id) {
+ ssl_host_state_->HostRanInsecureContent(host, id);
+ SSLManager::NotifySSLInternalStateChanged();
+}
+
+bool SSLPolicyBackend::DidHostRunInsecureContent(const std::string& host,
+ int pid) const {
+ return ssl_host_state_->DidHostRunInsecureContent(host, pid);
+}
+
+void SSLPolicyBackend::DenyCertForHost(net::X509Certificate* cert,
+ const std::string& host) {
+ ssl_host_state_->DenyCertForHost(cert, host);
+}
+
+void SSLPolicyBackend::AllowCertForHost(net::X509Certificate* cert,
+ const std::string& host) {
+ ssl_host_state_->AllowCertForHost(cert, host);
+}
+
+net::CertPolicy::Judgment SSLPolicyBackend::QueryPolicy(
+ net::X509Certificate* cert, const std::string& host) {
+ return ssl_host_state_->QueryPolicy(cert, host);
+}
diff --git a/content/browser/ssl/ssl_policy_backend.h b/content/browser/ssl/ssl_policy_backend.h
new file mode 100644
index 0000000..97fa38f
--- /dev/null
+++ b/content/browser/ssl/ssl_policy_backend.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2010 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 CONTENT_BROWSER_SSL_SSL_POLICY_BACKEND_H_
+#define CONTENT_BROWSER_SSL_SSL_POLICY_BACKEND_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "net/base/x509_certificate.h"
+
+class NavigationController;
+class SSLHostState;
+
+class SSLPolicyBackend {
+ public:
+ explicit SSLPolicyBackend(NavigationController* controller);
+
+ // Records that a host has run insecure content.
+ void HostRanInsecureContent(const std::string& host, int pid);
+
+ // Returns whether the specified host ran insecure content.
+ bool DidHostRunInsecureContent(const std::string& host, int pid) const;
+
+ // Records that |cert| is permitted to be used for |host| in the future.
+ void DenyCertForHost(net::X509Certificate* cert, const std::string& host);
+
+ // Records that |cert| is not permitted to be used for |host| in the future.
+ void AllowCertForHost(net::X509Certificate* cert, const std::string& host);
+
+ // Queries whether |cert| is allowed or denied for |host|.
+ net::CertPolicy::Judgment QueryPolicy(
+ net::X509Certificate* cert, const std::string& host);
+
+ private:
+ // SSL state specific for each host.
+ SSLHostState* ssl_host_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPolicyBackend);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_POLICY_BACKEND_H_
diff --git a/content/browser/ssl/ssl_request_info.cc b/content/browser/ssl/ssl_request_info.cc
new file mode 100644
index 0000000..19d4e4d
--- /dev/null
+++ b/content/browser/ssl/ssl_request_info.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2010 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 "content/browser/ssl/ssl_request_info.h"
+
+SSLRequestInfo::SSLRequestInfo(const GURL& url,
+ ResourceType::Type resource_type,
+ int child_id,
+ int ssl_cert_id,
+ int ssl_cert_status)
+ : url_(url),
+ resource_type_(resource_type),
+ child_id_(child_id),
+ ssl_cert_id_(ssl_cert_id),
+ ssl_cert_status_(ssl_cert_status) {
+}
+
+SSLRequestInfo::~SSLRequestInfo() {}
diff --git a/content/browser/ssl/ssl_request_info.h b/content/browser/ssl/ssl_request_info.h
new file mode 100644
index 0000000..1ab433d
--- /dev/null
+++ b/content/browser/ssl/ssl_request_info.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_SSL_SSL_REQUEST_INFO_H_
+#define CONTENT_BROWSER_SSL_SSL_REQUEST_INFO_H_
+#pragma once
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/glue/resource_type.h"
+
+// SSLRequestInfo wraps up the information SSLPolicy needs about a request in
+// order to update our security IU. SSLRequestInfo is RefCounted in case we
+// need to deal with the request asynchronously.
+class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> {
+ public:
+ SSLRequestInfo(const GURL& url,
+ ResourceType::Type resource_type,
+ int child_id,
+ int ssl_cert_id,
+ int ssl_cert_status);
+
+ const GURL& url() const { return url_; }
+ ResourceType::Type resource_type() const { return resource_type_; }
+ int child_id() const { return child_id_; }
+ int ssl_cert_id() const { return ssl_cert_id_; }
+ int ssl_cert_status() const { return ssl_cert_status_; }
+
+ private:
+ friend class base::RefCounted<SSLRequestInfo>;
+
+ virtual ~SSLRequestInfo();
+
+ GURL url_;
+ ResourceType::Type resource_type_;
+ int child_id_;
+ int ssl_cert_id_;
+ int ssl_cert_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLRequestInfo);
+};
+
+#endif // CONTENT_BROWSER_SSL_SSL_REQUEST_INFO_H_
diff --git a/content/browser/tab_contents/navigation_controller.h b/content/browser/tab_contents/navigation_controller.h
index 5994ce2..025c2b0 100644
--- a/content/browser/tab_contents/navigation_controller.h
+++ b/content/browser/tab_contents/navigation_controller.h
@@ -15,7 +15,7 @@
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "chrome/browser/sessions/session_id.h"
-#include "chrome/browser/ssl/ssl_manager.h"
+#include "content/browser/ssl/ssl_manager.h"
#include "content/common/navigation_types.h"
#include "content/common/page_transition_types.h"
diff --git a/content/browser/tab_contents/provisional_load_details.cc b/content/browser/tab_contents/provisional_load_details.cc
index 319f2b0..0d84aa3 100644
--- a/content/browser/tab_contents/provisional_load_details.cc
+++ b/content/browser/tab_contents/provisional_load_details.cc
@@ -5,7 +5,7 @@
#include "content/browser/tab_contents/provisional_load_details.h"
-#include "chrome/browser/ssl/ssl_manager.h"
+#include "content/browser/ssl/ssl_manager.h"
ProvisionalLoadDetails::ProvisionalLoadDetails(bool is_main_frame,
bool is_in_page_navigation,
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index f27de01..77d4cce 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -315,6 +315,24 @@
'browser/speech/speech_recognition_request.h',
'browser/speech/speech_recognizer.cc',
'browser/speech/speech_recognizer.h',
+ 'browser/ssl/ssl_cert_error_handler.cc',
+ 'browser/ssl/ssl_cert_error_handler.h',
+ 'browser/ssl/ssl_client_auth_handler.cc',
+ 'browser/ssl/ssl_client_auth_handler.h',
+ 'browser/ssl/ssl_client_auth_notification_details.cc',
+ 'browser/ssl/ssl_client_auth_notification_details.h',
+ 'browser/ssl/ssl_error_handler.cc',
+ 'browser/ssl/ssl_error_handler.h',
+ 'browser/ssl/ssl_host_state.cc',
+ 'browser/ssl/ssl_host_state.h',
+ 'browser/ssl/ssl_manager.cc',
+ 'browser/ssl/ssl_manager.h',
+ 'browser/ssl/ssl_policy.cc',
+ 'browser/ssl/ssl_policy.h',
+ 'browser/ssl/ssl_policy_backend.cc',
+ 'browser/ssl/ssl_policy_backend.h',
+ 'browser/ssl/ssl_request_info.cc',
+ 'browser/ssl/ssl_request_info.h',
'browser/tab_contents/constrained_window.h',
'browser/tab_contents/interstitial_page.cc',
'browser/tab_contents/interstitial_page.h',