LCOV - code coverage report
Current view: top level - security/manager/ssl - CertBlocklist.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 314 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; 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 "CertBlocklist.h"
       8             : 
       9             : #include "mozilla/Assertions.h"
      10             : #include "mozilla/Base64.h"
      11             : #include "mozilla/Casting.h"
      12             : #include "mozilla/IntegerPrintfMacros.h"
      13             : #include "mozilla/Logging.h"
      14             : #include "mozilla/Preferences.h"
      15             : #include "mozilla/Unused.h"
      16             : #include "nsAppDirectoryServiceDefs.h"
      17             : #include "nsDependentString.h"
      18             : #include "nsDirectoryServiceUtils.h"
      19             : #include "nsICryptoHash.h"
      20             : #include "nsIFileStreams.h"
      21             : #include "nsILineInputStream.h"
      22             : #include "nsISafeOutputStream.h"
      23             : #include "nsIX509Cert.h"
      24             : #include "nsNetCID.h"
      25             : #include "nsNetUtil.h"
      26             : #include "nsPromiseFlatString.h"
      27             : #include "nsTHashtable.h"
      28             : #include "nsThreadUtils.h"
      29             : #include "pkix/Input.h"
      30             : #include "prtime.h"
      31             : 
      32           0 : NS_IMPL_ISUPPORTS(CertBlocklist, nsICertBlocklist)
      33             : 
      34             : using namespace mozilla;
      35             : using namespace mozilla::pkix;
      36             : 
      37             : #define PREF_BACKGROUND_UPDATE_TIMER "app.update.lastUpdateTime.blocklist-background-update-timer"
      38             : #define PREF_BLOCKLIST_ONECRL_CHECKED "services.blocklist.onecrl.checked"
      39             : #define PREF_MAX_STALENESS_IN_SECONDS "security.onecrl.maximum_staleness_in_seconds"
      40             : #define PREF_ONECRL_VIA_AMO "security.onecrl.via.amo"
      41             : 
      42             : static LazyLogModule gCertBlockPRLog("CertBlock");
      43             : 
      44             : uint32_t CertBlocklist::sLastBlocklistUpdate = 0U;
      45             : uint32_t CertBlocklist::sLastKintoUpdate = 0U;
      46             : uint32_t CertBlocklist::sMaxStaleness = 0U;
      47             : bool CertBlocklist::sUseAMO = true;
      48             : 
      49           0 : CertBlocklistItem::CertBlocklistItem(const uint8_t* DNData,
      50             :                                      size_t DNLength,
      51             :                                      const uint8_t* otherData,
      52             :                                      size_t otherLength,
      53           0 :                                      CertBlocklistItemMechanism itemMechanism)
      54             :   : mIsCurrent(false)
      55           0 :   , mItemMechanism(itemMechanism)
      56             : {
      57           0 :   mDNData = new uint8_t[DNLength];
      58           0 :   memcpy(mDNData, DNData, DNLength);
      59           0 :   mDNLength = DNLength;
      60             : 
      61           0 :   mOtherData = new uint8_t[otherLength];
      62           0 :   memcpy(mOtherData, otherData, otherLength);
      63           0 :   mOtherLength = otherLength;
      64           0 : }
      65             : 
      66           0 : CertBlocklistItem::CertBlocklistItem(const CertBlocklistItem& aItem)
      67             : {
      68           0 :   mDNLength = aItem.mDNLength;
      69           0 :   mDNData = new uint8_t[mDNLength];
      70           0 :   memcpy(mDNData, aItem.mDNData, mDNLength);
      71             : 
      72           0 :   mOtherLength = aItem.mOtherLength;
      73           0 :   mOtherData = new uint8_t[mOtherLength];
      74           0 :   memcpy(mOtherData, aItem.mOtherData, mOtherLength);
      75             : 
      76           0 :   mItemMechanism = aItem.mItemMechanism;
      77             : 
      78           0 :   mIsCurrent = aItem.mIsCurrent;
      79           0 : }
      80             : 
      81           0 : CertBlocklistItem::~CertBlocklistItem()
      82             : {
      83           0 :   delete[] mDNData;
      84           0 :   delete[] mOtherData;
      85           0 : }
      86             : 
      87             : nsresult
      88           0 : CertBlocklistItem::ToBase64(nsACString& b64DNOut, nsACString& b64OtherOut)
      89             : {
      90           0 :   nsDependentCSubstring DNString(BitwiseCast<char*, uint8_t*>(mDNData),
      91           0 :                                  mDNLength);
      92           0 :   nsDependentCSubstring otherString(BitwiseCast<char*, uint8_t*>(mOtherData),
      93           0 :                                     mOtherLength);
      94           0 :   nsresult rv = Base64Encode(DNString, b64DNOut);
      95           0 :   if (NS_FAILED(rv)) {
      96           0 :     return rv;
      97             :   }
      98           0 :   rv = Base64Encode(otherString, b64OtherOut);
      99           0 :   return rv;
     100             : }
     101             : 
     102             : bool
     103           0 : CertBlocklistItem::operator==(const CertBlocklistItem& aItem) const
     104             : {
     105           0 :   if (aItem.mItemMechanism != mItemMechanism) {
     106           0 :     return false;
     107             :   }
     108           0 :   if (aItem.mDNLength != mDNLength ||
     109           0 :       aItem.mOtherLength != mOtherLength) {
     110           0 :     return false;
     111             :   }
     112           0 :   return memcmp(aItem.mDNData, mDNData, mDNLength) == 0 &&
     113           0 :          memcmp(aItem.mOtherData, mOtherData, mOtherLength) == 0;
     114             : }
     115             : 
     116             : uint32_t
     117           0 : CertBlocklistItem::Hash() const
     118             : {
     119             :   uint32_t hash;
     120             :   // there's no requirement for a serial to be as large as the size of the hash
     121             :   // key; if it's smaller, fall back to the first octet (otherwise, the last
     122             :   // four)
     123           0 :   if (mItemMechanism == BlockByIssuerAndSerial &&
     124           0 :       mOtherLength >= sizeof(hash)) {
     125           0 :     memcpy(&hash, mOtherData + mOtherLength - sizeof(hash), sizeof(hash));
     126             :   } else {
     127           0 :     hash = *mOtherData;
     128             :   }
     129           0 :   return hash;
     130             : }
     131             : 
     132           0 : CertBlocklist::CertBlocklist()
     133             :   : mMutex("CertBlocklist::mMutex")
     134             :   , mModified(false)
     135             :   , mBackingFileIsInitialized(false)
     136           0 :   , mBackingFile(nullptr)
     137             : {
     138           0 : }
     139             : 
     140           0 : CertBlocklist::~CertBlocklist()
     141             : {
     142             :   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
     143             :                                   PREF_BACKGROUND_UPDATE_TIMER,
     144           0 :                                   this);
     145             :   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
     146             :                                   PREF_MAX_STALENESS_IN_SECONDS,
     147           0 :                                   this);
     148             :   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
     149             :                                   PREF_ONECRL_VIA_AMO,
     150           0 :                                   this);
     151             :   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
     152             :                                   PREF_BLOCKLIST_ONECRL_CHECKED,
     153           0 :                                   this);
     154           0 : }
     155             : 
     156             : nsresult
     157           0 : CertBlocklist::Init()
     158             : {
     159           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug, ("CertBlocklist::Init"));
     160             : 
     161             :   // Init must be on main thread for getting the profile directory
     162           0 :   if (!NS_IsMainThread()) {
     163           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     164             :            ("CertBlocklist::Init - called off main thread"));
     165           0 :     return NS_ERROR_NOT_SAME_THREAD;
     166             :   }
     167             : 
     168             :   // Register preference callbacks
     169             :   nsresult rv =
     170             :       Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
     171             :                                            PREF_BACKGROUND_UPDATE_TIMER,
     172           0 :                                            this);
     173           0 :   if (NS_FAILED(rv)) {
     174           0 :     return rv;
     175             :   }
     176             :   rv = Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
     177             :                                             PREF_MAX_STALENESS_IN_SECONDS,
     178           0 :                                             this);
     179           0 :   if (NS_FAILED(rv)) {
     180           0 :     return rv;
     181             :   }
     182             :   rv = Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
     183             :                                             PREF_ONECRL_VIA_AMO,
     184           0 :                                             this);
     185           0 :   if (NS_FAILED(rv)) {
     186           0 :     return rv;
     187             :   }
     188             :   rv = Preferences::RegisterCallbackAndCall(CertBlocklist::PreferenceChanged,
     189             :                                             PREF_BLOCKLIST_ONECRL_CHECKED,
     190           0 :                                             this);
     191           0 :   if (NS_FAILED(rv)) {
     192           0 :     return rv;
     193             :   }
     194             : 
     195             :   // Get the profile directory
     196           0 :   rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
     197           0 :                               getter_AddRefs(mBackingFile));
     198           0 :   if (NS_FAILED(rv) || !mBackingFile) {
     199           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     200             :            ("CertBlocklist::Init - couldn't get profile dir"));
     201             :     // Since we're returning NS_OK here, set mBackingFile to a safe value.
     202             :     // (We need initialization to succeed and CertBlocklist to be in a
     203             :     // well-defined state if the profile directory doesn't exist.)
     204           0 :     mBackingFile = nullptr;
     205           0 :     return NS_OK;
     206             :   }
     207           0 :   rv = mBackingFile->Append(NS_LITERAL_STRING("revocations.txt"));
     208           0 :   if (NS_FAILED(rv)) {
     209           0 :     return rv;
     210             :   }
     211           0 :   nsAutoCString path;
     212           0 :   rv = mBackingFile->GetNativePath(path);
     213           0 :   if (NS_FAILED(rv)) {
     214           0 :     return rv;
     215             :   }
     216           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     217             :          ("CertBlocklist::Init certList path: %s", path.get()));
     218             : 
     219           0 :   return NS_OK;
     220             : }
     221             : 
     222             : nsresult
     223           0 : CertBlocklist::EnsureBackingFileInitialized(MutexAutoLock& lock)
     224             : {
     225           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     226             :          ("CertBlocklist::EnsureBackingFileInitialized"));
     227           0 :   if (mBackingFileIsInitialized || !mBackingFile) {
     228           0 :     return NS_OK;
     229             :   }
     230             : 
     231           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     232             :          ("CertBlocklist::EnsureBackingFileInitialized - not initialized"));
     233             : 
     234           0 :   bool exists = false;
     235           0 :   nsresult rv = mBackingFile->Exists(&exists);
     236           0 :   if (NS_FAILED(rv)) {
     237           0 :     return rv;
     238             :   }
     239           0 :   if (!exists) {
     240           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     241             :            ("CertBlocklist::EnsureBackingFileInitialized no revocations file"));
     242           0 :     return NS_OK;
     243             :   }
     244             : 
     245             :   // Load the revocations file into the cert blocklist
     246             :   nsCOMPtr<nsIFileInputStream> fileStream(
     247           0 :       do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv));
     248           0 :   if (NS_FAILED(rv)) {
     249           0 :     return rv;
     250             :   }
     251             : 
     252           0 :   rv = fileStream->Init(mBackingFile, -1, -1, false);
     253           0 :   if (NS_FAILED(rv)) {
     254           0 :     return rv;
     255             :   }
     256             : 
     257           0 :   nsCOMPtr<nsILineInputStream> lineStream(do_QueryInterface(fileStream, &rv));
     258           0 :   nsAutoCString line;
     259           0 :   nsAutoCString DN;
     260           0 :   nsAutoCString other;
     261             :   CertBlocklistItemMechanism mechanism;
     262             :   // read in the revocations file. The file format is as follows: each line
     263             :   // contains a comment, base64 encoded DER for a DN, base64 encoded DER for a
     264             :   // serial number or a Base64 encoded SHA256 hash of a public key. Comment
     265             :   // lines start with '#', serial number lines, ' ' (a space), public key hashes
     266             :   // with '\t' (a tab) and anything else is assumed to be a DN.
     267           0 :   bool more = true;
     268           0 :   do {
     269           0 :     rv = lineStream->ReadLine(line, &more);
     270           0 :     if (NS_FAILED(rv)) {
     271           0 :       break;
     272             :     }
     273             :     // ignore comments and empty lines
     274           0 :     if (line.IsEmpty() || line.First() == '#') {
     275           0 :       continue;
     276             :     }
     277           0 :     if (line.First() != ' ' && line.First() != '\t') {
     278           0 :       DN = line;
     279           0 :       continue;
     280             :     }
     281           0 :     other = line;
     282           0 :     if (line.First() == ' ') {
     283           0 :       mechanism = BlockByIssuerAndSerial;
     284             :     } else {
     285           0 :       mechanism = BlockBySubjectAndPubKey;
     286             :     }
     287           0 :     other.Trim(" \t", true, false, false);
     288             :     // Serial numbers and public key hashes 'belong' to the last DN line seen;
     289             :     // if no DN has been seen, the serial number or public key hash is ignored.
     290           0 :     if (DN.IsEmpty() || other.IsEmpty()) {
     291           0 :       continue;
     292             :     }
     293           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     294             :            ("CertBlocklist::EnsureBackingFileInitialized adding: %s %s",
     295             :             DN.get(), other.get()));
     296             : 
     297           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     298             :            ("CertBlocklist::EnsureBackingFileInitialized - pre-decode"));
     299             : 
     300           0 :     rv = AddRevokedCertInternal(DN, other, mechanism, CertOldFromLocalCache,
     301             :                                 lock);
     302             : 
     303           0 :     if (NS_FAILED(rv)) {
     304             :       // we warn here, rather than abandoning, since we need to
     305             :       // ensure that as many items as possible are read
     306           0 :       MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     307             :              ("CertBlocklist::EnsureBackingFileInitialized adding revoked cert "
     308             :               "failed"));
     309             :     }
     310             :   } while (more);
     311           0 :   mBackingFileIsInitialized = true;
     312           0 :   return NS_OK;
     313             : }
     314             : 
     315             : NS_IMETHODIMP
     316           0 : CertBlocklist::RevokeCertBySubjectAndPubKey(const nsACString& aSubject,
     317             :                                             const nsACString& aPubKeyHash)
     318             : {
     319           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     320             :          ("CertBlocklist::RevokeCertBySubjectAndPubKey - subject is: %s and pubKeyHash: %s",
     321             :           PromiseFlatCString(aSubject).get(),
     322             :           PromiseFlatCString(aPubKeyHash).get()));
     323           0 :   MutexAutoLock lock(mMutex);
     324             : 
     325             :   return AddRevokedCertInternal(aSubject, aPubKeyHash,
     326             :                                 BlockBySubjectAndPubKey,
     327           0 :                                 CertNewFromBlocklist, lock);
     328             : }
     329             : 
     330             : NS_IMETHODIMP
     331           0 : CertBlocklist::RevokeCertByIssuerAndSerial(const nsACString& aIssuer,
     332             :                                            const nsACString& aSerialNumber)
     333             : {
     334           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     335             :          ("CertBlocklist::RevokeCertByIssuerAndSerial - issuer is: %s and serial: %s",
     336             :           PromiseFlatCString(aIssuer).get(),
     337             :           PromiseFlatCString(aSerialNumber).get()));
     338           0 :   MutexAutoLock lock(mMutex);
     339             : 
     340             :   return AddRevokedCertInternal(aIssuer, aSerialNumber,
     341             :                                 BlockByIssuerAndSerial,
     342           0 :                                 CertNewFromBlocklist, lock);
     343             : }
     344             : 
     345             : nsresult
     346           0 : CertBlocklist::AddRevokedCertInternal(const nsACString& aEncodedDN,
     347             :                                       const nsACString& aEncodedOther,
     348             :                                       CertBlocklistItemMechanism aMechanism,
     349             :                                       CertBlocklistItemState aItemState,
     350             :                                       MutexAutoLock& /*proofOfLock*/)
     351             : {
     352           0 :   nsCString decodedDN;
     353           0 :   nsCString decodedOther;
     354             : 
     355           0 :   nsresult rv = Base64Decode(aEncodedDN, decodedDN);
     356           0 :   if (NS_FAILED(rv)) {
     357           0 :     return rv;
     358             :   }
     359           0 :   rv = Base64Decode(aEncodedOther, decodedOther);
     360           0 :   if (NS_FAILED(rv)) {
     361           0 :     return rv;
     362             :   }
     363             : 
     364             :   CertBlocklistItem item(
     365             :     BitwiseCast<const uint8_t*, const char*>(decodedDN.get()),
     366           0 :     decodedDN.Length(),
     367             :     BitwiseCast<const uint8_t*, const char*>(decodedOther.get()),
     368           0 :     decodedOther.Length(),
     369           0 :     aMechanism);
     370             : 
     371           0 :   if (aItemState == CertNewFromBlocklist) {
     372             :     // We want SaveEntries to be a no-op if no new entries are added.
     373           0 :     nsGenericHashKey<CertBlocklistItem>* entry = mBlocklist.GetEntry(item);
     374           0 :     if (!entry) {
     375           0 :       mModified = true;
     376             :     } else {
     377             :       // Ensure that any existing item is replaced by a fresh one so we can
     378             :       // use mIsCurrent to decide which entries to write out.
     379           0 :       mBlocklist.RemoveEntry(entry);
     380             :     }
     381           0 :     item.mIsCurrent = true;
     382             :   }
     383           0 :   mBlocklist.PutEntry(item);
     384             : 
     385           0 :   return NS_OK;
     386             : }
     387             : 
     388             : // Write a line for a given string in the output stream
     389             : nsresult
     390           0 : WriteLine(nsIOutputStream* outputStream, const nsACString& string)
     391             : {
     392           0 :   nsAutoCString line(string);
     393           0 :   line.Append('\n');
     394             : 
     395           0 :   const char* data = line.get();
     396           0 :   uint32_t length = line.Length();
     397           0 :   nsresult rv = NS_OK;
     398           0 :   while (NS_SUCCEEDED(rv) && length) {
     399           0 :     uint32_t bytesWritten = 0;
     400           0 :     rv = outputStream->Write(data, length, &bytesWritten);
     401           0 :     if (NS_FAILED(rv)) {
     402           0 :       return rv;
     403             :     }
     404             :     // if no data is written, something is wrong
     405           0 :     if (!bytesWritten) {
     406           0 :       return NS_ERROR_FAILURE;
     407             :     }
     408           0 :     length -= bytesWritten;
     409           0 :     data += bytesWritten;
     410             :   }
     411           0 :   return rv;
     412             : }
     413             : 
     414             : // void saveEntries();
     415             : // Store the blockist in a text file containing base64 encoded issuers and
     416             : // serial numbers.
     417             : //
     418             : // Each item is stored on a separate line; each issuer is followed by its
     419             : // revoked serial numbers, indented by one space.
     420             : //
     421             : // lines starting with a # character are ignored
     422             : NS_IMETHODIMP
     423           0 : CertBlocklist::SaveEntries()
     424             : {
     425           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Debug,
     426             :       ("CertBlocklist::SaveEntries - not initialized"));
     427           0 :   MutexAutoLock lock(mMutex);
     428           0 :   if (!mModified) {
     429           0 :     return NS_OK;
     430             :   }
     431             : 
     432           0 :   nsresult rv = EnsureBackingFileInitialized(lock);
     433           0 :   if (NS_FAILED(rv)) {
     434           0 :     return rv;
     435             :   }
     436             : 
     437           0 :   if (!mBackingFile) {
     438             :     // We allow this to succeed with no profile directory for tests
     439           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     440             :            ("CertBlocklist::SaveEntries no file in profile to write to"));
     441           0 :     return NS_OK;
     442             :   }
     443             : 
     444             :   // Data needed for writing blocklist items out to the revocations file
     445           0 :   IssuerTable issuerTable;
     446           0 :   BlocklistStringSet issuers;
     447           0 :   nsCOMPtr<nsIOutputStream> outputStream;
     448             : 
     449           0 :   rv = NS_NewAtomicFileOutputStream(getter_AddRefs(outputStream),
     450           0 :                                     mBackingFile, -1, -1, 0);
     451           0 :   if (NS_FAILED(rv)) {
     452           0 :     return rv;
     453             :   }
     454             : 
     455           0 :   rv = WriteLine(outputStream,
     456           0 :                  NS_LITERAL_CSTRING("# Auto generated contents. Do not edit."));
     457           0 :   if (NS_FAILED(rv)) {
     458           0 :     return rv;
     459             :   }
     460             : 
     461             :   // Sort blocklist items into lists of serials for each issuer
     462           0 :   for (auto iter = mBlocklist.Iter(); !iter.Done(); iter.Next()) {
     463           0 :     CertBlocklistItem item = iter.Get()->GetKey();
     464           0 :     if (!item.mIsCurrent) {
     465           0 :       continue;
     466             :     }
     467             : 
     468           0 :     nsAutoCString encDN;
     469           0 :     nsAutoCString encOther;
     470             : 
     471           0 :     nsresult rv = item.ToBase64(encDN, encOther);
     472           0 :     if (NS_FAILED(rv)) {
     473           0 :       MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     474             :              ("CertBlocklist::SaveEntries writing revocation data failed"));
     475           0 :       return NS_ERROR_FAILURE;
     476             :     }
     477             : 
     478             :     // If it's a subject / public key block, write it straight out
     479           0 :     if (item.mItemMechanism == BlockBySubjectAndPubKey) {
     480           0 :       WriteLine(outputStream, encDN);
     481           0 :       WriteLine(outputStream, NS_LITERAL_CSTRING("\t") + encOther);
     482           0 :       continue;
     483             :     }
     484             : 
     485             :     // Otherwise, we have to group entries by issuer
     486           0 :     issuers.PutEntry(encDN);
     487           0 :     BlocklistStringSet* issuerSet = issuerTable.Get(encDN);
     488           0 :     if (!issuerSet) {
     489           0 :       issuerSet = new BlocklistStringSet();
     490           0 :       issuerTable.Put(encDN, issuerSet);
     491             :     }
     492           0 :     issuerSet->PutEntry(encOther);
     493             :   }
     494             : 
     495           0 :   for (auto iter = issuers.Iter(); !iter.Done(); iter.Next()) {
     496           0 :     nsCStringHashKey* hashKey = iter.Get();
     497           0 :     nsAutoPtr<BlocklistStringSet> issuerSet;
     498           0 :     issuerTable.Remove(hashKey->GetKey(), &issuerSet);
     499             : 
     500           0 :     nsresult rv = WriteLine(outputStream, hashKey->GetKey());
     501           0 :     if (NS_FAILED(rv)) {
     502           0 :       break;
     503             :     }
     504             : 
     505             :     // Write serial data to the output stream
     506           0 :     for (auto iter = issuerSet->Iter(); !iter.Done(); iter.Next()) {
     507           0 :       nsresult rv = WriteLine(outputStream,
     508           0 :                               NS_LITERAL_CSTRING(" ") + iter.Get()->GetKey());
     509           0 :       if (NS_FAILED(rv)) {
     510           0 :         MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     511             :                ("CertBlocklist::SaveEntries writing revocation data failed"));
     512           0 :         return NS_ERROR_FAILURE;
     513             :       }
     514             :     }
     515             :   }
     516             : 
     517           0 :   nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outputStream);
     518           0 :   MOZ_ASSERT(safeStream, "expected a safe output stream!");
     519           0 :   if (!safeStream) {
     520           0 :     return NS_ERROR_FAILURE;
     521             :   }
     522           0 :   rv = safeStream->Finish();
     523           0 :   if (NS_FAILED(rv)) {
     524           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     525             :            ("CertBlocklist::SaveEntries saving revocation data failed"));
     526           0 :     return rv;
     527             :   }
     528           0 :   mModified = false;
     529           0 :   return NS_OK;
     530             : }
     531             : 
     532             : NS_IMETHODIMP
     533           0 : CertBlocklist::IsCertRevoked(const uint8_t* aIssuer,
     534             :                              uint32_t aIssuerLength,
     535             :                              const uint8_t* aSerial,
     536             :                              uint32_t aSerialLength,
     537             :                              const uint8_t* aSubject,
     538             :                              uint32_t aSubjectLength,
     539             :                              const uint8_t* aPubKey,
     540             :                              uint32_t aPubKeyLength,
     541             :                              bool* _retval)
     542             : {
     543           0 :   MutexAutoLock lock(mMutex);
     544             : 
     545           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     546             :           ("CertBlocklist::IsCertRevoked?"));
     547           0 :   nsresult rv = EnsureBackingFileInitialized(lock);
     548           0 :   if (NS_FAILED(rv)) {
     549           0 :     return rv;
     550             :   }
     551             : 
     552           0 :   Input issuer;
     553           0 :   Input serial;
     554           0 :   if (issuer.Init(aIssuer, aIssuerLength) != Success) {
     555           0 :     return NS_ERROR_FAILURE;
     556             :   }
     557           0 :   if (serial.Init(aSerial, aSerialLength) != Success) {
     558           0 :     return NS_ERROR_FAILURE;
     559             :   }
     560             : 
     561             :   CertBlocklistItem issuerSerial(aIssuer, aIssuerLength, aSerial, aSerialLength,
     562           0 :                                  BlockByIssuerAndSerial);
     563             : 
     564           0 :   nsAutoCString encDN;
     565           0 :   nsAutoCString encOther;
     566             : 
     567           0 :   issuerSerial.ToBase64(encDN, encOther);
     568           0 :   if (NS_FAILED(rv)) {
     569           0 :     return rv;
     570             :   }
     571             : 
     572           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     573             :           ("CertBlocklist::IsCertRevoked issuer %s - serial %s",
     574             :            encDN.get(), encOther.get()));
     575             : 
     576           0 :   *_retval = mBlocklist.Contains(issuerSerial);
     577             : 
     578           0 :   if (*_retval) {
     579           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     580             :             ("certblocklist::IsCertRevoked found by issuer / serial"));
     581           0 :     return NS_OK;
     582             :   }
     583             : 
     584           0 :   nsCOMPtr<nsICryptoHash> crypto;
     585           0 :   crypto = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
     586             : 
     587           0 :   rv = crypto->Init(nsICryptoHash::SHA256);
     588           0 :   if (NS_FAILED(rv)) {
     589           0 :     return rv;
     590             :   }
     591             : 
     592           0 :   rv = crypto->Update(aPubKey, aPubKeyLength);
     593           0 :   if (NS_FAILED(rv)) {
     594           0 :     return rv;
     595             :   }
     596             : 
     597           0 :   nsCString hashString;
     598           0 :   rv = crypto->Finish(false, hashString);
     599           0 :   if (NS_FAILED(rv)) {
     600           0 :     return rv;
     601             :   }
     602             : 
     603             :   CertBlocklistItem subjectPubKey(
     604             :     aSubject,
     605             :     static_cast<size_t>(aSubjectLength),
     606             :     BitwiseCast<const uint8_t*, const char*>(hashString.get()),
     607           0 :     hashString.Length(),
     608           0 :     BlockBySubjectAndPubKey);
     609             : 
     610           0 :   rv = subjectPubKey.ToBase64(encDN, encOther);
     611           0 :   if (NS_FAILED(rv)) {
     612           0 :     return rv;
     613             :   }
     614             : 
     615           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     616             :           ("CertBlocklist::IsCertRevoked subject %s - pubKey hash %s",
     617             :            encDN.get(), encOther.get()));
     618           0 :   *_retval = mBlocklist.Contains(subjectPubKey);
     619             : 
     620           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     621             :           ("CertBlocklist::IsCertRevoked by subject / pubkey? %s",
     622             :            *_retval ? "true" : "false"));
     623             : 
     624           0 :   return NS_OK;
     625             : }
     626             : 
     627             : NS_IMETHODIMP
     628           0 : CertBlocklist::IsBlocklistFresh(bool* _retval)
     629             : {
     630           0 :   MutexAutoLock lock(mMutex);
     631           0 :   *_retval = false;
     632             : 
     633           0 :   uint32_t now = uint32_t(PR_Now() / PR_USEC_PER_SEC);
     634           0 :   uint32_t lastUpdate = sUseAMO ? sLastBlocklistUpdate : sLastKintoUpdate;
     635           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     636             :           ("CertBlocklist::IsBlocklistFresh using AMO? %i lastUpdate is %i",
     637             :            sUseAMO, lastUpdate));
     638             : 
     639           0 :   if (now > lastUpdate) {
     640           0 :     int64_t interval = now - lastUpdate;
     641           0 :     MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     642             :            ("CertBlocklist::IsBlocklistFresh we're after the last BlocklistUpdate "
     643             :             "interval is %" PRId64 ", staleness %u", interval, sMaxStaleness));
     644           0 :     *_retval = sMaxStaleness > interval;
     645             :   }
     646           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     647             :          ("CertBlocklist::IsBlocklistFresh ? %s", *_retval ? "true" : "false"));
     648           0 :   return NS_OK;
     649             : }
     650             : 
     651             : 
     652             : /* static */
     653             : void
     654           0 : CertBlocklist::PreferenceChanged(const char* aPref, void* aClosure)
     655             : 
     656             : {
     657           0 :   auto blocklist = static_cast<CertBlocklist*>(aClosure);
     658           0 :   MutexAutoLock lock(blocklist->mMutex);
     659             : 
     660           0 :   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
     661             :          ("CertBlocklist::PreferenceChanged %s changed", aPref));
     662           0 :   if (strcmp(aPref, PREF_BACKGROUND_UPDATE_TIMER) == 0) {
     663           0 :     sLastBlocklistUpdate = Preferences::GetUint(PREF_BACKGROUND_UPDATE_TIMER,
     664             :                                                 uint32_t(0));
     665           0 :   } else if (strcmp(aPref, PREF_BLOCKLIST_ONECRL_CHECKED) == 0) {
     666           0 :     sLastKintoUpdate = Preferences::GetUint(PREF_BLOCKLIST_ONECRL_CHECKED,
     667             :                                             uint32_t(0));
     668           0 :   } else if (strcmp(aPref, PREF_MAX_STALENESS_IN_SECONDS) == 0) {
     669           0 :     sMaxStaleness = Preferences::GetUint(PREF_MAX_STALENESS_IN_SECONDS,
     670             :                                          uint32_t(0));
     671           0 :   } else if (strcmp(aPref, PREF_ONECRL_VIA_AMO) == 0) {
     672           0 :     sUseAMO = Preferences::GetBool(PREF_ONECRL_VIA_AMO, true);
     673             :   }
     674           0 : }

Generated by: LCOV version 1.13