Browse Source

provide security style for devtools security panel

deepak1556 9 years ago
parent
commit
54545a8a6e

+ 3 - 0
atom/browser/api/atom_api_web_contents.cc

@@ -13,6 +13,7 @@
 #include "atom/browser/atom_browser_client.h"
 #include "atom/browser/atom_browser_context.h"
 #include "atom/browser/atom_browser_main_parts.h"
+#include "atom/browser/atom_security_state_model_client.h"
 #include "atom/browser/native_window.h"
 #include "atom/browser/net/atom_network_delegate.h"
 #include "atom/browser/web_contents_permission_helper.h"
@@ -277,6 +278,8 @@ WebContents::WebContents(v8::Isolate* isolate,
 
   // Intialize permission helper.
   WebContentsPermissionHelper::CreateForWebContents(web_contents);
+  // Intialize security state client.
+  AtomSecurityStateModelClient::CreateForWebContents(web_contents);
 
   web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
 

+ 105 - 0
atom/browser/atom_security_state_model_client.cc

@@ -0,0 +1,105 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/atom_security_state_model_client.h"
+
+#include "content/public/browser/cert_store.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/origin_util.h"
+#include "content/public/common/ssl_status.h"
+#include "net/cert/x509_certificate.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::AtomSecurityStateModelClient);
+
+using security_state::SecurityStateModel;
+
+namespace atom {
+
+namespace {
+
+SecurityStateModel::SecurityLevel GetSecurityLevelForSecurityStyle(
+    content::SecurityStyle style) {
+  switch (style) {
+    case content::SECURITY_STYLE_UNKNOWN:
+      return SecurityStateModel::NONE;
+    case content::SECURITY_STYLE_UNAUTHENTICATED:
+      return SecurityStateModel::NONE;
+    case content::SECURITY_STYLE_AUTHENTICATION_BROKEN:
+      return SecurityStateModel::SECURITY_ERROR;
+    case content::SECURITY_STYLE_WARNING:
+      return SecurityStateModel::SECURITY_WARNING;
+    case content::SECURITY_STYLE_AUTHENTICATED:
+      return SecurityStateModel::SECURE;
+  }
+  return SecurityStateModel::NONE;
+}
+
+}  // namespace
+
+AtomSecurityStateModelClient::AtomSecurityStateModelClient(
+    content::WebContents* web_contents)
+    : web_contents_(web_contents),
+      security_state_model_(new SecurityStateModel()) {
+  security_state_model_->SetClient(this);
+}
+
+AtomSecurityStateModelClient::~AtomSecurityStateModelClient() {
+}
+
+const SecurityStateModel::SecurityInfo&
+AtomSecurityStateModelClient::GetSecurityInfo() const {
+  return security_state_model_->GetSecurityInfo();
+}
+
+bool AtomSecurityStateModelClient::RetrieveCert(
+    scoped_refptr<net::X509Certificate>* cert) {
+  content::NavigationEntry* entry =
+      web_contents_->GetController().GetVisibleEntry();
+  if (!entry)
+    return false;
+  return content::CertStore::GetInstance()->RetrieveCert(
+      entry->GetSSL().cert_id, cert);
+}
+
+bool AtomSecurityStateModelClient::UsedPolicyInstalledCertificate() {
+  return false;
+}
+
+bool AtomSecurityStateModelClient::IsOriginSecure(const GURL& url) {
+  return content::IsOriginSecure(url);
+}
+
+void AtomSecurityStateModelClient::GetVisibleSecurityState(
+    SecurityStateModel::VisibleSecurityState* state) {
+  content::NavigationEntry* entry =
+      web_contents_->GetController().GetVisibleEntry();
+  if (!entry ||
+      entry->GetSSL().security_style == content::SECURITY_STYLE_UNKNOWN) {
+    *state = SecurityStateModel::VisibleSecurityState();
+    return;
+  }
+
+  state->initialized = true;
+  state->url = entry->GetURL();
+  const content::SSLStatus& ssl = entry->GetSSL();
+  state->initial_security_level =
+      GetSecurityLevelForSecurityStyle(ssl.security_style);
+  state->cert_id = ssl.cert_id;
+  state->cert_status = ssl.cert_status;
+  state->connection_status = ssl.connection_status;
+  state->security_bits = ssl.security_bits;
+  state->sct_verify_statuses.clear();
+  for (const auto& sct : ssl.signed_certificate_timestamp_ids)
+    state->sct_verify_statuses.push_back(sct.status);
+  state->displayed_mixed_content =
+      (ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT)
+          ? true
+          : false;
+  state->ran_mixed_content =
+      (ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT) ? true
+                                                                      : false;
+}
+
+}  // namespace atom

+ 42 - 0
atom/browser/atom_security_state_model_client.h

@@ -0,0 +1,42 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_ATOM_SECURITY_STATE_MODEL_CLIENT_H_
+#define ATOM_BROWSER_ATOM_SECURITY_STATE_MODEL_CLIENT_H_
+
+#include "components/security_state/security_state_model.h"
+#include "components/security_state/security_state_model_client.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace atom {
+
+class AtomSecurityStateModelClient
+    : public security_state::SecurityStateModelClient,
+      public content::WebContentsUserData<AtomSecurityStateModelClient> {
+ public:
+  ~AtomSecurityStateModelClient() override;
+
+  const security_state::SecurityStateModel::SecurityInfo&
+  GetSecurityInfo() const;
+
+  // security_state::SecurityStateModelClient:
+  void GetVisibleSecurityState(
+      security_state::SecurityStateModel::VisibleSecurityState* state) override;
+  bool RetrieveCert(scoped_refptr<net::X509Certificate>* cert) override;
+  bool UsedPolicyInstalledCertificate() override;
+  bool IsOriginSecure(const GURL& url) override;
+
+ private:
+  explicit AtomSecurityStateModelClient(content::WebContents* web_contents);
+  friend class content::WebContentsUserData<AtomSecurityStateModelClient>;
+
+  content::WebContents* web_contents_;
+  scoped_ptr<security_state::SecurityStateModel> security_state_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(AtomSecurityStateModelClient);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_ATOM_SECURITY_STATE_MODEL_CLIENT_H_

+ 107 - 0
atom/browser/common_web_contents_delegate.cc

@@ -10,9 +10,11 @@
 
 #include "atom/browser/atom_browser_context.h"
 #include "atom/browser/atom_javascript_dialog_manager.h"
+#include "atom/browser/atom_security_state_model_client.h"
 #include "atom/browser/native_window.h"
 #include "atom/browser/ui/file_dialog.h"
 #include "atom/browser/web_dialog_helper.h"
+#include "atom/common/atom_constants.h"
 #include "base/files/file_util.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
@@ -25,6 +27,8 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/security_style_explanation.h"
+#include "content/public/browser/security_style_explanations.h"
 #include "storage/browser/fileapi/isolated_context.h"
 
 #if defined(TOOLKIT_VIEWS)
@@ -36,6 +40,7 @@
 #endif
 
 using content::BrowserThread;
+using security_state::SecurityStateModel;
 
 namespace atom {
 
@@ -140,6 +145,24 @@ std::set<std::string> GetAddedFileSystemPaths(
   return result;
 }
 
+content::SecurityStyle SecurityLevelToSecurityStyle(
+    SecurityStateModel::SecurityLevel security_level) {
+  switch (security_level) {
+    case SecurityStateModel::NONE:
+      return content::SECURITY_STYLE_UNAUTHENTICATED;
+    case SecurityStateModel::SECURITY_WARNING:
+    case SecurityStateModel::SECURITY_POLICY_WARNING:
+      return content::SECURITY_STYLE_WARNING;
+    case SecurityStateModel::EV_SECURE:
+    case SecurityStateModel::SECURE:
+      return content::SECURITY_STYLE_AUTHENTICATED;
+    case SecurityStateModel::SECURITY_ERROR:
+      return content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
+  }
+
+  return content::SECURITY_STYLE_UNKNOWN;
+}
+
 }  // namespace
 
 CommonWebContentsDelegate::CommonWebContentsDelegate()
@@ -265,6 +288,90 @@ bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
   return html_fullscreen_;
 }
 
+content::SecurityStyle CommonWebContentsDelegate::GetSecurityStyle(
+    content::WebContents* web_contents,
+    content::SecurityStyleExplanations* explanations) {
+  auto model_client =
+      AtomSecurityStateModelClient::FromWebContents(web_contents);
+
+  const SecurityStateModel::SecurityInfo& security_info =
+      model_client->GetSecurityInfo();
+
+  const content::SecurityStyle security_style =
+      SecurityLevelToSecurityStyle(security_info.security_level);
+
+  explanations->ran_insecure_content_style =
+      SecurityLevelToSecurityStyle(
+          SecurityStateModel::kRanInsecureContentLevel);
+  explanations->displayed_insecure_content_style =
+      SecurityLevelToSecurityStyle(
+          SecurityStateModel::kDisplayedInsecureContentLevel);
+
+  explanations->scheme_is_cryptographic = security_info.scheme_is_cryptographic;
+  if (!security_info.scheme_is_cryptographic)
+    return security_style;
+
+  if (security_info.sha1_deprecation_status ==
+      SecurityStateModel::DEPRECATED_SHA1_MAJOR) {
+    explanations->broken_explanations.push_back(
+        content::SecurityStyleExplanation(
+            kSHA1Certificate,
+            kSHA1MajorDescription,
+            security_info.cert_id));
+  } else if (security_info.sha1_deprecation_status ==
+                SecurityStateModel::DEPRECATED_SHA1_MINOR) {
+    explanations->unauthenticated_explanations.push_back(
+        content::SecurityStyleExplanation(
+            kSHA1Certificate,
+            kSHA1MinorDescription,
+            security_info.cert_id));
+  }
+
+  explanations->ran_insecure_content =
+      security_info.mixed_content_status ==
+          SecurityStateModel::RAN_MIXED_CONTENT ||
+      security_info.mixed_content_status ==
+          SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT;
+  explanations->displayed_insecure_content =
+      security_info.mixed_content_status ==
+          SecurityStateModel::DISPLAYED_MIXED_CONTENT ||
+      security_info.mixed_content_status ==
+          SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT;
+
+  if (net::IsCertStatusError(security_info.cert_status)) {
+    std::string error_string = net::ErrorToString(
+        net::MapCertStatusToNetError(security_info.cert_status));
+
+    content::SecurityStyleExplanation explanation(
+        kCertificateError,
+        "There are issues with the site's certificate chain " + error_string,
+        security_info.cert_id);
+
+    if (net::IsCertStatusMinorError(security_info.cert_status))
+      explanations->unauthenticated_explanations.push_back(explanation);
+    else
+      explanations->broken_explanations.push_back(explanation);
+  } else {
+    if (security_info.sha1_deprecation_status ==
+        SecurityStateModel::NO_DEPRECATED_SHA1) {
+      explanations->secure_explanations.push_back(
+          content::SecurityStyleExplanation(
+              kValidCertificate,
+              kValidCertificateDescription,
+              security_info.cert_id));
+    }
+  }
+
+  if (security_info.is_secure_protocol_and_ciphersuite) {
+    explanations->secure_explanations.push_back(
+        content::SecurityStyleExplanation(
+            kSecureProtocol,
+            kSecureProtocolDescription));
+  }
+
+  return security_style;
+}
+
 void CommonWebContentsDelegate::DevToolsSaveToFile(
     const std::string& url, const std::string& content, bool save_as) {
   base::FilePath path;

+ 3 - 0
atom/browser/common_web_contents_delegate.h

@@ -76,6 +76,9 @@ class CommonWebContentsDelegate
   void ExitFullscreenModeForTab(content::WebContents* source) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* source) const override;
+  content::SecurityStyle GetSecurityStyle(
+      content::WebContents* web_contents,
+      content::SecurityStyleExplanations* explanations) override;
 
   // brightray::InspectableWebContentsDelegate:
   void DevToolsSaveToFile(const std::string& url,

+ 17 - 1
atom/common/atom_constants.cc

@@ -6,6 +6,22 @@
 
 namespace atom {
 
-const char* kCORSHeader = "Access-Control-Allow-Origin: *";
+const char kCORSHeader[] = "Access-Control-Allow-Origin: *";
+
+const char kSHA1Certificate[] = "SHA-1 Certificate";
+const char kSHA1MajorDescription[] =
+    "The certificate for this site expires in 2017 or later, "
+    "and the certificate chain contains a certificate signed using SHA-1.";
+const char kSHA1MinorDescription[] =
+    "The certificate for this site expires in 2016, "
+    "and the certificate chain contains a certificate signed using SHA-1.";
+const char kCertificateError[] = "Certificate Error";
+const char kValidCertificate[] = "Valid Certificate";
+const char kValidCertificateDescription[] =
+    "The connection to this site is using a valid, trusted server certificate.";
+const char kSecureProtocol[] = "Secure TLS connection";
+const char kSecureProtocolDescription[] =
+    "The connection to this site is using a strong protocol version "
+    "and cipher suite.";
 
 }  // namespace atom

+ 11 - 1
atom/common/atom_constants.h

@@ -8,7 +8,17 @@
 namespace atom {
 
 // Header to ignore CORS.
-extern const char* kCORSHeader;
+extern const char kCORSHeader[];
+
+// Strings describing Chrome security policy for DevTools security panel.
+extern const char kSHA1Certificate[];
+extern const char kSHA1MajorDescription[];
+extern const char kSHA1MinorDescription[];
+extern const char kCertificateError[];
+extern const char kValidCertificate[];
+extern const char kValidCertificateDescription[];
+extern const char kSecureProtocol[];
+extern const char kSecureProtocolDescription[];
 
 }  // namespace atom
 

+ 2 - 0
filenames.gypi

@@ -157,6 +157,8 @@
       'atom/browser/atom_quota_permission_context.h',
       'atom/browser/atom_resource_dispatcher_host_delegate.cc',
       'atom/browser/atom_resource_dispatcher_host_delegate.h',
+      'atom/browser/atom_security_state_model_client.cc',
+      'atom/browser/atom_security_state_model_client.h',
       'atom/browser/atom_speech_recognition_manager_delegate.cc',
       'atom/browser/atom_speech_recognition_manager_delegate.h',
       'atom/browser/bridge_task_runner.cc',