Chromium Code Reviews| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 255 } | 255 } |
| 256 default_ssl_cert_decision_expiration_delta_ = | 256 default_ssl_cert_decision_expiration_delta_ = |
| 257 base::TimeDelta::FromSeconds(expiration_delta); | 257 base::TimeDelta::FromSeconds(expiration_delta); |
| 258 } | 258 } |
| 259 | 259 |
| 260 ChromeSSLHostStateDelegate::~ChromeSSLHostStateDelegate() { | 260 ChromeSSLHostStateDelegate::~ChromeSSLHostStateDelegate() { |
| 261 if (should_remember_ssl_decisions_ == ForgetSSLExceptionDecisionsAtSessionEnd) | 261 if (should_remember_ssl_decisions_ == ForgetSSLExceptionDecisionsAtSessionEnd) |
| 262 Clear(); | 262 Clear(); |
| 263 } | 263 } |
| 264 | 264 |
| 265 void ChromeSSLHostStateDelegate::DenyCert(const std::string& host, | |
| 266 net::X509Certificate* cert, | |
| 267 net::CertStatus error) { | |
| 268 ChangeCertPolicy(host, cert, error, net::CertPolicy::DENIED); | |
| 269 } | |
| 270 | |
| 271 void ChromeSSLHostStateDelegate::AllowCert(const std::string& host, | 265 void ChromeSSLHostStateDelegate::AllowCert(const std::string& host, |
| 272 net::X509Certificate* cert, | 266 net::X509Certificate* cert, |
| 273 net::CertStatus error) { | 267 net::CertStatus error) { |
| 274 ChangeCertPolicy(host, cert, error, net::CertPolicy::ALLOWED); | 268 GURL url = GetSecureGURLForHost(host); |
| 269 const ContentSettingsPattern pattern = | |
| 270 ContentSettingsPattern::FromURLNoWildcard(url); | |
| 271 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | |
| 272 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | |
| 273 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | |
| 274 | |
| 275 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | |
| 276 value.reset(new base::DictionaryValue()); | |
| 277 | |
| 278 base::DictionaryValue* dict; | |
| 279 bool success = value->GetAsDictionary(&dict); | |
| 280 DCHECK(success); | |
| 281 | |
| 282 bool expired_previous_decision; // unused value in this function | |
| 283 base::DictionaryValue* cert_dict = GetValidCertDecisionsDict( | |
| 284 dict, CreateDictionaryEntries, &expired_previous_decision); | |
| 285 // If a a valid certificate dictionary cannot be extracted from the content | |
| 286 // setting, that means it's in an unknown format. Unfortunately, there's | |
| 287 // nothing to be done in that case, so a silent fail is the only option. | |
| 288 if (!cert_dict) | |
| 289 return; | |
| 290 | |
| 291 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, | |
| 292 kDefaultSSLCertDecisionVersion); | |
| 293 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), | |
| 294 net::CertPolicy::ALLOWED); | |
| 295 | |
| 296 // The map takes ownership of the value, so it is released in the call to | |
| 297 // SetWebsiteSetting. | |
| 298 map->SetWebsiteSetting(pattern, | |
| 299 pattern, | |
| 300 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, | |
| 301 std::string(), | |
| 302 value.release()); | |
| 275 } | 303 } |
| 276 | 304 |
| 277 void ChromeSSLHostStateDelegate::Clear() { | 305 void ChromeSSLHostStateDelegate::Clear() { |
| 278 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( | 306 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( |
| 279 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); | 307 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); |
| 280 } | 308 } |
| 281 | 309 |
| 282 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( | 310 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( |
| 283 const std::string& host, | 311 const std::string& host, |
| 284 net::X509Certificate* cert, | 312 net::X509Certificate* cert, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 307 // This revoke is necessary to clear any old expired setting that may | 335 // This revoke is necessary to clear any old expired setting that may |
| 308 // lingering in the case that an old decision expried. | 336 // lingering in the case that an old decision expried. |
| 309 RevokeUserDecisions(host); | 337 RevokeUserDecisions(host); |
| 310 return net::CertPolicy::UNKNOWN; | 338 return net::CertPolicy::UNKNOWN; |
| 311 } | 339 } |
| 312 | 340 |
| 313 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), | 341 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), |
| 314 &policy_decision); | 342 &policy_decision); |
| 315 | 343 |
| 316 // If a policy decision was successfully retrieved and it's a valid value of | 344 // If a policy decision was successfully retrieved and it's a valid value of |
| 317 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. | 345 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. Since |
| 346 // the UI does not provide a way to deny certs and any DENIED value must have | |
| 347 // come from an external source, such as manually modifying the prefs file, | |
| 348 // Chrome we treats DENIED values as UNKNOWN. | |
|
Peter Kasting
2014/08/22 00:57:52
Can we get rid of the concept of a DENIED value?
jww
2014/08/22 03:49:35
I don't think so; they're used by net/. We could m
| |
| 318 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) | 349 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) |
| 319 return net::CertPolicy::Judgment::ALLOWED; | 350 return net::CertPolicy::Judgment::ALLOWED; |
| 320 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED) | |
| 321 return net::CertPolicy::Judgment::DENIED; | |
| 322 | 351 |
| 323 return net::CertPolicy::Judgment::UNKNOWN; | 352 return net::CertPolicy::Judgment::UNKNOWN; |
| 324 } | 353 } |
| 325 | 354 |
| 326 void ChromeSSLHostStateDelegate::RevokeUserDecisions(const std::string& host) { | 355 void ChromeSSLHostStateDelegate::RevokeUserDecisions(const std::string& host) { |
| 327 GURL url = GetSecureGURLForHost(host); | 356 GURL url = GetSecureGURLForHost(host); |
| 328 const ContentSettingsPattern pattern = | 357 const ContentSettingsPattern pattern = |
| 329 ContentSettingsPattern::FromURLNoWildcard(url); | 358 ContentSettingsPattern::FromURLNoWildcard(url); |
| 330 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | 359 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
| 331 | 360 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 353 // idle sockets. | 382 // idle sockets. |
| 354 void ChromeSSLHostStateDelegate::RevokeUserDecisionsHard( | 383 void ChromeSSLHostStateDelegate::RevokeUserDecisionsHard( |
| 355 const std::string& host) { | 384 const std::string& host) { |
| 356 RevokeUserDecisions(host); | 385 RevokeUserDecisions(host); |
| 357 scoped_refptr<net::URLRequestContextGetter> getter( | 386 scoped_refptr<net::URLRequestContextGetter> getter( |
| 358 profile_->GetRequestContext()); | 387 profile_->GetRequestContext()); |
| 359 profile_->GetRequestContext()->GetNetworkTaskRunner()->PostTask( | 388 profile_->GetRequestContext()->GetNetworkTaskRunner()->PostTask( |
| 360 FROM_HERE, base::Bind(&CloseIdleConnections, getter)); | 389 FROM_HERE, base::Bind(&CloseIdleConnections, getter)); |
| 361 } | 390 } |
| 362 | 391 |
| 363 bool ChromeSSLHostStateDelegate::HasUserDecision(const std::string& host) { | 392 bool ChromeSSLHostStateDelegate::HasAllowed(const std::string& host) { |
| 364 GURL url = GetSecureGURLForHost(host); | 393 GURL url = GetSecureGURLForHost(host); |
| 365 const ContentSettingsPattern pattern = | 394 const ContentSettingsPattern pattern = |
| 366 ContentSettingsPattern::FromURLNoWildcard(url); | 395 ContentSettingsPattern::FromURLNoWildcard(url); |
| 367 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | 396 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
| 368 | 397 |
| 369 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | 398 scoped_ptr<base::Value> value(map->GetWebsiteSetting( |
| 370 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | 399 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); |
| 371 | 400 |
| 372 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | 401 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) |
| 373 return false; | 402 return false; |
| 374 | 403 |
| 375 base::DictionaryValue* dict; // Owned by value | 404 base::DictionaryValue* dict; // Owned by value |
| 376 bool success = value->GetAsDictionary(&dict); | 405 bool success = value->GetAsDictionary(&dict); |
| 377 DCHECK(success); | 406 DCHECK(success); |
| 378 | 407 |
| 379 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { | 408 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { |
| 380 int policy_decision; // Owned by dict | 409 int policy_decision; // Owned by dict |
| 381 success = it.value().GetAsInteger(&policy_decision); | 410 success = it.value().GetAsInteger(&policy_decision); |
| 382 if (success && (static_cast<net::CertPolicy::Judgment>(policy_decision) != | 411 if (success && (static_cast<net::CertPolicy::Judgment>(policy_decision) == |
| 383 net::CertPolicy::UNKNOWN)) | 412 net::CertPolicy::ALLOWED)) |
| 384 return true; | 413 return true; |
| 385 } | 414 } |
| 386 | 415 |
| 387 return false; | 416 return false; |
| 388 } | 417 } |
| 389 | 418 |
| 390 void ChromeSSLHostStateDelegate::HostRanInsecureContent(const std::string& host, | 419 void ChromeSSLHostStateDelegate::HostRanInsecureContent(const std::string& host, |
| 391 int pid) { | 420 int pid) { |
| 392 ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid)); | 421 ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid)); |
| 393 } | 422 } |
| 394 | 423 |
| 395 bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent( | 424 bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent( |
| 396 const std::string& host, | 425 const std::string& host, |
| 397 int pid) const { | 426 int pid) const { |
| 398 return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid)); | 427 return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid)); |
| 399 } | 428 } |
| 400 void ChromeSSLHostStateDelegate::SetClock(scoped_ptr<base::Clock> clock) { | 429 void ChromeSSLHostStateDelegate::SetClock(scoped_ptr<base::Clock> clock) { |
| 401 clock_.reset(clock.release()); | 430 clock_.reset(clock.release()); |
| 402 } | 431 } |
| 403 | |
| 404 void ChromeSSLHostStateDelegate::ChangeCertPolicy( | |
| 405 const std::string& host, | |
| 406 net::X509Certificate* cert, | |
| 407 net::CertStatus error, | |
| 408 net::CertPolicy::Judgment judgment) { | |
| 409 GURL url = GetSecureGURLForHost(host); | |
| 410 const ContentSettingsPattern pattern = | |
| 411 ContentSettingsPattern::FromURLNoWildcard(url); | |
| 412 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | |
| 413 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | |
| 414 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | |
| 415 | |
| 416 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | |
| 417 value.reset(new base::DictionaryValue()); | |
| 418 | |
| 419 base::DictionaryValue* dict; | |
| 420 bool success = value->GetAsDictionary(&dict); | |
| 421 DCHECK(success); | |
| 422 | |
| 423 bool expired_previous_decision; // unused value in this function | |
| 424 base::DictionaryValue* cert_dict = GetValidCertDecisionsDict( | |
| 425 dict, CreateDictionaryEntries, &expired_previous_decision); | |
| 426 // If a a valid certificate dictionary cannot be extracted from the content | |
| 427 // setting, that means it's in an unknown format. Unfortunately, there's | |
| 428 // nothing to be done in that case, so a silent fail is the only option. | |
| 429 if (!cert_dict) | |
| 430 return; | |
| 431 | |
| 432 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, | |
| 433 kDefaultSSLCertDecisionVersion); | |
| 434 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), judgment); | |
| 435 | |
| 436 // The map takes ownership of the value, so it is released in the call to | |
| 437 // SetWebsiteSetting. | |
| 438 map->SetWebsiteSetting(pattern, | |
| 439 pattern, | |
| 440 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, | |
| 441 std::string(), | |
| 442 value.release()); | |
| 443 } | |
| OLD | NEW |