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, return the valid value. Otherwise, return UNKNOWN. Since the UI |
| 346 // does not provide a way to deny certs and any DENIED value must have come |
| 347 // from an external source, such as manually modifying the prefs file, Chrome |
| 348 // we treats DENIED values as UNKNOWN. |
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 |