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