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

Generated by: LCOV version 1.13