certificate_manager_model.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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
  3. // found in the LICENSE file.
  4. #include "chrome/browser/certificate_manager_model.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/logging.h"
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "content/public/browser/browser_context.h"
  10. #include "content/public/browser/browser_thread.h"
  11. #include "content/public/browser/resource_context.h"
  12. #include "crypto/nss_util.h"
  13. #include "crypto/nss_util_internal.h"
  14. #include "net/base/net_errors.h"
  15. #include "net/cert/nss_cert_database.h"
  16. #include "net/cert/x509_certificate.h"
  17. using content::BrowserThread;
  18. namespace {
  19. net::NSSCertDatabase* g_nss_cert_database = nullptr;
  20. net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
  21. content::ResourceContext* context,
  22. const base::Callback<void(net::NSSCertDatabase*)>& callback) {
  23. // This initialization is not thread safe. This CHECK ensures that this code
  24. // is only run on a single thread.
  25. CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  26. if (!g_nss_cert_database) {
  27. // Linux has only a single persistent slot compared to ChromeOS's separate
  28. // public and private slot.
  29. // Redirect any slot usage to this persistent slot on Linux.
  30. g_nss_cert_database = new net::NSSCertDatabase(
  31. crypto::ScopedPK11Slot(
  32. crypto::GetPersistentNSSKeySlot()) /* public slot */,
  33. crypto::ScopedPK11Slot(
  34. crypto::GetPersistentNSSKeySlot()) /* private slot */);
  35. }
  36. return g_nss_cert_database;
  37. }
  38. } // namespace
  39. // CertificateManagerModel is created on the UI thread. It needs a
  40. // NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
  41. // needs to be done on the IO thread.
  42. //
  43. // The initialization flow is roughly:
  44. //
  45. // UI thread IO Thread
  46. //
  47. // CertificateManagerModel::Create
  48. // \--------------------------------------v
  49. // CertificateManagerModel::GetCertDBOnIOThread
  50. // |
  51. // GetNSSCertDatabaseForResourceContext
  52. // |
  53. // CertificateManagerModel::DidGetCertDBOnIOThread
  54. // v--------------------------------------/
  55. // CertificateManagerModel::DidGetCertDBOnUIThread
  56. // |
  57. // new CertificateManagerModel
  58. // |
  59. // callback
  60. // static
  61. void CertificateManagerModel::Create(content::BrowserContext* browser_context,
  62. const CreationCallback& callback) {
  63. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  64. BrowserThread::PostTask(
  65. BrowserThread::IO, FROM_HERE,
  66. base::Bind(&CertificateManagerModel::GetCertDBOnIOThread,
  67. browser_context->GetResourceContext(), callback));
  68. }
  69. CertificateManagerModel::CertificateManagerModel(
  70. net::NSSCertDatabase* nss_cert_database,
  71. bool is_user_db_available)
  72. : cert_db_(nss_cert_database), is_user_db_available_(is_user_db_available) {
  73. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  74. }
  75. CertificateManagerModel::~CertificateManagerModel() {}
  76. int CertificateManagerModel::ImportFromPKCS12(
  77. PK11SlotInfo* slot_info,
  78. const std::string& data,
  79. const base::string16& password,
  80. bool is_extractable,
  81. net::ScopedCERTCertificateList* imported_certs) {
  82. return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
  83. imported_certs);
  84. }
  85. int CertificateManagerModel::ImportUserCert(const std::string& data) {
  86. return cert_db_->ImportUserCert(data);
  87. }
  88. bool CertificateManagerModel::ImportCACerts(
  89. const net::ScopedCERTCertificateList& certificates,
  90. net::NSSCertDatabase::TrustBits trust_bits,
  91. net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  92. return cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
  93. }
  94. bool CertificateManagerModel::ImportServerCert(
  95. const net::ScopedCERTCertificateList& certificates,
  96. net::NSSCertDatabase::TrustBits trust_bits,
  97. net::NSSCertDatabase::ImportCertFailureList* not_imported) {
  98. return cert_db_->ImportServerCert(certificates, trust_bits, not_imported);
  99. }
  100. bool CertificateManagerModel::SetCertTrust(
  101. CERTCertificate* cert,
  102. net::CertType type,
  103. net::NSSCertDatabase::TrustBits trust_bits) {
  104. return cert_db_->SetCertTrust(cert, type, trust_bits);
  105. }
  106. bool CertificateManagerModel::Delete(CERTCertificate* cert) {
  107. return cert_db_->DeleteCertAndKey(cert);
  108. }
  109. // static
  110. void CertificateManagerModel::DidGetCertDBOnUIThread(
  111. net::NSSCertDatabase* cert_db,
  112. bool is_user_db_available,
  113. const CreationCallback& callback) {
  114. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  115. std::unique_ptr<CertificateManagerModel> model(
  116. new CertificateManagerModel(cert_db, is_user_db_available));
  117. callback.Run(std::move(model));
  118. }
  119. // static
  120. void CertificateManagerModel::DidGetCertDBOnIOThread(
  121. const CreationCallback& callback,
  122. net::NSSCertDatabase* cert_db) {
  123. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  124. bool is_user_db_available = !!cert_db->GetPublicSlot();
  125. BrowserThread::PostTask(
  126. BrowserThread::UI, FROM_HERE,
  127. base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread, cert_db,
  128. is_user_db_available, callback));
  129. }
  130. // static
  131. void CertificateManagerModel::GetCertDBOnIOThread(
  132. content::ResourceContext* context,
  133. const CreationCallback& callback) {
  134. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  135. net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
  136. context,
  137. base::Bind(&CertificateManagerModel::DidGetCertDBOnIOThread, callback));
  138. if (cert_db)
  139. DidGetCertDBOnIOThread(callback, cert_db);
  140. }