security/manager/ssl/src/nsNSSComponent.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/src/nsNSSComponent.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2009 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifdef MOZ_LOGGING
    1.11 +#define FORCE_PR_LOG 1
    1.12 +#endif
    1.13 +
    1.14 +#include "nsNSSComponent.h"
    1.15 +
    1.16 +#include "ExtendedValidation.h"
    1.17 +#include "NSSCertDBTrustDomain.h"
    1.18 +#include "mozilla/Telemetry.h"
    1.19 +#include "nsCertVerificationThread.h"
    1.20 +#include "nsAppDirectoryServiceDefs.h"
    1.21 +#include "nsComponentManagerUtils.h"
    1.22 +#include "nsDirectoryServiceDefs.h"
    1.23 +#include "nsICertOverrideService.h"
    1.24 +#include "mozilla/Preferences.h"
    1.25 +#include "nsThreadUtils.h"
    1.26 +#include "mozilla/PublicSSL.h"
    1.27 +#include "mozilla/StaticPtr.h"
    1.28 +
    1.29 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
    1.30 +#include "nsIDOMNode.h"
    1.31 +#include "nsIDOMEvent.h"
    1.32 +#include "nsIDOMDocument.h"
    1.33 +#include "nsIDOMWindow.h"
    1.34 +#include "nsIDOMWindowCollection.h"
    1.35 +#include "nsIDocument.h"
    1.36 +#include "nsIDOMSmartCardEvent.h"
    1.37 +#include "nsSmartCardMonitor.h"
    1.38 +#include "nsIDOMCryptoLegacy.h"
    1.39 +#include "nsIPrincipal.h"
    1.40 +#else
    1.41 +#include "nsIDOMCrypto.h"
    1.42 +#endif
    1.43 +
    1.44 +#include "nsCRT.h"
    1.45 +#include "nsNTLMAuthModule.h"
    1.46 +#include "nsIFile.h"
    1.47 +#include "nsIProperties.h"
    1.48 +#include "nsIWindowWatcher.h"
    1.49 +#include "nsIPrompt.h"
    1.50 +#include "nsCertificatePrincipal.h"
    1.51 +#include "nsIBufEntropyCollector.h"
    1.52 +#include "nsITokenPasswordDialogs.h"
    1.53 +#include "nsServiceManagerUtils.h"
    1.54 +#include "nsNSSShutDown.h"
    1.55 +#include "GeneratedEvents.h"
    1.56 +#include "SharedSSLState.h"
    1.57 +
    1.58 +#include "nss.h"
    1.59 +#include "ssl.h"
    1.60 +#include "sslproto.h"
    1.61 +#include "secmod.h"
    1.62 +#include "secmime.h"
    1.63 +#include "ocsp.h"
    1.64 +#include "secerr.h"
    1.65 +#include "sslerr.h"
    1.66 +
    1.67 +#include "nsXULAppAPI.h"
    1.68 +
    1.69 +#ifdef XP_WIN
    1.70 +#include "nsILocalFileWin.h"
    1.71 +#endif
    1.72 +
    1.73 +#include "p12plcy.h"
    1.74 +
    1.75 +using namespace mozilla;
    1.76 +using namespace mozilla::dom;
    1.77 +using namespace mozilla::psm;
    1.78 +
    1.79 +#ifdef PR_LOGGING
    1.80 +PRLogModuleInfo* gPIPNSSLog = nullptr;
    1.81 +#endif
    1.82 +
    1.83 +int nsNSSComponent::mInstanceCount = 0;
    1.84 +
    1.85 +// XXX tmp callback for slot password
    1.86 +extern char* pk11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg);
    1.87 +
    1.88 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
    1.89 +//This class is used to run the callback code
    1.90 +//passed to the event handlers for smart card notification
    1.91 +class nsTokenEventRunnable : public nsIRunnable {
    1.92 +public:
    1.93 +  nsTokenEventRunnable(const nsAString& aType, const nsAString& aTokenName);
    1.94 +  virtual ~nsTokenEventRunnable();
    1.95 +
    1.96 +  NS_IMETHOD Run ();
    1.97 +  NS_DECL_THREADSAFE_ISUPPORTS
    1.98 +private:
    1.99 +  nsString mType;
   1.100 +  nsString mTokenName;
   1.101 +};
   1.102 +
   1.103 +// ISuuports implementation for nsTokenEventRunnable
   1.104 +NS_IMPL_ISUPPORTS(nsTokenEventRunnable, nsIRunnable)
   1.105 +
   1.106 +nsTokenEventRunnable::nsTokenEventRunnable(const nsAString& aType,
   1.107 +                                           const nsAString& aTokenName)
   1.108 +  : mType(aType)
   1.109 +  , mTokenName(aTokenName)
   1.110 +{
   1.111 +}
   1.112 +
   1.113 +nsTokenEventRunnable::~nsTokenEventRunnable() { }
   1.114 +
   1.115 +//Implementation that runs the callback passed to
   1.116 +//crypto.generateCRMFRequest as an event.
   1.117 +NS_IMETHODIMP
   1.118 +nsTokenEventRunnable::Run()
   1.119 +{
   1.120 +  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
   1.121 +
   1.122 +  nsresult rv;
   1.123 +  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   1.124 +  if (NS_FAILED(rv))
   1.125 +    return rv;
   1.126 +
   1.127 +  return nssComponent->DispatchEvent(mType, mTokenName);
   1.128 +}
   1.129 +#endif // MOZ_DISABLE_CRYPTOLEGACY
   1.130 +
   1.131 +bool nsPSMInitPanic::isPanic = false;
   1.132 +
   1.133 +// We must ensure that the nsNSSComponent has been loaded before
   1.134 +// creating any other components.
   1.135 +bool EnsureNSSInitialized(EnsureNSSOperator op)
   1.136 +{
   1.137 +  if (nsPSMInitPanic::GetPanic())
   1.138 +    return false;
   1.139 +
   1.140 +  if (GeckoProcessType_Default != XRE_GetProcessType())
   1.141 +  {
   1.142 +    if (op == nssEnsureOnChromeOnly)
   1.143 +    {
   1.144 +      // If the component needs PSM/NSS initialized only on the chrome process,
   1.145 +      // pretend we successfully initiated it but in reality we bypass it.
   1.146 +      // It's up to the programmer to check for process type in such components
   1.147 +      // and take care not to call anything that needs NSS/PSM initiated.
   1.148 +      return true;
   1.149 +    }
   1.150 +
   1.151 +    NS_ERROR("Trying to initialize PSM/NSS in a non-chrome process!");
   1.152 +    return false;
   1.153 +  }
   1.154 +
   1.155 +  static bool loading = false;
   1.156 +  static int32_t haveLoaded = 0;
   1.157 +
   1.158 +  switch (op)
   1.159 +  {
   1.160 +    // In following 4 cases we are protected by monitor of XPCOM component
   1.161 +    // manager - we are inside of do_GetService call for nss component, so it is
   1.162 +    // safe to move with the flags here.
   1.163 +  case nssLoadingComponent:
   1.164 +    if (loading)
   1.165 +      return false; // We are reentered during nss component creation
   1.166 +    loading = true;
   1.167 +    return true;
   1.168 +
   1.169 +  case nssInitSucceeded:
   1.170 +    NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
   1.171 +    loading = false;
   1.172 +    PR_AtomicSet(&haveLoaded, 1);
   1.173 +    return true;
   1.174 +
   1.175 +  case nssInitFailed:
   1.176 +    NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
   1.177 +    loading = false;
   1.178 +    // no break
   1.179 +
   1.180 +  case nssShutdown:
   1.181 +    PR_AtomicSet(&haveLoaded, 0);
   1.182 +    return false;
   1.183 +
   1.184 +    // In this case we are called from a component to ensure nss initilization.
   1.185 +    // If the component has not yet been loaded and is not currently loading
   1.186 +    // call do_GetService for nss component to ensure it.
   1.187 +  case nssEnsure:
   1.188 +  case nssEnsureOnChromeOnly:
   1.189 +    // We are reentered during nss component creation or nss component is already up
   1.190 +    if (PR_AtomicAdd(&haveLoaded, 0) || loading)
   1.191 +      return true;
   1.192 +
   1.193 +    {
   1.194 +    nsCOMPtr<nsINSSComponent> nssComponent
   1.195 +      = do_GetService(PSM_COMPONENT_CONTRACTID);
   1.196 +
   1.197 +    // Nss component failed to initialize, inform the caller of that fact.
   1.198 +    // Flags are appropriately set by component constructor itself.
   1.199 +    if (!nssComponent)
   1.200 +      return false;
   1.201 +
   1.202 +    bool isInitialized;
   1.203 +    nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
   1.204 +    return NS_SUCCEEDED(rv) && isInitialized;
   1.205 +    }
   1.206 +
   1.207 +  default:
   1.208 +    NS_ASSERTION(false, "Bad operator to EnsureNSSInitialized");
   1.209 +    return false;
   1.210 +  }
   1.211 +}
   1.212 +
   1.213 +static void
   1.214 +SetClassicOCSPBehaviorFromPrefs(/*out*/ CertVerifier::ocsp_download_config* odc,
   1.215 +                                /*out*/ CertVerifier::ocsp_strict_config* osc,
   1.216 +                                /*out*/ CertVerifier::ocsp_get_config* ogc,
   1.217 +                                const MutexAutoLock& /*proofOfLock*/)
   1.218 +{
   1.219 +  MOZ_ASSERT(NS_IsMainThread());
   1.220 +  MOZ_ASSERT(odc);
   1.221 +  MOZ_ASSERT(osc);
   1.222 +  MOZ_ASSERT(ogc);
   1.223 +
   1.224 +  // 0 = disabled, otherwise enabled
   1.225 +  *odc = Preferences::GetInt("security.OCSP.enabled", 1)
   1.226 +       ? CertVerifier::ocsp_on
   1.227 +       : CertVerifier::ocsp_off;
   1.228 +
   1.229 +  *osc = Preferences::GetBool("security.OCSP.require", false)
   1.230 +       ? CertVerifier::ocsp_strict
   1.231 +       : CertVerifier::ocsp_relaxed;
   1.232 +
   1.233 +  // XXX: Always use POST for OCSP; see bug 871954 for undoing this.
   1.234 +  *ogc = Preferences::GetBool("security.OCSP.GET.enabled", false)
   1.235 +       ? CertVerifier::ocsp_get_enabled
   1.236 +       : CertVerifier::ocsp_get_disabled;
   1.237 +
   1.238 +  SetClassicOCSPBehavior(*odc, *osc, *ogc);
   1.239 +
   1.240 +  SSL_ClearSessionCache();
   1.241 +}
   1.242 +
   1.243 +nsNSSComponent::nsNSSComponent()
   1.244 +  :mutex("nsNSSComponent.mutex"),
   1.245 +   mNSSInitialized(false),
   1.246 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
   1.247 +   mThreadList(nullptr),
   1.248 +#endif
   1.249 +   mCertVerificationThread(nullptr)
   1.250 +{
   1.251 +#ifdef PR_LOGGING
   1.252 +  if (!gPIPNSSLog)
   1.253 +    gPIPNSSLog = PR_NewLogModule("pipnss");
   1.254 +#endif
   1.255 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
   1.256 +  mObserversRegistered = false;
   1.257 +
   1.258 +  NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
   1.259 +  ++mInstanceCount;
   1.260 +  mShutdownObjectList = nsNSSShutDownList::construct();
   1.261 +  mIsNetworkDown = false;
   1.262 +}
   1.263 +
   1.264 +void
   1.265 +nsNSSComponent::deleteBackgroundThreads()
   1.266 +{
   1.267 +  if (mCertVerificationThread)
   1.268 +  {
   1.269 +    mCertVerificationThread->requestExit();
   1.270 +    delete mCertVerificationThread;
   1.271 +    mCertVerificationThread = nullptr;
   1.272 +  }
   1.273 +}
   1.274 +
   1.275 +void
   1.276 +nsNSSComponent::createBackgroundThreads()
   1.277 +{
   1.278 +  NS_ASSERTION(!mCertVerificationThread,
   1.279 +               "Cert verification thread already created.");
   1.280 +
   1.281 +  mCertVerificationThread = new nsCertVerificationThread;
   1.282 +  nsresult rv = mCertVerificationThread->startThread(
   1.283 +    NS_LITERAL_CSTRING("Cert Verify"));
   1.284 +
   1.285 +  if (NS_FAILED(rv)) {
   1.286 +    delete mCertVerificationThread;
   1.287 +    mCertVerificationThread = nullptr;
   1.288 +  }
   1.289 +}
   1.290 +
   1.291 +nsNSSComponent::~nsNSSComponent()
   1.292 +{
   1.293 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
   1.294 +
   1.295 +  deleteBackgroundThreads();
   1.296 +
   1.297 +  // All cleanup code requiring services needs to happen in xpcom_shutdown
   1.298 +
   1.299 +  ShutdownNSS();
   1.300 +  SharedSSLState::GlobalCleanup();
   1.301 +  RememberCertErrorsTable::Cleanup();
   1.302 +  --mInstanceCount;
   1.303 +  delete mShutdownObjectList;
   1.304 +
   1.305 +  // We are being freed, drop the haveLoaded flag to re-enable
   1.306 +  // potential nss initialization later.
   1.307 +  EnsureNSSInitialized(nssShutdown);
   1.308 +
   1.309 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
   1.310 +}
   1.311 +
   1.312 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
   1.313 +NS_IMETHODIMP
   1.314 +nsNSSComponent::PostEvent(const nsAString& eventType,
   1.315 +                          const nsAString& tokenName)
   1.316 +{
   1.317 +  nsCOMPtr<nsIRunnable> runnable =
   1.318 +                               new nsTokenEventRunnable(eventType, tokenName);
   1.319 +
   1.320 +  return NS_DispatchToMainThread(runnable);
   1.321 +}
   1.322 +
   1.323 +
   1.324 +NS_IMETHODIMP
   1.325 +nsNSSComponent::DispatchEvent(const nsAString& eventType,
   1.326 +                              const nsAString& tokenName)
   1.327 +{
   1.328 +  // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will
   1.329 +  // first check to see if a given window has requested crypto events.
   1.330 +  nsresult rv;
   1.331 +  nsCOMPtr<nsIWindowWatcher> windowWatcher =
   1.332 +                            do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
   1.333 +
   1.334 +  if (NS_FAILED(rv)) {
   1.335 +    return rv;
   1.336 +  }
   1.337 +
   1.338 +  nsCOMPtr<nsISimpleEnumerator> enumerator;
   1.339 +  rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator));
   1.340 +  if (NS_FAILED(rv)) {
   1.341 +    return rv;
   1.342 +  }
   1.343 +
   1.344 +  bool hasMoreWindows;
   1.345 +
   1.346 +  while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreWindows))
   1.347 +         && hasMoreWindows) {
   1.348 +    nsCOMPtr<nsISupports> supports;
   1.349 +    enumerator->GetNext(getter_AddRefs(supports));
   1.350 +    nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(supports));
   1.351 +    if (domWin) {
   1.352 +      nsresult rv2 = DispatchEventToWindow(domWin, eventType, tokenName);
   1.353 +      if (NS_FAILED(rv2)) {
   1.354 +        // return the last failure, don't let a single failure prevent
   1.355 +        // continued delivery of events.
   1.356 +        rv = rv2;
   1.357 +      }
   1.358 +    }
   1.359 +  }
   1.360 +  return rv;
   1.361 +}
   1.362 +
   1.363 +nsresult
   1.364 +nsNSSComponent::DispatchEventToWindow(nsIDOMWindow* domWin,
   1.365 +                                      const nsAString& eventType,
   1.366 +                                      const nsAString& tokenName)
   1.367 +{
   1.368 +  if (!domWin) {
   1.369 +    return NS_OK;
   1.370 +  }
   1.371 +
   1.372 +  // first walk the children and dispatch their events
   1.373 +  nsresult rv;
   1.374 +  nsCOMPtr<nsIDOMWindowCollection> frames;
   1.375 +  rv = domWin->GetFrames(getter_AddRefs(frames));
   1.376 +  if (NS_FAILED(rv)) {
   1.377 +    return rv;
   1.378 +  }
   1.379 +
   1.380 +  uint32_t length;
   1.381 +  frames->GetLength(&length);
   1.382 +  uint32_t i;
   1.383 +  for (i = 0; i < length; i++) {
   1.384 +    nsCOMPtr<nsIDOMWindow> childWin;
   1.385 +    frames->Item(i, getter_AddRefs(childWin));
   1.386 +    DispatchEventToWindow(childWin, eventType, tokenName);
   1.387 +  }
   1.388 +
   1.389 +  // check if we've enabled smart card events on this window
   1.390 +  // NOTE: it's not an error to say that we aren't going to dispatch
   1.391 +  // the event.
   1.392 +  nsCOMPtr<nsIDOMCrypto> crypto;
   1.393 +  domWin->GetCrypto(getter_AddRefs(crypto));
   1.394 +  if (!crypto) {
   1.395 +    return NS_OK; // nope, it doesn't have a crypto property
   1.396 +  }
   1.397 +
   1.398 +  bool boolrv;
   1.399 +  crypto->GetEnableSmartCardEvents(&boolrv);
   1.400 +  if (!boolrv) {
   1.401 +    return NS_OK; // nope, it's not enabled.
   1.402 +  }
   1.403 +
   1.404 +  // dispatch the event ...
   1.405 +
   1.406 +  // find the document
   1.407 +  nsCOMPtr<nsIDOMDocument> doc;
   1.408 +  rv = domWin->GetDocument(getter_AddRefs(doc));
   1.409 +  if (!doc) {
   1.410 +    return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
   1.411 +  }
   1.412 +
   1.413 +  nsCOMPtr<nsIDocument> d = do_QueryInterface(doc);
   1.414 +
   1.415 +  // create the event
   1.416 +  nsCOMPtr<nsIDOMEvent> event;
   1.417 +  NS_NewDOMSmartCardEvent(getter_AddRefs(event), d, nullptr, nullptr);
   1.418 +  nsCOMPtr<nsIDOMSmartCardEvent> smartCardEvent = do_QueryInterface(event);
   1.419 +  rv = smartCardEvent->InitSmartCardEvent(eventType, false, true, tokenName);
   1.420 +  NS_ENSURE_SUCCESS(rv, rv);
   1.421 +  smartCardEvent->SetTrusted(true);
   1.422 +
   1.423 +  // Send it
   1.424 +  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc, &rv);
   1.425 +  if (NS_FAILED(rv)) {
   1.426 +    return rv;
   1.427 +  }
   1.428 +
   1.429 +  return target->DispatchEvent(smartCardEvent, &boolrv);
   1.430 +}
   1.431 +#endif // MOZ_DISABLE_CRYPTOLEGACY
   1.432 +
   1.433 +NS_IMETHODIMP
   1.434 +nsNSSComponent::PIPBundleFormatStringFromName(const char* name,
   1.435 +                                              const char16_t** params,
   1.436 +                                              uint32_t numParams,
   1.437 +                                              nsAString& outString)
   1.438 +{
   1.439 +  nsresult rv = NS_ERROR_FAILURE;
   1.440 +
   1.441 +  if (mPIPNSSBundle && name) {
   1.442 +    nsXPIDLString result;
   1.443 +    rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   1.444 +                                             params, numParams,
   1.445 +                                             getter_Copies(result));
   1.446 +    if (NS_SUCCEEDED(rv)) {
   1.447 +      outString = result;
   1.448 +    }
   1.449 +  }
   1.450 +  return rv;
   1.451 +}
   1.452 +
   1.453 +NS_IMETHODIMP
   1.454 +nsNSSComponent::GetPIPNSSBundleString(const char* name, nsAString& outString)
   1.455 +{
   1.456 +  nsresult rv = NS_ERROR_FAILURE;
   1.457 +
   1.458 +  outString.SetLength(0);
   1.459 +  if (mPIPNSSBundle && name) {
   1.460 +    nsXPIDLString result;
   1.461 +    rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   1.462 +                                          getter_Copies(result));
   1.463 +    if (NS_SUCCEEDED(rv)) {
   1.464 +      outString = result;
   1.465 +      rv = NS_OK;
   1.466 +    }
   1.467 +  }
   1.468 +
   1.469 +  return rv;
   1.470 +}
   1.471 +
   1.472 +NS_IMETHODIMP
   1.473 +nsNSSComponent::NSSBundleFormatStringFromName(const char* name,
   1.474 +                                              const char16_t** params,
   1.475 +                                              uint32_t numParams,
   1.476 +                                              nsAString& outString)
   1.477 +{
   1.478 +  nsresult rv = NS_ERROR_FAILURE;
   1.479 +
   1.480 +  if (mNSSErrorsBundle && name) {
   1.481 +    nsXPIDLString result;
   1.482 +    rv = mNSSErrorsBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   1.483 +                                                params, numParams,
   1.484 +                                                getter_Copies(result));
   1.485 +    if (NS_SUCCEEDED(rv)) {
   1.486 +      outString = result;
   1.487 +    }
   1.488 +  }
   1.489 +  return rv;
   1.490 +}
   1.491 +
   1.492 +NS_IMETHODIMP
   1.493 +nsNSSComponent::GetNSSBundleString(const char* name, nsAString& outString)
   1.494 +{
   1.495 +  nsresult rv = NS_ERROR_FAILURE;
   1.496 +
   1.497 +  outString.SetLength(0);
   1.498 +  if (mNSSErrorsBundle && name) {
   1.499 +    nsXPIDLString result;
   1.500 +    rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
   1.501 +                                             getter_Copies(result));
   1.502 +    if (NS_SUCCEEDED(rv)) {
   1.503 +      outString = result;
   1.504 +      rv = NS_OK;
   1.505 +    }
   1.506 +  }
   1.507 +
   1.508 +  return rv;
   1.509 +}
   1.510 +
   1.511 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
   1.512 +void
   1.513 +nsNSSComponent::LaunchSmartCardThreads()
   1.514 +{
   1.515 +  nsNSSShutDownPreventionLock locker;
   1.516 +  {
   1.517 +    SECMODModuleList* list;
   1.518 +    SECMODListLock* lock = SECMOD_GetDefaultModuleListLock();
   1.519 +    if (!lock) {
   1.520 +        PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
   1.521 +               ("Couldn't get the module list lock, can't launch smart card threads\n"));
   1.522 +        return;
   1.523 +    }
   1.524 +    SECMOD_GetReadLock(lock);
   1.525 +    list = SECMOD_GetDefaultModuleList();
   1.526 +
   1.527 +    while (list) {
   1.528 +      SECMODModule* module = list->module;
   1.529 +      LaunchSmartCardThread(module);
   1.530 +      list = list->next;
   1.531 +    }
   1.532 +    SECMOD_ReleaseReadLock(lock);
   1.533 +  }
   1.534 +}
   1.535 +
   1.536 +NS_IMETHODIMP
   1.537 +nsNSSComponent::LaunchSmartCardThread(SECMODModule* module)
   1.538 +{
   1.539 +  SmartCardMonitoringThread* newThread;
   1.540 +  if (SECMOD_HasRemovableSlots(module)) {
   1.541 +    if (!mThreadList) {
   1.542 +      mThreadList = new SmartCardThreadList();
   1.543 +    }
   1.544 +    newThread = new SmartCardMonitoringThread(module);
   1.545 +    // newThread is adopted by the add.
   1.546 +    return mThreadList->Add(newThread);
   1.547 +  }
   1.548 +  return NS_OK;
   1.549 +}
   1.550 +
   1.551 +NS_IMETHODIMP
   1.552 +nsNSSComponent::ShutdownSmartCardThread(SECMODModule* module)
   1.553 +{
   1.554 +  if (!mThreadList) {
   1.555 +    return NS_OK;
   1.556 +  }
   1.557 +  mThreadList->Remove(module);
   1.558 +  return NS_OK;
   1.559 +}
   1.560 +
   1.561 +void
   1.562 +nsNSSComponent::ShutdownSmartCardThreads()
   1.563 +{
   1.564 +  delete mThreadList;
   1.565 +  mThreadList = nullptr;
   1.566 +}
   1.567 +#endif // MOZ_DISABLE_CRYPTOLEGACY
   1.568 +
   1.569 +void
   1.570 +nsNSSComponent::LoadLoadableRoots()
   1.571 +{
   1.572 +  nsNSSShutDownPreventionLock locker;
   1.573 +  SECMODModule* RootsModule = nullptr;
   1.574 +
   1.575 +  // In the past we used SECMOD_AddNewModule to load our module containing
   1.576 +  // root CA certificates. This caused problems, refer to bug 176501.
   1.577 +  // On startup, we fix our database and clean any stored module reference,
   1.578 +  // and will use SECMOD_LoadUserModule to temporarily load it
   1.579 +  // for the session. (This approach requires to clean up
   1.580 +  // using SECMOD_UnloadUserModule at the end of the session.)
   1.581 +
   1.582 +  {
   1.583 +    // Find module containing root certs
   1.584 +
   1.585 +    SECMODModuleList* list;
   1.586 +    SECMODListLock* lock = SECMOD_GetDefaultModuleListLock();
   1.587 +    if (!lock) {
   1.588 +        PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
   1.589 +               ("Couldn't get the module list lock, can't install loadable roots\n"));
   1.590 +        return;
   1.591 +    }
   1.592 +    SECMOD_GetReadLock(lock);
   1.593 +    list = SECMOD_GetDefaultModuleList();
   1.594 +
   1.595 +    while (!RootsModule && list) {
   1.596 +      SECMODModule* module = list->module;
   1.597 +
   1.598 +      for (int i=0; i < module->slotCount; i++) {
   1.599 +        PK11SlotInfo* slot = module->slots[i];
   1.600 +        if (PK11_IsPresent(slot)) {
   1.601 +          if (PK11_HasRootCerts(slot)) {
   1.602 +            RootsModule = SECMOD_ReferenceModule(module);
   1.603 +            break;
   1.604 +          }
   1.605 +        }
   1.606 +      }
   1.607 +
   1.608 +      list = list->next;
   1.609 +    }
   1.610 +    SECMOD_ReleaseReadLock(lock);
   1.611 +  }
   1.612 +
   1.613 +  if (RootsModule) {
   1.614 +    int32_t modType;
   1.615 +    SECMOD_DeleteModule(RootsModule->commonName, &modType);
   1.616 +    SECMOD_DestroyModule(RootsModule);
   1.617 +    RootsModule = nullptr;
   1.618 +  }
   1.619 +
   1.620 +  // Find the best Roots module for our purposes.
   1.621 +  // Prefer the application's installation directory,
   1.622 +  // but also ensure the library is at least the version we expect.
   1.623 +
   1.624 +  nsresult rv;
   1.625 +  nsAutoString modName;
   1.626 +  rv = GetPIPNSSBundleString("RootCertModuleName", modName);
   1.627 +  if (NS_FAILED(rv)) return;
   1.628 +
   1.629 +  nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
   1.630 +  if (!directoryService)
   1.631 +    return;
   1.632 +
   1.633 +  static const char nss_lib[] = "nss3";
   1.634 +  const char* possible_ckbi_locations[] = {
   1.635 +    nss_lib, // This special value means: search for ckbi in the directory
   1.636 +             // where nss3 is.
   1.637 +    NS_XPCOM_CURRENT_PROCESS_DIR,
   1.638 +    NS_GRE_DIR,
   1.639 +    0 // This special value means:
   1.640 +      //   search for ckbi in the directories on the shared
   1.641 +      //   library/DLL search path
   1.642 +  };
   1.643 +
   1.644 +  for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
   1.645 +    nsAutoCString libDir;
   1.646 +
   1.647 +    if (possible_ckbi_locations[il]) {
   1.648 +      nsCOMPtr<nsIFile> mozFile;
   1.649 +      if (possible_ckbi_locations[il] == nss_lib) {
   1.650 +        // Get the location of the nss3 library.
   1.651 +        char* nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
   1.652 +                                                   (PRFuncPtr) NSS_Initialize);
   1.653 +        if (!nss_path) {
   1.654 +          continue;
   1.655 +        }
   1.656 +        // Get the directory containing the nss3 library.
   1.657 +        nsCOMPtr<nsIFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
   1.658 +        if (NS_SUCCEEDED(rv)) {
   1.659 +          rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
   1.660 +        }
   1.661 +        PR_Free(nss_path);
   1.662 +        if (NS_SUCCEEDED(rv)) {
   1.663 +          nsCOMPtr<nsIFile> file;
   1.664 +          if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
   1.665 +            mozFile = do_QueryInterface(file);
   1.666 +          }
   1.667 +        }
   1.668 +      } else {
   1.669 +        directoryService->Get( possible_ckbi_locations[il],
   1.670 +                               NS_GET_IID(nsIFile),
   1.671 +                               getter_AddRefs(mozFile));
   1.672 +      }
   1.673 +
   1.674 +      if (!mozFile) {
   1.675 +        continue;
   1.676 +      }
   1.677 +
   1.678 +      if (NS_FAILED(mozFile->GetNativePath(libDir))) {
   1.679 +        continue;
   1.680 +      }
   1.681 +    }
   1.682 +
   1.683 +    NS_ConvertUTF16toUTF8 modNameUTF8(modName);
   1.684 +    if (mozilla::psm::LoadLoadableRoots(
   1.685 +            libDir.Length() > 0 ? libDir.get() : nullptr,
   1.686 +            modNameUTF8.get()) == SECSuccess) {
   1.687 +      break;
   1.688 +    }
   1.689 +  }
   1.690 +}
   1.691 +
   1.692 +void
   1.693 +nsNSSComponent::UnloadLoadableRoots()
   1.694 +{
   1.695 +  nsresult rv;
   1.696 +  nsAutoString modName;
   1.697 +  rv = GetPIPNSSBundleString("RootCertModuleName", modName);
   1.698 +  if (NS_FAILED(rv)) return;
   1.699 +
   1.700 +  NS_ConvertUTF16toUTF8 modNameUTF8(modName);
   1.701 +  ::mozilla::psm::UnloadLoadableRoots(modNameUTF8.get());
   1.702 +}
   1.703 +
   1.704 +nsresult
   1.705 +nsNSSComponent::ConfigureInternalPKCS11Token()
   1.706 +{
   1.707 +  nsNSSShutDownPreventionLock locker;
   1.708 +  nsAutoString manufacturerID;
   1.709 +  nsAutoString libraryDescription;
   1.710 +  nsAutoString tokenDescription;
   1.711 +  nsAutoString privateTokenDescription;
   1.712 +  nsAutoString slotDescription;
   1.713 +  nsAutoString privateSlotDescription;
   1.714 +  nsAutoString fips140TokenDescription;
   1.715 +  nsAutoString fips140SlotDescription;
   1.716 +
   1.717 +  nsresult rv;
   1.718 +  rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
   1.719 +  if (NS_FAILED(rv)) return rv;
   1.720 +
   1.721 +  rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
   1.722 +  if (NS_FAILED(rv)) return rv;
   1.723 +
   1.724 +  rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
   1.725 +  if (NS_FAILED(rv)) return rv;
   1.726 +
   1.727 +  rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
   1.728 +  if (NS_FAILED(rv)) return rv;
   1.729 +
   1.730 +  rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
   1.731 +  if (NS_FAILED(rv)) return rv;
   1.732 +
   1.733 +  rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
   1.734 +  if (NS_FAILED(rv)) return rv;
   1.735 +
   1.736 +  rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
   1.737 +  if (NS_FAILED(rv)) return rv;
   1.738 +
   1.739 +  rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
   1.740 +  if (NS_FAILED(rv)) return rv;
   1.741 +
   1.742 +  PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
   1.743 +                       NS_ConvertUTF16toUTF8(libraryDescription).get(),
   1.744 +                       NS_ConvertUTF16toUTF8(tokenDescription).get(),
   1.745 +                       NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
   1.746 +                       NS_ConvertUTF16toUTF8(slotDescription).get(),
   1.747 +                       NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
   1.748 +                       NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
   1.749 +                       NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
   1.750 +                       0, 0);
   1.751 +  return NS_OK;
   1.752 +}
   1.753 +
   1.754 +nsresult
   1.755 +nsNSSComponent::InitializePIPNSSBundle()
   1.756 +{
   1.757 +  // Called during init only, no mutex required.
   1.758 +
   1.759 +  nsresult rv;
   1.760 +  nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
   1.761 +  if (NS_FAILED(rv) || !bundleService)
   1.762 +    return NS_ERROR_FAILURE;
   1.763 +
   1.764 +  bundleService->CreateBundle("chrome://pipnss/locale/pipnss.properties",
   1.765 +                              getter_AddRefs(mPIPNSSBundle));
   1.766 +  if (!mPIPNSSBundle)
   1.767 +    rv = NS_ERROR_FAILURE;
   1.768 +
   1.769 +  bundleService->CreateBundle("chrome://pipnss/locale/nsserrors.properties",
   1.770 +                              getter_AddRefs(mNSSErrorsBundle));
   1.771 +  if (!mNSSErrorsBundle)
   1.772 +    rv = NS_ERROR_FAILURE;
   1.773 +
   1.774 +  return rv;
   1.775 +}
   1.776 +
   1.777 +// Table of pref names and SSL cipher ID
   1.778 +typedef struct {
   1.779 +  const char* pref;
   1.780 +  long id;
   1.781 +  bool enabledByDefault;
   1.782 +} CipherPref;
   1.783 +
   1.784 +// Update the switch statement in HandshakeCallback in nsNSSCallbacks.cpp when
   1.785 +// you add/remove cipher suites here.
   1.786 +static const CipherPref sCipherPrefs[] = {
   1.787 + { "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
   1.788 +   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, true },
   1.789 + { "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
   1.790 +   TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, true },
   1.791 + { "security.ssl3.ecdhe_rsa_aes_128_sha",
   1.792 +   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, true },
   1.793 + { "security.ssl3.ecdhe_ecdsa_aes_128_sha",
   1.794 +   TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true },
   1.795 +
   1.796 + { "security.ssl3.ecdhe_rsa_aes_256_sha",
   1.797 +   TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, true },
   1.798 + { "security.ssl3.ecdhe_ecdsa_aes_256_sha",
   1.799 +   TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true },
   1.800 +
   1.801 + { "security.ssl3.ecdhe_rsa_des_ede3_sha",
   1.802 +   TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (3DES)
   1.803 +
   1.804 + { "security.ssl3.dhe_rsa_aes_128_sha",
   1.805 +   TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
   1.806 + { "security.ssl3.dhe_rsa_camellia_128_sha",
   1.807 +   TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, true },
   1.808 +
   1.809 + { "security.ssl3.dhe_rsa_aes_256_sha",
   1.810 +   TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true },
   1.811 + { "security.ssl3.dhe_rsa_camellia_256_sha",
   1.812 +   TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, true },
   1.813 +
   1.814 + { "security.ssl3.dhe_rsa_des_ede3_sha",
   1.815 +   TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (3DES)
   1.816 +
   1.817 + { "security.ssl3.dhe_dss_aes_128_sha",
   1.818 +   TLS_DHE_DSS_WITH_AES_128_CBC_SHA, true }, // deprecated (DSS)
   1.819 + { "security.ssl3.dhe_dss_aes_256_sha",
   1.820 +   TLS_DHE_DSS_WITH_AES_256_CBC_SHA, true }, // deprecated (DSS)
   1.821 +
   1.822 + { "security.ssl3.ecdhe_rsa_rc4_128_sha",
   1.823 +   TLS_ECDHE_RSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
   1.824 + { "security.ssl3.ecdhe_ecdsa_rc4_128_sha",
   1.825 +   TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
   1.826 +
   1.827 + { "security.ssl3.rsa_aes_128_sha",
   1.828 +   TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
   1.829 + { "security.ssl3.rsa_camellia_128_sha",
   1.830 +   TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, true }, // deprecated (RSA key exchange)
   1.831 + { "security.ssl3.rsa_aes_256_sha",
   1.832 +   TLS_RSA_WITH_AES_256_CBC_SHA, true }, // deprecated (RSA key exchange)
   1.833 + { "security.ssl3.rsa_camellia_256_sha",
   1.834 +   TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, true }, // deprecated (RSA key exchange)
   1.835 + { "security.ssl3.rsa_des_ede3_sha",
   1.836 +   TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
   1.837 +
   1.838 + { "security.ssl3.rsa_rc4_128_sha",
   1.839 +   TLS_RSA_WITH_RC4_128_SHA, true }, // deprecated (RSA key exchange, RC4)
   1.840 + { "security.ssl3.rsa_rc4_128_md5",
   1.841 +   TLS_RSA_WITH_RC4_128_MD5, true }, // deprecated (RSA key exchange, RC4, HMAC-MD5)
   1.842 +
   1.843 + // All the rest are disabled by default
   1.844 +
   1.845 + { "security.ssl3.rsa_fips_des_ede3_sha",
   1.846 +   SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, false },
   1.847 + { "security.ssl3.dhe_dss_camellia_256_sha",
   1.848 +   TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, false },
   1.849 + { "security.ssl3.dhe_dss_camellia_128_sha",
   1.850 +   TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, false },
   1.851 + { "security.ssl3.rsa_seed_sha",
   1.852 +   TLS_RSA_WITH_SEED_CBC_SHA, false },
   1.853 +
   1.854 + { nullptr, 0 } // end marker
   1.855 +};
   1.856 +
   1.857 +static const int32_t OCSP_ENABLED_DEFAULT = 1;
   1.858 +static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
   1.859 +static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
   1.860 +static const bool FALSE_START_ENABLED_DEFAULT = true;
   1.861 +static const bool NPN_ENABLED_DEFAULT = true;
   1.862 +static const bool ALPN_ENABLED_DEFAULT = false;
   1.863 +static const bool SECURITY_NOCERTDB_DEFAULT = false;
   1.864 +static const bool DISABLE_SESSION_IDENTIFIERS_DEFAULT = false;
   1.865 +
   1.866 +namespace {
   1.867 +
   1.868 +class CipherSuiteChangeObserver : public nsIObserver
   1.869 +{
   1.870 +public:
   1.871 +  NS_DECL_ISUPPORTS
   1.872 +  NS_DECL_NSIOBSERVER
   1.873 +
   1.874 +  virtual ~CipherSuiteChangeObserver() {}
   1.875 +  static nsresult StartObserve();
   1.876 +  static nsresult StopObserve();
   1.877 +
   1.878 +private:
   1.879 +  static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
   1.880 +  CipherSuiteChangeObserver() {}
   1.881 +};
   1.882 +
   1.883 +NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver, nsIObserver)
   1.884 +
   1.885 +// static
   1.886 +StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
   1.887 +
   1.888 +// static
   1.889 +nsresult
   1.890 +CipherSuiteChangeObserver::StartObserve()
   1.891 +{
   1.892 +  NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StartObserve() can only be accessed in main thread");
   1.893 +  if (!sObserver) {
   1.894 +    nsRefPtr<CipherSuiteChangeObserver> observer = new CipherSuiteChangeObserver();
   1.895 +    nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
   1.896 +    if (NS_FAILED(rv)) {
   1.897 +      sObserver = nullptr;
   1.898 +      return rv;
   1.899 +    }
   1.900 +    sObserver = observer;
   1.901 +  }
   1.902 +  return NS_OK;
   1.903 +}
   1.904 +
   1.905 +// static
   1.906 +nsresult
   1.907 +CipherSuiteChangeObserver::StopObserve()
   1.908 +{
   1.909 +  NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::StopObserve() can only be accessed in main thread");
   1.910 +  if (sObserver) {
   1.911 +    nsresult rv = Preferences::RemoveObserver(sObserver.get(), "security.");
   1.912 +    sObserver = nullptr;
   1.913 +    if (NS_FAILED(rv)) {
   1.914 +      return rv;
   1.915 +    }
   1.916 +  }
   1.917 +  return NS_OK;
   1.918 +}
   1.919 +
   1.920 +nsresult
   1.921 +CipherSuiteChangeObserver::Observe(nsISupports* aSubject,
   1.922 +                                   const char* aTopic,
   1.923 +                                   const char16_t* someData)
   1.924 +{
   1.925 +  NS_ASSERTION(NS_IsMainThread(), "CipherSuiteChangeObserver::Observe can only be accessed in main thread");
   1.926 +  if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
   1.927 +    NS_ConvertUTF16toUTF8  prefName(someData);
   1.928 +    // Look through the cipher table and set according to pref setting
   1.929 +    for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
   1.930 +      if (prefName.Equals(cp->pref)) {
   1.931 +        bool cipherEnabled = Preferences::GetBool(cp->pref,
   1.932 +                                                  cp->enabledByDefault);
   1.933 +        SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
   1.934 +        SSL_ClearSessionCache();
   1.935 +        break;
   1.936 +      }
   1.937 +    }
   1.938 +  }
   1.939 +  return NS_OK;
   1.940 +}
   1.941 +
   1.942 +} // anonymous namespace
   1.943 +
   1.944 +// Caller must hold a lock on nsNSSComponent::mutex when calling this function
   1.945 +void nsNSSComponent::setValidationOptions(bool isInitialSetting,
   1.946 +                                          const MutexAutoLock& lock)
   1.947 +{
   1.948 +  // This preference controls whether we do OCSP fetching and does not affect
   1.949 +  // OCSP stapling.
   1.950 +  // 0 = disabled, 1 = enabled
   1.951 +  int32_t ocspEnabled = Preferences::GetInt("security.OCSP.enabled",
   1.952 +                                            OCSP_ENABLED_DEFAULT);
   1.953 +
   1.954 +  bool ocspRequired = ocspEnabled &&
   1.955 +    Preferences::GetBool("security.OCSP.require", false);
   1.956 +
   1.957 +  // We measure the setting of the pref at startup only to minimize noise by
   1.958 +  // addons that may muck with the settings, though it probably doesn't matter.
   1.959 +  if (isInitialSetting) {
   1.960 +    Telemetry::Accumulate(Telemetry::CERT_OCSP_ENABLED, ocspEnabled);
   1.961 +    Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
   1.962 +  }
   1.963 +
   1.964 +#ifndef NSS_NO_LIBPKIX
   1.965 +  bool crlDownloading = Preferences::GetBool("security.CRL_download.enabled",
   1.966 +                                             false);
   1.967 +  bool aiaDownloadEnabled =
   1.968 +    Preferences::GetBool("security.missing_cert_download.enabled", false);
   1.969 +
   1.970 +#endif
   1.971 +  bool ocspStaplingEnabled = Preferences::GetBool("security.ssl.enable_ocsp_stapling",
   1.972 +                                                  true);
   1.973 +  PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
   1.974 +  PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
   1.975 +
   1.976 +  CertVerifier::implementation_config certVerifierImplementation
   1.977 +    = CertVerifier::classic;
   1.978 +
   1.979 +  // The mozilla::pkix pref overrides the libpkix pref
   1.980 +  if (Preferences::GetBool("security.use_mozillapkix_verification", true)) {
   1.981 +    certVerifierImplementation = CertVerifier::mozillapkix;
   1.982 +  } else {
   1.983 +#ifndef NSS_NO_LIBPKIX
   1.984 +  if (Preferences::GetBool("security.use_libpkix_verification", false)) {
   1.985 +    certVerifierImplementation = CertVerifier::libpkix;
   1.986 +  }
   1.987 +#endif
   1.988 +  }
   1.989 +
   1.990 +  if (isInitialSetting) {
   1.991 +    if (certVerifierImplementation == CertVerifier::classic) {
   1.992 +      Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 1);
   1.993 +#ifndef NSS_NO_LIBPKIX
   1.994 +    } else if (certVerifierImplementation == CertVerifier::libpkix) {
   1.995 +      Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 2);
   1.996 +#endif
   1.997 +    } else if (certVerifierImplementation == CertVerifier::mozillapkix) {
   1.998 +      Telemetry::Accumulate(Telemetry::CERT_VALIDATION_LIBRARY, 3);
   1.999 +    }
  1.1000 +  }
  1.1001 +
  1.1002 +  // Default pinning enforcement level is disabled.
  1.1003 +  CertVerifier::pinning_enforcement_config
  1.1004 +    pinningEnforcementLevel =
  1.1005 +      static_cast<CertVerifier::pinning_enforcement_config>
  1.1006 +        (Preferences::GetInt("security.cert_pinning.enforcement_level",
  1.1007 +                             CertVerifier::pinningDisabled));
  1.1008 +
  1.1009 +  CertVerifier::ocsp_download_config odc;
  1.1010 +  CertVerifier::ocsp_strict_config osc;
  1.1011 +  CertVerifier::ocsp_get_config ogc;
  1.1012 +
  1.1013 +  SetClassicOCSPBehaviorFromPrefs(&odc, &osc, &ogc, lock);
  1.1014 +  mDefaultCertVerifier = new SharedCertVerifier(
  1.1015 +      certVerifierImplementation,
  1.1016 +#ifndef NSS_NO_LIBPKIX
  1.1017 +      aiaDownloadEnabled ?
  1.1018 +        CertVerifier::missing_cert_download_on : CertVerifier::missing_cert_download_off,
  1.1019 +      crlDownloading ?
  1.1020 +        CertVerifier::crl_download_allowed : CertVerifier::crl_local_only,
  1.1021 +#endif
  1.1022 +      odc, osc, ogc, pinningEnforcementLevel);
  1.1023 +
  1.1024 +  // mozilla::pkix has its own OCSP cache, so disable the NSS cache
  1.1025 +  // if appropriate.
  1.1026 +  if (certVerifierImplementation == CertVerifier::mozillapkix) {
  1.1027 +    // Using -1 disables the cache. The other arguments are the default
  1.1028 +    // values and aren't exposed by the API.
  1.1029 +    CERT_OCSPCacheSettings(-1, 1*60*60L, 24*60*60L);
  1.1030 +  } else {
  1.1031 +    // Using 1000 enables the cache with the default size of 1000. Again,
  1.1032 +    // these values are not exposed by the API.
  1.1033 +    CERT_OCSPCacheSettings(1000, 1*60*60L, 24*60*60L);
  1.1034 +  }
  1.1035 +
  1.1036 +  CERT_ClearOCSPCache();
  1.1037 +}
  1.1038 +
  1.1039 +// Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
  1.1040 +// TLS 1.2 (max) when the prefs aren't set or set to invalid values.
  1.1041 +nsresult
  1.1042 +nsNSSComponent::setEnabledTLSVersions()
  1.1043 +{
  1.1044 +  // keep these values in sync with security-prefs.js
  1.1045 +  static const int32_t PSM_DEFAULT_MIN_TLS_VERSION = 1;
  1.1046 +  static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 3;
  1.1047 +
  1.1048 +  int32_t minVersion = Preferences::GetInt("security.tls.version.min",
  1.1049 +                                           PSM_DEFAULT_MIN_TLS_VERSION);
  1.1050 +  int32_t maxVersion = Preferences::GetInt("security.tls.version.max",
  1.1051 +                                           PSM_DEFAULT_MAX_TLS_VERSION);
  1.1052 +
  1.1053 +  // 0 means SSL 3.0, 1 means TLS 1.0, 2 means TLS 1.1, etc.
  1.1054 +  minVersion += SSL_LIBRARY_VERSION_3_0;
  1.1055 +  maxVersion += SSL_LIBRARY_VERSION_3_0;
  1.1056 +
  1.1057 +  SSLVersionRange range = { (uint16_t) minVersion, (uint16_t) maxVersion };
  1.1058 +
  1.1059 +  if (minVersion != (int32_t) range.min || // prevent truncation
  1.1060 +      maxVersion != (int32_t) range.max || // prevent truncation
  1.1061 +      SSL_VersionRangeSetDefault(ssl_variant_stream, &range) != SECSuccess) {
  1.1062 +    range.min = SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MIN_TLS_VERSION;
  1.1063 +    range.max = SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MAX_TLS_VERSION;
  1.1064 +    if (SSL_VersionRangeSetDefault(ssl_variant_stream, &range)
  1.1065 +          != SECSuccess) {
  1.1066 +      return NS_ERROR_UNEXPECTED;
  1.1067 +    }
  1.1068 +  }
  1.1069 +
  1.1070 +  return NS_OK;
  1.1071 +}
  1.1072 +
  1.1073 +static nsresult
  1.1074 +GetNSSProfilePath(nsAutoCString& aProfilePath)
  1.1075 +{
  1.1076 +  aProfilePath.Truncate();
  1.1077 +  const char* dbDirOverride = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
  1.1078 +  if (dbDirOverride && strlen(dbDirOverride) > 0) {
  1.1079 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
  1.1080 +           ("Using specified MOZPSM_NSSDBDIR_OVERRIDE as NSS DB dir: %s\n",
  1.1081 +            dbDirOverride));
  1.1082 +    aProfilePath.Assign(dbDirOverride);
  1.1083 +    return NS_OK;
  1.1084 +  }
  1.1085 +
  1.1086 +  nsCOMPtr<nsIFile> profileFile;
  1.1087 +  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
  1.1088 +                                       getter_AddRefs(profileFile));
  1.1089 +  if (NS_FAILED(rv)) {
  1.1090 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1.1091 +           ("Unable to get profile directory - continuing with no NSS DB\n"));
  1.1092 +    return NS_OK;
  1.1093 +  }
  1.1094 +
  1.1095 +#if defined(XP_WIN)
  1.1096 +  // Native path will drop Unicode characters that cannot be mapped to system's
  1.1097 +  // codepage, using short (canonical) path as workaround.
  1.1098 +  nsCOMPtr<nsILocalFileWin> profileFileWin(do_QueryInterface(profileFile));
  1.1099 +  if (!profileFileWin) {
  1.1100 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1.1101 +           ("Could not get nsILocalFileWin for profile directory.\n"));
  1.1102 +    return NS_ERROR_FAILURE;
  1.1103 +  }
  1.1104 +  rv = profileFileWin->GetNativeCanonicalPath(aProfilePath);
  1.1105 +#else
  1.1106 +  rv = profileFile->GetNativePath(aProfilePath);
  1.1107 +#endif
  1.1108 +  if (NS_FAILED(rv)) {
  1.1109 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
  1.1110 +           ("Could not get native path for profile directory.\n"));
  1.1111 +    return rv;
  1.1112 +  }
  1.1113 +
  1.1114 +  return NS_OK;
  1.1115 +}
  1.1116 +
  1.1117 +nsresult
  1.1118 +nsNSSComponent::InitializeNSS()
  1.1119 +{
  1.1120 +  // Can be called both during init and profile change.
  1.1121 +  // Needs mutex protection.
  1.1122 +
  1.1123 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::InitializeNSS\n"));
  1.1124 +
  1.1125 +  static_assert(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
  1.1126 +                nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
  1.1127 +                nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
  1.1128 +                nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
  1.1129 +                "You must update the values in nsINSSErrorsService.idl");
  1.1130 +
  1.1131 +  MutexAutoLock lock(mutex);
  1.1132 +
  1.1133 +  if (mNSSInitialized) {
  1.1134 +    PR_ASSERT(!"Trying to initialize NSS twice"); // We should never try to
  1.1135 +                                                  // initialize NSS more than
  1.1136 +                                                  // once in a process.
  1.1137 +    return NS_ERROR_FAILURE;
  1.1138 +  }
  1.1139 +
  1.1140 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization beginning\n"));
  1.1141 +
  1.1142 +  // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
  1.1143 +  // but affects only static data.
  1.1144 +  // If we could assume i18n will not change between profiles, one call per application
  1.1145 +  // run were sufficient. As I can't predict what happens in the future, let's repeat
  1.1146 +  // this call for every re-init of NSS.
  1.1147 +
  1.1148 +  ConfigureInternalPKCS11Token();
  1.1149 +
  1.1150 +  nsAutoCString profileStr;
  1.1151 +  nsresult rv = GetNSSProfilePath(profileStr);
  1.1152 +  if (NS_FAILED(rv)) {
  1.1153 +    nsPSMInitPanic::SetPanic();
  1.1154 +    return NS_ERROR_NOT_AVAILABLE;
  1.1155 +  }
  1.1156 +
  1.1157 +  SECStatus init_rv = SECFailure;
  1.1158 +  bool nocertdb = Preferences::GetBool("security.nocertdb", SECURITY_NOCERTDB_DEFAULT);
  1.1159 +  
  1.1160 +  if (!nocertdb && !profileStr.IsEmpty()) {
  1.1161 +    // First try to initialize the NSS DB in read/write mode.
  1.1162 +    SECStatus init_rv = ::mozilla::psm::InitializeNSS(profileStr.get(), false);
  1.1163 +    // If that fails, attempt read-only mode.
  1.1164 +    if (init_rv != SECSuccess) {
  1.1165 +      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("could not init NSS r/w in %s\n", profileStr.get()));
  1.1166 +      init_rv = ::mozilla::psm::InitializeNSS(profileStr.get(), true);
  1.1167 +    }
  1.1168 +    if (init_rv != SECSuccess) {
  1.1169 +      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("could not init in r/o either\n"));
  1.1170 +    }
  1.1171 +  }
  1.1172 +  // If we haven't succeeded in initializing the DB in our profile
  1.1173 +  // directory or we don't have a profile at all, or the "security.nocertdb"
  1.1174 +  // pref has been set to "true", attempt to initialize with no DB.
  1.1175 +  if (nocertdb || init_rv != SECSuccess) {
  1.1176 +    init_rv = NSS_NoDB_Init(nullptr);
  1.1177 +  }
  1.1178 +  if (init_rv != SECSuccess) {
  1.1179 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("could not initialize NSS - panicking\n"));
  1.1180 +    nsPSMInitPanic::SetPanic();
  1.1181 +    return NS_ERROR_NOT_AVAILABLE;
  1.1182 +  }
  1.1183 +
  1.1184 +  mNSSInitialized = true;
  1.1185 +
  1.1186 +  PK11_SetPasswordFunc(PK11PasswordPrompt);
  1.1187 +
  1.1188 +  SharedSSLState::GlobalInit();
  1.1189 +
  1.1190 +  // Register an observer so we can inform NSS when these prefs change
  1.1191 +  Preferences::AddStrongObserver(this, "security.");
  1.1192 +
  1.1193 +  SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
  1.1194 +  SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
  1.1195 +
  1.1196 +  rv = setEnabledTLSVersions();
  1.1197 +  if (NS_FAILED(rv)) {
  1.1198 +    nsPSMInitPanic::SetPanic();
  1.1199 +    return NS_ERROR_UNEXPECTED;
  1.1200 +  }
  1.1201 +
  1.1202 +  DisableMD5();
  1.1203 +  // Initialize the certverifier log before calling any functions that library.
  1.1204 +  InitCertVerifierLog();
  1.1205 +  LoadLoadableRoots();
  1.1206 +
  1.1207 +  bool disableSessionIdentifiers =
  1.1208 +    Preferences::GetBool("security.ssl.disable_session_identifiers",
  1.1209 +                         DISABLE_SESSION_IDENTIFIERS_DEFAULT);
  1.1210 +  SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
  1.1211 +  SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
  1.1212 +
  1.1213 +  bool requireSafeNegotiation =
  1.1214 +    Preferences::GetBool("security.ssl.require_safe_negotiation",
  1.1215 +                         REQUIRE_SAFE_NEGOTIATION_DEFAULT);
  1.1216 +  SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
  1.1217 +
  1.1218 +  bool allowUnrestrictedRenego =
  1.1219 +    Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
  1.1220 +                         ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
  1.1221 +  SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
  1.1222 +                       allowUnrestrictedRenego ?
  1.1223 +                         SSL_RENEGOTIATE_UNRESTRICTED :
  1.1224 +                         SSL_RENEGOTIATE_REQUIRES_XTN);
  1.1225 +
  1.1226 +  SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
  1.1227 +                       Preferences::GetBool("security.ssl.enable_false_start",
  1.1228 +                                            FALSE_START_ENABLED_DEFAULT));
  1.1229 +
  1.1230 +  // SSL_ENABLE_NPN and SSL_ENABLE_ALPN also require calling
  1.1231 +  // SSL_SetNextProtoNego in order for the extensions to be negotiated.
  1.1232 +  // WebRTC does not do that so it will not use NPN or ALPN even when these
  1.1233 +  // preferences are true.
  1.1234 +  SSL_OptionSetDefault(SSL_ENABLE_NPN,
  1.1235 +                       Preferences::GetBool("security.ssl.enable_npn",
  1.1236 +                                            NPN_ENABLED_DEFAULT));
  1.1237 +  SSL_OptionSetDefault(SSL_ENABLE_ALPN,
  1.1238 +                       Preferences::GetBool("security.ssl.enable_alpn",
  1.1239 +                                            ALPN_ENABLED_DEFAULT));
  1.1240 +
  1.1241 +  if (NS_FAILED(InitializeCipherSuite())) {
  1.1242 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to initialize cipher suite settings\n"));
  1.1243 +    return NS_ERROR_FAILURE;
  1.1244 +  }
  1.1245 +
  1.1246 +  // dynamic options from prefs
  1.1247 +  setValidationOptions(true, lock);
  1.1248 +
  1.1249 +  mHttpForNSS.initTable();
  1.1250 +  mHttpForNSS.registerHttpClient();
  1.1251 +
  1.1252 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
  1.1253 +  LaunchSmartCardThreads();
  1.1254 +#endif
  1.1255 +
  1.1256 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization done\n"));
  1.1257 +  return NS_OK;
  1.1258 +}
  1.1259 +
  1.1260 +void
  1.1261 +nsNSSComponent::ShutdownNSS()
  1.1262 +{
  1.1263 +  // Can be called both during init and profile change,
  1.1264 +  // needs mutex protection.
  1.1265 +
  1.1266 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ShutdownNSS\n"));
  1.1267 +
  1.1268 +  MutexAutoLock lock(mutex);
  1.1269 +
  1.1270 +  if (mNSSInitialized) {
  1.1271 +    mNSSInitialized = false;
  1.1272 +
  1.1273 +    PK11_SetPasswordFunc((PK11PasswordFunc)nullptr);
  1.1274 +    mHttpForNSS.unregisterHttpClient();
  1.1275 +
  1.1276 +    Preferences::RemoveObserver(this, "security.");
  1.1277 +    if (NS_FAILED(CipherSuiteChangeObserver::StopObserve())) {
  1.1278 +      PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("nsNSSComponent::ShutdownNSS cannot stop observing cipher suite change\n"));
  1.1279 +    }
  1.1280 +
  1.1281 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
  1.1282 +    ShutdownSmartCardThreads();
  1.1283 +#endif
  1.1284 +    SSL_ClearSessionCache();
  1.1285 +    UnloadLoadableRoots();
  1.1286 +#ifndef MOZ_NO_EV_CERTS
  1.1287 +    CleanupIdentityInfo();
  1.1288 +#endif
  1.1289 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
  1.1290 +    mShutdownObjectList->evaporateAllNSSResources();
  1.1291 +    EnsureNSSInitialized(nssShutdown);
  1.1292 +    if (SECSuccess != ::NSS_Shutdown()) {
  1.1293 +      PR_LOG(gPIPNSSLog, PR_LOG_ALWAYS, ("NSS SHUTDOWN FAILURE\n"));
  1.1294 +    }
  1.1295 +    else {
  1.1296 +      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS shutdown =====>> OK <<=====\n"));
  1.1297 +    }
  1.1298 +  }
  1.1299 +}
  1.1300 +
  1.1301 +static const bool SEND_LM_DEFAULT = false;
  1.1302 +
  1.1303 +NS_IMETHODIMP
  1.1304 +nsNSSComponent::Init()
  1.1305 +{
  1.1306 +  // No mutex protection.
  1.1307 +  // Assume Init happens before any concurrency on "this" can start.
  1.1308 +
  1.1309 +  nsresult rv = NS_OK;
  1.1310 +
  1.1311 +  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
  1.1312 +
  1.1313 +  if (!mShutdownObjectList)
  1.1314 +  {
  1.1315 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
  1.1316 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1317 +  }
  1.1318 +
  1.1319 +  rv = InitializePIPNSSBundle();
  1.1320 +  if (NS_FAILED(rv)) {
  1.1321 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to create pipnss bundle.\n"));
  1.1322 +    return rv;
  1.1323 +  }
  1.1324 +
  1.1325 +  // Access our string bundles now, this prevents assertions from I/O
  1.1326 +  // - nsStandardURL not thread-safe
  1.1327 +  // - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
  1.1328 +  // when loading error strings on the SSL threads.
  1.1329 +  {
  1.1330 +    NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
  1.1331 +    nsXPIDLString result;
  1.1332 +    mPIPNSSBundle->GetStringFromName(dummy_name.get(),
  1.1333 +                                     getter_Copies(result));
  1.1334 +    mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
  1.1335 +                                        getter_Copies(result));
  1.1336 +  }
  1.1337 +
  1.1338 +  bool sendLM = Preferences::GetBool("network.ntlm.send-lm-response",
  1.1339 +                                     SEND_LM_DEFAULT);
  1.1340 +  nsNTLMAuthModule::SetSendLM(sendLM);
  1.1341 +
  1.1342 +  // Do that before NSS init, to make sure we won't get unloaded.
  1.1343 +  RegisterObservers();
  1.1344 +
  1.1345 +  rv = InitializeNSS();
  1.1346 +  if (NS_FAILED(rv)) {
  1.1347 +    PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
  1.1348 +
  1.1349 +    DeregisterObservers();
  1.1350 +    mPIPNSSBundle = nullptr;
  1.1351 +    return rv;
  1.1352 +  }
  1.1353 +
  1.1354 +  RememberCertErrorsTable::Init();
  1.1355 +
  1.1356 +  createBackgroundThreads();
  1.1357 +  if (!mCertVerificationThread)
  1.1358 +  {
  1.1359 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
  1.1360 +
  1.1361 +    DeregisterObservers();
  1.1362 +    mPIPNSSBundle = nullptr;
  1.1363 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1364 +  }
  1.1365 +
  1.1366 +  nsCOMPtr<nsIEntropyCollector> ec
  1.1367 +      = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
  1.1368 +
  1.1369 +  nsCOMPtr<nsIBufEntropyCollector> bec;
  1.1370 +
  1.1371 +  if (ec) {
  1.1372 +    bec = do_QueryInterface(ec);
  1.1373 +  }
  1.1374 +
  1.1375 +  NS_ASSERTION(bec, "No buffering entropy collector.  "
  1.1376 +                    "This means no entropy will be collected.");
  1.1377 +  if (bec) {
  1.1378 +    bec->ForwardTo(this);
  1.1379 +  }
  1.1380 +
  1.1381 +  return rv;
  1.1382 +}
  1.1383 +
  1.1384 +// nsISupports Implementation for the class
  1.1385 +NS_IMPL_ISUPPORTS(nsNSSComponent,
  1.1386 +                  nsISignatureVerifier,
  1.1387 +                  nsIEntropyCollector,
  1.1388 +                  nsINSSComponent,
  1.1389 +                  nsIObserver,
  1.1390 +                  nsISupportsWeakReference)
  1.1391 +
  1.1392 +
  1.1393 +// Callback functions for decoder. For now, use empty/default functions.
  1.1394 +static void
  1.1395 +ContentCallback(void* arg, const char* buf, unsigned long len)
  1.1396 +{
  1.1397 +}
  1.1398 +
  1.1399 +static PK11SymKey*
  1.1400 +GetDecryptKeyCallback(void* arg, SECAlgorithmID* algid)
  1.1401 +{
  1.1402 +  return nullptr;
  1.1403 +}
  1.1404 +
  1.1405 +static PRBool
  1.1406 +DecryptionAllowedCallback(SECAlgorithmID* algid, PK11SymKey* bulkkey)
  1.1407 +{
  1.1408 +  return SECMIME_DecryptionAllowed(algid, bulkkey);
  1.1409 +}
  1.1410 +
  1.1411 +static void*
  1.1412 +GetPasswordKeyCallback(void* arg, void* handle)
  1.1413 +{
  1.1414 +  return nullptr;
  1.1415 +}
  1.1416 +
  1.1417 +NS_IMETHODIMP
  1.1418 +nsNSSComponent::VerifySignature(const char* aRSABuf, uint32_t aRSABufLen,
  1.1419 +                                const char* aPlaintext, uint32_t aPlaintextLen,
  1.1420 +                                int32_t* aErrorCode,
  1.1421 +                                nsICertificatePrincipal** aPrincipal)
  1.1422 +{
  1.1423 +  if (!aPrincipal || !aErrorCode) {
  1.1424 +    return NS_ERROR_NULL_POINTER;
  1.1425 +  }
  1.1426 +
  1.1427 +  *aErrorCode = 0;
  1.1428 +  *aPrincipal = nullptr;
  1.1429 +
  1.1430 +  nsNSSShutDownPreventionLock locker;
  1.1431 +  ScopedSEC_PKCS7ContentInfo p7_info;
  1.1432 +  unsigned char hash[SHA1_LENGTH];
  1.1433 +
  1.1434 +  SECItem item;
  1.1435 +  item.type = siEncodedCertBuffer;
  1.1436 +  item.data = (unsigned char*)aRSABuf;
  1.1437 +  item.len = aRSABufLen;
  1.1438 +  p7_info = SEC_PKCS7DecodeItem(&item,
  1.1439 +                                ContentCallback, nullptr,
  1.1440 +                                GetPasswordKeyCallback, nullptr,
  1.1441 +                                GetDecryptKeyCallback, nullptr,
  1.1442 +                                DecryptionAllowedCallback);
  1.1443 +
  1.1444 +  if (!p7_info) {
  1.1445 +    return NS_ERROR_FAILURE;
  1.1446 +  }
  1.1447 +
  1.1448 +  // Make sure we call SEC_PKCS7DestroyContentInfo after this point;
  1.1449 +  // otherwise we leak data in p7_info
  1.1450 +
  1.1451 +  //-- If a plaintext was provided, hash it.
  1.1452 +  SECItem digest;
  1.1453 +  digest.data = nullptr;
  1.1454 +  digest.len = 0;
  1.1455 +
  1.1456 +  if (aPlaintext) {
  1.1457 +    HASHContext* hash_ctxt;
  1.1458 +    uint32_t hashLen = 0;
  1.1459 +
  1.1460 +    hash_ctxt = HASH_Create(HASH_AlgSHA1);
  1.1461 +    HASH_Begin(hash_ctxt);
  1.1462 +    HASH_Update(hash_ctxt,(const unsigned char*)aPlaintext, aPlaintextLen);
  1.1463 +    HASH_End(hash_ctxt, hash, &hashLen, SHA1_LENGTH);
  1.1464 +    HASH_Destroy(hash_ctxt);
  1.1465 +
  1.1466 +    digest.data = hash;
  1.1467 +    digest.len = SHA1_LENGTH;
  1.1468 +  }
  1.1469 +
  1.1470 +  //-- Verify signature
  1.1471 +  bool rv = SEC_PKCS7VerifyDetachedSignature(p7_info, certUsageObjectSigner,
  1.1472 +                                               &digest, HASH_AlgSHA1, false);
  1.1473 +  if (!rv) {
  1.1474 +    *aErrorCode = PR_GetError();
  1.1475 +  }
  1.1476 +
  1.1477 +  // Get the signing cert //
  1.1478 +  CERTCertificate* cert = p7_info->content.signedData->signerInfos[0]->cert;
  1.1479 +  nsresult rv2 = NS_OK;
  1.1480 +  if (cert) {
  1.1481 +    // Use |do { } while (0);| as a "more C++-ish" thing than goto;
  1.1482 +    // this way we don't have to worry about goto across variable
  1.1483 +    // declarations.  We have no loops in this code, so it's OK.
  1.1484 +    do {
  1.1485 +      nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
  1.1486 +      if (!pCert) {
  1.1487 +        rv2 = NS_ERROR_OUT_OF_MEMORY;
  1.1488 +        break;
  1.1489 +      }
  1.1490 +
  1.1491 +      //-- Create a certificate principal with id and organization data
  1.1492 +      nsAutoString fingerprint;
  1.1493 +      rv2 = pCert->GetSha1Fingerprint(fingerprint);
  1.1494 +      if (NS_FAILED(rv2)) {
  1.1495 +        break;
  1.1496 +      }
  1.1497 +      nsAutoString orgName;
  1.1498 +      rv2 = pCert->GetOrganization(orgName);
  1.1499 +      if (NS_FAILED(rv2)) {
  1.1500 +        break;
  1.1501 +      }
  1.1502 +      nsAutoString subjectName;
  1.1503 +      rv2 = pCert->GetSubjectName(subjectName);
  1.1504 +      if (NS_FAILED(rv2)) {
  1.1505 +        break;
  1.1506 +      }
  1.1507 +
  1.1508 +      nsCOMPtr<nsICertificatePrincipal> certPrincipal =
  1.1509 +        new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
  1.1510 +                                   NS_ConvertUTF16toUTF8(subjectName),
  1.1511 +                                   NS_ConvertUTF16toUTF8(orgName),
  1.1512 +                                   pCert);
  1.1513 +
  1.1514 +      certPrincipal.swap(*aPrincipal);
  1.1515 +    } while (0);
  1.1516 +  }
  1.1517 +
  1.1518 +  return rv2;
  1.1519 +}
  1.1520 +
  1.1521 +NS_IMETHODIMP
  1.1522 +nsNSSComponent::RandomUpdate(void* entropy, int32_t bufLen)
  1.1523 +{
  1.1524 +  nsNSSShutDownPreventionLock locker;
  1.1525 +
  1.1526 +  // Asynchronous event happening often,
  1.1527 +  // must not interfere with initialization or profile switch.
  1.1528 +
  1.1529 +  MutexAutoLock lock(mutex);
  1.1530 +
  1.1531 +  if (!mNSSInitialized)
  1.1532 +      return NS_ERROR_NOT_INITIALIZED;
  1.1533 +
  1.1534 +  PK11_RandomUpdate(entropy, bufLen);
  1.1535 +  return NS_OK;
  1.1536 +}
  1.1537 +
  1.1538 +static const char* const PROFILE_CHANGE_NET_TEARDOWN_TOPIC
  1.1539 +  = "profile-change-net-teardown";
  1.1540 +static const char* const PROFILE_CHANGE_NET_RESTORE_TOPIC
  1.1541 +  = "profile-change-net-restore";
  1.1542 +static const char* const PROFILE_CHANGE_TEARDOWN_TOPIC
  1.1543 +  = "profile-change-teardown";
  1.1544 +static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
  1.1545 +static const char* const PROFILE_DO_CHANGE_TOPIC = "profile-do-change";
  1.1546 +
  1.1547 +NS_IMETHODIMP
  1.1548 +nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
  1.1549 +                        const char16_t* someData)
  1.1550 +{
  1.1551 +  if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
  1.1552 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
  1.1553 +    DoProfileChangeTeardown(aSubject);
  1.1554 +  }
  1.1555 +  else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
  1.1556 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
  1.1557 +    DoProfileBeforeChange(aSubject);
  1.1558 +  }
  1.1559 +  else if (nsCRT::strcmp(aTopic, PROFILE_DO_CHANGE_TOPIC) == 0) {
  1.1560 +    if (someData && NS_LITERAL_STRING("startup").Equals(someData)) {
  1.1561 +      // The application is initializing against a known profile directory for
  1.1562 +      // the first time during process execution.
  1.1563 +      // However, earlier code execution might have already triggered NSS init.
  1.1564 +      // We must ensure that NSS gets shut down prior to any attempt to init
  1.1565 +      // it again. We use the same cleanup functionality used when switching
  1.1566 +      // profiles. The order of function calls must correspond to the order
  1.1567 +      // of notifications sent by Profile Manager (nsProfile).
  1.1568 +      DoProfileChangeNetTeardown();
  1.1569 +      DoProfileChangeTeardown(aSubject);
  1.1570 +      DoProfileBeforeChange(aSubject);
  1.1571 +      DoProfileChangeNetRestore();
  1.1572 +    }
  1.1573 +
  1.1574 +    bool needsInit = true;
  1.1575 +
  1.1576 +    {
  1.1577 +      MutexAutoLock lock(mutex);
  1.1578 +
  1.1579 +      if (mNSSInitialized) {
  1.1580 +        // We have already initialized NSS before the profile came up,
  1.1581 +        // no need to do it again
  1.1582 +        needsInit = false;
  1.1583 +      }
  1.1584 +    }
  1.1585 +
  1.1586 +    if (needsInit) {
  1.1587 +      if (NS_FAILED(InitializeNSS())) {
  1.1588 +        PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS after profile switch.\n"));
  1.1589 +      }
  1.1590 +    }
  1.1591 +  }
  1.1592 +  else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
  1.1593 +
  1.1594 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: XPCom shutdown observed\n"));
  1.1595 +
  1.1596 +    // Cleanup code that requires services, it's too late in destructor.
  1.1597 +
  1.1598 +    nsCOMPtr<nsIEntropyCollector> ec
  1.1599 +        = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
  1.1600 +
  1.1601 +    if (ec) {
  1.1602 +      nsCOMPtr<nsIBufEntropyCollector> bec
  1.1603 +        = do_QueryInterface(ec);
  1.1604 +      if (bec) {
  1.1605 +        bec->DontForward();
  1.1606 +      }
  1.1607 +    }
  1.1608 +  }
  1.1609 +  else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
  1.1610 +    nsNSSShutDownPreventionLock locker;
  1.1611 +    bool clearSessionCache = true;
  1.1612 +    NS_ConvertUTF16toUTF8  prefName(someData);
  1.1613 +
  1.1614 +    if (prefName.Equals("security.tls.version.min") ||
  1.1615 +        prefName.Equals("security.tls.version.max")) {
  1.1616 +      (void) setEnabledTLSVersions();
  1.1617 +    } else if (prefName.Equals("security.ssl.disable_session_identifiers")) {
  1.1618 +      bool disableSessionIdentifiers =
  1.1619 +        Preferences::GetBool("security.ssl.disable_session_identifiers",
  1.1620 +                             DISABLE_SESSION_IDENTIFIERS_DEFAULT);
  1.1621 +      SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
  1.1622 +      SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
  1.1623 +    } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
  1.1624 +      bool requireSafeNegotiation =
  1.1625 +        Preferences::GetBool("security.ssl.require_safe_negotiation",
  1.1626 +                             REQUIRE_SAFE_NEGOTIATION_DEFAULT);
  1.1627 +      SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
  1.1628 +    } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
  1.1629 +      bool allowUnrestrictedRenego =
  1.1630 +        Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
  1.1631 +                             ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
  1.1632 +      SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
  1.1633 +                           allowUnrestrictedRenego ?
  1.1634 +                             SSL_RENEGOTIATE_UNRESTRICTED :
  1.1635 +                             SSL_RENEGOTIATE_REQUIRES_XTN);
  1.1636 +    } else if (prefName.Equals("security.ssl.enable_false_start")) {
  1.1637 +      SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
  1.1638 +                           Preferences::GetBool("security.ssl.enable_false_start",
  1.1639 +                                                FALSE_START_ENABLED_DEFAULT));
  1.1640 +    } else if (prefName.Equals("security.ssl.enable_npn")) {
  1.1641 +      SSL_OptionSetDefault(SSL_ENABLE_NPN,
  1.1642 +                           Preferences::GetBool("security.ssl.enable_npn",
  1.1643 +                                                NPN_ENABLED_DEFAULT));
  1.1644 +    } else if (prefName.Equals("security.ssl.enable_alpn")) {
  1.1645 +      SSL_OptionSetDefault(SSL_ENABLE_ALPN,
  1.1646 +                           Preferences::GetBool("security.ssl.enable_alpn",
  1.1647 +                                                ALPN_ENABLED_DEFAULT));
  1.1648 +    } else if (prefName.Equals("security.OCSP.enabled")
  1.1649 +               || prefName.Equals("security.CRL_download.enabled")
  1.1650 +               || prefName.Equals("security.fresh_revocation_info.require")
  1.1651 +               || prefName.Equals("security.missing_cert_download.enabled")
  1.1652 +               || prefName.Equals("security.OCSP.require")
  1.1653 +               || prefName.Equals("security.OCSP.GET.enabled")
  1.1654 +               || prefName.Equals("security.ssl.enable_ocsp_stapling")
  1.1655 +               || prefName.Equals("security.use_mozillapkix_verification")
  1.1656 +               || prefName.Equals("security.use_libpkix_verification")
  1.1657 +               || prefName.Equals("security.cert_pinning.enforcement_level")) {
  1.1658 +      MutexAutoLock lock(mutex);
  1.1659 +      setValidationOptions(false, lock);
  1.1660 +    } else if (prefName.Equals("network.ntlm.send-lm-response")) {
  1.1661 +      bool sendLM = Preferences::GetBool("network.ntlm.send-lm-response",
  1.1662 +                                         SEND_LM_DEFAULT);
  1.1663 +      nsNTLMAuthModule::SetSendLM(sendLM);
  1.1664 +      clearSessionCache = false;
  1.1665 +    } else {
  1.1666 +      clearSessionCache = false;
  1.1667 +    }
  1.1668 +    if (clearSessionCache)
  1.1669 +      SSL_ClearSessionCache();
  1.1670 +  }
  1.1671 +  else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
  1.1672 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
  1.1673 +    DoProfileChangeNetTeardown();
  1.1674 +  }
  1.1675 +  else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_RESTORE_TOPIC) == 0) {
  1.1676 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network restore topic\n"));
  1.1677 +    DoProfileChangeNetRestore();
  1.1678 +  }
  1.1679 +
  1.1680 +  return NS_OK;
  1.1681 +}
  1.1682 +
  1.1683 +/*static*/ nsresult
  1.1684 +nsNSSComponent::GetNewPrompter(nsIPrompt** result)
  1.1685 +{
  1.1686 +  NS_ENSURE_ARG_POINTER(result);
  1.1687 +  *result = nullptr;
  1.1688 +
  1.1689 +  if (!NS_IsMainThread()) {
  1.1690 +    NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
  1.1691 +    return NS_ERROR_NOT_SAME_THREAD;
  1.1692 +  }
  1.1693 +
  1.1694 +  nsresult rv;
  1.1695 +  nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1.1696 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1697 +
  1.1698 +  rv = wwatch->GetNewPrompter(0, result);
  1.1699 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1700 +
  1.1701 +  return rv;
  1.1702 +}
  1.1703 +
  1.1704 +/*static*/ nsresult
  1.1705 +nsNSSComponent::ShowAlertWithConstructedString(const nsString& message)
  1.1706 +{
  1.1707 +  nsCOMPtr<nsIPrompt> prompter;
  1.1708 +  nsresult rv = GetNewPrompter(getter_AddRefs(prompter));
  1.1709 +  if (prompter) {
  1.1710 +    nsPSMUITracker tracker;
  1.1711 +    if (tracker.isUIForbidden()) {
  1.1712 +      NS_WARNING("Suppressing alert because PSM UI is forbidden");
  1.1713 +      rv = NS_ERROR_UNEXPECTED;
  1.1714 +    } else {
  1.1715 +      rv = prompter->Alert(nullptr, message.get());
  1.1716 +    }
  1.1717 +  }
  1.1718 +  return rv;
  1.1719 +}
  1.1720 +
  1.1721 +NS_IMETHODIMP
  1.1722 +nsNSSComponent::ShowAlertFromStringBundle(const char* messageID)
  1.1723 +{
  1.1724 +  nsString message;
  1.1725 +  nsresult rv;
  1.1726 +
  1.1727 +  rv = GetPIPNSSBundleString(messageID, message);
  1.1728 +  if (NS_FAILED(rv)) {
  1.1729 +    NS_ERROR("GetPIPNSSBundleString failed");
  1.1730 +    return rv;
  1.1731 +  }
  1.1732 +
  1.1733 +  return ShowAlertWithConstructedString(message);
  1.1734 +}
  1.1735 +
  1.1736 +nsresult nsNSSComponent::LogoutAuthenticatedPK11()
  1.1737 +{
  1.1738 +  nsCOMPtr<nsICertOverrideService> icos =
  1.1739 +    do_GetService("@mozilla.org/security/certoverride;1");
  1.1740 +  if (icos) {
  1.1741 +    icos->ClearValidityOverride(
  1.1742 +            NS_LITERAL_CSTRING("all:temporary-certificates"),
  1.1743 +            0);
  1.1744 +  }
  1.1745 +
  1.1746 +  nsClientAuthRememberService::ClearAllRememberedDecisions();
  1.1747 +
  1.1748 +  return mShutdownObjectList->doPK11Logout();
  1.1749 +}
  1.1750 +
  1.1751 +nsresult
  1.1752 +nsNSSComponent::RegisterObservers()
  1.1753 +{
  1.1754 +  // Happens once during init only, no mutex protection.
  1.1755 +
  1.1756 +  nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
  1.1757 +  NS_ASSERTION(observerService, "could not get observer service");
  1.1758 +  if (observerService) {
  1.1759 +    mObserversRegistered = true;
  1.1760 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: adding observers\n"));
  1.1761 +
  1.1762 +    // We are a service.
  1.1763 +    // Once we are loaded, don't allow being removed from memory.
  1.1764 +    // This makes sense, as initializing NSS is expensive.
  1.1765 +
  1.1766 +    // By using false for parameter ownsWeak in AddObserver,
  1.1767 +    // we make sure that we won't get unloaded until the application shuts down.
  1.1768 +
  1.1769 +    observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
  1.1770 +
  1.1771 +    observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC, false);
  1.1772 +    observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
  1.1773 +    observerService->AddObserver(this, PROFILE_DO_CHANGE_TOPIC, false);
  1.1774 +    observerService->AddObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC, false);
  1.1775 +    observerService->AddObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC, false);
  1.1776 +  }
  1.1777 +  return NS_OK;
  1.1778 +}
  1.1779 +
  1.1780 +nsresult
  1.1781 +nsNSSComponent::DeregisterObservers()
  1.1782 +{
  1.1783 +  if (!mObserversRegistered)
  1.1784 +    return NS_OK;
  1.1785 +
  1.1786 +  nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
  1.1787 +  NS_ASSERTION(observerService, "could not get observer service");
  1.1788 +  if (observerService) {
  1.1789 +    mObserversRegistered = false;
  1.1790 +    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n"));
  1.1791 +
  1.1792 +    observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
  1.1793 +
  1.1794 +    observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
  1.1795 +    observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
  1.1796 +    observerService->RemoveObserver(this, PROFILE_DO_CHANGE_TOPIC);
  1.1797 +    observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC);
  1.1798 +    observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC);
  1.1799 +  }
  1.1800 +  return NS_OK;
  1.1801 +}
  1.1802 +
  1.1803 +void
  1.1804 +nsNSSComponent::DoProfileChangeNetTeardown()
  1.1805 +{
  1.1806 +  if (mCertVerificationThread)
  1.1807 +    mCertVerificationThread->requestExit();
  1.1808 +  mIsNetworkDown = true;
  1.1809 +}
  1.1810 +
  1.1811 +void
  1.1812 +nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
  1.1813 +{
  1.1814 +  mShutdownObjectList->ifPossibleDisallowUI();
  1.1815 +}
  1.1816 +
  1.1817 +void
  1.1818 +nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
  1.1819 +{
  1.1820 +  NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
  1.1821 +
  1.1822 +  bool needsCleanup = true;
  1.1823 +
  1.1824 +  {
  1.1825 +    MutexAutoLock lock(mutex);
  1.1826 +
  1.1827 +    if (!mNSSInitialized) {
  1.1828 +      // Make sure we don't try to cleanup if we have already done so.
  1.1829 +      // This makes sure we behave safely, in case we are notified
  1.1830 +      // multiple times.
  1.1831 +      needsCleanup = false;
  1.1832 +    }
  1.1833 +  }
  1.1834 +
  1.1835 +  if (needsCleanup) {
  1.1836 +    ShutdownNSS();
  1.1837 +  }
  1.1838 +  mShutdownObjectList->allowUI();
  1.1839 +}
  1.1840 +
  1.1841 +void
  1.1842 +nsNSSComponent::DoProfileChangeNetRestore()
  1.1843 +{
  1.1844 +  // XXX this doesn't work well, since nothing expects null pointers
  1.1845 +  deleteBackgroundThreads();
  1.1846 +  createBackgroundThreads();
  1.1847 +  mIsNetworkDown = false;
  1.1848 +}
  1.1849 +
  1.1850 +NS_IMETHODIMP
  1.1851 +nsNSSComponent::IsNSSInitialized(bool* initialized)
  1.1852 +{
  1.1853 +  MutexAutoLock lock(mutex);
  1.1854 +  *initialized = mNSSInitialized;
  1.1855 +  return NS_OK;
  1.1856 +}
  1.1857 +
  1.1858 +SharedCertVerifier::~SharedCertVerifier() { }
  1.1859 +
  1.1860 +TemporaryRef<SharedCertVerifier>
  1.1861 +nsNSSComponent::GetDefaultCertVerifier()
  1.1862 +{
  1.1863 +  MutexAutoLock lock(mutex);
  1.1864 +  MOZ_ASSERT(mNSSInitialized);
  1.1865 +  return mDefaultCertVerifier;
  1.1866 +}
  1.1867 +
  1.1868 +namespace mozilla { namespace psm {
  1.1869 +
  1.1870 +TemporaryRef<SharedCertVerifier>
  1.1871 +GetDefaultCertVerifier()
  1.1872 +{
  1.1873 +  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1.1874 +
  1.1875 +  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
  1.1876 +  RefPtr<SharedCertVerifier> certVerifier;
  1.1877 +  if (nssComponent) {
  1.1878 +    return nssComponent->GetDefaultCertVerifier();
  1.1879 +  }
  1.1880 +
  1.1881 +  return nullptr;
  1.1882 +}
  1.1883 +
  1.1884 +} } // namespace mozilla::psm
  1.1885 +
  1.1886 +NS_IMPL_ISUPPORTS(PipUIContext, nsIInterfaceRequestor)
  1.1887 +
  1.1888 +PipUIContext::PipUIContext()
  1.1889 +{
  1.1890 +}
  1.1891 +
  1.1892 +PipUIContext::~PipUIContext()
  1.1893 +{
  1.1894 +}
  1.1895 +
  1.1896 +NS_IMETHODIMP
  1.1897 +PipUIContext::GetInterface(const nsIID& uuid, void** result)
  1.1898 +{
  1.1899 +  NS_ENSURE_ARG_POINTER(result);
  1.1900 +  *result = nullptr;
  1.1901 +
  1.1902 +  if (!NS_IsMainThread()) {
  1.1903 +    NS_ERROR("PipUIContext::GetInterface called off the main thread");
  1.1904 +    return NS_ERROR_NOT_SAME_THREAD;
  1.1905 +  }
  1.1906 +
  1.1907 +  if (!uuid.Equals(NS_GET_IID(nsIPrompt)))
  1.1908 +    return NS_ERROR_NO_INTERFACE;
  1.1909 +
  1.1910 +  nsIPrompt* prompt = nullptr;
  1.1911 +  nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
  1.1912 +  *result = prompt;
  1.1913 +  return rv;
  1.1914 +}
  1.1915 +
  1.1916 +nsresult
  1.1917 +getNSSDialogs(void** _result, REFNSIID aIID, const char* contract)
  1.1918 +{
  1.1919 +  if (!NS_IsMainThread()) {
  1.1920 +    NS_ERROR("getNSSDialogs called off the main thread");
  1.1921 +    return NS_ERROR_NOT_SAME_THREAD;
  1.1922 +  }
  1.1923 +
  1.1924 +  nsresult rv;
  1.1925 +
  1.1926 +  nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
  1.1927 +  if (NS_FAILED(rv)) {
  1.1928 +    return rv;
  1.1929 +  }
  1.1930 +
  1.1931 +  rv = svc->QueryInterface(aIID, _result);
  1.1932 +
  1.1933 +  return rv;
  1.1934 +}
  1.1935 +
  1.1936 +nsresult
  1.1937 +setPassword(PK11SlotInfo* slot, nsIInterfaceRequestor* ctx)
  1.1938 +{
  1.1939 +  nsNSSShutDownPreventionLock locker;
  1.1940 +  nsresult rv = NS_OK;
  1.1941 +
  1.1942 +  if (PK11_NeedUserInit(slot)) {
  1.1943 +    nsITokenPasswordDialogs* dialogs;
  1.1944 +    bool canceled;
  1.1945 +    NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot));
  1.1946 +
  1.1947 +    rv = getNSSDialogs((void**)&dialogs,
  1.1948 +                       NS_GET_IID(nsITokenPasswordDialogs),
  1.1949 +                       NS_TOKENPASSWORDSDIALOG_CONTRACTID);
  1.1950 +
  1.1951 +    if (NS_FAILED(rv)) goto loser;
  1.1952 +
  1.1953 +    {
  1.1954 +      nsPSMUITracker tracker;
  1.1955 +      if (tracker.isUIForbidden()) {
  1.1956 +        rv = NS_ERROR_NOT_AVAILABLE;
  1.1957 +      }
  1.1958 +      else {
  1.1959 +        rv = dialogs->SetPassword(ctx,
  1.1960 +                                  tokenName.get(),
  1.1961 +                                  &canceled);
  1.1962 +      }
  1.1963 +    }
  1.1964 +    NS_RELEASE(dialogs);
  1.1965 +    if (NS_FAILED(rv)) goto loser;
  1.1966 +
  1.1967 +    if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
  1.1968 +  }
  1.1969 + loser:
  1.1970 +  return rv;
  1.1971 +}
  1.1972 +
  1.1973 +namespace mozilla {
  1.1974 +namespace psm {
  1.1975 +
  1.1976 +nsresult
  1.1977 +InitializeCipherSuite()
  1.1978 +{
  1.1979 +  NS_ASSERTION(NS_IsMainThread(), "InitializeCipherSuite() can only be accessed in main thread");
  1.1980 +
  1.1981 +  if (NSS_SetDomesticPolicy() != SECSuccess) {
  1.1982 +    return NS_ERROR_FAILURE;
  1.1983 +  }
  1.1984 +
  1.1985 +  // Disable any ciphers that NSS might have enabled by default
  1.1986 +  for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
  1.1987 +    uint16_t cipher_id = SSL_ImplementedCiphers[i];
  1.1988 +    SSL_CipherPrefSetDefault(cipher_id, false);
  1.1989 +  }
  1.1990 +
  1.1991 +  // Now only set SSL/TLS ciphers we knew about at compile time
  1.1992 +  for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
  1.1993 +    bool cipherEnabled = Preferences::GetBool(cp->pref, cp->enabledByDefault);
  1.1994 +    SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
  1.1995 +  }
  1.1996 +
  1.1997 +  // Enable ciphers for PKCS#12
  1.1998 +  SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
  1.1999 +  SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
  1.2000 +  SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
  1.2001 +  SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
  1.2002 +  SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
  1.2003 +  SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
  1.2004 +  SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
  1.2005 +  PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
  1.2006 +
  1.2007 +  // Observe preference change around cipher suite setting.
  1.2008 +  return CipherSuiteChangeObserver::StartObserve();
  1.2009 +}
  1.2010 +
  1.2011 +} // namespace psm
  1.2012 +} // namespace mozilla

mercurial