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