зеркало из https://github.com/mozilla/gecko-dev.git
bug 1372656 - load loadable roots on a background thread r=Cykesiopka,jcj
In a profile, loading the loadable roots PKCS#11 module (i.e. the built-in root CA module) accounted for about 60% of the time to initialize PSM/NSS. Since we only need the roots module loaded when we're actually looking for an issuing certificate or querying a certificate's trust, we can do the load asynchronously (where it hopefully finishes before we actually need it, because otherwise we'll have to wait anyway). MozReview-Commit-ID: JyY6NtpQAUj --HG-- extra : rebase_source : f63a697b18a409dd042289afa2b727b09f81f19f
This commit is contained in:
Родитель
8b8a999a38
Коммит
8b85837b61
|
@ -137,6 +137,10 @@ IsCertChainRootBuiltInRoot(const UniqueCERTCertList& chain, bool& result)
|
|||
Result
|
||||
IsCertBuiltInRoot(CERTCertificate* cert, bool& result)
|
||||
{
|
||||
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
result = false;
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
|
||||
|
@ -464,6 +468,10 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
|||
MOZ_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus);
|
||||
MOZ_ASSERT(usage == certificateUsageSSLServer || !sha1ModeResult);
|
||||
|
||||
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
||||
if (evOidPolicy) {
|
||||
*evOidPolicy = SEC_OID_UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -1176,7 +1176,7 @@ CertIsAuthoritativeForEVPolicy(const UniqueCERTCertificate& cert,
|
|||
}
|
||||
|
||||
nsresult
|
||||
LoadExtendedValidationInfo()
|
||||
LoadExtendedValidationInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
static const char* sCABForumOIDString = "2.23.140.1.1";
|
||||
static const char* sCABForumOIDDescription = "CA/Browser Forum EV OID";
|
||||
|
|
|
@ -8,12 +8,15 @@
|
|||
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "certt.h"
|
||||
#include "nsNSSShutDown.h"
|
||||
|
||||
namespace mozilla { namespace pkix { struct CertPolicyId; } }
|
||||
|
||||
namespace mozilla { namespace psm {
|
||||
|
||||
nsresult LoadExtendedValidationInfo();
|
||||
nsresult LoadExtendedValidationInfo(
|
||||
const nsNSSShutDownPreventionLock& proofOfLock);
|
||||
|
||||
/**
|
||||
* Finds the first policy OID in the given cert that is known to be an EV policy
|
||||
* OID.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nss.h"
|
||||
|
@ -1260,32 +1261,27 @@ DisableMD5()
|
|||
bool
|
||||
LoadLoadableRoots(const nsCString& dir, const nsCString& modNameUTF8)
|
||||
{
|
||||
UniquePRLibraryName fullLibraryPath(
|
||||
PR_GetLibraryName(dir.IsEmpty() ? nullptr : dir.get(), "nssckbi"));
|
||||
if (!fullLibraryPath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Escape the \ and " characters.
|
||||
nsAutoCString escapedFullLibraryPath(fullLibraryPath.get());
|
||||
escapedFullLibraryPath.ReplaceSubstring("\\", "\\\\");
|
||||
escapedFullLibraryPath.ReplaceSubstring("\"", "\\\"");
|
||||
if (escapedFullLibraryPath.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a module exists with the same name, make a best effort attempt to delete
|
||||
// it. Note that it isn't possible to delete the internal module, so checking
|
||||
// the return value would be detrimental in that case.
|
||||
int unusedModType;
|
||||
Unused << SECMOD_DeleteModule(modNameUTF8.get(), &unusedModType);
|
||||
|
||||
nsAutoCString pkcs11ModuleSpec;
|
||||
pkcs11ModuleSpec.AppendPrintf("name=\"%s\" library=\"%s\"", modNameUTF8.get(),
|
||||
escapedFullLibraryPath.get());
|
||||
if (pkcs11ModuleSpec.IsEmpty()) {
|
||||
return false;
|
||||
nsAutoCString fullLibraryPath;
|
||||
if (!dir.IsEmpty()) {
|
||||
fullLibraryPath.Assign(dir);
|
||||
fullLibraryPath.AppendLiteral(FILE_PATH_SEPARATOR);
|
||||
}
|
||||
fullLibraryPath.Append(DLL_PREFIX "nssckbi" DLL_SUFFIX);
|
||||
// Escape the \ and " characters.
|
||||
fullLibraryPath.ReplaceSubstring("\\", "\\\\");
|
||||
fullLibraryPath.ReplaceSubstring("\"", "\\\"");
|
||||
|
||||
nsAutoCString pkcs11ModuleSpec("name=\"");
|
||||
pkcs11ModuleSpec.Append(modNameUTF8);
|
||||
pkcs11ModuleSpec.AppendLiteral("\" library=\"");
|
||||
pkcs11ModuleSpec.Append(fullLibraryPath);
|
||||
pkcs11ModuleSpec.AppendLiteral("\"");
|
||||
|
||||
UniqueSECMODModule rootsModule(
|
||||
SECMOD_LoadUserModule(const_cast<char*>(pkcs11ModuleSpec.get()), nullptr,
|
||||
|
|
|
@ -40,6 +40,9 @@ if not CONFIG['NSS_NO_EV_CERTS']:
|
|||
'ExtendedValidation.cpp',
|
||||
]
|
||||
|
||||
for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
|
||||
DEFINES[var] = '"%s"' % CONFIG[var]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/security/manager/ssl',
|
||||
'/security/pkix/include',
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "pkcs12.h"
|
||||
#include "prerror.h"
|
||||
#include "prio.h"
|
||||
#include "prmem.h"
|
||||
#include "sechash.h"
|
||||
#include "secmod.h"
|
||||
#include "secpkcs7.h"
|
||||
|
@ -327,9 +328,9 @@ MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePORTString,
|
|||
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRFileDesc,
|
||||
PRFileDesc,
|
||||
PR_Close)
|
||||
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRLibraryName,
|
||||
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRString,
|
||||
char,
|
||||
PR_FreeLibraryName)
|
||||
PR_Free)
|
||||
|
||||
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueSECAlgorithmID,
|
||||
SECAlgorithmID,
|
||||
|
|
|
@ -896,6 +896,11 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
|
|||
if (isAlreadyShutDown())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mCert)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
|
|
@ -108,8 +108,13 @@ nsNSSCertificateDB::FindCertByDBKey(const nsACString& aDBKey,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
UniqueCERTCertificate cert;
|
||||
nsresult rv = FindCertByDBKey(aDBKey, cert);
|
||||
rv = FindCertByDBKey(aDBKey, cert);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -892,6 +897,12 @@ nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
|
|||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus srv;
|
||||
UniqueCERTCertificate nsscert(cert->GetCert());
|
||||
CERTCertTrust nsstrust;
|
||||
|
@ -1002,6 +1013,10 @@ nsNSSCertificateDB::ImportPKCS12File(nsIFile* aFile)
|
|||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aFile);
|
||||
nsPKCS12Blob blob;
|
||||
|
@ -1019,6 +1034,10 @@ nsNSSCertificateDB::ExportPKCS12File(nsIFile* aFile, uint32_t count,
|
|||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aFile);
|
||||
if (count == 0) {
|
||||
|
@ -1037,6 +1056,11 @@ nsNSSCertificateDB::FindCertByEmailAddress(const nsACString& aEmailAddress,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
||||
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
|
||||
|
||||
|
@ -1157,6 +1181,10 @@ nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
|
|||
nsresult rv;
|
||||
CK_OBJECT_HANDLE keyHandle;
|
||||
|
||||
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
|
||||
return;
|
||||
}
|
||||
|
||||
CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
|
||||
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
|
|
|
@ -199,7 +199,10 @@ GetRevocationBehaviorFromPrefs(/*out*/ CertVerifier::OcspDownloadConfig* odc,
|
|||
}
|
||||
|
||||
nsNSSComponent::nsNSSComponent()
|
||||
: mMutex("nsNSSComponent.mMutex")
|
||||
: mLoadableRootsLoadedMonitor("nsNSSComponent.mLoadableRootsLoadedMonitor")
|
||||
, mLoadableRootsLoaded(false)
|
||||
, mLoadableRootsLoadedResult(NS_ERROR_FAILURE)
|
||||
, mMutex("nsNSSComponent.mMutex")
|
||||
, mNSSInitialized(false)
|
||||
#ifndef MOZ_NO_SMART_CARDS
|
||||
, mThreadList(nullptr)
|
||||
|
@ -1049,15 +1052,173 @@ nsNSSComponent::ImportEnterpriseRootsForLocation(
|
|||
}
|
||||
#endif // XP_WIN
|
||||
|
||||
void
|
||||
nsNSSComponent::LoadLoadableRoots()
|
||||
class LoadLoadableRootsTask final : public Runnable
|
||||
, public nsNSSShutDownObject
|
||||
{
|
||||
public:
|
||||
explicit LoadLoadableRootsTask(nsNSSComponent* nssComponent)
|
||||
: Runnable("LoadLoadableRootsTask")
|
||||
, mNSSComponent(nssComponent)
|
||||
{
|
||||
MOZ_ASSERT(nssComponent);
|
||||
}
|
||||
|
||||
~LoadLoadableRootsTask();
|
||||
|
||||
nsresult Dispatch();
|
||||
|
||||
void virtualDestroyNSSReference() override {} // nothing to release
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run() override;
|
||||
nsresult LoadLoadableRoots(const nsNSSShutDownPreventionLock& proofOfLock);
|
||||
RefPtr<nsNSSComponent> mNSSComponent;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
LoadLoadableRootsTask::~LoadLoadableRootsTask()
|
||||
{
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (isAlreadyShutDown()) {
|
||||
return;
|
||||
}
|
||||
shutdown(ShutdownCalledFrom::Object);
|
||||
}
|
||||
|
||||
nsresult
|
||||
LoadLoadableRootsTask::Dispatch()
|
||||
{
|
||||
// Can't add 'this' as the event to run, since mThread may not be set yet
|
||||
nsresult rv = NS_NewNamedThread("LoadRoots", getter_AddRefs(mThread),
|
||||
nullptr,
|
||||
nsIThreadManager::DEFAULT_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Note: event must not null out mThread!
|
||||
return mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadLoadableRootsTask::Run()
|
||||
{
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = LoadLoadableRoots(lock);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("LoadLoadableRoots failed"));
|
||||
// We don't return rv here because then BlockUntilLoadableRootsLoaded will
|
||||
// just wait forever. Instead we'll save its value (below) so we can inform
|
||||
// code that relies on the roots module being present that loading it
|
||||
// failed.
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (NS_FAILED(LoadExtendedValidationInfo(lock))) {
|
||||
// This isn't a show-stopper in the same way that failing to load the
|
||||
// roots module is.
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
|
||||
}
|
||||
}
|
||||
{
|
||||
MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableRootsLoadedMonitor);
|
||||
mNSSComponent->mLoadableRootsLoaded = true;
|
||||
// Cache the result of LoadLoadableRoots so BlockUntilLoadableRootsLoaded
|
||||
// can return it to all callers later.
|
||||
mNSSComponent->mLoadableRootsLoadedResult = rv;
|
||||
rv = mNSSComponent->mLoadableRootsLoadedMonitor.NotifyAll();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNSSComponent::BlockUntilLoadableRootsLoaded()
|
||||
{
|
||||
MonitorAutoLock rootsLoadedLock(mLoadableRootsLoadedMonitor);
|
||||
while (!mLoadableRootsLoaded) {
|
||||
nsresult rv = rootsLoadedLock.Wait();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(mLoadableRootsLoaded);
|
||||
return mLoadableRootsLoadedResult;
|
||||
}
|
||||
|
||||
// Returns by reference the path to the directory containing the file that has
|
||||
// been loaded as DLL_PREFIX nss3 DLL_SUFFIX.
|
||||
static nsresult
|
||||
GetNSS3Directory(nsCString& result)
|
||||
{
|
||||
UniquePRString nss3Path(
|
||||
PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
|
||||
reinterpret_cast<PRFuncPtr>(NSS_Initialize)));
|
||||
if (!nss3Path) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nss not loaded?"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIFile> nss3File(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
||||
if (!nss3File) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create a file?"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoCString nss3PathAsString(nss3Path.get());
|
||||
nsresult rv = nss3File->InitWithNativePath(nss3PathAsString);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("couldn't initialize file with path '%s'", nss3Path.get()));
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIFile> nss3Directory;
|
||||
rv = nss3File->GetParent(getter_AddRefs(nss3Directory));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get parent directory?"));
|
||||
return rv;
|
||||
}
|
||||
return nss3Directory->GetNativePath(result);
|
||||
}
|
||||
|
||||
// Returns by reference the path to the desired directory, based on the current
|
||||
// settings in the directory service.
|
||||
static nsresult
|
||||
GetDirectoryPath(const char* directoryKey, nsCString& result)
|
||||
{
|
||||
nsCOMPtr<nsIProperties> directoryService(
|
||||
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
if (!directoryService) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get directory service"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = directoryService->Get(directoryKey, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(directory));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("could not get '%s' from directory service", directoryKey));
|
||||
return rv;
|
||||
}
|
||||
return directory->GetNativePath(result);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
LoadLoadableRootsTask::LoadLoadableRoots(
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
// Find the best Roots module for our purposes.
|
||||
// Prefer the application's installation directory,
|
||||
// but also ensure the library is at least the version we expect.
|
||||
|
||||
nsAutoString modName;
|
||||
nsresult rv = GetPIPNSSBundleString("RootCertModuleName", modName);
|
||||
nsresult rv = mNSSComponent->GetPIPNSSBundleString("RootCertModuleName",
|
||||
modName);
|
||||
if (NS_FAILED(rv)) {
|
||||
// When running Cpp unit tests on Android, this will fail because string
|
||||
// bundles aren't available (see bug 1311077, bug 1228175 comment 12, and
|
||||
|
@ -1068,66 +1229,58 @@ nsNSSComponent::LoadLoadableRoots()
|
|||
// user, so this is a step in that direction anyway.
|
||||
modName.AssignLiteral("Builtin Roots Module");
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 modNameUTF8(modName);
|
||||
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
if (!directoryService)
|
||||
return;
|
||||
|
||||
static const char nss_lib[] = "nss3";
|
||||
const char* possible_ckbi_locations[] = {
|
||||
nss_lib, // This special value means: search for ckbi in the directory
|
||||
// where nss3 is.
|
||||
NS_XPCOM_CURRENT_PROCESS_DIR,
|
||||
NS_GRE_DIR,
|
||||
0 // This special value means:
|
||||
// search for ckbi in the directories on the shared
|
||||
// library/DLL search path
|
||||
};
|
||||
|
||||
for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
|
||||
nsAutoCString libDir;
|
||||
|
||||
if (possible_ckbi_locations[il]) {
|
||||
nsCOMPtr<nsIFile> mozFile;
|
||||
if (possible_ckbi_locations[il] == nss_lib) {
|
||||
// Get the location of the nss3 library.
|
||||
char* nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
|
||||
(PRFuncPtr) NSS_Initialize);
|
||||
if (!nss_path) {
|
||||
continue;
|
||||
}
|
||||
// Get the directory containing the nss3 library.
|
||||
nsCOMPtr<nsIFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
|
||||
Vector<nsCString> possibleCKBILocations;
|
||||
// First try in the directory where we've already loaded
|
||||
// DLL_PREFIX nss3 DLL_SUFFIX, since that's likely to be correct.
|
||||
nsAutoCString nss3Dir;
|
||||
rv = GetNSS3Directory(nss3Dir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
|
||||
}
|
||||
PR_Free(nss_path); // PR_GetLibraryFilePathname() uses PR_Malloc().
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
|
||||
mozFile = do_QueryInterface(file);
|
||||
}
|
||||
if (!possibleCKBILocations.append(Move(nss3Dir))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
directoryService->Get( possible_ckbi_locations[il],
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mozFile));
|
||||
// For some reason this fails on android. In any case, we should try with
|
||||
// the other potential locations we have.
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("could not determine where nss was loaded from"));
|
||||
}
|
||||
nsAutoCString currentProcessDir;
|
||||
rv = GetDirectoryPath(NS_XPCOM_CURRENT_PROCESS_DIR, currentProcessDir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!possibleCKBILocations.append(Move(currentProcessDir))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("could not get current process directory"));
|
||||
}
|
||||
nsAutoCString greDir;
|
||||
rv = GetDirectoryPath(NS_GRE_DIR, greDir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!possibleCKBILocations.append(Move(greDir))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get gre directory"));
|
||||
}
|
||||
// As a last resort, this will cause the library loading code to use the OS'
|
||||
// default library search path.
|
||||
nsAutoCString emptyString;
|
||||
if (!possibleCKBILocations.append(Move(emptyString))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!mozFile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_FAILED(mozFile->GetNativePath(libDir))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 modNameUTF8(modName);
|
||||
if (mozilla::psm::LoadLoadableRoots(libDir, modNameUTF8)) {
|
||||
break;
|
||||
for (const auto& possibleCKBILocation : possibleCKBILocations) {
|
||||
if (mozilla::psm::LoadLoadableRoots(possibleCKBILocation, modNameUTF8)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("loaded CKBI from %s",
|
||||
possibleCKBILocation.get()));
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not load loadable roots"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1851,13 +2004,6 @@ nsNSSComponent::InitializeNSS()
|
|||
}
|
||||
|
||||
DisableMD5();
|
||||
LoadLoadableRoots();
|
||||
|
||||
rv = LoadExtendedValidationInfo();
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
|
||||
return rv;
|
||||
}
|
||||
|
||||
MaybeEnableFamilySafetyCompatibility();
|
||||
MaybeImportEnterpriseRoots();
|
||||
|
@ -1923,6 +2069,9 @@ nsNSSComponent::InitializeNSS()
|
|||
Telemetry::Accumulate(Telemetry::FIPS_ENABLED, true);
|
||||
}
|
||||
|
||||
// Gather telemetry on any PKCS#11 modules we have loaded. Note that because
|
||||
// we load the built-in root module asynchronously after this, the telemetry
|
||||
// will not include it.
|
||||
{ // Introduce scope for the AutoSECMODListReadLock.
|
||||
AutoSECMODListReadLock lock;
|
||||
for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
|
||||
|
@ -1959,7 +2108,9 @@ nsNSSComponent::InitializeNSS()
|
|||
mNSSInitialized = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
RefPtr<LoadLoadableRootsTask> loadLoadableRootsTask(
|
||||
new LoadLoadableRootsTask(this));
|
||||
return loadLoadableRootsTask->Dispatch();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "ScopedNSSTypes.h"
|
||||
#include "SharedCertVerifier.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -82,6 +83,8 @@ public:
|
|||
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) = 0;
|
||||
#endif
|
||||
|
||||
NS_IMETHOD BlockUntilLoadableRootsLoaded() = 0;
|
||||
|
||||
virtual ::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
||||
GetDefaultCertVerifier() = 0;
|
||||
};
|
||||
|
@ -95,6 +98,10 @@ class nsNSSComponent final : public nsINSSComponent
|
|||
, public nsIObserver
|
||||
{
|
||||
public:
|
||||
// LoadLoadableRootsTask updates mLoadableRootsLoaded and
|
||||
// mLoadableRootsLoadedResult and then signals mLoadableRootsLoadedMonitor.
|
||||
friend class LoadLoadableRootsTask;
|
||||
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
|
||||
|
||||
nsNSSComponent();
|
||||
|
@ -135,6 +142,8 @@ public:
|
|||
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) override;
|
||||
#endif
|
||||
|
||||
NS_IMETHOD BlockUntilLoadableRootsLoaded() override;
|
||||
|
||||
::already_AddRefed<mozilla::psm::SharedCertVerifier>
|
||||
GetDefaultCertVerifier() override;
|
||||
|
||||
|
@ -154,7 +163,6 @@ private:
|
|||
nsresult InitializeNSS();
|
||||
void ShutdownNSS();
|
||||
|
||||
void LoadLoadableRoots();
|
||||
void UnloadLoadableRoots();
|
||||
void setValidationOptions(bool isInitialSetting);
|
||||
nsresult setEnabledTLSVersions();
|
||||
|
@ -175,6 +183,11 @@ private:
|
|||
void UnloadEnterpriseRoots(const mozilla::MutexAutoLock& proofOfLock);
|
||||
#endif // XP_WIN
|
||||
|
||||
// mLoadableRootsLoadedMonitor protects mLoadableRootsLoaded.
|
||||
mozilla::Monitor mLoadableRootsLoadedMonitor;
|
||||
bool mLoadableRootsLoaded;
|
||||
nsresult mLoadableRootsLoadedResult;
|
||||
|
||||
// mMutex protects all members that are accessed from more than one thread.
|
||||
// While this lock is held, the same thread must not attempt to acquire a
|
||||
// nsNSSShutDownPreventionLock (acquiring a nsNSSShutDownPreventionLock and
|
||||
|
@ -202,6 +215,16 @@ private:
|
|||
static int mInstanceCount;
|
||||
};
|
||||
|
||||
inline nsresult
|
||||
BlockUntilLoadableRootsLoaded()
|
||||
{
|
||||
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
|
||||
if (!component) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return component->BlockUntilLoadableRootsLoaded();
|
||||
}
|
||||
|
||||
class nsNSSErrors
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -453,6 +453,11 @@ nsPK11TokenDB::FindTokenByName(const nsACString& tokenName,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (tokenName.IsEmpty()) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
@ -479,6 +484,11 @@ nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (!array) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/Unused.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nsPK11TokenDB.h"
|
||||
#include "nsPromiseFlatString.h"
|
||||
#include "secmod.h"
|
||||
|
@ -429,6 +430,11 @@ nsPKCS11ModuleDB::FindModuleByName(const nsACString& name,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
UniqueSECMODModule mod(SECMOD_FindModule(PromiseFlatCString(name).get()));
|
||||
if (!mod) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -453,6 +459,11 @@ nsPKCS11ModuleDB::FindSlotByName(const nsACString& name,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (name.IsEmpty()) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
@ -478,6 +489,11 @@ nsPKCS11ModuleDB::ListModules(nsISimpleEnumerator** _retval)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = BlockUntilLoadableRootsLoaded();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (!array) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -61,7 +61,6 @@ function checkTestModuleExists() {
|
|||
function checkModuleTelemetry(additionalExpectedModule = undefined) {
|
||||
let expectedModules = [
|
||||
"NSS Internal PKCS #11 Module",
|
||||
`${AppConstants.DLL_PREFIX}nssckbi${AppConstants.DLL_SUFFIX}`,
|
||||
];
|
||||
if (additionalExpectedModule) {
|
||||
expectedModules.push(additionalExpectedModule);
|
||||
|
|
Загрузка…
Ссылка в новой задаче