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.
5 #include "chrome/browser/ssl/ssl_error_info.h"
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"
19 using base::UTF8ToUTF16
;
21 SSLErrorInfo::SSLErrorInfo(const base::string16
& title
,
22 const base::string16
& details
,
23 const base::string16
& short_description
,
24 const std::vector
<base::string16
>& extra_info
)
27 short_description_(short_description
),
28 extra_information_(extra_info
) {
32 SSLErrorInfo
SSLErrorInfo::CreateError(ErrorType error_type
,
33 net::X509Certificate
* cert
,
34 const GURL
& request_url
) {
35 base::string16 title
, details
, short_description
;
36 std::vector
<base::string16
> extra_info
;
38 case CERT_COMMON_NAME_INVALID
: {
40 l10n_util::GetStringUTF16(IDS_CERT_ERROR_COMMON_NAME_INVALID_TITLE
);
41 // If the certificate contains multiple DNS names, we choose the most
42 // representative one -- either the DNS name that's also in the subject
43 // field, or the first one. If this heuristic turns out to be
44 // inadequate, we can consider choosing the DNS name that is the
45 // "closest match" to the host name in the request URL, or listing all
46 // the DNS names with an HTML <ul>.
47 std::vector
<std::string
> dns_names
;
48 cert
->GetDNSNames(&dns_names
);
49 DCHECK(!dns_names
.empty());
51 for (; i
< dns_names
.size(); ++i
) {
52 if (dns_names
[i
] == cert
->subject().common_name
)
55 if (i
== dns_names
.size())
58 l10n_util::GetStringFUTF16(IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS
,
59 UTF8ToUTF16(request_url
.host()),
61 UTF8ToUTF16(dns_names
[i
])),
62 UTF8ToUTF16(request_url
.host()));
63 short_description
= l10n_util::GetStringUTF16(
64 IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION
);
66 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
68 l10n_util::GetStringFUTF16(
69 IDS_CERT_ERROR_COMMON_NAME_INVALID_EXTRA_INFO_2
,
70 net::EscapeForHTML(UTF8ToUTF16(cert
->subject().common_name
)),
71 UTF8ToUTF16(request_url
.host())));
74 case CERT_DATE_INVALID
:
76 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
77 if (cert
->HasExpired()) {
78 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_TITLE
);
79 details
= l10n_util::GetStringFUTF16(
80 IDS_CERT_ERROR_EXPIRED_DETAILS
,
81 UTF8ToUTF16(request_url
.host()),
82 UTF8ToUTF16(request_url
.host()),
83 base::TimeFormatFriendlyDateAndTime(base::Time::Now()));
85 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DESCRIPTION
);
86 extra_info
.push_back(l10n_util::GetStringUTF16(
87 IDS_CERT_ERROR_EXPIRED_DETAILS_EXTRA_INFO_2
));
89 // Then it must be not yet valid. We don't check that it is not yet
90 // valid as there is still a very unlikely chance that the cert might
91 // have become valid since the error occurred.
92 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_TITLE
);
93 details
= l10n_util::GetStringFUTF16(
94 IDS_CERT_ERROR_NOT_YET_VALID_DETAILS
,
95 UTF8ToUTF16(request_url
.host()),
96 UTF8ToUTF16(request_url
.host()),
97 base::TimeFormatFriendlyDateAndTime(base::Time::Now()));
99 l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION
);
100 extra_info
.push_back(
101 l10n_util::GetStringUTF16(
102 IDS_CERT_ERROR_NOT_YET_VALID_DETAILS_EXTRA_INFO_2
));
105 case CERT_AUTHORITY_INVALID
:
106 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_AUTHORITY_INVALID_TITLE
);
107 details
= l10n_util::GetStringFUTF16(
108 IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS
,
109 UTF8ToUTF16(request_url
.host()));
110 short_description
= l10n_util::GetStringUTF16(
111 IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION
);
112 extra_info
.push_back(
113 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
114 extra_info
.push_back(l10n_util::GetStringFUTF16(
115 IDS_CERT_ERROR_AUTHORITY_INVALID_EXTRA_INFO_2
,
116 UTF8ToUTF16(request_url
.host()),
117 UTF8ToUTF16(request_url
.host())));
119 // The third paragraph advises users to install a private trust anchor,
120 // but that is not possible in Chrome for iOS at this time.
121 extra_info
.push_back(l10n_util::GetStringUTF16(
122 IDS_CERT_ERROR_AUTHORITY_INVALID_EXTRA_INFO_3
));
125 case CERT_CONTAINS_ERRORS
:
126 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_TITLE
);
127 details
= l10n_util::GetStringFUTF16(
128 IDS_CERT_ERROR_CONTAINS_ERRORS_DETAILS
,
129 UTF8ToUTF16(request_url
.host()));
131 l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION
);
132 extra_info
.push_back(
133 l10n_util::GetStringFUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
,
134 UTF8ToUTF16(request_url
.host())));
135 extra_info
.push_back(l10n_util::GetStringUTF16(
136 IDS_CERT_ERROR_CONTAINS_ERRORS_EXTRA_INFO_2
));
138 case CERT_NO_REVOCATION_MECHANISM
:
139 title
= l10n_util::GetStringUTF16(
140 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_TITLE
);
141 details
= l10n_util::GetStringUTF16(
142 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS
);
143 short_description
= l10n_util::GetStringUTF16(
144 IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION
);
146 case CERT_UNABLE_TO_CHECK_REVOCATION
:
147 title
= l10n_util::GetStringUTF16(
148 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_TITLE
);
149 details
= l10n_util::GetStringUTF16(
150 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS
);
151 short_description
= l10n_util::GetStringUTF16(
152 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DESCRIPTION
);
155 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_TITLE
);
156 details
= l10n_util::GetStringFUTF16(IDS_CERT_ERROR_REVOKED_CERT_DETAILS
,
157 UTF8ToUTF16(request_url
.host()));
159 l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION
);
160 extra_info
.push_back(
161 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
162 extra_info
.push_back(
163 l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_EXTRA_INFO_2
));
166 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_TITLE
);
167 details
= l10n_util::GetStringFUTF16(
168 IDS_CERT_ERROR_INVALID_CERT_DETAILS
,
169 UTF8ToUTF16(request_url
.host()));
171 l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_DESCRIPTION
);
172 extra_info
.push_back(
173 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
174 extra_info
.push_back(l10n_util::GetStringUTF16(
175 IDS_CERT_ERROR_INVALID_CERT_EXTRA_INFO_2
));
177 case CERT_WEAK_SIGNATURE_ALGORITHM
:
178 title
= l10n_util::GetStringUTF16(
179 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_TITLE
);
180 details
= l10n_util::GetStringFUTF16(
181 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DETAILS
,
182 UTF8ToUTF16(request_url
.host()));
183 short_description
= l10n_util::GetStringUTF16(
184 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DESCRIPTION
);
185 extra_info
.push_back(
186 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
187 extra_info
.push_back(
188 l10n_util::GetStringUTF16(
189 IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_EXTRA_INFO_2
));
192 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_WEAK_KEY_TITLE
);
193 details
= l10n_util::GetStringFUTF16(
194 IDS_CERT_ERROR_WEAK_KEY_DETAILS
, UTF8ToUTF16(request_url
.host()));
195 short_description
= l10n_util::GetStringUTF16(
196 IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION
);
197 extra_info
.push_back(
198 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_1
));
199 extra_info
.push_back(
200 l10n_util::GetStringUTF16(
201 IDS_CERT_ERROR_WEAK_KEY_EXTRA_INFO_2
));
203 case CERT_WEAK_KEY_DH
:
204 title
= l10n_util::GetStringUTF16(
205 IDS_ERRORPAGES_HEADING_WEAK_SERVER_EPHEMERAL_DH_KEY
);
206 details
= l10n_util::GetStringFUTF16(
207 IDS_CERT_ERROR_WEAK_KEY_DETAILS
, UTF8ToUTF16(request_url
.host()));
208 short_description
= l10n_util::GetStringUTF16(
209 IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION
);
210 extra_info
.push_back(
211 l10n_util::GetStringUTF16(
212 IDS_ERRORPAGES_SUMMARY_WEAK_SERVER_EPHEMERAL_DH_KEY
));
213 case CERT_NAME_CONSTRAINT_VIOLATION
:
214 title
= l10n_util::GetStringUTF16(
215 IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_TITLE
);
216 details
= l10n_util::GetStringFUTF16(
217 IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DETAILS
,
218 UTF8ToUTF16(request_url
.host()));
219 short_description
= l10n_util::GetStringUTF16(
220 IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION
);
222 case CERT_PINNED_KEY_MISSING
:
223 title
= l10n_util::GetStringUTF16(
224 IDS_ERRORPAGES_HEADING_PINNING_FAILURE
);
225 details
= l10n_util::GetStringUTF16(
226 IDS_ERRORPAGES_SUMMARY_PINNING_FAILURE
);
227 short_description
= l10n_util::GetStringUTF16(
228 IDS_ERRORPAGES_DETAILS_PINNING_FAILURE
);
230 title
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_TITLE
);
231 details
= l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS
);
233 l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION
);
238 return SSLErrorInfo(title
, details
, short_description
, extra_info
);
241 SSLErrorInfo::~SSLErrorInfo() {
245 SSLErrorInfo::ErrorType
SSLErrorInfo::NetErrorToErrorType(int net_error
) {
247 case net::ERR_CERT_COMMON_NAME_INVALID
:
248 return CERT_COMMON_NAME_INVALID
;
249 case net::ERR_CERT_DATE_INVALID
:
250 return CERT_DATE_INVALID
;
251 case net::ERR_CERT_AUTHORITY_INVALID
:
252 return CERT_AUTHORITY_INVALID
;
253 case net::ERR_CERT_CONTAINS_ERRORS
:
254 return CERT_CONTAINS_ERRORS
;
255 case net::ERR_CERT_NO_REVOCATION_MECHANISM
:
256 return CERT_NO_REVOCATION_MECHANISM
;
257 case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION
:
258 return CERT_UNABLE_TO_CHECK_REVOCATION
;
259 case net::ERR_CERT_REVOKED
:
261 case net::ERR_CERT_INVALID
:
263 case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM
:
264 return CERT_WEAK_SIGNATURE_ALGORITHM
;
265 case net::ERR_CERT_WEAK_KEY
:
266 return CERT_WEAK_KEY
;
267 case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION
:
268 return CERT_NAME_CONSTRAINT_VIOLATION
;
269 case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY
:
270 return CERT_WEAK_KEY_DH
;
271 case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN
:
272 return CERT_PINNED_KEY_MISSING
;
280 int SSLErrorInfo::GetErrorsForCertStatus(int cert_id
,
281 net::CertStatus cert_status
,
283 std::vector
<SSLErrorInfo
>* errors
) {
284 const net::CertStatus kErrorFlags
[] = {
285 net::CERT_STATUS_COMMON_NAME_INVALID
,
286 net::CERT_STATUS_DATE_INVALID
,
287 net::CERT_STATUS_AUTHORITY_INVALID
,
288 net::CERT_STATUS_NO_REVOCATION_MECHANISM
,
289 net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION
,
290 net::CERT_STATUS_REVOKED
,
291 net::CERT_STATUS_INVALID
,
292 net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM
,
293 net::CERT_STATUS_WEAK_KEY
,
294 net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION
,
297 const ErrorType kErrorTypes
[] = {
298 CERT_COMMON_NAME_INVALID
,
300 CERT_AUTHORITY_INVALID
,
301 CERT_NO_REVOCATION_MECHANISM
,
302 CERT_UNABLE_TO_CHECK_REVOCATION
,
305 CERT_WEAK_SIGNATURE_ALGORITHM
,
307 CERT_NAME_CONSTRAINT_VIOLATION
,
309 DCHECK(arraysize(kErrorFlags
) == arraysize(kErrorTypes
));
311 scoped_refptr
<net::X509Certificate
> cert
= NULL
;
313 for (size_t i
= 0; i
< arraysize(kErrorFlags
); ++i
) {
314 if (cert_status
& kErrorFlags
[i
]) {
317 bool r
= content::CertStore::GetInstance()->RetrieveCert(
323 SSLErrorInfo::CreateError(kErrorTypes
[i
], cert
.get(), url
));