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