security/manager/ssl/src/nsNSSComponent.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #ifdef MOZ_LOGGING
     8 #define FORCE_PR_LOG 1
     9 #endif
    11 #include "nsNSSComponent.h"
    13 #include "ExtendedValidation.h"
    14 #include "NSSCertDBTrustDomain.h"
    15 #include "mozilla/Telemetry.h"
    16 #include "nsCertVerificationThread.h"
    17 #include "nsAppDirectoryServiceDefs.h"
    18 #include "nsComponentManagerUtils.h"
    19 #include "nsDirectoryServiceDefs.h"
    20 #include "nsICertOverrideService.h"
    21 #include "mozilla/Preferences.h"
    22 #include "nsThreadUtils.h"
    23 #include "mozilla/PublicSSL.h"
    24 #include "mozilla/StaticPtr.h"
    26 #ifndef MOZ_DISABLE_CRYPTOLEGACY
    27 #include "nsIDOMNode.h"
    28 #include "nsIDOMEvent.h"
    29 #include "nsIDOMDocument.h"
    30 #include "nsIDOMWindow.h"
    31 #include "nsIDOMWindowCollection.h"
    32 #include "nsIDocument.h"
    33 #include "nsIDOMSmartCardEvent.h"
    34 #include "nsSmartCardMonitor.h"
    35 #include "nsIDOMCryptoLegacy.h"
    36 #include "nsIPrincipal.h"
    37 #else
    38 #include "nsIDOMCrypto.h"
    39 #endif
    41 #include "nsCRT.h"
    42 #include "nsNTLMAuthModule.h"
    43 #include "nsIFile.h"
    44 #include "nsIProperties.h"
    45 #include "nsIWindowWatcher.h"
    46 #include "nsIPrompt.h"
    47 #include "nsCertificatePrincipal.h"
    48 #include "nsIBufEntropyCollector.h"
    49 #include "nsITokenPasswordDialogs.h"
    50 #include "nsServiceManagerUtils.h"
    51 #include "nsNSSShutDown.h"
    52 #include "GeneratedEvents.h"
    53 #include "SharedSSLState.h"
    55 #include "nss.h"
    56 #include "ssl.h"
    57 #include "sslproto.h"
    58 #include "secmod.h"
    59 #include "secmime.h"
    60 #include "ocsp.h"
    61 #include "secerr.h"
    62 #include "sslerr.h"
    64 #include "nsXULAppAPI.h"
    66 #ifdef XP_WIN
    67 #include "nsILocalFileWin.h"
    68 #endif
    70 #include "p12plcy.h"
    72 using namespace mozilla;
    73 using namespace mozilla::dom;
    74 using namespace mozilla::psm;
    76 #ifdef PR_LOGGING
    77 PRLogModuleInfo* gPIPNSSLog = nullptr;
    78 #endif
    80 int nsNSSComponent::mInstanceCount = 0;
    82 // XXX tmp callback for slot password
    83 extern char* pk11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg);
    85 #ifndef MOZ_DISABLE_CRYPTOLEGACY
    86 //This class is used to run the callback code
    87 //passed to the event handlers for smart card notification
    88 class nsTokenEventRunnable : public nsIRunnable {
    89 public:
    90   nsTokenEventRunnable(const nsAString& aType, const nsAString& aTokenName);
    91   virtual ~nsTokenEventRunnable();
    93   NS_IMETHOD Run ();
    94   NS_DECL_THREADSAFE_ISUPPORTS
    95 private:
    96   nsString mType;
    97   nsString mTokenName;
    98 };
   100 // ISuuports implementation for nsTokenEventRunnable
   101 NS_IMPL_ISUPPORTS(nsTokenEventRunnable, nsIRunnable)
   103 nsTokenEventRunnable::nsTokenEventRunnable(const nsAString& aType,
   104                                            const nsAString& aTokenName)
   105   : mType(aType)
   106   , mTokenName(aTokenName)
   107 {
   108 }
   110 nsTokenEventRunnable::~nsTokenEventRunnable() { }
   112 //Implementation that runs the callback passed to
   113 //crypto.generateCRMFRequest as an event.
   114 NS_IMETHODIMP
   115 nsTokenEventRunnable::Run()
   116 {
   117   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
   119   nsresult rv;
   120   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   121   if (NS_FAILED(rv))
   122     return rv;
   124   return nssComponent->DispatchEvent(mType, mTokenName);
   125 }
   126 #endif // MOZ_DISABLE_CRYPTOLEGACY
   128 bool nsPSMInitPanic::isPanic = false;
   130 // We must ensure that the nsNSSComponent has been loaded before
   131 // creating any other components.
   132 bool EnsureNSSInitialized(EnsureNSSOperator op)
   133 {
   134   if (nsPSMInitPanic::GetPanic())
   135     return false;
   137   if (GeckoProcessType_Default != XRE_GetProcessType())
   138   {
   139     if (op == nssEnsureOnChromeOnly)
   140     {
   141       // If the component needs PSM/NSS initialized only on the chrome process,
   142       // pretend we successfully initiated it but in reality we bypass it.
   143       // It's up to the programmer to check for process type in such components
   144       // and take care not to call anything that needs NSS/PSM initiated.
   145       return true;
   146     }
   148     NS_ERROR("Trying to initialize PSM/NSS in a non-chrome process!");
   149     return false;
   150   }
   152   static bool loading = false;
   153   static int32_t haveLoaded = 0;
   155   switch (op)
   156   {
   157     // In following 4 cases we are protected by monitor of XPCOM component
   158     // manager - we are inside of do_GetService call for nss component, so it is
   159     // safe to move with the flags here.
   160   case nssLoadingComponent:
   161     if (loading)
   162       return false; // We are reentered during nss component creation
   163     loading = true;
   164     return true;
   166   case nssInitSucceeded:
   167     NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
   168     loading = false;
   169     PR_AtomicSet(&haveLoaded, 1);
   170     return true;
   172   case nssInitFailed:
   173     NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
   174     loading = false;
   175     // no break
   177   case nssShutdown:
   178     PR_AtomicSet(&haveLoaded, 0);
   179     return false;
   181     // In this case we are called from a component to ensure nss initilization.
   182     // If the component has not yet been loaded and is not currently loading
   183     // call do_GetService for nss component to ensure it.
   184   case nssEnsure:
   185   case nssEnsureOnChromeOnly:
   186     // We are reentered during nss component creation or nss component is already up
   187     if (PR_AtomicAdd(&haveLoaded, 0) || loading)
   188       return true;
   190     {
   191     nsCOMPtr<nsINSSComponent> nssComponent
   192       = do_GetService(PSM_COMPONENT_CONTRACTID);
   194     // Nss component failed to initialize, inform the caller of that fact.
   195     // Flags are appropriately set by component constructor itself.
   196     if (!nssComponent)
   197       return false;
   199     bool isInitialized;
   200     nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
   201     return NS_SUCCEEDED(rv) && isInitialized;
   202     }
   204   default:
   205     NS_ASSERTION(false, "Bad operator to EnsureNSSInitialized");
   206     return false;
   207   }
   208 }
   210 static void
   211 SetClassicOCSPBehaviorFromPrefs(/*out*/ CertVerifier::ocsp_download_config* odc,
   212                                 /*out*/ CertVerifier::ocsp_strict_config* osc,
   213                                 /*out*/ CertVerifier::ocsp_get_config* ogc,
   214                                 const MutexAutoLock& /*proofOfLock*/)
   215 {
   216   MOZ_ASSERT(NS_IsMainThread());
   217   MOZ_ASSERT(odc);
   218   MOZ_ASSERT(osc);
   219   MOZ_ASSERT(ogc);
   221   // 0 = disabled, otherwise enabled
   222   *odc = Preferences::GetInt("security.OCSP.enabled", 1)
   223        ? CertVerifier::ocsp_on
   224        : CertVerifier::ocsp_off;
   226   *osc = Preferences::GetBool("security.OCSP.require", false)
   227        ? CertVerifier::ocsp_strict
   228        : CertVerifier::ocsp_relaxed;
   230   // XXX: Always use POST for OCSP; see bug 871954 for undoing this.
   231   *ogc = Preferences::GetBool("security.OCSP.GET.enabled", false)
   232        ? CertVerifier::ocsp_get_enabled
   233        : CertVerifier::ocsp_get_disabled;
   235   SetClassicOCSPBehavior(*odc, *osc, *ogc);
   237   SSL_ClearSessionCache();
   238 }
   240 nsNSSComponent::nsNSSComponent()
   241   :mutex("nsNSSComponent.mutex"),
   242    mNSSInitialized(false),
   243 #ifndef MOZ_DISABLE_CRYPTOLEGACY
   244    mThreadList(nullptr),
   245 #endif
   246    mCertVerificationThread(nullptr)
   247 {
   248 #ifdef PR_LOGGING
   249   if (!gPIPNSSLog)
   250     gPIPNSSLog = PR_NewLogModule("pipnss");
   251 #endif
   252   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
   253   mObserversRegistered = false;
   255   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
   256   ++mInstanceCount;
   257   mShutdownObjectList = nsNSSShutDownList::construct();
   258   mIsNetworkDown = false;
   259 }
   261 void
   262 nsNSSComponent::deleteBackgroundThreads()
   263 {
   264   if (mCertVerificationThread)
   265   {
   266     mCertVerificationThread->requestExit();
   267     delete mCertVerificationThread;
   268     mCertVerificationThread = nullptr;
   269   }
   270 }
   272 void
   273 nsNSSComponent::createBackgroundThreads()
   274 {
   275   NS_ASSERTION(!mCertVerificationThread,
   276                "Cert verification thread already created.");
   278   mCertVerificationThread = new nsCertVerificationThread;
   279   nsresult rv = mCertVerificationThread->startThread(
   280     NS_LITERAL_CSTRING("Cert Verify"));
   282   if (NS_FAILED(rv)) {
   283     delete mCertVerificationThread;
   284     mCertVerificationThread = nullptr;
   285   }
   286 }
   288 nsNSSComponent::~nsNSSComponent()
   289 {
   290   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
   292   deleteBackgroundThreads();
   294   // All cleanup code requiring services needs to happen in xpcom_shutdown
   296   ShutdownNSS();
   297   SharedSSLState::GlobalCleanup();
   298   RememberCertErrorsTable::Cleanup();
   299   --mInstanceCount;
   300   delete mShutdownObjectList;
   302   // We are being freed, drop the haveLoaded flag to re-enable
   303   // potential nss initialization later.
   304   EnsureNSSInitialized(nssShutdown);
   306   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
   307 }
   309 #ifndef MOZ_DISABLE_CRYPTOLEGACY
   310 NS_IMETHODIMP
   311 nsNSSComponent::PostEvent(const nsAString& eventType,
   312                           const nsAString& tokenName)
   313 {
   314   nsCOMPtr<nsIRunnable> runnable =
   315                                new nsTokenEventRunnable(eventType, tokenName);
   317   return NS_DispatchToMainThread(runnable);
   318 }
   321 NS_IMETHODIMP
   322 nsNSSComponent::DispatchEvent(const nsAString& eventType,
   323                               const nsAString& tokenName)
   324 {
   325   // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will
   326   // first check to see if a given window has requested crypto events.
   327   nsresult rv;
   328   nsCOMPtr<nsIWindowWatcher> windowWatcher =
   329                             do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
   331   if (NS_FAILED(rv)) {
   332     return rv;
   333   }
   335   nsCOMPtr<nsISimpleEnumerator> enumerator;
   336   rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator));
   337   if (NS_FAILED(rv)) {
   338     return rv;
   339   }
   341   bool hasMoreWindows;
   343   while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreWindows))
   344          && hasMoreWindows) {
   345     nsCOMPtr<nsISupports> supports;
   346     enumerator->GetNext(getter_AddRefs(supports));
   347     nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(supports));
   348     if (domWin) {
   349       nsresult rv2 = DispatchEventToWindow(domWin, eventType, tokenName);
   350       if (NS_FAILED(rv2)) {
   351         // return the last failure, don't let a single failure prevent
   352         // continued delivery of events.
   353         rv = rv2;
   354       }
   355     }
   356   }
   357   return rv;
   358 }
   360 nsresult
   361 nsNSSComponent::DispatchEventToWindow(nsIDOMWindow* domWin,
   362                                       const nsAString& eventType,
   363                                       const nsAString& tokenName)
   364 {
   365   if (!domWin) {
   366     return NS_OK;
   367   }
   369   // first walk the children and dispatch their events
   370   nsresult rv;
   371   nsCOMPtr<nsIDOMWindowCollection> frames;
   372   rv = domWin->GetFrames(getter_AddRefs(frames));
   373   if (NS_FAILED(rv)) {
   374     return rv;
   375   }
   377   uint32_t length;
   378   frames->GetLength(&length);
   379   uint32_t i;
   380   for (i = 0; i < length; i++) {
   381     nsCOMPtr<nsIDOMWindow> childWin;
   382     frames->Item(i, getter_AddRefs(childWin));
   383     DispatchEventToWindow(childWin, eventType, tokenName);
   384   }
   386   // check if we've enabled smart card events on this window
   387   // NOTE: it's not an error to say that we aren't going to dispatch
   388   // the event.
   389   nsCOMPtr<nsIDOMCrypto> crypto;
   390   domWin->GetCrypto(getter_AddRefs(crypto));
   391   if (!crypto) {
   392     return NS_OK; // nope, it doesn't have a crypto property
   393   }
   395   bool boolrv;
   396   crypto->GetEnableSmartCardEvents(&boolrv);
   397   if (!boolrv) {
   398     return NS_OK; // nope, it's not enabled.
   399   }
   401   // dispatch the event ...
   403   // find the document
   404   nsCOMPtr<nsIDOMDocument> doc;
   405   rv = domWin->GetDocument(getter_AddRefs(doc));
   406   if (!doc) {
   407     return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
   408   }
   410   nsCOMPtr<nsIDocument> d = do_QueryInterface(doc);
   412   // create the event
   413   nsCOMPtr<nsIDOMEvent> event;
   414   NS_NewDOMSmartCardEvent(getter_AddRefs(event), d, nullptr, nullptr);
   415   nsCOMPtr<nsIDOMSmartCardEvent> smartCardEvent = do_QueryInterface(event);
   416   rv = smartCardEvent->InitSmartCardEvent(eventType, false, true, tokenName);
   417   NS_ENSURE_SUCCESS(rv, rv);
   418   smartCardEvent->SetTrusted(true);
   420   // Send it
   421   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc, &rv);
   422   if (NS_FAILED(rv)) {
   423     return rv;
   424   }
   426   return target->DispatchEvent(smartCardEvent, &boolrv);
   427 }
   428 #endif // MOZ_DISABLE_CRYPTOLEGACY
   430 NS_IMETHODIMP
   431 nsNSSComponent::PIPBundleFormatStringFromName(const char* name,
   432                                               const char16_t** params,
   433                                               uint32_t numParams,
   434                                               nsAString& outString)
   435 {
   436   nsresult rv = NS_ERROR_FAILURE;
   438   if (mPIPNSSBundle && name) {
   439     nsXPIDLString result;
   440     rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   441                                              params, numParams,
   442                                              getter_Copies(result));
   443     if (NS_SUCCEEDED(rv)) {
   444       outString = result;
   445     }
   446   }
   447   return rv;
   448 }
   450 NS_IMETHODIMP
   451 nsNSSComponent::GetPIPNSSBundleString(const char* name, nsAString& outString)
   452 {
   453   nsresult rv = NS_ERROR_FAILURE;
   455   outString.SetLength(0);
   456   if (mPIPNSSBundle && name) {
   457     nsXPIDLString result;
   458     rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   459                                           getter_Copies(result));
   460     if (NS_SUCCEEDED(rv)) {
   461       outString = result;
   462       rv = NS_OK;
   463     }
   464   }
   466   return rv;
   467 }
   469 NS_IMETHODIMP
   470 nsNSSComponent::NSSBundleFormatStringFromName(const char* name,
   471                                               const char16_t** params,
   472                                               uint32_t numParams,
   473                                               nsAString& outString)
   474 {
   475   nsresult rv = NS_ERROR_FAILURE;
   477   if (mNSSErrorsBundle && name) {
   478     nsXPIDLString result;
   479     rv = mNSSErrorsBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   480                                                 params, numParams,
   481                                                 getter_Copies(result));
   482     if (NS_SUCCEEDED(rv)) {
   483       outString = result;
   484     }
   485   }
   486   return rv;
   487 }
   489 NS_IMETHODIMP
   490 nsNSSComponent::GetNSSBundleString(const char* name, nsAString& outString)
   491 {
   492   nsresult rv = NS_ERROR_FAILURE;
   494   outString.SetLength(0);
   495   if (mNSSErrorsBundle && name) {
   496     nsXPIDLString result;
   497     rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   498                                              getter_Copies(result));
   499     if (NS_SUCCEEDED(rv)) {
   500       outString = result;
   501       rv = NS_OK;
   502     }
   503   }
   505   return rv;
   506 }
   508 #ifndef MOZ_DISABLE_CRYPTOLEGACY
   509 void
   510 nsNSSComponent::LaunchSmartCardThreads()
   511 {
   512   nsNSSShutDownPreventionLock locker;
   513   {
   514     SECMODModuleList* list;
   515     SECMODListLock* lock = SECMOD_GetDefaultModuleListLock();
   516     if (!lock) {
   517         PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
   518                ("Couldn't get the module list lock, can't launch smart card threads\n"));
   519         return;
   520     }
   521     SECMOD_GetReadLock(lock);
   522     list = SECMOD_GetDefaultModuleList();
   524     while (list) {
   525       SECMODModule* module = list->module;
   526       LaunchSmartCardThread(module);
   527       list = list->next;
   528     }
   529     SECMOD_ReleaseReadLock(lock);
   530   }
   531 }
   533 NS_IMETHODIMP
   534 nsNSSComponent::LaunchSmartCardThread(SECMODModule* module)
   535 {
   536   SmartCardMonitoringThread* newThread;
   537   if (SECMOD_HasRemovableSlots(module)) {
   538     if (!mThreadList) {
   539       mThreadList = new SmartCardThreadList();
   540     }
   541     newThread = new SmartCardMonitoringThread(module);
   542     // newThread is adopted by the add.
   543     return mThreadList->Add(newThread);
   544   }
   545   return NS_OK;
   546 }
   548 NS_IMETHODIMP
   549 nsNSSComponent::ShutdownSmartCardThread(SECMODModule* module)
   550 {
   551   if (!mThreadList) {
   552     return NS_OK;
   553   }
   554   mThreadList->Remove(module);
   555   return NS_OK;
   556 }
   558 void
   559 nsNSSComponent::ShutdownSmartCardThreads()
   560 {
   561   delete mThreadList;
   562   mThreadList = nullptr;
   563 }
   564 #endif // MOZ_DISABLE_CRYPTOLEGACY
   566 void
   567 nsNSSComponent::LoadLoadableRoots()
   568 {
   569   nsNSSShutDownPreventionLock locker;
   570   SECMODModule* RootsModule = nullptr;
   572   // In the past we used SECMOD_AddNewModule to load our module containing
   573   // root CA certificates. This caused problems, refer to bug 176501.
   574   // On startup, we fix our database and clean any stored module reference,
   575   // and will use SECMOD_LoadUserModule to temporarily load it
   576   // for the session. (This approach requires to clean up
   577   // using SECMOD_UnloadUserModule at the end of the session.)
   579   {
   580     // Find module containing root certs
   582     SECMODModuleList* list;
   583     SECMODListLock* lock = SECMOD_GetDefaultModuleListLock();
   584     if (!lock) {
   585         PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
   586                ("Couldn't get the module list lock, can't install loadable roots\n"));
   587         return;
   588     }
   589     SECMOD_GetReadLock(lock);
   590     list = SECMOD_GetDefaultModuleList();
   592     while (!RootsModule && list) {
   593       SECMODModule* module = list->module;
   595       for (int i=0; i < module->slotCount; i++) {
   596         PK11SlotInfo* slot = module->slots[i];
   597         if (PK11_IsPresent(slot)) {
   598           if (PK11_HasRootCerts(slot)) {
   599             RootsModule = SECMOD_ReferenceModule(module);
   600             break;
   601           }
   602         }
   603       }
   605       list = list->next;
   606     }
   607     SECMOD_ReleaseReadLock(lock);
   608   }
   610   if (RootsModule) {
   611     int32_t modType;
   612     SECMOD_DeleteModule(RootsModule->commonName, &modType);
   613     SECMOD_DestroyModule(RootsModule);
   614     RootsModule = nullptr;
   615   }
   617   // Find the best Roots module for our purposes.
   618   // Prefer the application's installation directory,
   619   // but also ensure the library is at least the version we expect.
   621   nsresult rv;
   622   nsAutoString modName;
   623   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
   624   if (NS_FAILED(rv)) return;
   626   nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
   627   if (!directoryService)
   628     return;
   630   static const char nss_lib[] = "nss3";
   631   const char* possible_ckbi_locations[] = {
   632     nss_lib, // This special value means: search for ckbi in the directory
   633              // where nss3 is.
   634     NS_XPCOM_CURRENT_PROCESS_DIR,
   635     NS_GRE_DIR,
   636     0 // This special value means:
   637       //   search for ckbi in the directories on the shared
   638       //   library/DLL search path
   639   };
   641   for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
   642     nsAutoCString libDir;
   644     if (possible_ckbi_locations[il]) {
   645       nsCOMPtr<nsIFile> mozFile;
   646       if (possible_ckbi_locations[il] == nss_lib) {
   647         // Get the location of the nss3 library.
   648         char* nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
   649                                                    (PRFuncPtr) NSS_Initialize);
   650         if (!nss_path) {
   651           continue;
   652         }
   653         // Get the directory containing the nss3 library.
   654         nsCOMPtr<nsIFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
   655         if (NS_SUCCEEDED(rv)) {
   656           rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
   657         }
   658         PR_Free(nss_path);
   659         if (NS_SUCCEEDED(rv)) {
   660           nsCOMPtr<nsIFile> file;
   661           if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
   662             mozFile = do_QueryInterface(file);
   663           }
   664         }
   665       } else {
   666         directoryService->Get( possible_ckbi_locations[il],
   667                                NS_GET_IID(nsIFile),
   668                                getter_AddRefs(mozFile));
   669       }
   671       if (!mozFile) {
   672         continue;
   673       }
   675       if (NS_FAILED(mozFile->GetNativePath(libDir))) {
   676         continue;
   677       }
   678     }
   680     NS_ConvertUTF16toUTF8 modNameUTF8(modName);
   681     if (mozilla::psm::LoadLoadableRoots(
   682             libDir.Length() > 0 ? libDir.get() : nullptr,
   683             modNameUTF8.get()) == SECSuccess) {
   684       break;
   685     }
   686   }
   687 }
   689 void
   690 nsNSSComponent::UnloadLoadableRoots()
   691 {
   692   nsresult rv;
   693   nsAutoString modName;
   694   rv = GetPIPNSSBundleString("RootCertModuleName", modName);
   695   if (NS_FAILED(rv)) return;
   697   NS_ConvertUTF16toUTF8 modNameUTF8(modName);
   698   ::mozilla::psm::UnloadLoadableRoots(modNameUTF8.get());
   699 }
   701 nsresult
   702 nsNSSComponent::ConfigureInternalPKCS11Token()
   703 {
   704   nsNSSShutDownPreventionLock locker;
   705   nsAutoString manufacturerID;
   706   nsAutoString libraryDescription;
   707   nsAutoString tokenDescription;
   708   nsAutoString privateTokenDescription;
   709   nsAutoString slotDescription;
   710   nsAutoString privateSlotDescription;
   711   nsAutoString fips140TokenDescription;
   712   nsAutoString fips140SlotDescription;
   714   nsresult rv;
   715   rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
   716   if (NS_FAILED(rv)) return rv;
   718   rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
   719   if (NS_FAILED(rv)) return rv;
   721   rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
   722   if (NS_FAILED(rv)) return rv;
   724   rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
   725   if (NS_FAILED(rv)) return rv;
   727   rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
   728   if (NS_FAILED(rv)) return rv;
   730   rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
   731   if (NS_FAILED(rv)) return rv;
   733   rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
   734   if (NS_FAILED(rv)) return rv;
   736   rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
   737   if (NS_FAILED(rv)) return rv;
   739   PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
   740                        NS_ConvertUTF16toUTF8(libraryDescription).get(),
   741                        NS_ConvertUTF16toUTF8(tokenDescription).get(),
   742                        NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
   743                        NS_ConvertUTF16toUTF8(slotDescription).get(),
   744                        NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
   745                        NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
   746                        NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
   747                        0, 0);
   748   return NS_OK;
   749 }
   751 nsresult
   752 nsNSSComponent::InitializePIPNSSBundle()
   753 {
   754   // Called during init only, no mutex required.
   756   nsresult rv;
   757   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
   758   if (NS_FAILED(rv) || !bundleService)
   759     return NS_ERROR_FAILURE;
   761   bundleService->CreateBundle("chrome://pipnss/locale/pipnss.properties",
   762                               getter_AddRefs(mPIPNSSBundle));
   763   if (!mPIPNSSBundle)
   764     rv = NS_ERROR_FAILURE;
   766   bundleService->CreateBundle("chrome://pipnss/locale/nsserrors.properties",
   767                               getter_AddRefs(mNSSErrorsBundle));
   768   if (!mNSSErrorsBundle)
   769     rv = NS_ERROR_FAILURE;
   771   return rv;
   772 }
   774 // Table of pref names and SSL cipher ID
   775 typedef struct {
   776   const char* pref;
   777   long id;
   778   bool enabledByDefault;
   779 } CipherPref;
   781 // Update the switch statement in HandshakeCallback in nsNSSCallbacks.cpp when
   782 // you add/remove cipher suites here.
   783 static const CipherPref sCipherPrefs[] = {
   784  { "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
   785    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, true },
   786  { "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
   787    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, true },
   788  { "security.ssl3.ecdhe_rsa_aes_128_sha",
   789    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
   790  { "security.ssl3.ecdhe_ecdsa_aes_128_sha",
   791    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
   793  { "security.ssl3.ecdhe_rsa_aes_256_sha",
   794    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },
   795  { "security.ssl3.ecdhe_ecdsa_aes_256_sha",
   796    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true },
   798  { "security.ssl3.ecdhe_rsa_des_ede3_sha",
   799    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (3DES)
   801  { "security.ssl3.dhe_rsa_aes_128_sha",
   802    TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
   803  { "security.ssl3.dhe_rsa_camellia_128_sha",
   804    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, true },
   806  { "security.ssl3.dhe_rsa_aes_256_sha",
   807    TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true },
   808  { "security.ssl3.dhe_rsa_camellia_256_sha",
   809    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, true },
   811  { "security.ssl3.dhe_rsa_des_ede3_sha",
   812    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (3DES)
   814  { "security.ssl3.dhe_dss_aes_128_sha",
   815    TLS_DHE_DSS_WITH_AES_128_CBC_SHA, true }, // deprecated (DSS)
   816  { "security.ssl3.dhe_dss_aes_256_sha",
   817    TLS_DHE_DSS_WITH_AES_256_CBC_SHA, true }, // deprecated (DSS)
   819  { "security.ssl3.ecdhe_rsa_rc4_128_sha",
   820    TLS_ECDHE_RSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
   821  { "security.ssl3.ecdhe_ecdsa_rc4_128_sha",
   822    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
   824  { "security.ssl3.rsa_aes_128_sha",
   825    TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
   826  { "security.ssl3.rsa_camellia_128_sha",
   827    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, true }, // deprecated (RSA key exchange)
   828  { "security.ssl3.rsa_aes_256_sha",
   829    TLS_RSA_WITH_AES_256_CBC_SHA, true }, // deprecated (RSA key exchange)
   830  { "security.ssl3.rsa_camellia_256_sha",
   831    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, true }, // deprecated (RSA key exchange)
   832  { "security.ssl3.rsa_des_ede3_sha",
   833    TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
   835  { "security.ssl3.rsa_rc4_128_sha",
   836    TLS_RSA_WITH_RC4_128_SHA, true }, // deprecated (RSA key exchange, RC4)
   837  { "security.ssl3.rsa_rc4_128_md5",
   838    TLS_RSA_WITH_RC4_128_MD5, true }, // deprecated (RSA key exchange, RC4, HMAC-MD5)
   840  // All the rest are disabled by default
   842  { "security.ssl3.rsa_fips_des_ede3_sha",
   843    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, false },
   844  { "security.ssl3.dhe_dss_camellia_256_sha",
   845    TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, false },
   846  { "security.ssl3.dhe_dss_camellia_128_sha",
   847    TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, false },
   848  { "security.ssl3.rsa_seed_sha",
   849    TLS_RSA_WITH_SEED_CBC_SHA, false },
   851  { nullptr, 0 } // end marker
   852 };
   854 static const int32_t OCSP_ENABLED_DEFAULT = 1;
   855 static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
   856 static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
   857 static const bool FALSE_START_ENABLED_DEFAULT = true;
   858 static const bool NPN_ENABLED_DEFAULT = true;
   859 static const bool ALPN_ENABLED_DEFAULT = false;
   860 static const bool SECURITY_NOCERTDB_DEFAULT = false;
   861 static const bool DISABLE_SESSION_IDENTIFIERS_DEFAULT = false;
   863 namespace {
   865 class CipherSuiteChangeObserver : public nsIObserver
   866 {
   867 public:
   868   NS_DECL_ISUPPORTS
   869   NS_DECL_NSIOBSERVER
   871   virtual ~CipherSuiteChangeObserver() {}
   872   static nsresult StartObserve();
   873   static nsresult StopObserve();
   875 private:
   876   static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
   877   CipherSuiteChangeObserver() {}
   878 };
   880 NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver, nsIObserver)
   882 // static
   883 StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
   885 // static
   886 nsresult
   887 CipherSuiteChangeObserver::StartObserve()
   888 {
   889   NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StartObserve() can only be accessed in main thread");
   890   if (!sObserver) {
   891     nsRefPtr<CipherSuiteChangeObserver> observer = new CipherSuiteChangeObserver();
   892     nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
   893     if (NS_FAILED(rv)) {
   894       sObserver = nullptr;
   895       return rv;
   896     }
   897     sObserver = observer;
   898   }
   899   return NS_OK;
   900 }
   902 // static
   903 nsresult
   904 CipherSuiteChangeObserver::StopObserve()
   905 {
   906   NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StopObserve() can only be accessed in main thread");
   907   if (sObserver) {
   908     nsresult rv = Preferences::RemoveObserver(sObserver.get(), "security.");
   909     sObserver = nullptr;
   910     if (NS_FAILED(rv)) {
   911       return rv;
   912     }
   913   }
   914   return NS_OK;
   915 }
   917 nsresult
   918 CipherSuiteChangeObserver::Observe(nsISupports* aSubject,
   919                                    const char* aTopic,
   920                                    const char16_t* someData)
   921 {
   922   NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::Observe can only be accessed in main thread");
   923   if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
   924     NS_ConvertUTF16toUTF8  prefName(someData);
   925     // Look through the cipher table and set according to pref setting
   926     for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
   927       if (prefName.Equals(cp->pref)) {
   928         bool cipherEnabled = Preferences::GetBool(cp->pref,
   929                                                   cp->enabledByDefault);
   930         SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
   931         SSL_ClearSessionCache();
   932         break;
   933       }
   934     }
   935   }
   936   return NS_OK;
   937 }
   939 } // anonymous namespace
   941 // Caller must hold a lock on nsNSSComponent::mutex when calling this function
   942 void nsNSSComponent::setValidationOptions(bool isInitialSetting,
   943                                           const MutexAutoLock& lock)
   944 {
   945   // This preference controls whether we do OCSP fetching and does not affect
   946   // OCSP stapling.
   947   // 0 = disabled, 1 = enabled
   948   int32_t ocspEnabled = Preferences::GetInt("security.OCSP.enabled",
   949                                             OCSP_ENABLED_DEFAULT);
   951   bool ocspRequired = ocspEnabled &&
   952     Preferences::GetBool("security.OCSP.require", false);
   954   // We measure the setting of the pref at startup only to minimize noise by
   955   // addons that may muck with the settings, though it probably doesn't matter.
   956   if (isInitialSetting) {
   957     Telemetry::Accumulate(Telemetry::CERT_OCSP_ENABLED, ocspEnabled);
   958     Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
   959   }
   961 #ifndef NSS_NO_LIBPKIX
   962   bool crlDownloading = Preferences::GetBool("security.CRL_download.enabled",
   963                                              false);
   964   bool aiaDownloadEnabled =
   965     Preferences::GetBool("security.missing_cert_download.enabled", false);
   967 #endif
   968   bool ocspStaplingEnabled = Preferences::GetBool("security.ssl.enable_ocsp_stapling",
   969                                                   true);
   970   PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
   971   PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
   973   CertVerifier::implementation_config certVerifierImplementation
   974     = CertVerifier::classic;
   976   // The mozilla::pkix pref overrides the libpkix pref
   977   if (Preferences::GetBool("security.use_mozillapkix_verification", true)) {
   978     certVerifierImplementation = CertVerifier::mozillapkix;
   979   } else {
   980 #ifndef NSS_NO_LIBPKIX
   981   if (Preferences::GetBool("security.use_libpkix_verification", false)) {
   982     certVerifierImplementation = CertVerifier::libpkix;
   983   }
   984 #endif
   985   }
   987   if (isInitialSetting) {
   988     if (certVerifierImplementation == CertVerifier::classic) {
   989       Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 1);
   990 #ifndef NSS_NO_LIBPKIX
   991     } else if (certVerifierImplementation == CertVerifier::libpkix) {
   992       Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 2);
   993 #endif
   994     } else if (certVerifierImplementation == CertVerifier::mozillapkix) {
   995       Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 3);
   996     }
   997   }
   999   // Default pinning enforcement level is disabled.
  1000   CertVerifier::pinning_enforcement_config
  1001     pinningEnforcementLevel =
  1002       static_cast<CertVerifier::pinning_enforcement_config>
  1003         (Preferences::GetInt("security.cert_pinning.enforcement_level",
  1004                              CertVerifier::pinningDisabled));
  1006   CertVerifier::ocsp_download_config odc;
  1007   CertVerifier::ocsp_strict_config osc;
  1008   CertVerifier::ocsp_get_config ogc;
  1010   SetClassicOCSPBehaviorFromPrefs(&odc, &osc, &ogc, lock);
  1011   mDefaultCertVerifier = new SharedCertVerifier(
  1012       certVerifierImplementation,
  1013 #ifndef NSS_NO_LIBPKIX
  1014       aiaDownloadEnabled ?
  1015         CertVerifier::missing_cert_download_on : CertVerifier::missing_cert_download_off,
  1016       crlDownloading ?
  1017         CertVerifier::crl_download_allowed : CertVerifier::crl_local_only,
  1018 #endif
  1019       odc, osc, ogc, pinningEnforcementLevel);
  1021   // mozilla::pkix has its own OCSP cache, so disable the NSS cache
  1022   // if appropriate.
  1023   if (certVerifierImplementation == CertVerifier::mozillapkix) {
  1024     // Using -1 disables the cache. The other arguments are the default
  1025     // values and aren't exposed by the API.
  1026     CERT_OCSPCacheSettings(-1, 1*60*60L, 24*60*60L);
  1027   } else {
  1028     // Using 1000 enables the cache with the default size of 1000. Again,
  1029     // these values are not exposed by the API.
  1030     CERT_OCSPCacheSettings(1000, 1*60*60L, 24*60*60L);
  1033   CERT_ClearOCSPCache();
  1036 // Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
  1037 // TLS 1.2 (max) when the prefs aren't set or set to invalid values.
  1038 nsresult
  1039 nsNSSComponent::setEnabledTLSVersions()
  1041   // keep these values in sync with security-prefs.js
  1042   static const int32_t PSM_DEFAULT_MIN_TLS_VERSION = 1;
  1043   static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 3;
  1045   int32_t minVersion = Preferences::GetInt("security.tls.version.min",
  1046                                            PSM_DEFAULT_MIN_TLS_VERSION);
  1047   int32_t maxVersion = Preferences::GetInt("security.tls.version.max",
  1048                                            PSM_DEFAULT_MAX_TLS_VERSION);
  1050   // 0 means SSL 3.0, 1 means TLS 1.0, 2 means TLS 1.1, etc.
  1051   minVersion += SSL_LIBRARY_VERSION_3_0;
  1052   maxVersion += SSL_LIBRARY_VERSION_3_0;
  1054   SSLVersionRange range = { (uint16_t) minVersion, (uint16_t) maxVersion };
  1056   if (minVersion != (int32_t) range.min || // prevent truncation
  1057       maxVersion != (int32_t) range.max || // prevent truncation
  1058       SSL_VersionRangeSetDefault(ssl_variant_stream, &range) != SECSuccess) {
  1059     range.min = SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MIN_TLS_VERSION;
  1060     range.max = SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MAX_TLS_VERSION;
  1061     if (SSL_VersionRangeSetDefault(ssl_variant_stream, &range)
  1062           != SECSuccess) {
  1063       return NS_ERROR_UNEXPECTED;
  1067   return NS_OK;
  1070 static nsresult
  1071 GetNSSProfilePath(nsAutoCString& aProfilePath)
  1073   aProfilePath.Truncate();
  1074   const char* dbDirOverride = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
  1075   if (dbDirOverride && strlen(dbDirOverride) > 0) {
  1076     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
  1077            ("Using specified MOZPSM_NSSDBDIR_OVERRIDE as NSS DB dir: %s\n",
  1078             dbDirOverride));
  1079     aProfilePath.Assign(dbDirOverride);
  1080     return NS_OK;
  1083   nsCOMPtr<nsIFile> profileFile;
  1084   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
  1085                                        getter_AddRefs(profileFile));
  1086   if (NS_FAILED(rv)) {
  1087     PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1088            ("Unable to get profile directory - continuing with no NSS DB\n"));
  1089     return NS_OK;
  1092 #if defined(XP_WIN)
  1093   // Native path will drop Unicode characters that cannot be mapped to system's
  1094   // codepage, using short (canonical) path as workaround.
  1095   nsCOMPtr<nsILocalFileWin> profileFileWin(do_QueryInterface(profileFile));
  1096   if (!profileFileWin) {
  1097     PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1098            ("Could not get nsILocalFileWin for profile directory.\n"));
  1099     return NS_ERROR_FAILURE;
  1101   rv = profileFileWin->GetNativeCanonicalPath(aProfilePath);
  1102 #else
  1103   rv = profileFile->GetNativePath(aProfilePath);
  1104 #endif
  1105   if (NS_FAILED(rv)) {
  1106     PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1107            ("Could not get native path for profile directory.\n"));
  1108     return rv;
  1111   return NS_OK;
  1114 nsresult
  1115 nsNSSComponent::InitializeNSS()
  1117   // Can be called both during init and profile change.
  1118   // Needs mutex protection.
  1120   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::InitializeNSS\n"));
  1122   static_assert(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
  1123                 nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
  1124                 nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
  1125                 nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
  1126                 "You must update the values in nsINSSErrorsService.idl");
  1128   MutexAutoLock lock(mutex);
  1130   if (mNSSInitialized) {
  1131     PR_ASSERT(!"Trying to initialize NSS twice"); // We should never try to
  1132                                                   // initialize NSS more than
  1133                                                   // once in a process.
  1134     return NS_ERROR_FAILURE;
  1137   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization beginning\n"));
  1139   // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
  1140   // but affects only static data.
  1141   // If we could assume i18n will not change between profiles, one call per application
  1142   // run were sufficient. As I can't predict what happens in the future, let's repeat
  1143   // this call for every re-init of NSS.
  1145   ConfigureInternalPKCS11Token();
  1147   nsAutoCString profileStr;
  1148   nsresult rv = GetNSSProfilePath(profileStr);
  1149   if (NS_FAILED(rv)) {
  1150     nsPSMInitPanic::SetPanic();
  1151     return NS_ERROR_NOT_AVAILABLE;
  1154   SECStatus init_rv = SECFailure;
  1155   bool nocertdb = Preferences::GetBool("security.nocertdb", SECURITY_NOCERTDB_DEFAULT);
  1157   if (!nocertdb && !profileStr.IsEmpty()) {
  1158     // First try to initialize the NSS DB in read/write mode.
  1159     SECStatus init_rv = ::mozilla::psm::InitializeNSS(profileStr.get(), false);
  1160     // If that fails, attempt read-only mode.
  1161     if (init_rv != SECSuccess) {
  1162       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("could not init NSS r/w in %s\n", profileStr.get()));
  1163       init_rv = ::mozilla::psm::InitializeNSS(profileStr.get(), true);
  1165     if (init_rv != SECSuccess) {
  1166       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("could not init in r/o either\n"));
  1169   // If we haven't succeeded in initializing the DB in our profile
  1170   // directory or we don't have a profile at all, or the "security.nocertdb"
  1171   // pref has been set to "true", attempt to initialize with no DB.
  1172   if (nocertdb || init_rv != SECSuccess) {
  1173     init_rv = NSS_NoDB_Init(nullptr);
  1175   if (init_rv != SECSuccess) {
  1176     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("could not initialize NSS - panicking\n"));
  1177     nsPSMInitPanic::SetPanic();
  1178     return NS_ERROR_NOT_AVAILABLE;
  1181   mNSSInitialized = true;
  1183   PK11_SetPasswordFunc(PK11PasswordPrompt);
  1185   SharedSSLState::GlobalInit();
  1187   // Register an observer so we can inform NSS when these prefs change
  1188   Preferences::AddStrongObserver(this, "security.");
  1190   SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
  1191   SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
  1193   rv = setEnabledTLSVersions();
  1194   if (NS_FAILED(rv)) {
  1195     nsPSMInitPanic::SetPanic();
  1196     return NS_ERROR_UNEXPECTED;
  1199   DisableMD5();
  1200   // Initialize the certverifier log before calling any functions that library.
  1201   InitCertVerifierLog();
  1202   LoadLoadableRoots();
  1204   bool disableSessionIdentifiers =
  1205     Preferences::GetBool("security.ssl.disable_session_identifiers",
  1206                          DISABLE_SESSION_IDENTIFIERS_DEFAULT);
  1207   SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
  1208   SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
  1210   bool requireSafeNegotiation =
  1211     Preferences::GetBool("security.ssl.require_safe_negotiation",
  1212                          REQUIRE_SAFE_NEGOTIATION_DEFAULT);
  1213   SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
  1215   bool allowUnrestrictedRenego =
  1216     Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
  1217                          ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
  1218   SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
  1219                        allowUnrestrictedRenego ?
  1220                          SSL_RENEGOTIATE_UNRESTRICTED :
  1221                          SSL_RENEGOTIATE_REQUIRES_XTN);
  1223   SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
  1224                        Preferences::GetBool("security.ssl.enable_false_start",
  1225                                             FALSE_START_ENABLED_DEFAULT));
  1227   // SSL_ENABLE_NPN and SSL_ENABLE_ALPN also require calling
  1228   // SSL_SetNextProtoNego in order for the extensions to be negotiated.
  1229   // WebRTC does not do that so it will not use NPN or ALPN even when these
  1230   // preferences are true.
  1231   SSL_OptionSetDefault(SSL_ENABLE_NPN,
  1232                        Preferences::GetBool("security.ssl.enable_npn",
  1233                                             NPN_ENABLED_DEFAULT));
  1234   SSL_OptionSetDefault(SSL_ENABLE_ALPN,
  1235                        Preferences::GetBool("security.ssl.enable_alpn",
  1236                                             ALPN_ENABLED_DEFAULT));
  1238   if (NS_FAILED(InitializeCipherSuite())) {
  1239     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to initialize cipher suite settings\n"));
  1240     return NS_ERROR_FAILURE;
  1243   // dynamic options from prefs
  1244   setValidationOptions(true, lock);
  1246   mHttpForNSS.initTable();
  1247   mHttpForNSS.registerHttpClient();
  1249 #ifndef MOZ_DISABLE_CRYPTOLEGACY
  1250   LaunchSmartCardThreads();
  1251 #endif
  1253   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization done\n"));
  1254   return NS_OK;
  1257 void
  1258 nsNSSComponent::ShutdownNSS()
  1260   // Can be called both during init and profile change,
  1261   // needs mutex protection.
  1263   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ShutdownNSS\n"));
  1265   MutexAutoLock lock(mutex);
  1267   if (mNSSInitialized) {
  1268     mNSSInitialized = false;
  1270     PK11_SetPasswordFunc((PK11PasswordFunc)nullptr);
  1271     mHttpForNSS.unregisterHttpClient();
  1273     Preferences::RemoveObserver(this, "security.");
  1274     if (NS_FAILED(CipherSuiteChangeObserver::StopObserve())) {
  1275       PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("nsNSSComponent::ShutdownNSS cannot stop observing cipher suite change\n"));
  1278 #ifndef MOZ_DISABLE_CRYPTOLEGACY
  1279     ShutdownSmartCardThreads();
  1280 #endif
  1281     SSL_ClearSessionCache();
  1282     UnloadLoadableRoots();
  1283 #ifndef MOZ_NO_EV_CERTS
  1284     CleanupIdentityInfo();
  1285 #endif
  1286     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
  1287     mShutdownObjectList->evaporateAllNSSResources();
  1288     EnsureNSSInitialized(nssShutdown);
  1289     if (SECSuccess != ::NSS_Shutdown()) {
  1290       PR_LOG(gPIPNSSLog, PR_LOG_ALWAYS, ("NSS SHUTDOWN FAILURE\n"));
  1292     else {
  1293       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS shutdown =====>> OK <<=====\n"));
  1298 static const bool SEND_LM_DEFAULT = false;
  1300 NS_IMETHODIMP
  1301 nsNSSComponent::Init()
  1303   // No mutex protection.
  1304   // Assume Init happens before any concurrency on "this" can start.
  1306   nsresult rv = NS_OK;
  1308   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
  1310   if (!mShutdownObjectList)
  1312     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
  1313     return NS_ERROR_OUT_OF_MEMORY;
  1316   rv = InitializePIPNSSBundle();
  1317   if (NS_FAILED(rv)) {
  1318     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to create pipnss bundle.\n"));
  1319     return rv;
  1322   // Access our string bundles now, this prevents assertions from I/O
  1323   // - nsStandardURL not thread-safe
  1324   // - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
  1325   // when loading error strings on the SSL threads.
  1327     NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
  1328     nsXPIDLString result;
  1329     mPIPNSSBundle->GetStringFromName(dummy_name.get(),
  1330                                      getter_Copies(result));
  1331     mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
  1332                                         getter_Copies(result));
  1335   bool sendLM = Preferences::GetBool("network.ntlm.send-lm-response",
  1336                                      SEND_LM_DEFAULT);
  1337   nsNTLMAuthModule::SetSendLM(sendLM);
  1339   // Do that before NSS init, to make sure we won't get unloaded.
  1340   RegisterObservers();
  1342   rv = InitializeNSS();
  1343   if (NS_FAILED(rv)) {
  1344     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
  1346     DeregisterObservers();
  1347     mPIPNSSBundle = nullptr;
  1348     return rv;
  1351   RememberCertErrorsTable::Init();
  1353   createBackgroundThreads();
  1354   if (!mCertVerificationThread)
  1356     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
  1358     DeregisterObservers();
  1359     mPIPNSSBundle = nullptr;
  1360     return NS_ERROR_OUT_OF_MEMORY;
  1363   nsCOMPtr<nsIEntropyCollector> ec
  1364       = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
  1366   nsCOMPtr<nsIBufEntropyCollector> bec;
  1368   if (ec) {
  1369     bec = do_QueryInterface(ec);
  1372   NS_ASSERTION(bec, "No buffering entropy collector.  "
  1373                     "This means no entropy will be collected.");
  1374   if (bec) {
  1375     bec->ForwardTo(this);
  1378   return rv;
  1381 // nsISupports Implementation for the class
  1382 NS_IMPL_ISUPPORTS(nsNSSComponent,
  1383                   nsISignatureVerifier,
  1384                   nsIEntropyCollector,
  1385                   nsINSSComponent,
  1386                   nsIObserver,
  1387                   nsISupportsWeakReference)
  1390 // Callback functions for decoder. For now, use empty/default functions.
  1391 static void
  1392 ContentCallback(void* arg, const char* buf, unsigned long len)
  1396 static PK11SymKey*
  1397 GetDecryptKeyCallback(void* arg, SECAlgorithmID* algid)
  1399   return nullptr;
  1402 static PRBool
  1403 DecryptionAllowedCallback(SECAlgorithmID* algid, PK11SymKey* bulkkey)
  1405   return SECMIME_DecryptionAllowed(algid, bulkkey);
  1408 static void*
  1409 GetPasswordKeyCallback(void* arg, void* handle)
  1411   return nullptr;
  1414 NS_IMETHODIMP
  1415 nsNSSComponent::VerifySignature(const char* aRSABuf, uint32_t aRSABufLen,
  1416                                 const char* aPlaintext, uint32_t aPlaintextLen,
  1417                                 int32_t* aErrorCode,
  1418                                 nsICertificatePrincipal** aPrincipal)
  1420   if (!aPrincipal || !aErrorCode) {
  1421     return NS_ERROR_NULL_POINTER;
  1424   *aErrorCode = 0;
  1425   *aPrincipal = nullptr;
  1427   nsNSSShutDownPreventionLock locker;
  1428   ScopedSEC_PKCS7ContentInfo p7_info;
  1429   unsigned char hash[SHA1_LENGTH];
  1431   SECItem item;
  1432   item.type = siEncodedCertBuffer;
  1433   item.data = (unsigned char*)aRSABuf;
  1434   item.len = aRSABufLen;
  1435   p7_info = SEC_PKCS7DecodeItem(&item,
  1436                                 ContentCallback, nullptr,
  1437                                 GetPasswordKeyCallback, nullptr,
  1438                                 GetDecryptKeyCallback, nullptr,
  1439                                 DecryptionAllowedCallback);
  1441   if (!p7_info) {
  1442     return NS_ERROR_FAILURE;
  1445   // Make sure we call SEC_PKCS7DestroyContentInfo after this point;
  1446   // otherwise we leak data in p7_info
  1448   //-- If a plaintext was provided, hash it.
  1449   SECItem digest;
  1450   digest.data = nullptr;
  1451   digest.len = 0;
  1453   if (aPlaintext) {
  1454     HASHContext* hash_ctxt;
  1455     uint32_t hashLen = 0;
  1457     hash_ctxt = HASH_Create(HASH_AlgSHA1);
  1458     HASH_Begin(hash_ctxt);
  1459     HASH_Update(hash_ctxt,(const unsigned char*)aPlaintext, aPlaintextLen);
  1460     HASH_End(hash_ctxt, hash, &hashLen, SHA1_LENGTH);
  1461     HASH_Destroy(hash_ctxt);
  1463     digest.data = hash;
  1464     digest.len = SHA1_LENGTH;
  1467   //-- Verify signature
  1468   bool rv = SEC_PKCS7VerifyDetachedSignature(p7_info, certUsageObjectSigner,
  1469                                                &digest, HASH_AlgSHA1, false);
  1470   if (!rv) {
  1471     *aErrorCode = PR_GetError();
  1474   // Get the signing cert //
  1475   CERTCertificate* cert = p7_info->content.signedData->signerInfos[0]->cert;
  1476   nsresult rv2 = NS_OK;
  1477   if (cert) {
  1478     // Use |do { } while (0);| as a "more C++-ish" thing than goto;
  1479     // this way we don't have to worry about goto across variable
  1480     // declarations.  We have no loops in this code, so it's OK.
  1481     do {
  1482       nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
  1483       if (!pCert) {
  1484         rv2 = NS_ERROR_OUT_OF_MEMORY;
  1485         break;
  1488       //-- Create a certificate principal with id and organization data
  1489       nsAutoString fingerprint;
  1490       rv2 = pCert->GetSha1Fingerprint(fingerprint);
  1491       if (NS_FAILED(rv2)) {
  1492         break;
  1494       nsAutoString orgName;
  1495       rv2 = pCert->GetOrganization(orgName);
  1496       if (NS_FAILED(rv2)) {
  1497         break;
  1499       nsAutoString subjectName;
  1500       rv2 = pCert->GetSubjectName(subjectName);
  1501       if (NS_FAILED(rv2)) {
  1502         break;
  1505       nsCOMPtr<nsICertificatePrincipal> certPrincipal =
  1506         new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
  1507                                    NS_ConvertUTF16toUTF8(subjectName),
  1508                                    NS_ConvertUTF16toUTF8(orgName),
  1509                                    pCert);
  1511       certPrincipal.swap(*aPrincipal);
  1512     } while (0);
  1515   return rv2;
  1518 NS_IMETHODIMP
  1519 nsNSSComponent::RandomUpdate(void* entropy, int32_t bufLen)
  1521   nsNSSShutDownPreventionLock locker;
  1523   // Asynchronous event happening often,
  1524   // must not interfere with initialization or profile switch.
  1526   MutexAutoLock lock(mutex);
  1528   if (!mNSSInitialized)
  1529       return NS_ERROR_NOT_INITIALIZED;
  1531   PK11_RandomUpdate(entropy, bufLen);
  1532   return NS_OK;
  1535 static const char* const PROFILE_CHANGE_NET_TEARDOWN_TOPIC
  1536   = "profile-change-net-teardown";
  1537 static const char* const PROFILE_CHANGE_NET_RESTORE_TOPIC
  1538   = "profile-change-net-restore";
  1539 static const char* const PROFILE_CHANGE_TEARDOWN_TOPIC
  1540   = "profile-change-teardown";
  1541 static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
  1542 static const char* const PROFILE_DO_CHANGE_TOPIC = "profile-do-change";
  1544 NS_IMETHODIMP
  1545 nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
  1546                         const char16_t* someData)
  1548   if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
  1549     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
  1550     DoProfileChangeTeardown(aSubject);
  1552   else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
  1553     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
  1554     DoProfileBeforeChange(aSubject);
  1556   else if (nsCRT::strcmp(aTopic, PROFILE_DO_CHANGE_TOPIC) == 0) {
  1557     if (someData && NS_LITERAL_STRING("startup").Equals(someData)) {
  1558       // The application is initializing against a known profile directory for
  1559       // the first time during process execution.
  1560       // However, earlier code execution might have already triggered NSS init.
  1561       // We must ensure that NSS gets shut down prior to any attempt to init
  1562       // it again. We use the same cleanup functionality used when switching
  1563       // profiles. The order of function calls must correspond to the order
  1564       // of notifications sent by Profile Manager (nsProfile).
  1565       DoProfileChangeNetTeardown();
  1566       DoProfileChangeTeardown(aSubject);
  1567       DoProfileBeforeChange(aSubject);
  1568       DoProfileChangeNetRestore();
  1571     bool needsInit = true;
  1574       MutexAutoLock lock(mutex);
  1576       if (mNSSInitialized) {
  1577         // We have already initialized NSS before the profile came up,
  1578         // no need to do it again
  1579         needsInit = false;
  1583     if (needsInit) {
  1584       if (NS_FAILED(InitializeNSS())) {
  1585         PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS after profile switch.\n"));
  1589   else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
  1591     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: XPCom shutdown observed\n"));
  1593     // Cleanup code that requires services, it's too late in destructor.
  1595     nsCOMPtr<nsIEntropyCollector> ec
  1596         = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
  1598     if (ec) {
  1599       nsCOMPtr<nsIBufEntropyCollector> bec
  1600         = do_QueryInterface(ec);
  1601       if (bec) {
  1602         bec->DontForward();
  1606   else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
  1607     nsNSSShutDownPreventionLock locker;
  1608     bool clearSessionCache = true;
  1609     NS_ConvertUTF16toUTF8  prefName(someData);
  1611     if (prefName.Equals("security.tls.version.min") ||
  1612         prefName.Equals("security.tls.version.max")) {
  1613       (void) setEnabledTLSVersions();
  1614     } else if (prefName.Equals("security.ssl.disable_session_identifiers")) {
  1615       bool disableSessionIdentifiers =
  1616         Preferences::GetBool("security.ssl.disable_session_identifiers",
  1617                              DISABLE_SESSION_IDENTIFIERS_DEFAULT);
  1618       SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
  1619       SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
  1620     } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
  1621       bool requireSafeNegotiation =
  1622         Preferences::GetBool("security.ssl.require_safe_negotiation",
  1623                              REQUIRE_SAFE_NEGOTIATION_DEFAULT);
  1624       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
  1625     } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
  1626       bool allowUnrestrictedRenego =
  1627         Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
  1628                              ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
  1629       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
  1630                            allowUnrestrictedRenego ?
  1631                              SSL_RENEGOTIATE_UNRESTRICTED :
  1632                              SSL_RENEGOTIATE_REQUIRES_XTN);
  1633     } else if (prefName.Equals("security.ssl.enable_false_start")) {
  1634       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
  1635                            Preferences::GetBool("security.ssl.enable_false_start",
  1636                                                 FALSE_START_ENABLED_DEFAULT));
  1637     } else if (prefName.Equals("security.ssl.enable_npn")) {
  1638       SSL_OptionSetDefault(SSL_ENABLE_NPN,
  1639                            Preferences::GetBool("security.ssl.enable_npn",
  1640                                                 NPN_ENABLED_DEFAULT));
  1641     } else if (prefName.Equals("security.ssl.enable_alpn")) {
  1642       SSL_OptionSetDefault(SSL_ENABLE_ALPN,
  1643                            Preferences::GetBool("security.ssl.enable_alpn",
  1644                                                 ALPN_ENABLED_DEFAULT));
  1645     } else if (prefName.Equals("security.OCSP.enabled")
  1646                || prefName.Equals("security.CRL_download.enabled")
  1647                || prefName.Equals("security.fresh_revocation_info.require")
  1648                || prefName.Equals("security.missing_cert_download.enabled")
  1649                || prefName.Equals("security.OCSP.require")
  1650                || prefName.Equals("security.OCSP.GET.enabled")
  1651                || prefName.Equals("security.ssl.enable_ocsp_stapling")
  1652                || prefName.Equals("security.use_mozillapkix_verification")
  1653                || prefName.Equals("security.use_libpkix_verification")
  1654                || prefName.Equals("security.cert_pinning.enforcement_level")) {
  1655       MutexAutoLock lock(mutex);
  1656       setValidationOptions(false, lock);
  1657     } else if (prefName.Equals("network.ntlm.send-lm-response")) {
  1658       bool sendLM = Preferences::GetBool("network.ntlm.send-lm-response",
  1659                                          SEND_LM_DEFAULT);
  1660       nsNTLMAuthModule::SetSendLM(sendLM);
  1661       clearSessionCache = false;
  1662     } else {
  1663       clearSessionCache = false;
  1665     if (clearSessionCache)
  1666       SSL_ClearSessionCache();
  1668   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
  1669     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
  1670     DoProfileChangeNetTeardown();
  1672   else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_RESTORE_TOPIC) == 0) {
  1673     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network restore topic\n"));
  1674     DoProfileChangeNetRestore();
  1677   return NS_OK;
  1680 /*static*/ nsresult
  1681 nsNSSComponent::GetNewPrompter(nsIPrompt** result)
  1683   NS_ENSURE_ARG_POINTER(result);
  1684   *result = nullptr;
  1686   if (!NS_IsMainThread()) {
  1687     NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
  1688     return NS_ERROR_NOT_SAME_THREAD;
  1691   nsresult rv;
  1692   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1693   NS_ENSURE_SUCCESS(rv, rv);
  1695   rv = wwatch->GetNewPrompter(0, result);
  1696   NS_ENSURE_SUCCESS(rv, rv);
  1698   return rv;
  1701 /*static*/ nsresult
  1702 nsNSSComponent::ShowAlertWithConstructedString(const nsString& message)
  1704   nsCOMPtr<nsIPrompt> prompter;
  1705   nsresult rv = GetNewPrompter(getter_AddRefs(prompter));
  1706   if (prompter) {
  1707     nsPSMUITracker tracker;
  1708     if (tracker.isUIForbidden()) {
  1709       NS_WARNING("Suppressing alert because PSM UI is forbidden");
  1710       rv = NS_ERROR_UNEXPECTED;
  1711     } else {
  1712       rv = prompter->Alert(nullptr, message.get());
  1715   return rv;
  1718 NS_IMETHODIMP
  1719 nsNSSComponent::ShowAlertFromStringBundle(const char* messageID)
  1721   nsString message;
  1722   nsresult rv;
  1724   rv = GetPIPNSSBundleString(messageID, message);
  1725   if (NS_FAILED(rv)) {
  1726     NS_ERROR("GetPIPNSSBundleString failed");
  1727     return rv;
  1730   return ShowAlertWithConstructedString(message);
  1733 nsresult nsNSSComponent::LogoutAuthenticatedPK11()
  1735   nsCOMPtr<nsICertOverrideService> icos =
  1736     do_GetService("@mozilla.org/security/certoverride;1");
  1737   if (icos) {
  1738     icos->ClearValidityOverride(
  1739             NS_LITERAL_CSTRING("all:temporary-certificates"),
  1740             0);
  1743   nsClientAuthRememberService::ClearAllRememberedDecisions();
  1745   return mShutdownObjectList->doPK11Logout();
  1748 nsresult
  1749 nsNSSComponent::RegisterObservers()
  1751   // Happens once during init only, no mutex protection.
  1753   nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
  1754   NS_ASSERTION(observerService, "could not get observer service");
  1755   if (observerService) {
  1756     mObserversRegistered = true;
  1757     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: adding observers\n"));
  1759     // We are a service.
  1760     // Once we are loaded, don't allow being removed from memory.
  1761     // This makes sense, as initializing NSS is expensive.
  1763     // By using false for parameter ownsWeak in AddObserver,
  1764     // we make sure that we won't get unloaded until the application shuts down.
  1766     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
  1768     observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC, false);
  1769     observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
  1770     observerService->AddObserver(this, PROFILE_DO_CHANGE_TOPIC, false);
  1771     observerService->AddObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC, false);
  1772     observerService->AddObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC, false);
  1774   return NS_OK;
  1777 nsresult
  1778 nsNSSComponent::DeregisterObservers()
  1780   if (!mObserversRegistered)
  1781     return NS_OK;
  1783   nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
  1784   NS_ASSERTION(observerService, "could not get observer service");
  1785   if (observerService) {
  1786     mObserversRegistered = false;
  1787     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n"));
  1789     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
  1791     observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
  1792     observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
  1793     observerService->RemoveObserver(this, PROFILE_DO_CHANGE_TOPIC);
  1794     observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC);
  1795     observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC);
  1797   return NS_OK;
  1800 void
  1801 nsNSSComponent::DoProfileChangeNetTeardown()
  1803   if (mCertVerificationThread)
  1804     mCertVerificationThread->requestExit();
  1805   mIsNetworkDown = true;
  1808 void
  1809 nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
  1811   mShutdownObjectList->ifPossibleDisallowUI();
  1814 void
  1815 nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
  1817   NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
  1819   bool needsCleanup = true;
  1822     MutexAutoLock lock(mutex);
  1824     if (!mNSSInitialized) {
  1825       // Make sure we don't try to cleanup if we have already done so.
  1826       // This makes sure we behave safely, in case we are notified
  1827       // multiple times.
  1828       needsCleanup = false;
  1832   if (needsCleanup) {
  1833     ShutdownNSS();
  1835   mShutdownObjectList->allowUI();
  1838 void
  1839 nsNSSComponent::DoProfileChangeNetRestore()
  1841   // XXX this doesn't work well, since nothing expects null pointers
  1842   deleteBackgroundThreads();
  1843   createBackgroundThreads();
  1844   mIsNetworkDown = false;
  1847 NS_IMETHODIMP
  1848 nsNSSComponent::IsNSSInitialized(bool* initialized)
  1850   MutexAutoLock lock(mutex);
  1851   *initialized = mNSSInitialized;
  1852   return NS_OK;
  1855 SharedCertVerifier::~SharedCertVerifier() { }
  1857 TemporaryRef<SharedCertVerifier>
  1858 nsNSSComponent::GetDefaultCertVerifier()
  1860   MutexAutoLock lock(mutex);
  1861   MOZ_ASSERT(mNSSInitialized);
  1862   return mDefaultCertVerifier;
  1865 namespace mozilla { namespace psm {
  1867 TemporaryRef<SharedCertVerifier>
  1868 GetDefaultCertVerifier()
  1870   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1872   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
  1873   RefPtr<SharedCertVerifier> certVerifier;
  1874   if (nssComponent) {
  1875     return nssComponent->GetDefaultCertVerifier();
  1878   return nullptr;
  1881 } } // namespace mozilla::psm
  1883 NS_IMPL_ISUPPORTS(PipUIContext, nsIInterfaceRequestor)
  1885 PipUIContext::PipUIContext()
  1889 PipUIContext::~PipUIContext()
  1893 NS_IMETHODIMP
  1894 PipUIContext::GetInterface(const nsIID& uuid, void** result)
  1896   NS_ENSURE_ARG_POINTER(result);
  1897   *result = nullptr;
  1899   if (!NS_IsMainThread()) {
  1900     NS_ERROR("PipUIContext::GetInterface called off the main thread");
  1901     return NS_ERROR_NOT_SAME_THREAD;
  1904   if (!uuid.Equals(NS_GET_IID(nsIPrompt)))
  1905     return NS_ERROR_NO_INTERFACE;
  1907   nsIPrompt* prompt = nullptr;
  1908   nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
  1909   *result = prompt;
  1910   return rv;
  1913 nsresult
  1914 getNSSDialogs(void** _result, REFNSIID aIID, const char* contract)
  1916   if (!NS_IsMainThread()) {
  1917     NS_ERROR("getNSSDialogs called off the main thread");
  1918     return NS_ERROR_NOT_SAME_THREAD;
  1921   nsresult rv;
  1923   nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
  1924   if (NS_FAILED(rv)) {
  1925     return rv;
  1928   rv = svc->QueryInterface(aIID, _result);
  1930   return rv;
  1933 nsresult
  1934 setPassword(PK11SlotInfo* slot, nsIInterfaceRequestor* ctx)
  1936   nsNSSShutDownPreventionLock locker;
  1937   nsresult rv = NS_OK;
  1939   if (PK11_NeedUserInit(slot)) {
  1940     nsITokenPasswordDialogs* dialogs;
  1941     bool canceled;
  1942     NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot));
  1944     rv = getNSSDialogs((void**)&dialogs,
  1945                        NS_GET_IID(nsITokenPasswordDialogs),
  1946                        NS_TOKENPASSWORDSDIALOG_CONTRACTID);
  1948     if (NS_FAILED(rv)) goto loser;
  1951       nsPSMUITracker tracker;
  1952       if (tracker.isUIForbidden()) {
  1953         rv = NS_ERROR_NOT_AVAILABLE;
  1955       else {
  1956         rv = dialogs->SetPassword(ctx,
  1957                                   tokenName.get(),
  1958                                   &canceled);
  1961     NS_RELEASE(dialogs);
  1962     if (NS_FAILED(rv)) goto loser;
  1964     if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
  1966  loser:
  1967   return rv;
  1970 namespace mozilla {
  1971 namespace psm {
  1973 nsresult
  1974 InitializeCipherSuite()
  1976   NS_ASSERTION(NS_IsMainThread(), "InitializeCipherSuite() can only be accessed in main thread");
  1978   if (NSS_SetDomesticPolicy() != SECSuccess) {
  1979     return NS_ERROR_FAILURE;
  1982   // Disable any ciphers that NSS might have enabled by default
  1983   for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
  1984     uint16_t cipher_id = SSL_ImplementedCiphers[i];
  1985     SSL_CipherPrefSetDefault(cipher_id, false);
  1988   // Now only set SSL/TLS ciphers we knew about at compile time
  1989   for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
  1990     bool cipherEnabled = Preferences::GetBool(cp->pref, cp->enabledByDefault);
  1991     SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
  1994   // Enable ciphers for PKCS#12
  1995   SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
  1996   SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
  1997   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
  1998   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
  1999   SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
  2000   SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
  2001   SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
  2002   PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
  2004   // Observe preference change around cipher suite setting.
  2005   return CipherSuiteChangeObserver::StartObserve();
  2008 } // namespace psm
  2009 } // namespace mozilla

mercurial