diff --git a/security/manager/ssl/nsNSSComponent.cpp b/security/manager/ssl/nsNSSComponent.cpp --- a/security/manager/ssl/nsNSSComponent.cpp +++ b/security/manager/ssl/nsNSSComponent.cpp @@ -1654,6 +1654,51 @@ } return AttemptToRenamePKCS11ModuleDB(profilePath, sqlModuleDBFilename); } + +// When we changed from the old dbm database format to the newer sqlite +// implementation, the upgrade process left behind the existing files. Suppose a +// user had not set a password for the old key3.db (which is about 99% of +// users). After upgrading, both the old database and the new database are +// unprotected. If the user then sets a password for the new database, the old +// one will not be protected. In this scenario, we should probably just remove +// the old database (it would only be relevant if the user downgraded to a +// version of Firefox before 58, but we have to trade this off against the +// user's old private keys being unexpectedly unprotected after setting a +// password). +// This was never an issue on Android because we always used the new +// implementation. +static void +MaybeCleanUpOldNSSFiles(const nsACString& profilePath) +{ + UniquePK11SlotInfo slot(PK11_GetInternalKeySlot()); + if (!slot) { + return; + } + // Unfortunately we can't now tell the difference between "there already was a + // password when the upgrade happened" and "there was not a password but then + // the user added one after upgrading". + bool hasPassword = PK11_NeedLogin(slot.get()) && + !PK11_NeedUserInit(slot.get()); + if (!hasPassword) { + return; + } + nsCOMPtr dbFile = do_CreateInstance("@mozilla.org/file/local;1"); + if (!dbFile) { + return; + } + nsresult rv = dbFile->InitWithNativePath(profilePath); + if (NS_FAILED(rv)) { + return; + } + NS_NAMED_LITERAL_CSTRING(keyDBFilename, "key3.db"); + rv = dbFile->AppendNative(keyDBFilename); + if (NS_FAILED(rv)) { + return; + } + // Since this isn't a directory, the `recursive` argument to `Remove` is + // irrelevant. + Unused << dbFile->Remove(false); +} #endif // ifndef ANDROID // Given a profile directory, attempt to initialize NSS. If nocertdb is true, @@ -1685,6 +1730,9 @@ SECStatus srv = ::mozilla::psm::InitializeNSS(profilePath, false, !safeMode); if (srv == SECSuccess) { MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode")); +#ifndef ANDROID + MaybeCleanUpOldNSSFiles(profilePath); +#endif // ifndef ANDROID return NS_OK; } #ifndef ANDROID