bug 783994 - add preference for and enable sqlite-backed NSS databases r?Cykesiopka,jcj
In the future,
bug 1377940 will make the sqlite-backed databases the default,
but until we're sure this will stick we want to make this a Firefox-only change.
The use of a preference to configure which format to use will hopefully allow us
to restore the old behavior quickly and relatively safely if necessary. Note
that doing this should be done with care; any changes made in the sqlite
databases after upgrade migration will not be reflected if we need to go back to
the old database format. Thus, user data (imported CAs, client certificates, and
keys) can be lost.
MozReview-Commit-ID: E4ieLCo1e13
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -14,21 +14,23 @@
#include "OCSPVerificationTrustDomain.h"
#include "PublicKeyPinningService.h"
#include "cert.h"
#include "certdb.h"
#include "mozilla/Assertions.h"
#include "mozilla/Casting.h"
#include "mozilla/Move.h"
#include "mozilla/PodOperations.h"
+#include "mozilla/Preferences.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Unused.h"
#include "nsCRTGlue.h"
#include "nsNSSCertificate.h"
#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
#include "nss.h"
#include "pk11pub.h"
#include "pkix/Result.h"
#include "pkix/pkix.h"
#include "pkix/pkixnss.h"
#include "prerror.h"
#include "secerr.h"
@@ -1223,33 +1225,46 @@ NSSCertDBTrustDomain::NoteAuxiliaryExten
}
if (out) {
SECItem extensionDataItem = UnsafeMapInputToSECItem(extensionData);
out->reset(SECITEM_DupItem(&extensionDataItem));
}
}
SECStatus
-InitializeNSS(const char* dir, bool readOnly, bool loadPKCS11Modules)
+InitializeNSS(const nsACString& dir, bool readOnly, bool loadPKCS11Modules)
{
+ MOZ_ASSERT(NS_IsMainThread());
+
// The NSS_INIT_NOROOTINIT flag turns off the loading of the root certs
// module by NSS_Initialize because we will load it in InstallLoadableRoots
// later. It also allows us to work around a bug in the system NSS in
// Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
// "/usr/lib/nss/libnssckbi.so".
uint32_t flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
if (readOnly) {
flags |= NSS_INIT_READONLY;
}
if (!loadPKCS11Modules) {
flags |= NSS_INIT_NOMODDB;
}
+ bool useSQLDB = Preferences::GetBool("security.sqldb.enabled", false);
+ nsAutoCString dbTypeAndDirectory;
+ // Don't change any behavior if the user has specified an alternative database
+ // location with MOZPSM_NSSDBDIR_OVERRIDE.
+ const char* dbDirOverride = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
+ if (useSQLDB && (!dbDirOverride || strlen(dbDirOverride) == 0)) {
+ dbTypeAndDirectory.Append("sql:");
+ }
+ dbTypeAndDirectory.Append(dir);
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
- ("InitializeNSS(%s, %d, %d)", dir, readOnly, loadPKCS11Modules));
- SECStatus srv = NSS_Initialize(dir, "", "", SECMOD_DB, flags);
+ ("InitializeNSS(%s, %d, %d)", dbTypeAndDirectory.get(), readOnly,
+ loadPKCS11Modules));
+ SECStatus srv = NSS_Initialize(dbTypeAndDirectory.get(), "", "",
+ SECMOD_DB, flags);
if (srv != SECSuccess) {
return srv;
}
if (!readOnly) {
UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
if (!slot) {
return SECFailure;
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -32,17 +32,18 @@ enum class ValidityCheckingMode {
// * Never match: the OID is never considered equivalent to serverAuth
enum class NetscapeStepUpPolicy : uint32_t {
AlwaysMatch = 0,
MatchBefore23August2016 = 1,
MatchBefore23August2015 = 2,
NeverMatch = 3,
};
-SECStatus InitializeNSS(const char* dir, bool readOnly, bool loadPKCS11Modules);
+SECStatus InitializeNSS(const nsACString& dir, bool readOnly,
+ bool loadPKCS11Modules);
void DisableMD5();
/**
* Loads root certificates from a module.
*
* @param dir
* The path to the directory containing the NSS builtin roots module.
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -1881,33 +1881,31 @@ InitializeNSSWithFallbacks(const nsACStr
if (nocertdb || profilePath.IsEmpty()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
SECStatus srv = NSS_NoDB_Init(nullptr);
return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
}
- const nsCString& profilePathCStr = PromiseFlatCString(profilePath);
// Try read/write mode. If we're in safeMode, we won't load PKCS#11 modules.
#ifndef ANDROID
PRErrorCode savedPRErrorCode1;
#endif // ifndef ANDROID
- SECStatus srv = ::mozilla::psm::InitializeNSS(profilePathCStr.get(), false,
- !safeMode);
+ SECStatus srv = ::mozilla::psm::InitializeNSS(profilePath, false, !safeMode);
if (srv == SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode"));
return NS_OK;
}
#ifndef ANDROID
savedPRErrorCode1 = PR_GetError();
PRErrorCode savedPRErrorCode2;
#endif // ifndef ANDROID
// That failed. Try read-only mode.
- srv = ::mozilla::psm::InitializeNSS(profilePathCStr.get(), true, !safeMode);
+ srv = ::mozilla::psm::InitializeNSS(profilePath, true, !safeMode);
if (srv == SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r-o mode"));
return NS_OK;
}
#ifndef ANDROID
savedPRErrorCode2 = PR_GetError();
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
@@ -1924,38 +1922,38 @@ InitializeNSSWithFallbacks(const nsACStr
savedPRErrorCode1 == SEC_ERROR_PKCS11_DEVICE_ERROR ||
savedPRErrorCode2 == SEC_ERROR_PKCS11_DEVICE_ERROR)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("attempting no-module db init"));
// It would make sense to initialize NSS in read-only mode here since this
// is just a test to see if the PKCS#11 module DB being in FIPS mode is the
// problem, but for some reason the combination of read-only and no-moddb
// flags causes NSS initialization to fail, so unfortunately we have to use
// read-write mode.
- srv = ::mozilla::psm::InitializeNSS(profilePathCStr.get(), false, false);
+ srv = ::mozilla::psm::InitializeNSS(profilePath, false, false);
if (srv == SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FIPS may be the problem"));
// Unload NSS so we can attempt to fix this situation for the user.
srv = NSS_Shutdown();
if (srv != SECSuccess) {
return NS_ERROR_FAILURE;
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trying to rename module db"));
// If this fails non-catastrophically, we'll attempt to initialize NSS
// again in r/w then r-o mode (both of which will fail), and then we'll
// fall back to NSS_NoDB_Init, which is the behavior we want.
nsresult rv = AttemptToRenameBothPKCS11ModuleDBVersions(profilePath);
if (NS_FAILED(rv)) {
return rv;
}
- srv = ::mozilla::psm::InitializeNSS(profilePathCStr.get(), false, true);
+ srv = ::mozilla::psm::InitializeNSS(profilePath, false, true);
if (srv == SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r/w mode"));
return NS_OK;
}
- srv = ::mozilla::psm::InitializeNSS(profilePathCStr.get(), true, true);
+ srv = ::mozilla::psm::InitializeNSS(profilePath, true, true);
if (srv == SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r-o mode"));
return NS_OK;
}
}
}
#endif
--- a/security/manager/ssl/security-prefs.js
+++ b/security/manager/ssl/security-prefs.js
@@ -38,16 +38,21 @@ pref("security.ssl3.rsa_des_ede3_sha", f
pref("security.content.signature.root_hash",
"97:E8:BA:9C:F1:2F:B3:DE:53:CC:42:A4:E6:57:7E:D6:4D:F4:93:C2:47:B4:14:FE:A0:36:81:8D:38:23:56:0E");
pref("security.default_personal_cert", "Ask Every Time");
pref("security.remember_cert_checkbox_default_setting", true);
pref("security.ask_for_password", 0);
pref("security.password_lifetime", 30);
+// If true, use the modern sqlite-backed certificate and key databases in NSS.
+// If false, use the old BerkeleyDB format. Changing this requires a restart
+// to take effect.
+pref("security.sqldb.enabled", true);
+
// The supported values of this pref are:
// 0: disable detecting Family Safety mode and importing the root
// 1: only attempt to detect Family Safety mode (don't import the root)
// 2: detect Family Safety mode and import the root
// (This is only relevant to Windows 8.1)
pref("security.family_safety.mode", 2);
pref("security.enterprise_roots.enabled", false);