Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: net/base/nss_cert_database.cc

Issue 10916094: Move the NSS functions out of CertDatabase into a new NSSCertDatabase class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/base/cert_database.h" 5 #include "net/base/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"
16 #include "base/observer_list_threadsafe.h"
15 #include "crypto/nss_util.h" 17 #include "crypto/nss_util.h"
16 #include "crypto/nss_util_internal.h" 18 #include "crypto/nss_util_internal.h"
19 #include "net/base/cert_database.h"
17 #include "net/base/crypto_module.h" 20 #include "net/base/crypto_module.h"
18 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
19 #include "net/base/x509_certificate.h" 22 #include "net/base/x509_certificate.h"
20 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" 23 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
21 #include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" 24 #include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"
22 25
23 // In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use 26 // In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use
24 // the new name of the macro. 27 // the new name of the macro.
25 #if !defined(CERTDB_TERMINAL_RECORD) 28 #if !defined(CERTDB_TERMINAL_RECORD)
26 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER 29 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
27 #endif 30 #endif
28 31
29 // PSM = Mozilla's Personal Security Manager. 32 // PSM = Mozilla's Personal Security Manager.
30 namespace psm = mozilla_security_manager; 33 namespace psm = mozilla_security_manager;
31 34
32 namespace net { 35 namespace net {
33 36
34 CertDatabase::CertDatabase() { 37 namespace {
35 crypto::EnsureNSSInit(); 38
36 psm::EnsurePKCS12Init(); 39 // Notifies registered observers when new user certificates are added to the
37 } 40 // database.
41 class NSSCertDatabaseNotifier {
42 public:
43 NSSCertDatabaseNotifier()
44 : observer_list_(new ObserverListThreadSafe<NSSCertDatabase::Observer>) {}
45
46 static NSSCertDatabaseNotifier* GetInstance() {
47 return Singleton<NSSCertDatabaseNotifier>::get();
48 }
49
50 private:
51 friend struct DefaultSingletonTraits<NSSCertDatabaseNotifier>;
52 friend class net::NSSCertDatabase;
53
54 const scoped_refptr<ObserverListThreadSafe<NSSCertDatabase::Observer> >
55 observer_list_;
56 };
57
58 } // namespace
59
60 // CertDatabase ----------------------------------------------------------------
38 61
39 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { 62 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) {
40 if (!cert_obj) 63 if (!cert_obj)
41 return ERR_CERT_INVALID; 64 return ERR_CERT_INVALID;
42 if (cert_obj->HasExpired()) 65 if (cert_obj->HasExpired())
43 return ERR_CERT_DATE_INVALID; 66 return ERR_CERT_DATE_INVALID;
44 67
45 // Check if the private key corresponding to the certificate exist 68 // Check if the private key corresponding to the certificate exist
46 // We shouldn't accept any random client certificate sent by a CA. 69 // We shouldn't accept any random client certificate sent by a CA.
47 70
(...skipping 21 matching lines...) Expand all
69 cert, 92 cert,
70 cert_obj->GetDefaultNickname(net::USER_CERT).c_str(), 93 cert_obj->GetDefaultNickname(net::USER_CERT).c_str(),
71 NULL); 94 NULL);
72 } 95 }
73 96
74 if (!slot) { 97 if (!slot) {
75 LOG(ERROR) << "Couldn't import user certificate."; 98 LOG(ERROR) << "Couldn't import user certificate.";
76 return ERR_ADD_USER_CERT_FAILED; 99 return ERR_ADD_USER_CERT_FAILED;
77 } 100 }
78 PK11_FreeSlot(slot); 101 PK11_FreeSlot(slot);
79 CertDatabase::NotifyObserversOfUserCertAdded(cert_obj); 102 NotifyObserversOfCertAdded(cert_obj);
80 return OK; 103 return OK;
81 } 104 }
82 105
83 void CertDatabase::ListCerts(CertificateList* certs) { 106 // NSSCertDatabase::ImportCertFailure ------------------------------------------
107
108 NSSCertDatabase::ImportCertFailure::ImportCertFailure(
109 X509Certificate* cert, int err)
110 : certificate(cert),
111 net_error(err) {}
112
113 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {}
114
115 // NSSCertDatabase -------------------------------------------------------------
116
117 NSSCertDatabase::NSSCertDatabase() {
118 EnsureInit();
119 }
120
121 // static
122 void NSSCertDatabase::EnsureInit() {
123 crypto::EnsureNSSInit();
124 psm::EnsurePKCS12Init();
125 }
126
127 void NSSCertDatabase::ListCerts(CertificateList* certs) {
84 certs->clear(); 128 certs->clear();
85 129
86 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); 130 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL);
87 CERTCertListNode* node; 131 CERTCertListNode* node;
88 for (node = CERT_LIST_HEAD(cert_list); 132 for (node = CERT_LIST_HEAD(cert_list);
89 !CERT_LIST_END(node, cert_list); 133 !CERT_LIST_END(node, cert_list);
90 node = CERT_LIST_NEXT(node)) { 134 node = CERT_LIST_NEXT(node)) {
91 certs->push_back(X509Certificate::CreateFromHandle( 135 certs->push_back(X509Certificate::CreateFromHandle(
92 node->cert, X509Certificate::OSCertHandles())); 136 node->cert, X509Certificate::OSCertHandles()));
93 } 137 }
94 CERT_DestroyCertList(cert_list); 138 CERT_DestroyCertList(cert_list);
95 } 139 }
96 140
97 CryptoModule* CertDatabase::GetPublicModule() const { 141 CryptoModule* NSSCertDatabase::GetPublicModule() const {
98 CryptoModule* module = 142 CryptoModule* module =
99 CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot()); 143 CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot());
100 // The module is already referenced when returned from 144 // The module is already referenced when returned from
101 // GetPublicNSSKeySlot, so we need to deref it once. 145 // GetPublicNSSKeySlot, so we need to deref it once.
102 PK11_FreeSlot(module->os_module_handle()); 146 PK11_FreeSlot(module->os_module_handle());
103 147
104 return module; 148 return module;
105 } 149 }
106 150
107 CryptoModule* CertDatabase::GetPrivateModule() const { 151 CryptoModule* NSSCertDatabase::GetPrivateModule() const {
108 CryptoModule* module = 152 CryptoModule* module =
109 CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot()); 153 CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot());
110 // The module is already referenced when returned from 154 // The module is already referenced when returned from
111 // GetPrivateNSSKeySlot, so we need to deref it once. 155 // GetPrivateNSSKeySlot, so we need to deref it once.
112 PK11_FreeSlot(module->os_module_handle()); 156 PK11_FreeSlot(module->os_module_handle());
113 157
114 return module; 158 return module;
115 } 159 }
116 160
117 void CertDatabase::ListModules(CryptoModuleList* modules, bool need_rw) const { 161 void NSSCertDatabase::ListModules(CryptoModuleList* modules,
162 bool need_rw) const {
118 modules->clear(); 163 modules->clear();
119 164
120 PK11SlotList* slot_list = NULL; 165 PK11SlotList* slot_list = NULL;
121 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. 166 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
122 slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 167 slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
123 need_rw ? PR_TRUE : PR_FALSE, // needRW 168 need_rw ? PR_TRUE : PR_FALSE, // needRW
124 PR_TRUE, // loadCerts (unused) 169 PR_TRUE, // loadCerts (unused)
125 NULL); // wincx 170 NULL); // wincx
126 if (!slot_list) { 171 if (!slot_list) {
127 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); 172 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError();
128 return; 173 return;
129 } 174 }
130 175
131 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list); 176 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list);
132 while (slot_element) { 177 while (slot_element) {
133 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); 178 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot));
134 slot_element = PK11_GetNextSafe(slot_list, slot_element, 179 slot_element = PK11_GetNextSafe(slot_list, slot_element,
135 PR_FALSE); // restart 180 PR_FALSE); // restart
136 } 181 }
137 182
138 PK11_FreeSlotList(slot_list); 183 PK11_FreeSlotList(slot_list);
139 } 184 }
140 185
141 int CertDatabase::ImportFromPKCS12( 186 int NSSCertDatabase::ImportFromPKCS12(
142 CryptoModule* module, 187 CryptoModule* module,
143 const std::string& data, 188 const std::string& data,
144 const string16& password, 189 const string16& password,
145 bool is_extractable, 190 bool is_extractable,
146 net::CertificateList* imported_certs) { 191 net::CertificateList* imported_certs) {
147 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), 192 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(),
148 data.data(), data.size(), 193 data.data(), data.size(),
149 password, 194 password,
150 is_extractable, 195 is_extractable,
151 imported_certs); 196 imported_certs);
152 if (result == net::OK) 197 if (result == net::OK)
153 CertDatabase::NotifyObserversOfUserCertAdded(NULL); 198 NotifyObserversOfCertAdded(NULL);
154 199
155 return result; 200 return result;
156 } 201 }
157 202
158 int CertDatabase::ExportToPKCS12( 203 int NSSCertDatabase::ExportToPKCS12(
159 const CertificateList& certs, 204 const CertificateList& certs,
160 const string16& password, 205 const string16& password,
161 std::string* output) const { 206 std::string* output) const {
162 return psm::nsPKCS12Blob_Export(output, certs, password); 207 return psm::nsPKCS12Blob_Export(output, certs, password);
163 } 208 }
164 209
165 X509Certificate* CertDatabase::FindRootInList( 210 X509Certificate* NSSCertDatabase::FindRootInList(
166 const CertificateList& certificates) const { 211 const CertificateList& certificates) const {
167 DCHECK_GT(certificates.size(), 0U); 212 DCHECK_GT(certificates.size(), 0U);
168 213
169 if (certificates.size() == 1) 214 if (certificates.size() == 1)
170 return certificates[0].get(); 215 return certificates[0].get();
171 216
172 X509Certificate* cert0 = certificates[0]; 217 X509Certificate* cert0 = certificates[0];
173 X509Certificate* cert1 = certificates[1]; 218 X509Certificate* cert1 = certificates[1];
174 X509Certificate* certn_2 = certificates[certificates.size() - 2]; 219 X509Certificate* certn_2 = certificates[certificates.size() - 2];
175 X509Certificate* certn_1 = certificates[certificates.size() - 1]; 220 X509Certificate* certn_1 = certificates[certificates.size() - 1];
176 221
177 if (CERT_CompareName(&cert1->os_cert_handle()->issuer, 222 if (CERT_CompareName(&cert1->os_cert_handle()->issuer,
178 &cert0->os_cert_handle()->subject) == SECEqual) 223 &cert0->os_cert_handle()->subject) == SECEqual)
179 return cert0; 224 return cert0;
180 if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, 225 if (CERT_CompareName(&certn_2->os_cert_handle()->issuer,
181 &certn_1->os_cert_handle()->subject) == SECEqual) 226 &certn_1->os_cert_handle()->subject) == SECEqual)
182 return certn_1; 227 return certn_1;
183 228
184 VLOG(1) << "certificate list is not a hierarchy"; 229 VLOG(1) << "certificate list is not a hierarchy";
185 return cert0; 230 return cert0;
186 } 231 }
187 232
188 bool CertDatabase::ImportCACerts(const CertificateList& certificates, 233 bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates,
189 TrustBits trust_bits, 234 TrustBits trust_bits,
190 ImportCertFailureList* not_imported) { 235 ImportCertFailureList* not_imported) {
191 X509Certificate* root = FindRootInList(certificates); 236 X509Certificate* root = FindRootInList(certificates);
192 bool success = psm::ImportCACerts(certificates, root, trust_bits, 237 bool success = psm::ImportCACerts(certificates, root, trust_bits,
193 not_imported); 238 not_imported);
194 if (success) 239 if (success)
195 CertDatabase::NotifyObserversOfCertTrustChanged(NULL); 240 NotifyObserversOfCertTrustChanged(NULL);
196 241
197 return success; 242 return success;
198 } 243 }
199 244
200 bool CertDatabase::ImportServerCert(const CertificateList& certificates, 245 bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates,
201 TrustBits trust_bits, 246 TrustBits trust_bits,
202 ImportCertFailureList* not_imported) { 247 ImportCertFailureList* not_imported) {
203 return psm::ImportServerCert(certificates, trust_bits, not_imported); 248 return psm::ImportServerCert(certificates, trust_bits, not_imported);
204 } 249 }
205 250
206 CertDatabase::TrustBits CertDatabase::GetCertTrust(const X509Certificate* cert, 251 NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust(
207 CertType type) const { 252 const X509Certificate* cert,
253 CertType type) const {
208 CERTCertTrust trust; 254 CERTCertTrust trust;
209 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); 255 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust);
210 if (srv != SECSuccess) { 256 if (srv != SECSuccess) {
211 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 257 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError();
212 return TRUST_DEFAULT; 258 return TRUST_DEFAULT;
213 } 259 }
214 // We define our own more "friendly" TrustBits, which means we aren't able to 260 // We define our own more "friendly" TrustBits, which means we aren't able to
215 // round-trip all possible NSS trust flag combinations. We try to map them in 261 // round-trip all possible NSS trust flag combinations. We try to map them in
216 // a sensible way. 262 // a sensible way.
217 switch (type) { 263 switch (type) {
(...skipping 24 matching lines...) Expand all
242 if (trust.sslFlags & CERTDB_TRUSTED) 288 if (trust.sslFlags & CERTDB_TRUSTED)
243 return TRUSTED_SSL; 289 return TRUSTED_SSL;
244 return DISTRUSTED_SSL; 290 return DISTRUSTED_SSL;
245 } 291 }
246 return TRUST_DEFAULT; 292 return TRUST_DEFAULT;
247 default: 293 default:
248 return TRUST_DEFAULT; 294 return TRUST_DEFAULT;
249 } 295 }
250 } 296 }
251 297
252 bool CertDatabase::IsUntrusted(const X509Certificate* cert) const { 298 bool NSSCertDatabase::IsUntrusted(const X509Certificate* cert) const {
253 CERTCertTrust nsstrust; 299 CERTCertTrust nsstrust;
254 SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); 300 SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust);
255 if (rv != SECSuccess) { 301 if (rv != SECSuccess) {
256 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 302 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError();
257 return false; 303 return false;
258 } 304 }
259 305
260 // The CERTCertTrust structure contains three trust records: 306 // The CERTCertTrust structure contains three trust records:
261 // sslFlags, emailFlags, and objectSigningFlags. The three 307 // sslFlags, emailFlags, and objectSigningFlags. The three
262 // trust records are independent of each other. 308 // trust records are independent of each other.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 if (CERT_CompareName(&cert->os_cert_handle()->issuer, 341 if (CERT_CompareName(&cert->os_cert_handle()->issuer,
296 &cert->os_cert_handle()->subject) == SECEqual) { 342 &cert->os_cert_handle()->subject) == SECEqual) {
297 return (nsstrust.sslFlags & kTrusted) == 0 && 343 return (nsstrust.sslFlags & kTrusted) == 0 &&
298 (nsstrust.emailFlags & kTrusted) == 0 && 344 (nsstrust.emailFlags & kTrusted) == 0 &&
299 (nsstrust.objectSigningFlags & kTrusted) == 0; 345 (nsstrust.objectSigningFlags & kTrusted) == 0;
300 } 346 }
301 347
302 return false; 348 return false;
303 } 349 }
304 350
305 bool CertDatabase::SetCertTrust(const X509Certificate* cert, 351 bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert,
306 CertType type, 352 CertType type,
307 TrustBits trust_bits) { 353 TrustBits trust_bits) {
308 bool success = psm::SetCertTrust(cert, type, trust_bits); 354 bool success = psm::SetCertTrust(cert, type, trust_bits);
309 if (success) 355 if (success)
310 CertDatabase::NotifyObserversOfCertTrustChanged(cert); 356 NotifyObserversOfCertTrustChanged(cert);
311 357
312 return success; 358 return success;
313 } 359 }
314 360
315 bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { 361 bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
316 // For some reason, PK11_DeleteTokenCertAndKey only calls 362 // For some reason, PK11_DeleteTokenCertAndKey only calls
317 // SEC_DeletePermCertificate if the private key is found. So, we check 363 // SEC_DeletePermCertificate if the private key is found. So, we check
318 // whether a private key exists before deciding which function to call to 364 // whether a private key exists before deciding which function to call to
319 // delete the cert. 365 // delete the cert.
320 SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), 366 SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(),
321 NULL); 367 NULL);
322 if (privKey) { 368 if (privKey) {
323 SECKEY_DestroyPrivateKey(privKey); 369 SECKEY_DestroyPrivateKey(privKey);
324 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { 370 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) {
325 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); 371 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError();
326 return false; 372 return false;
327 } 373 }
328 } else { 374 } else {
329 if (SEC_DeletePermCertificate(cert->os_cert_handle())) { 375 if (SEC_DeletePermCertificate(cert->os_cert_handle())) {
330 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); 376 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError();
331 return false; 377 return false;
332 } 378 }
333 } 379 }
334 380
335 CertDatabase::NotifyObserversOfUserCertRemoved(cert); 381 NotifyObserversOfCertRemoved(cert);
336 382
337 return true; 383 return true;
338 } 384 }
339 385
340 bool CertDatabase::IsReadOnly(const X509Certificate* cert) const { 386 bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const {
341 PK11SlotInfo* slot = cert->os_cert_handle()->slot; 387 PK11SlotInfo* slot = cert->os_cert_handle()->slot;
342 return slot && PK11_IsReadOnly(slot); 388 return slot && PK11_IsReadOnly(slot);
343 } 389 }
344 390
391 void NSSCertDatabase::AddObserver(Observer* observer) {
392 NSSCertDatabaseNotifier::GetInstance()->observer_list_->AddObserver(observer);
393 }
394
395 void NSSCertDatabase::RemoveObserver(Observer* observer) {
396 NSSCertDatabaseNotifier::GetInstance()->observer_list_->RemoveObserver(
397 observer);
398 }
399
400 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
401 NSSCertDatabaseNotifier::GetInstance()->observer_list_->Notify(
402 &Observer::OnCertAdded, make_scoped_refptr(cert));
403 }
404
405 void NSSCertDatabase::NotifyObserversOfCertRemoved(
406 const X509Certificate* cert) {
407 NSSCertDatabaseNotifier::GetInstance()->observer_list_->Notify(
408 &Observer::OnCertRemoved, make_scoped_refptr(cert));
409 }
410
411 void NSSCertDatabase::NotifyObserversOfCertTrustChanged(
412 const X509Certificate* cert) {
413 NSSCertDatabaseNotifier::GetInstance()->observer_list_->Notify(
414 &Observer::OnCertTrustChanged, make_scoped_refptr(cert));
415 }
416
345 } // namespace net 417 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698