ssl_error_info.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ssl/ssl_error_info.h" 6 7#include "base/i18n/time_formatting.h" 8#include "base/strings/utf_string_conversions.h" 9#include "content/public/browser/cert_store.h" 10#include "grit/chromium_strings.h" 11#include "grit/generated_resources.h" 12#include "net/base/escape.h" 13#include "net/base/net_errors.h" 14#include "net/cert/cert_status_flags.h" 15#include "net/ssl/ssl_info.h" 16#include "ui/base/l10n/l10n_util.h" 17#include "url/gurl.h" 18 19SSLErrorInfo::SSLErrorInfo(const string16& title, 20 const string16& details, 21 const string16& short_description, 22 const std::vector<string16>& extra_info) 23 : title_(title), 24 details_(details), 25 short_description_(short_description), 26 extra_information_(extra_info) { 27} 28 29// static 30SSLErrorInfo SSLErrorInfo::CreateError(ErrorType error_type, 31 net::X509Certificate* cert, 32 const GURL& request_url) { 33 string16 title, details, short_description; 34 std::vector<string16> extra_info; 35 switch (error_type) { 36 case CERT_COMMON_NAME_INVALID: { 37 title = 38 l10n_util::GetStringUTF16(IDS_CERT_ERROR_COMMON_NAME_INVALID_TITLE); 39 // If the certificate contains multiple DNS names, we choose the most 40 // representative one -- either the DNS name that's also in the subject 41 // field, or the first one. If this heuristic turns out to be 42 // inadequate, we can consider choosing the DNS name that is the 43 // "closest match" to the host name in the request URL, or listing all 44 // the DNS names with an HTML <ul>. 45 std::vector<std::string> dns_names; 46 cert->GetDNSNames(&dns_names); 47 DCHECK(!dns_names.empty()); 48 size_t i = 0; 49 for (; i < dns_names.size(); ++i) { 50 if (dns_names[i] == cert->subject().common_name) 51 break; 52 } 53 if (i == dns_names.size()) 54 i = 0; 55 details = 56 l10n_util::GetStringFUTF16(IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS, 57 UTF8ToUTF16(request_url.host()), 58 net::EscapeForHTML( 59 UTF8ToUTF16(dns_names[i])), 60 UTF8ToUTF16(request_url.host())); 61 short_description = l10n_util::GetStringUTF16( 62 IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION); 63 extra_info.push_back( 64 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 65 extra_info.push_back( 66 l10n_util::GetStringFUTF16( 67 IDS_CERT_ERROR_COMMON_NAME_INVALID_EXTRA_INFO_2, 68 net::EscapeForHTML(UTF8ToUTF16(cert->subject().common_name)), 69 UTF8ToUTF16(request_url.host()))); 70 break; 71 } 72 case CERT_DATE_INVALID: 73 extra_info.push_back( 74 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 75 if (cert->HasExpired()) { 76 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_TITLE); 77 details = l10n_util::GetStringFUTF16( 78 IDS_CERT_ERROR_EXPIRED_DETAILS, 79 UTF8ToUTF16(request_url.host()), 80 UTF8ToUTF16(request_url.host()), 81 base::TimeFormatFriendlyDateAndTime(base::Time::Now())); 82 short_description = 83 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DESCRIPTION); 84 extra_info.push_back(l10n_util::GetStringUTF16( 85 IDS_CERT_ERROR_EXPIRED_DETAILS_EXTRA_INFO_2)); 86 } else { 87 // Then it must be not yet valid. We don't check that it is not yet 88 // valid as there is still a very unlikely chance that the cert might 89 // have become valid since the error occurred. 90 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_TITLE); 91 details = l10n_util::GetStringFUTF16( 92 IDS_CERT_ERROR_NOT_YET_VALID_DETAILS, 93 UTF8ToUTF16(request_url.host()), 94 UTF8ToUTF16(request_url.host()), 95 base::TimeFormatFriendlyDateAndTime(base::Time::Now())); 96 short_description = 97 l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION); 98 extra_info.push_back( 99 l10n_util::GetStringUTF16( 100 IDS_CERT_ERROR_NOT_YET_VALID_DETAILS_EXTRA_INFO_2)); 101 } 102 break; 103 case CERT_AUTHORITY_INVALID: 104 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_AUTHORITY_INVALID_TITLE); 105 details = l10n_util::GetStringFUTF16( 106 IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS, 107 UTF8ToUTF16(request_url.host())); 108 short_description = l10n_util::GetStringUTF16( 109 IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION); 110 extra_info.push_back( 111 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 112 extra_info.push_back(l10n_util::GetStringFUTF16( 113 IDS_CERT_ERROR_AUTHORITY_INVALID_EXTRA_INFO_2, 114 UTF8ToUTF16(request_url.host()), 115 UTF8ToUTF16(request_url.host()))); 116#if !defined(OS_IOS) 117 // The third paragraph advises users to install a private trust anchor, 118 // but that is not possible in Chrome for iOS at this time. 119 extra_info.push_back(l10n_util::GetStringUTF16( 120 IDS_CERT_ERROR_AUTHORITY_INVALID_EXTRA_INFO_3)); 121#endif 122 break; 123 case CERT_CONTAINS_ERRORS: 124 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_TITLE); 125 details = l10n_util::GetStringFUTF16( 126 IDS_CERT_ERROR_CONTAINS_ERRORS_DETAILS, 127 UTF8ToUTF16(request_url.host())); 128 short_description = 129 l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION); 130 extra_info.push_back( 131 l10n_util::GetStringFUTF16(IDS_CERT_ERROR_EXTRA_INFO_1, 132 UTF8ToUTF16(request_url.host()))); 133 extra_info.push_back(l10n_util::GetStringUTF16( 134 IDS_CERT_ERROR_CONTAINS_ERRORS_EXTRA_INFO_2)); 135 break; 136 case CERT_NO_REVOCATION_MECHANISM: 137 title = l10n_util::GetStringUTF16( 138 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_TITLE); 139 details = l10n_util::GetStringUTF16( 140 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS); 141 short_description = l10n_util::GetStringUTF16( 142 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION); 143 break; 144 case CERT_UNABLE_TO_CHECK_REVOCATION: 145 title = l10n_util::GetStringUTF16( 146 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_TITLE); 147 details = l10n_util::GetStringUTF16( 148 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS); 149 short_description = l10n_util::GetStringUTF16( 150 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DESCRIPTION); 151 break; 152 case CERT_REVOKED: 153 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_TITLE); 154 details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_REVOKED_CERT_DETAILS, 155 UTF8ToUTF16(request_url.host())); 156 short_description = 157 l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION); 158 extra_info.push_back( 159 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 160 extra_info.push_back( 161 l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_EXTRA_INFO_2)); 162 break; 163 case CERT_INVALID: 164 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_TITLE); 165 details = l10n_util::GetStringFUTF16( 166 IDS_CERT_ERROR_INVALID_CERT_DETAILS, 167 UTF8ToUTF16(request_url.host())); 168 short_description = 169 l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_DESCRIPTION); 170 extra_info.push_back( 171 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 172 extra_info.push_back(l10n_util::GetStringUTF16( 173 IDS_CERT_ERROR_INVALID_CERT_EXTRA_INFO_2)); 174 break; 175 case CERT_WEAK_SIGNATURE_ALGORITHM: 176 title = l10n_util::GetStringUTF16( 177 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_TITLE); 178 details = l10n_util::GetStringFUTF16( 179 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DETAILS, 180 UTF8ToUTF16(request_url.host())); 181 short_description = l10n_util::GetStringUTF16( 182 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DESCRIPTION); 183 extra_info.push_back( 184 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 185 extra_info.push_back( 186 l10n_util::GetStringUTF16( 187 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_EXTRA_INFO_2)); 188 break; 189 case CERT_WEAK_KEY: 190 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_WEAK_KEY_TITLE); 191 details = l10n_util::GetStringFUTF16( 192 IDS_CERT_ERROR_WEAK_KEY_DETAILS, UTF8ToUTF16(request_url.host())); 193 short_description = l10n_util::GetStringUTF16( 194 IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION); 195 extra_info.push_back( 196 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1)); 197 extra_info.push_back( 198 l10n_util::GetStringUTF16( 199 IDS_CERT_ERROR_WEAK_KEY_EXTRA_INFO_2)); 200 break; 201 case CERT_WEAK_KEY_DH: 202 title = l10n_util::GetStringUTF16( 203 IDS_ERRORPAGES_HEADING_WEAK_SERVER_EPHEMERAL_DH_KEY); 204 details = l10n_util::GetStringFUTF16( 205 IDS_CERT_ERROR_WEAK_KEY_DETAILS, UTF8ToUTF16(request_url.host())); 206 short_description = l10n_util::GetStringUTF16( 207 IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION); 208 extra_info.push_back( 209 l10n_util::GetStringUTF16( 210 IDS_ERRORPAGES_SUMMARY_WEAK_SERVER_EPHEMERAL_DH_KEY)); 211 case CERT_PINNED_KEY_MISSING: 212 title = l10n_util::GetStringUTF16( 213 IDS_ERRORPAGES_HEADING_PINNING_FAILURE); 214 details = l10n_util::GetStringUTF16( 215 IDS_ERRORPAGES_SUMMARY_PINNING_FAILURE); 216 short_description = l10n_util::GetStringUTF16( 217 IDS_ERRORPAGES_DETAILS_PINNING_FAILURE); 218 case UNKNOWN: 219 title = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_TITLE); 220 details = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS); 221 short_description = 222 l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION); 223 break; 224 default: 225 NOTREACHED(); 226 } 227 return SSLErrorInfo(title, details, short_description, extra_info); 228} 229 230SSLErrorInfo::~SSLErrorInfo() { 231} 232 233// static 234SSLErrorInfo::ErrorType SSLErrorInfo::NetErrorToErrorType(int net_error) { 235 switch (net_error) { 236 case net::ERR_CERT_COMMON_NAME_INVALID: 237 return CERT_COMMON_NAME_INVALID; 238 case net::ERR_CERT_DATE_INVALID: 239 return CERT_DATE_INVALID; 240 case net::ERR_CERT_AUTHORITY_INVALID: 241 return CERT_AUTHORITY_INVALID; 242 case net::ERR_CERT_CONTAINS_ERRORS: 243 return CERT_CONTAINS_ERRORS; 244 case net::ERR_CERT_NO_REVOCATION_MECHANISM: 245 return CERT_NO_REVOCATION_MECHANISM; 246 case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: 247 return CERT_UNABLE_TO_CHECK_REVOCATION; 248 case net::ERR_CERT_REVOKED: 249 return CERT_REVOKED; 250 case net::ERR_CERT_INVALID: 251 return CERT_INVALID; 252 case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM: 253 return CERT_WEAK_SIGNATURE_ALGORITHM; 254 case net::ERR_CERT_WEAK_KEY: 255 return CERT_WEAK_KEY; 256 case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: 257 return CERT_WEAK_KEY_DH; 258 case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: 259 return CERT_PINNED_KEY_MISSING; 260 default: 261 NOTREACHED(); 262 return UNKNOWN; 263 } 264} 265 266// static 267int SSLErrorInfo::GetErrorsForCertStatus(int cert_id, 268 net::CertStatus cert_status, 269 const GURL& url, 270 std::vector<SSLErrorInfo>* errors) { 271 const net::CertStatus kErrorFlags[] = { 272 net::CERT_STATUS_COMMON_NAME_INVALID, 273 net::CERT_STATUS_DATE_INVALID, 274 net::CERT_STATUS_AUTHORITY_INVALID, 275 net::CERT_STATUS_NO_REVOCATION_MECHANISM, 276 net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, 277 net::CERT_STATUS_REVOKED, 278 net::CERT_STATUS_INVALID, 279 net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, 280 net::CERT_STATUS_WEAK_KEY 281 }; 282 283 const ErrorType kErrorTypes[] = { 284 CERT_COMMON_NAME_INVALID, 285 CERT_DATE_INVALID, 286 CERT_AUTHORITY_INVALID, 287 CERT_NO_REVOCATION_MECHANISM, 288 CERT_UNABLE_TO_CHECK_REVOCATION, 289 CERT_REVOKED, 290 CERT_INVALID, 291 CERT_WEAK_SIGNATURE_ALGORITHM, 292 CERT_WEAK_KEY 293 }; 294 DCHECK(arraysize(kErrorFlags) == arraysize(kErrorTypes)); 295 296 scoped_refptr<net::X509Certificate> cert = NULL; 297 int count = 0; 298 for (size_t i = 0; i < arraysize(kErrorFlags); ++i) { 299 if (cert_status & kErrorFlags[i]) { 300 count++; 301 if (!cert.get()) { 302 bool r = content::CertStore::GetInstance()->RetrieveCert( 303 cert_id, &cert); 304 DCHECK(r); 305 } 306 if (errors) 307 errors->push_back( 308 SSLErrorInfo::CreateError(kErrorTypes[i], cert.get(), url)); 309 } 310 } 311 return count; 312} 313