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 "CryptoTask.h"
10 #include "EnterpriseRoots.h"
11 #include "ExtendedValidation.h"
12 #include "NSSCertDBTrustDomain.h"
13 #include "SSLTokensCache.h"
14 #include "ScopedNSSTypes.h"
15 #include "SharedSSLState.h"
16 #include "cert.h"
17 #include "cert_storage/src/cert_storage.h"
18 #include "certdb.h"
19 #include "mozilla/AppShutdown.h"
20 #include "mozilla/ArrayUtils.h"
21 #include "mozilla/Assertions.h"
22 #include "mozilla/Casting.h"
23 #include "mozilla/EndianUtils.h"
24 #include "mozilla/PodOperations.h"
25 #include "mozilla/Preferences.h"
26 #include "mozilla/ProfilerLabels.h"
27 #include "mozilla/ProfilerMarkers.h"
28 #include "mozilla/PublicSSL.h"
29 #include "mozilla/ScopeExit.h"
30 #include "mozilla/Services.h"
31 #include "mozilla/StaticMutex.h"
32 #include "mozilla/StaticPtr.h"
33 #include "mozilla/SyncRunnable.h"
34 #include "mozilla/Telemetry.h"
35 #include "mozilla/TimeStamp.h"
36 #include "mozilla/Unused.h"
37 #include "mozilla/Vector.h"
38 #include "mozilla/net/SocketProcessParent.h"
39 #include "mozpkix/pkixnss.h"
40 #include "nsAppDirectoryServiceDefs.h"
41 #include "nsCRT.h"
42 #include "nsClientAuthRemember.h"
43 #include "nsComponentManagerUtils.h"
44 #include "nsDirectoryServiceDefs.h"
45 #include "nsICertOverrideService.h"
46 #include "nsIFile.h"
47 #include "nsILocalFileWin.h"
48 #include "nsIOService.h"
49 #include "nsIObserverService.h"
50 #include "nsIPrompt.h"
51 #include "nsIProperties.h"
52 #include "nsISerialEventTarget.h"
53 #include "nsISiteSecurityService.h"
54 #include "nsITimer.h"
55 #include "nsITokenPasswordDialogs.h"
56 #include "nsIWindowWatcher.h"
57 #include "nsIXULRuntime.h"
58 #include "nsLiteralString.h"
59 #include "nsNSSCertificateDB.h"
60 #include "nsNSSHelper.h"
61 #include "nsNetCID.h"
62 #include "nsPK11TokenDB.h"
63 #include "nsPrintfCString.h"
64 #include "nsServiceManagerUtils.h"
65 #include "nsThreadUtils.h"
66 #include "nsXULAppAPI.h"
67 #include "nss.h"
68 #include "p12plcy.h"
69 #include "pk11pub.h"
70 #include "prmem.h"
71 #include "secerr.h"
72 #include "secmod.h"
73 #include "ssl.h"
74 #include "sslerr.h"
75 #include "sslproto.h"
76 
77 #if defined(XP_LINUX) && !defined(ANDROID)
78 #  include <linux/magic.h>
79 #  include <sys/vfs.h>
80 #endif
81 
82 #ifdef XP_WIN
83 #  include "mozilla/WindowsVersion.h"
84 #  include "nsILocalFileWin.h"
85 
86 #  include "windows.h"  // this needs to be before the following includes
87 #  include "lmcons.h"
88 #  include "sddl.h"
89 #  include "wincrypt.h"
90 #  include "nsIWindowsRegKey.h"
91 #endif
92 
93 using namespace mozilla;
94 using namespace mozilla::psm;
95 
96 LazyLogModule gPIPNSSLog("pipnss");
97 
98 int nsNSSComponent::mInstanceCount = 0;
99 
100 // Forward declaration.
101 nsresult CommonInit();
102 
103 // This function can be called from chrome or content or socket processes
104 // to ensure that NSS is initialized.
EnsureNSSInitializedChromeOrContent()105 bool EnsureNSSInitializedChromeOrContent() {
106   static Atomic<bool> initialized(false);
107 
108   if (initialized) {
109     return true;
110   }
111 
112   // If this is not the main thread (i.e. probably a worker) then forward this
113   // call to the main thread.
114   if (!NS_IsMainThread()) {
115     nsCOMPtr<nsIThread> mainThread;
116     nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
117     if (NS_FAILED(rv)) {
118       return false;
119     }
120 
121     // Forward to the main thread synchronously.
122     mozilla::SyncRunnable::DispatchToThread(
123         mainThread, new SyncRunnable(NS_NewRunnableFunction(
124                         "EnsureNSSInitializedChromeOrContent",
125                         []() { EnsureNSSInitializedChromeOrContent(); })));
126 
127     return initialized;
128   }
129 
130   if (XRE_IsParentProcess()) {
131     nsCOMPtr<nsISupports> nss = do_GetService(PSM_COMPONENT_CONTRACTID);
132     if (!nss) {
133       return false;
134     }
135     initialized = true;
136     return true;
137   }
138 
139   if (NSS_IsInitialized()) {
140     initialized = true;
141     return true;
142   }
143 
144   if (NSS_NoDB_Init(nullptr) != SECSuccess) {
145     return false;
146   }
147 
148   if (XRE_IsSocketProcess()) {
149     if (NS_FAILED(CommonInit())) {
150       return false;
151     }
152     initialized = true;
153     return true;
154   }
155 
156   if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
157     return false;
158   }
159 
160   mozilla::psm::DisableMD5();
161   mozilla::pkix::RegisterErrorTable();
162   initialized = true;
163   return true;
164 }
165 
166 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_DEFAULT = 2000;
167 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX = 5000;
168 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_DEFAULT = 10000;
169 static const uint32_t OCSP_TIMEOUT_MILLISECONDS_HARD_MAX = 20000;
170 
GetRevocationBehaviorFromPrefs(CertVerifier::OcspDownloadConfig * odc,CertVerifier::OcspStrictConfig * osc,uint32_t * certShortLifetimeInDays,TimeDuration & softTimeout,TimeDuration & hardTimeout,const MutexAutoLock &)171 void nsNSSComponent::GetRevocationBehaviorFromPrefs(
172     /*out*/ CertVerifier::OcspDownloadConfig* odc,
173     /*out*/ CertVerifier::OcspStrictConfig* osc,
174     /*out*/ uint32_t* certShortLifetimeInDays,
175     /*out*/ TimeDuration& softTimeout,
176     /*out*/ TimeDuration& hardTimeout, const MutexAutoLock& /*proofOfLock*/) {
177   MOZ_ASSERT(NS_IsMainThread());
178   MOZ_ASSERT(odc);
179   MOZ_ASSERT(osc);
180   MOZ_ASSERT(certShortLifetimeInDays);
181 
182   // 0 = disabled
183   // 1 = enabled for everything (default)
184   // 2 = enabled for EV certificates only
185   int32_t ocspLevel = Preferences::GetInt("security.OCSP.enabled", 1);
186   switch (ocspLevel) {
187     case 0:
188       *odc = CertVerifier::ocspOff;
189       break;
190     case 2:
191       *odc = CertVerifier::ocspEVOnly;
192       break;
193     default:
194       *odc = CertVerifier::ocspOn;
195       break;
196   }
197 
198   *osc = Preferences::GetBool("security.OCSP.require", false)
199              ? CertVerifier::ocspStrict
200              : CertVerifier::ocspRelaxed;
201 
202   // If we pass in just 0 as the second argument to Preferences::GetUint, there
203   // are two function signatures that match (given that 0 can be intepreted as
204   // a null pointer). Thus the compiler will complain without the cast.
205   *certShortLifetimeInDays = Preferences::GetUint(
206       "security.pki.cert_short_lifetime_in_days", static_cast<uint32_t>(0));
207 
208   uint32_t softTimeoutMillis =
209       Preferences::GetUint("security.OCSP.timeoutMilliseconds.soft",
210                            OCSP_TIMEOUT_MILLISECONDS_SOFT_DEFAULT);
211   softTimeoutMillis =
212       std::min(softTimeoutMillis, OCSP_TIMEOUT_MILLISECONDS_SOFT_MAX);
213   softTimeout = TimeDuration::FromMilliseconds(softTimeoutMillis);
214 
215   uint32_t hardTimeoutMillis =
216       Preferences::GetUint("security.OCSP.timeoutMilliseconds.hard",
217                            OCSP_TIMEOUT_MILLISECONDS_HARD_DEFAULT);
218   hardTimeoutMillis =
219       std::min(hardTimeoutMillis, OCSP_TIMEOUT_MILLISECONDS_HARD_MAX);
220   hardTimeout = TimeDuration::FromMilliseconds(hardTimeoutMillis);
221 
222   ClearSSLExternalAndInternalSessionCache();
223 }
224 
nsNSSComponent()225 nsNSSComponent::nsNSSComponent()
226     : mLoadableCertsLoadedMonitor("nsNSSComponent.mLoadableCertsLoadedMonitor"),
227       mLoadableCertsLoaded(false),
228       mLoadableCertsLoadedResult(NS_ERROR_FAILURE),
229       mMutex("nsNSSComponent.mMutex"),
230       mMitmDetecionEnabled(false),
231       mLoadLoadableCertsTaskDispatched(false) {
232   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ctor\n"));
233   MOZ_RELEASE_ASSERT(NS_IsMainThread());
234 
235   MOZ_ASSERT(mInstanceCount == 0,
236              "nsNSSComponent is a singleton, but instantiated multiple times!");
237   ++mInstanceCount;
238 }
239 
~nsNSSComponent()240 nsNSSComponent::~nsNSSComponent() {
241   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor\n"));
242   MOZ_RELEASE_ASSERT(NS_IsMainThread());
243 
244   // All cleanup code requiring services needs to happen in xpcom_shutdown
245 
246   ShutdownNSS();
247   SharedSSLState::GlobalCleanup();
248   RememberCertErrorsTable::Cleanup();
249   --mInstanceCount;
250 
251   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::dtor finished\n"));
252 }
253 
254 #ifdef XP_WIN
GetUserSid(nsAString & sidString)255 static bool GetUserSid(nsAString& sidString) {
256   // UNLEN is the maximum user name length (see Lmcons.h). +1 for the null
257   // terminator.
258   WCHAR lpAccountName[UNLEN + 1];
259   DWORD lcAccountName = sizeof(lpAccountName) / sizeof(lpAccountName[0]);
260   BOOL success = GetUserName(lpAccountName, &lcAccountName);
261   if (!success) {
262     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetUserName failed"));
263     return false;
264   }
265   char sid_buffer[SECURITY_MAX_SID_SIZE];
266   SID* sid = BitwiseCast<SID*, char*>(sid_buffer);
267   DWORD cbSid = ArrayLength(sid_buffer);
268   SID_NAME_USE eUse;
269   // There doesn't appear to be a defined maximum length for the domain name
270   // here. To deal with this, we start with a reasonable buffer length and
271   // see if that works. If it fails and the error indicates insufficient length,
272   // we use the indicated required length and try again.
273   DWORD cchReferencedDomainName = 128;
274   auto ReferencedDomainName(MakeUnique<WCHAR[]>(cchReferencedDomainName));
275   success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
276                               ReferencedDomainName.get(),
277                               &cchReferencedDomainName, &eUse);
278   if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
279     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
280     return false;
281   }
282   if (!success) {
283     ReferencedDomainName = MakeUnique<WCHAR[]>(cchReferencedDomainName);
284     success = LookupAccountName(nullptr, lpAccountName, sid, &cbSid,
285                                 ReferencedDomainName.get(),
286                                 &cchReferencedDomainName, &eUse);
287   }
288   if (!success) {
289     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("LookupAccountName failed"));
290     return false;
291   }
292   LPTSTR StringSid;
293   success = ConvertSidToStringSid(sid, &StringSid);
294   if (!success) {
295     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ConvertSidToStringSid failed"));
296     return false;
297   }
298   sidString.Assign(StringSid);
299   LocalFree(StringSid);
300   return true;
301 }
302 
303 // This is a specialized helper function to read the value of a registry key
304 // that might not be present. If it is present, returns (via the output
305 // parameter) its value. Otherwise, returns the given default value.
306 // This function handles one level of nesting. That is, if the desired value
307 // is actually in a direct child of the given registry key (where the child
308 // and/or the value being sought may not actually be present), this function
309 // will handle that. In the normal case, though, optionalChildName will be
310 // null.
ReadRegKeyValueWithDefault(nsCOMPtr<nsIWindowsRegKey> regKey,uint32_t flags,const wchar_t * optionalChildName,const wchar_t * valueName,uint32_t defaultValue,uint32_t & valueOut)311 static nsresult ReadRegKeyValueWithDefault(nsCOMPtr<nsIWindowsRegKey> regKey,
312                                            uint32_t flags,
313                                            const wchar_t* optionalChildName,
314                                            const wchar_t* valueName,
315                                            uint32_t defaultValue,
316                                            uint32_t& valueOut) {
317   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ReadRegKeyValueWithDefault"));
318   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
319           ("attempting to read '%S%s%S' with default '%u'",
320            optionalChildName ? optionalChildName : L"",
321            optionalChildName ? "\\" : "", valueName, defaultValue));
322   if (optionalChildName) {
323     nsDependentString childNameString(optionalChildName);
324     bool hasChild;
325     nsresult rv = regKey->HasChild(childNameString, &hasChild);
326     if (NS_FAILED(rv)) {
327       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
328               ("failed to determine if child key is present"));
329       return rv;
330     }
331     if (!hasChild) {
332       valueOut = defaultValue;
333       return NS_OK;
334     }
335     nsCOMPtr<nsIWindowsRegKey> childRegKey;
336     rv = regKey->OpenChild(childNameString, flags, getter_AddRefs(childRegKey));
337     if (NS_FAILED(rv)) {
338       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open child key"));
339       return rv;
340     }
341     return ReadRegKeyValueWithDefault(childRegKey, flags, nullptr, valueName,
342                                       defaultValue, valueOut);
343   }
344   nsDependentString valueNameString(valueName);
345   bool hasValue;
346   nsresult rv = regKey->HasValue(valueNameString, &hasValue);
347   if (NS_FAILED(rv)) {
348     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
349             ("failed to determine if value is present"));
350     return rv;
351   }
352   if (!hasValue) {
353     valueOut = defaultValue;
354     return NS_OK;
355   }
356   rv = regKey->ReadIntValue(valueNameString, &valueOut);
357   if (NS_FAILED(rv)) {
358     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to read value"));
359     return rv;
360   }
361   return NS_OK;
362 }
363 
AccountHasFamilySafetyEnabled(bool & enabled)364 static nsresult AccountHasFamilySafetyEnabled(bool& enabled) {
365   enabled = false;
366   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("AccountHasFamilySafetyEnabled?"));
367   nsCOMPtr<nsIWindowsRegKey> parentalControlsKey(
368       do_CreateInstance("@mozilla.org/windows-registry-key;1"));
369   if (!parentalControlsKey) {
370     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create nsIWindowsRegKey"));
371     return NS_ERROR_FAILURE;
372   }
373   uint32_t flags = nsIWindowsRegKey::ACCESS_READ | nsIWindowsRegKey::WOW64_64;
374   constexpr auto familySafetyPath =
375       u"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Parental Controls"_ns;
376   nsresult rv = parentalControlsKey->Open(
377       nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, familySafetyPath, flags);
378   if (NS_FAILED(rv)) {
379     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open parentalControlsKey"));
380     return rv;
381   }
382   constexpr auto usersString = u"Users"_ns;
383   bool hasUsers;
384   rv = parentalControlsKey->HasChild(usersString, &hasUsers);
385   if (NS_FAILED(rv)) {
386     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(Users) failed"));
387     return rv;
388   }
389   if (!hasUsers) {
390     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
391             ("Users subkey not present - Parental Controls not enabled"));
392     return NS_OK;
393   }
394   nsCOMPtr<nsIWindowsRegKey> usersKey;
395   rv = parentalControlsKey->OpenChild(usersString, flags,
396                                       getter_AddRefs(usersKey));
397   if (NS_FAILED(rv)) {
398     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to open Users subkey"));
399     return rv;
400   }
401   nsAutoString sid;
402   if (!GetUserSid(sid)) {
403     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get sid"));
404     return NS_ERROR_FAILURE;
405   }
406   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("our sid is '%S'", sid.get()));
407   bool hasSid;
408   rv = usersKey->HasChild(sid, &hasSid);
409   if (NS_FAILED(rv)) {
410     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HasChild(sid) failed"));
411     return rv;
412   }
413   if (!hasSid) {
414     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
415             ("sid not present in Family Safety Users"));
416     return NS_OK;
417   }
418   nsCOMPtr<nsIWindowsRegKey> sidKey;
419   rv = usersKey->OpenChild(sid, flags, getter_AddRefs(sidKey));
420   if (NS_FAILED(rv)) {
421     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't open sid key"));
422     return rv;
423   }
424   // There are three keys we're interested in: "Parental Controls On",
425   // "Logging Required", and "Web\\Filter On". These keys will have value 0
426   // or 1, indicating a particular feature is disabled or enabled,
427   // respectively. So, if "Parental Controls On" is not 1, Family Safety is
428   // disabled and we don't care about anything else. If both "Logging
429   // Required" and "Web\\Filter On" are 0, the proxy will not be running,
430   // so for our purposes we can consider Family Safety disabled in that
431   // case.
432   // By default, "Logging Required" is 1 and "Web\\Filter On" is 0,
433   // reflecting the initial settings when Family Safety is enabled for an
434   // account for the first time, However, these sub-keys are not created
435   // unless they are switched away from the default value.
436   uint32_t parentalControlsOn;
437   rv = sidKey->ReadIntValue(u"Parental Controls On"_ns, &parentalControlsOn);
438   if (NS_FAILED(rv)) {
439     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
440             ("couldn't read Parental Controls On"));
441     return rv;
442   }
443   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
444           ("Parental Controls On: %u", parentalControlsOn));
445   if (parentalControlsOn != 1) {
446     return NS_OK;
447   }
448   uint32_t loggingRequired;
449   rv = ReadRegKeyValueWithDefault(sidKey, flags, nullptr, L"Logging Required",
450                                   1, loggingRequired);
451   if (NS_FAILED(rv)) {
452     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
453             ("failed to read value of Logging Required"));
454     return rv;
455   }
456   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
457           ("Logging Required: %u", loggingRequired));
458   uint32_t webFilterOn;
459   rv = ReadRegKeyValueWithDefault(sidKey, flags, L"Web", L"Filter On", 0,
460                                   webFilterOn);
461   if (NS_FAILED(rv)) {
462     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
463             ("failed to read value of Web\\Filter On"));
464     return rv;
465   }
466   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Web\\Filter On: %u", webFilterOn));
467   enabled = loggingRequired == 1 || webFilterOn == 1;
468   return NS_OK;
469 }
470 #endif  // XP_WIN
471 
472 // On Windows 8.1, if the following preference is 2, we will attempt to detect
473 // if the Family Safety TLS interception feature has been enabled. If so, we
474 // will behave as if the enterprise roots feature has been enabled (i.e. import
475 // and trust third party root certificates from the OS).
476 // With any other value of the pref or on any other platform, this does nothing.
477 // This preference takes precedence over "security.enterprise_roots.enabled".
478 const char* kFamilySafetyModePref = "security.family_safety.mode";
479 const uint32_t kFamilySafetyModeDefault = 0;
480 
ShouldEnableEnterpriseRootsForFamilySafety(uint32_t familySafetyMode)481 bool nsNSSComponent::ShouldEnableEnterpriseRootsForFamilySafety(
482     uint32_t familySafetyMode) {
483 #ifdef XP_WIN
484   if (!(IsWin8Point1OrLater() && !IsWin10OrLater())) {
485     return false;
486   }
487   if (familySafetyMode != 2) {
488     return false;
489   }
490   bool familySafetyEnabled;
491   nsresult rv = AccountHasFamilySafetyEnabled(familySafetyEnabled);
492   if (NS_FAILED(rv)) {
493     return false;
494   }
495   return familySafetyEnabled;
496 #else
497   return false;
498 #endif  // XP_WIN
499 }
500 
UnloadEnterpriseRoots()501 void nsNSSComponent::UnloadEnterpriseRoots() {
502   MOZ_ASSERT(NS_IsMainThread());
503   if (!NS_IsMainThread()) {
504     return;
505   }
506   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("UnloadEnterpriseRoots"));
507   MutexAutoLock lock(mMutex);
508   mEnterpriseCerts.clear();
509   setValidationOptions(false, lock);
510 }
511 
512 static const char* kEnterpriseRootModePref =
513     "security.enterprise_roots.enabled";
514 static const char* kOSClientCertsModulePref = "security.osclientcerts.autoload";
515 
516 class BackgroundImportEnterpriseCertsTask final : public CryptoTask {
517  public:
BackgroundImportEnterpriseCertsTask(nsNSSComponent * nssComponent)518   explicit BackgroundImportEnterpriseCertsTask(nsNSSComponent* nssComponent)
519       : mNSSComponent(nssComponent) {}
520 
521  private:
CalculateResult()522   virtual nsresult CalculateResult() override {
523     mNSSComponent->ImportEnterpriseRoots();
524     mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
525     return NS_OK;
526   }
527 
CallCallback(nsresult rv)528   virtual void CallCallback(nsresult rv) override {
529     nsCOMPtr<nsIObserverService> observerService =
530         mozilla::services::GetObserverService();
531     if (observerService) {
532       observerService->NotifyObservers(nullptr, "psm:enterprise-certs-imported",
533                                        nullptr);
534     }
535   }
536 
537   RefPtr<nsNSSComponent> mNSSComponent;
538 };
539 
MaybeImportEnterpriseRoots()540 void nsNSSComponent::MaybeImportEnterpriseRoots() {
541   MOZ_ASSERT(NS_IsMainThread());
542   if (!NS_IsMainThread()) {
543     return;
544   }
545   bool importEnterpriseRoots =
546       Preferences::GetBool(kEnterpriseRootModePref, false);
547   uint32_t familySafetyMode =
548       Preferences::GetUint(kFamilySafetyModePref, kFamilySafetyModeDefault);
549   // If we've been configured to detect the Family Safety TLS interception
550   // feature, see if it's enabled. If so, we want to import enterprise roots.
551   if (ShouldEnableEnterpriseRootsForFamilySafety(familySafetyMode)) {
552     importEnterpriseRoots = true;
553   }
554   if (importEnterpriseRoots) {
555     RefPtr<BackgroundImportEnterpriseCertsTask> task =
556         new BackgroundImportEnterpriseCertsTask(this);
557     Unused << task->Dispatch();
558   }
559 }
560 
ImportEnterpriseRoots()561 void nsNSSComponent::ImportEnterpriseRoots() {
562   MOZ_ASSERT(!NS_IsMainThread());
563   if (NS_IsMainThread()) {
564     return;
565   }
566 
567   Vector<EnterpriseCert> enterpriseCerts;
568   nsresult rv = GatherEnterpriseCerts(enterpriseCerts);
569   if (NS_SUCCEEDED(rv)) {
570     MutexAutoLock lock(mMutex);
571     mEnterpriseCerts = std::move(enterpriseCerts);
572   } else {
573     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed gathering enterprise roots"));
574   }
575 }
576 
CommonGetEnterpriseCerts(nsTArray<nsTArray<uint8_t>> & enterpriseCerts,bool getRoots)577 nsresult nsNSSComponent::CommonGetEnterpriseCerts(
578     nsTArray<nsTArray<uint8_t>>& enterpriseCerts, bool getRoots) {
579   nsresult rv = BlockUntilLoadableCertsLoaded();
580   if (NS_FAILED(rv)) {
581     return rv;
582   }
583 
584   MutexAutoLock nsNSSComponentLock(mMutex);
585   enterpriseCerts.Clear();
586   for (const auto& cert : mEnterpriseCerts) {
587     nsTArray<uint8_t> certCopy;
588     // mEnterpriseCerts includes both roots and intermediates.
589     if (cert.GetIsRoot() == getRoots) {
590       nsresult rv = cert.CopyBytes(certCopy);
591       if (NS_FAILED(rv)) {
592         return rv;
593       }
594       // XXX(Bug 1631371) Check if this should use a fallible operation as it
595       // pretended earlier.
596       enterpriseCerts.AppendElement(std::move(certCopy));
597     }
598   }
599   return NS_OK;
600 }
601 
602 NS_IMETHODIMP
GetEnterpriseRoots(nsTArray<nsTArray<uint8_t>> & enterpriseRoots)603 nsNSSComponent::GetEnterpriseRoots(
604     nsTArray<nsTArray<uint8_t>>& enterpriseRoots) {
605   return CommonGetEnterpriseCerts(enterpriseRoots, true);
606 }
607 
608 NS_IMETHODIMP
GetEnterpriseIntermediates(nsTArray<nsTArray<uint8_t>> & enterpriseIntermediates)609 nsNSSComponent::GetEnterpriseIntermediates(
610     nsTArray<nsTArray<uint8_t>>& enterpriseIntermediates) {
611   return CommonGetEnterpriseCerts(enterpriseIntermediates, false);
612 }
613 
614 NS_IMETHODIMP
AddEnterpriseIntermediate(const nsTArray<uint8_t> & intermediateBytes)615 nsNSSComponent::AddEnterpriseIntermediate(
616     const nsTArray<uint8_t>& intermediateBytes) {
617   nsresult rv = BlockUntilLoadableCertsLoaded();
618   if (NS_FAILED(rv)) {
619     return rv;
620   }
621   EnterpriseCert intermediate;
622   rv = intermediate.Init(intermediateBytes.Elements(),
623                          intermediateBytes.Length(), false);
624   if (NS_FAILED(rv)) {
625     return rv;
626   }
627 
628   {
629     MutexAutoLock nsNSSComponentLock(mMutex);
630     if (!mEnterpriseCerts.append(std::move(intermediate))) {
631       return NS_ERROR_OUT_OF_MEMORY;
632     }
633   }
634 
635   UpdateCertVerifierWithEnterpriseRoots();
636   return NS_OK;
637 }
638 
639 class LoadLoadableCertsTask final : public Runnable {
640  public:
LoadLoadableCertsTask(nsNSSComponent * nssComponent,bool importEnterpriseRoots,uint32_t familySafetyMode,Vector<nsCString> && possibleLoadableRootsLocations,Maybe<nsCString> && osClientCertsModuleLocation)641   LoadLoadableCertsTask(nsNSSComponent* nssComponent,
642                         bool importEnterpriseRoots, uint32_t familySafetyMode,
643                         Vector<nsCString>&& possibleLoadableRootsLocations,
644                         Maybe<nsCString>&& osClientCertsModuleLocation)
645       : Runnable("LoadLoadableCertsTask"),
646         mNSSComponent(nssComponent),
647         mImportEnterpriseRoots(importEnterpriseRoots),
648         mFamilySafetyMode(familySafetyMode),
649         mPossibleLoadableRootsLocations(
650             std::move(possibleLoadableRootsLocations)),
651         mOSClientCertsModuleLocation(std::move(osClientCertsModuleLocation)) {
652     MOZ_ASSERT(nssComponent);
653   }
654 
655   ~LoadLoadableCertsTask() = default;
656 
657   nsresult Dispatch();
658 
659  private:
660   NS_IMETHOD Run() override;
661   nsresult LoadLoadableRoots();
662   RefPtr<nsNSSComponent> mNSSComponent;
663   bool mImportEnterpriseRoots;
664   uint32_t mFamilySafetyMode;
665   Vector<nsCString> mPossibleLoadableRootsLocations;
666   Maybe<nsCString> mOSClientCertsModuleLocation;
667 };
668 
Dispatch()669 nsresult LoadLoadableCertsTask::Dispatch() {
670   // The stream transport service (note: not the socket transport service) can
671   // be used to perform background tasks or I/O that would otherwise block the
672   // main thread.
673   nsCOMPtr<nsIEventTarget> target(
674       do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID));
675   if (!target) {
676     return NS_ERROR_FAILURE;
677   }
678   return target->Dispatch(this, NS_DISPATCH_NORMAL);
679 }
680 
681 NS_IMETHODIMP
Run()682 LoadLoadableCertsTask::Run() {
683   Telemetry::AutoScalarTimer<Telemetry::ScalarID::NETWORKING_LOADING_CERTS_TASK>
684       timer;
685 
686   nsresult loadLoadableRootsResult = LoadLoadableRoots();
687   if (NS_WARN_IF(NS_FAILED(loadLoadableRootsResult))) {
688     MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("LoadLoadableRoots failed"));
689     // We don't return loadLoadableRootsResult here because then
690     // BlockUntilLoadableCertsLoaded will just wait forever. Instead we'll save
691     // its value (below) so we can inform code that relies on the roots module
692     // being present that loading it failed.
693   }
694 
695   // Loading EV information will only succeed if we've successfully loaded the
696   // loadable roots module.
697   if (NS_SUCCEEDED(loadLoadableRootsResult)) {
698     if (NS_FAILED(LoadExtendedValidationInfo())) {
699       // This isn't a show-stopper in the same way that failing to load the
700       // roots module is.
701       MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
702     }
703   }
704 
705   // If we've been configured to detect the Family Safety TLS interception
706   // feature, see if it's enabled. If so, we want to import enterprise roots.
707   if (mNSSComponent->ShouldEnableEnterpriseRootsForFamilySafety(
708           mFamilySafetyMode)) {
709     mImportEnterpriseRoots = true;
710   }
711   if (mImportEnterpriseRoots) {
712     mNSSComponent->ImportEnterpriseRoots();
713     mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
714   }
715   if (mOSClientCertsModuleLocation.isSome()) {
716     bool success = LoadOSClientCertsModule(*mOSClientCertsModuleLocation);
717     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
718             ("loading OS client certs module %s",
719              success ? "succeeded" : "failed"));
720   }
721   {
722     MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableCertsLoadedMonitor);
723     mNSSComponent->mLoadableCertsLoaded = true;
724     // Cache the result of LoadLoadableRoots so BlockUntilLoadableCertsLoaded
725     // can return it to all callers later (we use that particular result because
726     // if that operation fails, it's unlikely that any TLS connection will
727     // succeed whereas the browser may still be able to operate if the other
728     // tasks fail).
729     mNSSComponent->mLoadableCertsLoadedResult = loadLoadableRootsResult;
730     mNSSComponent->mLoadableCertsLoadedMonitor.NotifyAll();
731   }
732   return NS_OK;
733 }
734 
735 // Returns by reference the path to the desired directory, based on the current
736 // settings in the directory service.
GetDirectoryPath(const char * directoryKey,nsCString & result)737 static nsresult GetDirectoryPath(const char* directoryKey, nsCString& result) {
738   MOZ_ASSERT(NS_IsMainThread());
739 
740   nsCOMPtr<nsIProperties> directoryService(
741       do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
742   if (!directoryService) {
743     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get directory service"));
744     return NS_ERROR_FAILURE;
745   }
746   nsCOMPtr<nsIFile> directory;
747   nsresult rv = directoryService->Get(directoryKey, NS_GET_IID(nsIFile),
748                                       getter_AddRefs(directory));
749   if (NS_FAILED(rv)) {
750     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
751             ("could not get '%s' from directory service", directoryKey));
752     return rv;
753   }
754 #ifdef XP_WIN
755   // Native path will drop Unicode characters that cannot be mapped to system's
756   // codepage, using short (canonical) path as workaround.
757   nsCOMPtr<nsILocalFileWin> directoryWin = do_QueryInterface(directory);
758   if (!directoryWin) {
759     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get nsILocalFileWin"));
760     return NS_ERROR_FAILURE;
761   }
762   return directoryWin->GetNativeCanonicalPath(result);
763 #else
764   return directory->GetNativePath(result);
765 #endif
766 }
767 
768 class BackgroundLoadOSClientCertsModuleTask final : public CryptoTask {
769  public:
BackgroundLoadOSClientCertsModuleTask(const nsCString && libraryDir)770   explicit BackgroundLoadOSClientCertsModuleTask(const nsCString&& libraryDir)
771       : mLibraryDir(std::move(libraryDir)) {}
772 
773  private:
CalculateResult()774   virtual nsresult CalculateResult() override {
775     bool success = LoadOSClientCertsModule(mLibraryDir);
776     return success ? NS_OK : NS_ERROR_FAILURE;
777   }
778 
CallCallback(nsresult rv)779   virtual void CallCallback(nsresult rv) override {
780     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
781             ("loading OS client certs module %s",
782              NS_SUCCEEDED(rv) ? "succeeded" : "failed"));
783     nsCOMPtr<nsIObserverService> observerService =
784         mozilla::services::GetObserverService();
785     if (observerService) {
786       observerService->NotifyObservers(
787           nullptr, "psm:load-os-client-certs-module-task-ran", nullptr);
788     }
789   }
790 
791   nsCString mLibraryDir;
792 };
793 
AsyncLoadOrUnloadOSClientCertsModule(bool load)794 void AsyncLoadOrUnloadOSClientCertsModule(bool load) {
795   if (load) {
796     nsCString libraryDir;
797     nsresult rv = GetDirectoryPath(NS_GRE_BIN_DIR, libraryDir);
798     if (NS_FAILED(rv)) {
799       return;
800     }
801     RefPtr<BackgroundLoadOSClientCertsModuleTask> task =
802         new BackgroundLoadOSClientCertsModuleTask(std::move(libraryDir));
803     Unused << task->Dispatch();
804   } else {
805     UniqueSECMODModule osClientCertsModule(
806         SECMOD_FindModule(kOSClientCertsModuleName));
807     if (osClientCertsModule) {
808       SECMOD_UnloadUserModule(osClientCertsModule.get());
809     }
810   }
811 }
812 
813 NS_IMETHODIMP
HasActiveSmartCards(bool * result)814 nsNSSComponent::HasActiveSmartCards(bool* result) {
815   NS_ENSURE_ARG_POINTER(result);
816 
817   BlockUntilLoadableCertsLoaded();
818 
819 #ifndef MOZ_NO_SMART_CARDS
820   AutoSECMODListReadLock secmodLock;
821   SECMODModuleList* list = SECMOD_GetDefaultModuleList();
822   while (list) {
823     SECMODModule* module = list->module;
824     if (SECMOD_HasRemovableSlots(module)) {
825       *result = true;
826       return NS_OK;
827     }
828     for (int i = 0; i < module->slotCount; i++) {
829       if (!PK11_IsFriendly(module->slots[i])) {
830         *result = true;
831         return NS_OK;
832       }
833     }
834     list = list->next;
835   }
836 #endif
837   *result = false;
838   return NS_OK;
839 }
840 
841 NS_IMETHODIMP
HasUserCertsInstalled(bool * result)842 nsNSSComponent::HasUserCertsInstalled(bool* result) {
843   NS_ENSURE_ARG_POINTER(result);
844 
845   BlockUntilLoadableCertsLoaded();
846 
847   // FindClientCertificatesWithPrivateKeys won't ever return an empty list, so
848   // all we need to do is check if this is null or not.
849   UniqueCERTCertList certList(FindClientCertificatesWithPrivateKeys());
850   *result = !!certList;
851 
852   return NS_OK;
853 }
854 
BlockUntilLoadableCertsLoaded()855 nsresult nsNSSComponent::BlockUntilLoadableCertsLoaded() {
856   MonitorAutoLock rootsLoadedLock(mLoadableCertsLoadedMonitor);
857   while (!mLoadableCertsLoaded) {
858     rootsLoadedLock.Wait();
859   }
860   MOZ_ASSERT(mLoadableCertsLoaded);
861 
862   return mLoadableCertsLoadedResult;
863 }
864 
865 #ifndef MOZ_NO_SMART_CARDS
866 static StaticMutex sCheckForSmartCardChangesMutex;
867 static TimeStamp sLastCheckedForSmartCardChanges = TimeStamp::Now();
868 #endif
869 
CheckForSmartCardChanges()870 nsresult nsNSSComponent::CheckForSmartCardChanges() {
871 #ifndef MOZ_NO_SMART_CARDS
872   {
873     StaticMutexAutoLock lock(sCheckForSmartCardChangesMutex);
874     // Do this at most once every 3 seconds.
875     TimeStamp now = TimeStamp::Now();
876     if (now - sLastCheckedForSmartCardChanges <
877         TimeDuration::FromSeconds(3.0)) {
878       return NS_OK;
879     }
880     sLastCheckedForSmartCardChanges = now;
881   }
882 
883   // SECMOD_UpdateSlotList attempts to acquire the list lock as well,
884   // so we have to do this in two steps. The lock protects the list itself, so
885   // if we get our own owned references to the modules we're interested in,
886   // there's no thread safety concern here.
887   Vector<UniqueSECMODModule> modulesWithRemovableSlots;
888   {
889     AutoSECMODListReadLock secmodLock;
890     SECMODModuleList* list = SECMOD_GetDefaultModuleList();
891     while (list) {
892       if (SECMOD_HasRemovableSlots(list->module)) {
893         UniqueSECMODModule module(SECMOD_ReferenceModule(list->module));
894         if (!modulesWithRemovableSlots.append(std::move(module))) {
895           return NS_ERROR_OUT_OF_MEMORY;
896         }
897       }
898       list = list->next;
899     }
900   }
901   for (auto& module : modulesWithRemovableSlots) {
902     // Best-effort.
903     Unused << SECMOD_UpdateSlotList(module.get());
904     for (int i = 0; i < module->slotCount; i++) {
905       // We actually don't care about the return value here - we just need to
906       // call this to get NSS to update its view of this slot.
907       Unused << PK11_IsPresent(module->slots[i]);
908     }
909   }
910 #endif
911 
912   return NS_OK;
913 }
914 
915 // Returns by reference the path to the directory containing the file that has
916 // been loaded as MOZ_DLL_PREFIX nss3 MOZ_DLL_SUFFIX.
GetNSS3Directory(nsCString & result)917 static nsresult GetNSS3Directory(nsCString& result) {
918   MOZ_ASSERT(NS_IsMainThread());
919 
920   UniquePRString nss3Path(
921       PR_GetLibraryFilePathname(MOZ_DLL_PREFIX "nss3" MOZ_DLL_SUFFIX,
922                                 reinterpret_cast<PRFuncPtr>(NSS_Initialize)));
923   if (!nss3Path) {
924     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nss not loaded?"));
925     return NS_ERROR_FAILURE;
926   }
927   nsCOMPtr<nsIFile> nss3File(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
928   if (!nss3File) {
929     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create a file?"));
930     return NS_ERROR_FAILURE;
931   }
932   nsAutoCString nss3PathAsString(nss3Path.get());
933   nsresult rv = nss3File->InitWithNativePath(nss3PathAsString);
934   if (NS_FAILED(rv)) {
935     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
936             ("couldn't initialize file with path '%s'", nss3Path.get()));
937     return rv;
938   }
939   nsCOMPtr<nsIFile> nss3Directory;
940   rv = nss3File->GetParent(getter_AddRefs(nss3Directory));
941   if (NS_FAILED(rv)) {
942     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get parent directory?"));
943     return rv;
944   }
945 #ifdef XP_WIN
946   // Native path will drop Unicode characters that cannot be mapped to system's
947   // codepage, using short (canonical) path as workaround.
948   nsCOMPtr<nsILocalFileWin> nss3DirectoryWin = do_QueryInterface(nss3Directory);
949   if (!nss3DirectoryWin) {
950     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get nsILocalFileWin"));
951     return NS_ERROR_FAILURE;
952   }
953   return nss3DirectoryWin->GetNativeCanonicalPath(result);
954 #else
955   return nss3Directory->GetNativePath(result);
956 #endif
957 }
958 
959 // The loadable roots library is probably in the same directory we loaded the
960 // NSS shared library from, but in some cases it may be elsewhere. This function
961 // enumerates and returns the possible locations as nsCStrings.
ListPossibleLoadableRootsLocations(Vector<nsCString> & possibleLoadableRootsLocations)962 static nsresult ListPossibleLoadableRootsLocations(
963     Vector<nsCString>& possibleLoadableRootsLocations) {
964   MOZ_ASSERT(NS_IsMainThread());
965   if (!NS_IsMainThread()) {
966     return NS_ERROR_NOT_SAME_THREAD;
967   }
968 
969   // First try in the directory where we've already loaded
970   // MOZ_DLL_PREFIX nss3 MOZ_DLL_SUFFIX, since that's likely to be correct.
971   nsAutoCString nss3Dir;
972   nsresult rv = GetNSS3Directory(nss3Dir);
973   if (NS_SUCCEEDED(rv)) {
974     if (!possibleLoadableRootsLocations.append(std::move(nss3Dir))) {
975       return NS_ERROR_OUT_OF_MEMORY;
976     }
977   } else {
978     // For some reason this fails on android. In any case, we should try with
979     // the other potential locations we have.
980     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
981             ("could not determine where nss was loaded from"));
982   }
983   nsAutoCString currentProcessDir;
984   rv = GetDirectoryPath(NS_XPCOM_CURRENT_PROCESS_DIR, currentProcessDir);
985   if (NS_SUCCEEDED(rv)) {
986     if (!possibleLoadableRootsLocations.append(std::move(currentProcessDir))) {
987       return NS_ERROR_OUT_OF_MEMORY;
988     }
989   } else {
990     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
991             ("could not get current process directory"));
992   }
993   nsAutoCString greDir;
994   rv = GetDirectoryPath(NS_GRE_DIR, greDir);
995   if (NS_SUCCEEDED(rv)) {
996     if (!possibleLoadableRootsLocations.append(std::move(greDir))) {
997       return NS_ERROR_OUT_OF_MEMORY;
998     }
999   } else {
1000     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get gre directory"));
1001   }
1002   // As a last resort, this will cause the library loading code to use the OS'
1003   // default library search path.
1004   nsAutoCString emptyString;
1005   if (!possibleLoadableRootsLocations.append(std::move(emptyString))) {
1006     return NS_ERROR_OUT_OF_MEMORY;
1007   }
1008 
1009   return NS_OK;
1010 }
1011 
LoadLoadableRoots()1012 nsresult LoadLoadableCertsTask::LoadLoadableRoots() {
1013   for (const auto& possibleLocation : mPossibleLoadableRootsLocations) {
1014     if (mozilla::psm::LoadLoadableRoots(possibleLocation)) {
1015       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1016               ("loaded CKBI from %s", possibleLocation.get()));
1017       return NS_OK;
1018     }
1019   }
1020   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not load loadable roots"));
1021   return NS_ERROR_FAILURE;
1022 }
1023 
1024 // Table of pref names and SSL cipher ID
1025 typedef struct {
1026   const char* pref;
1027   long id;
1028   bool enabledByDefault;
1029 } CipherPref;
1030 
1031 // Update the switch statement in AccumulateCipherSuite in nsNSSCallbacks.cpp
1032 // when you add/remove cipher suites here.
1033 static const CipherPref sCipherPrefs[] = {
1034     {"security.ssl3.ecdhe_rsa_aes_128_gcm_sha256",
1035      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, true},
1036     {"security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256",
1037      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, true},
1038 
1039     {"security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256",
1040      TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, true},
1041     {"security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256",
1042      TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, true},
1043 
1044     {"security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384",
1045      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, true},
1046     {"security.ssl3.ecdhe_rsa_aes_256_gcm_sha384",
1047      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, true},
1048 
1049     {"security.ssl3.ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
1050      true},
1051     {"security.ssl3.ecdhe_ecdsa_aes_128_sha",
1052      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, true},
1053 
1054     {"security.ssl3.ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
1055      true},
1056     {"security.ssl3.ecdhe_ecdsa_aes_256_sha",
1057      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true},
1058 
1059     {"security.ssl3.dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1060      false},
1061 
1062     {"security.ssl3.dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1063      false},
1064 
1065     {"security.tls13.aes_128_gcm_sha256", TLS_AES_128_GCM_SHA256, true},
1066     {"security.tls13.chacha20_poly1305_sha256", TLS_CHACHA20_POLY1305_SHA256,
1067      true},
1068     {"security.tls13.aes_256_gcm_sha384", TLS_AES_256_GCM_SHA384, true},
1069 
1070     {"security.ssl3.rsa_aes_128_gcm_sha256", TLS_RSA_WITH_AES_128_GCM_SHA256,
1071      true},  // deprecated (RSA key exchange)
1072     {"security.ssl3.rsa_aes_256_gcm_sha384", TLS_RSA_WITH_AES_256_GCM_SHA384,
1073      true},  // deprecated (RSA key exchange)
1074     {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA,
1075      true},  // deprecated (RSA key exchange)
1076     {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA,
1077      true},  // deprecated (RSA key exchange)
1078     {"security.ssl3.rsa_des_ede3_sha", TLS_RSA_WITH_3DES_EDE_CBC_SHA,
1079      true},  // deprecated (RSA key exchange, 3DES)
1080 
1081     // All the rest are disabled
1082 
1083     {nullptr, 0}  // end marker
1084 };
1085 
1086 // This function will convert from pref values like 1, 2, ...
1087 // to the internal values of SSL_LIBRARY_VERSION_TLS_1_0,
1088 // SSL_LIBRARY_VERSION_TLS_1_1, ...
1089 /*static*/
FillTLSVersionRange(SSLVersionRange & rangeOut,uint32_t minFromPrefs,uint32_t maxFromPrefs,SSLVersionRange defaults)1090 void nsNSSComponent::FillTLSVersionRange(SSLVersionRange& rangeOut,
1091                                          uint32_t minFromPrefs,
1092                                          uint32_t maxFromPrefs,
1093                                          SSLVersionRange defaults) {
1094   rangeOut = defaults;
1095   // determine what versions are supported
1096   SSLVersionRange supported;
1097   if (SSL_VersionRangeGetSupported(ssl_variant_stream, &supported) !=
1098       SECSuccess) {
1099     return;
1100   }
1101 
1102   // Clip the defaults by what NSS actually supports to enable
1103   // working with a system NSS with different ranges.
1104   rangeOut.min = std::max(rangeOut.min, supported.min);
1105   rangeOut.max = std::min(rangeOut.max, supported.max);
1106 
1107   // convert min/maxFromPrefs to the internal representation
1108   minFromPrefs += SSL_LIBRARY_VERSION_3_0;
1109   maxFromPrefs += SSL_LIBRARY_VERSION_3_0;
1110   // if min/maxFromPrefs are invalid, use defaults
1111   if (minFromPrefs > maxFromPrefs || minFromPrefs < supported.min ||
1112       maxFromPrefs > supported.max ||
1113       minFromPrefs < SSL_LIBRARY_VERSION_TLS_1_0) {
1114     return;
1115   }
1116 
1117   // fill out rangeOut
1118   rangeOut.min = (uint16_t)minFromPrefs;
1119   rangeOut.max = (uint16_t)maxFromPrefs;
1120 }
1121 
1122 static const int32_t OCSP_ENABLED_DEFAULT = 1;
1123 static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
1124 static const bool FALSE_START_ENABLED_DEFAULT = true;
1125 static const bool ALPN_ENABLED_DEFAULT = false;
1126 static const bool ENABLED_0RTT_DATA_DEFAULT = false;
1127 static const bool HELLO_DOWNGRADE_CHECK_DEFAULT = true;
1128 static const bool ENABLED_POST_HANDSHAKE_AUTH_DEFAULT = false;
1129 static const bool DELEGATED_CREDENTIALS_ENABLED_DEFAULT = false;
1130 
ConfigureTLSSessionIdentifiers()1131 static void ConfigureTLSSessionIdentifiers() {
1132   bool disableSessionIdentifiers =
1133       Preferences::GetBool("security.ssl.disable_session_identifiers", false);
1134   SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, !disableSessionIdentifiers);
1135   SSL_OptionSetDefault(SSL_NO_CACHE, disableSessionIdentifiers);
1136 }
1137 
CommonInit()1138 nsresult CommonInit() {
1139   SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
1140   SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
1141 
1142   nsresult rv = nsNSSComponent::SetEnabledTLSVersions();
1143   if (NS_FAILED(rv)) {
1144     return rv;
1145   }
1146 
1147   ConfigureTLSSessionIdentifiers();
1148 
1149   bool requireSafeNegotiation =
1150       Preferences::GetBool("security.ssl.require_safe_negotiation",
1151                            REQUIRE_SAFE_NEGOTIATION_DEFAULT);
1152   SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
1153 
1154   SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_REQUIRES_XTN);
1155 
1156   SSL_OptionSetDefault(SSL_ENABLE_EXTENDED_MASTER_SECRET, true);
1157 
1158   bool enableDowngradeCheck = Preferences::GetBool(
1159       "security.tls.hello_downgrade_check", HELLO_DOWNGRADE_CHECK_DEFAULT);
1160   SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, enableDowngradeCheck);
1161 
1162   SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
1163                        Preferences::GetBool("security.ssl.enable_false_start",
1164                                             FALSE_START_ENABLED_DEFAULT));
1165 
1166   // SSL_ENABLE_ALPN also requires calling SSL_SetNextProtoNego in order for
1167   // the extensions to be negotiated.
1168   // WebRTC does not do that so it will not use ALPN even when this preference
1169   // is true.
1170   SSL_OptionSetDefault(
1171       SSL_ENABLE_ALPN,
1172       Preferences::GetBool("security.ssl.enable_alpn", ALPN_ENABLED_DEFAULT));
1173 
1174   SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
1175                        Preferences::GetBool("security.tls.enable_0rtt_data",
1176                                             ENABLED_0RTT_DATA_DEFAULT));
1177 
1178   SSL_OptionSetDefault(
1179       SSL_ENABLE_POST_HANDSHAKE_AUTH,
1180       Preferences::GetBool("security.tls.enable_post_handshake_auth",
1181                            ENABLED_POST_HANDSHAKE_AUTH_DEFAULT));
1182 
1183   SSL_OptionSetDefault(
1184       SSL_ENABLE_DELEGATED_CREDENTIALS,
1185       Preferences::GetBool("security.tls.enable_delegated_credentials",
1186                            DELEGATED_CREDENTIALS_ENABLED_DEFAULT));
1187 
1188   rv = InitializeCipherSuite();
1189   if (NS_FAILED(rv)) {
1190     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
1191             ("Unable to initialize cipher suite settings\n"));
1192     return rv;
1193   }
1194 
1195   DisableMD5();
1196 
1197   mozilla::pkix::RegisterErrorTable();
1198 
1199   SharedSSLState::GlobalInit();
1200   RememberCertErrorsTable::Init();
1201 
1202   SetValidationOptionsCommon();
1203 
1204   return NS_OK;
1205 }
1206 
NSSShutdownForSocketProcess()1207 void NSSShutdownForSocketProcess() {
1208   MOZ_ASSERT(XRE_IsSocketProcess());
1209   SharedSSLState::GlobalCleanup();
1210   RememberCertErrorsTable::Cleanup();
1211 }
1212 
HandleTLSPrefChange(const nsCString & prefName)1213 bool HandleTLSPrefChange(const nsCString& prefName) {
1214   // Note that the code in this function should be kept in sync with
1215   // gCallbackSecurityPrefs in nsIOService.cpp.
1216   bool prefFound = true;
1217   if (prefName.EqualsLiteral("security.tls.version.min") ||
1218       prefName.EqualsLiteral("security.tls.version.max") ||
1219       prefName.EqualsLiteral("security.tls.version.enable-deprecated")) {
1220     (void)nsNSSComponent::SetEnabledTLSVersions();
1221   } else if (prefName.EqualsLiteral("security.tls.hello_downgrade_check")) {
1222     bool enableDowngradeCheck = Preferences::GetBool(
1223         "security.tls.hello_downgrade_check", HELLO_DOWNGRADE_CHECK_DEFAULT);
1224     SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK,
1225                          enableDowngradeCheck);
1226   } else if (prefName.EqualsLiteral("security.ssl.require_safe_negotiation")) {
1227     bool requireSafeNegotiation =
1228         Preferences::GetBool("security.ssl.require_safe_negotiation",
1229                              REQUIRE_SAFE_NEGOTIATION_DEFAULT);
1230     SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, requireSafeNegotiation);
1231   } else if (prefName.EqualsLiteral("security.ssl.enable_false_start")) {
1232     SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
1233                          Preferences::GetBool("security.ssl.enable_false_start",
1234                                               FALSE_START_ENABLED_DEFAULT));
1235   } else if (prefName.EqualsLiteral("security.ssl.enable_alpn")) {
1236     SSL_OptionSetDefault(
1237         SSL_ENABLE_ALPN,
1238         Preferences::GetBool("security.ssl.enable_alpn", ALPN_ENABLED_DEFAULT));
1239   } else if (prefName.EqualsLiteral("security.tls.enable_0rtt_data")) {
1240     SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
1241                          Preferences::GetBool("security.tls.enable_0rtt_data",
1242                                               ENABLED_0RTT_DATA_DEFAULT));
1243   } else if (prefName.EqualsLiteral(
1244                  "security.tls.enable_post_handshake_auth")) {
1245     SSL_OptionSetDefault(
1246         SSL_ENABLE_POST_HANDSHAKE_AUTH,
1247         Preferences::GetBool("security.tls.enable_post_handshake_auth",
1248                              ENABLED_POST_HANDSHAKE_AUTH_DEFAULT));
1249   } else if (prefName.EqualsLiteral(
1250                  "security.tls.enable_delegated_credentials")) {
1251     SSL_OptionSetDefault(
1252         SSL_ENABLE_DELEGATED_CREDENTIALS,
1253         Preferences::GetBool("security.tls.enable_delegated_credentials",
1254                              DELEGATED_CREDENTIALS_ENABLED_DEFAULT));
1255   } else if (prefName.EqualsLiteral(
1256                  "security.ssl.disable_session_identifiers")) {
1257     ConfigureTLSSessionIdentifiers();
1258   } else {
1259     prefFound = false;
1260   }
1261   return prefFound;
1262 }
1263 
SetValidationOptionsCommon()1264 void SetValidationOptionsCommon() {
1265   // Note that the code in this function should be kept in sync with
1266   // gCallbackSecurityPrefs in nsIOService.cpp.
1267   bool ocspStaplingEnabled =
1268       Preferences::GetBool("security.ssl.enable_ocsp_stapling", true);
1269   PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
1270   PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
1271 
1272   bool ocspMustStapleEnabled =
1273       Preferences::GetBool("security.ssl.enable_ocsp_must_staple", true);
1274   PublicSSLState()->SetOCSPMustStapleEnabled(ocspMustStapleEnabled);
1275   PrivateSSLState()->SetOCSPMustStapleEnabled(ocspMustStapleEnabled);
1276 
1277   const CertVerifier::CertificateTransparencyMode defaultCTMode =
1278       CertVerifier::CertificateTransparencyMode::TelemetryOnly;
1279   CertVerifier::CertificateTransparencyMode ctMode =
1280       static_cast<CertVerifier::CertificateTransparencyMode>(
1281           Preferences::GetInt("security.pki.certificate_transparency.mode",
1282                               static_cast<int32_t>(defaultCTMode)));
1283   switch (ctMode) {
1284     case CertVerifier::CertificateTransparencyMode::Disabled:
1285     case CertVerifier::CertificateTransparencyMode::TelemetryOnly:
1286       break;
1287     default:
1288       ctMode = defaultCTMode;
1289       break;
1290   }
1291   bool sctsEnabled =
1292       ctMode != CertVerifier::CertificateTransparencyMode::Disabled;
1293   PublicSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
1294   PrivateSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
1295 
1296   BRNameMatchingPolicy::Mode nameMatchingMode =
1297       static_cast<BRNameMatchingPolicy::Mode>(Preferences::GetInt(
1298           "security.pki.name_matching_mode",
1299           static_cast<int32_t>(BRNameMatchingPolicy::Mode::DoNotEnforce)));
1300   switch (nameMatchingMode) {
1301     case BRNameMatchingPolicy::Mode::Enforce:
1302     case BRNameMatchingPolicy::Mode::EnforceAfter23August2015:
1303     case BRNameMatchingPolicy::Mode::EnforceAfter23August2016:
1304     case BRNameMatchingPolicy::Mode::DoNotEnforce:
1305       break;
1306     default:
1307       nameMatchingMode = BRNameMatchingPolicy::Mode::DoNotEnforce;
1308       break;
1309   }
1310   PublicSSLState()->SetNameMatchingMode(nameMatchingMode);
1311   PrivateSSLState()->SetNameMatchingMode(nameMatchingMode);
1312 }
1313 
1314 namespace {
1315 
1316 class CipherSuiteChangeObserver : public nsIObserver {
1317  public:
1318   NS_DECL_ISUPPORTS
1319   NS_DECL_NSIOBSERVER
1320 
1321   static nsresult StartObserve();
1322 
1323  protected:
1324   virtual ~CipherSuiteChangeObserver() = default;
1325 
1326  private:
1327   static StaticRefPtr<CipherSuiteChangeObserver> sObserver;
1328   CipherSuiteChangeObserver() = default;
1329 };
1330 
1331 NS_IMPL_ISUPPORTS(CipherSuiteChangeObserver, nsIObserver)
1332 
1333 // static
1334 StaticRefPtr<CipherSuiteChangeObserver> CipherSuiteChangeObserver::sObserver;
1335 
1336 // static
StartObserve()1337 nsresult CipherSuiteChangeObserver::StartObserve() {
1338   MOZ_ASSERT(NS_IsMainThread(),
1339              "CipherSuiteChangeObserver::StartObserve() can only be accessed "
1340              "on the main thread");
1341   if (!sObserver) {
1342     RefPtr<CipherSuiteChangeObserver> observer =
1343         new CipherSuiteChangeObserver();
1344     nsresult rv = Preferences::AddStrongObserver(observer.get(), "security.");
1345     if (NS_FAILED(rv)) {
1346       sObserver = nullptr;
1347       return rv;
1348     }
1349 
1350     nsCOMPtr<nsIObserverService> observerService =
1351         mozilla::services::GetObserverService();
1352     observerService->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
1353                                  false);
1354 
1355     sObserver = observer;
1356   }
1357   return NS_OK;
1358 }
1359 
Observe(nsISupports *,const char * aTopic,const char16_t * someData)1360 nsresult CipherSuiteChangeObserver::Observe(nsISupports* /*aSubject*/,
1361                                             const char* aTopic,
1362                                             const char16_t* someData) {
1363   MOZ_ASSERT(NS_IsMainThread(),
1364              "CipherSuiteChangeObserver::Observe can only be accessed on main "
1365              "thread");
1366   if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
1367     NS_ConvertUTF16toUTF8 prefName(someData);
1368     // Look through the cipher table and set according to pref setting
1369     const CipherPref* const cp = sCipherPrefs;
1370     for (size_t i = 0; cp[i].pref; ++i) {
1371       if (prefName.Equals(cp[i].pref)) {
1372         bool cipherEnabled =
1373             Preferences::GetBool(cp[i].pref, cp[i].enabledByDefault);
1374         SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
1375         nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
1376         break;
1377       }
1378     }
1379   } else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
1380     Preferences::RemoveObserver(this, "security.");
1381     MOZ_ASSERT(sObserver.get() == this);
1382     sObserver = nullptr;
1383     nsCOMPtr<nsIObserverService> observerService =
1384         mozilla::services::GetObserverService();
1385     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
1386   }
1387   return NS_OK;
1388 }
1389 
1390 }  // namespace
1391 
setValidationOptions(bool isInitialSetting,const mozilla::MutexAutoLock & proofOfLock)1392 void nsNSSComponent::setValidationOptions(
1393     bool isInitialSetting, const mozilla::MutexAutoLock& proofOfLock) {
1394   // We access prefs so this must be done on the main thread.
1395   MOZ_ASSERT(NS_IsMainThread());
1396   if (NS_WARN_IF(!NS_IsMainThread())) {
1397     return;
1398   }
1399 
1400   SetValidationOptionsCommon();
1401 
1402   const CertVerifier::CertificateTransparencyMode defaultCTMode =
1403       CertVerifier::CertificateTransparencyMode::TelemetryOnly;
1404   CertVerifier::CertificateTransparencyMode ctMode =
1405       static_cast<CertVerifier::CertificateTransparencyMode>(
1406           Preferences::GetInt("security.pki.certificate_transparency.mode",
1407                               static_cast<int32_t>(defaultCTMode)));
1408   switch (ctMode) {
1409     case CertVerifier::CertificateTransparencyMode::Disabled:
1410     case CertVerifier::CertificateTransparencyMode::TelemetryOnly:
1411       break;
1412     default:
1413       ctMode = defaultCTMode;
1414       break;
1415   }
1416 
1417   // This preference controls whether we do OCSP fetching and does not affect
1418   // OCSP stapling.
1419   // 0 = disabled, 1 = enabled
1420   int32_t ocspEnabled =
1421       Preferences::GetInt("security.OCSP.enabled", OCSP_ENABLED_DEFAULT);
1422 
1423   bool ocspRequired =
1424       ocspEnabled && Preferences::GetBool("security.OCSP.require", false);
1425 
1426   // We measure the setting of the pref at startup only to minimize noise by
1427   // addons that may muck with the settings, though it probably doesn't matter.
1428   if (isInitialSetting) {
1429     Telemetry::Accumulate(Telemetry::CERT_OCSP_ENABLED, ocspEnabled);
1430     Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
1431   }
1432 
1433   CertVerifier::SHA1Mode sha1Mode =
1434       static_cast<CertVerifier::SHA1Mode>(Preferences::GetInt(
1435           "security.pki.sha1_enforcement_level",
1436           static_cast<int32_t>(CertVerifier::SHA1Mode::Allowed)));
1437   switch (sha1Mode) {
1438     case CertVerifier::SHA1Mode::Allowed:
1439     case CertVerifier::SHA1Mode::Forbidden:
1440     case CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden:
1441     case CertVerifier::SHA1Mode::ImportedRoot:
1442     case CertVerifier::SHA1Mode::ImportedRootOrBefore2016:
1443       break;
1444     default:
1445       sha1Mode = CertVerifier::SHA1Mode::Allowed;
1446       break;
1447   }
1448 
1449   // Convert a previously-available setting to a safe one.
1450   if (sha1Mode == CertVerifier::SHA1Mode::UsedToBeBefore2016ButNowIsForbidden) {
1451     sha1Mode = CertVerifier::SHA1Mode::Forbidden;
1452   }
1453 
1454   NetscapeStepUpPolicy netscapeStepUpPolicy =
1455       static_cast<NetscapeStepUpPolicy>(Preferences::GetUint(
1456           "security.pki.netscape_step_up_policy",
1457           static_cast<uint32_t>(NetscapeStepUpPolicy::AlwaysMatch)));
1458   switch (netscapeStepUpPolicy) {
1459     case NetscapeStepUpPolicy::AlwaysMatch:
1460     case NetscapeStepUpPolicy::MatchBefore23August2016:
1461     case NetscapeStepUpPolicy::MatchBefore23August2015:
1462     case NetscapeStepUpPolicy::NeverMatch:
1463       break;
1464     default:
1465       netscapeStepUpPolicy = NetscapeStepUpPolicy::AlwaysMatch;
1466       break;
1467   }
1468 
1469   CRLiteMode defaultCRLiteMode = CRLiteMode::Disabled;
1470   CRLiteMode crliteMode = static_cast<CRLiteMode>(Preferences::GetUint(
1471       "security.pki.crlite_mode", static_cast<uint32_t>(defaultCRLiteMode)));
1472   switch (crliteMode) {
1473     case CRLiteMode::Disabled:
1474     case CRLiteMode::TelemetryOnly:
1475     case CRLiteMode::Enforce:
1476       break;
1477     default:
1478       crliteMode = defaultCRLiteMode;
1479       break;
1480   }
1481 
1482   uint32_t defaultCRLiteCTMergeDelaySeconds =
1483       60 * 60 * 28;  // 28 hours in seconds
1484   uint64_t maxCRLiteCTMergeDelaySeconds = 60 * 60 * 24 * 365;
1485   uint64_t crliteCTMergeDelaySeconds =
1486       Preferences::GetUint("security.pki.crlite_ct_merge_delay_seconds",
1487                            defaultCRLiteCTMergeDelaySeconds);
1488   if (crliteCTMergeDelaySeconds > maxCRLiteCTMergeDelaySeconds) {
1489     crliteCTMergeDelaySeconds = maxCRLiteCTMergeDelaySeconds;
1490   }
1491 
1492   CertVerifier::OcspDownloadConfig odc;
1493   CertVerifier::OcspStrictConfig osc;
1494   uint32_t certShortLifetimeInDays;
1495   TimeDuration softTimeout;
1496   TimeDuration hardTimeout;
1497 
1498   GetRevocationBehaviorFromPrefs(&odc, &osc, &certShortLifetimeInDays,
1499                                  softTimeout, hardTimeout, proofOfLock);
1500 
1501   mDefaultCertVerifier = new SharedCertVerifier(
1502       odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays, sha1Mode,
1503       PublicSSLState()->NameMatchingMode(), netscapeStepUpPolicy, ctMode,
1504       crliteMode, crliteCTMergeDelaySeconds, mEnterpriseCerts);
1505 }
1506 
UpdateCertVerifierWithEnterpriseRoots()1507 void nsNSSComponent::UpdateCertVerifierWithEnterpriseRoots() {
1508   MutexAutoLock lock(mMutex);
1509   MOZ_ASSERT(mDefaultCertVerifier);
1510   if (NS_WARN_IF(!mDefaultCertVerifier)) {
1511     return;
1512   }
1513 
1514   RefPtr<SharedCertVerifier> oldCertVerifier = mDefaultCertVerifier;
1515   mDefaultCertVerifier = new SharedCertVerifier(
1516       oldCertVerifier->mOCSPDownloadConfig,
1517       oldCertVerifier->mOCSPStrict ? CertVerifier::ocspStrict
1518                                    : CertVerifier::ocspRelaxed,
1519       oldCertVerifier->mOCSPTimeoutSoft, oldCertVerifier->mOCSPTimeoutHard,
1520       oldCertVerifier->mCertShortLifetimeInDays, oldCertVerifier->mSHA1Mode,
1521       oldCertVerifier->mNameMatchingMode,
1522       oldCertVerifier->mNetscapeStepUpPolicy, oldCertVerifier->mCTMode,
1523       oldCertVerifier->mCRLiteMode, oldCertVerifier->mCRLiteCTMergeDelaySeconds,
1524       mEnterpriseCerts);
1525 }
1526 
1527 // Enable the TLS versions given in the prefs, defaulting to TLS 1.0 (min) and
1528 // TLS 1.2 (max) when the prefs aren't set or set to invalid values.
SetEnabledTLSVersions()1529 nsresult nsNSSComponent::SetEnabledTLSVersions() {
1530   // Keep these values in sync with all.js.
1531   // 1 means TLS 1.0, 2 means TLS 1.1, etc.
1532   static const uint32_t PSM_DEFAULT_MIN_TLS_VERSION = 3;
1533   static const uint32_t PSM_DEFAULT_MAX_TLS_VERSION = 4;
1534   static const uint32_t PSM_DEPRECATED_TLS_VERSION = 1;
1535 
1536   uint32_t minFromPrefs = Preferences::GetUint("security.tls.version.min",
1537                                                PSM_DEFAULT_MIN_TLS_VERSION);
1538   uint32_t maxFromPrefs = Preferences::GetUint("security.tls.version.max",
1539                                                PSM_DEFAULT_MAX_TLS_VERSION);
1540 
1541   // This override should be removed some time after
1542   // PSM_DEFAULT_MIN_TLS_VERSION is increased to 3.
1543   bool enableDeprecated =
1544       Preferences::GetBool("security.tls.version.enable-deprecated", false);
1545   if (enableDeprecated) {
1546     minFromPrefs = std::min(minFromPrefs, PSM_DEPRECATED_TLS_VERSION);
1547   }
1548 
1549   SSLVersionRange defaults = {
1550       SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MIN_TLS_VERSION,
1551       SSL_LIBRARY_VERSION_3_0 + PSM_DEFAULT_MAX_TLS_VERSION};
1552   SSLVersionRange filledInRange;
1553   FillTLSVersionRange(filledInRange, minFromPrefs, maxFromPrefs, defaults);
1554 
1555   SECStatus srv =
1556       SSL_VersionRangeSetDefault(ssl_variant_stream, &filledInRange);
1557   if (srv != SECSuccess) {
1558     return NS_ERROR_FAILURE;
1559   }
1560 
1561   return NS_OK;
1562 }
1563 
1564 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1565 // If the profile directory is on a networked drive, we want to set the
1566 // environment variable NSS_SDB_USE_CACHE to yes (as long as it hasn't been set
1567 // before).
SetNSSDatabaseCacheModeAsAppropriate()1568 static void SetNSSDatabaseCacheModeAsAppropriate() {
1569   MOZ_ASSERT(NS_IsMainThread());
1570 
1571   nsCOMPtr<nsIFile> profileFile;
1572   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
1573                                        getter_AddRefs(profileFile));
1574   if (NS_FAILED(rv)) {
1575     // We're probably running without a profile directory, so this is
1576     // irrelevant.
1577     return;
1578   }
1579 
1580   static const char sNSS_SDB_USE_CACHE[] = "NSS_SDB_USE_CACHE";
1581   static const char sNSS_SDB_USE_CACHE_WITH_VALUE[] = "NSS_SDB_USE_CACHE=yes";
1582   auto profilePath = profileFile->NativePath();
1583 
1584 #  if defined(XP_LINUX) && !defined(ANDROID)
1585   struct statfs statfs_s;
1586   if (statfs(profilePath.get(), &statfs_s) == 0 &&
1587       statfs_s.f_type == NFS_SUPER_MAGIC && !PR_GetEnv(sNSS_SDB_USE_CACHE)) {
1588     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1589             ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
1590              "setting NSS_SDB_USE_CACHE"));
1591     PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE);
1592   } else {
1593     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("not setting NSS_SDB_USE_CACHE"));
1594   }
1595 #  endif  // defined(XP_LINUX) && !defined(ANDROID)
1596 
1597 #  ifdef XP_WIN
1598   wchar_t volPath[MAX_PATH];
1599   if (::GetVolumePathNameW(profilePath.get(), volPath, MAX_PATH) &&
1600       ::GetDriveTypeW(volPath) == DRIVE_REMOTE &&
1601       !PR_GetEnv(sNSS_SDB_USE_CACHE)) {
1602     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1603             ("profile is remote (and NSS_SDB_USE_CACHE wasn't set): "
1604              "setting NSS_SDB_USE_CACHE"));
1605     PR_SetEnv(sNSS_SDB_USE_CACHE_WITH_VALUE);
1606   } else {
1607     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("not setting NSS_SDB_USE_CACHE"));
1608   }
1609 #  endif  // XP_WIN
1610 }
1611 #endif  // defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1612 
GetNSSProfilePath(nsAutoCString & aProfilePath)1613 static nsresult GetNSSProfilePath(nsAutoCString& aProfilePath) {
1614   aProfilePath.Truncate();
1615   nsCOMPtr<nsIFile> profileFile;
1616   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
1617                                        getter_AddRefs(profileFile));
1618   if (NS_FAILED(rv)) {
1619     NS_WARNING(
1620         "NSS will be initialized without a profile directory. "
1621         "Some things may not work as expected.");
1622     return NS_OK;
1623   }
1624 
1625 #if defined(XP_WIN)
1626   // SQLite always takes UTF-8 file paths regardless of the current system
1627   // code page.
1628   nsCOMPtr<nsILocalFileWin> profileFileWin(do_QueryInterface(profileFile));
1629   if (!profileFileWin) {
1630     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
1631             ("Could not get nsILocalFileWin for profile directory.\n"));
1632     return NS_ERROR_FAILURE;
1633   }
1634   nsAutoString u16ProfilePath;
1635   rv = profileFileWin->GetCanonicalPath(u16ProfilePath);
1636   CopyUTF16toUTF8(u16ProfilePath, aProfilePath);
1637 #else
1638   rv = profileFile->GetNativePath(aProfilePath);
1639 #endif
1640   if (NS_FAILED(rv)) {
1641     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
1642             ("Could not get native path for profile directory.\n"));
1643     return rv;
1644   }
1645 
1646   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1647           ("NSS profile at '%s'\n", aProfilePath.get()));
1648   return NS_OK;
1649 }
1650 
1651 #ifndef ANDROID
1652 // Given a profile path, attempt to rename the PKCS#11 module DB to
1653 // "pkcs11.txt.fips". In the case of a catastrophic failure (e.g. out of
1654 // memory), returns a failing nsresult. If execution could conceivably proceed,
1655 // returns NS_OK even if renaming the file didn't work. This simplifies the
1656 // logic of the calling code.
1657 // |profilePath| is encoded in UTF-8.
AttemptToRenamePKCS11ModuleDB(const nsACString & profilePath)1658 static nsresult AttemptToRenamePKCS11ModuleDB(const nsACString& profilePath) {
1659   nsCOMPtr<nsIFile> profileDir = do_CreateInstance("@mozilla.org/file/local;1");
1660   if (!profileDir) {
1661     return NS_ERROR_FAILURE;
1662   }
1663 #  ifdef XP_WIN
1664   // |profilePath| is encoded in UTF-8 because SQLite always takes UTF-8 file
1665   // paths regardless of the current system code page.
1666   nsresult rv = profileDir->InitWithPath(NS_ConvertUTF8toUTF16(profilePath));
1667 #  else
1668   nsresult rv = profileDir->InitWithNativePath(profilePath);
1669 #  endif
1670   if (NS_FAILED(rv)) {
1671     return rv;
1672   }
1673   const char* moduleDBFilename = "pkcs11.txt";
1674   nsAutoCString destModuleDBFilename(moduleDBFilename);
1675   destModuleDBFilename.Append(".fips");
1676   nsCOMPtr<nsIFile> dbFile;
1677   rv = profileDir->Clone(getter_AddRefs(dbFile));
1678   if (NS_FAILED(rv) || !dbFile) {
1679     return NS_ERROR_FAILURE;
1680   }
1681   rv = dbFile->AppendNative(nsAutoCString(moduleDBFilename));
1682   if (NS_FAILED(rv)) {
1683     return rv;
1684   }
1685   // If the PKCS#11 module DB doesn't exist, renaming it won't help.
1686   bool exists;
1687   rv = dbFile->Exists(&exists);
1688   if (NS_FAILED(rv)) {
1689     return rv;
1690   }
1691   // This is strange, but not a catastrophic failure.
1692   if (!exists) {
1693     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1694             ("%s doesn't exist?", moduleDBFilename));
1695     return NS_OK;
1696   }
1697   nsCOMPtr<nsIFile> destDBFile;
1698   rv = profileDir->Clone(getter_AddRefs(destDBFile));
1699   if (NS_FAILED(rv) || !destDBFile) {
1700     return NS_ERROR_FAILURE;
1701   }
1702   rv = destDBFile->AppendNative(destModuleDBFilename);
1703   if (NS_FAILED(rv)) {
1704     return rv;
1705   }
1706   // If the destination exists, presumably we've already tried this. Doing it
1707   // again won't help.
1708   rv = destDBFile->Exists(&exists);
1709   if (NS_FAILED(rv)) {
1710     return rv;
1711   }
1712   // Unfortunate, but not a catastrophic failure.
1713   if (exists) {
1714     MOZ_LOG(
1715         gPIPNSSLog, LogLevel::Debug,
1716         ("%s already exists - not overwriting", destModuleDBFilename.get()));
1717     return NS_OK;
1718   }
1719   // Now do the actual move.
1720   // This may fail on, e.g., a read-only file system. This would be unfortunate,
1721   // but again it isn't catastropic and we would want to fall back to
1722   // initializing NSS in no-DB mode.
1723   Unused << dbFile->MoveToNative(profileDir, destModuleDBFilename);
1724   return NS_OK;
1725 }
1726 #endif  // ifndef ANDROID
1727 
1728 // Given a profile directory, attempt to initialize NSS. If nocertdb is true,
1729 // (or if we don't have a profile directory) simply initialize NSS in no DB mode
1730 // and return. Otherwise, first attempt to initialize in read/write mode, and
1731 // then read-only mode if that fails. If both attempts fail, we may be failing
1732 // to initialize an NSS DB collection that has FIPS mode enabled. Attempt to
1733 // ascertain if this is the case, and if so, rename the offending PKCS#11 module
1734 // DB so we can (hopefully) initialize NSS in read-write mode. Again attempt
1735 // read-only mode if that fails. Finally, fall back to no DB mode. On Android
1736 // we can skip the FIPS workaround since it was never possible to enable FIPS
1737 // there anyway.
1738 // |profilePath| is encoded in UTF-8.
InitializeNSSWithFallbacks(const nsACString & profilePath,bool nocertdb,bool safeMode)1739 static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
1740                                            bool nocertdb, bool safeMode) {
1741   if (nocertdb || profilePath.IsEmpty()) {
1742     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1743             ("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
1744     SECStatus srv = NSS_NoDB_Init(nullptr);
1745 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1746     if (srv != SECSuccess) {
1747       MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1748                               PR_GetError());
1749     }
1750 #endif
1751     return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
1752   }
1753 
1754   // Try read/write mode. If we're in safeMode, we won't load PKCS#11 modules.
1755 #ifndef ANDROID
1756   PRErrorCode savedPRErrorCode1;
1757 #endif  // ifndef ANDROID
1758   PKCS11DBConfig safeModeDBConfig =
1759       safeMode ? PKCS11DBConfig::DoNotLoadModules : PKCS11DBConfig::LoadModules;
1760   SECStatus srv = ::mozilla::psm::InitializeNSS(
1761       profilePath, NSSDBConfig::ReadWrite, safeModeDBConfig);
1762   if (srv == SECSuccess) {
1763     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode"));
1764     return NS_OK;
1765   }
1766 #ifndef ANDROID
1767   savedPRErrorCode1 = PR_GetError();
1768   PRErrorCode savedPRErrorCode2;
1769 #endif  // ifndef ANDROID
1770   // That failed. Try read-only mode.
1771   srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
1772                                       safeModeDBConfig);
1773   if (srv == SECSuccess) {
1774     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r-o mode"));
1775     return NS_OK;
1776   }
1777 #ifndef ANDROID
1778   savedPRErrorCode2 = PR_GetError();
1779 
1780   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1781           ("failed to initialize NSS with codes %d %d", savedPRErrorCode1,
1782            savedPRErrorCode2));
1783 #endif  // ifndef ANDROID
1784 
1785 #ifndef ANDROID
1786   // That failed as well. Maybe we're trying to load a PKCS#11 module DB that is
1787   // in FIPS mode, but we don't support FIPS? Test load NSS without PKCS#11
1788   // modules. If that succeeds, that's probably what's going on.
1789   if (!safeMode && (savedPRErrorCode1 == SEC_ERROR_LEGACY_DATABASE ||
1790                     savedPRErrorCode2 == SEC_ERROR_LEGACY_DATABASE ||
1791                     savedPRErrorCode1 == SEC_ERROR_PKCS11_DEVICE_ERROR ||
1792                     savedPRErrorCode2 == SEC_ERROR_PKCS11_DEVICE_ERROR)) {
1793     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("attempting no-module db init"));
1794     // It would make sense to initialize NSS in read-only mode here since this
1795     // is just a test to see if the PKCS#11 module DB being in FIPS mode is the
1796     // problem, but for some reason the combination of read-only and no-moddb
1797     // flags causes NSS initialization to fail, so unfortunately we have to use
1798     // read-write mode.
1799     srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
1800                                         PKCS11DBConfig::DoNotLoadModules);
1801     if (srv == SECSuccess) {
1802       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FIPS may be the problem"));
1803       // Unload NSS so we can attempt to fix this situation for the user.
1804       srv = NSS_Shutdown();
1805       if (srv != SECSuccess) {
1806 #  ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1807         MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1808                                 PR_GetError());
1809 #  endif
1810         return NS_ERROR_FAILURE;
1811       }
1812       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trying to rename module db"));
1813       // If this fails non-catastrophically, we'll attempt to initialize NSS
1814       // again in r/w then r-o mode (both of which will fail), and then we'll
1815       // fall back to NSS_NoDB_Init, which is the behavior we want.
1816       nsresult rv = AttemptToRenamePKCS11ModuleDB(profilePath);
1817       if (NS_FAILED(rv)) {
1818 #  ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1819         // An nsresult is a uint32_t, but at least one of our compilers doesn't
1820         // like this format string unless we include the cast. <shruggie emoji>
1821         MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %u",
1822                                 (uint32_t)rv);
1823 #  endif
1824         return rv;
1825       }
1826       srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
1827                                           PKCS11DBConfig::LoadModules);
1828       if (srv == SECSuccess) {
1829         MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r/w mode"));
1830         return NS_OK;
1831       }
1832       srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
1833                                           PKCS11DBConfig::LoadModules);
1834       if (srv == SECSuccess) {
1835         MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r-o mode"));
1836         return NS_OK;
1837       }
1838     }
1839   }
1840 #endif
1841 
1842   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("last-resort NSS_NoDB_Init"));
1843   srv = NSS_NoDB_Init(nullptr);
1844 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1845   if (srv != SECSuccess) {
1846     MOZ_CRASH_UNSAFE_PRINTF("InitializeNSSWithFallbacks failed: %d",
1847                             PR_GetError());
1848   }
1849 #endif
1850   return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
1851 }
1852 
InitializeNSS()1853 nsresult nsNSSComponent::InitializeNSS() {
1854   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::InitializeNSS\n"));
1855   AUTO_PROFILER_LABEL("nsNSSComponent::InitializeNSS", OTHER);
1856   AUTO_PROFILER_TRACING_MARKER("NSS", "nsNSSComponent::InitializeNSS", OTHER);
1857 
1858   static_assert(
1859       nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
1860           nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
1861           nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
1862           nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
1863       "You must update the values in nsINSSErrorsService.idl");
1864 
1865   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization beginning\n"));
1866 
1867   nsAutoCString profileStr;
1868   nsresult rv = GetNSSProfilePath(profileStr);
1869   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1870   if (NS_FAILED(rv)) {
1871     return NS_ERROR_NOT_AVAILABLE;
1872   }
1873 
1874 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
1875   SetNSSDatabaseCacheModeAsAppropriate();
1876 #endif
1877 
1878   bool nocertdb = Preferences::GetBool("security.nocertdb", false);
1879   bool inSafeMode = true;
1880   nsCOMPtr<nsIXULRuntime> runtime(do_GetService("@mozilla.org/xre/runtime;1"));
1881   // There might not be an nsIXULRuntime in embedded situations. This will
1882   // default to assuming we are in safe mode (as a result, no external PKCS11
1883   // modules will be loaded).
1884   if (runtime) {
1885     rv = runtime->GetInSafeMode(&inSafeMode);
1886     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1887     if (NS_FAILED(rv)) {
1888       return rv;
1889     }
1890   }
1891   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("inSafeMode: %u\n", inSafeMode));
1892 
1893   rv = InitializeNSSWithFallbacks(profileStr, nocertdb, inSafeMode);
1894   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1895   if (NS_FAILED(rv)) {
1896     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to initialize NSS"));
1897     return rv;
1898   }
1899 
1900   PK11_SetPasswordFunc(PK11PasswordPrompt);
1901 
1902   // Register an observer so we can inform NSS when these prefs change
1903   Preferences::AddStrongObserver(this, "security.");
1904 
1905   rv = CommonInit();
1906 
1907   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1908   if (NS_FAILED(rv)) {
1909     return NS_ERROR_UNEXPECTED;
1910   }
1911 
1912   nsCOMPtr<nsICertOverrideService> certOverrideService(
1913       do_GetService(NS_CERTOVERRIDE_CONTRACTID));
1914   nsCOMPtr<nsIClientAuthRememberService> clientAuthRememberService(
1915       do_GetService(NS_CLIENTAUTHREMEMBERSERVICE_CONTRACTID));
1916   nsCOMPtr<nsISiteSecurityService> siteSecurityService(
1917       do_GetService(NS_SSSERVICE_CONTRACTID));
1918   nsCOMPtr<nsICertStorage> certStorage(do_GetService(NS_CERT_STORAGE_CID));
1919 
1920   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization done\n"));
1921 
1922   {
1923     MutexAutoLock lock(mMutex);
1924 
1925     // ensure we have initial values for various root hashes
1926 #ifdef DEBUG
1927     mTestBuiltInRootHash.Truncate();
1928     Preferences::GetString("security.test.built_in_root_hash",
1929                            mTestBuiltInRootHash);
1930 #endif
1931     mContentSigningRootHash.Truncate();
1932     Preferences::GetCString("security.content.signature.root_hash",
1933                             mContentSigningRootHash);
1934 
1935     mMitmCanaryIssuer.Truncate();
1936     Preferences::GetString("security.pki.mitm_canary_issuer",
1937                            mMitmCanaryIssuer);
1938     mMitmDetecionEnabled =
1939         Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
1940 
1941     // Set dynamic options from prefs.
1942     setValidationOptions(true, lock);
1943 
1944     bool importEnterpriseRoots =
1945         Preferences::GetBool(kEnterpriseRootModePref, false);
1946     uint32_t familySafetyMode =
1947         Preferences::GetUint(kFamilySafetyModePref, kFamilySafetyModeDefault);
1948     Vector<nsCString> possibleLoadableRootsLocations;
1949     rv = ListPossibleLoadableRootsLocations(possibleLoadableRootsLocations);
1950     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1951     if (NS_FAILED(rv)) {
1952       return rv;
1953     }
1954 
1955     bool loadOSClientCertsModule =
1956         Preferences::GetBool(kOSClientCertsModulePref, false);
1957     Maybe<nsCString> maybeOSClientCertsModuleLocation;
1958     if (loadOSClientCertsModule) {
1959       nsAutoCString libraryDir;
1960       if (NS_SUCCEEDED(GetDirectoryPath(NS_GRE_BIN_DIR, libraryDir))) {
1961         maybeOSClientCertsModuleLocation.emplace(libraryDir);
1962       }
1963     }
1964     RefPtr<LoadLoadableCertsTask> loadLoadableCertsTask(
1965         new LoadLoadableCertsTask(this, importEnterpriseRoots, familySafetyMode,
1966                                   std::move(possibleLoadableRootsLocations),
1967                                   std::move(maybeOSClientCertsModuleLocation)));
1968     rv = loadLoadableCertsTask->Dispatch();
1969     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
1970     if (NS_FAILED(rv)) {
1971       return rv;
1972     }
1973 
1974     mLoadLoadableCertsTaskDispatched = true;
1975     return NS_OK;
1976   }
1977 }
1978 
ShutdownNSS()1979 void nsNSSComponent::ShutdownNSS() {
1980   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ShutdownNSS\n"));
1981   MOZ_RELEASE_ASSERT(NS_IsMainThread());
1982 
1983   bool loadLoadableCertsTaskDispatched;
1984   {
1985     MutexAutoLock lock(mMutex);
1986     loadLoadableCertsTaskDispatched = mLoadLoadableCertsTaskDispatched;
1987   }
1988   // We have to block until the load loadable certs task has completed, because
1989   // otherwise we might try to unload the loaded modules while the loadable
1990   // certs loading thread is setting up EV information, which can cause
1991   // it to fail to find the roots it is expecting. However, if initialization
1992   // failed, we won't have dispatched the load loadable certs background task.
1993   // In that case, we don't want to block on an event that will never happen.
1994   if (loadLoadableCertsTaskDispatched) {
1995     Unused << BlockUntilLoadableCertsLoaded();
1996   }
1997 
1998   ::mozilla::psm::UnloadUserModules();
1999 
2000   PK11_SetPasswordFunc((PK11PasswordFunc) nullptr);
2001 
2002   Preferences::RemoveObserver(this, "security.");
2003 
2004   if (mIntermediatePreloadingHealerTimer) {
2005     mIntermediatePreloadingHealerTimer->Cancel();
2006     mIntermediatePreloadingHealerTimer = nullptr;
2007   }
2008 
2009   // Release the default CertVerifier. This will cause any held NSS resources
2010   // to be released.
2011   MutexAutoLock lock(mMutex);
2012   mDefaultCertVerifier = nullptr;
2013   // We don't actually shut down NSS - XPCOM does, after all threads have been
2014   // joined and the component manager has been shut down (and so there shouldn't
2015   // be any XPCOM objects holding NSS resources).
2016 }
2017 
2018 // The aim of the intermediate preloading healer is to remove intermediates
2019 // that were previously cached by PSM in the NSS certdb that are now preloaded
2020 // in cert_storage. When cached by PSM, these certificates will have no
2021 // particular trust set - they are intended to inherit their trust. If, upon
2022 // examination, these certificates do have trust bits set that affect
2023 // certificate validation, they must have been modified by the user, so we want
2024 // to leave them alone.
CertHasDefaultTrust(CERTCertificate * cert)2025 bool CertHasDefaultTrust(CERTCertificate* cert) {
2026   CERTCertTrust trust;
2027   if (CERT_GetCertTrust(cert, &trust) != SECSuccess) {
2028     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CERT_GetCertTrust failed"));
2029     return false;
2030   }
2031   // This is the active distrust test for CA certificates (this is expected to
2032   // be an intermediate).
2033   if ((trust.sslFlags & (CERTDB_TRUSTED_CA | CERTDB_TERMINAL_RECORD)) ==
2034       CERTDB_TERMINAL_RECORD) {
2035     return false;
2036   }
2037   // This is the trust anchor test.
2038   if (trust.sslFlags & CERTDB_TRUSTED_CA) {
2039     return false;
2040   }
2041   // This is the active distrust test for CA certificates (this is expected to
2042   // be an intermediate).
2043   if ((trust.emailFlags & (CERTDB_TRUSTED_CA | CERTDB_TERMINAL_RECORD)) ==
2044       CERTDB_TERMINAL_RECORD) {
2045     return false;
2046   }
2047   // This is the trust anchor test.
2048   if (trust.emailFlags & CERTDB_TRUSTED_CA) {
2049     return false;
2050   }
2051   return true;
2052 }
2053 
IntermediatePreloadingHealerCallback(nsITimer *,void *)2054 void IntermediatePreloadingHealerCallback(nsITimer*, void*) {
2055   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2056           ("IntermediatePreloadingHealerCallback"));
2057 
2058   if (AppShutdown::IsShuttingDown()) {
2059     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2060             ("Exiting healer due to app shutdown"));
2061     return;
2062   }
2063 
2064   // Get the slot corresponding to the NSS certdb.
2065   UniquePK11SlotInfo softokenSlot(PK11_GetInternalKeySlot());
2066   if (!softokenSlot) {
2067     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("PK11_GetInternalKeySlot failed"));
2068     return;
2069   }
2070   // List the certificates in the NSS certdb.
2071   UniqueCERTCertList softokenCertificates(
2072       PK11_ListCertsInSlot(softokenSlot.get()));
2073   if (!softokenCertificates) {
2074     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("PK11_ListCertsInSlot failed"));
2075     return;
2076   }
2077   nsCOMPtr<nsICertStorage> certStorage(do_GetService(NS_CERT_STORAGE_CID));
2078   if (!certStorage) {
2079     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get cert_storage"));
2080     return;
2081   }
2082   Vector<UniqueCERTCertificate> certsToDelete;
2083   // For each certificate, look it up in cert_storage. If there's a match, this
2084   // is a preloaded intermediate.
2085   for (CERTCertListNode* n = CERT_LIST_HEAD(softokenCertificates);
2086        !CERT_LIST_END(n, softokenCertificates); n = CERT_LIST_NEXT(n)) {
2087     if (AppShutdown::IsShuttingDown()) {
2088       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2089               ("Exiting healer due to app shutdown"));
2090       return;
2091     }
2092 
2093     nsTArray<uint8_t> subject;
2094     subject.AppendElements(n->cert->derSubject.data, n->cert->derSubject.len);
2095     nsTArray<nsTArray<uint8_t>> certs;
2096     nsresult rv = certStorage->FindCertsBySubject(subject, certs);
2097     if (NS_FAILED(rv)) {
2098       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FindCertsBySubject failed"));
2099       break;
2100     }
2101     for (const auto& encodedCert : certs) {
2102       if (encodedCert.Length() != n->cert->derCert.len) {
2103         continue;
2104       }
2105       if (memcmp(encodedCert.Elements(), n->cert->derCert.data,
2106                  encodedCert.Length()) != 0) {
2107         continue;
2108       }
2109       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2110               ("found preloaded intermediate in certdb"));
2111       if (!CertHasDefaultTrust(n->cert)) {
2112         MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2113                 ("certificate doesn't have default trust - skipping"));
2114         continue;
2115       }
2116       UniqueCERTCertificate certCopy(CERT_DupCertificate(n->cert));
2117       if (!certCopy) {
2118         MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CERT_DupCertificate failed"));
2119         continue;
2120       }
2121       // Note that we want to remove this certificate from the NSS certdb
2122       // because it also exists in preloaded intermediate storage and is thus
2123       // superfluous.
2124       if (!certsToDelete.append(std::move(certCopy))) {
2125         MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2126                 ("append failed - out of memory?"));
2127         return;
2128       }
2129       break;
2130     }
2131     // Only delete 20 at a time.
2132     if (certsToDelete.length() >= 20) {
2133       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2134               ("found limit of 20 preloaded intermediates in certdb"));
2135       break;
2136     }
2137   }
2138   for (const auto& certToDelete : certsToDelete) {
2139     if (AppShutdown::IsShuttingDown()) {
2140       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2141               ("Exiting healer due to app shutdown"));
2142       return;
2143     }
2144     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2145             ("attempting to delete preloaded intermediate '%s'",
2146              certToDelete->subjectName));
2147     if (SEC_DeletePermCertificate(certToDelete.get()) != SECSuccess) {
2148       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2149               ("SEC_DeletePermCertificate failed"));
2150     }
2151   }
2152 
2153   // This is for tests - notify that this ran.
2154   nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
2155       "IntermediatePreloadingHealerCallbackDone", []() -> void {
2156         nsCOMPtr<nsIObserverService> observerService =
2157             mozilla::services::GetObserverService();
2158         if (observerService) {
2159           observerService->NotifyObservers(
2160               nullptr, "psm:intermediate-preloading-healer-ran", nullptr);
2161         }
2162       }));
2163   Unused << NS_DispatchToMainThread(runnable.forget());
2164 }
2165 
Init()2166 nsresult nsNSSComponent::Init() {
2167   MOZ_RELEASE_ASSERT(NS_IsMainThread());
2168   if (!NS_IsMainThread()) {
2169     return NS_ERROR_NOT_SAME_THREAD;
2170   }
2171 
2172   MOZ_ASSERT(XRE_IsParentProcess());
2173   if (!XRE_IsParentProcess()) {
2174     return NS_ERROR_NOT_AVAILABLE;
2175   }
2176 
2177   Telemetry::AutoScalarTimer<Telemetry::ScalarID::NETWORKING_NSS_INITIALIZATION>
2178       timer;
2179 
2180   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Beginning NSS initialization\n"));
2181 
2182   nsresult rv = InitializeNSS();
2183   if (NS_FAILED(rv)) {
2184     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
2185             ("nsNSSComponent::InitializeNSS() failed\n"));
2186     return rv;
2187   }
2188 
2189   rv = RegisterObservers();
2190   if (NS_FAILED(rv)) {
2191     return rv;
2192   }
2193 
2194   rv = MaybeEnableIntermediatePreloadingHealer();
2195   if (NS_FAILED(rv)) {
2196     return rv;
2197   }
2198 
2199   return NS_OK;
2200 }
2201 
MaybeEnableIntermediatePreloadingHealer()2202 nsresult nsNSSComponent::MaybeEnableIntermediatePreloadingHealer() {
2203   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2204           ("nsNSSComponent::MaybeEnableIntermediatePreloadingHealer"));
2205   MOZ_ASSERT(NS_IsMainThread());
2206   if (!NS_IsMainThread()) {
2207     return NS_ERROR_NOT_SAME_THREAD;
2208   }
2209 
2210   if (mIntermediatePreloadingHealerTimer) {
2211     mIntermediatePreloadingHealerTimer->Cancel();
2212     mIntermediatePreloadingHealerTimer = nullptr;
2213   }
2214 
2215   if (!Preferences::GetBool("security.intermediate_preloading_healer.enabled",
2216                             false)) {
2217     return NS_OK;
2218   }
2219 
2220   if (!mIntermediatePreloadingHealerTaskQueue) {
2221     nsresult rv = NS_CreateBackgroundTaskQueue(
2222         "IntermediatePreloadingHealer",
2223         getter_AddRefs(mIntermediatePreloadingHealerTaskQueue));
2224     if (NS_FAILED(rv)) {
2225       MOZ_LOG(gPIPNSSLog, LogLevel::Error,
2226               ("NS_CreateBackgroundTaskQueue failed"));
2227       return rv;
2228     }
2229   }
2230   uint32_t timerDelayMS = Preferences::GetUint(
2231       "security.intermediate_preloading_healer.timer_interval_ms",
2232       5 * 60 * 1000);
2233   nsresult rv = NS_NewTimerWithFuncCallback(
2234       getter_AddRefs(mIntermediatePreloadingHealerTimer),
2235       IntermediatePreloadingHealerCallback, nullptr, timerDelayMS,
2236       nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
2237       "IntermediatePreloadingHealer", mIntermediatePreloadingHealerTaskQueue);
2238   if (NS_FAILED(rv)) {
2239     MOZ_LOG(gPIPNSSLog, LogLevel::Error,
2240             ("NS_NewTimerWithFuncCallback failed"));
2241     return rv;
2242   }
2243   return NS_OK;
2244 }
2245 
2246 // nsISupports Implementation for the class
2247 NS_IMPL_ISUPPORTS(nsNSSComponent, nsINSSComponent, nsIObserver)
2248 
2249 static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
2250 
2251 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * someData)2252 nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
2253                         const char16_t* someData) {
2254   // In some tests, we don't receive a "profile-before-change" topic. However,
2255   // we still have to shut down before the storage service shuts down, because
2256   // closing the sql-backed softoken requires sqlite still be available. Thus,
2257   // we observe "xpcom-shutdown" just in case.
2258   if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0 ||
2259       nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
2260     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2261             ("receiving profile change or XPCOM shutdown notification"));
2262     ShutdownNSS();
2263   } else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
2264     bool clearSessionCache = true;
2265     NS_ConvertUTF16toUTF8 prefName(someData);
2266 
2267     if (HandleTLSPrefChange(prefName)) {
2268       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("HandleTLSPrefChange done"));
2269     } else if (prefName.EqualsLiteral("security.OCSP.enabled") ||
2270                prefName.EqualsLiteral("security.OCSP.require") ||
2271                prefName.EqualsLiteral(
2272                    "security.pki.cert_short_lifetime_in_days") ||
2273                prefName.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
2274                prefName.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
2275                prefName.EqualsLiteral(
2276                    "security.pki.certificate_transparency.mode") ||
2277                prefName.EqualsLiteral("security.pki.sha1_enforcement_level") ||
2278                prefName.EqualsLiteral("security.pki.name_matching_mode") ||
2279                prefName.EqualsLiteral("security.pki.netscape_step_up_policy") ||
2280                prefName.EqualsLiteral(
2281                    "security.OCSP.timeoutMilliseconds.soft") ||
2282                prefName.EqualsLiteral(
2283                    "security.OCSP.timeoutMilliseconds.hard") ||
2284                prefName.EqualsLiteral("security.pki.crlite_mode") ||
2285                prefName.EqualsLiteral(
2286                    "security.pki.crlite_ct_merge_delay_seconds")) {
2287       MutexAutoLock lock(mMutex);
2288       setValidationOptions(false, lock);
2289 #ifdef DEBUG
2290     } else if (prefName.EqualsLiteral("security.test.built_in_root_hash")) {
2291       MutexAutoLock lock(mMutex);
2292       mTestBuiltInRootHash.Truncate();
2293       Preferences::GetString("security.test.built_in_root_hash",
2294                              mTestBuiltInRootHash);
2295 #endif  // DEBUG
2296     } else if (prefName.EqualsLiteral("security.content.signature.root_hash")) {
2297       MutexAutoLock lock(mMutex);
2298       mContentSigningRootHash.Truncate();
2299       Preferences::GetCString("security.content.signature.root_hash",
2300                               mContentSigningRootHash);
2301     } else if (prefName.Equals(kEnterpriseRootModePref) ||
2302                prefName.Equals(kFamilySafetyModePref)) {
2303       UnloadEnterpriseRoots();
2304       MaybeImportEnterpriseRoots();
2305     } else if (prefName.Equals(kOSClientCertsModulePref)) {
2306       bool loadOSClientCertsModule =
2307           Preferences::GetBool(kOSClientCertsModulePref, false);
2308       AsyncLoadOrUnloadOSClientCertsModule(loadOSClientCertsModule);
2309     } else if (prefName.EqualsLiteral("security.pki.mitm_canary_issuer")) {
2310       MutexAutoLock lock(mMutex);
2311       mMitmCanaryIssuer.Truncate();
2312       Preferences::GetString("security.pki.mitm_canary_issuer",
2313                              mMitmCanaryIssuer);
2314     } else if (prefName.EqualsLiteral(
2315                    "security.pki.mitm_canary_issuer.enabled")) {
2316       MutexAutoLock lock(mMutex);
2317       mMitmDetecionEnabled =
2318           Preferences::GetBool("security.pki.mitm_canary_issuer.enabled", true);
2319     } else {
2320       clearSessionCache = false;
2321     }
2322     if (clearSessionCache) {
2323       ClearSSLExternalAndInternalSessionCache();
2324     }
2325 
2326     // Preferences that don't affect certificate verification.
2327     if (prefName.Equals("security.intermediate_preloading_healer.enabled") ||
2328         prefName.Equals(
2329             "security.intermediate_preloading_healer.timer_interval_ms")) {
2330       MaybeEnableIntermediatePreloadingHealer();
2331     }
2332   }
2333 
2334   return NS_OK;
2335 }
2336 
2337 /*static*/
GetNewPrompter(nsIPrompt ** result)2338 nsresult nsNSSComponent::GetNewPrompter(nsIPrompt** result) {
2339   NS_ENSURE_ARG_POINTER(result);
2340   *result = nullptr;
2341 
2342   if (!NS_IsMainThread()) {
2343     NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
2344     return NS_ERROR_NOT_SAME_THREAD;
2345   }
2346 
2347   nsresult rv;
2348   nsCOMPtr<nsIWindowWatcher> wwatch(
2349       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
2350   NS_ENSURE_SUCCESS(rv, rv);
2351 
2352   rv = wwatch->GetNewPrompter(0, result);
2353   NS_ENSURE_SUCCESS(rv, rv);
2354 
2355   return rv;
2356 }
2357 
LogoutAuthenticatedPK11()2358 nsresult nsNSSComponent::LogoutAuthenticatedPK11() {
2359   nsCOMPtr<nsICertOverrideService> icos =
2360       do_GetService("@mozilla.org/security/certoverride;1");
2361   if (icos) {
2362     icos->ClearValidityOverride("all:temporary-certificates"_ns, 0,
2363                                 OriginAttributes());
2364   }
2365 
2366   ClearSSLExternalAndInternalSessionCache();
2367 
2368   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
2369   if (os) {
2370     os->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
2371   }
2372 
2373   return NS_OK;
2374 }
2375 
RegisterObservers()2376 nsresult nsNSSComponent::RegisterObservers() {
2377   nsCOMPtr<nsIObserverService> observerService(
2378       do_GetService("@mozilla.org/observer-service;1"));
2379   if (!observerService) {
2380     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2381             ("nsNSSComponent: couldn't get observer service\n"));
2382     return NS_ERROR_FAILURE;
2383   }
2384 
2385   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent: adding observers\n"));
2386   // Using false for the ownsweak parameter means the observer service will
2387   // keep a strong reference to this component. As a result, this will live at
2388   // least as long as the observer service.
2389   observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
2390   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
2391 
2392   return NS_OK;
2393 }
2394 
2395 NS_IMETHODIMP
IsCertTestBuiltInRoot(CERTCertificate * cert,bool * result)2396 nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool* result) {
2397   NS_ENSURE_ARG_POINTER(cert);
2398   NS_ENSURE_ARG_POINTER(result);
2399   *result = false;
2400 
2401 #ifdef DEBUG
2402   RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
2403   if (!nsc) {
2404     return NS_ERROR_FAILURE;
2405   }
2406   nsAutoString certHash;
2407   nsresult rv = nsc->GetSha256Fingerprint(certHash);
2408   if (NS_FAILED(rv)) {
2409     return rv;
2410   }
2411 
2412   MutexAutoLock lock(mMutex);
2413   if (mTestBuiltInRootHash.IsEmpty()) {
2414     return NS_OK;
2415   }
2416 
2417   *result = mTestBuiltInRootHash.Equals(certHash);
2418 #endif  // DEBUG
2419 
2420   return NS_OK;
2421 }
2422 
2423 NS_IMETHODIMP
IsCertContentSigningRoot(const nsTArray<uint8_t> & cert,bool * result)2424 nsNSSComponent::IsCertContentSigningRoot(const nsTArray<uint8_t>& cert,
2425                                          bool* result) {
2426   NS_ENSURE_ARG_POINTER(result);
2427   *result = false;
2428   if (cert.Length() > std::numeric_limits<uint32_t>::max()) {
2429     return NS_ERROR_INVALID_ARG;
2430   }
2431   nsTArray<uint8_t> digestArray;
2432   nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, cert.Elements(),
2433                                   cert.Length(), digestArray);
2434   if (NS_FAILED(rv)) {
2435     return rv;
2436   }
2437   SECItem digestItem = {siBuffer, digestArray.Elements(),
2438                         static_cast<unsigned int>(digestArray.Length())};
2439 
2440   UniquePORTString fingerprintCString(
2441       CERT_Hexify(&digestItem, true /* use colon delimiters */));
2442   if (!fingerprintCString) {
2443     return NS_ERROR_FAILURE;
2444   }
2445 
2446   MutexAutoLock lock(mMutex);
2447   *result = mContentSigningRootHash.Equals(fingerprintCString.get());
2448   return NS_OK;
2449 }
2450 
2451 NS_IMETHODIMP
IssuerMatchesMitmCanary(const char * aCertIssuer)2452 nsNSSComponent::IssuerMatchesMitmCanary(const char* aCertIssuer) {
2453   MutexAutoLock lock(mMutex);
2454   if (mMitmDetecionEnabled && !mMitmCanaryIssuer.IsEmpty()) {
2455     nsString certIssuer = NS_ConvertUTF8toUTF16(aCertIssuer);
2456     if (mMitmCanaryIssuer.Equals(certIssuer)) {
2457       return NS_OK;
2458     }
2459   }
2460 
2461   return NS_ERROR_FAILURE;
2462 }
2463 
2464 SharedCertVerifier::~SharedCertVerifier() = default;
2465 
2466 NS_IMETHODIMP
GetDefaultCertVerifier(SharedCertVerifier ** result)2467 nsNSSComponent::GetDefaultCertVerifier(SharedCertVerifier** result) {
2468   MutexAutoLock lock(mMutex);
2469   NS_ENSURE_ARG_POINTER(result);
2470   RefPtr<SharedCertVerifier> certVerifier(mDefaultCertVerifier);
2471   certVerifier.forget(result);
2472   return NS_OK;
2473 }
2474 
2475 // static
DoClearSSLExternalAndInternalSessionCache()2476 void nsNSSComponent::DoClearSSLExternalAndInternalSessionCache() {
2477   SSL_ClearSessionCache();
2478   mozilla::net::SSLTokensCache::Clear();
2479 }
2480 
2481 NS_IMETHODIMP
ClearSSLExternalAndInternalSessionCache()2482 nsNSSComponent::ClearSSLExternalAndInternalSessionCache() {
2483   MOZ_ASSERT(XRE_IsParentProcess());
2484   if (!XRE_IsParentProcess()) {
2485     return NS_ERROR_NOT_AVAILABLE;
2486   }
2487 
2488   if (mozilla::net::nsIOService::UseSocketProcess()) {
2489     if (mozilla::net::gIOService) {
2490       mozilla::net::gIOService->CallOrWaitForSocketProcess([]() {
2491         Unused << mozilla::net::SocketProcessParent::GetSingleton()
2492                       ->SendClearSessionCache();
2493       });
2494     }
2495   }
2496   DoClearSSLExternalAndInternalSessionCache();
2497   return NS_OK;
2498 }
2499 
2500 namespace mozilla {
2501 namespace psm {
2502 
GetDefaultCertVerifier()2503 already_AddRefed<SharedCertVerifier> GetDefaultCertVerifier() {
2504   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
2505 
2506   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
2507   if (!nssComponent) {
2508     return nullptr;
2509   }
2510   nsresult rv = nssComponent->BlockUntilLoadableCertsLoaded();
2511   if (NS_FAILED(rv)) {
2512     return nullptr;
2513   }
2514   RefPtr<SharedCertVerifier> result;
2515   rv = nssComponent->GetDefaultCertVerifier(getter_AddRefs(result));
2516   if (NS_FAILED(rv)) {
2517     return nullptr;
2518   }
2519   return result.forget();
2520 }
2521 
2522 // Helper for FindClientCertificatesWithPrivateKeys. Copies all
2523 // CERTCertificates from `from` to `to`.
CopyCertificatesTo(UniqueCERTCertList & from,UniqueCERTCertList & to)2524 static inline void CopyCertificatesTo(UniqueCERTCertList& from,
2525                                       UniqueCERTCertList& to) {
2526   MOZ_ASSERT(from);
2527   MOZ_ASSERT(to);
2528   for (CERTCertListNode* n = CERT_LIST_HEAD(from.get());
2529        !CERT_LIST_END(n, from.get()); n = CERT_LIST_NEXT(n)) {
2530     UniqueCERTCertificate cert(CERT_DupCertificate(n->cert));
2531     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2532             ("      provisionally adding '%s'", n->cert->subjectName));
2533     if (CERT_AddCertToListTail(to.get(), cert.get()) == SECSuccess) {
2534       Unused << cert.release();
2535     }
2536   }
2537 }
2538 
2539 // Lists all private keys on all modules and returns a list of any corresponding
2540 // client certificates. Returns null if no such certificates can be found. Also
2541 // returns null if an error is encountered, because this is called as part of
2542 // the client auth data callback, and NSS ignores any errors returned by the
2543 // callback.
FindClientCertificatesWithPrivateKeys()2544 UniqueCERTCertList FindClientCertificatesWithPrivateKeys() {
2545   TimeStamp begin(TimeStamp::Now());
2546   auto exitTelemetry = MakeScopeExit([&] {
2547     Telemetry::AccumulateTimeDelta(Telemetry::CLIENT_CERTIFICATE_SCAN_TIME,
2548                                    begin, TimeStamp::Now());
2549   });
2550   MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2551           ("FindClientCertificatesWithPrivateKeys"));
2552   UniqueCERTCertList certsWithPrivateKeys(CERT_NewCertList());
2553   if (!certsWithPrivateKeys) {
2554     return nullptr;
2555   }
2556 
2557   UniquePK11SlotInfo internalSlot(PK11_GetInternalKeySlot());
2558 
2559   AutoSECMODListReadLock secmodLock;
2560   SECMODModuleList* list = SECMOD_GetDefaultModuleList();
2561   while (list) {
2562     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2563             ("  module '%s'", list->module->commonName));
2564     for (int i = 0; i < list->module->slotCount; i++) {
2565       PK11SlotInfo* slot = list->module->slots[i];
2566       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2567               ("    slot '%s'", PK11_GetSlotName(slot)));
2568       // If this is the internal certificate/key slot, there may be many more
2569       // certificates than private keys, so search by private keys.
2570       if (internalSlot.get() == slot) {
2571         MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2572                 ("    (looking at internal slot)"));
2573         if (PK11_Authenticate(slot, true, nullptr) != SECSuccess) {
2574           MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (couldn't authenticate)"));
2575           continue;
2576         }
2577         UniqueSECKEYPrivateKeyList privateKeys(
2578             PK11_ListPrivKeysInSlot(slot, nullptr, nullptr));
2579         if (!privateKeys) {
2580           MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("      (no private keys)"));
2581           continue;
2582         }
2583         for (SECKEYPrivateKeyListNode* node = PRIVKEY_LIST_HEAD(privateKeys);
2584              !PRIVKEY_LIST_END(node, privateKeys);
2585              node = PRIVKEY_LIST_NEXT(node)) {
2586           UniqueCERTCertList certs(PK11_GetCertsMatchingPrivateKey(node->key));
2587           if (!certs) {
2588             MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2589                     ("      PK11_GetCertsMatchingPrivateKey encountered an "
2590                      "error "));
2591             continue;
2592           }
2593           if (CERT_LIST_EMPTY(certs)) {
2594             MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("      (no certs for key)"));
2595             continue;
2596           }
2597           CopyCertificatesTo(certs, certsWithPrivateKeys);
2598         }
2599       } else {
2600         // ... otherwise, optimistically assume that searching by certificate
2601         // won't take too much time. Since "friendly" slots expose certificates
2602         // without needing to be authenticated to, this results in fewer PIN
2603         // dialogs shown to the user.
2604         MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2605                 ("    (looking at non-internal slot)"));
2606 
2607         if (!PK11_IsPresent(slot)) {
2608           MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (not present)"));
2609           continue;
2610         }
2611         // If this isn't a "friendly" slot, authenticate to expose certificates.
2612         if (!PK11_IsFriendly(slot) &&
2613             PK11_Authenticate(slot, true, nullptr) != SECSuccess) {
2614           MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    (couldn't authenticate)"));
2615           continue;
2616         }
2617         UniqueCERTCertList certsInSlot(PK11_ListCertsInSlot(slot));
2618         if (!certsInSlot) {
2619           MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2620                   ("      (couldn't list certs in slot)"));
2621           continue;
2622         }
2623         // When NSS decodes a certificate, if that certificate has a
2624         // corresponding private key (or public key, if the slot it's on hasn't
2625         // been logged into), it notes it as a "user cert".
2626         if (CERT_FilterCertListForUserCerts(certsInSlot.get()) != SECSuccess) {
2627           MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2628                   ("      (couldn't filter certs)"));
2629           continue;
2630         }
2631         CopyCertificatesTo(certsInSlot, certsWithPrivateKeys);
2632       }
2633     }
2634     list = list->next;
2635   }
2636 
2637   if (CERT_FilterCertListByUsage(certsWithPrivateKeys.get(), certUsageSSLClient,
2638                                  false) != SECSuccess) {
2639     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
2640             ("  CERT_FilterCertListByUsage encountered an error - returning"));
2641     return nullptr;
2642   }
2643 
2644   if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPIPNSSLog, LogLevel::Debug))) {
2645     MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("  returning:"));
2646     for (CERTCertListNode* n = CERT_LIST_HEAD(certsWithPrivateKeys);
2647          !CERT_LIST_END(n, certsWithPrivateKeys); n = CERT_LIST_NEXT(n)) {
2648       MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("    %s", n->cert->subjectName));
2649     }
2650   }
2651 
2652   if (CERT_LIST_EMPTY(certsWithPrivateKeys)) {
2653     return nullptr;
2654   }
2655 
2656   return certsWithPrivateKeys;
2657 }
2658 
2659 }  // namespace psm
2660 }  // namespace mozilla
2661 
2662 NS_IMPL_ISUPPORTS(PipUIContext, nsIInterfaceRequestor)
2663 
2664 PipUIContext::PipUIContext() = default;
2665 
2666 PipUIContext::~PipUIContext() = default;
2667 
2668 NS_IMETHODIMP
GetInterface(const nsIID & uuid,void ** result)2669 PipUIContext::GetInterface(const nsIID& uuid, void** result) {
2670   NS_ENSURE_ARG_POINTER(result);
2671   *result = nullptr;
2672 
2673   if (!NS_IsMainThread()) {
2674     NS_ERROR("PipUIContext::GetInterface called off the main thread");
2675     return NS_ERROR_NOT_SAME_THREAD;
2676   }
2677 
2678   if (!uuid.Equals(NS_GET_IID(nsIPrompt))) return NS_ERROR_NO_INTERFACE;
2679 
2680   nsIPrompt* prompt = nullptr;
2681   nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
2682   *result = prompt;
2683   return rv;
2684 }
2685 
getNSSDialogs(void ** _result,REFNSIID aIID,const char * contract)2686 nsresult getNSSDialogs(void** _result, REFNSIID aIID, const char* contract) {
2687   if (!NS_IsMainThread()) {
2688     NS_ERROR("getNSSDialogs called off the main thread");
2689     return NS_ERROR_NOT_SAME_THREAD;
2690   }
2691 
2692   nsresult rv;
2693 
2694   nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
2695   if (NS_FAILED(rv)) {
2696     return rv;
2697   }
2698 
2699   rv = svc->QueryInterface(aIID, _result);
2700 
2701   return rv;
2702 }
2703 
setPassword(PK11SlotInfo * slot,nsIInterfaceRequestor * ctx)2704 nsresult setPassword(PK11SlotInfo* slot, nsIInterfaceRequestor* ctx) {
2705   MOZ_ASSERT(slot);
2706   MOZ_ASSERT(ctx);
2707   NS_ENSURE_ARG_POINTER(slot);
2708   NS_ENSURE_ARG_POINTER(ctx);
2709 
2710   if (PK11_NeedUserInit(slot)) {
2711     nsCOMPtr<nsITokenPasswordDialogs> dialogs;
2712     nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
2713                                 NS_GET_IID(nsITokenPasswordDialogs),
2714                                 NS_TOKENPASSWORDSDIALOG_CONTRACTID);
2715     if (NS_FAILED(rv)) {
2716       return rv;
2717     }
2718 
2719     bool canceled;
2720     nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot);
2721     rv = dialogs->SetPassword(ctx, token, &canceled);
2722     if (NS_FAILED(rv)) {
2723       return rv;
2724     }
2725 
2726     if (canceled) {
2727       return NS_ERROR_NOT_AVAILABLE;
2728     }
2729   }
2730 
2731   return NS_OK;
2732 }
2733 
ConvertBetweenUCS2andASCII(PRBool toUnicode,unsigned char * inBuf,unsigned int inBufLen,unsigned char * outBuf,unsigned int maxOutBufLen,unsigned int * outBufLen,PRBool swapBytes)2734 static PRBool ConvertBetweenUCS2andASCII(PRBool toUnicode, unsigned char* inBuf,
2735                                          unsigned int inBufLen,
2736                                          unsigned char* outBuf,
2737                                          unsigned int maxOutBufLen,
2738                                          unsigned int* outBufLen,
2739                                          PRBool swapBytes) {
2740   std::unique_ptr<unsigned char[]> inBufDup(new unsigned char[inBufLen]);
2741   if (!inBufDup) {
2742     return PR_FALSE;
2743   }
2744   std::memcpy(inBufDup.get(), inBuf, inBufLen * sizeof(unsigned char));
2745 
2746   // If converting Unicode to ASCII, swap bytes before conversion as neccessary.
2747   if (!toUnicode && swapBytes) {
2748     if (inBufLen % 2 != 0) {
2749       return PR_FALSE;
2750     }
2751     mozilla::NativeEndian::swapFromLittleEndianInPlace(
2752         reinterpret_cast<char16_t*>(inBufDup.get()), inBufLen / 2);
2753   }
2754   return PORT_UCS2_UTF8Conversion(toUnicode, inBufDup.get(), inBufLen, outBuf,
2755                                   maxOutBufLen, outBufLen);
2756 }
2757 
2758 namespace mozilla {
2759 namespace psm {
2760 
InitializeCipherSuite()2761 nsresult InitializeCipherSuite() {
2762   MOZ_ASSERT(NS_IsMainThread(),
2763              "InitializeCipherSuite() can only be accessed on the main thread");
2764 
2765   if (NSS_SetDomesticPolicy() != SECSuccess) {
2766     return NS_ERROR_FAILURE;
2767   }
2768 
2769   // Disable any ciphers that NSS might have enabled by default
2770   for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
2771     uint16_t cipher_id = SSL_ImplementedCiphers[i];
2772     SSL_CipherPrefSetDefault(cipher_id, false);
2773   }
2774 
2775   // Now only set SSL/TLS ciphers we knew about at compile time
2776   const CipherPref* const cp = sCipherPrefs;
2777   for (size_t i = 0; cp[i].pref; ++i) {
2778     bool cipherEnabled =
2779         Preferences::GetBool(cp[i].pref, cp[i].enabledByDefault);
2780     SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
2781   }
2782 
2783   // Enable ciphers for PKCS#12
2784   SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
2785   SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
2786   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
2787   SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
2788   SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
2789   SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
2790   SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
2791   SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
2792   SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
2793   SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
2794   PORT_SetUCS2_ASCIIConversionFunction(ConvertBetweenUCS2andASCII);
2795 
2796   // PSM enforces a minimum RSA key size of 1024 bits, which is overridable.
2797   // NSS has its own minimum, which is not overridable (the default is 1023
2798   // bits). This sets the NSS minimum to 512 bits so users can still connect to
2799   // devices like wifi routers with woefully small keys (they would have to add
2800   // an override to do so, but they already do for such devices).
2801   NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 512);
2802 
2803   // Observe preference change around cipher suite setting.
2804   return CipherSuiteChangeObserver::StartObserve();
2805 }
2806 
2807 }  // namespace psm
2808 }  // namespace mozilla
2809