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