OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" | 5 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 // argument dict that is passed in. | 140 // argument dict that is passed in. |
141 // | 141 // |
142 // If create_entries is set to |DoNotCreateDictionaryEntries|, | 142 // If create_entries is set to |DoNotCreateDictionaryEntries|, |
143 // GetValidCertDecisionsDict will return NULL if there is anything invalid about | 143 // GetValidCertDecisionsDict will return NULL if there is anything invalid about |
144 // the setting, such as an invalid version or invalid value types (in addition | 144 // the setting, such as an invalid version or invalid value types (in addition |
145 // to there not be any values in the dictionary). If create_entries is set to | 145 // to there not be any values in the dictionary). If create_entries is set to |
146 // |CreateDictionaryEntries|, if no dictionary is found or the decisions are | 146 // |CreateDictionaryEntries|, if no dictionary is found or the decisions are |
147 // expired, a new dictionary will be created | 147 // expired, a new dictionary will be created |
148 base::DictionaryValue* ChromeSSLHostStateDelegate::GetValidCertDecisionsDict( | 148 base::DictionaryValue* ChromeSSLHostStateDelegate::GetValidCertDecisionsDict( |
149 base::DictionaryValue* dict, | 149 base::DictionaryValue* dict, |
150 CreateDictionaryEntriesDisposition create_entries) { | 150 CreateDictionaryEntriesDisposition create_entries, |
| 151 bool* expired_previous_decision) { |
| 152 // This needs to be done first in case the method is short circuited by an |
| 153 // early failure. |
| 154 *expired_previous_decision = false; |
| 155 |
151 // Extract the version of the certificate decision structure from the content | 156 // Extract the version of the certificate decision structure from the content |
152 // setting. | 157 // setting. |
153 int version; | 158 int version; |
154 bool success = dict->GetInteger(kSSLCertDecisionVersionKey, &version); | 159 bool success = dict->GetInteger(kSSLCertDecisionVersionKey, &version); |
155 if (!success) { | 160 if (!success) { |
156 if (create_entries == DoNotCreateDictionaryEntries) | 161 if (create_entries == DoNotCreateDictionaryEntries) |
157 return NULL; | 162 return NULL; |
158 | 163 |
159 dict->SetInteger(kSSLCertDecisionVersionKey, | 164 dict->SetInteger(kSSLCertDecisionVersionKey, |
160 kDefaultSSLCertDecisionVersion); | 165 kDefaultSSLCertDecisionVersion); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } | 200 } |
196 | 201 |
197 // Check to see if the user's certificate decision has expired. | 202 // Check to see if the user's certificate decision has expired. |
198 // - Expired and |create_entries| is DoNotCreateDictionaryEntries, return | 203 // - Expired and |create_entries| is DoNotCreateDictionaryEntries, return |
199 // NULL. | 204 // NULL. |
200 // - Expired and |create_entries| is CreateDictionaryEntries, update the | 205 // - Expired and |create_entries| is CreateDictionaryEntries, update the |
201 // expiration time. | 206 // expiration time. |
202 if (should_remember_ssl_decisions_ != | 207 if (should_remember_ssl_decisions_ != |
203 ForgetSSLExceptionDecisionsAtSessionEnd && | 208 ForgetSSLExceptionDecisionsAtSessionEnd && |
204 decision_expiration.ToInternalValue() <= now.ToInternalValue()) { | 209 decision_expiration.ToInternalValue() <= now.ToInternalValue()) { |
| 210 *expired_previous_decision = true; |
| 211 |
205 if (create_entries == DoNotCreateDictionaryEntries) | 212 if (create_entries == DoNotCreateDictionaryEntries) |
206 return NULL; | 213 return NULL; |
207 | 214 |
208 expired = true; | 215 expired = true; |
209 | |
210 base::Time expiration_time = | 216 base::Time expiration_time = |
211 now + default_ssl_cert_decision_expiration_delta_; | 217 now + default_ssl_cert_decision_expiration_delta_; |
212 // Unfortunately, JSON (and thus content settings) doesn't support int64 | 218 // Unfortunately, JSON (and thus content settings) doesn't support int64 |
213 // values, only doubles. Since this mildly depends on precision, it is | 219 // values, only doubles. Since this mildly depends on precision, it is |
214 // better to store the value as a string. | 220 // better to store the value as a string. |
215 dict->SetString(kSSLCertDecisionExpirationTimeKey, | 221 dict->SetString(kSSLCertDecisionExpirationTimeKey, |
216 base::Int64ToString(expiration_time.ToInternalValue())); | 222 base::Int64ToString(expiration_time.ToInternalValue())); |
217 } | 223 } |
218 | 224 |
219 // Extract the map of certificate fingerprints to errors from the setting. | 225 // Extract the map of certificate fingerprints to errors from the setting. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 } | 275 } |
270 | 276 |
271 void ChromeSSLHostStateDelegate::Clear() { | 277 void ChromeSSLHostStateDelegate::Clear() { |
272 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( | 278 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( |
273 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); | 279 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); |
274 } | 280 } |
275 | 281 |
276 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( | 282 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( |
277 const std::string& host, | 283 const std::string& host, |
278 net::X509Certificate* cert, | 284 net::X509Certificate* cert, |
279 net::CertStatus error) { | 285 net::CertStatus error, |
| 286 bool* expired_previous_decision) { |
280 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | 287 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
281 GURL url = GetSecureGURLForHost(host); | 288 GURL url = GetSecureGURLForHost(host); |
282 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | 289 scoped_ptr<base::Value> value(map->GetWebsiteSetting( |
283 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | 290 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); |
284 | 291 |
| 292 // Set a default value in case this method is short circuited and doesn't do a |
| 293 // full query. |
| 294 *expired_previous_decision = false; |
285 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | 295 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) |
286 return net::CertPolicy::UNKNOWN; | 296 return net::CertPolicy::UNKNOWN; |
287 | 297 |
288 base::DictionaryValue* dict; // Owned by value | 298 base::DictionaryValue* dict; // Owned by value |
289 int policy_decision; | 299 int policy_decision; |
290 bool success = value->GetAsDictionary(&dict); | 300 bool success = value->GetAsDictionary(&dict); |
291 DCHECK(success); | 301 DCHECK(success); |
292 | 302 |
293 base::DictionaryValue* cert_error_dict; // Owned by value | 303 base::DictionaryValue* cert_error_dict; // Owned by value |
294 cert_error_dict = | 304 cert_error_dict = GetValidCertDecisionsDict( |
295 GetValidCertDecisionsDict(dict, DoNotCreateDictionaryEntries); | 305 dict, DoNotCreateDictionaryEntries, expired_previous_decision); |
296 if (!cert_error_dict) | 306 if (!cert_error_dict) { |
| 307 // This revoke is necessary to clear any old expired setting that may |
| 308 // lingering in the case that an old decision expried. |
| 309 RevokeUserDecisions(host); |
297 return net::CertPolicy::UNKNOWN; | 310 return net::CertPolicy::UNKNOWN; |
| 311 } |
298 | 312 |
299 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), | 313 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), |
300 &policy_decision); | 314 &policy_decision); |
301 | 315 |
302 // If a policy decision was successfully retrieved and it's a valid value of | 316 // If a policy decision was successfully retrieved and it's a valid value of |
303 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. | 317 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. |
304 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) | 318 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) |
305 return net::CertPolicy::Judgment::ALLOWED; | 319 return net::CertPolicy::Judgment::ALLOWED; |
306 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED) | 320 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED) |
307 return net::CertPolicy::Judgment::DENIED; | 321 return net::CertPolicy::Judgment::DENIED; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | 413 scoped_ptr<base::Value> value(map->GetWebsiteSetting( |
400 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | 414 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); |
401 | 415 |
402 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | 416 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) |
403 value.reset(new base::DictionaryValue()); | 417 value.reset(new base::DictionaryValue()); |
404 | 418 |
405 base::DictionaryValue* dict; | 419 base::DictionaryValue* dict; |
406 bool success = value->GetAsDictionary(&dict); | 420 bool success = value->GetAsDictionary(&dict); |
407 DCHECK(success); | 421 DCHECK(success); |
408 | 422 |
409 base::DictionaryValue* cert_dict = | 423 bool expired_previous_decision; // unused value in this function |
410 GetValidCertDecisionsDict(dict, CreateDictionaryEntries); | 424 base::DictionaryValue* cert_dict = GetValidCertDecisionsDict( |
| 425 dict, CreateDictionaryEntries, &expired_previous_decision); |
411 // If a a valid certificate dictionary cannot be extracted from the content | 426 // If a a valid certificate dictionary cannot be extracted from the content |
412 // setting, that means it's in an unknown format. Unfortunately, there's | 427 // setting, that means it's in an unknown format. Unfortunately, there's |
413 // nothing to be done in that case, so a silent fail is the only option. | 428 // nothing to be done in that case, so a silent fail is the only option. |
414 if (!cert_dict) | 429 if (!cert_dict) |
415 return; | 430 return; |
416 | 431 |
417 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, | 432 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, |
418 kDefaultSSLCertDecisionVersion); | 433 kDefaultSSLCertDecisionVersion); |
419 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), judgment); | 434 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), judgment); |
420 | 435 |
421 // The map takes ownership of the value, so it is released in the call to | 436 // The map takes ownership of the value, so it is released in the call to |
422 // SetWebsiteSetting. | 437 // SetWebsiteSetting. |
423 map->SetWebsiteSetting(pattern, | 438 map->SetWebsiteSetting(pattern, |
424 pattern, | 439 pattern, |
425 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, | 440 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, |
426 std::string(), | 441 std::string(), |
427 value.release()); | 442 value.release()); |
428 } | 443 } |
OLD | NEW |