| 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/cert/nss_cert_database.h" | 5 #include "net/cert/nss_cert_database.h" |
| 6 | 6 |
| 7 #include <cert.h> | 7 #include <cert.h> |
| 8 #include <certdb.h> | 8 #include <certdb.h> |
| 9 #include <keyhi.h> | 9 #include <keyhi.h> |
| 10 #include <pk11pub.h> | 10 #include <pk11pub.h> |
| 11 #include <secmod.h> | 11 #include <secmod.h> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/memory/singleton.h" | 15 #include "base/memory/singleton.h" |
| 16 #include "base/observer_list_threadsafe.h" | |
| 17 #include "crypto/nss_util.h" | 16 #include "crypto/nss_util.h" |
| 18 #include "crypto/nss_util_internal.h" | 17 #include "crypto/nss_util_internal.h" |
| 18 #include "crypto/scoped_nss_types.h" |
| 19 #include "net/cert/cert_database.h" |
| 19 #include "net/base/crypto_module.h" | 20 #include "net/base/crypto_module.h" |
| 20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
| 21 #include "net/cert/cert_database.h" | 22 #include "net/cert/cert_database.h" |
| 22 #include "net/cert/x509_certificate.h" | 23 #include "net/cert/x509_certificate.h" |
| 23 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" | 24 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" |
| 24 #include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" | 25 #include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" |
| 25 | 26 |
| 26 // In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use | 27 // In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use |
| 27 // the new name of the macro. | 28 // the new name of the macro. |
| 28 #if !defined(CERTDB_TERMINAL_RECORD) | 29 #if !defined(CERTDB_TERMINAL_RECORD) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 40 : certificate(cert), net_error(err) {} | 41 : certificate(cert), net_error(err) {} |
| 41 | 42 |
| 42 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} | 43 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} |
| 43 | 44 |
| 44 // static | 45 // static |
| 45 NSSCertDatabase* NSSCertDatabase::GetInstance() { | 46 NSSCertDatabase* NSSCertDatabase::GetInstance() { |
| 46 return Singleton<NSSCertDatabase, | 47 return Singleton<NSSCertDatabase, |
| 47 LeakySingletonTraits<NSSCertDatabase> >::get(); | 48 LeakySingletonTraits<NSSCertDatabase> >::get(); |
| 48 } | 49 } |
| 49 | 50 |
| 50 NSSCertDatabase::NSSCertDatabase() | 51 NSSCertDatabase::NSSCertDatabase() { |
| 51 : observer_list_(new ObserverListThreadSafe<Observer>) { | |
| 52 crypto::EnsureNSSInit(); | 52 crypto::EnsureNSSInit(); |
| 53 psm::EnsurePKCS12Init(); | 53 psm::EnsurePKCS12Init(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 NSSCertDatabase::~NSSCertDatabase() {} | 56 NSSCertDatabase::~NSSCertDatabase() {} |
| 57 | 57 |
| 58 void NSSCertDatabase::ListCerts(CertificateList* certs) { | 58 void NSSCertDatabase::ListCerts(CertificateList* certs) { |
| 59 certs->clear(); | 59 certs->clear(); |
| 60 | 60 |
| 61 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); | 61 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); |
| 62 CERTCertListNode* node; | 62 CERTCertListNode* node; |
| 63 for (node = CERT_LIST_HEAD(cert_list); | 63 for (node = CERT_LIST_HEAD(cert_list); |
| 64 !CERT_LIST_END(node, cert_list); | 64 !CERT_LIST_END(node, cert_list); |
| 65 node = CERT_LIST_NEXT(node)) { | 65 node = CERT_LIST_NEXT(node)) { |
| 66 certs->push_back(X509Certificate::CreateFromHandle( | 66 certs->push_back(X509Certificate::CreateFromHandle( |
| 67 node->cert, X509Certificate::OSCertHandles())); | 67 node->cert, X509Certificate::OSCertHandles())); |
| 68 } | 68 } |
| 69 CERT_DestroyCertList(cert_list); | 69 CERT_DestroyCertList(cert_list); |
| 70 } | 70 } |
| 71 | 71 |
| 72 CryptoModule* NSSCertDatabase::GetPublicModule() const { | 72 CryptoModule* NSSCertDatabase::GetPublicModule() const { |
| 73 CryptoModule* module = | 73 crypto::ScopedPK11Slot slot(GetPublicSlot()); |
| 74 CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot()); | 74 CryptoModule* module = CryptoModule::CreateFromHandle(slot.get()); |
| 75 // The module is already referenced when returned from | |
| 76 // GetPublicNSSKeySlot, so we need to deref it once. | |
| 77 PK11_FreeSlot(module->os_module_handle()); | |
| 78 | 75 |
| 79 return module; | 76 return module; |
| 80 } | 77 } |
| 81 | 78 |
| 82 CryptoModule* NSSCertDatabase::GetPrivateModule() const { | 79 CryptoModule* NSSCertDatabase::GetPrivateModule() const { |
| 83 CryptoModule* module = | 80 crypto::ScopedPK11Slot slot(GetPrivateSlot()); |
| 84 CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot()); | 81 CryptoModule* module = CryptoModule::CreateFromHandle(slot.get()); |
| 85 // The module is already referenced when returned from | |
| 86 // GetPrivateNSSKeySlot, so we need to deref it once. | |
| 87 PK11_FreeSlot(module->os_module_handle()); | |
| 88 | 82 |
| 89 return module; | 83 return module; |
| 90 } | 84 } |
| 91 | 85 |
| 92 void NSSCertDatabase::ListModules(CryptoModuleList* modules, | 86 void NSSCertDatabase::ListModules(CryptoModuleList* modules, |
| 93 bool need_rw) const { | 87 bool need_rw) const { |
| 94 modules->clear(); | 88 modules->clear(); |
| 95 | 89 |
| 96 PK11SlotList* slot_list = NULL; | |
| 97 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. | 90 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. |
| 98 slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, | 91 crypto::ScopedPK11SlotList slot_list( |
| 99 need_rw ? PR_TRUE : PR_FALSE, // needRW | 92 PK11_GetAllTokens(CKM_INVALID_MECHANISM, |
| 100 PR_TRUE, // loadCerts (unused) | 93 need_rw ? PR_TRUE : PR_FALSE, // needRW |
| 101 NULL); // wincx | 94 PR_TRUE, // loadCerts (unused) |
| 95 NULL)); // wincx |
| 102 if (!slot_list) { | 96 if (!slot_list) { |
| 103 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); | 97 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); |
| 104 return; | 98 return; |
| 105 } | 99 } |
| 106 | 100 |
| 107 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list); | 101 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get()); |
| 108 while (slot_element) { | 102 while (slot_element) { |
| 109 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); | 103 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); |
| 110 slot_element = PK11_GetNextSafe(slot_list, slot_element, | 104 slot_element = PK11_GetNextSafe(slot_list.get(), slot_element, |
| 111 PR_FALSE); // restart | 105 PR_FALSE); // restart |
| 112 } | 106 } |
| 113 | |
| 114 PK11_FreeSlotList(slot_list); | |
| 115 } | 107 } |
| 116 | 108 |
| 117 int NSSCertDatabase::ImportFromPKCS12( | 109 int NSSCertDatabase::ImportFromPKCS12( |
| 118 CryptoModule* module, | 110 CryptoModule* module, |
| 119 const std::string& data, | 111 const std::string& data, |
| 120 const base::string16& password, | 112 const base::string16& password, |
| 121 bool is_extractable, | 113 bool is_extractable, |
| 122 net::CertificateList* imported_certs) { | 114 net::CertificateList* imported_certs) { |
| 115 VLOG(1) << __func__ << " " |
| 116 << PK11_GetModuleID(module->os_module_handle()) << ":" |
| 117 << PK11_GetSlotID(module->os_module_handle()); |
| 123 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), | 118 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), |
| 124 data.data(), data.size(), | 119 data.data(), data.size(), |
| 125 password, | 120 password, |
| 126 is_extractable, | 121 is_extractable, |
| 127 imported_certs); | 122 imported_certs); |
| 128 if (result == net::OK) | 123 if (result == net::OK) |
| 129 NotifyObserversOfCertAdded(NULL); | 124 NotifyObserversOfCertAdded(NULL); |
| 130 | 125 |
| 131 return result; | 126 return result; |
| 132 } | 127 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 158 return certn_1; | 153 return certn_1; |
| 159 | 154 |
| 160 VLOG(1) << "certificate list is not a hierarchy"; | 155 VLOG(1) << "certificate list is not a hierarchy"; |
| 161 return cert0; | 156 return cert0; |
| 162 } | 157 } |
| 163 | 158 |
| 164 bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, | 159 bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, |
| 165 TrustBits trust_bits, | 160 TrustBits trust_bits, |
| 166 ImportCertFailureList* not_imported) { | 161 ImportCertFailureList* not_imported) { |
| 167 X509Certificate* root = FindRootInList(certificates); | 162 X509Certificate* root = FindRootInList(certificates); |
| 168 bool success = psm::ImportCACerts(certificates, root, trust_bits, | 163 bool success = psm::ImportCACerts( |
| 169 not_imported); | 164 GetPublicSlot(), |
| 165 certificates, |
| 166 root, |
| 167 trust_bits, |
| 168 not_imported); |
| 170 if (success) | 169 if (success) |
| 171 NotifyObserversOfCertTrustChanged(NULL); | 170 NotifyObserversOfCertTrustChanged(NULL); |
| 172 | 171 |
| 173 return success; | 172 return success; |
| 174 } | 173 } |
| 175 | 174 |
| 176 bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, | 175 bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, |
| 177 TrustBits trust_bits, | 176 TrustBits trust_bits, |
| 178 ImportCertFailureList* not_imported) { | 177 ImportCertFailureList* not_imported) { |
| 179 return psm::ImportServerCert(certificates, trust_bits, not_imported); | 178 return psm::ImportServerCert( |
| 179 GetPublicSlot(), |
| 180 certificates, |
| 181 trust_bits, |
| 182 not_imported); |
| 180 } | 183 } |
| 181 | 184 |
| 182 NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( | 185 NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( |
| 183 const X509Certificate* cert, | 186 const X509Certificate* cert, |
| 184 CertType type) const { | 187 CertType type) const { |
| 185 CERTCertTrust trust; | 188 CERTCertTrust trust; |
| 186 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); | 189 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); |
| 187 if (srv != SECSuccess) { | 190 if (srv != SECSuccess) { |
| 188 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); | 191 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); |
| 189 return TRUST_DEFAULT; | 192 return TRUST_DEFAULT; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 NotifyObserversOfCertRemoved(cert); | 315 NotifyObserversOfCertRemoved(cert); |
| 313 | 316 |
| 314 return true; | 317 return true; |
| 315 } | 318 } |
| 316 | 319 |
| 317 bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { | 320 bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { |
| 318 PK11SlotInfo* slot = cert->os_cert_handle()->slot; | 321 PK11SlotInfo* slot = cert->os_cert_handle()->slot; |
| 319 return slot && PK11_IsReadOnly(slot); | 322 return slot && PK11_IsReadOnly(slot); |
| 320 } | 323 } |
| 321 | 324 |
| 322 void NSSCertDatabase::AddObserver(Observer* observer) { | 325 crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { |
| 323 observer_list_->AddObserver(observer); | 326 return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()); |
| 324 } | 327 } |
| 325 | 328 |
| 326 void NSSCertDatabase::RemoveObserver(Observer* observer) { | 329 crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { |
| 327 observer_list_->RemoveObserver(observer); | 330 return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()); |
| 328 } | 331 } |
| 329 | 332 |
| 330 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { | 333 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { |
| 331 observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); | 334 CertDatabase::GetInstance()->NotifyObserversOfCertAdded(cert); |
| 332 } | 335 } |
| 333 | 336 |
| 334 void NSSCertDatabase::NotifyObserversOfCertRemoved( | 337 void NSSCertDatabase::NotifyObserversOfCertRemoved( |
| 335 const X509Certificate* cert) { | 338 const X509Certificate* cert) { |
| 336 observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); | 339 CertDatabase::GetInstance()->NotifyObserversOfCertRemoved(cert); |
| 337 } | 340 } |
| 338 | 341 |
| 339 void NSSCertDatabase::NotifyObserversOfCertTrustChanged( | 342 void NSSCertDatabase::NotifyObserversOfCertTrustChanged( |
| 340 const X509Certificate* cert) { | 343 const X509Certificate* cert) { |
| 341 observer_list_->Notify( | 344 CertDatabase::GetInstance()->NotifyObserversOfCertTrustChanged(cert); |
| 342 &Observer::OnCertTrustChanged, make_scoped_refptr(cert)); | |
| 343 } | 345 } |
| 344 | 346 |
| 345 } // namespace net | 347 } // namespace net |
| OLD | NEW |