1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "crypto/scoped_test_nss_db.h" 6 7 #include <cert.h> 8 9 #include "base/logging.h" 10 #include "base/threading/thread_restrictions.h" 11 #include "crypto/nss_util.h" 12 #include "crypto/nss_util_internal.h" 13 14 namespace crypto { 15 16 ScopedTestNSSDB::ScopedTestNSSDB() { 17 EnsureNSSInit(); 18 // NSS is allowed to do IO on the current thread since dispatching 19 // to a dedicated thread would still have the affect of blocking 20 // the current thread, due to NSS's internal locking requirements 21 base::ThreadRestrictions::ScopedAllowIO allow_io; 22 23 if (!temp_dir_.CreateUniqueTempDir()) 24 return; 25 26 const char kTestDescription[] = "Test DB"; 27 slot_ = OpenSoftwareNSSDB(temp_dir_.path(), kTestDescription); 28 } 29 30 ScopedTestNSSDB::~ScopedTestNSSDB() { 31 // Remove trust from any certs in the test DB before closing it. Otherwise NSS 32 // may cache verification results even after the test DB is gone. 33 if (slot_) { 34 CERTCertList* cert_list = PK11_ListCertsInSlot(slot_.get()); 35 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 36 !CERT_LIST_END(node, cert_list); 37 node = CERT_LIST_NEXT(node)) { 38 CERTCertTrust trust = {0}; 39 if (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), node->cert, &trust) != 40 SECSuccess) { 41 LOG(ERROR) << "CERT_ChangeCertTrust failed: " << PORT_GetError(); 42 } 43 } 44 CERT_DestroyCertList(cert_list); 45 } 46 47 // Don't close when NSS is < 3.15.1, because it would require an additional 48 // sleep for 1 second after closing the database, due to 49 // http://bugzil.la/875601. 50 if (!NSS_VersionCheck("3.15.1")) { 51 LOG(ERROR) << "NSS version is < 3.15.1, test DB will not be closed."; 52 temp_dir_.Take(); 53 return; 54 } 55 56 // NSS is allowed to do IO on the current thread since dispatching 57 // to a dedicated thread would still have the affect of blocking 58 // the current thread, due to NSS's internal locking requirements 59 base::ThreadRestrictions::ScopedAllowIO allow_io; 60 61 if (slot_) { 62 SECStatus status = SECMOD_CloseUserDB(slot_.get()); 63 if (status != SECSuccess) 64 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); 65 } 66 67 if (!temp_dir_.Delete()) 68 LOG(ERROR) << "Could not delete temporary directory."; 69 } 70 71 } // namespace crypto 72