• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SSLErrorInfo(const string16 & title,const string16 & details,const string16 & short_description,const std::vector<string16> & extra_info)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
CreateError(ErrorType error_type,net::X509Certificate * cert,const GURL & request_url)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 
~SSLErrorInfo()200 SSLErrorInfo::~SSLErrorInfo() {
201 }
202 
203 // static
NetErrorToErrorType(int net_error)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
GetErrorsForCertStatus(int cert_id,int cert_status,const GURL & url,std::vector<SSLErrorInfo> * errors)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