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