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.

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

mercurial