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 |