| 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/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 NSSCertDatabase::ImportCertFailure::ImportCertFailure( |
| 38 X509Certificate* cert, int err) |
| 39 : certificate(cert), |
| 40 net_error(err) {} |
| 41 |
| 42 NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} |
| 43 |
| 44 // static |
| 45 NSSCertDatabase* NSSCertDatabase::GetInstance() { |
| 46 return Singleton<NSSCertDatabase>::get(); |
| 47 } |
| 48 |
| 49 NSSCertDatabase::NSSCertDatabase() |
| 50 : observer_list_(new ObserverListThreadSafe<Observer>) { |
| 35 crypto::EnsureNSSInit(); | 51 crypto::EnsureNSSInit(); |
| 36 psm::EnsurePKCS12Init(); | 52 psm::EnsurePKCS12Init(); |
| 37 } | 53 } |
| 38 | 54 |
| 39 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { | 55 NSSCertDatabase::~NSSCertDatabase() {} |
| 40 if (!cert_obj) | |
| 41 return ERR_CERT_INVALID; | |
| 42 if (cert_obj->HasExpired()) | |
| 43 return ERR_CERT_DATE_INVALID; | |
| 44 | 56 |
| 45 // Check if the private key corresponding to the certificate exist | 57 void NSSCertDatabase::ListCerts(CertificateList* certs) { |
| 46 // We shouldn't accept any random client certificate sent by a CA. | |
| 47 | |
| 48 // Note: The NSS source documentation wrongly suggests that this | |
| 49 // also imports the certificate if the private key exists. This | |
| 50 // doesn't seem to be the case. | |
| 51 | |
| 52 CERTCertificate* cert = cert_obj->os_cert_handle(); | |
| 53 PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL); | |
| 54 if (!slot) | |
| 55 return ERR_NO_PRIVATE_KEY_FOR_CERT; | |
| 56 | |
| 57 PK11_FreeSlot(slot); | |
| 58 | |
| 59 return OK; | |
| 60 } | |
| 61 | |
| 62 int CertDatabase::AddUserCert(X509Certificate* cert_obj) { | |
| 63 CERTCertificate* cert = cert_obj->os_cert_handle(); | |
| 64 PK11SlotInfo* slot = NULL; | |
| 65 | |
| 66 { | |
| 67 crypto::AutoNSSWriteLock lock; | |
| 68 slot = PK11_ImportCertForKey( | |
| 69 cert, | |
| 70 cert_obj->GetDefaultNickname(net::USER_CERT).c_str(), | |
| 71 NULL); | |
| 72 } | |
| 73 | |
| 74 if (!slot) { | |
| 75 LOG(ERROR) << "Couldn't import user certificate."; | |
| 76 return ERR_ADD_USER_CERT_FAILED; | |
| 77 } | |
| 78 PK11_FreeSlot(slot); | |
| 79 CertDatabase::NotifyObserversOfUserCertAdded(cert_obj); | |
| 80 return OK; | |
| 81 } | |
| 82 | |
| 83 void CertDatabase::ListCerts(CertificateList* certs) { | |
| 84 certs->clear(); | 58 certs->clear(); |
| 85 | 59 |
| 86 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); | 60 CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); |
| 87 CERTCertListNode* node; | 61 CERTCertListNode* node; |
| 88 for (node = CERT_LIST_HEAD(cert_list); | 62 for (node = CERT_LIST_HEAD(cert_list); |
| 89 !CERT_LIST_END(node, cert_list); | 63 !CERT_LIST_END(node, cert_list); |
| 90 node = CERT_LIST_NEXT(node)) { | 64 node = CERT_LIST_NEXT(node)) { |
| 91 certs->push_back(X509Certificate::CreateFromHandle( | 65 certs->push_back(X509Certificate::CreateFromHandle( |
| 92 node->cert, X509Certificate::OSCertHandles())); | 66 node->cert, X509Certificate::OSCertHandles())); |
| 93 } | 67 } |
| 94 CERT_DestroyCertList(cert_list); | 68 CERT_DestroyCertList(cert_list); |
| 95 } | 69 } |
| 96 | 70 |
| 97 CryptoModule* CertDatabase::GetPublicModule() const { | 71 CryptoModule* NSSCertDatabase::GetPublicModule() const { |
| 98 CryptoModule* module = | 72 CryptoModule* module = |
| 99 CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot()); | 73 CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot()); |
| 100 // The module is already referenced when returned from | 74 // The module is already referenced when returned from |
| 101 // GetPublicNSSKeySlot, so we need to deref it once. | 75 // GetPublicNSSKeySlot, so we need to deref it once. |
| 102 PK11_FreeSlot(module->os_module_handle()); | 76 PK11_FreeSlot(module->os_module_handle()); |
| 103 | 77 |
| 104 return module; | 78 return module; |
| 105 } | 79 } |
| 106 | 80 |
| 107 CryptoModule* CertDatabase::GetPrivateModule() const { | 81 CryptoModule* NSSCertDatabase::GetPrivateModule() const { |
| 108 CryptoModule* module = | 82 CryptoModule* module = |
| 109 CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot()); | 83 CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot()); |
| 110 // The module is already referenced when returned from | 84 // The module is already referenced when returned from |
| 111 // GetPrivateNSSKeySlot, so we need to deref it once. | 85 // GetPrivateNSSKeySlot, so we need to deref it once. |
| 112 PK11_FreeSlot(module->os_module_handle()); | 86 PK11_FreeSlot(module->os_module_handle()); |
| 113 | 87 |
| 114 return module; | 88 return module; |
| 115 } | 89 } |
| 116 | 90 |
| 117 void CertDatabase::ListModules(CryptoModuleList* modules, bool need_rw) const { | 91 void NSSCertDatabase::ListModules(CryptoModuleList* modules, |
| 92 bool need_rw) const { |
| 118 modules->clear(); | 93 modules->clear(); |
| 119 | 94 |
| 120 PK11SlotList* slot_list = NULL; | 95 PK11SlotList* slot_list = NULL; |
| 121 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. | 96 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. |
| 122 slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, | 97 slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, |
| 123 need_rw ? PR_TRUE : PR_FALSE, // needRW | 98 need_rw ? PR_TRUE : PR_FALSE, // needRW |
| 124 PR_TRUE, // loadCerts (unused) | 99 PR_TRUE, // loadCerts (unused) |
| 125 NULL); // wincx | 100 NULL); // wincx |
| 126 if (!slot_list) { | 101 if (!slot_list) { |
| 127 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); | 102 LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); |
| 128 return; | 103 return; |
| 129 } | 104 } |
| 130 | 105 |
| 131 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list); | 106 PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list); |
| 132 while (slot_element) { | 107 while (slot_element) { |
| 133 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); | 108 modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); |
| 134 slot_element = PK11_GetNextSafe(slot_list, slot_element, | 109 slot_element = PK11_GetNextSafe(slot_list, slot_element, |
| 135 PR_FALSE); // restart | 110 PR_FALSE); // restart |
| 136 } | 111 } |
| 137 | 112 |
| 138 PK11_FreeSlotList(slot_list); | 113 PK11_FreeSlotList(slot_list); |
| 139 } | 114 } |
| 140 | 115 |
| 141 int CertDatabase::ImportFromPKCS12( | 116 int NSSCertDatabase::ImportFromPKCS12( |
| 142 CryptoModule* module, | 117 CryptoModule* module, |
| 143 const std::string& data, | 118 const std::string& data, |
| 144 const string16& password, | 119 const string16& password, |
| 145 bool is_extractable, | 120 bool is_extractable, |
| 146 net::CertificateList* imported_certs) { | 121 net::CertificateList* imported_certs) { |
| 147 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), | 122 int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), |
| 148 data.data(), data.size(), | 123 data.data(), data.size(), |
| 149 password, | 124 password, |
| 150 is_extractable, | 125 is_extractable, |
| 151 imported_certs); | 126 imported_certs); |
| 152 if (result == net::OK) | 127 if (result == net::OK) |
| 153 CertDatabase::NotifyObserversOfUserCertAdded(NULL); | 128 NotifyObserversOfCertAdded(NULL); |
| 154 | 129 |
| 155 return result; | 130 return result; |
| 156 } | 131 } |
| 157 | 132 |
| 158 int CertDatabase::ExportToPKCS12( | 133 int NSSCertDatabase::ExportToPKCS12( |
| 159 const CertificateList& certs, | 134 const CertificateList& certs, |
| 160 const string16& password, | 135 const string16& password, |
| 161 std::string* output) const { | 136 std::string* output) const { |
| 162 return psm::nsPKCS12Blob_Export(output, certs, password); | 137 return psm::nsPKCS12Blob_Export(output, certs, password); |
| 163 } | 138 } |
| 164 | 139 |
| 165 X509Certificate* CertDatabase::FindRootInList( | 140 X509Certificate* NSSCertDatabase::FindRootInList( |
| 166 const CertificateList& certificates) const { | 141 const CertificateList& certificates) const { |
| 167 DCHECK_GT(certificates.size(), 0U); | 142 DCHECK_GT(certificates.size(), 0U); |
| 168 | 143 |
| 169 if (certificates.size() == 1) | 144 if (certificates.size() == 1) |
| 170 return certificates[0].get(); | 145 return certificates[0].get(); |
| 171 | 146 |
| 172 X509Certificate* cert0 = certificates[0]; | 147 X509Certificate* cert0 = certificates[0]; |
| 173 X509Certificate* cert1 = certificates[1]; | 148 X509Certificate* cert1 = certificates[1]; |
| 174 X509Certificate* certn_2 = certificates[certificates.size() - 2]; | 149 X509Certificate* certn_2 = certificates[certificates.size() - 2]; |
| 175 X509Certificate* certn_1 = certificates[certificates.size() - 1]; | 150 X509Certificate* certn_1 = certificates[certificates.size() - 1]; |
| 176 | 151 |
| 177 if (CERT_CompareName(&cert1->os_cert_handle()->issuer, | 152 if (CERT_CompareName(&cert1->os_cert_handle()->issuer, |
| 178 &cert0->os_cert_handle()->subject) == SECEqual) | 153 &cert0->os_cert_handle()->subject) == SECEqual) |
| 179 return cert0; | 154 return cert0; |
| 180 if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, | 155 if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, |
| 181 &certn_1->os_cert_handle()->subject) == SECEqual) | 156 &certn_1->os_cert_handle()->subject) == SECEqual) |
| 182 return certn_1; | 157 return certn_1; |
| 183 | 158 |
| 184 VLOG(1) << "certificate list is not a hierarchy"; | 159 VLOG(1) << "certificate list is not a hierarchy"; |
| 185 return cert0; | 160 return cert0; |
| 186 } | 161 } |
| 187 | 162 |
| 188 bool CertDatabase::ImportCACerts(const CertificateList& certificates, | 163 bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, |
| 189 TrustBits trust_bits, | 164 TrustBits trust_bits, |
| 190 ImportCertFailureList* not_imported) { | 165 ImportCertFailureList* not_imported) { |
| 191 X509Certificate* root = FindRootInList(certificates); | 166 X509Certificate* root = FindRootInList(certificates); |
| 192 bool success = psm::ImportCACerts(certificates, root, trust_bits, | 167 bool success = psm::ImportCACerts(certificates, root, trust_bits, |
| 193 not_imported); | 168 not_imported); |
| 194 if (success) | 169 if (success) |
| 195 CertDatabase::NotifyObserversOfCertTrustChanged(NULL); | 170 NotifyObserversOfCertTrustChanged(NULL); |
| 196 | 171 |
| 197 return success; | 172 return success; |
| 198 } | 173 } |
| 199 | 174 |
| 200 bool CertDatabase::ImportServerCert(const CertificateList& certificates, | 175 bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, |
| 201 TrustBits trust_bits, | 176 TrustBits trust_bits, |
| 202 ImportCertFailureList* not_imported) { | 177 ImportCertFailureList* not_imported) { |
| 203 return psm::ImportServerCert(certificates, trust_bits, not_imported); | 178 return psm::ImportServerCert(certificates, trust_bits, not_imported); |
| 204 } | 179 } |
| 205 | 180 |
| 206 CertDatabase::TrustBits CertDatabase::GetCertTrust(const X509Certificate* cert, | 181 NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( |
| 207 CertType type) const { | 182 const X509Certificate* cert, |
| 183 CertType type) const { |
| 208 CERTCertTrust trust; | 184 CERTCertTrust trust; |
| 209 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); | 185 SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); |
| 210 if (srv != SECSuccess) { | 186 if (srv != SECSuccess) { |
| 211 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); | 187 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); |
| 212 return TRUST_DEFAULT; | 188 return TRUST_DEFAULT; |
| 213 } | 189 } |
| 214 // We define our own more "friendly" TrustBits, which means we aren't able to | 190 // 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 | 191 // round-trip all possible NSS trust flag combinations. We try to map them in |
| 216 // a sensible way. | 192 // a sensible way. |
| 217 switch (type) { | 193 switch (type) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 242 if (trust.sslFlags & CERTDB_TRUSTED) | 218 if (trust.sslFlags & CERTDB_TRUSTED) |
| 243 return TRUSTED_SSL; | 219 return TRUSTED_SSL; |
| 244 return DISTRUSTED_SSL; | 220 return DISTRUSTED_SSL; |
| 245 } | 221 } |
| 246 return TRUST_DEFAULT; | 222 return TRUST_DEFAULT; |
| 247 default: | 223 default: |
| 248 return TRUST_DEFAULT; | 224 return TRUST_DEFAULT; |
| 249 } | 225 } |
| 250 } | 226 } |
| 251 | 227 |
| 252 bool CertDatabase::IsUntrusted(const X509Certificate* cert) const { | 228 bool NSSCertDatabase::IsUntrusted(const X509Certificate* cert) const { |
| 253 CERTCertTrust nsstrust; | 229 CERTCertTrust nsstrust; |
| 254 SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); | 230 SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); |
| 255 if (rv != SECSuccess) { | 231 if (rv != SECSuccess) { |
| 256 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); | 232 LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); |
| 257 return false; | 233 return false; |
| 258 } | 234 } |
| 259 | 235 |
| 260 // The CERTCertTrust structure contains three trust records: | 236 // The CERTCertTrust structure contains three trust records: |
| 261 // sslFlags, emailFlags, and objectSigningFlags. The three | 237 // sslFlags, emailFlags, and objectSigningFlags. The three |
| 262 // trust records are independent of each other. | 238 // trust records are independent of each other. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 if (CERT_CompareName(&cert->os_cert_handle()->issuer, | 271 if (CERT_CompareName(&cert->os_cert_handle()->issuer, |
| 296 &cert->os_cert_handle()->subject) == SECEqual) { | 272 &cert->os_cert_handle()->subject) == SECEqual) { |
| 297 return (nsstrust.sslFlags & kTrusted) == 0 && | 273 return (nsstrust.sslFlags & kTrusted) == 0 && |
| 298 (nsstrust.emailFlags & kTrusted) == 0 && | 274 (nsstrust.emailFlags & kTrusted) == 0 && |
| 299 (nsstrust.objectSigningFlags & kTrusted) == 0; | 275 (nsstrust.objectSigningFlags & kTrusted) == 0; |
| 300 } | 276 } |
| 301 | 277 |
| 302 return false; | 278 return false; |
| 303 } | 279 } |
| 304 | 280 |
| 305 bool CertDatabase::SetCertTrust(const X509Certificate* cert, | 281 bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, |
| 306 CertType type, | 282 CertType type, |
| 307 TrustBits trust_bits) { | 283 TrustBits trust_bits) { |
| 308 bool success = psm::SetCertTrust(cert, type, trust_bits); | 284 bool success = psm::SetCertTrust(cert, type, trust_bits); |
| 309 if (success) | 285 if (success) |
| 310 CertDatabase::NotifyObserversOfCertTrustChanged(cert); | 286 NotifyObserversOfCertTrustChanged(cert); |
| 311 | 287 |
| 312 return success; | 288 return success; |
| 313 } | 289 } |
| 314 | 290 |
| 315 bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { | 291 bool NSSCertDatabase::DeleteCertAndKey(const X509Certificate* cert) { |
| 316 // For some reason, PK11_DeleteTokenCertAndKey only calls | 292 // For some reason, PK11_DeleteTokenCertAndKey only calls |
| 317 // SEC_DeletePermCertificate if the private key is found. So, we check | 293 // SEC_DeletePermCertificate if the private key is found. So, we check |
| 318 // whether a private key exists before deciding which function to call to | 294 // whether a private key exists before deciding which function to call to |
| 319 // delete the cert. | 295 // delete the cert. |
| 320 SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), | 296 SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), |
| 321 NULL); | 297 NULL); |
| 322 if (privKey) { | 298 if (privKey) { |
| 323 SECKEY_DestroyPrivateKey(privKey); | 299 SECKEY_DestroyPrivateKey(privKey); |
| 324 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { | 300 if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { |
| 325 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); | 301 LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); |
| 326 return false; | 302 return false; |
| 327 } | 303 } |
| 328 } else { | 304 } else { |
| 329 if (SEC_DeletePermCertificate(cert->os_cert_handle())) { | 305 if (SEC_DeletePermCertificate(cert->os_cert_handle())) { |
| 330 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); | 306 LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); |
| 331 return false; | 307 return false; |
| 332 } | 308 } |
| 333 } | 309 } |
| 334 | 310 |
| 335 CertDatabase::NotifyObserversOfUserCertRemoved(cert); | 311 NotifyObserversOfCertRemoved(cert); |
| 336 | 312 |
| 337 return true; | 313 return true; |
| 338 } | 314 } |
| 339 | 315 |
| 340 bool CertDatabase::IsReadOnly(const X509Certificate* cert) const { | 316 bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { |
| 341 PK11SlotInfo* slot = cert->os_cert_handle()->slot; | 317 PK11SlotInfo* slot = cert->os_cert_handle()->slot; |
| 342 return slot && PK11_IsReadOnly(slot); | 318 return slot && PK11_IsReadOnly(slot); |
| 343 } | 319 } |
| 344 | 320 |
| 321 void NSSCertDatabase::AddObserver(Observer* observer) { |
| 322 observer_list_->AddObserver(observer); |
| 323 } |
| 324 |
| 325 void NSSCertDatabase::RemoveObserver(Observer* observer) { |
| 326 observer_list_->RemoveObserver(observer); |
| 327 } |
| 328 |
| 329 void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { |
| 330 observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); |
| 331 } |
| 332 |
| 333 void NSSCertDatabase::NotifyObserversOfCertRemoved( |
| 334 const X509Certificate* cert) { |
| 335 observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); |
| 336 } |
| 337 |
| 338 void NSSCertDatabase::NotifyObserversOfCertTrustChanged( |
| 339 const X509Certificate* cert) { |
| 340 observer_list_->Notify( |
| 341 &Observer::OnCertTrustChanged, make_scoped_refptr(cert)); |
| 342 } |
| 343 |
| 345 } // namespace net | 344 } // namespace net |
| OLD | NEW |