| 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> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER | 34 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER |
| 35 #endif | 35 #endif |
| 36 | 36 |
| 37 // PSM = Mozilla's Personal Security Manager. | 37 // PSM = Mozilla's Personal Security Manager. |
| 38 namespace psm = mozilla_security_manager; | 38 namespace psm = mozilla_security_manager; |
| 39 | 39 |
| 40 namespace net { | 40 namespace net { |
| 41 | 41 |
| 42 namespace { | 42 namespace { |
| 43 | 43 |
| 44 base::LazyInstance<NSSCertDatabase>::Leaky | 44 base::LazyInstance<NSSCertDatabase>::Leaky g_nss_cert_database = |
| 45 g_nss_cert_database = LAZY_INSTANCE_INITIALIZER; | 45 LAZY_INSTANCE_INITIALIZER; |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 NSSCertDatabase::ImportCertFailure::ImportCertFailure( | 49 NSSCertDatabase::ImportCertFailure::ImportCertFailure( |
| 50 const scoped_refptr<X509Certificate>& cert, | 50 const scoped_refptr<X509Certificate>& cert, |
| 51 int err) | 51 int err) |
| 52 : certificate(cert), net_error(err) {} | 52 : certificate(cert), net_error(err) { |
| 53 } |
| 53 | 54 |
| 54 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} | 55 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() { |
| 56 } |
| 55 | 57 |
| 56 // static | 58 // static |
| 57 NSSCertDatabase* NSSCertDatabase::GetInstance() { | 59 NSSCertDatabase* NSSCertDatabase::GetInstance() { |
| 58 // TODO(mattm): Remove this ifdef guard once the linux impl of | 60 // TODO(mattm): Remove this ifdef guard once the linux impl of |
| 59 // GetNSSCertDatabaseForResourceContext does not call GetInstance. | 61 // GetNSSCertDatabaseForResourceContext does not call GetInstance. |
| 60 #if defined(OS_CHROMEOS) | 62 #if defined(OS_CHROMEOS) |
| 61 LOG(ERROR) << "NSSCertDatabase::GetInstance() is deprecated." | 63 LOG(ERROR) << "NSSCertDatabase::GetInstance() is deprecated." |
| 62 << "See http://crbug.com/329735."; | 64 << "See http://crbug.com/329735."; |
| 63 #endif | 65 #endif |
| 64 return &g_nss_cert_database.Get(); | 66 return &g_nss_cert_database.Get(); |
| 65 } | 67 } |
| 66 | 68 |
| 67 NSSCertDatabase::NSSCertDatabase() | 69 NSSCertDatabase::NSSCertDatabase() |
| 68 : observer_list_(new ObserverListThreadSafe<Observer>) { | 70 : observer_list_(new ObserverListThreadSafe<Observer>) { |
| 69 // This also makes sure that NSS has been initialized. | 71 // This also makes sure that NSS has been initialized. |
| 70 CertDatabase::GetInstance()->ObserveNSSCertDatabase(this); | 72 CertDatabase::GetInstance()->ObserveNSSCertDatabase(this); |
| 71 | 73 |
| 72 psm::EnsurePKCS12Init(); | 74 psm::EnsurePKCS12Init(); |
| 73 } | 75 } |
| 74 | 76 |
| 75 NSSCertDatabase::~NSSCertDatabase() {} | 77 NSSCertDatabase::~NSSCertDatabase() { |
| 78 } |
| 76 | 79 |
| 77 void NSSCertDatabase::ListCertsSync(CertificateList* certs) { | 80 void NSSCertDatabase::ListCertsSync(CertificateList* certs) { |
| 78 ListCertsImpl(certs); | 81 ListCertsImpl(certs); |
| 79 } | 82 } |
| 80 | 83 |
| 81 void NSSCertDatabase::ListCerts( | 84 void NSSCertDatabase::ListCerts( |
| 82 const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { | 85 const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { |
| 83 scoped_ptr<CertificateList> certs(new CertificateList()); | 86 scoped_ptr<CertificateList> certs(new CertificateList()); |
| 84 | 87 |
| 85 // base::Pased will NULL out |certs|, so cache the underlying pointer here. | 88 // base::Pased will NULL out |certs|, so cache the underlying pointer here. |
| 86 CertificateList* raw_certs = certs.get(); | 89 CertificateList* raw_certs = certs.get(); |
| 87 GetSlowTaskRunner()->PostTaskAndReply( | 90 GetSlowTaskRunner()->PostTaskAndReply( |
| 88 FROM_HERE, | 91 FROM_HERE, |
| 89 base::Bind(&NSSCertDatabase::ListCertsImpl, | 92 base::Bind(&NSSCertDatabase::ListCertsImpl, base::Unretained(raw_certs)), |
| 90 base::Unretained(raw_certs)), | |
| 91 base::Bind(callback, base::Passed(&certs))); | 93 base::Bind(callback, base::Passed(&certs))); |
| 92 } | 94 } |
| 93 | 95 |
| 94 crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { | 96 crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { |
| 95 return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()); | 97 return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()); |
| 96 } | 98 } |
| 97 | 99 |
| 98 crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { | 100 crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { |
| 99 return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()); | 101 return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()); |
| 100 } | 102 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 120 PR_TRUE, // loadCerts (unused) | 122 PR_TRUE, // loadCerts (unused) |
| 121 NULL)); // wincx | 123 NULL)); // wincx |
| 122 if (!slot_list) { | 124 if (!slot_list) { |
| 123 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); | 125 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); |
| 124 return; | 126 return; |
| 125 } | 127 } |
| 126 | 128 |
| 127 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get()); | 129 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get()); |
| 128 while (slot_element) { | 130 while (slot_element) { |
| 129 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); | 131 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); |
| 130 slot_element = PK11_GetNextSafe(slot_list.get(), slot_element, | 132 slot_element = PK11_GetNextSafe(slot_list.get(), |
| 133 slot_element, |
| 131 PR_FALSE); // restart | 134 PR_FALSE); // restart |
| 132 } | 135 } |
| 133 } | 136 } |
| 134 | 137 |
| 135 int NSSCertDatabase::ImportFromPKCS12( | 138 int NSSCertDatabase::ImportFromPKCS12(CryptoModule* module, |
| 136 CryptoModule* module, | 139 const std::string& data, |
| 137 const std::string& data, | 140 const base::string16& password, |
| 138 const base::string16& password, | 141 bool is_extractable, |
| 139 bool is_extractable, | 142 net::CertificateList* imported_certs) { |
| 140 net::CertificateList* imported_certs) { | 143 DVLOG(1) << __func__ << " " << PK11_GetModuleID(module->os_module_handle()) |
| 141 DVLOG(1) << __func__ << " " | 144 << ":" << PK11_GetSlotID(module->os_module_handle()); |
| 142 << PK11_GetModuleID(module->os_module_handle()) << ":" | |
| 143 << PK11_GetSlotID(module->os_module_handle()); | |
| 144 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), | 145 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), |
| 145 data.data(), data.size(), | 146 data.data(), |
| 147 data.size(), |
| 146 password, | 148 password, |
| 147 is_extractable, | 149 is_extractable, |
| 148 imported_certs); | 150 imported_certs); |
| 149 if (result == net::OK) | 151 if (result == net::OK) |
| 150 NotifyObserversOfCertAdded(NULL); | 152 NotifyObserversOfCertAdded(NULL); |
| 151 | 153 |
| 152 return result; | 154 return result; |
| 153 } | 155 } |
| 154 | 156 |
| 155 int NSSCertDatabase::ExportToPKCS12( | 157 int NSSCertDatabase::ExportToPKCS12(const CertificateList& certs, |
| 156 const CertificateList& certs, | 158 const base::string16& password, |
| 157 const base::string16& password, | 159 std::string* output) const { |
| 158 std::string* output) const { | |
| 159 return psm::nsPKCS12Blob_Export(output, certs, password); | 160 return psm::nsPKCS12Blob_Export(output, certs, password); |
| 160 } | 161 } |
| 161 | 162 |
| 162 X509Certificate* NSSCertDatabase::FindRootInList( | 163 X509Certificate* NSSCertDatabase::FindRootInList( |
| 163 const CertificateList& certificates) const { | 164 const CertificateList& certificates) const { |
| 164 DCHECK_GT(certificates.size(), 0U); | 165 DCHECK_GT(certificates.size(), 0U); |
| 165 | 166 |
| 166 if (certificates.size() == 1) | 167 if (certificates.size() == 1) |
| 167 return certificates[0].get(); | 168 return certificates[0].get(); |
| 168 | 169 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 &cert->os_cert_handle()->subject) == SECEqual) { | 298 &cert->os_cert_handle()->subject) == SECEqual) { |
| 298 return (nsstrust.sslFlags & kTrusted) == 0 && | 299 return (nsstrust.sslFlags & kTrusted) == 0 && |
| 299 (nsstrust.emailFlags & kTrusted) == 0 && | 300 (nsstrust.emailFlags & kTrusted) == 0 && |
| 300 (nsstrust.objectSigningFlags & kTrusted) == 0; | 301 (nsstrust.objectSigningFlags & kTrusted) == 0; |
| 301 } | 302 } |
| 302 | 303 |
| 303 return false; | 304 return false; |
| 304 } | 305 } |
| 305 | 306 |
| 306 bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, | 307 bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, |
| 307 CertType type, | 308 CertType type, |
| 308 TrustBits trust_bits) { | 309 TrustBits trust_bits) { |
| 309 bool success = psm::SetCertTrust(cert, type, trust_bits); | 310 bool success = psm::SetCertTrust(cert, type, trust_bits); |
| 310 if (success) | 311 if (success) |
| 311 NotifyObserversOfCACertChanged(cert); | 312 NotifyObserversOfCACertChanged(cert); |
| 312 | 313 |
| 313 return success; | 314 return success; |
| 314 } | 315 } |
| 315 | 316 |
| 316 bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) { | 317 bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) { |
| 317 // For some reason, PK11_DeleteTokenCertAndKey only calls | 318 // For some reason, PK11_DeleteTokenCertAndKey only calls |
| 318 // SEC_DeletePermCertificate if the private key is found. So, we check | 319 // SEC_DeletePermCertificate if the private key is found. So, we check |
| 319 // whether a private key exists before deciding which function to call to | 320 // whether a private key exists before deciding which function to call to |
| 320 // delete the cert. | 321 // delete the cert. |
| 321 SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), | 322 SECKEYPrivateKey* privKey = |
| 322 NULL); | 323 PK11_FindKeyByAnyCert(cert->os_cert_handle(), NULL); |
| 323 if (privKey) { | 324 if (privKey) { |
| 324 SECKEY_DestroyPrivateKey(privKey); | 325 SECKEY_DestroyPrivateKey(privKey); |
| 325 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { | 326 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { |
| 326 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); | 327 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); |
| 327 return false; | 328 return false; |
| 328 } | 329 } |
| 329 } else { | 330 } else { |
| 330 if (SEC_DeletePermCertificate(cert->os_cert_handle())) { | 331 if (SEC_DeletePermCertificate(cert->os_cert_handle())) { |
| 331 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); | 332 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); |
| 332 return false; | 333 return false; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 360 const scoped_refptr<base::TaskRunner>& task_runner) { | 361 const scoped_refptr<base::TaskRunner>& task_runner) { |
| 361 slow_task_runner_for_test_ = task_runner; | 362 slow_task_runner_for_test_ = task_runner; |
| 362 } | 363 } |
| 363 | 364 |
| 364 // static | 365 // static |
| 365 void NSSCertDatabase::ListCertsImpl(CertificateList* certs) { | 366 void NSSCertDatabase::ListCertsImpl(CertificateList* certs) { |
| 366 certs->clear(); | 367 certs->clear(); |
| 367 | 368 |
| 368 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); | 369 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); |
| 369 CERTCertListNode* node; | 370 CERTCertListNode* node; |
| 370 for (node = CERT_LIST_HEAD(cert_list); | 371 for (node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); |
| 371 !CERT_LIST_END(node, cert_list); | |
| 372 node = CERT_LIST_NEXT(node)) { | 372 node = CERT_LIST_NEXT(node)) { |
| 373 certs->push_back(X509Certificate::CreateFromHandle( | 373 certs->push_back(X509Certificate::CreateFromHandle( |
| 374 node->cert, X509Certificate::OSCertHandles())); | 374 node->cert, X509Certificate::OSCertHandles())); |
| 375 } | 375 } |
| 376 CERT_DestroyCertList(cert_list); | 376 CERT_DestroyCertList(cert_list); |
| 377 } | 377 } |
| 378 | 378 |
| 379 scoped_refptr<base::TaskRunner> NSSCertDatabase::GetSlowTaskRunner() const { | 379 scoped_refptr<base::TaskRunner> NSSCertDatabase::GetSlowTaskRunner() const { |
| 380 if (slow_task_runner_for_test_) | 380 if (slow_task_runner_for_test_) |
| 381 return slow_task_runner_for_test_; | 381 return slow_task_runner_for_test_; |
| 382 return base::WorkerPool::GetTaskRunner(true /*task is slow*/); | 382 return base::WorkerPool::GetTaskRunner(true /*task is slow*/); |
| 383 } | 383 } |
| 384 | 384 |
| 385 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { | 385 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { |
| 386 observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); | 386 observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); |
| 387 } | 387 } |
| 388 | 388 |
| 389 void NSSCertDatabase::NotifyObserversOfCertRemoved( | 389 void NSSCertDatabase::NotifyObserversOfCertRemoved( |
| 390 const X509Certificate* cert) { | 390 const X509Certificate* cert) { |
| 391 observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); | 391 observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); |
| 392 } | 392 } |
| 393 | 393 |
| 394 void NSSCertDatabase::NotifyObserversOfCACertChanged( | 394 void NSSCertDatabase::NotifyObserversOfCACertChanged( |
| 395 const X509Certificate* cert) { | 395 const X509Certificate* cert) { |
| 396 observer_list_->Notify( | 396 observer_list_->Notify(&Observer::OnCACertChanged, make_scoped_refptr(cert)); |
| 397 &Observer::OnCACertChanged, make_scoped_refptr(cert)); | |
| 398 } | 397 } |
| 399 | 398 |
| 400 } // namespace net | 399 } // namespace net |
| OLD | NEW |