security/manager/ssl/src/nsNSSComponent.cpp

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

mercurial