| 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 19 matching lines...) Expand all Loading... |
| 30 #if defined(USE_NSS) | 30 #if defined(USE_NSS) |
| 31 #include <private/pprthred.h> // PR_DetachThread | 31 #include <private/pprthred.h> // PR_DetachThread |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 namespace net { | 34 namespace net { |
| 35 | 35 |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 const int kKeySizeInBits = 1024; | 38 const int kKeySizeInBits = 1024; |
| 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 | |
| 41 // so the result will still hold even after chrome has been running for a | |
| 42 // while. | |
| 43 const int kSystemTimeValidityBufferInDays = 90; | |
| 44 | 40 |
| 45 bool IsSupportedCertType(uint8 type) { | 41 bool IsSupportedCertType(uint8 type) { |
| 46 switch(type) { | 42 switch(type) { |
| 47 case CLIENT_CERT_ECDSA_SIGN: | 43 case CLIENT_CERT_ECDSA_SIGN: |
| 48 return true; | 44 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: | 45 default: |
| 52 return false; | 46 return false; |
| 53 } | 47 } |
| 54 } | 48 } |
| 55 | 49 |
| 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 | 50 // Used by the GetDomainBoundCertResult histogram to record the final |
| 71 // outcome of each GetDomainBoundCert call. Do not re-use values. | 51 // outcome of each GetDomainBoundCert call. Do not re-use values. |
| 72 enum GetCertResult { | 52 enum GetCertResult { |
| 73 // Synchronously found and returned an existing domain bound cert. | 53 // Synchronously found and returned an existing domain bound cert. |
| 74 SYNC_SUCCESS = 0, | 54 SYNC_SUCCESS = 0, |
| 75 // Retrieved or generated and returned a domain bound cert asynchronously. | 55 // Retrieved or generated and returned a domain bound cert asynchronously. |
| 76 ASYNC_SUCCESS = 1, | 56 ASYNC_SUCCESS = 1, |
| 77 // Retrieval/generation request was cancelled before the cert generation | 57 // Retrieval/generation request was cancelled before the cert generation |
| 78 // completed. | 58 // completed. |
| 79 ASYNC_CANCELLED = 2, | 59 ASYNC_CANCELLED = 2, |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 | 386 |
| 407 ServerBoundCertService::ServerBoundCertService( | 387 ServerBoundCertService::ServerBoundCertService( |
| 408 ServerBoundCertStore* server_bound_cert_store, | 388 ServerBoundCertStore* server_bound_cert_store, |
| 409 const scoped_refptr<base::TaskRunner>& task_runner) | 389 const scoped_refptr<base::TaskRunner>& task_runner) |
| 410 : server_bound_cert_store_(server_bound_cert_store), | 390 : server_bound_cert_store_(server_bound_cert_store), |
| 411 task_runner_(task_runner), | 391 task_runner_(task_runner), |
| 412 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | 392 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 413 requests_(0), | 393 requests_(0), |
| 414 cert_store_hits_(0), | 394 cert_store_hits_(0), |
| 415 inflight_joins_(0) { | 395 inflight_joins_(0) { |
| 416 base::Time start = base::Time::Now(); | |
| 417 base::Time end = start + base::TimeDelta::FromDays( | |
| 418 kValidityPeriodInDays + kSystemTimeValidityBufferInDays); | |
| 419 is_system_time_valid_ = x509_util::IsSupportedValidityRange(start, end); | |
| 420 } | 396 } |
| 421 | 397 |
| 422 ServerBoundCertService::~ServerBoundCertService() { | 398 ServerBoundCertService::~ServerBoundCertService() { |
| 423 STLDeleteValues(&inflight_); | 399 STLDeleteValues(&inflight_); |
| 424 } | 400 } |
| 425 | 401 |
| 426 //static | 402 //static |
| 427 std::string ServerBoundCertService::GetDomainForHost(const std::string& host) { | 403 std::string ServerBoundCertService::GetDomainForHost(const std::string& host) { |
| 428 std::string domain = | 404 std::string domain = |
| 429 RegistryControlledDomainService::GetDomainAndRegistry(host); | 405 RegistryControlledDomainService::GetDomainAndRegistry(host); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 request_start, | 476 request_start, |
| 501 base::Bind(&RequestHandle::OnRequestComplete, | 477 base::Bind(&RequestHandle::OnRequestComplete, |
| 502 base::Unretained(out_req)), | 478 base::Unretained(out_req)), |
| 503 type, private_key, cert); | 479 type, private_key, cert); |
| 504 job->AddRequest(request); | 480 job->AddRequest(request); |
| 505 out_req->RequestStarted(this, request, callback); | 481 out_req->RequestStarted(this, request, callback); |
| 506 return ERR_IO_PENDING; | 482 return ERR_IO_PENDING; |
| 507 } | 483 } |
| 508 | 484 |
| 509 // Check if a domain bound cert of an acceptable type already exists for this | 485 // Check if a domain bound cert of an acceptable type already exists for this |
| 510 // domain, and that it has not expired. | 486 // domain. Note that |expiration_time| is ignored, and expired certs are |
| 487 // considered valid. |
| 511 base::Time expiration_time; | 488 base::Time expiration_time; |
| 512 if (server_bound_cert_store_->GetServerBoundCert( | 489 if (server_bound_cert_store_->GetServerBoundCert( |
| 513 domain, | 490 domain, |
| 514 type, | 491 type, |
| 515 &expiration_time, | 492 &expiration_time /* ignored */, |
| 516 private_key, | 493 private_key, |
| 517 cert, | 494 cert, |
| 518 base::Bind(&ServerBoundCertService::GotServerBoundCert, | 495 base::Bind(&ServerBoundCertService::GotServerBoundCert, |
| 519 weak_ptr_factory_.GetWeakPtr()))) { | 496 weak_ptr_factory_.GetWeakPtr()))) { |
| 520 if (*type != CLIENT_CERT_INVALID_TYPE) { | 497 if (type && IsSupportedCertType(*type)) { |
| 521 // Sync lookup found a cert. | 498 // Sync lookup found a valid cert. |
| 522 if (CertIsValid(domain, *type, expiration_time)) { | 499 DVLOG(1) << "Cert store had valid cert for " << domain |
| 523 DVLOG(1) << "Cert store had valid cert for " << domain | 500 << " of type " << *type; |
| 524 << " of type " << *type; | 501 cert_store_hits_++; |
| 525 cert_store_hits_++; | 502 RecordGetDomainBoundCertResult(SYNC_SUCCESS); |
| 526 RecordGetDomainBoundCertResult(SYNC_SUCCESS); | 503 base::TimeDelta request_time = base::TimeTicks::Now() - request_start; |
| 527 base::TimeDelta request_time = base::TimeTicks::Now() - request_start; | 504 UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); |
| 528 UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); | 505 RecordGetCertTime(request_time); |
| 529 RecordGetCertTime(request_time); | 506 return OK; |
| 530 return OK; | |
| 531 } | |
| 532 } | 507 } |
| 533 | 508 |
| 534 // Sync lookup did not find a cert, or it found an expired one. Start | 509 // Sync lookup did not find a valid cert. Start generating a new one. |
| 535 // generating a new one. | |
| 536 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( | 510 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( |
| 537 domain, | 511 domain, |
| 538 preferred_type, | 512 preferred_type, |
| 539 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, | 513 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, |
| 540 weak_ptr_factory_.GetWeakPtr())); | 514 weak_ptr_factory_.GetWeakPtr())); |
| 541 if (!worker->Start(task_runner_)) { | 515 if (!worker->Start(task_runner_)) { |
| 542 delete worker; | 516 delete worker; |
| 543 // TODO(rkn): Log to the NetLog. | 517 // TODO(rkn): Log to the NetLog. |
| 544 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; | 518 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; |
| 545 RecordGetDomainBoundCertResult(WORKER_FAILURE); | 519 RecordGetDomainBoundCertResult(WORKER_FAILURE); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 570 DCHECK(CalledOnValidThread()); | 544 DCHECK(CalledOnValidThread()); |
| 571 | 545 |
| 572 std::map<std::string, ServerBoundCertServiceJob*>::iterator j; | 546 std::map<std::string, ServerBoundCertServiceJob*>::iterator j; |
| 573 j = inflight_.find(server_identifier); | 547 j = inflight_.find(server_identifier); |
| 574 if (j == inflight_.end()) { | 548 if (j == inflight_.end()) { |
| 575 NOTREACHED(); | 549 NOTREACHED(); |
| 576 return; | 550 return; |
| 577 } | 551 } |
| 578 ServerBoundCertServiceJob* job = j->second; | 552 ServerBoundCertServiceJob* job = j->second; |
| 579 | 553 |
| 580 if (type != CLIENT_CERT_INVALID_TYPE) { | 554 if (IsSupportedCertType(type)) { |
| 581 // Async DB lookup found a cert. | 555 // Async DB lookup found a valid cert. |
| 582 if (CertIsValid(server_identifier, type, expiration_time)) { | 556 DVLOG(1) << "Cert store had valid cert for " << server_identifier |
| 583 DVLOG(1) << "Cert store had valid cert for " << server_identifier | 557 << " of type " << type; |
| 584 << " of type " << type; | 558 cert_store_hits_++; |
| 585 cert_store_hits_++; | 559 // ServerBoundCertServiceRequest::Post will do the histograms and stuff. |
| 586 // ServerBoundCertServiceRequest::Post will do the histograms and stuff. | 560 HandleResult(OK, server_identifier, type, key, cert); |
| 587 HandleResult(OK, server_identifier, type, key, cert); | 561 return; |
| 588 return; | |
| 589 } | |
| 590 } | 562 } |
| 591 | 563 |
| 592 // Async lookup did not find a cert, or it found an expired one. Start | 564 // Async lookup did not find a valid cert. Start generating a new one. |
| 593 // generating a new one. | |
| 594 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( | 565 ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( |
| 595 server_identifier, | 566 server_identifier, |
| 596 job->type(), | 567 job->type(), |
| 597 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, | 568 base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, |
| 598 weak_ptr_factory_.GetWeakPtr())); | 569 weak_ptr_factory_.GetWeakPtr())); |
| 599 if (!worker->Start(task_runner_)) { | 570 if (!worker->Start(task_runner_)) { |
| 600 delete worker; | 571 delete worker; |
| 601 // TODO(rkn): Log to the NetLog. | 572 // TODO(rkn): Log to the NetLog. |
| 602 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; | 573 LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; |
| 603 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, | 574 HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 | 625 |
| 655 job->HandleResult(error, type, private_key, cert); | 626 job->HandleResult(error, type, private_key, cert); |
| 656 delete job; | 627 delete job; |
| 657 } | 628 } |
| 658 | 629 |
| 659 int ServerBoundCertService::cert_count() { | 630 int ServerBoundCertService::cert_count() { |
| 660 return server_bound_cert_store_->GetCertCount(); | 631 return server_bound_cert_store_->GetCertCount(); |
| 661 } | 632 } |
| 662 | 633 |
| 663 } // namespace net | 634 } // namespace net |
| OLD | NEW |