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 
ScopedTestNSSDB()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 
~ScopedTestNSSDB()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