diff options
author | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-28 09:56:51 +0000 |
---|---|---|
committer | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-28 09:56:51 +0000 |
commit | 190933f29103844bbc40a88bca8b14e49bf7e008 (patch) | |
tree | 8a14ff4d9011f73175a12f851d5fb039c45bd41c /crypto/nss_util.cc | |
parent | a017c66088a4671cf0ea59be150c73d3679f31d4 (diff) | |
download | chromium_src-190933f29103844bbc40a88bca8b14e49bf7e008.zip chromium_src-190933f29103844bbc40a88bca8b14e49bf7e008.tar.gz chromium_src-190933f29103844bbc40a88bca8b14e49bf7e008.tar.bz2 |
Extract ScopedTestNSSDB from nss_util.
Before ScopedTestNSSDB affected several slot getters from nss_util.h .
This change reduces ScopedTestNSSDB to solely setup a temporary test DB and not influencing the global state in nss_util anymore.
As a replacement for some of its old behavior, a new ScopedTestSystemNSSKeySlot is added, which allows to override the slot returned by GetSystemNSSKeySlot().
With this change it's now possible to write tests that need both a user and system NSS DB by using ScopedTestSystemNSSKeySlot.
As a side-effect, GetPersistentNSSKeySlot() is now compiled on !OS_CHROMEOS only.
BUG=210525
(For include changes:)
R=rsleevi@chromium.org
TBR=nkostylev@chromium.org, stevenjb@chromium.org
Review URL: https://codereview.chromium.org/401623006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285881 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'crypto/nss_util.cc')
-rw-r--r-- | crypto/nss_util.cc | 172 |
1 files changed, 46 insertions, 126 deletions
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc index 6ab07bc..64489dc 100644 --- a/crypto/nss_util.cc +++ b/crypto/nss_util.cc @@ -198,12 +198,6 @@ class NSPRInitSingleton { base::LazyInstance<NSPRInitSingleton>::Leaky g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; -// This is a LazyInstance so that it will be deleted automatically when the -// unittest exits. NSSInitSingleton is a LeakySingleton, so it would not be -// deleted if it were a regular member. -base::LazyInstance<base::ScopedTempDir> g_test_nss_db_dir = - LAZY_INSTANCE_INITIALIZER; - // Force a crash with error info on NSS_NoDB_Init failure. void CrashOnNSSInitFailure() { int nss_error = PR_GetError(); @@ -287,8 +281,8 @@ class NSSInitSingleton { PK11SlotInfo* tpm_slot; }; - PK11SlotInfo* OpenPersistentNSSDBForPath(const std::string& db_name, - const base::FilePath& path) { + ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, + const base::FilePath& path) { DCHECK(thread_checker_.CalledOnValidThread()); // NSS is allowed to do IO on the current thread since dispatching // to a dedicated thread would still have the affect of blocking @@ -298,9 +292,9 @@ class NSSInitSingleton { base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); if (!base::CreateDirectory(nssdb_path)) { LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; - return NULL; + return ScopedPK11Slot(); } - return OpenUserDB(nssdb_path, db_name); + return OpenSoftwareNSSDB(nssdb_path, db_name); } void EnableTPMTokenForNSS() { @@ -393,10 +387,10 @@ class NSSInitSingleton { chaps_module_ = tpm_args->chaps_module; tpm_slot_ = tpm_args->tpm_slot; - if (!chaps_module_ && test_slot_) { + if (!chaps_module_ && test_system_slot_) { // chromeos_unittests try to test the TPM initialization process. If we // have a test DB open, pretend that it is the TPM slot. - tpm_slot_ = PK11_ReferenceSlot(test_slot_); + tpm_slot_ = PK11_ReferenceSlot(test_system_slot_.get()); } initializing_tpm_token_ = false; @@ -463,12 +457,6 @@ class NSSInitSingleton { return false; } - // If test slot is set, slot getter methods will short circuit - // checking |chromeos_user_map_|, so there is nothing left to be - // initialized. - if (test_slot_) - return false; - DVLOG(2) << "Opening NSS DB " << path.value(); std::string db_name = base::StringPrintf( "%s %s", kUserNSSDatabaseName, username_hash.c_str()); @@ -551,11 +539,6 @@ class NSSInitSingleton { return ScopedPK11Slot(); } - if (test_slot_) { - DVLOG(2) << "returning test_slot_ for " << username_hash; - return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); - } - if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { LOG(ERROR) << username_hash << " not initialized."; return ScopedPK11Slot(); @@ -579,56 +562,26 @@ class NSSInitSingleton { DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - if (test_slot_) { - DVLOG(2) << "returning test_slot_ for " << username_hash; - return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); - } - return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); } - void CloseTestChromeOSUser(const std::string& username_hash) { + void CloseChromeOSUserForTesting(const std::string& username_hash) { DCHECK(thread_checker_.CalledOnValidThread()); ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); DCHECK(i != chromeos_user_map_.end()); delete i->second; chromeos_user_map_.erase(i); } -#endif // defined(OS_CHROMEOS) - - bool OpenTestNSSDB() { - DCHECK(thread_checker_.CalledOnValidThread()); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (test_slot_) - return true; - if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) - return false; - test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); - return !!test_slot_; - } - - void CloseTestNSSDB() { - DCHECK(thread_checker_.CalledOnValidThread()); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (!test_slot_) - return; - SECStatus status = SECMOD_CloseUserDB(test_slot_); - if (status != SECSuccess) - PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); - PK11_FreeSlot(test_slot_); - test_slot_ = NULL; - ignore_result(g_test_nss_db_dir.Get().Delete()); + void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + // Ensure that a previous value of test_system_slot_ is not overwritten. + // Unsetting, i.e. setting a NULL, however is allowed. + DCHECK(!slot || !test_system_slot_); + test_system_slot_ = slot.Pass(); } +#endif // defined(OS_CHROMEOS) +#if !defined(OS_CHROMEOS) PK11SlotInfo* GetPersistentNSSKeySlot() { // TODO(mattm): Change to DCHECK when callers have been fixed. if (!thread_checker_.CalledOnValidThread()) { @@ -636,18 +589,14 @@ class NSSInitSingleton { << base::debug::StackTrace().ToString(); } - if (test_slot_) - return PK11_ReferenceSlot(test_slot_); return PK11_GetInternalKeySlot(); } +#endif #if defined(OS_CHROMEOS) PK11SlotInfo* GetSystemNSSKeySlot() { DCHECK(thread_checker_.CalledOnValidThread()); - if (test_slot_) - return PK11_ReferenceSlot(test_slot_); - // TODO(mattm): chromeos::TPMTokenloader always calls // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is // disabled, tpm_slot_ will be the first user's slot instead. Can that be @@ -679,7 +628,6 @@ class NSSInitSingleton { : tpm_token_enabled_for_nss_(false), initializing_tpm_token_(false), chaps_module_(NULL), - test_slot_(NULL), tpm_slot_(NULL), root_(NULL) { base::TimeTicks start_time = base::TimeTicks::Now(); @@ -801,7 +749,6 @@ class NSSInitSingleton { PK11_FreeSlot(tpm_slot_); tpm_slot_ = NULL; } - CloseTestNSSDB(); if (root_) { SECMOD_UnloadUserModule(root_); SECMOD_DestroyModule(root_); @@ -863,23 +810,6 @@ class NSSInitSingleton { } #endif - static PK11SlotInfo* OpenUserDB(const base::FilePath& path, - const std::string& description) { - const std::string modspec = - base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", - path.value().c_str(), - description.c_str()); - PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); - if (db_slot) { - if (PK11_NeedUserInit(db_slot)) - PK11_InitPin(db_slot, NULL, NULL); - } else { - LOG(ERROR) << "Error opening persistent database (" << modspec - << "): " << GetNSSErrorMessage(); - } - return db_slot; - } - static void DisableAESNIIfNeeded() { if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { // Some versions of NSS have a bug that causes AVX instructions to be @@ -903,12 +833,12 @@ class NSSInitSingleton { typedef std::vector<base::Closure> TPMReadyCallbackList; TPMReadyCallbackList tpm_ready_callback_list_; SECMODModule* chaps_module_; - PK11SlotInfo* test_slot_; PK11SlotInfo* tpm_slot_; SECMODModule* root_; #if defined(OS_CHROMEOS) typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; ChromeOSUserMap chromeos_user_map_; + ScopedPK11Slot test_system_slot_; #endif #if defined(USE_NSS) // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 @@ -926,9 +856,24 @@ base::LazyInstance<NSSInitSingleton>::Leaky g_nss_singleton = LAZY_INSTANCE_INITIALIZER; } // namespace -const char kTestTPMTokenName[] = "Test DB"; - #if defined(USE_NSS) +ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path, + const std::string& description) { + const std::string modspec = + base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", + path.value().c_str(), + description.c_str()); + PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); + if (db_slot) { + if (PK11_NeedUserInit(db_slot)) + PK11_InitPin(db_slot, NULL, NULL); + } else { + LOG(ERROR) << "Error opening persistent database (" << modspec + << "): " << GetNSSErrorMessage(); + } + return ScopedPK11Slot(db_slot); +} + void EarlySetupForNSSInit() { base::FilePath database_dir = GetInitialConfigDirectory(); if (!database_dir.empty()) @@ -1027,19 +972,6 @@ bool CheckNSSVersion(const char* version) { } #if defined(USE_NSS) -ScopedTestNSSDB::ScopedTestNSSDB() - : is_open_(g_nss_singleton.Get().OpenTestNSSDB()) { -} - -ScopedTestNSSDB::~ScopedTestNSSDB() { - // Don't close when NSS is < 3.15.1, because it would require an additional - // sleep for 1 second after closing the database, due to - // http://bugzil.la/875601. - if (NSS_VersionCheck("3.15.1")) { - g_nss_singleton.Get().CloseTestNSSDB(); - } -} - base::Lock* GetNSSWriteLock() { return g_nss_singleton.Get().write_lock(); } @@ -1065,7 +997,6 @@ AutoSECMODListReadLock::AutoSECMODListReadLock() AutoSECMODListReadLock::~AutoSECMODListReadLock() { SECMOD_ReleaseReadLock(lock_); } - #endif // defined(USE_NSS) #if defined(OS_CHROMEOS) @@ -1073,6 +1004,10 @@ PK11SlotInfo* GetSystemNSSKeySlot() { return g_nss_singleton.Get().GetSystemNSSKeySlot(); } +void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + g_nss_singleton.Get().SetSystemKeySlotForTesting(ScopedPK11Slot()); +} + void EnableTPMTokenForNSS() { g_nss_singleton.Get().EnableTPMTokenForNSS(); } @@ -1092,30 +1027,6 @@ void InitializeTPMTokenAndSystemSlot( callback); } -ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( - const std::string& username_hash) - : username_hash_(username_hash), constructed_successfully_(false) { - if (!temp_dir_.CreateUniqueTempDir()) - return; - constructed_successfully_ = - InitializeNSSForChromeOSUser(username_hash, - username_hash, - temp_dir_.path()); -} - -ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { - if (constructed_successfully_) - g_nss_singleton.Get().CloseTestChromeOSUser(username_hash_); -} - -void ScopedTestNSSChromeOSUser::FinishInit() { - DCHECK(constructed_successfully_); - if (!ShouldInitializeTPMForChromeOSUser(username_hash_)) - return; - WillInitializeTPMForChromeOSUser(username_hash_); - InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); -} - bool InitializeNSSForChromeOSUser( const std::string& email, const std::string& username_hash, @@ -1138,20 +1049,27 @@ void InitializeTPMForChromeOSUser( CK_SLOT_ID slot_id) { g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id); } + void InitializePrivateSoftwareSlotForChromeOSUser( const std::string& username_hash) { g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser( username_hash); } + ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) { return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash); } + ScopedPK11Slot GetPrivateSlotForChromeOSUser( const std::string& username_hash, const base::Callback<void(ScopedPK11Slot)>& callback) { return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash, callback); } + +void CloseChromeOSUserForTesting(const std::string& username_hash) { + g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash); +} #endif // defined(OS_CHROMEOS) base::Time PRTimeToBaseTime(PRTime prtime) { @@ -1163,8 +1081,10 @@ PRTime BaseTimeToPRTime(base::Time time) { return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); } +#if !defined(OS_CHROMEOS) PK11SlotInfo* GetPersistentNSSKeySlot() { return g_nss_singleton.Get().GetPersistentNSSKeySlot(); } +#endif } // namespace crypto |