LCOV - code coverage report
Current view: top level - security/manager/ssl - nsNSSComponent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 362 759 47.7 %
Date: 2017-07-14 16:53:18 Functions: 34 59 57.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsNSSComponent.h"
       8             : 
       9             : #include "ExtendedValidation.h"
      10             : #include "NSSCertDBTrustDomain.h"
      11             : #include "PKCS11.h"
      12             : #include "ScopedNSSTypes.h"
      13             : #include "SharedSSLState.h"
      14             : #include "cert.h"
      15             : #include "certdb.h"
      16             : #include "mozilla/ArrayUtils.h"
      17             : #include "mozilla/Assertions.h"
      18             : #include "mozilla/Casting.h"
      19             : #include "mozilla/Preferences.h"
      20             : #include "mozilla/PodOperations.h"
      21             : #include "mozilla/PublicSSL.h"
      22             : #include "mozilla/Services.h"
      23             : #include "mozilla/StaticPtr.h"
      24             : #include "mozilla/SyncRunnable.h"
      25             : #include "mozilla/Telemetry.h"
      26             : #include "mozilla/TimeStamp.h"
      27             : #include "mozilla/Unused.h"
      28             : #include "nsAppDirectoryServiceDefs.h"
      29             : #include "nsCRT.h"
      30             : #include "nsClientAuthRemember.h"
      31             : #include "nsComponentManagerUtils.h"
      32             : #include "nsDirectoryServiceDefs.h"
      33             : #include "nsICertOverrideService.h"
      34             : #include "nsIFile.h"
      35             : #include "nsIObserverService.h"
      36             : #include "nsIPrompt.h"
      37             : #include "nsIProperties.h"
      38             : #include "nsISiteSecurityService.h"
      39             : #include "nsITokenPasswordDialogs.h"
      40             : #include "nsIWindowWatcher.h"
      41             : #include "nsIXULRuntime.h"
      42             : #include "nsLiteralString.h"
      43             : #include "nsNSSCertificateDB.h"
      44             : #include "nsNSSHelper.h"
      45             : #include "nsNSSShutDown.h"
      46             : #include "nsPrintfCString.h"
      47             : #include "nsServiceManagerUtils.h"
      48             : #include "nsThreadUtils.h"
      49             : #include "nsXULAppAPI.h"
      50             : #include "nss.h"
      51             : #include "p12plcy.h"
      52             : #include "pkix/pkixnss.h"
      53             : #include "secerr.h"
      54             : #include "secmod.h"
      55             : #include "ssl.h"
      56             : #include "sslerr.h"
      57             : #include "sslproto.h"
      58             : #include "prmem.h"
      59             : 
      60             : #ifndef MOZ_NO_SMART_CARDS
      61             : #include "nsSmartCardMonitor.h"
      62             : #endif
      63             : 
      64             : #ifdef XP_WIN
      65             : #include "mozilla/WindowsVersion.h"
      66             : #include "nsILocalFileWin.h"
      67             : 
      68             : #include "windows.h" // this needs to be before the following includes
      69             : #include "lmcons.h"
      70             : #include "sddl.h"
      71             : #include "wincrypt.h"
      72             : #include "nsIWindowsRegKey.h"
      73             : #endif
      74             : 
      75             : using namespace mozilla;
      76             : using namespace mozilla::psm;
      77             : 
      78             : LazyLogModule gPIPNSSLog("pipnss");
      79             : 
      80             : int nsNSSComponent::mInstanceCount = 0;
      81             : 
      82             : // This function can be called from chrome or content processes
      83             : // to ensure that NSS is initialized.
      84          19 : bool EnsureNSSInitializedChromeOrContent()
      85             : {
      86             :   // If this is not the main thread (i.e. probably a worker) then forward this
      87             :   // call to the main thread.
      88          19 :   if (!NS_IsMainThread()) {
      89             :     static Atomic<bool> initialized(false);
      90             : 
      91             :     // Cache the result to dispatch to the main thread only once per worker.
      92          14 :     if (initialized) {
      93          13 :       return true;
      94             :     }
      95             : 
      96           2 :     nsCOMPtr<nsIThread> mainThread;
      97           1 :     nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
      98           1 :     if (NS_FAILED(rv)) {
      99           0 :       return false;
     100             :     }
     101             : 
     102             :     // Forward to the main thread synchronously.
     103           2 :     mozilla::SyncRunnable::DispatchToThread(
     104             :       mainThread,
     105             :       new SyncRunnable(
     106           3 :         NS_NewRunnableFunction("EnsureNSSInitializedChromeOrContent", []() {
     107           1 :           initialized = EnsureNSSInitializedChromeOrContent();
     108           2 :         })));
     109             : 
     110           1 :     return initialized;
     111             :   }
     112             : 
     113           5 :   if (XRE_IsParentProcess()) {
     114           8 :     nsCOMPtr<nsISupports> nss = do_GetService(PSM_COMPONENT_CONTRACTID);
     115           4 :     if (!nss) {
     116           0 :       return false;
     117             :     }
     118           4 :     return true;
     119             :   }
     120             : 
     121           1 :   if (NSS_IsInitialized()) {
     122           0 :     return true;
     123             :   }
     124             : 
     125           1 :   if (NSS_NoDB_Init(nullptr) != SECSuccess) {
     126           0 :     return false;
     127             :   }
     128             : 
     129           1 :   if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
     130           0 :     return false;
     131             :   }
     132             : 
     133           1 :   mozilla::psm::DisableMD5();
     134           1 :   return true;
     135             : }
     136             : 
     137             : static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_DEFAULT = 2000;
     138             : static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX = 5000;
     139             : static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_DEFAULT = 10000;
     140             : static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_MAX = 20000;
     141             : 
     142             : static void
     143           1 : GetRevocationBehaviorFromPrefs(/*out*/ CertVerifier::OcspDownloadConfig* odc,
     144             :                                /*out*/ CertVerifier::OcspStrictConfig* osc,
     145             :                                /*out*/ CertVerifier::OcspGetConfig* ogc,
     146             :                                /*out*/ uint32_t* certShortLifetimeInDays,
     147             :                                /*out*/ TimeDuration& softTimeout,
     148             :                                /*out*/ TimeDuration& hardTimeout,
     149             :                                const MutexAutoLock& /*proofOfLock*/)
     150             : {
     151           1 :   MOZ_ASSERT(NS_IsMainThread());
     152           1 :   MOZ_ASSERT(odc);
     153           1 :   MOZ_ASSERT(osc);
     154           1 :   MOZ_ASSERT(ogc);
     155           1 :   MOZ_ASSERT(certShortLifetimeInDays);
     156             : 
     157             :   // 0 = disabled
     158             :   // 1 = enabled for everything (default)
     159             :   // 2 = enabled for EV certificates only
     160           1 :   int32_t ocspLevel = Preferences::GetInt("security.OCSP.enabled", 1);
     161           1 :   switch (ocspLevel) {
     162           0 :     case 0: *odc = CertVerifier::ocspOff; break;
     163           1 :     case 2: *odc = CertVerifier::ocspEVOnly; break;
     164           0 :     default: *odc = CertVerifier::ocspOn; break;
     165             :   }
     166             : 
     167           2 :   *osc = Preferences::GetBool("security.OCSP.require", false)
     168           1 :        ? CertVerifier::ocspStrict
     169             :        : CertVerifier::ocspRelaxed;
     170             : 
     171             :   // XXX: Always use POST for OCSP; see bug 871954 for undoing this.
     172           2 :   *ogc = Preferences::GetBool("security.OCSP.GET.enabled", false)
     173           1 :        ? CertVerifier::ocspGetEnabled
     174             :        : CertVerifier::ocspGetDisabled;
     175             : 
     176             :   // If we pass in just 0 as the second argument to Preferences::GetUint, there
     177             :   // are two function signatures that match (given that 0 can be intepreted as
     178             :   // a null pointer). Thus the compiler will complain without the cast.
     179           1 :   *certShortLifetimeInDays =
     180           1 :     Preferences::GetUint("security.pki.cert_short_lifetime_in_days",
     181             :                          static_cast<uint32_t>(0));
     182             : 
     183             :   uint32_t softTimeoutMillis =
     184           1 :     Preferences::GetUint("security.OCSP.timeoutMilliseconds.soft",
     185           1 :                          OCSP_TIMEOUT_MILLISECONDS_SOFT_DEFAULT);
     186           1 :   softTimeoutMillis = std::min(softTimeoutMillis,
     187           1 :                                OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX);
     188           1 :   softTimeout = TimeDuration::FromMilliseconds(softTimeoutMillis);
     189             : 
     190             :   uint32_t hardTimeoutMillis =
     191           1 :     Preferences::GetUint("security.OCSP.timeoutMilliseconds.hard",
     192           1 :                          OCSP_TIMEOUT_MILLISECONDS_HARD_DEFAULT);
     193           1 :   hardTimeoutMillis = std::min(hardTimeoutMillis,
     194           1 :                                OCSP_TIMEOUT_MILLISECONDS_HARD_MAX);
     195           1 :   hardTimeout = TimeDuration::FromMilliseconds(hardTimeoutMillis);
     196             : 
     197           1 :   SSL_ClearSessionCache();
     198           1 : }
     199             : 
     200           1 : nsNSSComponent::nsNSSComponent()
     201             :   : mMutex("nsNSSComponent.mMutex")
     202             :   , mNSSInitialized(false)
     203             : #ifndef MOZ_NO_SMART_CARDS
     204           1 :   , mThreadList(nullptr)
     205             : #endif
     206             : {
     207           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ctor\n"));
     208           1 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
     209             : 
     210           1 :   MOZ_ASSERT(mInstanceCount == 0,
     211             :              "nsNSSComponent is a singleton, but instantiated multiple times!");
     212           1 :   ++mInstanceCount;
     213           1 : }
     214             : 
     215           0 : nsNSSComponent::~nsNSSComponent()
     216             : {
     217           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor\n"));
     218           0 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
     219             : 
     220             :   // All cleanup code requiring services needs to happen in xpcom_shutdown
     221             : 
     222           0 :   ShutdownNSS();
     223           0 :   SharedSSLState::GlobalCleanup();
     224           0 :   RememberCertErrorsTable::Cleanup();
     225           0 :   --mInstanceCount;
     226             : 
     227           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor finished\n"));
     228           0 : }
     229             : 
     230             : NS_IMETHODIMP
     231           0 : nsNSSComponent::PIPBundleFormatStringFromName(const char* name,
     232             :                                               const char16_t** params,
     233             :                                               uint32_t numParams,
     234             :                                               nsAString& outString)
     235             : {
     236           0 :   MutexAutoLock lock(mMutex);
     237           0 :   nsresult rv = NS_ERROR_FAILURE;
     238             : 
     239           0 :   if (mPIPNSSBundle && name) {
     240           0 :     nsXPIDLString result;
     241           0 :     rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     242             :                                              params, numParams,
     243           0 :                                              getter_Copies(result));
     244           0 :     if (NS_SUCCEEDED(rv)) {
     245           0 :       outString = result;
     246             :     }
     247             :   }
     248           0 :   return rv;
     249             : }
     250             : 
     251             : NS_IMETHODIMP
     252           9 : nsNSSComponent::GetPIPNSSBundleString(const char* name, nsAString& outString)
     253             : {
     254          18 :   MutexAutoLock lock(mMutex);
     255           9 :   nsresult rv = NS_ERROR_FAILURE;
     256             : 
     257           9 :   outString.SetLength(0);
     258           9 :   if (mPIPNSSBundle && name) {
     259          18 :     nsXPIDLString result;
     260          27 :     rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     261          27 :                                           getter_Copies(result));
     262           9 :     if (NS_SUCCEEDED(rv)) {
     263           9 :       outString = result;
     264           9 :       rv = NS_OK;
     265             :     }
     266             :   }
     267             : 
     268          18 :   return rv;
     269             : }
     270             : 
     271             : NS_IMETHODIMP
     272           0 : nsNSSComponent::GetNSSBundleString(const char* name, nsAString& outString)
     273             : {
     274           0 :   MutexAutoLock lock(mMutex);
     275           0 :   nsresult rv = NS_ERROR_FAILURE;
     276             : 
     277           0 :   outString.SetLength(0);
     278           0 :   if (mNSSErrorsBundle && name) {
     279           0 :     nsXPIDLString result;
     280           0 :     rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
     281           0 :                                              getter_Copies(result));
     282           0 :     if (NS_SUCCEEDED(rv)) {
     283           0 :       outString = result;
     284           0 :       rv = NS_OK;
     285             :     }
     286             :   }
     287             : 
     288           0 :   return rv;
     289             : }
     290             : 
     291             : #ifndef MOZ_NO_SMART_CARDS
     292             : nsresult
     293           1 : nsNSSComponent::LaunchSmartCardThreads()
     294             : {
     295           1 :   MOZ_ASSERT(NS_IsMainThread());
     296           1 :   if (!NS_IsMainThread()) {
     297           0 :     return NS_ERROR_NOT_SAME_THREAD;
     298             :   }
     299             : 
     300           2 :   AutoSECMODListReadLock lock;
     301           1 :   SECMODModuleList* list = SECMOD_GetDefaultModuleList();
     302             :   nsresult rv;
     303           5 :   while (list) {
     304           2 :     rv = LaunchSmartCardThread(list->module);
     305           2 :     if (NS_FAILED(rv)) {
     306           0 :       return rv;
     307             :     }
     308           2 :     list = list->next;
     309             :   }
     310           1 :   return NS_OK;
     311             : }
     312             : 
     313             : NS_IMETHODIMP
     314           2 : nsNSSComponent::LaunchSmartCardThread(SECMODModule* module)
     315             : {
     316           2 :   MOZ_ASSERT(NS_IsMainThread());
     317           2 :   if (!NS_IsMainThread()) {
     318           0 :     return NS_ERROR_NOT_SAME_THREAD;
     319             :   }
     320             : 
     321             :   SmartCardMonitoringThread* newThread;
     322           2 :   if (SECMOD_HasRemovableSlots(module)) {
     323           0 :     if (!mThreadList) {
     324           0 :       mThreadList = new SmartCardThreadList();
     325             :     }
     326           0 :     newThread = new SmartCardMonitoringThread(module);
     327             :     // newThread is adopted by the add.
     328           0 :     return mThreadList->Add(newThread);
     329             :   }
     330           2 :   return NS_OK;
     331             : }
     332             : 
     333             : NS_IMETHODIMP
     334           0 : nsNSSComponent::ShutdownSmartCardThread(SECMODModule* module)
     335             : {
     336           0 :   MOZ_ASSERT(NS_IsMainThread());
     337           0 :   if (!NS_IsMainThread()) {
     338           0 :     return NS_ERROR_NOT_SAME_THREAD;
     339             :   }
     340             : 
     341           0 :   if (!mThreadList) {
     342           0 :     return NS_OK;
     343             :   }
     344           0 :   mThreadList->Remove(module);
     345           0 :   return NS_OK;
     346             : }
     347             : 
     348             : void
     349           0 : nsNSSComponent::ShutdownSmartCardThreads()
     350             : {
     351           0 :   MOZ_ASSERT(NS_IsMainThread());
     352           0 :   if (!NS_IsMainThread()) {
     353           0 :     return;
     354             :   }
     355             : 
     356           0 :   delete mThreadList;
     357           0 :   mThreadList = nullptr;
     358             : }
     359             : #endif // MOZ_NO_SMART_CARDS
     360             : 
     361             : #ifdef XP_WIN
     362             : static bool
     363             : GetUserSid(nsAString& sidString)
     364             : {
     365             :   // UNLEN is the maximum user name length (see Lmcons.h). +1 for the null
     366             :   // terminator.
     367             :   WCHAR lpAccountName[UNLEN + 1];
     368             :   DWORD lcAccountName = sizeof(lpAccountName) / sizeof(lpAccountName[0]);
     369             :   BOOL success = GetUserName(lpAccountName, &lcAccountName);
     370             :   if (!success) {
     371             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetUserName failed"));
     372             :     return false;
     373             :   }
     374             :   char sid_buffer[SECURITY_MAX_SID_SIZE];
     375             :   SID* sid = BitwiseCast<SID*, char*>(sid_buffer);
     376             :   DWORD cbSid = ArrayLength(sid_buffer);
     377             :   SID_NAME_USE eUse;
     378             :   // There doesn't appear to be a defined maximum length for the domain name
     379             :   // here. To deal with this, we start with a reasonable buffer length and
     380             :   // see if that works. If it fails and the error indicates insufficient length,
     381             :   // we use the indicated required length and try again.
     382             :   DWORD cchReferencedDomainName = 128;
     383             :   auto ReferencedDomainName(MakeUnique<WCHAR[]>(cchReferencedDomainName));
     384             :   success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
     385             :                               ReferencedDomainName.get(),
     386             :                               &cchReferencedDomainName, &eUse);
     387             :   if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
     388             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
     389             :     return false;
     390             :   }
     391             :   if (!success) {
     392             :     ReferencedDomainName = MakeUnique<WCHAR[]>(cchReferencedDomainName);
     393             :     success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
     394             :                                 ReferencedDomainName.get(),
     395             :                                 &cchReferencedDomainName, &eUse);
     396             :   }
     397             :   if (!success) {
     398             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
     399             :     return false;
     400             :   }
     401             :   LPTSTR StringSid;
     402             :   success = ConvertSidToStringSid(sid, &StringSid);
     403             :   if (!success) {
     404             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ConvertSidToStringSid failed"));
     405             :     return false;
     406             :   }
     407             :   sidString.Assign(StringSid);
     408             :   LocalFree(StringSid);
     409             :   return true;
     410             : }
     411             : 
     412             : // This is a specialized helper function to read the value of a registry key
     413             : // that might not be present. If it is present, returns (via the output
     414             : // parameter) its value. Otherwise, returns the given default value.
     415             : // This function handles one level of nesting. That is, if the desired value
     416             : // is actually in a direct child of the given registry key (where the child
     417             : // and/or the value being sought may not actually be present), this function
     418             : // will handle that. In the normal case, though, optionalChildName will be
     419             : // null.
     420             : static nsresult
     421             : ReadRegKeyValueWithDefault(nsCOMPtr<nsIWindowsRegKey> regKey,
     422             :                            uint32_t flags,
     423             :                            wchar_t* optionalChildName,
     424             :                            wchar_t* valueName,
     425             :                            uint32_t defaultValue,
     426             :                            uint32_t& valueOut)
     427             : {
     428             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ReadRegKeyValueWithDefault"));
     429             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     430             :           ("attempting to read '%S%s%S' with default '%u'",
     431             :            optionalChildName ? optionalChildName : L"",
     432             :            optionalChildName ? "\\" : "", valueName, defaultValue));
     433             :   if (optionalChildName) {
     434             :     nsDependentString childNameString(optionalChildName);
     435             :     bool hasChild;
     436             :     nsresult rv = regKey->HasChild(childNameString, &hasChild);
     437             :     if (NS_FAILED(rv)) {
     438             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     439             :               ("failed to determine if child key is present"));
     440             :       return rv;
     441             :     }
     442             :     if (!hasChild) {
     443             :       valueOut = defaultValue;
     444             :       return NS_OK;
     445             :     }
     446             :     nsCOMPtr<nsIWindowsRegKey> childRegKey;
     447             :     rv = regKey->OpenChild(childNameString, flags,
     448             :                            getter_AddRefs(childRegKey));
     449             :     if (NS_FAILED(rv)) {
     450             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open child key"));
     451             :       return rv;
     452             :     }
     453             :     return ReadRegKeyValueWithDefault(childRegKey, flags, nullptr, valueName,
     454             :                                       defaultValue, valueOut);
     455             :   }
     456             :   nsDependentString valueNameString(valueName);
     457             :   bool hasValue;
     458             :   nsresult rv = regKey->HasValue(valueNameString, &hasValue);
     459             :   if (NS_FAILED(rv)) {
     460             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     461             :             ("failed to determine if value is present"));
     462             :     return rv;
     463             :   }
     464             :   if (!hasValue) {
     465             :     valueOut = defaultValue;
     466             :     return NS_OK;
     467             :   }
     468             :   rv = regKey->ReadIntValue(valueNameString, &valueOut);
     469             :   if (NS_FAILED(rv)) {
     470             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to read value"));
     471             :     return rv;
     472             :   }
     473             :   return NS_OK;
     474             : }
     475             : 
     476             : static nsresult
     477             : AccountHasFamilySafetyEnabled(bool& enabled)
     478             : {
     479             :   enabled = false;
     480             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("AccountHasFamilySafetyEnabled?"));
     481             :   nsCOMPtr<nsIWindowsRegKey> parentalControlsKey(
     482             :     do_CreateInstance("@mozilla.org/windows-registry-key;1"));
     483             :   if (!parentalControlsKey) {
     484             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create nsIWindowsRegKey"));
     485             :     return NS_ERROR_FAILURE;
     486             :   }
     487             :   uint32_t flags = nsIWindowsRegKey::ACCESS_READ | nsIWindowsRegKey::WOW64_64;
     488             :   NS_NAMED_LITERAL_STRING(familySafetyPath,
     489             :     "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Parental Controls");
     490             :   nsresult rv = parentalControlsKey->Open(
     491             :     nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, familySafetyPath, flags);
     492             :   if (NS_FAILED(rv)) {
     493             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open parentalControlsKey"));
     494             :     return rv;
     495             :   }
     496             :   NS_NAMED_LITERAL_STRING(usersString, "Users");
     497             :   bool hasUsers;
     498             :   rv = parentalControlsKey->HasChild(usersString, &hasUsers);
     499             :   if (NS_FAILED(rv)) {
     500             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(Users) failed"));
     501             :     return rv;
     502             :   }
     503             :   if (!hasUsers) {
     504             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     505             :             ("Users subkey not present - Parental Controls not enabled"));
     506             :     return NS_OK;
     507             :   }
     508             :   nsCOMPtr<nsIWindowsRegKey> usersKey;
     509             :   rv = parentalControlsKey->OpenChild(usersString, flags,
     510             :                                       getter_AddRefs(usersKey));
     511             :   if (NS_FAILED(rv)) {
     512             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to open Users subkey"));
     513             :     return rv;
     514             :   }
     515             :   nsAutoString sid;
     516             :   if (!GetUserSid(sid)) {
     517             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get sid"));
     518             :     return NS_ERROR_FAILURE;
     519             :   }
     520             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("our sid is '%S'", sid.get()));
     521             :   bool hasSid;
     522             :   rv = usersKey->HasChild(sid, &hasSid);
     523             :   if (NS_FAILED(rv)) {
     524             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(sid) failed"));
     525             :     return rv;
     526             :   }
     527             :   if (!hasSid) {
     528             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     529             :             ("sid not present in Family Safety Users"));
     530             :     return NS_OK;
     531             :   }
     532             :   nsCOMPtr<nsIWindowsRegKey> sidKey;
     533             :   rv = usersKey->OpenChild(sid, flags, getter_AddRefs(sidKey));
     534             :   if (NS_FAILED(rv)) {
     535             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open sid key"));
     536             :     return rv;
     537             :   }
     538             :   // There are three keys we're interested in: "Parental Controls On",
     539             :   // "Logging Required", and "Web\\Filter On". These keys will have value 0
     540             :   // or 1, indicating a particular feature is disabled or enabled,
     541             :   // respectively. So, if "Parental Controls On" is not 1, Family Safety is
     542             :   // disabled and we don't care about anything else. If both "Logging
     543             :   // Required" and "Web\\Filter On" are 0, the proxy will not be running,
     544             :   // so for our purposes we can consider Family Safety disabled in that
     545             :   // case.
     546             :   // By default, "Logging Required" is 1 and "Web\\Filter On" is 0,
     547             :   // reflecting the initial settings when Family Safety is enabled for an
     548             :   // account for the first time, However, these sub-keys are not created
     549             :   // unless they are switched away from the default value.
     550             :   uint32_t parentalControlsOn;
     551             :   rv = sidKey->ReadIntValue(NS_LITERAL_STRING("Parental Controls On"),
     552             :                             &parentalControlsOn);
     553             :   if (NS_FAILED(rv)) {
     554             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     555             :             ("couldn't read Parental Controls On"));
     556             :     return rv;
     557             :   }
     558             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     559             :           ("Parental Controls On: %u", parentalControlsOn));
     560             :   if (parentalControlsOn != 1) {
     561             :     return NS_OK;
     562             :   }
     563             :   uint32_t loggingRequired;
     564             :   rv = ReadRegKeyValueWithDefault(sidKey, flags, nullptr, L"Logging Required",
     565             :                                   1, loggingRequired);
     566             :   if (NS_FAILED(rv)) {
     567             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     568             :             ("failed to read value of Logging Required"));
     569             :     return rv;
     570             :   }
     571             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     572             :           ("Logging Required: %u", loggingRequired));
     573             :   uint32_t webFilterOn;
     574             :   rv = ReadRegKeyValueWithDefault(sidKey, flags, L"Web", L"Filter On", 0,
     575             :                                   webFilterOn);
     576             :   if (NS_FAILED(rv)) {
     577             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     578             :             ("failed to read value of Web\\Filter On"));
     579             :     return rv;
     580             :   }
     581             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Web\\Filter On: %u", webFilterOn));
     582             :   enabled = loggingRequired == 1 || webFilterOn == 1;
     583             :   return NS_OK;
     584             : }
     585             : 
     586             : // It would be convenient to just use nsIX509CertDB in the following code.
     587             : // However, since nsIX509CertDB depends on nsNSSComponent initialization (and
     588             : // since this code runs during that initialization), we can't use it. Instead,
     589             : // we can use NSS APIs directly (as long as we're called late enough in
     590             : // nsNSSComponent initialization such that those APIs are safe to use).
     591             : 
     592             : // Helper function to convert a PCCERT_CONTEXT (i.e. a certificate obtained via
     593             : // a Windows API) to a temporary CERTCertificate (i.e. a certificate for use
     594             : // with NSS APIs).
     595             : static UniqueCERTCertificate
     596             : PCCERT_CONTEXTToCERTCertificate(PCCERT_CONTEXT pccert)
     597             : {
     598             :   MOZ_ASSERT(pccert);
     599             :   if (!pccert) {
     600             :     return nullptr;
     601             :   }
     602             : 
     603             :   SECItem derCert = {
     604             :     siBuffer,
     605             :     pccert->pbCertEncoded,
     606             :     pccert->cbCertEncoded
     607             :   };
     608             :   return UniqueCERTCertificate(
     609             :     CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
     610             :                             nullptr, // nickname unnecessary
     611             :                             false, // not permanent
     612             :                             true)); // copy DER
     613             : }
     614             : 
     615             : static NS_NAMED_LITERAL_CSTRING(kMicrosoftFamilySafetyCN,
     616             :                                 "Microsoft Family Safety");
     617             : 
     618             : nsresult
     619             : nsNSSComponent::MaybeImportFamilySafetyRoot(PCCERT_CONTEXT certificate,
     620             :                                             bool& wasFamilySafetyRoot)
     621             : {
     622             :   MutexAutoLock lock(mMutex);
     623             :   MOZ_ASSERT(NS_IsMainThread());
     624             :   if (!NS_IsMainThread()) {
     625             :     return NS_ERROR_NOT_SAME_THREAD;
     626             :   }
     627             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("MaybeImportFamilySafetyRoot"));
     628             :   wasFamilySafetyRoot = false;
     629             : 
     630             :   UniqueCERTCertificate nssCertificate(
     631             :     PCCERT_CONTEXTToCERTCertificate(certificate));
     632             :   if (!nssCertificate) {
     633             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't decode certificate"));
     634             :     return NS_ERROR_FAILURE;
     635             :   }
     636             :   // Looking for a certificate with the common name 'Microsoft Family Safety'
     637             :   UniquePORTString subjectName(CERT_GetCommonName(&nssCertificate->subject));
     638             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     639             :           ("subject name is '%s'", subjectName.get()));
     640             :   if (kMicrosoftFamilySafetyCN.Equals(subjectName.get())) {
     641             :     wasFamilySafetyRoot = true;
     642             :     CERTCertTrust trust = {
     643             :       CERTDB_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_USER,
     644             :       0,
     645             :       0
     646             :     };
     647             :     if (CERT_ChangeCertTrust(nullptr, nssCertificate.get(), &trust)
     648             :           != SECSuccess) {
     649             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     650             :               ("couldn't trust certificate for TLS server auth"));
     651             :       return NS_ERROR_FAILURE;
     652             :     }
     653             :     MOZ_ASSERT(!mFamilySafetyRoot);
     654             :     mFamilySafetyRoot = Move(nssCertificate);
     655             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("added Family Safety root"));
     656             :   }
     657             :   return NS_OK;
     658             : }
     659             : 
     660             : // Because HCERTSTORE is just a typedef void*, we can't use any of the nice
     661             : // scoped or unique pointer templates. To elaborate, any attempt would
     662             : // instantiate those templates with T = void. When T gets used in the context
     663             : // of T&, this results in void&, which isn't legal.
     664             : class ScopedCertStore final
     665             : {
     666             : public:
     667             :   explicit ScopedCertStore(HCERTSTORE certstore) : certstore(certstore) {}
     668             : 
     669             :   ~ScopedCertStore()
     670             :   {
     671             :     CertCloseStore(certstore, 0);
     672             :   }
     673             : 
     674             :   HCERTSTORE get()
     675             :   {
     676             :     return certstore;
     677             :   }
     678             : 
     679             : private:
     680             :   ScopedCertStore(const ScopedCertStore&) = delete;
     681             :   ScopedCertStore& operator=(const ScopedCertStore&) = delete;
     682             :   HCERTSTORE certstore;
     683             : };
     684             : 
     685             : static const wchar_t* kWindowsDefaultRootStoreName = L"ROOT";
     686             : 
     687             : nsresult
     688             : nsNSSComponent::LoadFamilySafetyRoot()
     689             : {
     690             :   ScopedCertStore certstore(
     691             :     CertOpenSystemStore(0, kWindowsDefaultRootStoreName));
     692             :   if (!certstore.get()) {
     693             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     694             :             ("couldn't get certstore '%S'", kWindowsDefaultRootStoreName));
     695             :     return NS_ERROR_FAILURE;
     696             :   }
     697             :   // Any resources held by the certificate are released by the next call to
     698             :   // CertFindCertificateInStore.
     699             :   PCCERT_CONTEXT certificate = nullptr;
     700             :   while ((certificate = CertFindCertificateInStore(certstore.get(),
     701             :                                                    X509_ASN_ENCODING, 0,
     702             :                                                    CERT_FIND_ANY, nullptr,
     703             :                                                    certificate))) {
     704             :     bool wasFamilySafetyRoot = false;
     705             :     nsresult rv = MaybeImportFamilySafetyRoot(certificate,
     706             :                                               wasFamilySafetyRoot);
     707             :     if (NS_SUCCEEDED(rv) && wasFamilySafetyRoot) {
     708             :       return NS_OK; // We're done (we're only expecting one root).
     709             :     }
     710             :   }
     711             :   return NS_ERROR_FAILURE;
     712             : }
     713             : 
     714             : void
     715             : nsNSSComponent::UnloadFamilySafetyRoot()
     716             : {
     717             :   MutexAutoLock lock(mMutex);
     718             :   MOZ_ASSERT(NS_IsMainThread());
     719             :   if (!NS_IsMainThread()) {
     720             :     return;
     721             :   }
     722             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("UnloadFamilySafetyRoot"));
     723             :   if (!mFamilySafetyRoot) {
     724             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Family Safety Root wasn't present"));
     725             :     return;
     726             :   }
     727             :   // It would be intuitive to set the trust to { 0, 0, 0 } here. However, this
     728             :   // doesn't work for temporary certificates because CERT_ChangeCertTrust first
     729             :   // looks up the current trust settings in the permanent cert database, finds
     730             :   // that such trust doesn't exist, considers the current trust to be
     731             :   // { 0, 0, 0 }, and decides that it doesn't need to update the trust since
     732             :   // they're the same. To work around this, we set a non-zero flag to ensure
     733             :   // that the trust will get updated.
     734             :   CERTCertTrust trust = { CERTDB_USER, 0, 0 };
     735             :   if (CERT_ChangeCertTrust(nullptr, mFamilySafetyRoot.get(), &trust)
     736             :         != SECSuccess) {
     737             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     738             :             ("couldn't untrust certificate for TLS server auth"));
     739             :   }
     740             :   mFamilySafetyRoot = nullptr;
     741             : }
     742             : 
     743             : #endif // XP_WIN
     744             : 
     745             : // The supported values of this pref are:
     746             : // 0: disable detecting Family Safety mode and importing the root
     747             : // 1: only attempt to detect Family Safety mode (don't import the root)
     748             : // 2: detect Family Safety mode and import the root
     749             : const char* kFamilySafetyModePref = "security.family_safety.mode";
     750             : 
     751             : // The telemetry gathered by this function is as follows:
     752             : // 0-2: the value of the Family Safety mode pref
     753             : // 3: detecting Family Safety mode failed
     754             : // 4: Family Safety was not enabled
     755             : // 5: Family Safety was enabled
     756             : // 6: failed to import the Family Safety root
     757             : // 7: successfully imported the root
     758             : void
     759           1 : nsNSSComponent::MaybeEnableFamilySafetyCompatibility()
     760             : {
     761             : #ifdef XP_WIN
     762             :   UnloadFamilySafetyRoot();
     763             :   if (!(IsWin8Point1OrLater() && !IsWin10OrLater())) {
     764             :     return;
     765             :   }
     766             :   // Detect but don't import by default.
     767             :   uint32_t familySafetyMode = Preferences::GetUint(kFamilySafetyModePref, 1);
     768             :   if (familySafetyMode > 2) {
     769             :     familySafetyMode = 0;
     770             :   }
     771             :   Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, familySafetyMode);
     772             :   if (familySafetyMode == 0) {
     773             :     return;
     774             :   }
     775             :   bool familySafetyEnabled;
     776             :   nsresult rv = AccountHasFamilySafetyEnabled(familySafetyEnabled);
     777             :   if (NS_FAILED(rv)) {
     778             :     Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, 3);
     779             :     return;
     780             :   }
     781             :   if (!familySafetyEnabled) {
     782             :     Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, 4);
     783             :     return;
     784             :   }
     785             :   Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, 5);
     786             :   if (familySafetyMode == 2) {
     787             :     rv = LoadFamilySafetyRoot();
     788             :     if (NS_FAILED(rv)) {
     789             :       Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, 6);
     790             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     791             :               ("failed to load Family Safety root"));
     792             :     } else {
     793             :       Telemetry::Accumulate(Telemetry::FAMILY_SAFETY, 7);
     794             :     }
     795             :   }
     796             : #endif // XP_WIN
     797           1 : }
     798             : 
     799             : #ifdef XP_WIN
     800             : // Helper function to determine if the OS considers the given certificate to be
     801             : // a trust anchor for TLS server auth certificates. This is to be used in the
     802             : // context of importing what are presumed to be root certificates from the OS.
     803             : // If this function returns true but it turns out that the given certificate is
     804             : // in some way unsuitable to issue certificates, mozilla::pkix will never build
     805             : // a valid chain that includes the certificate, so importing it even if it
     806             : // isn't a valid CA poses no risk.
     807             : static bool
     808             : CertIsTrustAnchorForTLSServerAuth(PCCERT_CONTEXT certificate)
     809             : {
     810             :   MOZ_ASSERT(certificate);
     811             :   if (!certificate) {
     812             :     return false;
     813             :   }
     814             : 
     815             :   PCCERT_CHAIN_CONTEXT pChainContext = nullptr;
     816             :   CERT_ENHKEY_USAGE enhkeyUsage;
     817             :   memset(&enhkeyUsage, 0, sizeof(CERT_ENHKEY_USAGE));
     818             :   LPSTR identifiers[] = {
     819             :     "1.3.6.1.5.5.7.3.1", // id-kp-serverAuth
     820             :   };
     821             :   enhkeyUsage.cUsageIdentifier = ArrayLength(identifiers);
     822             :   enhkeyUsage.rgpszUsageIdentifier = identifiers;
     823             :   CERT_USAGE_MATCH certUsage;
     824             :   memset(&certUsage, 0, sizeof(CERT_USAGE_MATCH));
     825             :   certUsage.dwType = USAGE_MATCH_TYPE_AND;
     826             :   certUsage.Usage = enhkeyUsage;
     827             :   CERT_CHAIN_PARA chainPara;
     828             :   memset(&chainPara, 0, sizeof(CERT_CHAIN_PARA));
     829             :   chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
     830             :   chainPara.RequestedUsage = certUsage;
     831             : 
     832             :   if (!CertGetCertificateChain(nullptr, certificate, nullptr, nullptr,
     833             :                                &chainPara, 0, nullptr, &pChainContext)) {
     834             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CertGetCertificateChain failed"));
     835             :     return false;
     836             :   }
     837             :   bool trusted = pChainContext->TrustStatus.dwErrorStatus ==
     838             :                  CERT_TRUST_NO_ERROR;
     839             :   bool isRoot = pChainContext->cChain == 1;
     840             :   CertFreeCertificateChain(pChainContext);
     841             :   if (trusted && isRoot) {
     842             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     843             :             ("certificate is trust anchor for TLS server auth"));
     844             :     return true;
     845             :   }
     846             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     847             :           ("certificate not trust anchor for TLS server auth"));
     848             :   return false;
     849             : }
     850             : 
     851             : void
     852             : nsNSSComponent::UnloadEnterpriseRoots(const MutexAutoLock& /*proof of lock*/)
     853             : {
     854             :   MOZ_ASSERT(NS_IsMainThread());
     855             :   if (!NS_IsMainThread()) {
     856             :     return;
     857             :   }
     858             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("UnloadEnterpriseRoots"));
     859             :   if (!mEnterpriseRoots) {
     860             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("no enterprise roots were present"));
     861             :     return;
     862             :   }
     863             :   // It would be intuitive to set the trust to { 0, 0, 0 } here. However, this
     864             :   // doesn't work for temporary certificates because CERT_ChangeCertTrust first
     865             :   // looks up the current trust settings in the permanent cert database, finds
     866             :   // that such trust doesn't exist, considers the current trust to be
     867             :   // { 0, 0, 0 }, and decides that it doesn't need to update the trust since
     868             :   // they're the same. To work around this, we set a non-zero flag to ensure
     869             :   // that the trust will get updated.
     870             :   CERTCertTrust trust = { CERTDB_USER, 0, 0 };
     871             :   for (CERTCertListNode* n = CERT_LIST_HEAD(mEnterpriseRoots.get());
     872             :        !CERT_LIST_END(n, mEnterpriseRoots.get()); n = CERT_LIST_NEXT(n)) {
     873             :     if (!n || !n->cert) {
     874             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     875             :               ("library failure: CERTCertListNode null or lacks cert"));
     876             :       continue;
     877             :     }
     878             :     if (CERT_ChangeCertTrust(nullptr, n->cert, &trust) != SECSuccess) {
     879             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     880             :               ("couldn't untrust certificate for TLS server auth"));
     881             :     }
     882             :   }
     883             :   mEnterpriseRoots = nullptr;
     884             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("unloaded enterprise roots"));
     885             : }
     886             : 
     887             : NS_IMETHODIMP
     888             : nsNSSComponent::GetEnterpriseRoots(nsIX509CertList** enterpriseRoots)
     889             : {
     890             :   nsNSSShutDownPreventionLock lock;
     891             :   MutexAutoLock nsNSSComponentLock(mMutex);
     892             :   MOZ_ASSERT(NS_IsMainThread());
     893             :   if (!NS_IsMainThread()) {
     894             :     return NS_ERROR_NOT_SAME_THREAD;
     895             :   }
     896             :   NS_ENSURE_ARG_POINTER(enterpriseRoots);
     897             : 
     898             :   // nsNSSComponent isn't a nsNSSShutDownObject, so we can't check
     899             :   // isAlreadyShutDown(). However, since mEnterpriseRoots is cleared when NSS
     900             :   // shuts down, we can use that as a proxy for checking for NSS shutdown.
     901             :   // (Of course, it may also be the case that no enterprise roots were imported,
     902             :   // so we should just return a null list and NS_OK in this case.)
     903             :   if (!mEnterpriseRoots) {
     904             :     *enterpriseRoots = nullptr;
     905             :     return NS_OK;
     906             :   }
     907             :   UniqueCERTCertList enterpriseRootsCopy(
     908             :     nsNSSCertList::DupCertList(mEnterpriseRoots, lock));
     909             :   if (!enterpriseRootsCopy) {
     910             :     return NS_ERROR_FAILURE;
     911             :   }
     912             :   nsCOMPtr<nsIX509CertList> enterpriseRootsCertList(
     913             :     new nsNSSCertList(Move(enterpriseRootsCopy), lock));
     914             :   if (!enterpriseRootsCertList) {
     915             :     return NS_ERROR_FAILURE;
     916             :   }
     917             :   enterpriseRootsCertList.forget(enterpriseRoots);
     918             :   return NS_OK;
     919             : }
     920             : #endif // XP_WIN
     921             : 
     922             : static const char* kEnterpriseRootModePref = "security.enterprise_roots.enabled";
     923             : 
     924             : void
     925           1 : nsNSSComponent::MaybeImportEnterpriseRoots()
     926             : {
     927             : #ifdef XP_WIN
     928             :   MutexAutoLock lock(mMutex);
     929             :   MOZ_ASSERT(NS_IsMainThread());
     930             :   if (!NS_IsMainThread()) {
     931             :     return;
     932             :   }
     933             :   UnloadEnterpriseRoots(lock);
     934             :   bool importEnterpriseRoots = Preferences::GetBool(kEnterpriseRootModePref,
     935             :                                                     false);
     936             :   if (!importEnterpriseRoots) {
     937             :     return;
     938             :   }
     939             : 
     940             :   MOZ_ASSERT(!mEnterpriseRoots);
     941             :   mEnterpriseRoots.reset(CERT_NewCertList());
     942             :   if (!mEnterpriseRoots) {
     943             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
     944             :             ("failed to allocate a new CERTCertList for mEnterpriseRoots"));
     945             :     return;
     946             :   }
     947             : 
     948             :   ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE, lock);
     949             :   ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
     950             :                                    lock);
     951             :   ImportEnterpriseRootsForLocation(CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
     952             :                                    lock);
     953             : #endif // XP_WIN
     954           1 : }
     955             : 
     956             : #ifdef XP_WIN
     957             : // Loads the enterprise roots at the registry location corresponding to the
     958             : // given location flag.
     959             : // Supported flags are:
     960             : //   CERT_SYSTEM_STORE_LOCAL_MACHINE
     961             : //     (for HKLM\SOFTWARE\Microsoft\SystemCertificates)
     962             : //   CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
     963             : //     (for HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\Root\Certificates)
     964             : //   CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
     965             : //     (for HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\Root\Certificates)
     966             : void
     967             : nsNSSComponent::ImportEnterpriseRootsForLocation(
     968             :   DWORD locationFlag, const MutexAutoLock& /*proof of lock*/)
     969             : {
     970             :   MOZ_ASSERT(NS_IsMainThread());
     971             :   if (!NS_IsMainThread()) {
     972             :     return;
     973             :   }
     974             :   MOZ_ASSERT(locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE ||
     975             :              locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY ||
     976             :              locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
     977             :              "unexpected locationFlag for ImportEnterpriseRootsForLocation");
     978             :   if (!(locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE ||
     979             :         locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY ||
     980             :         locationFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE)) {
     981             :     return;
     982             :   }
     983             : 
     984             :   DWORD flags = locationFlag |
     985             :                 CERT_STORE_OPEN_EXISTING_FLAG |
     986             :                 CERT_STORE_READONLY_FLAG;
     987             :   // The certificate store being opened should consist only of certificates
     988             :   // added by a user or administrator and not any certificates that are part
     989             :   // of Microsoft's root store program.
     990             :   // The 3rd parameter to CertOpenStore should be NULL according to
     991             :   // https://msdn.microsoft.com/en-us/library/windows/desktop/aa376559%28v=vs.85%29.aspx
     992             :   ScopedCertStore enterpriseRootStore(CertOpenStore(
     993             :     CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, NULL, flags,
     994             :     kWindowsDefaultRootStoreName));
     995             :   if (!enterpriseRootStore.get()) {
     996             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to open enterprise root store"));
     997             :     return;
     998             :   }
     999             :   CERTCertTrust trust = {
    1000             :     CERTDB_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_USER,
    1001             :     0,
    1002             :     0
    1003             :   };
    1004             :   PCCERT_CONTEXT certificate = nullptr;
    1005             :   uint32_t numImported = 0;
    1006             :   while ((certificate = CertFindCertificateInStore(enterpriseRootStore.get(),
    1007             :                                                    X509_ASN_ENCODING, 0,
    1008             :                                                    CERT_FIND_ANY, nullptr,
    1009             :                                                    certificate))) {
    1010             :     if (!CertIsTrustAnchorForTLSServerAuth(certificate)) {
    1011             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1012             :               ("skipping cert not trust anchor for TLS server auth"));
    1013             :       continue;
    1014             :     }
    1015             :     UniqueCERTCertificate nssCertificate(
    1016             :       PCCERT_CONTEXTToCERTCertificate(certificate));
    1017             :     if (!nssCertificate) {
    1018             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't decode certificate"));
    1019             :       continue;
    1020             :     }
    1021             :     // Don't import the Microsoft Family Safety root (this prevents the
    1022             :     // Enterprise Roots feature from interacting poorly with the Family
    1023             :     // Safety support).
    1024             :     UniquePORTString subjectName(
    1025             :       CERT_GetCommonName(&nssCertificate->subject));
    1026             :     if (kMicrosoftFamilySafetyCN.Equals(subjectName.get())) {
    1027             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("skipping Family Safety Root"));
    1028             :       continue;
    1029             :     }
    1030             :     MOZ_ASSERT(mEnterpriseRoots, "mEnterpriseRoots unexpectedly NULL?");
    1031             :     if (!mEnterpriseRoots) {
    1032             :       return;
    1033             :     }
    1034             :     if (CERT_AddCertToListTail(mEnterpriseRoots.get(), nssCertificate.get())
    1035             :           != SECSuccess) {
    1036             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't add cert to list"));
    1037             :       continue;
    1038             :     }
    1039             :     if (CERT_ChangeCertTrust(nullptr, nssCertificate.get(), &trust)
    1040             :           != SECSuccess) {
    1041             :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1042             :               ("couldn't trust certificate for TLS server auth"));
    1043             :     }
    1044             :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Imported '%s'", subjectName.get()));
    1045             :     numImported++;
    1046             :     // now owned by mEnterpriseRoots
    1047             :     Unused << nssCertificate.release();
    1048             :   }
    1049             :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("imported %u roots", numImported));
    1050             : }
    1051             : #endif // XP_WIN
    1052             : 
    1053             : void
    1054           1 : nsNSSComponent::LoadLoadableRoots()
    1055             : {
    1056             :   // Find the best Roots module for our purposes.
    1057             :   // Prefer the application's installation directory,
    1058             :   // but also ensure the library is at least the version we expect.
    1059             : 
    1060           2 :   nsAutoString modName;
    1061           1 :   nsresult rv = GetPIPNSSBundleString("RootCertModuleName", modName);
    1062           1 :   if (NS_FAILED(rv)) {
    1063             :     // When running Cpp unit tests on Android, this will fail because string
    1064             :     // bundles aren't available (see bug 1311077, bug 1228175 comment 12, and
    1065             :     // bug 929655). Because the module name is really only for display purposes,
    1066             :     // we can just hard-code the value here. Furthermore, if we want to be able
    1067             :     // to stop using string bundles in PSM in this way, we'll have to hard-code
    1068             :     // the string and only use the localized version when displaying it to the
    1069             :     // user, so this is a step in that direction anyway.
    1070           0 :     modName.AssignLiteral("Builtin Roots Module");
    1071             :   }
    1072             : 
    1073           2 :   nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
    1074           1 :   if (!directoryService)
    1075           0 :     return;
    1076             : 
    1077             :   static const char nss_lib[] = "nss3";
    1078             :   const char* possible_ckbi_locations[] = {
    1079             :     nss_lib, // This special value means: search for ckbi in the directory
    1080             :              // where nss3 is.
    1081             :     NS_XPCOM_CURRENT_PROCESS_DIR,
    1082             :     NS_GRE_DIR,
    1083             :     0 // This special value means:
    1084             :       //   search for ckbi in the directories on the shared
    1085             :       //   library/DLL search path
    1086           1 :   };
    1087             : 
    1088           1 :   for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
    1089           1 :     nsAutoCString libDir;
    1090             : 
    1091           1 :     if (possible_ckbi_locations[il]) {
    1092           2 :       nsCOMPtr<nsIFile> mozFile;
    1093           1 :       if (possible_ckbi_locations[il] == nss_lib) {
    1094             :         // Get the location of the nss3 library.
    1095             :         char* nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
    1096           1 :                                                    (PRFuncPtr) NSS_Initialize);
    1097           1 :         if (!nss_path) {
    1098           0 :           continue;
    1099             :         }
    1100             :         // Get the directory containing the nss3 library.
    1101           2 :         nsCOMPtr<nsIFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
    1102           1 :         if (NS_SUCCEEDED(rv)) {
    1103           1 :           rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
    1104             :         }
    1105           1 :         PR_Free(nss_path); // PR_GetLibraryFilePathname() uses PR_Malloc().
    1106           1 :         if (NS_SUCCEEDED(rv)) {
    1107           2 :           nsCOMPtr<nsIFile> file;
    1108           1 :           if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
    1109           1 :             mozFile = do_QueryInterface(file);
    1110             :           }
    1111             :         }
    1112             :       } else {
    1113           0 :         directoryService->Get( possible_ckbi_locations[il],
    1114             :                                NS_GET_IID(nsIFile),
    1115           0 :                                getter_AddRefs(mozFile));
    1116             :       }
    1117             : 
    1118           1 :       if (!mozFile) {
    1119           0 :         continue;
    1120             :       }
    1121             : 
    1122           1 :       if (NS_FAILED(mozFile->GetNativePath(libDir))) {
    1123           0 :         continue;
    1124             :       }
    1125             :     }
    1126             : 
    1127           1 :     NS_ConvertUTF16toUTF8 modNameUTF8(modName);
    1128           1 :     if (mozilla::psm::LoadLoadableRoots(libDir, modNameUTF8)) {
    1129           1 :       break;
    1130             :     }
    1131             :   }
    1132             : }
    1133             : 
    1134             : void
    1135           0 : nsNSSComponent::UnloadLoadableRoots()
    1136             : {
    1137             :   nsresult rv;
    1138           0 :   nsAutoString modName;
    1139           0 :   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
    1140           0 :   if (NS_FAILED(rv)) return;
    1141             : 
    1142           0 :   NS_ConvertUTF16toUTF8 modNameUTF8(modName);
    1143           0 :   ::mozilla::psm::UnloadLoadableRoots(modNameUTF8.get());
    1144             : }
    1145             : 
    1146             : nsresult
    1147           1 : nsNSSComponent::ConfigureInternalPKCS11Token()
    1148             : {
    1149           2 :   nsAutoString manufacturerID;
    1150           2 :   nsAutoString libraryDescription;
    1151           2 :   nsAutoString tokenDescription;
    1152           2 :   nsAutoString privateTokenDescription;
    1153           2 :   nsAutoString slotDescription;
    1154           2 :   nsAutoString privateSlotDescription;
    1155           2 :   nsAutoString fips140SlotDescription;
    1156           2 :   nsAutoString fips140TokenDescription;
    1157             : 
    1158             :   nsresult rv;
    1159           1 :   rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
    1160           1 :   if (NS_FAILED(rv)) return rv;
    1161             : 
    1162           1 :   rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
    1163           1 :   if (NS_FAILED(rv)) return rv;
    1164             : 
    1165           1 :   rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
    1166           1 :   if (NS_FAILED(rv)) return rv;
    1167             : 
    1168           1 :   rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
    1169           1 :   if (NS_FAILED(rv)) return rv;
    1170             : 
    1171           1 :   rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
    1172           1 :   if (NS_FAILED(rv)) return rv;
    1173             : 
    1174           1 :   rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
    1175           1 :   if (NS_FAILED(rv)) return rv;
    1176             : 
    1177           1 :   rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
    1178           1 :   if (NS_FAILED(rv)) return rv;
    1179             : 
    1180           1 :   rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
    1181           1 :   if (NS_FAILED(rv)) return rv;
    1182             : 
    1183           8 :   PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
    1184           2 :                        NS_ConvertUTF16toUTF8(libraryDescription).get(),
    1185           2 :                        NS_ConvertUTF16toUTF8(tokenDescription).get(),
    1186           2 :                        NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
    1187           2 :                        NS_ConvertUTF16toUTF8(slotDescription).get(),
    1188           2 :                        NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
    1189           2 :                        NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
    1190           2 :                        NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
    1191           1 :                        0, 0);
    1192           1 :   return NS_OK;
    1193             : }
    1194             : 
    1195             : nsresult
    1196           1 : nsNSSComponent::InitializePIPNSSBundle()
    1197             : {
    1198           2 :   MutexAutoLock lock(mMutex);
    1199             :   nsresult rv;
    1200           2 :   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
    1201           1 :   if (NS_FAILED(rv) || !bundleService)
    1202           0 :     return NS_ERROR_FAILURE;
    1203             : 
    1204           2 :   bundleService->CreateBundle("chrome://pipnss/locale/pipnss.properties",
    1205           2 :                               getter_AddRefs(mPIPNSSBundle));
    1206           1 :   if (!mPIPNSSBundle)
    1207           0 :     rv = NS_ERROR_FAILURE;
    1208             : 
    1209           2 :   bundleService->CreateBundle("chrome://pipnss/locale/nsserrors.properties",
    1210           2 :                               getter_AddRefs(mNSSErrorsBundle));
    1211           1 :   if (!mNSSErrorsBundle)
    1212           0 :     rv = NS_ERROR_FAILURE;
    1213             : 
    1214           1 :   return rv;
    1215             : }
    1216             : 
    1217             : // Table of pref names and SSL cipher ID
    1218             : typedef struct {
    1219             :   const char* pref;
    1220             :   long id;
    1221             :   bool enabledByDefault;
    1222             : } CipherPref;
    1223             : 
    1224             : // Update the switch statement in AccumulateCipherSuite in nsNSSCallbacks.cpp
    1225             : // when you add/remove cipher suites here.
    1226             : static const CipherPref sCipherPrefs[] = {
    1227             :  { "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
    1228             :    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, true },
    1229             :  { "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
    1230             :    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, true },
    1231             : 
    1232             :  { "security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256",
    1233             :    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, true },
    1234             :  { "security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256",
    1235             :    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, true },
    1236             : 
    1237             :  { "security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384",
    1238             :    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, true },
    1239             :  { "security.ssl3.ecdhe_rsa_aes_256_gcm_sha384",
    1240             :    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, true },
    1241             : 
    1242             :  { "security.ssl3.ecdhe_rsa_aes_128_sha",
    1243             :    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
    1244             :  { "security.ssl3.ecdhe_ecdsa_aes_128_sha",
    1245             :    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
    1246             : 
    1247             :  { "security.ssl3.ecdhe_rsa_aes_256_sha",
    1248             :    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },
    1249             :  { "security.ssl3.ecdhe_ecdsa_aes_256_sha",
    1250             :    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true },
    1251             : 
    1252             :  { "security.ssl3.dhe_rsa_aes_128_sha",
    1253             :    TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
    1254             : 
    1255             :  { "security.ssl3.dhe_rsa_aes_256_sha",
    1256             :    TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true },
    1257             : 
    1258             :  { "security.tls13.aes_128_gcm_sha256",
    1259             :    TLS_AES_128_GCM_SHA256, true },
    1260             :  { "security.tls13.chacha20_poly1305_sha256",
    1261             :    TLS_CHACHA20_POLY1305_SHA256, true },
    1262             :  { "security.tls13.aes_256_gcm_sha384",
    1263             :    TLS_AES_256_GCM_SHA384, true },
    1264             : 
    1265             :  { "security.ssl3.rsa_aes_128_sha",
    1266             :    TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
    1267             :  { "security.ssl3.rsa_aes_256_sha",
    1268             :    TLS_RSA_WITH_AES_256_CBC_SHA, true }, // deprecated (RSA key exchange)
    1269             :  { "security.ssl3.rsa_des_ede3_sha",
    1270             :    TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
    1271             : 
    1272             :  // All the rest are disabled
    1273             : 
    1274             :  { nullptr, 0 } // end marker
    1275             : };
    1276             : 
    1277             : // This function will convert from pref values like 1, 2, ...
    1278             : // to the internal values of SSL_LIBRARY_VERSION_TLS_1_0,
    1279             : // SSL_LIBRARY_VERSION_TLS_1_1, ...
    1280             : /*static*/ void
    1281           3 : nsNSSComponent::FillTLSVersionRange(SSLVersionRange& rangeOut,
    1282             :                                     uint32_t minFromPrefs,
    1283             :                                     uint32_t maxFromPrefs,
    1284             :                                     SSLVersionRange defaults)
    1285             : {
    1286           3 :   rangeOut = defaults;
    1287             :   // determine what versions are supported
    1288             :   SSLVersionRange supported;
    1289           3 :   if (SSL_VersionRangeGetSupported(ssl_variant_stream, &supported)
    1290             :         != SECSuccess) {
    1291           0 :     return;
    1292             :   }
    1293             : 
    1294             :   // Clip the defaults by what NSS actually supports to enable
    1295             :   // working with a system NSS with different ranges.
    1296           3 :   rangeOut.min = std::max(rangeOut.min, supported.min);
    1297           3 :   rangeOut.max = std::min(rangeOut.max, supported.max);
    1298             : 
    1299             :   // convert min/maxFromPrefs to the internal representation
    1300           3 :   minFromPrefs += SSL_LIBRARY_VERSION_3_0;
    1301           3 :   maxFromPrefs += SSL_LIBRARY_VERSION_3_0;
    1302             :   // if min/maxFromPrefs are invalid, use defaults
    1303           6 :   if (minFromPrefs > maxFromPrefs ||
    1304           6 :       minFromPrefs < supported.min || maxFromPrefs > supported.max ||
    1305             :       minFromPrefs < SSL_LIBRARY_VERSION_TLS_1_0) {
    1306           0 :     return;
    1307             :   }
    1308             : 
    1309             :   // fill out rangeOut
    1310           3 :   rangeOut.min = (uint16_t) minFromPrefs;
    1311           3 :   rangeOut.max = (uint16_t) maxFromPrefs;
    1312             : }
    1313             : 
    1314             : static const int32_t OCSP_ENABLED_DEFAULT = 1;
    1315             : static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
    1316             : static const bool FALSE_START_ENABLED_DEFAULT = true;
    1317             : static const bool ALPN_ENABLED_DEFAULT = false;
    1318             : static const bool ENABLED_0RTT_DATA_DEFAULT = false;
    1319             : 
    1320             : static void
    1321           1 : ConfigureTLSSessionIdentifiers()
    1322             : {
    1323             :   bool disableSessionIdentifiers =
    1324           1 :     Preferences::GetBool("security.ssl.disable_session_identifiers", false);
    1325           1 :   SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
    1326           1 :   SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
    1327           1 : }
    1328             : 
    1329             : namespace {
    1330             : 
    1331             : class CipherSuiteChangeObserver : public nsIObserver
    1332             : {
    1333             : public:
    1334             :   NS_DECL_ISUPPORTS
    1335             :   NS_DECL_NSIOBSERVER
    1336             : 
    1337             :   static nsresult StartObserve();
    1338             : 
    1339             : protected:
    1340           0 :   virtual ~CipherSuiteChangeObserver() {}
    1341             : 
    1342             : private:
    1343             :   static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
    1344           2 :   CipherSuiteChangeObserver() {}
    1345             : };
    1346             : 
    1347          24 : NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver, nsIObserver)
    1348             : 
    1349             : // static
    1350           3 : StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
    1351             : 
    1352             : // static
    1353             : nsresult
    1354           2 : CipherSuiteChangeObserver::StartObserve()
    1355             : {
    1356           2 :   MOZ_ASSERT(NS_IsMainThread(),
    1357             :              "CipherSuiteChangeObserver::StartObserve() can only be accessed "
    1358             :              "on the main thread");
    1359           2 :   if (!sObserver) {
    1360           4 :     RefPtr<CipherSuiteChangeObserver> observer = new CipherSuiteChangeObserver();
    1361           2 :     nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
    1362           2 :     if (NS_FAILED(rv)) {
    1363           0 :       sObserver = nullptr;
    1364           0 :       return rv;
    1365             :     }
    1366             : 
    1367             :     nsCOMPtr<nsIObserverService> observerService =
    1368           4 :       mozilla::services::GetObserverService();
    1369           2 :     observerService->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
    1370           2 :                                  false);
    1371             : 
    1372           2 :     sObserver = observer;
    1373             :   }
    1374           2 :   return NS_OK;
    1375             : }
    1376             : 
    1377             : nsresult
    1378           0 : CipherSuiteChangeObserver::Observe(nsISupports* /*aSubject*/,
    1379             :                                    const char* aTopic,
    1380             :                                    const char16_t* someData)
    1381             : {
    1382           0 :   MOZ_ASSERT(NS_IsMainThread(),
    1383             :              "CipherSuiteChangeObserver::Observe can only be accessed on main "
    1384             :              "thread");
    1385           0 :   if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
    1386           0 :     NS_ConvertUTF16toUTF8  prefName(someData);
    1387             :     // Look through the cipher table and set according to pref setting
    1388           0 :     const CipherPref* const cp = sCipherPrefs;
    1389           0 :     for (size_t i = 0; cp[i].pref; ++i) {
    1390           0 :       if (prefName.Equals(cp[i].pref)) {
    1391           0 :         bool cipherEnabled = Preferences::GetBool(cp[i].pref,
    1392           0 :                                                   cp[i].enabledByDefault);
    1393           0 :         SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
    1394           0 :         SSL_ClearSessionCache();
    1395           0 :         break;
    1396             :       }
    1397             :     }
    1398           0 :   } else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
    1399           0 :     Preferences::RemoveObserver(this, "security.");
    1400           0 :     MOZ_ASSERT(sObserver.get() == this);
    1401           0 :     sObserver = nullptr;
    1402             :     nsCOMPtr<nsIObserverService> observerService =
    1403           0 :       mozilla::services::GetObserverService();
    1404           0 :     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    1405             :   }
    1406           0 :   return NS_OK;
    1407             : }
    1408             : 
    1409             : } // namespace
    1410             : 
    1411           1 : void nsNSSComponent::setValidationOptions(bool isInitialSetting)
    1412             : {
    1413           2 :   MutexAutoLock lock(mMutex);
    1414             :   // This preference controls whether we do OCSP fetching and does not affect
    1415             :   // OCSP stapling.
    1416             :   // 0 = disabled, 1 = enabled
    1417             :   int32_t ocspEnabled = Preferences::GetInt("security.OCSP.enabled",
    1418           1 :                                             OCSP_ENABLED_DEFAULT);
    1419             : 
    1420           2 :   bool ocspRequired = ocspEnabled &&
    1421           2 :     Preferences::GetBool("security.OCSP.require", false);
    1422             : 
    1423             :   // We measure the setting of the pref at startup only to minimize noise by
    1424             :   // addons that may muck with the settings, though it probably doesn't matter.
    1425           1 :   if (isInitialSetting) {
    1426           1 :     Telemetry::Accumulate(Telemetry::CERT_OCSP_ENABLED, ocspEnabled);
    1427           1 :     Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
    1428             :   }
    1429             : 
    1430             :   bool ocspStaplingEnabled = Preferences::GetBool("security.ssl.enable_ocsp_stapling",
    1431           1 :                                                   true);
    1432           1 :   PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
    1433           1 :   PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
    1434             : 
    1435             :   bool ocspMustStapleEnabled = Preferences::GetBool("security.ssl.enable_ocsp_must_staple",
    1436           1 :                                                     true);
    1437           1 :   PublicSSLState()->SetOCSPMustStapleEnabled(ocspMustStapleEnabled);
    1438           1 :   PrivateSSLState()->SetOCSPMustStapleEnabled(ocspMustStapleEnabled);
    1439             : 
    1440             :   const CertVerifier::CertificateTransparencyMode defaultCTMode =
    1441           1 :     CertVerifier::CertificateTransparencyMode::TelemetryOnly;
    1442             :   CertVerifier::CertificateTransparencyMode ctMode =
    1443             :     static_cast<CertVerifier::CertificateTransparencyMode>
    1444             :       (Preferences::GetInt("security.pki.certificate_transparency.mode",
    1445           1 :                            static_cast<int32_t>(defaultCTMode)));
    1446           1 :   switch (ctMode) {
    1447             :     case CertVerifier::CertificateTransparencyMode::Disabled:
    1448             :     case CertVerifier::CertificateTransparencyMode::TelemetryOnly:
    1449           1 :       break;
    1450             :     default:
    1451           0 :       ctMode = defaultCTMode;
    1452           0 :       break;
    1453             :   }
    1454             :   bool sctsEnabled =
    1455           1 :     ctMode != CertVerifier::CertificateTransparencyMode::Disabled;
    1456           1 :   PublicSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
    1457           1 :   PrivateSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
    1458             : 
    1459             :   CertVerifier::PinningMode pinningMode =
    1460             :     static_cast<CertVerifier::PinningMode>
    1461           1 :       (Preferences::GetInt("security.cert_pinning.enforcement_level",
    1462           1 :                            CertVerifier::pinningDisabled));
    1463           1 :   if (pinningMode > CertVerifier::pinningEnforceTestMode) {
    1464           0 :     pinningMode = CertVerifier::pinningDisabled;
    1465             :   }
    1466             : 
    1467             :   CertVerifier::SHA1Mode sha1Mode = static_cast<CertVerifier::SHA1Mode>
    1468             :       (Preferences::GetInt("security.pki.sha1_enforcement_level",
    1469           1 :                            static_cast<int32_t>(CertVerifier::SHA1Mode::Allowed)));
    1470           1 :   switch (sha1Mode) {
    1471             :     case CertVerifier::SHA1Mode::Allowed:
    1472             :     case CertVerifier::SHA1Mode::Forbidden:
    1473             :     case CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden:
    1474             :     case CertVerifier::SHA1Mode::ImportedRoot:
    1475             :     case CertVerifier::SHA1Mode::ImportedRootOrBefore2016:
    1476           1 :       break;
    1477             :     default:
    1478           0 :       sha1Mode = CertVerifier::SHA1Mode::Allowed;
    1479           0 :       break;
    1480             :   }
    1481             : 
    1482             :   // Convert a previously-available setting to a safe one.
    1483           1 :   if (sha1Mode == CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden) {
    1484           0 :     sha1Mode = CertVerifier::SHA1Mode::Forbidden;
    1485             :   }
    1486             : 
    1487             :   BRNameMatchingPolicy::Mode nameMatchingMode =
    1488             :     static_cast<BRNameMatchingPolicy::Mode>
    1489             :       (Preferences::GetInt("security.pki.name_matching_mode",
    1490           1 :                            static_cast<int32_t>(BRNameMatchingPolicy::Mode::DoNotEnforce)));
    1491           1 :   switch (nameMatchingMode) {
    1492             :     case BRNameMatchingPolicy::Mode::Enforce:
    1493             :     case BRNameMatchingPolicy::Mode::EnforceAfter23August2015:
    1494             :     case BRNameMatchingPolicy::Mode::EnforceAfter23August2016:
    1495             :     case BRNameMatchingPolicy::Mode::DoNotEnforce:
    1496           1 :       break;
    1497             :     default:
    1498           0 :       nameMatchingMode = BRNameMatchingPolicy::Mode::DoNotEnforce;
    1499           0 :       break;
    1500             :   }
    1501             : 
    1502             :   NetscapeStepUpPolicy netscapeStepUpPolicy =
    1503             :     static_cast<NetscapeStepUpPolicy>
    1504             :       (Preferences::GetUint("security.pki.netscape_step_up_policy",
    1505           1 :                             static_cast<uint32_t>(NetscapeStepUpPolicy::AlwaysMatch)));
    1506           1 :   switch (netscapeStepUpPolicy) {
    1507             :     case NetscapeStepUpPolicy::AlwaysMatch:
    1508             :     case NetscapeStepUpPolicy::MatchBefore23August2016:
    1509             :     case NetscapeStepUpPolicy::MatchBefore23August2015:
    1510             :     case NetscapeStepUpPolicy::NeverMatch:
    1511           1 :       break;
    1512             :     default:
    1513           0 :       netscapeStepUpPolicy = NetscapeStepUpPolicy::AlwaysMatch;
    1514           0 :       break;
    1515             :   }
    1516             : 
    1517             :   CertVerifier::OcspDownloadConfig odc;
    1518             :   CertVerifier::OcspStrictConfig osc;
    1519             :   CertVerifier::OcspGetConfig ogc;
    1520             :   uint32_t certShortLifetimeInDays;
    1521           1 :   TimeDuration softTimeout;
    1522           1 :   TimeDuration hardTimeout;
    1523             : 
    1524             :   GetRevocationBehaviorFromPrefs(&odc, &osc, &ogc, &certShortLifetimeInDays,
    1525           1 :                                  softTimeout, hardTimeout, lock);
    1526             :   mDefaultCertVerifier = new SharedCertVerifier(odc, osc, ogc, softTimeout,
    1527             :                                                 hardTimeout,
    1528             :                                                 certShortLifetimeInDays,
    1529             :                                                 pinningMode, sha1Mode,
    1530             :                                                 nameMatchingMode,
    1531             :                                                 netscapeStepUpPolicy,
    1532           2 :                                                 ctMode);
    1533           1 : }
    1534             : 
    1535             : // Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
    1536             : // TLS 1.2 (max) when the prefs aren't set or set to invalid values.
    1537             : nsresult
    1538           1 : nsNSSComponent::setEnabledTLSVersions()
    1539             : {
    1540             :   // keep these values in sync with security-prefs.js
    1541             :   // 1 means TLS 1.0, 2 means TLS 1.1, etc.
    1542             :   static const uint32_t PSM_DEFAULT_MIN_TLS_VERSION = 1;
    1543             :   static const uint32_t PSM_DEFAULT_MAX_TLS_VERSION = 4;
    1544             : 
    1545             :   uint32_t minFromPrefs = Preferences::GetUint("security.tls.version.min",
    1546           1 :                                                PSM_DEFAULT_MIN_TLS_VERSION);
    1547             :   uint32_t maxFromPrefs = Preferences::GetUint("security.tls.version.max",
    1548           1 :                                                PSM_DEFAULT_MAX_TLS_VERSION);
    1549             : 
    1550             :   SSLVersionRange defaults = {
    1551             :     SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MIN_TLS_VERSION,
    1552             :     SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MAX_TLS_VERSION
    1553           1 :   };
    1554             :   SSLVersionRange filledInRange;
    1555           1 :   FillTLSVersionRange(filledInRange, minFromPrefs, maxFromPrefs, defaults);
    1556             : 
    1557             :   SECStatus srv =
    1558           1 :     SSL_VersionRangeSetDefault(ssl_variant_stream, &filledInRange);
    1559           1 :   if (srv != SECSuccess) {
    1560           0 :     return NS_ERROR_FAILURE;
    1561             :   }
    1562             : 
    1563           1 :   return NS_OK;
    1564             : }
    1565             : 
    1566             : static nsresult
    1567           1 : GetNSSProfilePath(nsAutoCString& aProfilePath)
    1568             : {
    1569           1 :   aProfilePath.Truncate();
    1570           1 :   const char* dbDirOverride = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
    1571           1 :   if (dbDirOverride && strlen(dbDirOverride) > 0) {
    1572           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1573             :            ("Using specified MOZPSM_NSSDBDIR_OVERRIDE as NSS DB dir: %s\n",
    1574             :             dbDirOverride));
    1575           0 :     aProfilePath.Assign(dbDirOverride);
    1576           0 :     return NS_OK;
    1577             :   }
    1578             : 
    1579           2 :   nsCOMPtr<nsIFile> profileFile;
    1580           1 :   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
    1581           2 :                                        getter_AddRefs(profileFile));
    1582           1 :   if (NS_FAILED(rv)) {
    1583             :     NS_WARNING("NSS will be initialized without a profile directory. "
    1584           0 :                "Some things may not work as expected.");
    1585           0 :     return NS_OK;
    1586             :   }
    1587             : 
    1588             : #if defined(XP_WIN)
    1589             :   // Native path will drop Unicode characters that cannot be mapped to system's
    1590             :   // codepage, using short (canonical) path as workaround.
    1591             :   nsCOMPtr<nsILocalFileWin> profileFileWin(do_QueryInterface(profileFile));
    1592             :   if (!profileFileWin) {
    1593             :     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
    1594             :            ("Could not get nsILocalFileWin for profile directory.\n"));
    1595             :     return NS_ERROR_FAILURE;
    1596             :   }
    1597             :   rv = profileFileWin->GetNativeCanonicalPath(aProfilePath);
    1598             : #else
    1599           1 :   rv = profileFile->GetNativePath(aProfilePath);
    1600             : #endif
    1601           1 :   if (NS_FAILED(rv)) {
    1602           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
    1603             :            ("Could not get native path for profile directory.\n"));
    1604           0 :     return rv;
    1605             :   }
    1606             : 
    1607           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1608             :           ("NSS profile at '%s'\n", aProfilePath.get()));
    1609           1 :   return NS_OK;
    1610             : }
    1611             : 
    1612             : #ifndef ANDROID
    1613             : // Given a profile path, attempt to rename the PKCS#11 module DB to
    1614             : // "<original name>.fips". In the case of a catastrophic failure (e.g. out of
    1615             : // memory), returns a failing nsresult. If execution could conceivably proceed,
    1616             : // returns NS_OK even if renaming the file didn't work. This simplifies the
    1617             : // logic of the calling code.
    1618             : static nsresult
    1619           0 : AttemptToRenamePKCS11ModuleDB(const nsACString& profilePath)
    1620             : {
    1621             :   // profilePath may come from the environment variable
    1622             :   // MOZPSM_NSSDBDIR_OVERRIDE. If so, the user's NSS DBs are most likely not in
    1623             :   // their profile directory and we shouldn't mess with them.
    1624           0 :   const char* dbDirOverride = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
    1625           0 :   if (dbDirOverride && strlen(dbDirOverride) > 0) {
    1626           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1627             :             ("MOZPSM_NSSDBDIR_OVERRIDE set - not renaming PKCS#11 module DB"));
    1628           0 :     return NS_OK;
    1629             :   }
    1630           0 :   NS_NAMED_LITERAL_CSTRING(moduleDBFilename, "secmod.db");
    1631           0 :   NS_NAMED_LITERAL_CSTRING(destModuleDBFilename, "secmod.db.fips");
    1632           0 :   nsCOMPtr<nsIFile> dbFile = do_CreateInstance("@mozilla.org/file/local;1");
    1633           0 :   if (!dbFile) {
    1634           0 :     return NS_ERROR_FAILURE;
    1635             :   }
    1636           0 :   nsresult rv = dbFile->InitWithNativePath(profilePath);
    1637           0 :   if (NS_FAILED(rv)) {
    1638           0 :     return rv;
    1639             :   }
    1640           0 :   rv = dbFile->AppendNative(moduleDBFilename);
    1641           0 :   if (NS_FAILED(rv)) {
    1642           0 :     return rv;
    1643             :   }
    1644             :   // If the PKCS#11 module DB doesn't exist, renaming it won't help.
    1645             :   bool exists;
    1646           0 :   rv = dbFile->Exists(&exists);
    1647           0 :   if (NS_FAILED(rv)) {
    1648           0 :     return rv;
    1649             :   }
    1650             :   // This is strange, but not a catastrophic failure.
    1651           0 :   if (!exists) {
    1652           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1653             :             ("%s doesn't exist?", moduleDBFilename.get()));
    1654           0 :     return NS_OK;
    1655             :   }
    1656           0 :   nsCOMPtr<nsIFile> destDBFile = do_CreateInstance("@mozilla.org/file/local;1");
    1657           0 :   if (!destDBFile) {
    1658           0 :     return NS_ERROR_FAILURE;
    1659             :   }
    1660           0 :   rv = destDBFile->InitWithNativePath(profilePath);
    1661           0 :   if (NS_FAILED(rv)) {
    1662           0 :     return rv;
    1663             :   }
    1664           0 :   rv = destDBFile->AppendNative(destModuleDBFilename);
    1665           0 :   if (NS_FAILED(rv)) {
    1666           0 :     return rv;
    1667             :   }
    1668             :   // If the destination exists, presumably we've already tried this. Doing it
    1669             :   // again won't help.
    1670           0 :   rv = destDBFile->Exists(&exists);
    1671           0 :   if (NS_FAILED(rv)) {
    1672           0 :     return rv;
    1673             :   }
    1674             :   // Unfortunate, but not a catastrophic failure.
    1675           0 :   if (exists) {
    1676           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1677             :             ("%s already exists - not overwriting",
    1678             :              destModuleDBFilename.get()));
    1679           0 :     return NS_OK;
    1680             :   }
    1681             :   // Now do the actual move.
    1682           0 :   nsCOMPtr<nsIFile> profileDir = do_CreateInstance("@mozilla.org/file/local;1");
    1683           0 :   if (!profileDir) {
    1684           0 :     return NS_ERROR_FAILURE;
    1685             :   }
    1686           0 :   rv = profileDir->InitWithNativePath(profilePath);
    1687           0 :   if (NS_FAILED(rv)) {
    1688           0 :     return rv;
    1689             :   }
    1690             :   // This may fail on, e.g., a read-only file system. This would be unfortunate,
    1691             :   // but again it isn't catastropic and we would want to fall back to
    1692             :   // initializing NSS in no-DB mode.
    1693           0 :   Unused << dbFile->MoveToNative(profileDir, destModuleDBFilename);
    1694           0 :   return NS_OK;
    1695             : }
    1696             : #endif // ifndef ANDROID
    1697             : 
    1698             : // Given a profile directory, attempt to initialize NSS. If nocertdb is true,
    1699             : // (or if we don't have a profile directory) simply initialize NSS in no DB mode
    1700             : // and return. Otherwise, first attempt to initialize in read/write mode, and
    1701             : // then read-only mode if that fails. If both attempts fail, we may be failing
    1702             : // to initialize an NSS DB collection that has FIPS mode enabled. Attempt to
    1703             : // ascertain if this is the case, and if so, rename the offending PKCS#11 module
    1704             : // DB so we can (hopefully) initialize NSS in read-write mode. Again attempt
    1705             : // read-only mode if that fails. Finally, fall back to no DB mode. On Android
    1706             : // we can skip the FIPS workaround since it was never possible to enable FIPS
    1707             : // there anyway.
    1708             : static nsresult
    1709           1 : InitializeNSSWithFallbacks(const nsACString& profilePath, bool nocertdb,
    1710             :                            bool safeMode)
    1711             : {
    1712           1 :   if (nocertdb || profilePath.IsEmpty()) {
    1713           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    1714             :             ("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
    1715           0 :     SECStatus srv = NSS_NoDB_Init(nullptr);
    1716           0 :     return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
    1717             :   }
    1718             : 
    1719           1 :   const char* profilePathCStr = PromiseFlatCString(profilePath).get();
    1720             :   // Try read/write mode. If we're in safeMode, we won't load PKCS#11 modules.
    1721             : #ifndef ANDROID
    1722             :   PRErrorCode savedPRErrorCode1;
    1723             : #endif // ifndef ANDROID
    1724           1 :   SECStatus srv = ::mozilla::psm::InitializeNSS(profilePathCStr, false,
    1725           2 :                                                 !safeMode);
    1726           1 :   if (srv == SECSuccess) {
    1727           1 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode"));
    1728           1 :     return NS_OK;
    1729             :   }
    1730             : #ifndef ANDROID
    1731           0 :   savedPRErrorCode1 = PR_GetError();
    1732             :   PRErrorCode savedPRErrorCode2;
    1733             : #endif // ifndef ANDROID
    1734             :   // That failed. Try read-only mode.
    1735           0 :   srv = ::mozilla::psm::InitializeNSS(profilePathCStr, true, !safeMode);
    1736           0 :   if (srv == SECSuccess) {
    1737           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r-o mode"));
    1738           0 :     return NS_OK;
    1739             :   }
    1740             : #ifndef ANDROID
    1741           0 :   savedPRErrorCode2 = PR_GetError();
    1742             : #endif // ifndef ANDROID
    1743             : 
    1744             : #ifndef ANDROID
    1745             :   // That failed as well. Maybe we're trying to load a PKCS#11 module DB that is
    1746             :   // in FIPS mode, but we don't support FIPS? Test load NSS without PKCS#11
    1747             :   // modules. If that succeeds, that's probably what's going on.
    1748           0 :   if (!safeMode && (savedPRErrorCode1 == SEC_ERROR_LEGACY_DATABASE ||
    1749             :                     savedPRErrorCode2 == SEC_ERROR_LEGACY_DATABASE)) {
    1750           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("attempting no-module db init"));
    1751             :     // It would make sense to initialize NSS in read-only mode here since this
    1752             :     // is just a test to see if the PKCS#11 module DB being in FIPS mode is the
    1753             :     // problem, but for some reason the combination of read-only and no-moddb
    1754             :     // flags causes NSS initialization to fail, so unfortunately we have to use
    1755             :     // read-write mode.
    1756           0 :     srv = ::mozilla::psm::InitializeNSS(profilePathCStr, false, false);
    1757           0 :     if (srv == SECSuccess) {
    1758           0 :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FIPS may be the problem"));
    1759             :       // Unload NSS so we can attempt to fix this situation for the user.
    1760           0 :       srv = NSS_Shutdown();
    1761           0 :       if (srv != SECSuccess) {
    1762           0 :         return NS_ERROR_FAILURE;
    1763             :       }
    1764           0 :       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trying to rename module db"));
    1765             :       // If this fails non-catastrophically, we'll attempt to initialize NSS
    1766             :       // again in r/w then r-o mode (both of which will fail), and then we'll
    1767             :       // fall back to NSS_NoDB_Init, which is the behavior we want.
    1768           0 :       nsresult rv = AttemptToRenamePKCS11ModuleDB(profilePath);
    1769           0 :       if (NS_FAILED(rv)) {
    1770           0 :         return rv;
    1771             :       }
    1772           0 :       srv = ::mozilla::psm::InitializeNSS(profilePathCStr, false, true);
    1773           0 :       if (srv == SECSuccess) {
    1774           0 :         MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r/w mode"));
    1775           0 :         return NS_OK;
    1776             :       }
    1777           0 :       srv = ::mozilla::psm::InitializeNSS(profilePathCStr, true, true);
    1778           0 :       if (srv == SECSuccess) {
    1779           0 :         MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r-o mode"));
    1780           0 :         return NS_OK;
    1781             :       }
    1782             :     }
    1783             :   }
    1784             : #endif
    1785             : 
    1786           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("last-resort NSS_NoDB_Init"));
    1787           0 :   srv = NSS_NoDB_Init(nullptr);
    1788           0 :   return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
    1789             : }
    1790             : 
    1791             : nsresult
    1792           1 : nsNSSComponent::InitializeNSS()
    1793             : {
    1794           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::InitializeNSS\n"));
    1795             : 
    1796             :   static_assert(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
    1797             :                 nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
    1798             :                 nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
    1799             :                 nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
    1800             :                 "You must update the values in nsINSSErrorsService.idl");
    1801             : 
    1802           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization beginning\n"));
    1803             : 
    1804             :   // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
    1805             :   // but affects only static data.
    1806             :   // If we could assume i18n will not change between profiles, one call per application
    1807             :   // run were sufficient. As I can't predict what happens in the future, let's repeat
    1808             :   // this call for every re-init of NSS.
    1809             : 
    1810           1 :   ConfigureInternalPKCS11Token();
    1811             : 
    1812           2 :   nsAutoCString profileStr;
    1813           1 :   nsresult rv = GetNSSProfilePath(profileStr);
    1814           1 :   if (NS_FAILED(rv)) {
    1815           0 :     return NS_ERROR_NOT_AVAILABLE;
    1816             :   }
    1817             : 
    1818           1 :   bool nocertdb = Preferences::GetBool("security.nocertdb", false);
    1819           1 :   bool inSafeMode = true;
    1820           2 :   nsCOMPtr<nsIXULRuntime> runtime(do_GetService("@mozilla.org/xre/runtime;1"));
    1821             :   // There might not be an nsIXULRuntime in embedded situations. This will
    1822             :   // default to assuming we are in safe mode (as a result, no external PKCS11
    1823             :   // modules will be loaded).
    1824           1 :   if (runtime) {
    1825           1 :     rv = runtime->GetInSafeMode(&inSafeMode);
    1826           1 :     if (NS_FAILED(rv)) {
    1827           0 :       return rv;
    1828             :     }
    1829             :   }
    1830           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("inSafeMode: %u\n", inSafeMode));
    1831             : 
    1832           1 :   rv = InitializeNSSWithFallbacks(profileStr, nocertdb, inSafeMode);
    1833           1 :   if (NS_FAILED(rv)) {
    1834           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to initialize NSS"));
    1835           0 :     return rv;
    1836             :   }
    1837             : 
    1838           1 :   PK11_SetPasswordFunc(PK11PasswordPrompt);
    1839             : 
    1840           1 :   SharedSSLState::GlobalInit();
    1841             : 
    1842             :   // Register an observer so we can inform NSS when these prefs change
    1843           1 :   Preferences::AddStrongObserver(this, "security.");
    1844             : 
    1845           1 :   SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
    1846           1 :   SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
    1847             : 
    1848           1 :   rv = setEnabledTLSVersions();
    1849           1 :   if (NS_FAILED(rv)) {
    1850           0 :     return NS_ERROR_UNEXPECTED;
    1851             :   }
    1852             : 
    1853           1 :   DisableMD5();
    1854           1 :   LoadLoadableRoots();
    1855             : 
    1856           1 :   rv = LoadExtendedValidationInfo();
    1857           1 :   if (NS_FAILED(rv)) {
    1858           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
    1859           0 :     return rv;
    1860             :   }
    1861             : 
    1862           1 :   MaybeEnableFamilySafetyCompatibility();
    1863           1 :   MaybeImportEnterpriseRoots();
    1864             : 
    1865           1 :   ConfigureTLSSessionIdentifiers();
    1866             : 
    1867             :   bool requireSafeNegotiation =
    1868             :     Preferences::GetBool("security.ssl.require_safe_negotiation",
    1869           1 :                          REQUIRE_SAFE_NEGOTIATION_DEFAULT);
    1870           1 :   SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
    1871             : 
    1872           1 :   SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_REQUIRES_XTN);
    1873             : 
    1874           1 :   SSL_OptionSetDefault(SSL_ENABLE_EXTENDED_MASTER_SECRET, true);
    1875             : 
    1876           1 :   SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
    1877           1 :                        Preferences::GetBool("security.ssl.enable_false_start",
    1878           1 :                                             FALSE_START_ENABLED_DEFAULT));
    1879             : 
    1880             :   // SSL_ENABLE_ALPN also requires calling SSL_SetNextProtoNego in order for
    1881             :   // the extensions to be negotiated.
    1882             :   // WebRTC does not do that so it will not use ALPN even when this preference
    1883             :   // is true.
    1884           1 :   SSL_OptionSetDefault(SSL_ENABLE_ALPN,
    1885           1 :                        Preferences::GetBool("security.ssl.enable_alpn",
    1886           1 :                                             ALPN_ENABLED_DEFAULT));
    1887             : 
    1888           1 :   SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
    1889           1 :                        Preferences::GetBool("security.tls.enable_0rtt_data",
    1890           1 :                                             ENABLED_0RTT_DATA_DEFAULT));
    1891             : 
    1892           1 :   if (NS_FAILED(InitializeCipherSuite())) {
    1893           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("Unable to initialize cipher suite settings\n"));
    1894           0 :     return NS_ERROR_FAILURE;
    1895             :   }
    1896             : 
    1897             :   // TLSServerSocket may be run with the session cache enabled. It is necessary
    1898             :   // to call this once before that can happen. This specifies a maximum of 1000
    1899             :   // cache entries (the default number of cache entries is 10000, which seems a
    1900             :   // little excessive as there probably won't be that many clients connecting to
    1901             :   // any TLSServerSockets the browser runs.)
    1902             :   // Note that this must occur before any calls to SSL_ClearSessionCache
    1903             :   // (otherwise memory will leak).
    1904           1 :   if (SSL_ConfigServerSessionIDCache(1000, 0, 0, nullptr) != SECSuccess) {
    1905           0 :     return NS_ERROR_FAILURE;
    1906             :   }
    1907             : 
    1908             :   // dynamic options from prefs
    1909           1 :   setValidationOptions(true);
    1910             : 
    1911             : #ifndef MOZ_NO_SMART_CARDS
    1912           1 :   rv = LaunchSmartCardThreads();
    1913           1 :   if (NS_FAILED(rv)) {
    1914           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
    1915             :             ("failed to start smart card threads"));
    1916           0 :     return rv;
    1917             :   }
    1918             : #endif
    1919             : 
    1920           1 :   mozilla::pkix::RegisterErrorTable();
    1921             : 
    1922           1 :   if (PK11_IsFIPS()) {
    1923           0 :     Telemetry::Accumulate(Telemetry::FIPS_ENABLED, true);
    1924             :   }
    1925             : 
    1926             :   { // Introduce scope for the AutoSECMODListReadLock.
    1927           2 :     AutoSECMODListReadLock lock;
    1928           3 :     for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
    1929           2 :          list = list->next) {
    1930           4 :       nsAutoString scalarKey;
    1931           2 :       GetModuleNameForTelemetry(list->module, scalarKey);
    1932             :       // Scalar keys must be between 0 and 70 characters (exclusive).
    1933             :       // GetModuleNameForTelemetry takes care of keys that are too long. If for
    1934             :       // some reason it couldn't come up with an appropriate name and returned
    1935             :       // an empty result, however, we need to not attempt to record this (it
    1936             :       // wouldn't give us anything useful anyway).
    1937           2 :       if (scalarKey.Length() > 0) {
    1938             :         Telemetry::ScalarSet(
    1939           2 :           Telemetry::ScalarID::SECURITY_PKCS11_MODULES_LOADED, scalarKey, true);
    1940             :       }
    1941             :     }
    1942             :   }
    1943             : 
    1944           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization done\n"));
    1945             : 
    1946             :   {
    1947           2 :     MutexAutoLock lock(mMutex);
    1948             : 
    1949             :     // ensure we have initial values for various root hashes
    1950             : #ifdef DEBUG
    1951             :     mTestBuiltInRootHash =
    1952           1 :       Preferences::GetString("security.test.built_in_root_hash");
    1953             : #endif
    1954             :     mContentSigningRootHash =
    1955           1 :       Preferences::GetString("security.content.signature.root_hash");
    1956             : 
    1957           1 :     mNSSInitialized = true;
    1958             :   }
    1959             : 
    1960           1 :   return NS_OK;
    1961             : }
    1962             : 
    1963             : void
    1964           0 : nsNSSComponent::ShutdownNSS()
    1965             : {
    1966           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ShutdownNSS\n"));
    1967           0 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
    1968             : 
    1969             :   // This is idempotent and can happen as a result of observing
    1970             :   // profile-before-change and being called from nsNSSComponent's destructor.
    1971             :   // We need to do this before other cleanup because we must avoid acquiring
    1972             :   // mMutex and then preventing threads holding nsNSSShutDownPreventionLocks
    1973             :   // from continuing (which is what evaporateAllNSSResourcesAndShutDown does).
    1974           0 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("evaporating psm resources"));
    1975           0 :   if (NS_FAILED(nsNSSShutDownList::evaporateAllNSSResourcesAndShutDown())) {
    1976           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to evaporate resources"));
    1977           0 :     return;
    1978             :   }
    1979             : 
    1980             :   // This currently calls GetPIPNSSBundleString, which acquires mMutex, so we
    1981             :   // can't call it while already holding mMutex. This is fine as mMutex doesn't
    1982             :   // actually protect anything that UnloadLoadableRoots is modifying. Also,
    1983             :   // UnloadLoadableRoots is idempotent.
    1984           0 :   UnloadLoadableRoots();
    1985             : 
    1986           0 :   MutexAutoLock lock(mMutex);
    1987             : 
    1988             :   // Other shutdown tasks are not guaranteed to be idempotent and we should
    1989             :   // avoid performing them more than once.
    1990           0 :   if (!mNSSInitialized) {
    1991           0 :     return;
    1992             :   }
    1993           0 :   mNSSInitialized = false;
    1994             : 
    1995             : #ifdef XP_WIN
    1996             :   mFamilySafetyRoot = nullptr;
    1997             :   mEnterpriseRoots = nullptr;
    1998             : #endif
    1999             : 
    2000           0 :   PK11_SetPasswordFunc((PK11PasswordFunc)nullptr);
    2001             : 
    2002           0 :   Preferences::RemoveObserver(this, "security.");
    2003             : 
    2004             : #ifndef MOZ_NO_SMART_CARDS
    2005           0 :   ShutdownSmartCardThreads();
    2006             : #endif
    2007           0 :   SSL_ClearSessionCache();
    2008             :   // TLSServerSocket may be run with the session cache enabled. This ensures
    2009             :   // those resources are cleaned up.
    2010           0 :   Unused << SSL_ShutdownServerSessionIDCache();
    2011             : 
    2012             :   // Release the default CertVerifier. This will cause any held NSS resources
    2013             :   // to be released (it's not an nsNSSShutDownObject, so we have to do this
    2014             :   // manually).
    2015           0 :   mDefaultCertVerifier = nullptr;
    2016             : 
    2017           0 :   if (NSS_Shutdown() != SECSuccess) {
    2018           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("NSS SHUTDOWN FAILURE"));
    2019             :   } else {
    2020           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS shutdown =====>> OK <<====="));
    2021             :   }
    2022             : }
    2023             : 
    2024             : nsresult
    2025           1 : nsNSSComponent::Init()
    2026             : {
    2027           1 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
    2028           1 :   if (!NS_IsMainThread()) {
    2029           0 :     return NS_ERROR_NOT_SAME_THREAD;
    2030             :   }
    2031             : 
    2032           1 :   MOZ_ASSERT(XRE_IsParentProcess());
    2033           1 :   if (!XRE_IsParentProcess()) {
    2034           0 :     return NS_ERROR_NOT_AVAILABLE;
    2035             :   }
    2036             : 
    2037           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Beginning NSS initialization\n"));
    2038             : 
    2039           1 :   nsresult rv = InitializePIPNSSBundle();
    2040           1 :   if (NS_FAILED(rv)) {
    2041           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("Unable to create pipnss bundle.\n"));
    2042           0 :     return rv;
    2043             :   }
    2044             : 
    2045           1 :   rv = InitializeNSS();
    2046           1 :   if (NS_FAILED(rv)) {
    2047           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
    2048             :             ("nsNSSComponent::InitializeNSS() failed\n"));
    2049           0 :     return rv;
    2050             :   }
    2051             : 
    2052           1 :   RememberCertErrorsTable::Init();
    2053             : 
    2054           1 :   return RegisterObservers();
    2055             : }
    2056             : 
    2057             : // nsISupports Implementation for the class
    2058          60 : NS_IMPL_ISUPPORTS(nsNSSComponent,
    2059             :                   nsINSSComponent,
    2060             :                   nsIObserver)
    2061             : 
    2062             : static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
    2063             : 
    2064             : NS_IMETHODIMP
    2065           0 : nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
    2066             :                         const char16_t* someData)
    2067             : {
    2068           0 :   if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
    2069           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("receiving profile change topic\n"));
    2070           0 :     ShutdownNSS();
    2071           0 :   } else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
    2072           0 :     nsNSSShutDownPreventionLock locker;
    2073           0 :     bool clearSessionCache = true;
    2074           0 :     NS_ConvertUTF16toUTF8  prefName(someData);
    2075             : 
    2076           0 :     if (prefName.EqualsLiteral("security.tls.version.min") ||
    2077           0 :         prefName.EqualsLiteral("security.tls.version.max")) {
    2078           0 :       (void) setEnabledTLSVersions();
    2079           0 :     } else if (prefName.EqualsLiteral("security.ssl.require_safe_negotiation")) {
    2080             :       bool requireSafeNegotiation =
    2081             :         Preferences::GetBool("security.ssl.require_safe_negotiation",
    2082           0 :                              REQUIRE_SAFE_NEGOTIATION_DEFAULT);
    2083           0 :       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
    2084           0 :     } else if (prefName.EqualsLiteral("security.ssl.enable_false_start")) {
    2085           0 :       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
    2086           0 :                            Preferences::GetBool("security.ssl.enable_false_start",
    2087           0 :                                                 FALSE_START_ENABLED_DEFAULT));
    2088           0 :     } else if (prefName.EqualsLiteral("security.ssl.enable_alpn")) {
    2089           0 :       SSL_OptionSetDefault(SSL_ENABLE_ALPN,
    2090           0 :                            Preferences::GetBool("security.ssl.enable_alpn",
    2091           0 :                                                 ALPN_ENABLED_DEFAULT));
    2092           0 :     } else if (prefName.EqualsLiteral("security.tls.enable_0rtt_data")) {
    2093           0 :       SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
    2094           0 :                            Preferences::GetBool("security.tls.enable_0rtt_data",
    2095           0 :                                                 ENABLED_0RTT_DATA_DEFAULT));
    2096           0 :     } else if (prefName.Equals("security.ssl.disable_session_identifiers")) {
    2097           0 :       ConfigureTLSSessionIdentifiers();
    2098           0 :     } else if (prefName.EqualsLiteral("security.OCSP.enabled") ||
    2099           0 :                prefName.EqualsLiteral("security.OCSP.require") ||
    2100           0 :                prefName.EqualsLiteral("security.OCSP.GET.enabled") ||
    2101           0 :                prefName.EqualsLiteral("security.pki.cert_short_lifetime_in_days") ||
    2102           0 :                prefName.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
    2103           0 :                prefName.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
    2104           0 :                prefName.EqualsLiteral("security.pki.certificate_transparency.mode") ||
    2105           0 :                prefName.EqualsLiteral("security.cert_pinning.enforcement_level") ||
    2106           0 :                prefName.EqualsLiteral("security.pki.sha1_enforcement_level") ||
    2107           0 :                prefName.EqualsLiteral("security.pki.name_matching_mode") ||
    2108           0 :                prefName.EqualsLiteral("security.pki.netscape_step_up_policy") ||
    2109           0 :                prefName.EqualsLiteral("security.OCSP.timeoutMilliseconds.soft") ||
    2110           0 :                prefName.EqualsLiteral("security.OCSP.timeoutMilliseconds.hard")) {
    2111           0 :       setValidationOptions(false);
    2112             : #ifdef DEBUG
    2113           0 :     } else if (prefName.EqualsLiteral("security.test.built_in_root_hash")) {
    2114           0 :       MutexAutoLock lock(mMutex);
    2115           0 :       mTestBuiltInRootHash = Preferences::GetString("security.test.built_in_root_hash");
    2116             : #endif // DEBUG
    2117           0 :     } else if (prefName.Equals(kFamilySafetyModePref)) {
    2118           0 :       MaybeEnableFamilySafetyCompatibility();
    2119           0 :     } else if (prefName.EqualsLiteral("security.content.signature.root_hash")) {
    2120           0 :       MutexAutoLock lock(mMutex);
    2121             :       mContentSigningRootHash =
    2122           0 :         Preferences::GetString("security.content.signature.root_hash");
    2123           0 :     } else if (prefName.Equals(kEnterpriseRootModePref)) {
    2124           0 :       MaybeImportEnterpriseRoots();
    2125             :     } else {
    2126           0 :       clearSessionCache = false;
    2127             :     }
    2128           0 :     if (clearSessionCache)
    2129           0 :       SSL_ClearSessionCache();
    2130             :   }
    2131             : 
    2132           0 :   return NS_OK;
    2133             : }
    2134             : 
    2135             : /*static*/ nsresult
    2136           0 : nsNSSComponent::GetNewPrompter(nsIPrompt** result)
    2137             : {
    2138           0 :   NS_ENSURE_ARG_POINTER(result);
    2139           0 :   *result = nullptr;
    2140             : 
    2141           0 :   if (!NS_IsMainThread()) {
    2142           0 :     NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
    2143           0 :     return NS_ERROR_NOT_SAME_THREAD;
    2144             :   }
    2145             : 
    2146             :   nsresult rv;
    2147           0 :   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
    2148           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2149             : 
    2150           0 :   rv = wwatch->GetNewPrompter(0, result);
    2151           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2152             : 
    2153           0 :   return rv;
    2154             : }
    2155             : 
    2156           0 : nsresult nsNSSComponent::LogoutAuthenticatedPK11()
    2157             : {
    2158             :   nsCOMPtr<nsICertOverrideService> icos =
    2159           0 :     do_GetService("@mozilla.org/security/certoverride;1");
    2160           0 :   if (icos) {
    2161           0 :     icos->ClearValidityOverride(
    2162           0 :             NS_LITERAL_CSTRING("all:temporary-certificates"),
    2163           0 :             0);
    2164             :   }
    2165             : 
    2166           0 :   nsClientAuthRememberService::ClearAllRememberedDecisions();
    2167             : 
    2168           0 :   return nsNSSShutDownList::doPK11Logout();
    2169             : }
    2170             : 
    2171             : nsresult
    2172           1 : nsNSSComponent::RegisterObservers()
    2173             : {
    2174             :   nsCOMPtr<nsIObserverService> observerService(
    2175           2 :     do_GetService("@mozilla.org/observer-service;1"));
    2176           1 :   if (!observerService) {
    2177           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
    2178             :             ("nsNSSComponent: couldn't get observer service\n"));
    2179           0 :     return NS_ERROR_FAILURE;
    2180             :   }
    2181             : 
    2182           1 :   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent: adding observers\n"));
    2183             :   // Using false for the ownsweak parameter means the observer service will
    2184             :   // keep a strong reference to this component. As a result, this will live at
    2185             :   // least as long as the observer service.
    2186           1 :   observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
    2187             : 
    2188           1 :   return NS_OK;
    2189             : }
    2190             : 
    2191             : #ifdef DEBUG
    2192             : NS_IMETHODIMP
    2193           0 : nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool& result)
    2194             : {
    2195           0 :   result = false;
    2196             : 
    2197             :   // Create the nsNSSCertificate and get its hash before acquiring mMutex (we
    2198             :   // must avoid acquiring mMutex and then creating an
    2199             :   // nsNSSShutDownPreventionLock).
    2200           0 :   RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
    2201           0 :   if (!nsc) {
    2202           0 :     return NS_ERROR_FAILURE;
    2203             :   }
    2204           0 :   nsAutoString certHash;
    2205           0 :   nsresult rv = nsc->GetSha256Fingerprint(certHash);
    2206           0 :   if (NS_FAILED(rv)) {
    2207           0 :     return rv;
    2208             :   }
    2209             : 
    2210           0 :   MutexAutoLock lock(mMutex);
    2211           0 :   MOZ_ASSERT(mNSSInitialized);
    2212           0 :   if (mTestBuiltInRootHash.IsEmpty()) {
    2213           0 :     return NS_OK;
    2214             :   }
    2215             : 
    2216           0 :   result = mTestBuiltInRootHash.Equals(certHash);
    2217           0 :   return NS_OK;
    2218             : }
    2219             : #endif // DEBUG
    2220             : 
    2221             : NS_IMETHODIMP
    2222           0 : nsNSSComponent::IsCertContentSigningRoot(CERTCertificate* cert, bool& result)
    2223             : {
    2224           0 :   result = false;
    2225             : 
    2226             :   // Create the nsNSSCertificate and get its hash before acquiring mMutex (we
    2227             :   // must avoid acquiring mMutex and then creating an
    2228             :   // nsNSSShutDownPreventionLock).
    2229           0 :   RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
    2230           0 :   if (!nsc) {
    2231           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("creating nsNSSCertificate failed"));
    2232           0 :     return NS_ERROR_FAILURE;
    2233             :   }
    2234           0 :   nsAutoString certHash;
    2235           0 :   nsresult rv = nsc->GetSha256Fingerprint(certHash);
    2236           0 :   if (NS_FAILED(rv)) {
    2237           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("getting cert fingerprint failed"));
    2238           0 :     return rv;
    2239             :   }
    2240             : 
    2241           0 :   MutexAutoLock lock(mMutex);
    2242           0 :   MOZ_ASSERT(mNSSInitialized);
    2243             : 
    2244           0 :   if (mContentSigningRootHash.IsEmpty()) {
    2245           0 :     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("mContentSigningRootHash is empty"));
    2246           0 :     return NS_ERROR_FAILURE;
    2247             :   }
    2248             : 
    2249           0 :   result = mContentSigningRootHash.Equals(certHash);
    2250           0 :   return NS_OK;
    2251             : }
    2252             : 
    2253           0 : SharedCertVerifier::~SharedCertVerifier() { }
    2254             : 
    2255             : already_AddRefed<SharedCertVerifier>
    2256           0 : nsNSSComponent::GetDefaultCertVerifier()
    2257             : {
    2258           0 :   MutexAutoLock lock(mMutex);
    2259           0 :   MOZ_ASSERT(mNSSInitialized);
    2260           0 :   RefPtr<SharedCertVerifier> certVerifier(mDefaultCertVerifier);
    2261           0 :   return certVerifier.forget();
    2262             : }
    2263             : 
    2264             : namespace mozilla { namespace psm {
    2265             : 
    2266             : already_AddRefed<SharedCertVerifier>
    2267           0 : GetDefaultCertVerifier()
    2268             : {
    2269             :   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
    2270             : 
    2271           0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
    2272           0 :   if (nssComponent) {
    2273           0 :     return nssComponent->GetDefaultCertVerifier();
    2274             :   }
    2275             : 
    2276           0 :   return nullptr;
    2277             : }
    2278             : 
    2279             : } } // namespace mozilla::psm
    2280             : 
    2281           4 : NS_IMPL_ISUPPORTS(PipUIContext, nsIInterfaceRequestor)
    2282             : 
    2283           1 : PipUIContext::PipUIContext()
    2284             : {
    2285           1 : }
    2286             : 
    2287           0 : PipUIContext::~PipUIContext()
    2288             : {
    2289           0 : }
    2290             : 
    2291             : NS_IMETHODIMP
    2292           0 : PipUIContext::GetInterface(const nsIID& uuid, void** result)
    2293             : {
    2294           0 :   NS_ENSURE_ARG_POINTER(result);
    2295           0 :   *result = nullptr;
    2296             : 
    2297           0 :   if (!NS_IsMainThread()) {
    2298           0 :     NS_ERROR("PipUIContext::GetInterface called off the main thread");
    2299           0 :     return NS_ERROR_NOT_SAME_THREAD;
    2300             :   }
    2301             : 
    2302           0 :   if (!uuid.Equals(NS_GET_IID(nsIPrompt)))
    2303           0 :     return NS_ERROR_NO_INTERFACE;
    2304             : 
    2305           0 :   nsIPrompt* prompt = nullptr;
    2306           0 :   nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
    2307           0 :   *result = prompt;
    2308           0 :   return rv;
    2309             : }
    2310             : 
    2311             : nsresult
    2312           0 : getNSSDialogs(void** _result, REFNSIID aIID, const char* contract)
    2313             : {
    2314           0 :   if (!NS_IsMainThread()) {
    2315           0 :     NS_ERROR("getNSSDialogs called off the main thread");
    2316           0 :     return NS_ERROR_NOT_SAME_THREAD;
    2317             :   }
    2318             : 
    2319             :   nsresult rv;
    2320             : 
    2321           0 :   nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
    2322           0 :   if (NS_FAILED(rv)) {
    2323           0 :     return rv;
    2324             :   }
    2325             : 
    2326           0 :   rv = svc->QueryInterface(aIID, _result);
    2327             : 
    2328           0 :   return rv;
    2329             : }
    2330             : 
    2331             : nsresult
    2332           0 : setPassword(PK11SlotInfo* slot, nsIInterfaceRequestor* ctx,
    2333             :             nsNSSShutDownPreventionLock& /*proofOfLock*/)
    2334             : {
    2335           0 :   MOZ_ASSERT(slot);
    2336           0 :   MOZ_ASSERT(ctx);
    2337           0 :   NS_ENSURE_ARG_POINTER(slot);
    2338           0 :   NS_ENSURE_ARG_POINTER(ctx);
    2339             : 
    2340           0 :   if (PK11_NeedUserInit(slot)) {
    2341           0 :     nsCOMPtr<nsITokenPasswordDialogs> dialogs;
    2342           0 :     nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
    2343             :                                 NS_GET_IID(nsITokenPasswordDialogs),
    2344           0 :                                 NS_TOKENPASSWORDSDIALOG_CONTRACTID);
    2345           0 :     if (NS_FAILED(rv)) {
    2346           0 :       return rv;
    2347             :     }
    2348             : 
    2349             :     bool canceled;
    2350           0 :     NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot));
    2351           0 :     rv = dialogs->SetPassword(ctx, tokenName, &canceled);
    2352           0 :     if (NS_FAILED(rv)) {
    2353           0 :       return rv;
    2354             :     }
    2355             : 
    2356           0 :     if (canceled) {
    2357           0 :       return NS_ERROR_NOT_AVAILABLE;
    2358             :     }
    2359             :   }
    2360             : 
    2361           0 :   return NS_OK;
    2362             : }
    2363             : 
    2364             : namespace mozilla {
    2365             : namespace psm {
    2366             : 
    2367             : nsresult
    2368           2 : InitializeCipherSuite()
    2369             : {
    2370           2 :   MOZ_ASSERT(NS_IsMainThread(),
    2371             :              "InitializeCipherSuite() can only be accessed on the main thread");
    2372             : 
    2373           2 :   if (NSS_SetDomesticPolicy() != SECSuccess) {
    2374           0 :     return NS_ERROR_FAILURE;
    2375             :   }
    2376             : 
    2377             :   // Disable any ciphers that NSS might have enabled by default
    2378         144 :   for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
    2379         142 :     uint16_t cipher_id = SSL_ImplementedCiphers[i];
    2380         142 :     SSL_CipherPrefSetDefault(cipher_id, false);
    2381             :   }
    2382             : 
    2383             :   // Now only set SSL/TLS ciphers we knew about at compile time
    2384           2 :   const CipherPref* const cp = sCipherPrefs;
    2385          38 :   for (size_t i = 0; cp[i].pref; ++i) {
    2386          36 :     bool cipherEnabled = Preferences::GetBool(cp[i].pref,
    2387          72 :                                               cp[i].enabledByDefault);
    2388          36 :     SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
    2389             :   }
    2390             : 
    2391             :   // Enable ciphers for PKCS#12
    2392           2 :   SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
    2393           2 :   SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
    2394           2 :   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
    2395           2 :   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
    2396           2 :   SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
    2397           2 :   SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
    2398           2 :   SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
    2399           2 :   PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
    2400             : 
    2401             :   // PSM enforces a minimum RSA key size of 1024 bits, which is overridable.
    2402             :   // NSS has its own minimum, which is not overridable (the default is 1023
    2403             :   // bits). This sets the NSS minimum to 512 bits so users can still connect to
    2404             :   // devices like wifi routers with woefully small keys (they would have to add
    2405             :   // an override to do so, but they already do for such devices).
    2406           2 :   NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 512);
    2407             : 
    2408             :   // Observe preference change around cipher suite setting.
    2409           2 :   return CipherSuiteChangeObserver::StartObserve();
    2410             : }
    2411             : 
    2412             : } // namespace psm
    2413             : } // namespace mozilla

Generated by: LCOV version 1.13