summaryrefslogtreecommitdiffstats
path: root/components/ssl_errors
diff options
context:
space:
mode:
authorfelt <felt@chromium.org>2015-09-16 16:50:30 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-16 23:50:59 +0000
commit7f1410648c7767ae8d466ada4385e78176f5db06 (patch)
treecafbd1d112de4a3b39ae8055aa9c604ed8c046bd /components/ssl_errors
parent9c467a8cff471575e1975f8e1f703db2f531f432 (diff)
downloadchromium_src-7f1410648c7767ae8d466ada4385e78176f5db06.zip
chromium_src-7f1410648c7767ae8d466ada4385e78176f5db06.tar.gz
chromium_src-7f1410648c7767ae8d466ada4385e78176f5db06.tar.bz2
Create a component for SSL error handling
Classes like SSLErrorInfo, SSLErrorHandler, and SSLErrorClassification are tightly coupled with the SSL interstitial. Since the interstitial UI is being componentized, I want to move the SSL error handling classes into a component too. This CL begins with SSLErrorInfo. BUG=488673 Review URL: https://codereview.chromium.org/1341923002 Cr-Commit-Position: refs/heads/master@{#349282}
Diffstat (limited to 'components/ssl_errors')
-rw-r--r--components/ssl_errors/BUILD.gn18
-rw-r--r--components/ssl_errors/DEPS5
-rw-r--r--components/ssl_errors/OWNERS6
-rw-r--r--components/ssl_errors/error_info.cc255
-rw-r--r--components/ssl_errors/error_info.h79
5 files changed, 363 insertions, 0 deletions
diff --git a/components/ssl_errors/BUILD.gn b/components/ssl_errors/BUILD.gn
new file mode 100644
index 0000000..fc3da15
--- /dev/null
+++ b/components/ssl_errors/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2015 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.
+
+# GYP version: components/ssl_errors.gyp
+source_set("ssl_errors") {
+ sources = [
+ "error_info.cc",
+ "error_info.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings",
+ "//net",
+ "//ui/base",
+ ]
+}
diff --git a/components/ssl_errors/DEPS b/components/ssl_errors/DEPS
new file mode 100644
index 0000000..37f0ae0
--- /dev/null
+++ b/components/ssl_errors/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+grit",
+ "+net",
+ "+ui/base"
+] \ No newline at end of file
diff --git a/components/ssl_errors/OWNERS b/components/ssl_errors/OWNERS
new file mode 100644
index 0000000..3f66a8d
--- /dev/null
+++ b/components/ssl_errors/OWNERS
@@ -0,0 +1,6 @@
+agl@chromium.org
+estark@chromium.org
+felt@chromium.org
+meacer@chromium.org
+palmer@chromium.org
+rsleevi@chromium.org
diff --git a/components/ssl_errors/error_info.cc b/components/ssl_errors/error_info.cc
new file mode 100644
index 0000000..625a31b
--- /dev/null
+++ b/components/ssl_errors/error_info.cc
@@ -0,0 +1,255 @@
+// Copyright 2015 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 "components/ssl_errors/error_info.h"
+
+#include "base/i18n/message_formatter.h"
+#include "base/strings/utf_string_conversions.h"
+#include "grit/components_strings.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/ssl/ssl_info.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
+
+using base::UTF8ToUTF16;
+
+namespace ssl_errors {
+
+ErrorInfo::ErrorInfo(const base::string16& details,
+ const base::string16& short_description)
+ : details_(details), short_description_(short_description) {}
+
+// static
+ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
+ net::X509Certificate* cert,
+ const GURL& request_url) {
+ base::string16 details, short_description;
+ switch (error_type) {
+ case CERT_COMMON_NAME_INVALID: {
+ // If the certificate contains multiple DNS names, we choose the most
+ // representative one -- either the DNS name that's also in the subject
+ // field, or the first one. If this heuristic turns out to be
+ // inadequate, we can consider choosing the DNS name that is the
+ // "closest match" to the host name in the request URL, or listing all
+ // the DNS names with an HTML <ul>.
+ std::vector<std::string> dns_names;
+ cert->GetDNSNames(&dns_names);
+ DCHECK(!dns_names.empty());
+ size_t i = 0;
+ for (; i < dns_names.size(); ++i) {
+ if (dns_names[i] == cert->subject().common_name)
+ break;
+ }
+ if (i == dns_names.size())
+ i = 0;
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS,
+ UTF8ToUTF16(request_url.host()),
+ net::EscapeForHTML(UTF8ToUTF16(dns_names[i])));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION);
+ break;
+ }
+ case CERT_DATE_INVALID:
+ if (cert->HasExpired()) {
+ // Make sure to round up to the smallest integer value not less than
+ // the expiration value (https://crbug.com/476758).
+ int expiration_value =
+ (base::Time::Now() - cert->valid_expiry()).InDays() + 1;
+ details = base::i18n::MessageFormatter::FormatWithNumberedArgs(
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DETAILS),
+ request_url.host(), expiration_value, base::Time::Now());
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DESCRIPTION);
+ } else if (base::Time::Now() < cert->valid_start()) {
+ details = base::i18n::MessageFormatter::FormatWithNumberedArgs(
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_DETAILS),
+ request_url.host(),
+ (cert->valid_start() - base::Time::Now()).InDays());
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION);
+ } else {
+ // Two possibilities: (1) an intermediate or root certificate has
+ // expired, or (2) the certificate has become valid since the error
+ // occurred. Both are probably rare cases. To avoid giving the wrong
+ // date, remove the information.
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_NOT_VALID_AT_THIS_TIME_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_NOT_VALID_AT_THIS_TIME_DESCRIPTION);
+ }
+ break;
+ case CERT_AUTHORITY_INVALID:
+ details =
+ l10n_util::GetStringFUTF16(IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION);
+ break;
+ case CERT_CONTAINS_ERRORS:
+ details =
+ l10n_util::GetStringFUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION);
+ break;
+ case CERT_NO_REVOCATION_MECHANISM:
+ details = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS);
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION);
+ break;
+ case CERT_REVOKED:
+ details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_REVOKED_CERT_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION);
+ break;
+ case CERT_INVALID:
+ details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_INVALID_CERT_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_DESCRIPTION);
+ break;
+ case CERT_WEAK_SIGNATURE_ALGORITHM:
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DESCRIPTION);
+ break;
+ case CERT_WEAK_KEY:
+ details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_WEAK_KEY_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION);
+ break;
+ case CERT_WEAK_KEY_DH:
+ details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_WEAK_KEY_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION);
+ case CERT_NAME_CONSTRAINT_VIOLATION:
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION);
+ break;
+ case CERT_VALIDITY_TOO_LONG:
+ details =
+ l10n_util::GetStringFUTF16(IDS_CERT_ERROR_VALIDITY_TOO_LONG_DETAILS,
+ UTF8ToUTF16(request_url.host()));
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_VALIDITY_TOO_LONG_DESCRIPTION);
+ break;
+ case CERT_PINNED_KEY_MISSING:
+ details = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DETAILS);
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DESCRIPTION);
+ break;
+ case CERT_UNABLE_TO_CHECK_REVOCATION:
+ details = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS);
+ short_description = l10n_util::GetStringUTF16(
+ IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DESCRIPTION);
+ break;
+ case UNKNOWN:
+ details = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS);
+ short_description =
+ l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION);
+ break;
+ default:
+ NOTREACHED();
+ }
+ return ErrorInfo(details, short_description);
+}
+
+ErrorInfo::~ErrorInfo() {}
+
+// static
+ErrorInfo::ErrorType ErrorInfo::NetErrorToErrorType(int net_error) {
+ switch (net_error) {
+ case net::ERR_CERT_COMMON_NAME_INVALID:
+ return CERT_COMMON_NAME_INVALID;
+ case net::ERR_CERT_DATE_INVALID:
+ return CERT_DATE_INVALID;
+ case net::ERR_CERT_AUTHORITY_INVALID:
+ return CERT_AUTHORITY_INVALID;
+ case net::ERR_CERT_CONTAINS_ERRORS:
+ return CERT_CONTAINS_ERRORS;
+ case net::ERR_CERT_NO_REVOCATION_MECHANISM:
+ return CERT_NO_REVOCATION_MECHANISM;
+ case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
+ return CERT_UNABLE_TO_CHECK_REVOCATION;
+ case net::ERR_CERT_REVOKED:
+ return CERT_REVOKED;
+ case net::ERR_CERT_INVALID:
+ return CERT_INVALID;
+ case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
+ return CERT_WEAK_SIGNATURE_ALGORITHM;
+ case net::ERR_CERT_WEAK_KEY:
+ return CERT_WEAK_KEY;
+ case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
+ return CERT_NAME_CONSTRAINT_VIOLATION;
+ case net::ERR_CERT_VALIDITY_TOO_LONG:
+ return CERT_VALIDITY_TOO_LONG;
+ case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
+ return CERT_WEAK_KEY_DH;
+ case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
+ return CERT_PINNED_KEY_MISSING;
+ default:
+ NOTREACHED();
+ return UNKNOWN;
+ }
+}
+
+// static
+void ErrorInfo::GetErrorsForCertStatus(
+ const scoped_refptr<net::X509Certificate>& cert,
+ net::CertStatus cert_status,
+ const GURL& url,
+ std::vector<ErrorInfo>* errors) {
+ const net::CertStatus kErrorFlags[] = {
+ net::CERT_STATUS_COMMON_NAME_INVALID,
+ net::CERT_STATUS_DATE_INVALID,
+ net::CERT_STATUS_AUTHORITY_INVALID,
+ net::CERT_STATUS_NO_REVOCATION_MECHANISM,
+ net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
+ net::CERT_STATUS_REVOKED,
+ net::CERT_STATUS_INVALID,
+ net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM,
+ net::CERT_STATUS_WEAK_KEY,
+ net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION,
+ net::CERT_STATUS_VALIDITY_TOO_LONG,
+ };
+
+ const ErrorType kErrorTypes[] = {
+ CERT_COMMON_NAME_INVALID,
+ CERT_DATE_INVALID,
+ CERT_AUTHORITY_INVALID,
+ CERT_NO_REVOCATION_MECHANISM,
+ CERT_UNABLE_TO_CHECK_REVOCATION,
+ CERT_REVOKED,
+ CERT_INVALID,
+ CERT_WEAK_SIGNATURE_ALGORITHM,
+ CERT_WEAK_KEY,
+ CERT_NAME_CONSTRAINT_VIOLATION,
+ CERT_VALIDITY_TOO_LONG,
+ };
+ DCHECK(arraysize(kErrorFlags) == arraysize(kErrorTypes));
+
+ for (size_t i = 0; i < arraysize(kErrorFlags); ++i) {
+ if ((cert_status & kErrorFlags[i]) && errors) {
+ errors->push_back(
+ ErrorInfo::CreateError(kErrorTypes[i], cert.get(), url));
+ }
+ }
+}
+
+} // namespace ssl_errors
diff --git a/components/ssl_errors/error_info.h b/components/ssl_errors/error_info.h
new file mode 100644
index 0000000..1b26be5
--- /dev/null
+++ b/components/ssl_errors/error_info.h
@@ -0,0 +1,79 @@
+// Copyright 2015 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 COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_
+#define COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/cert/x509_certificate.h"
+
+class GURL;
+
+namespace ssl_errors {
+
+// This class describes an error that happened while showing a page over SSL.
+// An ErrorInfo object only exists on the UI thread and only contains
+// information about an error (type of error and text details).
+// Note no DISALLOW_COPY_AND_ASSIGN as we want the copy constructor.
+class ErrorInfo {
+ public:
+ // This enum is being histogrammed; please only add new values at the end.
+ enum ErrorType {
+ CERT_COMMON_NAME_INVALID = 0,
+ CERT_DATE_INVALID,
+ CERT_AUTHORITY_INVALID,
+ CERT_CONTAINS_ERRORS,
+ CERT_NO_REVOCATION_MECHANISM,
+ CERT_UNABLE_TO_CHECK_REVOCATION,
+ CERT_REVOKED,
+ CERT_INVALID,
+ CERT_WEAK_SIGNATURE_ALGORITHM,
+ CERT_WEAK_KEY,
+ CERT_NAME_CONSTRAINT_VIOLATION,
+ UNKNOWN,
+ CERT_WEAK_KEY_DH,
+ CERT_PINNED_KEY_MISSING,
+ CERT_VALIDITY_TOO_LONG,
+ END_OF_ENUM
+ };
+
+ virtual ~ErrorInfo();
+
+ // Converts a network error code to an ErrorType.
+ static ErrorType NetErrorToErrorType(int net_error);
+
+ static ErrorInfo CreateError(ErrorType error_type,
+ net::X509Certificate* cert,
+ const GURL& request_url);
+
+ // Populates the specified |errors| vector with the errors contained in
+ // |cert_status| for |cert|. Returns the number of errors found.
+ // Callers only interested in the error count can pass NULL for |errors|.
+ static void GetErrorsForCertStatus(
+ const scoped_refptr<net::X509Certificate>& cert,
+ net::CertStatus cert_status,
+ const GURL& url,
+ std::vector<ErrorInfo>* errors);
+
+ // A description of the error.
+ const base::string16& details() const { return details_; }
+
+ // A short message describing the error (1 line).
+ const base::string16& short_description() const { return short_description_; }
+
+ private:
+ ErrorInfo(const base::string16& details,
+ const base::string16& short_description);
+
+ base::string16 details_;
+ base::string16 short_description_;
+};
+
+} // namespace ssl_errors
+
+#endif // COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_