LCOV - code coverage report
Current view: top level - security/manager/ssl - nsCertOverrideService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 14 269 5.2 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #include "nsCertOverrideService.h"
       8             : 
       9             : #include "NSSCertDBTrustDomain.h"
      10             : #include "ScopedNSSTypes.h"
      11             : #include "SharedSSLState.h"
      12             : #include "mozilla/Assertions.h"
      13             : #include "mozilla/Telemetry.h"
      14             : #include "mozilla/Unused.h"
      15             : #include "nsAppDirectoryServiceDefs.h"
      16             : #include "nsCRT.h"
      17             : #include "nsILineInputStream.h"
      18             : #include "nsIObserver.h"
      19             : #include "nsIObserverService.h"
      20             : #include "nsIOutputStream.h"
      21             : #include "nsISafeOutputStream.h"
      22             : #include "nsIX509Cert.h"
      23             : #include "nsNSSCertHelper.h"
      24             : #include "nsNSSCertificate.h"
      25             : #include "nsNSSComponent.h"
      26             : #include "nsNetUtil.h"
      27             : #include "nsStreamUtils.h"
      28             : #include "nsStringBuffer.h"
      29             : #include "nsThreadUtils.h"
      30             : #include "ssl.h" // For SSL_ClearSessionCache
      31             : 
      32             : using namespace mozilla;
      33             : using namespace mozilla::psm;
      34             : 
      35             : #define CERT_OVERRIDE_FILE_NAME "cert_override.txt"
      36             : 
      37             : void
      38           0 : nsCertOverride::convertBitsToString(OverrideBits ob, /*out*/ nsACString& str)
      39             : {
      40           0 :   str.Truncate();
      41             : 
      42           0 :   if (ob & OverrideBits::Mismatch) {
      43           0 :     str.Append('M');
      44             :   }
      45             : 
      46           0 :   if (ob & OverrideBits::Untrusted) {
      47           0 :     str.Append('U');
      48             :   }
      49             : 
      50           0 :   if (ob & OverrideBits::Time) {
      51           0 :     str.Append('T');
      52             :   }
      53           0 : }
      54             : 
      55             : void
      56           0 : nsCertOverride::convertStringToBits(const nsACString& str,
      57             :                             /*out*/ OverrideBits& ob)
      58             : {
      59           0 :   ob = OverrideBits::None;
      60             : 
      61           0 :   for (uint32_t i = 0; i < str.Length(); i++) {
      62           0 :     switch (str.CharAt(i)) {
      63             :       case 'm':
      64             :       case 'M':
      65             :         ob |= OverrideBits::Mismatch;
      66             :         break;
      67             : 
      68             :       case 'u':
      69             :       case 'U':
      70             :         ob |= OverrideBits::Untrusted;
      71             :         break;
      72             : 
      73             :       case 't':
      74             :       case 'T':
      75             :         ob |= OverrideBits::Time;
      76             :         break;
      77             : 
      78             :       default:
      79             :         break;
      80             :     }
      81             :   }
      82           0 : }
      83             : 
      84           0 : NS_IMPL_ISUPPORTS(nsCertOverrideService,
      85             :                   nsICertOverrideService,
      86             :                   nsIObserver,
      87             :                   nsISupportsWeakReference)
      88             : 
      89           0 : nsCertOverrideService::nsCertOverrideService()
      90           0 :   : mMutex("nsCertOverrideService.mutex")
      91             : {
      92           0 : }
      93             : 
      94           0 : nsCertOverrideService::~nsCertOverrideService()
      95             : {
      96           0 : }
      97             : 
      98             : nsresult
      99           0 : nsCertOverrideService::Init()
     100             : {
     101           0 :   if (!NS_IsMainThread()) {
     102           0 :     MOZ_ASSERT_UNREACHABLE("nsCertOverrideService initialized off main thread");
     103             :     return NS_ERROR_NOT_SAME_THREAD;
     104             :   }
     105             : 
     106             :   nsCOMPtr<nsIObserverService> observerService =
     107           2 :       mozilla::services::GetObserverService();
     108             : 
     109             :   // If we cannot add ourselves as a profile change observer, then we will not
     110             :   // attempt to read/write any settings file. Otherwise, we would end up
     111             :   // reading/writing the wrong settings file after a profile change.
     112           1 :   if (observerService) {
     113           0 :     observerService->AddObserver(this, "profile-before-change", true);
     114           1 :     observerService->AddObserver(this, "profile-do-change", true);
     115             :     // simulate a profile change so we read the current profile's settings file
     116           1 :     Observe(nullptr, "profile-do-change", nullptr);
     117             :   }
     118             : 
     119           0 :   SharedSSLState::NoteCertOverrideServiceInstantiated();
     120             :   return NS_OK;
     121             : }
     122             : 
     123             : NS_IMETHODIMP
     124           1 : nsCertOverrideService::Observe(nsISupports     *,
     125             :                                const char      *aTopic,
     126             :                                const char16_t *aData)
     127             : {
     128             :   // check the topic
     129           1 :   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     130             :     // The profile is about to change,
     131             :     // or is going away because the application is shutting down.
     132             : 
     133           0 :     RemoveAllFromMemory();
     134           1 :   } else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
     135             :     // The profile has already changed.
     136             :     // Now read from the new profile location.
     137             :     // we also need to update the cached file location
     138             : 
     139           0 :     MutexAutoLock lock(mMutex);
     140             : 
     141           2 :     nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mSettingsFile));
     142           1 :     if (NS_SUCCEEDED(rv)) {
     143           3 :       mSettingsFile->AppendNative(NS_LITERAL_CSTRING(CERT_OVERRIDE_FILE_NAME));
     144             :     } else {
     145           0 :       mSettingsFile = nullptr;
     146             :     }
     147           0 :     Read(lock);
     148           0 :     CountPermanentOverrideTelemetry(lock);
     149             :   }
     150             : 
     151           0 :   return NS_OK;
     152             : }
     153             : 
     154             : void
     155           0 : nsCertOverrideService::RemoveAllFromMemory()
     156             : {
     157           0 :   MutexAutoLock lock(mMutex);
     158           0 :   mSettingsTable.Clear();
     159           0 : }
     160             : 
     161             : void
     162           0 : nsCertOverrideService::RemoveAllTemporaryOverrides()
     163             : {
     164           0 :   MutexAutoLock lock(mMutex);
     165           0 :   for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
     166           0 :     nsCertOverrideEntry *entry = iter.Get();
     167           0 :     if (entry->mSettings.mIsTemporary) {
     168           0 :       entry->mSettings.mCert = nullptr;
     169           0 :       iter.Remove();
     170             :     }
     171             :   }
     172             :   // no need to write, as temporaries are never written to disk
     173           0 : }
     174             : 
     175             : nsresult
     176           1 : nsCertOverrideService::Read(const MutexAutoLock& aProofOfLock)
     177             : {
     178             :   // If we don't have a profile, then we won't try to read any settings file.
     179           0 :   if (!mSettingsFile)
     180             :     return NS_OK;
     181             : 
     182             :   nsresult rv;
     183           2 :   nsCOMPtr<nsIInputStream> fileInputStream;
     184           3 :   rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), mSettingsFile);
     185           0 :   if (NS_FAILED(rv)) {
     186             :     return rv;
     187             :   }
     188             : 
     189           0 :   nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(fileInputStream, &rv);
     190           0 :   if (NS_FAILED(rv)) {
     191             :     return rv;
     192             :   }
     193             : 
     194           0 :   nsAutoCString buffer;
     195           0 :   bool isMore = true;
     196           0 :   int32_t hostIndex = 0, algoIndex, fingerprintIndex, overrideBitsIndex, dbKeyIndex;
     197             : 
     198             :   /* file format is:
     199             :    *
     200             :    * host:port \t fingerprint-algorithm \t fingerprint \t override-mask \t dbKey
     201             :    *
     202             :    *   where override-mask is a sequence of characters,
     203             :    *     M meaning hostname-Mismatch-override
     204             :    *     U meaning Untrusted-override
     205             :    *     T meaning Time-error-override (expired/not yet valid)
     206             :    *
     207             :    * if this format isn't respected we move onto the next line in the file.
     208             :    */
     209             : 
     210           0 :   while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
     211           0 :     if (buffer.IsEmpty() || buffer.First() == '#') {
     212           0 :       continue;
     213             :     }
     214             : 
     215             :     // this is a cheap, cheesy way of parsing a tab-delimited line into
     216             :     // string indexes, which can be lopped off into substrings. just for
     217             :     // purposes of obfuscation, it also checks that each token was found.
     218             :     // todo: use iterators?
     219           0 :     if ((algoIndex         = buffer.FindChar('\t', hostIndex)         + 1) == 0 ||
     220           0 :         (fingerprintIndex  = buffer.FindChar('\t', algoIndex)         + 1) == 0 ||
     221           0 :         (overrideBitsIndex = buffer.FindChar('\t', fingerprintIndex)  + 1) == 0 ||
     222           0 :         (dbKeyIndex        = buffer.FindChar('\t', overrideBitsIndex) + 1) == 0) {
     223             :       continue;
     224             :     }
     225             : 
     226           0 :     const nsACString& tmp = Substring(buffer, hostIndex, algoIndex - hostIndex - 1);
     227             :     // We just ignore the algorithm string.
     228           0 :     const nsACString& fingerprint = Substring(buffer, fingerprintIndex, overrideBitsIndex - fingerprintIndex - 1);
     229           0 :     const nsACString& bits_string = Substring(buffer, overrideBitsIndex, dbKeyIndex - overrideBitsIndex - 1);
     230           0 :     const nsACString& db_key = Substring(buffer, dbKeyIndex, buffer.Length() - dbKeyIndex);
     231             : 
     232           0 :     nsAutoCString host(tmp);
     233             :     nsCertOverride::OverrideBits bits;
     234           0 :     nsCertOverride::convertStringToBits(bits_string, bits);
     235             : 
     236             :     int32_t port;
     237           0 :     int32_t portIndex = host.RFindChar(':');
     238           0 :     if (portIndex == kNotFound)
     239           0 :       continue; // Ignore broken entries
     240             : 
     241             :     nsresult portParseError;
     242           0 :     nsAutoCString portString(Substring(host, portIndex+1));
     243           0 :     port = portString.ToInteger(&portParseError);
     244           0 :     if (NS_FAILED(portParseError))
     245             :       continue; // Ignore broken entries
     246             : 
     247           0 :     host.Truncate(portIndex);
     248             : 
     249             :     AddEntryToList(host, port,
     250             :                    nullptr, // don't have the cert
     251             :                    false, // not temporary
     252           0 :                    fingerprint, bits, db_key, aProofOfLock);
     253             :   }
     254             : 
     255           0 :   return NS_OK;
     256             : }
     257             : 
     258             : static const char sSHA256OIDString[] = "OID.2.16.840.1.101.3.4.2.1";
     259             : nsresult
     260           0 : nsCertOverrideService::Write(const MutexAutoLock& aProofOfLock)
     261             : {
     262             :   // If we don't have any profile, then we won't try to write any file
     263           0 :   if (!mSettingsFile) {
     264             :     return NS_OK;
     265             :   }
     266             : 
     267             :   nsresult rv;
     268           0 :   nsCOMPtr<nsIOutputStream> fileOutputStream;
     269           0 :   rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(fileOutputStream),
     270             :                                        mSettingsFile,
     271             :                                        -1,
     272           0 :                                        0600);
     273           0 :   if (NS_FAILED(rv)) {
     274           0 :     NS_ERROR("failed to open cert_warn_settings.txt for writing");
     275           0 :     return rv;
     276             :   }
     277             : 
     278             :   // get a buffered output stream 4096 bytes big, to optimize writes
     279           0 :   nsCOMPtr<nsIOutputStream> bufferedOutputStream;
     280           0 :   rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
     281           0 :                                   fileOutputStream.forget(), 4096);
     282           0 :   if (NS_FAILED(rv)) {
     283             :     return rv;
     284             :   }
     285             : 
     286             :   static const char kHeader[] =
     287             :       "# PSM Certificate Override Settings file" NS_LINEBREAK
     288             :       "# This is a generated file!  Do not edit." NS_LINEBREAK;
     289             : 
     290             :   /* see ::Read for file format */
     291             : 
     292             :   uint32_t unused;
     293           0 :   bufferedOutputStream->Write(kHeader, sizeof(kHeader) - 1, &unused);
     294             : 
     295             :   static const char kTab[] = "\t";
     296           0 :   for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
     297           0 :     nsCertOverrideEntry *entry = iter.Get();
     298             : 
     299           0 :     const nsCertOverride &settings = entry->mSettings;
     300           0 :     if (settings.mIsTemporary) {
     301           0 :       continue;
     302             :     }
     303             : 
     304           0 :     nsAutoCString bits_string;
     305           0 :     nsCertOverride::convertBitsToString(settings.mOverrideBits, bits_string);
     306             : 
     307           0 :     bufferedOutputStream->Write(entry->mHostWithPort.get(),
     308           0 :                                 entry->mHostWithPort.Length(), &unused);
     309           0 :     bufferedOutputStream->Write(kTab, sizeof(kTab) - 1, &unused);
     310           0 :     bufferedOutputStream->Write(sSHA256OIDString, sizeof(sSHA256OIDString) - 1,
     311           0 :                                 &unused);
     312           0 :     bufferedOutputStream->Write(kTab, sizeof(kTab) - 1, &unused);
     313           0 :     bufferedOutputStream->Write(settings.mFingerprint.get(),
     314           0 :                                 settings.mFingerprint.Length(), &unused);
     315           0 :     bufferedOutputStream->Write(kTab, sizeof(kTab) - 1, &unused);
     316           0 :     bufferedOutputStream->Write(bits_string.get(),
     317           0 :                                 bits_string.Length(), &unused);
     318           0 :     bufferedOutputStream->Write(kTab, sizeof(kTab) - 1, &unused);
     319           0 :     bufferedOutputStream->Write(settings.mDBKey.get(),
     320           0 :                                 settings.mDBKey.Length(), &unused);
     321           0 :     bufferedOutputStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &unused);
     322             :   }
     323             : 
     324             :   // All went ok. Maybe except for problems in Write(), but the stream detects
     325             :   // that for us
     326           0 :   nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(bufferedOutputStream);
     327           0 :   MOZ_ASSERT(safeStream, "Expected a safe output stream!");
     328           0 :   if (safeStream) {
     329           0 :     rv = safeStream->Finish();
     330           0 :     if (NS_FAILED(rv)) {
     331           0 :       NS_WARNING("failed to save cert warn settings file! possible dataloss");
     332           0 :       return rv;
     333             :     }
     334             :   }
     335             : 
     336             :   return NS_OK;
     337             : }
     338             : 
     339             : static nsresult
     340           0 : GetCertFingerprintByOidTag(nsIX509Cert *aCert,
     341             :                            SECOidTag aOidTag,
     342             :                            nsCString &fp)
     343             : {
     344           0 :   UniqueCERTCertificate nsscert(aCert->GetCert());
     345           0 :   if (!nsscert) {
     346             :     return NS_ERROR_FAILURE;
     347             :   }
     348           0 :   return GetCertFingerprintByOidTag(nsscert.get(), aOidTag, fp);
     349             : }
     350             : 
     351             : NS_IMETHODIMP
     352           0 : nsCertOverrideService::RememberValidityOverride(const nsACString& aHostName,
     353             :                                                 int32_t aPort,
     354             :                                                 nsIX509Cert* aCert,
     355             :                                                 uint32_t aOverrideBits,
     356             :                                                 bool aTemporary)
     357             : {
     358           0 :   NS_ENSURE_ARG_POINTER(aCert);
     359           0 :   if (aHostName.IsEmpty())
     360             :     return NS_ERROR_INVALID_ARG;
     361           0 :   if (aPort < -1)
     362             :     return NS_ERROR_INVALID_ARG;
     363             : 
     364           0 :   UniqueCERTCertificate nsscert(aCert->GetCert());
     365           0 :   if (!nsscert) {
     366             :     return NS_ERROR_FAILURE;
     367             :   }
     368             : 
     369           0 :   nsAutoCString nickname;
     370           0 :   nsresult rv = DefaultServerNicknameForCert(nsscert.get(), nickname);
     371           0 :   if (!aTemporary && NS_SUCCEEDED(rv)) {
     372           0 :     UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
     373           0 :     if (!slot) {
     374           0 :       return NS_ERROR_FAILURE;
     375             :     }
     376             : 
     377             :     // This can fail (for example, if we're in read-only mode). Luckily, we
     378             :     // don't even need it to succeed - we always match on the stored hash of the
     379             :     // certificate rather than the full certificate. It makes the display a bit
     380             :     // less informative (since we won't have a certificate to display), but it's
     381             :     // better than failing the entire operation.
     382           0 :     Unused << PK11_ImportCert(slot.get(), nsscert.get(), CK_INVALID_HANDLE,
     383             :                               nickname.get(), false);
     384             :   }
     385             : 
     386           0 :   nsAutoCString fpStr;
     387           0 :   rv = GetCertFingerprintByOidTag(nsscert.get(), SEC_OID_SHA256, fpStr);
     388           0 :   if (NS_FAILED(rv))
     389             :     return rv;
     390             : 
     391           0 :   nsAutoCString dbkey;
     392           0 :   rv = aCert->GetDbKey(dbkey);
     393           0 :   if (NS_FAILED(rv)) {
     394             :     return rv;
     395             :   }
     396             : 
     397             :   {
     398           0 :     MutexAutoLock lock(mMutex);
     399           0 :     AddEntryToList(aHostName, aPort,
     400             :                    aTemporary ? aCert : nullptr,
     401             :                      // keep a reference to the cert for temporary overrides
     402             :                    aTemporary,
     403             :                    fpStr,
     404             :                    (nsCertOverride::OverrideBits)aOverrideBits,
     405           0 :                    dbkey, lock);
     406           0 :     if (!aTemporary) {
     407           0 :       Write(lock);
     408             :     }
     409             :   }
     410             : 
     411           0 :   return NS_OK;
     412             : }
     413             : 
     414             : NS_IMETHODIMP
     415           0 : nsCertOverrideService::RememberTemporaryValidityOverrideUsingFingerprint(
     416             :   const nsACString& aHostName,
     417             :   int32_t aPort,
     418             :   const nsACString& aCertFingerprint,
     419             :   uint32_t aOverrideBits)
     420             : {
     421           0 :   if(aCertFingerprint.IsEmpty() || aHostName.IsEmpty() || (aPort < -1)) {
     422             :     return NS_ERROR_INVALID_ARG;
     423             :   }
     424             : 
     425           0 :   MutexAutoLock lock(mMutex);
     426           0 :   AddEntryToList(aHostName, aPort,
     427             :                  nullptr, // No cert to keep alive
     428             :                  true, // temporary
     429             :                  aCertFingerprint,
     430             :                  (nsCertOverride::OverrideBits)aOverrideBits,
     431           0 :                  EmptyCString(),  // dbkey
     432           0 :                  lock);
     433             : 
     434             :   return NS_OK;
     435             : }
     436             : 
     437             : NS_IMETHODIMP
     438           0 : nsCertOverrideService::HasMatchingOverride(const nsACString & aHostName, int32_t aPort,
     439             :                                            nsIX509Cert *aCert,
     440             :                                            uint32_t *aOverrideBits,
     441             :                                            bool *aIsTemporary,
     442             :                                            bool *_retval)
     443             : {
     444           0 :   if (aHostName.IsEmpty())
     445             :     return NS_ERROR_INVALID_ARG;
     446           0 :   if (aPort < -1)
     447             :     return NS_ERROR_INVALID_ARG;
     448             : 
     449           0 :   NS_ENSURE_ARG_POINTER(aCert);
     450           0 :   NS_ENSURE_ARG_POINTER(aOverrideBits);
     451           0 :   NS_ENSURE_ARG_POINTER(aIsTemporary);
     452           0 :   NS_ENSURE_ARG_POINTER(_retval);
     453           0 :   *_retval = false;
     454           0 :   *aOverrideBits = static_cast<uint32_t>(nsCertOverride::OverrideBits::None);
     455             : 
     456           0 :   nsAutoCString hostPort;
     457           0 :   GetHostWithPort(aHostName, aPort, hostPort);
     458           0 :   nsCertOverride settings;
     459             : 
     460             :   {
     461           0 :     MutexAutoLock lock(mMutex);
     462           0 :     nsCertOverrideEntry *entry = mSettingsTable.GetEntry(hostPort.get());
     463             : 
     464           0 :     if (!entry)
     465           0 :       return NS_OK;
     466             : 
     467           0 :     settings = entry->mSettings; // copy
     468             :   }
     469             : 
     470           0 :   *aOverrideBits = static_cast<uint32_t>(settings.mOverrideBits);
     471           0 :   *aIsTemporary = settings.mIsTemporary;
     472             : 
     473           0 :   nsAutoCString fpStr;
     474             :   nsresult rv;
     475             : 
     476           0 :   rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256, fpStr);
     477           0 :   if (NS_FAILED(rv)) {
     478             :     return rv;
     479             :   }
     480             : 
     481           0 :   *_retval = settings.mFingerprint.Equals(fpStr);
     482           0 :   return NS_OK;
     483             : }
     484             : 
     485             : nsresult
     486           0 : nsCertOverrideService::AddEntryToList(const nsACString &aHostName, int32_t aPort,
     487             :                                       nsIX509Cert *aCert,
     488             :                                       const bool aIsTemporary,
     489             :                                       const nsACString &fingerprint,
     490             :                                       nsCertOverride::OverrideBits ob,
     491             :                                       const nsACString &dbKey,
     492             :                                       const MutexAutoLock& aProofOfLock)
     493             : {
     494           0 :   nsAutoCString hostPort;
     495           0 :   GetHostWithPort(aHostName, aPort, hostPort);
     496             : 
     497           0 :   nsCertOverrideEntry *entry = mSettingsTable.PutEntry(hostPort.get());
     498             : 
     499           0 :   if (!entry) {
     500           0 :     NS_ERROR("can't insert a null entry!");
     501           0 :     return NS_ERROR_OUT_OF_MEMORY;
     502             :   }
     503             : 
     504           0 :   entry->mHostWithPort = hostPort;
     505             : 
     506           0 :   nsCertOverride &settings = entry->mSettings;
     507           0 :   settings.mAsciiHost = aHostName;
     508           0 :   settings.mPort = aPort;
     509           0 :   settings.mIsTemporary = aIsTemporary;
     510           0 :   settings.mFingerprint = fingerprint;
     511           0 :   settings.mOverrideBits = ob;
     512           0 :   settings.mDBKey = dbKey;
     513             :   // remove whitespace from stored dbKey for backwards compatibility
     514           0 :   settings.mDBKey.StripWhitespace();
     515           0 :   settings.mCert = aCert;
     516             : 
     517           0 :   return NS_OK;
     518             : }
     519             : 
     520             : NS_IMETHODIMP
     521           0 : nsCertOverrideService::ClearValidityOverride(const nsACString & aHostName, int32_t aPort)
     522             : {
     523           0 :   if (!NS_IsMainThread()) {
     524             :     return NS_ERROR_NOT_SAME_THREAD;
     525             :   }
     526             : 
     527           0 :   if (aPort == 0 && aHostName.EqualsLiteral("all:temporary-certificates")) {
     528           0 :     RemoveAllTemporaryOverrides();
     529           0 :     return NS_OK;
     530             :   }
     531           0 :   nsAutoCString hostPort;
     532           0 :   GetHostWithPort(aHostName, aPort, hostPort);
     533             :   {
     534           0 :     MutexAutoLock lock(mMutex);
     535           0 :     mSettingsTable.RemoveEntry(hostPort.get());
     536           0 :     Write(lock);
     537             :   }
     538             : 
     539           0 :   nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
     540           0 :   if (nss) {
     541           0 :     SSL_ClearSessionCache();
     542             :   } else {
     543             :     return NS_ERROR_NOT_AVAILABLE;
     544             :   }
     545             : 
     546           0 :   return NS_OK;
     547             : }
     548             : 
     549             : void
     550           0 : nsCertOverrideService::CountPermanentOverrideTelemetry(const MutexAutoLock& aProofOfLock)
     551             : {
     552           0 :   uint32_t overrideCount = 0;
     553           1 :   for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
     554           0 :     if (!iter.Get()->mSettings.mIsTemporary) {
     555           0 :       overrideCount++;
     556             :     }
     557             :   }
     558             :   Telemetry::Accumulate(Telemetry::SSL_PERMANENT_CERT_ERROR_OVERRIDES,
     559           0 :                         overrideCount);
     560           0 : }
     561             : 
     562             : static bool
     563           0 : matchesDBKey(nsIX509Cert* cert, const nsCString& matchDbKey)
     564             : {
     565           0 :   nsAutoCString dbKey;
     566           0 :   nsresult rv = cert->GetDbKey(dbKey);
     567           0 :   if (NS_FAILED(rv)) {
     568             :     return false;
     569             :   }
     570           0 :   return dbKey.Equals(matchDbKey);
     571             : }
     572             : 
     573             : NS_IMETHODIMP
     574           0 : nsCertOverrideService::IsCertUsedForOverrides(nsIX509Cert *aCert,
     575             :                                               bool aCheckTemporaries,
     576             :                                               bool aCheckPermanents,
     577             :                                               uint32_t *_retval)
     578             : {
     579           0 :   NS_ENSURE_ARG(aCert);
     580           0 :   NS_ENSURE_ARG(_retval);
     581             : 
     582           0 :   uint32_t counter = 0;
     583             :   {
     584           0 :     MutexAutoLock lock(mMutex);
     585           0 :     for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
     586           0 :       const nsCertOverride &settings = iter.Get()->mSettings;
     587             : 
     588           0 :       if (( settings.mIsTemporary && !aCheckTemporaries) ||
     589           0 :           (!settings.mIsTemporary && !aCheckPermanents)) {
     590             :         continue;
     591             :       }
     592             : 
     593           0 :       if (matchesDBKey(aCert, settings.mDBKey)) {
     594           0 :         nsAutoCString cert_fingerprint;
     595             :         nsresult rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256,
     596           0 :                                                  cert_fingerprint);
     597           0 :         if (NS_SUCCEEDED(rv) &&
     598           0 :             settings.mFingerprint.Equals(cert_fingerprint)) {
     599           0 :           counter++;
     600             :         }
     601             :       }
     602             :     }
     603             :   }
     604           0 :   *_retval = counter;
     605           0 :   return NS_OK;
     606             : }
     607             : 
     608             : nsresult
     609           0 : nsCertOverrideService::EnumerateCertOverrides(nsIX509Cert *aCert,
     610             :                          CertOverrideEnumerator aEnumerator,
     611             :                          void *aUserData)
     612             : {
     613           0 :   MutexAutoLock lock(mMutex);
     614           0 :   for (auto iter = mSettingsTable.Iter(); !iter.Done(); iter.Next()) {
     615           0 :     const nsCertOverride &settings = iter.Get()->mSettings;
     616             : 
     617           0 :     if (!aCert) {
     618           0 :       aEnumerator(settings, aUserData);
     619             :     } else {
     620           0 :       if (matchesDBKey(aCert, settings.mDBKey)) {
     621           0 :         nsAutoCString cert_fingerprint;
     622             :         nsresult rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256,
     623           0 :                                                  cert_fingerprint);
     624           0 :         if (NS_SUCCEEDED(rv) &&
     625           0 :             settings.mFingerprint.Equals(cert_fingerprint)) {
     626           0 :           aEnumerator(settings, aUserData);
     627             :         }
     628             :       }
     629             :     }
     630             :   }
     631           0 :   return NS_OK;
     632             : }
     633             : 
     634             : void
     635           0 : nsCertOverrideService::GetHostWithPort(const nsACString & aHostName, int32_t aPort, nsACString& _retval)
     636             : {
     637           0 :   nsAutoCString hostPort(aHostName);
     638           0 :   if (aPort == -1) {
     639           0 :     aPort = 443;
     640             :   }
     641           0 :   if (!hostPort.IsEmpty()) {
     642           0 :     hostPort.Append(':');
     643           0 :     hostPort.AppendInt(aPort);
     644             :   }
     645           0 :   _retval.Assign(hostPort);
     646           0 : }

Generated by: LCOV version 1.13-14-ga5dd952