Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ssl / ssl_error_info.cc
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/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/grit/chromium_strings.h"
11 #include "chrome/grit/generated_resources.h"
12 #include "content/public/browser/cert_store.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
20 using base::UTF8ToUTF16;
21
22 SSLErrorInfo::SSLErrorInfo(const base::string16& details,
23                            const base::string16& short_description)
24     : details_(details),
25       short_description_(short_description) {
26 }
27
28 // static
29 SSLErrorInfo SSLErrorInfo::CreateError(ErrorType error_type,
30                                        net::X509Certificate* cert,
31                                        const GURL& request_url) {
32   base::string16 details, short_description;
33   switch (error_type) {
34     case CERT_COMMON_NAME_INVALID: {
35       // If the certificate contains multiple DNS names, we choose the most
36       // representative one -- either the DNS name that's also in the subject
37       // field, or the first one.  If this heuristic turns out to be
38       // inadequate, we can consider choosing the DNS name that is the
39       // "closest match" to the host name in the request URL, or listing all
40       // the DNS names with an HTML <ul>.
41       std::vector<std::string> dns_names;
42       cert->GetDNSNames(&dns_names);
43       DCHECK(!dns_names.empty());
44       size_t i = 0;
45       for (; i < dns_names.size(); ++i) {
46         if (dns_names[i] == cert->subject().common_name)
47           break;
48       }
49       if (i == dns_names.size())
50         i = 0;
51       details =
52           l10n_util::GetStringFUTF16(IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS,
53                                      UTF8ToUTF16(request_url.host()),
54                                      net::EscapeForHTML(
55                                          UTF8ToUTF16(dns_names[i])));
56       short_description = l10n_util::GetStringUTF16(
57           IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION);
58       break;
59     }
60     case CERT_DATE_INVALID:
61       if (cert->HasExpired()) {
62         details = l10n_util::GetStringFUTF16(
63             IDS_CERT_ERROR_EXPIRED_DETAILS,
64             UTF8ToUTF16(request_url.host()),
65             base::IntToString16(
66                 (base::Time::Now() - cert->valid_expiry()).InDays()),
67             base::TimeFormatFriendlyDate(base::Time::Now()));
68         short_description =
69             l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DESCRIPTION);
70       } else if (base::Time::Now() < cert->valid_start()) {
71         details = l10n_util::GetStringFUTF16(
72             IDS_CERT_ERROR_NOT_YET_VALID_DETAILS,
73             UTF8ToUTF16(request_url.host()),
74             base::IntToString16(
75                 (cert->valid_start() - base::Time::Now()).InDays()));
76         short_description =
77             l10n_util::GetStringUTF16(IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION);
78       } else {
79         // Two possibilities: (1) an intermediate or root certificate has
80         // expired, or (2) the certificate has become valid since the error
81         // occurred. Since (1) is more likely, assume that's the case.
82         details = l10n_util::GetStringFUTF16(
83             IDS_CERT_ERROR_CHAIN_EXPIRED_DETAILS,
84             UTF8ToUTF16(request_url.host()),
85             base::TimeFormatFriendlyDate(base::Time::Now()));
86         short_description =
87             l10n_util::GetStringUTF16(IDS_CERT_ERROR_CHAIN_EXPIRED_DESCRIPTION);
88       }
89       break;
90     case CERT_AUTHORITY_INVALID:
91       details = l10n_util::GetStringFUTF16(
92           IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS,
93           UTF8ToUTF16(request_url.host()));
94       short_description = l10n_util::GetStringUTF16(
95           IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION);
96       break;
97     case CERT_CONTAINS_ERRORS:
98       details = l10n_util::GetStringFUTF16(
99           IDS_CERT_ERROR_CONTAINS_ERRORS_DETAILS,
100           UTF8ToUTF16(request_url.host()));
101       short_description =
102           l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION);
103       break;
104     case CERT_NO_REVOCATION_MECHANISM:
105       details = l10n_util::GetStringUTF16(
106           IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS);
107       short_description = l10n_util::GetStringUTF16(
108           IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION);
109       break;
110     case CERT_REVOKED:
111       details = l10n_util::GetStringFUTF16(IDS_CERT_ERROR_REVOKED_CERT_DETAILS,
112                                            UTF8ToUTF16(request_url.host()));
113       short_description =
114           l10n_util::GetStringUTF16(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION);
115       break;
116     case CERT_INVALID:
117       details = l10n_util::GetStringFUTF16(
118           IDS_CERT_ERROR_INVALID_CERT_DETAILS,
119           UTF8ToUTF16(request_url.host()));
120       short_description =
121           l10n_util::GetStringUTF16(IDS_CERT_ERROR_INVALID_CERT_DESCRIPTION);
122       break;
123     case CERT_WEAK_SIGNATURE_ALGORITHM:
124       details = l10n_util::GetStringFUTF16(
125           IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DETAILS,
126           UTF8ToUTF16(request_url.host()));
127       short_description = l10n_util::GetStringUTF16(
128           IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DESCRIPTION);
129       break;
130     case CERT_WEAK_KEY:
131       details = l10n_util::GetStringFUTF16(
132           IDS_CERT_ERROR_WEAK_KEY_DETAILS, UTF8ToUTF16(request_url.host()));
133       short_description = l10n_util::GetStringUTF16(
134           IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION);
135       break;
136     case CERT_WEAK_KEY_DH:
137       details = l10n_util::GetStringFUTF16(
138           IDS_CERT_ERROR_WEAK_KEY_DETAILS, UTF8ToUTF16(request_url.host()));
139       short_description = l10n_util::GetStringUTF16(
140           IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION);
141     case CERT_NAME_CONSTRAINT_VIOLATION:
142       details = l10n_util::GetStringFUTF16(
143           IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DETAILS,
144           UTF8ToUTF16(request_url.host()));
145       short_description = l10n_util::GetStringUTF16(
146           IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION);
147       break;
148     case CERT_PINNED_KEY_MISSING:
149       details = l10n_util::GetStringUTF16(
150           IDS_ERRORPAGES_SUMMARY_PINNING_FAILURE);
151       short_description = l10n_util::GetStringUTF16(
152           IDS_ERRORPAGES_DETAILS_PINNING_FAILURE);
153       break;
154     case UNKNOWN:
155       details = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS);
156       short_description =
157           l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION);
158       break;
159     case CERT_UNABLE_TO_CHECK_REVOCATION:  // Deprecated.
160     default:
161       NOTREACHED();
162   }
163   return SSLErrorInfo(details, short_description);
164 }
165
166 SSLErrorInfo::~SSLErrorInfo() {
167 }
168
169 // static
170 SSLErrorInfo::ErrorType SSLErrorInfo::NetErrorToErrorType(int net_error) {
171   switch (net_error) {
172     case net::ERR_CERT_COMMON_NAME_INVALID:
173       return CERT_COMMON_NAME_INVALID;
174     case net::ERR_CERT_DATE_INVALID:
175       return CERT_DATE_INVALID;
176     case net::ERR_CERT_AUTHORITY_INVALID:
177       return CERT_AUTHORITY_INVALID;
178     case net::ERR_CERT_CONTAINS_ERRORS:
179       return CERT_CONTAINS_ERRORS;
180     case net::ERR_CERT_NO_REVOCATION_MECHANISM:
181       return CERT_NO_REVOCATION_MECHANISM;
182     case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
183       return CERT_UNABLE_TO_CHECK_REVOCATION;
184     case net::ERR_CERT_REVOKED:
185       return CERT_REVOKED;
186     case net::ERR_CERT_INVALID:
187       return CERT_INVALID;
188     case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
189       return CERT_WEAK_SIGNATURE_ALGORITHM;
190     case net::ERR_CERT_WEAK_KEY:
191       return CERT_WEAK_KEY;
192     case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
193       return CERT_NAME_CONSTRAINT_VIOLATION;
194     case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
195       return CERT_WEAK_KEY_DH;
196     case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
197       return CERT_PINNED_KEY_MISSING;
198     default:
199       NOTREACHED();
200       return UNKNOWN;
201     }
202 }
203
204 // static
205 int SSLErrorInfo::GetErrorsForCertStatus(int cert_id,
206                                          net::CertStatus cert_status,
207                                          const GURL& url,
208                                          std::vector<SSLErrorInfo>* errors) {
209   const net::CertStatus kErrorFlags[] = {
210     net::CERT_STATUS_COMMON_NAME_INVALID,
211     net::CERT_STATUS_DATE_INVALID,
212     net::CERT_STATUS_AUTHORITY_INVALID,
213     net::CERT_STATUS_NO_REVOCATION_MECHANISM,
214     net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
215     net::CERT_STATUS_REVOKED,
216     net::CERT_STATUS_INVALID,
217     net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM,
218     net::CERT_STATUS_WEAK_KEY,
219     net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION,
220   };
221
222   const ErrorType kErrorTypes[] = {
223     CERT_COMMON_NAME_INVALID,
224     CERT_DATE_INVALID,
225     CERT_AUTHORITY_INVALID,
226     CERT_NO_REVOCATION_MECHANISM,
227     CERT_UNABLE_TO_CHECK_REVOCATION,
228     CERT_REVOKED,
229     CERT_INVALID,
230     CERT_WEAK_SIGNATURE_ALGORITHM,
231     CERT_WEAK_KEY,
232     CERT_NAME_CONSTRAINT_VIOLATION,
233   };
234   DCHECK(arraysize(kErrorFlags) == arraysize(kErrorTypes));
235
236   scoped_refptr<net::X509Certificate> cert = NULL;
237   int count = 0;
238   for (size_t i = 0; i < arraysize(kErrorFlags); ++i) {
239     if (cert_status & kErrorFlags[i]) {
240       count++;
241       if (!cert.get()) {
242         bool r = content::CertStore::GetInstance()->RetrieveCert(
243             cert_id, &cert);
244         DCHECK(r);
245       }
246       if (errors)
247         errors->push_back(
248             SSLErrorInfo::CreateError(kErrorTypes[i], cert.get(), url));
249     }
250   }
251   return count;
252 }