Bug 1605894 reduce the proliferation of DefaultLoopbackTone to only AudioStreamFlowin...
[gecko.git] / security / manager / ssl / nsCertOverrideService.cpp
blobb8d0bbc3a12f74c19284b26eadada361abeb7946
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 #include "nsCertOverrideService.h"
9 #include "NSSCertDBTrustDomain.h"
10 #include "ScopedNSSTypes.h"
11 #include "SharedSSLState.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/ScopeExit.h"
14 #include "mozilla/TaskQueue.h"
15 #include "mozilla/Telemetry.h"
16 #include "mozilla/TextUtils.h"
17 #include "mozilla/Tokenizer.h"
18 #include "mozilla/Unused.h"
19 #include "mozilla/dom/ToJSValue.h"
20 #include "nsAppDirectoryServiceDefs.h"
21 #include "nsCRT.h"
22 #include "nsILineInputStream.h"
23 #ifdef ENABLE_WEBDRIVER
24 # include "nsIMarionette.h"
25 #endif
26 #include "nsIObserver.h"
27 #include "nsIObserverService.h"
28 #include "nsIOutputStream.h"
29 #ifdef ENABLE_WEBDRIVER
30 # include "nsIRemoteAgent.h"
31 #endif
32 #include "nsISafeOutputStream.h"
33 #include "nsIX509Cert.h"
34 #include "nsNSSCertificate.h"
35 #include "nsNSSComponent.h"
36 #include "nsNetUtil.h"
37 #include "nsStreamUtils.h"
38 #include "nsStringBuffer.h"
39 #include "nsThreadUtils.h"
41 using namespace mozilla;
42 using namespace mozilla::psm;
44 #define CERT_OVERRIDE_FILE_NAME "cert_override.txt"
46 class WriterRunnable : public Runnable {
47 public:
48 WriterRunnable(nsCertOverrideService* aService, nsCString& aData,
49 nsCOMPtr<nsIFile> aFile)
50 : Runnable("nsCertOverrideService::WriterRunnable"),
51 mCertOverrideService(aService),
52 mData(aData),
53 mFile(std::move(aFile)) {}
55 NS_IMETHOD
56 Run() override {
57 mCertOverrideService->AssertOnTaskQueue();
58 nsresult rv;
60 auto removeShutdownBlockerOnExit =
61 MakeScopeExit([certOverrideService = mCertOverrideService]() {
62 NS_DispatchToMainThread(NS_NewRunnableFunction(
63 "nsCertOverrideService::RemoveShutdownBlocker",
64 [certOverrideService] {
65 certOverrideService->RemoveShutdownBlocker();
66 }));
67 });
69 nsCOMPtr<nsIOutputStream> outputStream;
70 rv = NS_NewSafeLocalFileOutputStream(
71 getter_AddRefs(outputStream), mFile,
72 PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY);
73 NS_ENSURE_SUCCESS(rv, rv);
75 const char* ptr = mData.get();
76 uint32_t remaining = mData.Length();
77 uint32_t written = 0;
78 while (remaining > 0) {
79 rv = outputStream->Write(ptr, remaining, &written);
80 NS_ENSURE_SUCCESS(rv, rv);
81 remaining -= written;
82 ptr += written;
85 nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outputStream);
86 MOZ_ASSERT(safeStream);
87 rv = safeStream->Finish();
88 NS_ENSURE_SUCCESS(rv, rv);
90 return NS_OK;
93 private:
94 const RefPtr<nsCertOverrideService> mCertOverrideService;
95 nsCString mData;
96 const nsCOMPtr<nsIFile> mFile;
99 NS_IMPL_ISUPPORTS(nsCertOverride, nsICertOverride)
101 NS_IMETHODIMP
102 nsCertOverride::GetAsciiHost(/*out*/ nsACString& aAsciiHost) {
103 aAsciiHost = mAsciiHost;
104 return NS_OK;
107 NS_IMETHODIMP
108 nsCertOverride::GetFingerprint(/*out*/ nsACString& aFingerprint) {
109 aFingerprint = mFingerprint;
110 return NS_OK;
113 NS_IMETHODIMP
114 nsCertOverride::GetPort(/*out*/ int32_t* aPort) {
115 *aPort = mPort;
116 return NS_OK;
119 NS_IMETHODIMP
120 nsCertOverride::GetHostPort(/*out*/ nsACString& aHostPort) {
121 nsCertOverrideService::GetHostWithPort(mAsciiHost, mPort, aHostPort);
122 return NS_OK;
125 NS_IMETHODIMP
126 nsCertOverride::GetOriginAttributes(
127 JSContext* aCtx, /*out*/ JS::MutableHandle<JS::Value> aValue) {
128 if (ToJSValue(aCtx, mOriginAttributes, aValue)) {
129 return NS_OK;
131 return NS_ERROR_FAILURE;
134 NS_IMPL_ISUPPORTS(nsCertOverrideService, nsICertOverrideService, nsIObserver,
135 nsISupportsWeakReference, nsIAsyncShutdownBlocker)
137 nsCertOverrideService::nsCertOverrideService()
138 : mMutex("nsCertOverrideService.mutex"),
139 mDisableAllSecurityCheck(false),
140 mPendingWriteCount(0) {
141 nsCOMPtr<nsIEventTarget> target =
142 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
143 MOZ_ASSERT(target);
145 mWriterTaskQueue = TaskQueue::Create(target.forget(), "CertOverrideService");
148 nsCertOverrideService::~nsCertOverrideService() = default;
150 static nsCOMPtr<nsIAsyncShutdownClient> GetShutdownBarrier() {
151 MOZ_ASSERT(NS_IsMainThread());
152 nsCOMPtr<nsIAsyncShutdownService> svc =
153 mozilla::services::GetAsyncShutdownService();
154 MOZ_RELEASE_ASSERT(svc);
156 nsCOMPtr<nsIAsyncShutdownClient> barrier;
157 nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
159 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
160 MOZ_RELEASE_ASSERT(barrier);
161 return barrier;
164 nsresult nsCertOverrideService::Init() {
165 if (!NS_IsMainThread()) {
166 MOZ_ASSERT_UNREACHABLE("nsCertOverrideService initialized off main thread");
167 return NS_ERROR_NOT_SAME_THREAD;
170 nsCOMPtr<nsIObserverService> observerService =
171 mozilla::services::GetObserverService();
173 // If we cannot add ourselves as a profile change observer, then we will not
174 // attempt to read/write any settings file. Otherwise, we would end up
175 // reading/writing the wrong settings file after a profile change.
176 if (observerService) {
177 observerService->AddObserver(this, "profile-do-change", true);
178 // simulate a profile change so we read the current profile's settings file
179 Observe(nullptr, "profile-do-change", nullptr);
182 SharedSSLState::NoteCertOverrideServiceInstantiated();
183 return NS_OK;
186 NS_IMETHODIMP
187 nsCertOverrideService::Observe(nsISupports*, const char* aTopic,
188 const char16_t* aData) {
189 if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
190 // The profile has already changed.
191 // Now read from the new profile location.
192 // we also need to update the cached file location
194 MutexAutoLock lock(mMutex);
196 nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
197 getter_AddRefs(mSettingsFile));
198 if (NS_SUCCEEDED(rv)) {
199 mSettingsFile->AppendNative(nsLiteralCString(CERT_OVERRIDE_FILE_NAME));
200 } else {
201 mSettingsFile = nullptr;
203 Read(lock);
204 CountPermanentOverrideTelemetry(lock);
207 return NS_OK;
210 void nsCertOverrideService::RemoveAllTemporaryOverrides() {
211 MutexAutoLock lock(mMutex);
212 bool removedAny = false;
213 for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
214 nsCertOverrideEntry* entry = iter.Get();
215 if (entry->mSettings->mIsTemporary) {
216 iter.Remove();
217 removedAny = true;
220 if (removedAny) {
221 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
222 if (os) {
223 os->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
226 // no need to write, as temporaries are never written to disk
229 static const char sSHA256OIDString[] = "OID.2.16.840.1.101.3.4.2.1";
230 nsresult nsCertOverrideService::Read(const MutexAutoLock& aProofOfLock) {
231 mMutex.AssertCurrentThreadOwns();
232 // If we don't have a profile, then we won't try to read any settings file.
233 if (!mSettingsFile) return NS_OK;
235 nsresult rv;
236 nsCOMPtr<nsIInputStream> fileInputStream;
237 rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream),
238 mSettingsFile);
239 if (NS_FAILED(rv)) {
240 return rv;
243 nsCOMPtr<nsILineInputStream> lineInputStream =
244 do_QueryInterface(fileInputStream, &rv);
245 if (NS_FAILED(rv)) {
246 return rv;
249 nsAutoCString buffer;
250 bool isMore = true;
252 // Each line is of the form:
253 // host:port:originAttributes \t sSHA256OIDString \t fingerprint \t
254 // There may be some "bits" identifiers and "dbKey" after the `fingerprint`
255 // field in 'fingerprint \t \t dbKey' format, but these are now ignored.
256 // Lines that don't match this form are silently dropped.
258 while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
259 if (buffer.IsEmpty() || buffer.First() == '#') {
260 continue;
263 Tokenizer parser(buffer);
264 nsDependentCSubstring host;
265 if (parser.CheckChar('[')) { // this is a IPv6 address
266 if (!parser.ReadUntil(Tokenizer::Token::Char(']'), host) ||
267 host.Length() == 0 || !parser.CheckChar(':')) {
268 continue;
270 } else if (!parser.ReadUntil(Tokenizer::Token::Char(':'), host) ||
271 host.Length() == 0) {
272 continue;
274 int32_t port = -1;
275 if (!parser.ReadInteger(&port)) {
276 continue;
278 OriginAttributes attributes;
279 if (parser.CheckChar(':')) {
280 nsDependentCSubstring attributesString;
281 if (!parser.ReadUntil(Tokenizer::Token::Whitespace(), attributesString) ||
282 !attributes.PopulateFromSuffix(attributesString)) {
283 continue;
285 } else if (!parser.CheckWhite()) {
286 continue;
288 nsDependentCSubstring algorithm;
289 if (!parser.ReadUntil(Tokenizer::Token::Whitespace(), algorithm) ||
290 algorithm != sSHA256OIDString) {
291 continue;
293 nsDependentCSubstring fingerprint;
294 if (!parser.ReadUntil(Tokenizer::Token::Whitespace(), fingerprint) ||
295 fingerprint.Length() == 0) {
296 continue;
299 AddEntryToList(host, port, attributes,
300 false, // not temporary
301 fingerprint, aProofOfLock);
304 return NS_OK;
307 nsresult nsCertOverrideService::Write(const MutexAutoLock& aProofOfLock) {
308 mMutex.AssertCurrentThreadOwns();
309 MOZ_ASSERT(NS_IsMainThread());
310 if (!NS_IsMainThread()) {
311 return NS_ERROR_NOT_SAME_THREAD;
314 // If we don't have any profile, then we won't try to write any file
315 if (!mSettingsFile) {
316 return NS_OK;
319 nsCString output;
321 static const char kHeader[] =
322 "# PSM Certificate Override Settings file" NS_LINEBREAK
323 "# This is a generated file! Do not edit." NS_LINEBREAK;
325 /* see ::Read for file format */
327 output.Append(kHeader);
329 static const char kTab[] = "\t";
330 for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
331 nsCertOverrideEntry* entry = iter.Get();
333 RefPtr<nsCertOverride> settings = entry->mSettings;
334 if (settings->mIsTemporary) {
335 continue;
338 output.Append(entry->mKeyString);
339 output.Append(kTab);
340 output.Append(sSHA256OIDString);
341 output.Append(kTab);
342 output.Append(settings->mFingerprint);
343 output.Append(kTab);
344 // the "bits" string used to go here, but it no longer exists
345 // the "\t dbKey" string used to go here, but it no longer exists
346 output.Append(NS_LINEBREAK);
349 // Make a clone of the file to pass to the WriterRunnable.
350 nsCOMPtr<nsIFile> file;
351 nsresult rv;
352 rv = mSettingsFile->Clone(getter_AddRefs(file));
353 NS_ENSURE_SUCCESS(rv, rv);
355 nsCOMPtr<nsIRunnable> runnable = new WriterRunnable(this, output, file);
356 rv = mWriterTaskQueue->Dispatch(runnable.forget());
357 if (NS_FAILED(rv)) {
358 return rv;
360 mPendingWriteCount++;
362 if (mPendingWriteCount == 1) {
363 rv = GetShutdownBarrier()->AddBlocker(
364 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__,
365 u"nsCertOverrideService writing data"_ns);
366 NS_ENSURE_SUCCESS(rv, rv);
369 return NS_OK;
372 nsresult GetCertSha256Fingerprint(nsIX509Cert* aCert, nsCString& aResult) {
373 nsAutoString fpStrUTF16;
374 nsresult rv = aCert->GetSha256Fingerprint(fpStrUTF16);
375 if (NS_FAILED(rv)) {
376 return rv;
378 aResult.Assign(NS_ConvertUTF16toUTF8(fpStrUTF16));
379 return NS_OK;
382 NS_IMETHODIMP
383 nsCertOverrideService::RememberValidityOverride(
384 const nsACString& aHostName, int32_t aPort,
385 const OriginAttributes& aOriginAttributes, nsIX509Cert* aCert,
386 bool aTemporary) {
387 if (aHostName.IsEmpty() || !IsAscii(aHostName) || !aCert) {
388 return NS_ERROR_INVALID_ARG;
390 if (aPort < -1) {
391 return NS_ERROR_INVALID_ARG;
393 if (!NS_IsMainThread()) {
394 return NS_ERROR_NOT_SAME_THREAD;
397 UniqueCERTCertificate nsscert(aCert->GetCert());
398 if (!nsscert) {
399 return NS_ERROR_FAILURE;
402 nsAutoCString fpStr;
403 nsresult rv = GetCertSha256Fingerprint(aCert, fpStr);
404 if (NS_FAILED(rv)) {
405 return rv;
409 MutexAutoLock lock(mMutex);
410 AddEntryToList(aHostName, aPort, aOriginAttributes, aTemporary, fpStr,
411 lock);
412 if (!aTemporary) {
413 Write(lock);
417 return NS_OK;
420 NS_IMETHODIMP
421 nsCertOverrideService::RememberValidityOverrideScriptable(
422 const nsACString& aHostName, int32_t aPort,
423 JS::Handle<JS::Value> aOriginAttributes, nsIX509Cert* aCert,
424 bool aTemporary, JSContext* aCx) {
425 OriginAttributes attrs;
426 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
427 return NS_ERROR_INVALID_ARG;
430 return RememberValidityOverride(aHostName, aPort, attrs, aCert, aTemporary);
433 NS_IMETHODIMP
434 nsCertOverrideService::HasMatchingOverride(
435 const nsACString& aHostName, int32_t aPort,
436 const OriginAttributes& aOriginAttributes, nsIX509Cert* aCert,
437 bool* aIsTemporary, bool* aRetval) {
438 bool disableAllSecurityCheck = false;
440 MutexAutoLock lock(mMutex);
441 disableAllSecurityCheck = mDisableAllSecurityCheck;
443 if (disableAllSecurityCheck) {
444 *aIsTemporary = false;
445 *aRetval = true;
446 return NS_OK;
449 if (aHostName.IsEmpty() || !IsAscii(aHostName)) {
450 return NS_ERROR_INVALID_ARG;
452 if (aPort < -1) return NS_ERROR_INVALID_ARG;
454 NS_ENSURE_ARG_POINTER(aCert);
455 NS_ENSURE_ARG_POINTER(aIsTemporary);
456 NS_ENSURE_ARG_POINTER(aRetval);
457 *aRetval = false;
459 RefPtr<nsCertOverride> settings(
460 GetOverrideFor(aHostName, aPort, aOriginAttributes));
461 // If there is no corresponding override and the given OriginAttributes isn't
462 // the default, try to look up an override using the default OriginAttributes.
463 if (!settings && aOriginAttributes != OriginAttributes()) {
464 settings = GetOverrideFor(aHostName, aPort, OriginAttributes());
466 if (!settings) {
467 return NS_OK;
470 *aIsTemporary = settings->mIsTemporary;
472 nsAutoCString fpStr;
473 nsresult rv = GetCertSha256Fingerprint(aCert, fpStr);
474 if (NS_FAILED(rv)) {
475 return rv;
478 *aRetval = settings->mFingerprint.Equals(fpStr);
479 return NS_OK;
482 already_AddRefed<nsCertOverride> nsCertOverrideService::GetOverrideFor(
483 const nsACString& aHostName, int32_t aPort,
484 const OriginAttributes& aOriginAttributes) {
485 nsAutoCString keyString;
486 GetKeyString(aHostName, aPort, aOriginAttributes, keyString);
487 MutexAutoLock lock(mMutex);
488 nsCertOverrideEntry* entry = mSettingsTable.GetEntry(keyString.get());
489 if (!entry) {
490 return nullptr;
492 return do_AddRef(entry->mSettings);
495 NS_IMETHODIMP
496 nsCertOverrideService::HasMatchingOverrideScriptable(
497 const nsACString& aHostName, int32_t aPort,
498 JS::Handle<JS::Value> aOriginAttributes, nsIX509Cert* aCert,
499 bool* aIsTemporary, JSContext* aCx, bool* aRetval) {
500 OriginAttributes attrs;
501 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
502 return NS_ERROR_INVALID_ARG;
505 return HasMatchingOverride(aHostName, aPort, attrs, aCert, aIsTemporary,
506 aRetval);
509 nsresult nsCertOverrideService::AddEntryToList(
510 const nsACString& aHostName, int32_t aPort,
511 const OriginAttributes& aOriginAttributes, const bool aIsTemporary,
512 const nsACString& fingerprint, const MutexAutoLock& aProofOfLock) {
513 mMutex.AssertCurrentThreadOwns();
514 nsAutoCString keyString;
515 GetKeyString(aHostName, aPort, aOriginAttributes, keyString);
517 nsCertOverrideEntry* entry = mSettingsTable.PutEntry(keyString.get());
519 if (!entry) {
520 NS_ERROR("can't insert a null entry!");
521 return NS_ERROR_OUT_OF_MEMORY;
524 entry->mKeyString = keyString;
526 RefPtr<nsCertOverride> settings(new nsCertOverride());
528 settings->mAsciiHost = aHostName;
529 settings->mPort = aPort;
530 settings->mOriginAttributes = aOriginAttributes;
531 settings->mIsTemporary = aIsTemporary;
532 settings->mFingerprint = fingerprint;
533 entry->mSettings = settings;
535 return NS_OK;
538 NS_IMETHODIMP
539 nsCertOverrideService::ClearValidityOverride(
540 const nsACString& aHostName, int32_t aPort,
541 const OriginAttributes& aOriginAttributes) {
542 if (aHostName.IsEmpty() || !IsAscii(aHostName)) {
543 return NS_ERROR_INVALID_ARG;
545 if (!NS_IsMainThread()) {
546 return NS_ERROR_NOT_SAME_THREAD;
549 if (aPort == 0 && aHostName.EqualsLiteral("all:temporary-certificates")) {
550 RemoveAllTemporaryOverrides();
551 return NS_OK;
553 nsAutoCString keyString;
554 GetKeyString(aHostName, aPort, aOriginAttributes, keyString);
556 MutexAutoLock lock(mMutex);
557 mSettingsTable.RemoveEntry(keyString.get());
558 Write(lock);
561 nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
562 if (nss) {
563 nss->ClearSSLExternalAndInternalSessionCache();
564 } else {
565 return NS_ERROR_NOT_AVAILABLE;
568 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
569 if (os) {
570 os->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
573 return NS_OK;
575 NS_IMETHODIMP
576 nsCertOverrideService::ClearValidityOverrideScriptable(
577 const nsACString& aHostName, int32_t aPort,
578 JS::Handle<JS::Value> aOriginAttributes, JSContext* aCx) {
579 OriginAttributes attrs;
580 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
581 return NS_ERROR_INVALID_ARG;
584 return ClearValidityOverride(aHostName, aPort, attrs);
587 NS_IMETHODIMP
588 nsCertOverrideService::ClearAllOverrides() {
589 if (!NS_IsMainThread()) {
590 return NS_ERROR_NOT_SAME_THREAD;
594 MutexAutoLock lock(mMutex);
595 mSettingsTable.Clear();
596 Write(lock);
599 nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
600 if (nss) {
601 nss->ClearSSLExternalAndInternalSessionCache();
602 } else {
603 return NS_ERROR_NOT_AVAILABLE;
606 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
607 if (os) {
608 os->NotifyObservers(nullptr, "net:cancel-all-connections", nullptr);
611 return NS_OK;
614 void nsCertOverrideService::CountPermanentOverrideTelemetry(
615 const MutexAutoLock& aProofOfLock) {
616 mMutex.AssertCurrentThreadOwns();
617 uint32_t overrideCount = 0;
618 for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
619 if (!iter.Get()->mSettings->mIsTemporary) {
620 overrideCount++;
623 Telemetry::Accumulate(Telemetry::SSL_PERMANENT_CERT_ERROR_OVERRIDES,
624 overrideCount);
627 static bool IsDebugger() {
628 #ifdef ENABLE_WEBDRIVER
629 nsCOMPtr<nsIMarionette> marionette = do_GetService(NS_MARIONETTE_CONTRACTID);
630 if (marionette) {
631 bool marionetteRunning = false;
632 marionette->GetRunning(&marionetteRunning);
633 if (marionetteRunning) {
634 return true;
638 nsCOMPtr<nsIRemoteAgent> agent = do_GetService(NS_REMOTEAGENT_CONTRACTID);
639 if (agent) {
640 bool remoteAgentRunning = false;
641 agent->GetRunning(&remoteAgentRunning);
642 if (remoteAgentRunning) {
643 return true;
646 #endif
648 return false;
651 NS_IMETHODIMP
652 nsCertOverrideService::
653 SetDisableAllSecurityChecksAndLetAttackersInterceptMyData(bool aDisable) {
654 if (!(PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR") || IsDebugger())) {
655 return NS_ERROR_NOT_AVAILABLE;
659 MutexAutoLock lock(mMutex);
660 mDisableAllSecurityCheck = aDisable;
663 nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
664 if (nss) {
665 nss->ClearSSLExternalAndInternalSessionCache();
666 } else {
667 return NS_ERROR_NOT_AVAILABLE;
670 return NS_OK;
673 NS_IMETHODIMP
674 nsCertOverrideService::GetSecurityCheckDisabled(bool* aDisabled) {
675 MutexAutoLock lock(mMutex);
676 *aDisabled = mDisableAllSecurityCheck;
677 return NS_OK;
680 NS_IMETHODIMP
681 nsCertOverrideService::GetOverrides(
682 /*out*/ nsTArray<RefPtr<nsICertOverride>>& retval) {
683 MutexAutoLock lock(mMutex);
684 for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
685 const RefPtr<nsICertOverride> settings = iter.Get()->mSettings;
687 retval.AppendElement(settings);
689 return NS_OK;
692 void nsCertOverrideService::GetHostWithPort(const nsACString& aHostName,
693 int32_t aPort,
694 nsACString& aRetval) {
695 nsAutoCString hostPort;
696 if (aHostName.Contains(':')) {
697 // if aHostName is an IPv6 address, add brackets to match the internal
698 // representation, which always stores IPv6 addresses with brackets
699 hostPort.Append('[');
700 hostPort.Append(aHostName);
701 hostPort.Append(']');
702 } else {
703 hostPort.Append(aHostName);
705 if (aPort == -1) {
706 aPort = 443;
708 if (!hostPort.IsEmpty()) {
709 hostPort.Append(':');
710 hostPort.AppendInt(aPort);
712 aRetval.Assign(hostPort);
715 void nsCertOverrideService::GetKeyString(
716 const nsACString& aHostName, int32_t aPort,
717 const OriginAttributes& aOriginAttributes, nsACString& aRetval) {
718 nsAutoCString keyString;
719 GetHostWithPort(aHostName, aPort, keyString);
720 keyString.Append(':');
721 OriginAttributes strippedAttributes(aOriginAttributes);
722 strippedAttributes.StripAttributes(
723 ~OriginAttributes::STRIP_PRIVATE_BROWSING_ID);
724 nsAutoCString attributeSuffix;
725 strippedAttributes.CreateSuffix(attributeSuffix);
726 keyString.Append(attributeSuffix);
727 aRetval.Assign(keyString);
730 // nsIAsyncShutdownBlocker implementation
731 NS_IMETHODIMP
732 nsCertOverrideService::GetName(nsAString& aName) {
733 aName = u"nsCertOverrideService: shutdown"_ns;
734 return NS_OK;
737 NS_IMETHODIMP
738 nsCertOverrideService::GetState(nsIPropertyBag** aState) {
739 if (!aState) {
740 return NS_ERROR_INVALID_ARG;
742 *aState = nullptr;
743 return NS_OK;
746 NS_IMETHODIMP
747 nsCertOverrideService::BlockShutdown(nsIAsyncShutdownClient*) { return NS_OK; }
749 void nsCertOverrideService::RemoveShutdownBlocker() {
750 MOZ_ASSERT(NS_IsMainThread());
751 MOZ_ASSERT(mPendingWriteCount > 0);
752 mPendingWriteCount--;
753 if (mPendingWriteCount == 0) {
754 nsresult rv = GetShutdownBarrier()->RemoveBlocker(this);
755 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));