| Index: base/nss_util.cc
|
| diff --git a/base/nss_util.cc b/base/nss_util.cc
|
| index fe78fe0c218bfb37162702f2cf6b5815b52cbe41..2207d3d0dff331f5304deb8aff7ebea0c29c84b7 100644
|
| --- a/base/nss_util.cc
|
| +++ b/base/nss_util.cc
|
| @@ -204,6 +204,12 @@ class NSSInitSingleton {
|
| }
|
| #endif // defined(USE_NSS)
|
|
|
| + // This method is used to force NSS to ne initialized without a DB.
|
| + // Call this method before NSSInitSingleton() is constructed.
|
| + static void ForceNoDBInit() {
|
| + force_nodb_init_ = true;
|
| + }
|
| +
|
| private:
|
| friend struct DefaultLazyInstanceTraits<NSSInitSingleton>;
|
|
|
| @@ -236,63 +242,69 @@ class NSSInitSingleton {
|
| }
|
|
|
| SECStatus status = SECFailure;
|
| + bool nodb_init = force_nodb_init_;
|
| +
|
| #if !defined(USE_NSS)
|
| // Use the system certificate store, so initialize NSS without database.
|
| - status = NSS_NoDB_Init(NULL);
|
| - if (status != SECSuccess) {
|
| - LOG(ERROR) << "Error initializing NSS without a persistent "
|
| - "database: NSS error code " << PR_GetError();
|
| - }
|
| -#else
|
| - FilePath database_dir = GetInitialConfigDirectory();
|
| - if (!database_dir.empty()) {
|
| - // This duplicates the work which should have been done in
|
| - // EarlySetupForNSSInit. However, this function is idempotent so there's
|
| - // no harm done.
|
| - UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
|
| -
|
| - // Initialize with a persistent database (likely, ~/.pki/nssdb).
|
| - // Use "sql:" which can be shared by multiple processes safely.
|
| - std::string nss_config_dir =
|
| - StringPrintf("sql:%s", database_dir.value().c_str());
|
| + nodb_init = true;
|
| +#endif
|
| +
|
| + if (nodb_init) {
|
| + status = NSS_NoDB_Init(NULL);
|
| + if (status != SECSuccess) {
|
| + LOG(ERROR) << "Error initializing NSS without a persistent "
|
| + "database: NSS error code " << PR_GetError();
|
| + }
|
| + } else {
|
| + FilePath database_dir = GetInitialConfigDirectory();
|
| + if (!database_dir.empty()) {
|
| + // This duplicates the work which should have been done in
|
| + // EarlySetupForNSSInit. However, this function is idempotent so
|
| + // there's no harm done.
|
| + UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
|
| +
|
| + // Initialize with a persistent database (likely, ~/.pki/nssdb).
|
| + // Use "sql:" which can be shared by multiple processes safely.
|
| + std::string nss_config_dir =
|
| + StringPrintf("sql:%s", database_dir.value().c_str());
|
| #if defined(OS_CHROMEOS)
|
| - status = NSS_Init(nss_config_dir.c_str());
|
| + status = NSS_Init(nss_config_dir.c_str());
|
| #else
|
| - status = NSS_InitReadWrite(nss_config_dir.c_str());
|
| + status = NSS_InitReadWrite(nss_config_dir.c_str());
|
| #endif
|
| - if (status != SECSuccess) {
|
| - LOG(ERROR) << "Error initializing NSS with a persistent "
|
| - "database (" << nss_config_dir
|
| - << "): NSS error code " << PR_GetError();
|
| + if (status != SECSuccess) {
|
| + LOG(ERROR) << "Error initializing NSS with a persistent "
|
| + "database (" << nss_config_dir
|
| + << "): NSS error code " << PR_GetError();
|
| + }
|
| }
|
| - }
|
| - if (status != SECSuccess) {
|
| - LOG(WARNING) << "Initialize NSS without a persistent database "
|
| - "(~/.pki/nssdb).";
|
| - status = NSS_NoDB_Init(NULL);
|
| if (status != SECSuccess) {
|
| - LOG(ERROR) << "Error initializing NSS without a persistent "
|
| - "database: NSS error code " << PR_GetError();
|
| - return;
|
| + LOG(WARNING) << "Initialize NSS without a persistent database "
|
| + "(~/.pki/nssdb).";
|
| + status = NSS_NoDB_Init(NULL);
|
| + if (status != SECSuccess) {
|
| + LOG(ERROR) << "Error initializing NSS without a persistent "
|
| + "database: NSS error code " << PR_GetError();
|
| + return;
|
| + }
|
| }
|
| - }
|
|
|
| - PK11_SetPasswordFunc(PKCS11PasswordFunc);
|
| -
|
| - // If we haven't initialized the password for the NSS databases,
|
| - // initialize an empty-string password so that we don't need to
|
| - // log in.
|
| - PK11SlotInfo* slot = PK11_GetInternalKeySlot();
|
| - if (slot) {
|
| - // PK11_InitPin may write to the keyDB, but no other thread can use NSS
|
| - // yet, so we don't need to lock.
|
| - if (PK11_NeedUserInit(slot))
|
| - PK11_InitPin(slot, NULL, NULL);
|
| - PK11_FreeSlot(slot);
|
| - }
|
| + PK11_SetPasswordFunc(PKCS11PasswordFunc);
|
| +
|
| + // If we haven't initialized the password for the NSS databases,
|
| + // initialize an empty-string password so that we don't need to
|
| + // log in.
|
| + PK11SlotInfo* slot = PK11_GetInternalKeySlot();
|
| + if (slot) {
|
| + // PK11_InitPin may write to the keyDB, but no other thread can use NSS
|
| + // yet, so we don't need to lock.
|
| + if (PK11_NeedUserInit(slot))
|
| + PK11_InitPin(slot, NULL, NULL);
|
| + PK11_FreeSlot(slot);
|
| + }
|
|
|
| - root_ = InitDefaultRootCerts();
|
| -#endif // !defined(USE_NSS)
|
| + root_ = InitDefaultRootCerts();
|
| + }
|
| }
|
|
|
| // NOTE(willchan): We don't actually execute this code since we leak NSS to
|
| @@ -337,6 +349,9 @@ class NSSInitSingleton {
|
| return db_slot;
|
| }
|
|
|
| + // If this is set to true NSS is forced to be initialized without a DB.
|
| + static bool force_nodb_init_;
|
| +
|
| PK11SlotInfo* real_db_slot_; // Overrides internal key slot if non-NULL.
|
| PK11SlotInfo* test_db_slot_; // Overrides internal key slot and real_db_slot_
|
| SECMODModule *root_;
|
| @@ -348,6 +363,8 @@ class NSSInitSingleton {
|
| #endif // defined(USE_NSS)
|
| };
|
|
|
| +bool NSSInitSingleton::force_nodb_init_ = false;
|
| +
|
| LazyInstance<NSSInitSingleton, LeakyLazyInstanceTraits<NSSInitSingleton> >
|
| g_nss_singleton(LINKER_INITIALIZED);
|
|
|
| @@ -373,6 +390,19 @@ void EnsureNSSInit() {
|
| g_nss_singleton.Get();
|
| }
|
|
|
| +void EnsureNSSNoDBInit() {
|
| + ThreadRestrictions::ScopedAllowIO allow_io;
|
| +
|
| + // Force NSS to be initialized without a DB.
|
| + NSSInitSingleton::ForceNoDBInit();
|
| + g_nss_singleton.Get();
|
| +}
|
| +
|
| +void DisableNSSForkCheck() {
|
| + scoped_ptr<Environment> env(Environment::Create());
|
| + env->SetVar("NSS_STRICT_NOFORK", "DISABLED");
|
| +}
|
| +
|
| bool CheckNSSVersion(const char* version) {
|
| return !!NSS_VersionCheck(version);
|
| }
|
|
|