Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(759)

Side by Side Diff: chrome/browser/ssl/chrome_ssl_host_state_delegate.cc

Issue 465133004: Remove DenyCertForHost from SSLHostStateDelegate API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed UNKNOWN and CertPolicy Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 20 matching lines...) Expand all
31 // the end of the current session. 31 // the end of the current session.
32 const int64 kForgetAtSessionEndSwitchValue = -1; 32 const int64 kForgetAtSessionEndSwitchValue = -1;
33 33
34 // Experiment information 34 // Experiment information
35 const char kRememberCertificateErrorDecisionsFieldTrialName[] = 35 const char kRememberCertificateErrorDecisionsFieldTrialName[] =
36 "RememberCertificateErrorDecisions"; 36 "RememberCertificateErrorDecisions";
37 const char kRememberCertificateErrorDecisionsFieldTrialDefaultGroup[] = 37 const char kRememberCertificateErrorDecisionsFieldTrialDefaultGroup[] =
38 "Default"; 38 "Default";
39 const char kRememberCertificateErrorDecisionsFieldTrialLengthParam[] = "length"; 39 const char kRememberCertificateErrorDecisionsFieldTrialLengthParam[] = "length";
40 40
41 // Keys for the per-site error + certificate finger to judgement content 41 // Keys for the per-site error + certificate finger to judgment content
42 // settings map. 42 // settings map.
43 const char kSSLCertDecisionCertErrorMapKey[] = "cert_exceptions_map"; 43 const char kSSLCertDecisionCertErrorMapKey[] = "cert_exceptions_map";
44 const char kSSLCertDecisionExpirationTimeKey[] = "decision_expiration_time"; 44 const char kSSLCertDecisionExpirationTimeKey[] = "decision_expiration_time";
45 const char kSSLCertDecisionVersionKey[] = "version"; 45 const char kSSLCertDecisionVersionKey[] = "version";
46 46
47 const int kDefaultSSLCertDecisionVersion = 1; 47 const int kDefaultSSLCertDecisionVersion = 1;
48 48
49 // Closes all idle network connections for the given URLRequestContext. This is 49 // Closes all idle network connections for the given URLRequestContext. This is
50 // a big hammer and should be wielded with extreme caution as it can have a big, 50 // a big hammer and should be wielded with extreme caution as it can have a big,
51 // negative impact on network performance. In this case, it is used by 51 // negative impact on network performance. In this case, it is used by
52 // RevokeUserDecisionsHard, which should only be called by rare, user initiated 52 // RevokeUserAllowExceptionsHard, which should only be called by rare, user
53 // events. See the comment before RevokeUserDecisionsHard implementation for 53 // initiated events. See the comment before RevokeUserAllowExceptionsHard
54 // more information. 54 // implementation for more information.
55 void CloseIdleConnections( 55 void CloseIdleConnections(
56 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) { 56 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
57 url_request_context_getter-> 57 url_request_context_getter->
58 GetURLRequestContext()-> 58 GetURLRequestContext()->
59 http_transaction_factory()-> 59 http_transaction_factory()->
60 GetSession()-> 60 GetSession()->
61 CloseIdleConnections(); 61 CloseIdleConnections();
62 } 62 }
63 63
64 // All SSL decisions are per host (and are shared arcoss schemes), so this 64 // All SSL decisions are per host (and are shared arcoss schemes), so this
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
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), ALLOWED);
294
295 // The map takes ownership of the value, so it is released in the call to
296 // SetWebsiteSetting.
297 map->SetWebsiteSetting(pattern,
298 pattern,
299 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS,
300 std::string(),
301 value.release());
275 } 302 }
276 303
277 void ChromeSSLHostStateDelegate::Clear() { 304 void ChromeSSLHostStateDelegate::Clear() {
278 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( 305 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType(
279 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); 306 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS);
280 } 307 }
281 308
282 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( 309 content::SSLHostStateDelegate::CertJudgment
283 const std::string& host, 310 ChromeSSLHostStateDelegate::QueryPolicy(const std::string& host,
284 net::X509Certificate* cert, 311 net::X509Certificate* cert,
285 net::CertStatus error, 312 net::CertStatus error,
286 bool* expired_previous_decision) { 313 bool* expired_previous_decision) {
287 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); 314 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
288 GURL url = GetSecureGURLForHost(host); 315 GURL url = GetSecureGURLForHost(host);
289 scoped_ptr<base::Value> value(map->GetWebsiteSetting( 316 scoped_ptr<base::Value> value(map->GetWebsiteSetting(
290 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); 317 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL));
291 318
292 // Set a default value in case this method is short circuited and doesn't do a 319 // Set a default value in case this method is short circuited and doesn't do a
293 // full query. 320 // full query.
294 *expired_previous_decision = false; 321 *expired_previous_decision = false;
295 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) 322 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY))
296 return net::CertPolicy::UNKNOWN; 323 return DENIED;
297 324
298 base::DictionaryValue* dict; // Owned by value 325 base::DictionaryValue* dict; // Owned by value
299 int policy_decision; 326 int policy_decision;
300 bool success = value->GetAsDictionary(&dict); 327 bool success = value->GetAsDictionary(&dict);
301 DCHECK(success); 328 DCHECK(success);
302 329
303 base::DictionaryValue* cert_error_dict; // Owned by value 330 base::DictionaryValue* cert_error_dict; // Owned by value
304 cert_error_dict = GetValidCertDecisionsDict( 331 cert_error_dict = GetValidCertDecisionsDict(
305 dict, DoNotCreateDictionaryEntries, expired_previous_decision); 332 dict, DoNotCreateDictionaryEntries, expired_previous_decision);
306 if (!cert_error_dict) { 333 if (!cert_error_dict) {
307 // This revoke is necessary to clear any old expired setting that may 334 // This revoke is necessary to clear any old expired setting that may
308 // lingering in the case that an old decision expried. 335 // lingering in the case that an old decision expried.
309 RevokeUserDecisions(host); 336 RevokeUserAllowExceptions(host);
310 return net::CertPolicy::UNKNOWN; 337 return DENIED;
311 } 338 }
312 339
313 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), 340 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error),
314 &policy_decision); 341 &policy_decision);
315 342
316 // If a policy decision was successfully retrieved and it's a valid value of 343 // 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. 344 // ALLOWED, return the valid value. Otherwise, return DENIED.
318 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) 345 if (success && policy_decision == ALLOWED)
319 return net::CertPolicy::Judgment::ALLOWED; 346 return ALLOWED;
320 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED)
321 return net::CertPolicy::Judgment::DENIED;
322 347
323 return net::CertPolicy::Judgment::UNKNOWN; 348 return DENIED;
324 } 349 }
325 350
326 void ChromeSSLHostStateDelegate::RevokeUserDecisions(const std::string& host) { 351 void ChromeSSLHostStateDelegate::RevokeUserAllowExceptions(
352 const std::string& host) {
327 GURL url = GetSecureGURLForHost(host); 353 GURL url = GetSecureGURLForHost(host);
328 const ContentSettingsPattern pattern = 354 const ContentSettingsPattern pattern =
329 ContentSettingsPattern::FromURLNoWildcard(url); 355 ContentSettingsPattern::FromURLNoWildcard(url);
330 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); 356 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
331 357
332 map->SetWebsiteSetting(pattern, 358 map->SetWebsiteSetting(pattern,
333 pattern, 359 pattern,
334 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, 360 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS,
335 std::string(), 361 std::string(),
336 NULL); 362 NULL);
337 } 363 }
338 364
339 // TODO(jww): This will revoke all of the decisions in the browser context. 365 // TODO(jww): This will revoke all of the decisions in the browser context.
340 // However, the networking stack actually keeps track of its own list of 366 // However, the networking stack actually keeps track of its own list of
341 // exceptions per-HttpNetworkTransaction in the SSLConfig structure (see the 367 // exceptions per-HttpNetworkTransaction in the SSLConfig structure (see the
342 // allowed_bad_certs Vector in net/ssl/ssl_config.h). This dual-tracking of 368 // allowed_bad_certs Vector in net/ssl/ssl_config.h). This dual-tracking of
343 // exceptions introduces a problem where the browser context can revoke a 369 // exceptions introduces a problem where the browser context can revoke a
344 // certificate, but if a transaction reuses a cached version of the SSLConfig 370 // certificate, but if a transaction reuses a cached version of the SSLConfig
345 // (probably from a pooled socket), it may bypass the intestitial layer. 371 // (probably from a pooled socket), it may bypass the intestitial layer.
346 // 372 //
347 // Over time, the cached versions should expire and it should converge on 373 // Over time, the cached versions should expire and it should converge on
348 // showing the interstitial. We probably need to introduce into the networking 374 // showing the interstitial. We probably need to introduce into the networking
349 // stack a way revoke SSLConfig's allowed_bad_certs lists per socket. 375 // stack a way revoke SSLConfig's allowed_bad_certs lists per socket.
350 // 376 //
351 // For now, RevokeUserDecisionsHard is our solution for the rare case where it 377 // For now, RevokeUserAllowExceptionsHard is our solution for the rare case
378 // where it
352 // is necessary to revoke the preferences immediately. It does so by flushing 379 // is necessary to revoke the preferences immediately. It does so by flushing
353 // idle sockets. 380 // idle sockets.
354 void ChromeSSLHostStateDelegate::RevokeUserDecisionsHard( 381 void ChromeSSLHostStateDelegate::RevokeUserAllowExceptionsHard(
355 const std::string& host) { 382 const std::string& host) {
356 RevokeUserDecisions(host); 383 RevokeUserAllowExceptions(host);
357 scoped_refptr<net::URLRequestContextGetter> getter( 384 scoped_refptr<net::URLRequestContextGetter> getter(
358 profile_->GetRequestContext()); 385 profile_->GetRequestContext());
359 profile_->GetRequestContext()->GetNetworkTaskRunner()->PostTask( 386 profile_->GetRequestContext()->GetNetworkTaskRunner()->PostTask(
360 FROM_HERE, base::Bind(&CloseIdleConnections, getter)); 387 FROM_HERE, base::Bind(&CloseIdleConnections, getter));
361 } 388 }
362 389
363 bool ChromeSSLHostStateDelegate::HasUserDecision(const std::string& host) { 390 bool ChromeSSLHostStateDelegate::HasAllowed(const std::string& host) {
364 GURL url = GetSecureGURLForHost(host); 391 GURL url = GetSecureGURLForHost(host);
365 const ContentSettingsPattern pattern = 392 const ContentSettingsPattern pattern =
366 ContentSettingsPattern::FromURLNoWildcard(url); 393 ContentSettingsPattern::FromURLNoWildcard(url);
367 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); 394 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
368 395
369 scoped_ptr<base::Value> value(map->GetWebsiteSetting( 396 scoped_ptr<base::Value> value(map->GetWebsiteSetting(
370 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); 397 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL));
371 398
372 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) 399 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY))
373 return false; 400 return false;
374 401
375 base::DictionaryValue* dict; // Owned by value 402 base::DictionaryValue* dict; // Owned by value
376 bool success = value->GetAsDictionary(&dict); 403 bool success = value->GetAsDictionary(&dict);
377 DCHECK(success); 404 DCHECK(success);
378 405
379 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { 406 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
380 int policy_decision; // Owned by dict 407 int policy_decision; // Owned by dict
381 success = it.value().GetAsInteger(&policy_decision); 408 success = it.value().GetAsInteger(&policy_decision);
382 if (success && (static_cast<net::CertPolicy::Judgment>(policy_decision) != 409 if (success && (static_cast<CertJudgment>(policy_decision) == ALLOWED))
383 net::CertPolicy::UNKNOWN))
384 return true; 410 return true;
385 } 411 }
386 412
387 return false; 413 return false;
388 } 414 }
389 415
390 void ChromeSSLHostStateDelegate::HostRanInsecureContent(const std::string& host, 416 void ChromeSSLHostStateDelegate::HostRanInsecureContent(const std::string& host,
391 int pid) { 417 int pid) {
392 ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid)); 418 ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid));
393 } 419 }
394 420
395 bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent( 421 bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent(
396 const std::string& host, 422 const std::string& host,
397 int pid) const { 423 int pid) const {
398 return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid)); 424 return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid));
399 } 425 }
400 void ChromeSSLHostStateDelegate::SetClock(scoped_ptr<base::Clock> clock) { 426 void ChromeSSLHostStateDelegate::SetClock(scoped_ptr<base::Clock> clock) {
401 clock_.reset(clock.release()); 427 clock_.reset(clock.release());
402 } 428 }
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698