diff options
author | felt <felt@chromium.org> | 2015-09-16 16:50:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-16 23:50:59 +0000 |
commit | 7f1410648c7767ae8d466ada4385e78176f5db06 (patch) | |
tree | cafbd1d112de4a3b39ae8055aa9c604ed8c046bd /components/ssl_errors | |
parent | 9c467a8cff471575e1975f8e1f703db2f531f432 (diff) | |
download | chromium_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.gn | 18 | ||||
-rw-r--r-- | components/ssl_errors/DEPS | 5 | ||||
-rw-r--r-- | components/ssl_errors/OWNERS | 6 | ||||
-rw-r--r-- | components/ssl_errors/error_info.cc | 255 | ||||
-rw-r--r-- | components/ssl_errors/error_info.h | 79 |
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_ |