OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/ssl/server_bound_cert_service.h" | 5 #include "net/ssl/server_bound_cert_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
39 const int kValidityPeriodInDays = 365; | 39 const int kValidityPeriodInDays = 365; |
40 // When we check the system time, we add this many days to the end of the check | 40 // When we check the system time, we add this many days to the end of the check |
41 // so the result will still hold even after chrome has been running for a | 41 // so the result will still hold even after chrome has been running for a |
42 // while. | 42 // while. |
43 const int kSystemTimeValidityBufferInDays = 90; | 43 const int kSystemTimeValidityBufferInDays = 90; |
44 | 44 |
45 bool IsSupportedCertType(uint8 type) { | 45 bool IsSupportedCertType(uint8 type) { |
46 switch(type) { | 46 switch(type) { |
47 case CLIENT_CERT_ECDSA_SIGN: | 47 case CLIENT_CERT_ECDSA_SIGN: |
48 return true; | 48 return true; |
49 // If we add any more supported types, CertIsValid will need to be updated | |
50 // to check that the returned type matches one of the requested types. | |
51 default: | 49 default: |
52 return false; | 50 return false; |
53 } | 51 } |
54 } | 52 } |
55 | 53 |
56 bool CertIsValid(const std::string& domain, | |
57 SSLClientCertType type, | |
58 base::Time expiration_time) { | |
59 if (expiration_time < base::Time::Now()) { | |
60 DVLOG(1) << "Cert store had expired cert for " << domain; | |
61 return false; | |
62 } else if (!IsSupportedCertType(type)) { | |
63 DVLOG(1) << "Cert store had cert of wrong type " << type << " for " | |
64 << domain; | |
65 return false; | |
66 } | |
67 return true; | |
68 } | |
69 | |
70 // Used by the GetDomainBoundCertResult histogram to record the final | 54 // Used by the GetDomainBoundCertResult histogram to record the final |
71 // outcome of each GetDomainBoundCert call. Do not re-use values. | 55 // outcome of each GetDomainBoundCert call. Do not re-use values. |
72 enum GetCertResult { | 56 enum GetCertResult { |
73 // Synchronously found and returned an existing domain bound cert. | 57 // Synchronously found and returned an existing domain bound cert. |
74 SYNC_SUCCESS = 0, | 58 SYNC_SUCCESS = 0, |
75 // Retrieved or generated and returned a domain bound cert asynchronously. | 59 // Retrieved or generated and returned a domain bound cert asynchronously. |
76 ASYNC_SUCCESS = 1, | 60 ASYNC_SUCCESS = 1, |
77 // Retrieval/generation request was cancelled before the cert generation | 61 // Retrieval/generation request was cancelled before the cert generation |
78 // completed. | 62 // completed. |
79 ASYNC_CANCELLED = 2, | 63 ASYNC_CANCELLED = 2, |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 ServerBoundCertStore* server_bound_cert_store, | 392 ServerBoundCertStore* server_bound_cert_store, |
409 const scoped_refptr<base::TaskRunner>& task_runner) | 393 const scoped_refptr<base::TaskRunner>& task_runner) |
410 : server_bound_cert_store_(server_bound_cert_store), | 394 : server_bound_cert_store_(server_bound_cert_store), |
411 task_runner_(task_runner), | 395 task_runner_(task_runner), |
412 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | 396 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
413 requests_(0), | 397 requests_(0), |
414 cert_store_hits_(0), | 398 cert_store_hits_(0), |
415 inflight_joins_(0) { | 399 inflight_joins_(0) { |
416 base::Time start = base::Time::Now(); | 400 base::Time start = base::Time::Now(); |
417 base::Time end = start + base::TimeDelta::FromDays( | 401 base::Time end = start + base::TimeDelta::FromDays( |
418 kValidityPeriodInDays + kSystemTimeValidityBufferInDays); | 402 kValidityPeriodInDays + kSystemTimeValidityBufferInDays); |
419 is_system_time_valid_ = x509_util::IsSupportedValidityRange(start, end); | 403 is_system_time_valid_ = x509_util::IsSupportedValidityRange(start, end); |
420 } | 404 } |
421 | 405 |
422 ServerBoundCertService::~ServerBoundCertService() { | 406 ServerBoundCertService::~ServerBoundCertService() { |
423 STLDeleteValues(&inflight_); | 407 STLDeleteValues(&inflight_); |
424 } | 408 } |
425 | 409 |
426 //static | 410 //static |
427 std::string ServerBoundCertService::GetDomainForHost(const std::string& host) { | 411 std::string ServerBoundCertService::GetDomainForHost(const std::string& host) { |
428 std::string domain = | 412 std::string domain = |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
500 request_start, | 484 request_start, |
501 base::Bind(&RequestHandle::OnRequestComplete, | 485 base::Bind(&RequestHandle::OnRequestComplete, |
502 base::Unretained(out_req)), | 486 base::Unretained(out_req)), |
503 type, private_key, cert); | 487 type, private_key, cert); |
504 job->AddRequest(request); | 488 job->AddRequest(request); |
505 out_req->RequestStarted(this, request, callback); | 489 out_req->RequestStarted(this, request, callback); |
506 return ERR_IO_PENDING; | 490 return ERR_IO_PENDING; |
507 } | 491 } |
508 | 492 |
509 // Check if a domain bound cert of an acceptable type already exists for this | 493 // Check if a domain bound cert of an acceptable type already exists for this |
510 // domain, and that it has not expired. | 494 // domain. Note that |expiration_time| is ignored, and expired certs are |
495 // considered valid. | |
511 base::Time expiration_time; | 496 base::Time expiration_time; |
512 if (server_bound_cert_store_->GetServerBoundCert( | 497 if (server_bound_cert_store_->GetServerBoundCert( |
513 domain, | 498 domain, |
514 type, | 499 type, |
515 &expiration_time, | 500 &expiration_time /* ignored */, |
516 private_key, | 501 private_key, |
517 cert, | 502 cert, |
518 base::Bind(&ServerBoundCertService::GotServerBoundCert, | 503 base::Bind(&ServerBoundCertService::GotServerBoundCert, |
519 weak_ptr_factory_.GetWeakPtr()))) { | 504 weak_ptr_factory_.GetWeakPtr()))) { |
520 if (*type != CLIENT_CERT_INVALID_TYPE) { | 505 if (type && IsSupportedCertType(*type)) { |
mattm
2013/04/01 23:03:12
Can remove the "type && " check, since it is alrea
thaidn_google
2013/04/01 23:56:14
Done.
| |
521 // Sync lookup found a cert. | 506 // Sync lookup found a valid cert. |
522 if (CertIsValid(domain, *type, expiration_time)) { | 507 DVLOG(1) << "Cert store had valid cert for " << domain |
523 DVLOG(1) << "Cert store had valid cert for " << domain | 508 << " of type " << *type; |
524 << " of type " << *type; | 509 cert_store_hits_++; |
525 cert_store_hits_++; | 510 RecordGetDomainBoundCertResult(SYNC_SUCCESS); |
526 RecordGetDomainBoundCertResult(SYNC_SUCCESS); | 511 base::TimeDelta request_time = base::TimeTicks::Now() - request_start; |
527 base::TimeDelta request_time = base::TimeTicks::Now() - request_start; | 512 UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); |
528 UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); | 513 RecordGetCertTime(request_time); |
529 RecordGetCertTime(request_time); | 514 return OK; |
530 return OK; | |
531 } | |
532 } | 515 } |
533 | 516 |
534 // Sync lookup did not find a cert, or it found an expired one. Start | 517 // Sync lookup did not find a valid cert. Start generating a new one. |
535 // generating a new one. | |
536 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( | 518 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( |
537 domain, | 519 domain, |
538 preferred_type, | 520 preferred_type, |
539 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, | 521 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, |
540 weak_ptr_factory_.GetWeakPtr())); | 522 weak_ptr_factory_.GetWeakPtr())); |
541 if (!worker->Start(task_runner_)) { | 523 if (!worker->Start(task_runner_)) { |
542 delete worker; | 524 delete worker; |
543 // TODO(rkn): Log to the NetLog. | 525 // TODO(rkn): Log to the NetLog. |
544 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; | 526 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; |
545 RecordGetDomainBoundCertResult(WORKER_FAILURE); | 527 RecordGetDomainBoundCertResult(WORKER_FAILURE); |
(...skipping 24 matching lines...) Expand all Loading... | |
570 DCHECK(CalledOnValidThread()); | 552 DCHECK(CalledOnValidThread()); |
571 | 553 |
572 std::map<std::string, ServerBoundCertServiceJob*>::iterator j; | 554 std::map<std::string, ServerBoundCertServiceJob*>::iterator j; |
573 j = inflight_.find(server_identifier); | 555 j = inflight_.find(server_identifier); |
574 if (j == inflight_.end()) { | 556 if (j == inflight_.end()) { |
575 NOTREACHED(); | 557 NOTREACHED(); |
576 return; | 558 return; |
577 } | 559 } |
578 ServerBoundCertServiceJob* job = j->second; | 560 ServerBoundCertServiceJob* job = j->second; |
579 | 561 |
580 if (type != CLIENT_CERT_INVALID_TYPE) { | 562 if (IsSupportedCertType(type)) { |
581 // Async DB lookup found a cert. | 563 // Async DB lookup found a valid cert. |
582 if (CertIsValid(server_identifier, type, expiration_time)) { | 564 DVLOG(1) << "Cert store had valid cert for " << server_identifier |
583 DVLOG(1) << "Cert store had valid cert for " << server_identifier | 565 << " of type " << type; |
584 << " of type " << type; | 566 cert_store_hits_++; |
585 cert_store_hits_++; | 567 // ServerBoundCertServiceRequest::Post will do the histograms and stuff. |
586 // ServerBoundCertServiceRequest::Post will do the histograms and stuff. | 568 HandleResult(OK, server_identifier, type, key, cert); |
587 HandleResult(OK, server_identifier, type, key, cert); | 569 return; |
588 return; | |
589 } | |
590 } | 570 } |
591 | 571 |
592 // Async lookup did not find a cert, or it found an expired one. Start | 572 // Async lookup did not find a valid cert. Start generating a new one. |
593 // generating a new one. | |
594 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( | 573 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( |
595 server_identifier, | 574 server_identifier, |
596 job->type(), | 575 job->type(), |
597 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, | 576 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, |
598 weak_ptr_factory_.GetWeakPtr())); | 577 weak_ptr_factory_.GetWeakPtr())); |
599 if (!worker->Start(task_runner_)) { | 578 if (!worker->Start(task_runner_)) { |
600 delete worker; | 579 delete worker; |
601 // TODO(rkn): Log to the NetLog. | 580 // TODO(rkn): Log to the NetLog. |
602 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; | 581 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; |
603 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, | 582 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
654 | 633 |
655 job->HandleResult(error, type, private_key, cert); | 634 job->HandleResult(error, type, private_key, cert); |
656 delete job; | 635 delete job; |
657 } | 636 } |
658 | 637 |
659 int ServerBoundCertService::cert_count() { | 638 int ServerBoundCertService::cert_count() { |
660 return server_bound_cert_store_->GetCertCount(); | 639 return server_bound_cert_store_->GetCertCount(); |
661 } | 640 } |
662 | 641 |
663 } // namespace net | 642 } // namespace net |
OLD | NEW |