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