| 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 |