123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsCertTree.h"
- #include "ScopedNSSTypes.h"
- #include "mozilla/Logging.h"
- #include "nsArray.h"
- #include "nsArrayUtils.h"
- #include "nsHashKeys.h"
- #include "nsISupportsPrimitives.h"
- #include "nsITreeColumns.h"
- #include "nsIX509CertDB.h"
- #include "nsIX509Cert.h"
- #include "nsIX509CertValidity.h"
- #include "nsNSSCertHelper.h"
- #include "nsNSSCertificate.h"
- #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
- #include "nsNSSHelper.h"
- #include "nsReadableUtils.h"
- #include "nsTHashtable.h"
- #include "nsUnicharUtils.h"
- #include "nsXPCOMCID.h"
- #include "nsXPIDLString.h"
- #include "pkix/pkixtypes.h"
- using namespace mozilla;
- extern LazyLogModule gPIPNSSLog;
- static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID);
- // treeArrayElStr
- //
- // structure used to hold map of tree. Each thread (an organization
- // field from a cert) has an element in the array. The numChildren field
- // stores the number of certs corresponding to that thread.
- struct treeArrayElStr {
- nsString orgName; /* heading for thread */
- bool open; /* toggle open state for thread */
- int32_t certIndex; /* index into cert array for 1st cert */
- int32_t numChildren; /* number of chidren (certs) for thread */
- };
- CompareCacheHashEntryPtr::CompareCacheHashEntryPtr()
- {
- entry = new CompareCacheHashEntry;
- }
- CompareCacheHashEntryPtr::~CompareCacheHashEntryPtr()
- {
- delete entry;
- }
- CompareCacheHashEntry::CompareCacheHashEntry()
- :key(nullptr)
- {
- for (int i = 0; i < max_criterions; ++i) {
- mCritInit[i] = false;
- }
- }
- static bool
- CompareCacheMatchEntry(const PLDHashEntryHdr *hdr, const void *key)
- {
- const CompareCacheHashEntryPtr *entryPtr = static_cast<const CompareCacheHashEntryPtr*>(hdr);
- return entryPtr->entry->key == key;
- }
- static void
- CompareCacheInitEntry(PLDHashEntryHdr *hdr, const void *key)
- {
- new (hdr) CompareCacheHashEntryPtr();
- CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
- entryPtr->entry->key = (void*)key;
- }
- static void
- CompareCacheClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
- {
- CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
- entryPtr->~CompareCacheHashEntryPtr();
- }
- static const PLDHashTableOps gMapOps = {
- PLDHashTable::HashVoidPtrKeyStub,
- CompareCacheMatchEntry,
- PLDHashTable::MoveEntryStub,
- CompareCacheClearEntry,
- CompareCacheInitEntry
- };
- NS_IMPL_ISUPPORTS0(nsCertAddonInfo)
- NS_IMPL_ISUPPORTS(nsCertTreeDispInfo, nsICertTreeItem)
- nsCertTreeDispInfo::nsCertTreeDispInfo()
- :mAddonInfo(nullptr)
- ,mTypeOfEntry(direct_db)
- ,mPort(-1)
- ,mOverrideBits(nsCertOverride::ob_None)
- ,mIsTemporary(true)
- {
- }
- nsCertTreeDispInfo::nsCertTreeDispInfo(nsCertTreeDispInfo &other)
- {
- mAddonInfo = other.mAddonInfo;
- mTypeOfEntry = other.mTypeOfEntry;
- mAsciiHost = other.mAsciiHost;
- mPort = other.mPort;
- mOverrideBits = other.mOverrideBits;
- mIsTemporary = other.mIsTemporary;
- mCert = other.mCert;
- }
- nsCertTreeDispInfo::~nsCertTreeDispInfo()
- {
- }
- NS_IMETHODIMP
- nsCertTreeDispInfo::GetCert(nsIX509Cert **_cert)
- {
- NS_ENSURE_ARG(_cert);
- if (mCert) {
- // we may already have the cert for temporary overrides
- *_cert = mCert;
- NS_IF_ADDREF(*_cert);
- return NS_OK;
- }
- if (mAddonInfo) {
- *_cert = mAddonInfo->mCert.get();
- NS_IF_ADDREF(*_cert);
- }
- else {
- *_cert = nullptr;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTreeDispInfo::GetHostPort(nsAString &aHostPort)
- {
- nsAutoCString hostPort;
- nsCertOverrideService::GetHostWithPort(mAsciiHost, mPort, hostPort);
- aHostPort = NS_ConvertUTF8toUTF16(hostPort);
- return NS_OK;
- }
- NS_IMPL_ISUPPORTS(nsCertTree, nsICertTree, nsITreeView)
- nsCertTree::nsCertTree()
- : mTreeArray(nullptr)
- , mCompareCache(&gMapOps, sizeof(CompareCacheHashEntryPtr),
- kInitialCacheLength)
- {
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
- mNSSComponent = do_GetService(kNSSComponentCID);
- mOverrideService = do_GetService("@mozilla.org/security/certoverride;1");
- // Might be a different service if someone is overriding the contract
- nsCOMPtr<nsICertOverrideService> origCertOverride =
- do_GetService(kCertOverrideCID);
- mOriginalOverrideService =
- static_cast<nsCertOverrideService*>(origCertOverride.get());
- mCellText = nullptr;
- }
- void nsCertTree::ClearCompareHash()
- {
- mCompareCache.ClearAndPrepareForLength(kInitialCacheLength);
- }
- nsCertTree::~nsCertTree()
- {
- delete [] mTreeArray;
- }
- void
- nsCertTree::FreeCertArray()
- {
- mDispInfo.Clear();
- }
- CompareCacheHashEntry*
- nsCertTree::getCacheEntry(void* cache, void* aCert)
- {
- PLDHashTable& aCompareCache = *static_cast<PLDHashTable*>(cache);
- auto entryPtr = static_cast<CompareCacheHashEntryPtr*>
- (aCompareCache.Add(aCert, fallible));
- return entryPtr ? entryPtr->entry : nullptr;
- }
- void nsCertTree::RemoveCacheEntry(void *key)
- {
- mCompareCache.Remove(key);
- }
- // CountOrganizations
- //
- // Count the number of different organizations encountered in the cert
- // list.
- int32_t
- nsCertTree::CountOrganizations()
- {
- uint32_t i, certCount;
- certCount = mDispInfo.Length();
- if (certCount == 0) return 0;
- nsCOMPtr<nsIX509Cert> orgCert = nullptr;
- nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(0)->mAddonInfo;
- if (addonInfo) {
- orgCert = addonInfo->mCert;
- }
- nsCOMPtr<nsIX509Cert> nextCert = nullptr;
- int32_t orgCount = 1;
- for (i=1; i<certCount; i++) {
- nextCert = nullptr;
- addonInfo = mDispInfo.SafeElementAt(i, nullptr)->mAddonInfo;
- if (addonInfo) {
- nextCert = addonInfo->mCert;
- }
- // XXX we assume issuer org is always criterion 1
- if (CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None) != 0) {
- orgCert = nextCert;
- orgCount++;
- }
- }
- return orgCount;
- }
- // GetThreadDescAtIndex
- //
- // If the row at index is an organization thread, return the collection
- // associated with that thread. Otherwise, return null.
- treeArrayEl *
- nsCertTree::GetThreadDescAtIndex(int32_t index)
- {
- int i, idx=0;
- if (index < 0) return nullptr;
- for (i=0; i<mNumOrgs; i++) {
- if (index == idx) {
- return &mTreeArray[i];
- }
- if (mTreeArray[i].open) {
- idx += mTreeArray[i].numChildren;
- }
- idx++;
- if (idx > index) break;
- }
- return nullptr;
- }
- // GetCertAtIndex
- //
- // If the row at index is a cert, return that cert. Otherwise, return null.
- already_AddRefed<nsIX509Cert>
- nsCertTree::GetCertAtIndex(int32_t index, int32_t *outAbsoluteCertOffset)
- {
- RefPtr<nsCertTreeDispInfo> certdi(
- GetDispInfoAtIndex(index, outAbsoluteCertOffset));
- if (!certdi)
- return nullptr;
- nsCOMPtr<nsIX509Cert> ret;
- if (certdi->mCert) {
- ret = certdi->mCert;
- } else if (certdi->mAddonInfo) {
- ret = certdi->mAddonInfo->mCert;
- }
- return ret.forget();
- }
- // If the row at index is a cert, return that cert. Otherwise, return null.
- already_AddRefed<nsCertTreeDispInfo>
- nsCertTree::GetDispInfoAtIndex(int32_t index,
- int32_t *outAbsoluteCertOffset)
- {
- int i, idx = 0, cIndex = 0, nc;
- if (index < 0) return nullptr;
- // Loop over the threads
- for (i=0; i<mNumOrgs; i++) {
- if (index == idx) return nullptr; // index is for thread
- idx++; // get past the thread
- nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
- if (index < idx + nc) { // cert is within range of this thread
- int32_t certIndex = cIndex + index - idx;
- if (outAbsoluteCertOffset)
- *outAbsoluteCertOffset = certIndex;
- RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
- nullptr));
- if (certdi) {
- return certdi.forget();
- }
- break;
- }
- if (mTreeArray[i].open)
- idx += mTreeArray[i].numChildren;
- cIndex += mTreeArray[i].numChildren;
- if (idx > index) break;
- }
- return nullptr;
- }
- nsCertTree::nsCertCompareFunc
- nsCertTree::GetCompareFuncFromCertType(uint32_t aType)
- {
- switch (aType) {
- case nsIX509Cert::ANY_CERT:
- case nsIX509Cert::USER_CERT:
- return CmpUserCert;
- case nsIX509Cert::CA_CERT:
- return CmpCACert;
- case nsIX509Cert::EMAIL_CERT:
- return CmpEmailCert;
- case nsIX509Cert::SERVER_CERT:
- default:
- return CmpWebSiteCert;
- }
- }
- struct nsCertAndArrayAndPositionAndCounterAndTracker
- {
- RefPtr<nsCertAddonInfo> certai;
- nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
- int position;
- int counter;
- nsTHashtable<nsCStringHashKey> *tracker;
- };
- // Used to enumerate host:port overrides that match a stored
- // certificate, creates and adds a display-info-object to the
- // provided array. Increments insert position and entry counter.
- // We remove the given key from the tracker, which is used to
- // track entries that have not yet been handled.
- // The created display-info references the cert, so make a note
- // of that by incrementing the cert usage counter.
- static void
- MatchingCertOverridesCallback(const nsCertOverride &aSettings,
- void *aUserData)
- {
- nsCertAndArrayAndPositionAndCounterAndTracker *cap =
- (nsCertAndArrayAndPositionAndCounterAndTracker*)aUserData;
- if (!cap)
- return;
- nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
- if (certdi) {
- if (cap->certai)
- cap->certai->mUsageCount++;
- certdi->mAddonInfo = cap->certai;
- certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
- certdi->mAsciiHost = aSettings.mAsciiHost;
- certdi->mPort = aSettings.mPort;
- certdi->mOverrideBits = aSettings.mOverrideBits;
- certdi->mIsTemporary = aSettings.mIsTemporary;
- certdi->mCert = aSettings.mCert;
- cap->array->InsertElementAt(cap->position, certdi);
- cap->position++;
- cap->counter++;
- }
- // this entry is now associated to a displayed cert, remove
- // it from the list of remaining entries
- nsAutoCString hostPort;
- nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
- cap->tracker->RemoveEntry(hostPort);
- }
- // Used to collect a list of the (unique) host:port keys
- // for all stored overrides.
- static void
- CollectAllHostPortOverridesCallback(const nsCertOverride &aSettings,
- void *aUserData)
- {
- nsTHashtable<nsCStringHashKey> *collectorTable =
- (nsTHashtable<nsCStringHashKey> *)aUserData;
- if (!collectorTable)
- return;
- nsAutoCString hostPort;
- nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
- collectorTable->PutEntry(hostPort);
- }
- struct nsArrayAndPositionAndCounterAndTracker
- {
- nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
- int position;
- int counter;
- nsTHashtable<nsCStringHashKey> *tracker;
- };
- // Used when enumerating the stored host:port overrides where
- // no associated certificate was found in the NSS database.
- static void
- AddRemaningHostPortOverridesCallback(const nsCertOverride &aSettings,
- void *aUserData)
- {
- nsArrayAndPositionAndCounterAndTracker *cap =
- (nsArrayAndPositionAndCounterAndTracker*)aUserData;
- if (!cap)
- return;
- nsAutoCString hostPort;
- nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
- if (!cap->tracker->GetEntry(hostPort))
- return;
- // This entry is not associated to any stored cert,
- // so we still need to display it.
- nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
- if (certdi) {
- certdi->mAddonInfo = nullptr;
- certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
- certdi->mAsciiHost = aSettings.mAsciiHost;
- certdi->mPort = aSettings.mPort;
- certdi->mOverrideBits = aSettings.mOverrideBits;
- certdi->mIsTemporary = aSettings.mIsTemporary;
- certdi->mCert = aSettings.mCert;
- cap->array->InsertElementAt(cap->position, certdi);
- cap->position++;
- cap->counter++;
- }
- }
- nsresult
- nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList,
- uint32_t aWantedType,
- nsCertCompareFunc aCertCmpFn,
- void *aCertCmpFnArg)
- {
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetCertsByTypeFromCertList"));
- if (!aCertList)
- return NS_ERROR_FAILURE;
- if (!mOriginalOverrideService)
- return NS_ERROR_FAILURE;
- nsTHashtable<nsCStringHashKey> allHostPortOverrideKeys;
- if (aWantedType == nsIX509Cert::SERVER_CERT) {
- mOriginalOverrideService->
- EnumerateCertOverrides(nullptr,
- CollectAllHostPortOverridesCallback,
- &allHostPortOverrideKeys);
- }
- CERTCertListNode *node;
- int count = 0;
- for (node = CERT_LIST_HEAD(aCertList);
- !CERT_LIST_END(node, aCertList);
- node = CERT_LIST_NEXT(node)) {
- bool wantThisCert = (aWantedType == nsIX509Cert::ANY_CERT);
- bool wantThisCertIfNoOverrides = false;
- bool wantThisCertIfHaveOverrides = false;
- bool addOverrides = false;
- if (!wantThisCert) {
- uint32_t thisCertType = getCertType(node->cert);
- // The output from getCertType is a "guess", which can be wrong.
- // The guess is based on stored trust flags, but for the host:port
- // overrides, we are storing certs without any trust flags associated.
- // So we must check whether the cert really belongs to the
- // server, email or unknown tab. We will lookup the cert in the override
- // list to come to the decision. Unfortunately, the lookup in the
- // override list is quite expensive. Therefore we are using this
- // lengthy if/else statement to minimize
- // the number of override-list-lookups.
- if (aWantedType == nsIX509Cert::SERVER_CERT
- && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
- // This unknown cert was stored without trust
- // Are there host:port based overrides stored?
- // If yes, display them.
- addOverrides = true;
- }
- else
- if (aWantedType == nsIX509Cert::UNKNOWN_CERT
- && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
- // This unknown cert was stored without trust.
- // If there are associated overrides, do not show as unknown.
- // If there are no associated overrides, display as unknown.
- wantThisCertIfNoOverrides = true;
- }
- else
- if (aWantedType == nsIX509Cert::SERVER_CERT
- && thisCertType == nsIX509Cert::SERVER_CERT) {
- // This server cert is explicitly marked as a web site peer,
- // with or without trust, but editable, so show it
- wantThisCert = true;
- // Are there host:port based overrides stored?
- // If yes, display them.
- addOverrides = true;
- }
- else
- if (aWantedType == nsIX509Cert::SERVER_CERT
- && thisCertType == nsIX509Cert::EMAIL_CERT) {
- // This cert might have been categorized as an email cert
- // because it carries an email address. But is it really one?
- // Our cert categorization is uncertain when it comes to
- // distinguish between email certs and web site certs.
- // So, let's see if we have an override for that cert
- // and if there is, conclude it's really a web site cert.
- addOverrides = true;
- }
- else
- if (aWantedType == nsIX509Cert::EMAIL_CERT
- && thisCertType == nsIX509Cert::EMAIL_CERT) {
- // This cert might have been categorized as an email cert
- // because it carries an email address. But is it really one?
- // Our cert categorization is uncertain when it comes to
- // distinguish between email certs and web site certs.
- // So, let's see if we have an override for that cert
- // and if there is, conclude it's really a web site cert.
- wantThisCertIfNoOverrides = true;
- }
- else
- if (thisCertType == aWantedType) {
- wantThisCert = true;
- }
- }
- nsCOMPtr<nsIX509Cert> pipCert = nsNSSCertificate::Create(node->cert);
- if (!pipCert)
- return NS_ERROR_OUT_OF_MEMORY;
- if (wantThisCertIfNoOverrides || wantThisCertIfHaveOverrides) {
- uint32_t ocount = 0;
- nsresult rv =
- mOverrideService->IsCertUsedForOverrides(pipCert,
- true, // we want temporaries
- true, // we want permanents
- &ocount);
- if (wantThisCertIfNoOverrides) {
- if (NS_FAILED(rv) || ocount == 0) {
- // no overrides for this cert
- wantThisCert = true;
- }
- }
- if (wantThisCertIfHaveOverrides) {
- if (NS_SUCCEEDED(rv) && ocount > 0) {
- // there are overrides for this cert
- wantThisCert = true;
- }
- }
- }
- RefPtr<nsCertAddonInfo> certai(new nsCertAddonInfo);
- certai->mCert = pipCert;
- certai->mUsageCount = 0;
- if (wantThisCert || addOverrides) {
- int InsertPosition = 0;
- for (; InsertPosition < count; ++InsertPosition) {
- nsCOMPtr<nsIX509Cert> cert = nullptr;
- RefPtr<nsCertTreeDispInfo> elem(
- mDispInfo.SafeElementAt(InsertPosition, nullptr));
- if (elem && elem->mAddonInfo) {
- cert = elem->mAddonInfo->mCert;
- }
- if ((*aCertCmpFn)(aCertCmpFnArg, pipCert, cert) < 0) {
- break;
- }
- }
- if (wantThisCert) {
- nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
- certdi->mAddonInfo = certai;
- certai->mUsageCount++;
- certdi->mTypeOfEntry = nsCertTreeDispInfo::direct_db;
- // not necessary: certdi->mAsciiHost.Clear(); certdi->mPort = -1;
- certdi->mOverrideBits = nsCertOverride::ob_None;
- certdi->mIsTemporary = false;
- mDispInfo.InsertElementAt(InsertPosition, certdi);
- ++count;
- ++InsertPosition;
- }
- if (addOverrides) {
- nsCertAndArrayAndPositionAndCounterAndTracker cap;
- cap.certai = certai;
- cap.array = &mDispInfo;
- cap.position = InsertPosition;
- cap.counter = 0;
- cap.tracker = &allHostPortOverrideKeys;
- mOriginalOverrideService->
- EnumerateCertOverrides(pipCert, MatchingCertOverridesCallback, &cap);
- count += cap.counter;
- }
- }
- }
- if (aWantedType == nsIX509Cert::SERVER_CERT) {
- nsArrayAndPositionAndCounterAndTracker cap;
- cap.array = &mDispInfo;
- cap.position = 0;
- cap.counter = 0;
- cap.tracker = &allHostPortOverrideKeys;
- mOriginalOverrideService->
- EnumerateCertOverrides(nullptr, AddRemaningHostPortOverridesCallback, &cap);
- }
- return NS_OK;
- }
- nsresult
- nsCertTree::GetCertsByType(uint32_t aType,
- nsCertCompareFunc aCertCmpFn,
- void *aCertCmpFnArg)
- {
- nsNSSShutDownPreventionLock locker;
- nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
- UniqueCERTCertList certList(PK11_ListCerts(PK11CertListUnique, cxt));
- return GetCertsByTypeFromCertList(certList.get(), aType, aCertCmpFn,
- aCertCmpFnArg);
- }
- nsresult
- nsCertTree::GetCertsByTypeFromCache(nsIX509CertList *aCache,
- uint32_t aType,
- nsCertCompareFunc aCertCmpFn,
- void *aCertCmpFnArg)
- {
- NS_ENSURE_ARG_POINTER(aCache);
- // GetRawCertList checks for NSS shutdown since we can't do it ourselves here
- // easily. We still have to acquire a shutdown prevention lock to prevent NSS
- // shutting down after GetRawCertList has returned. While cumbersome, this is
- // at least mostly correct. The rest of this implementation doesn't even go
- // this far in attempting to check for or prevent NSS shutdown at the
- // appropriate times. If this were reimplemented at a higher level using
- // more encapsulated types that handled NSS shutdown themselves, we wouldn't
- // be having these kinds of problems.
- nsNSSShutDownPreventionLock locker;
- CERTCertList* certList = aCache->GetRawCertList();
- if (!certList)
- return NS_ERROR_FAILURE;
- return GetCertsByTypeFromCertList(certList, aType, aCertCmpFn, aCertCmpFnArg);
- }
- // LoadCerts
- //
- // Load all of the certificates in the DB for this type. Sort them
- // by token, organization, then common name.
- NS_IMETHODIMP
- nsCertTree::LoadCertsFromCache(nsIX509CertList *aCache, uint32_t aType)
- {
- if (mTreeArray) {
- FreeCertArray();
- delete [] mTreeArray;
- mTreeArray = nullptr;
- mNumRows = 0;
- }
- ClearCompareHash();
- nsresult rv = GetCertsByTypeFromCache(aCache, aType,
- GetCompareFuncFromCertType(aType),
- &mCompareCache);
- if (NS_FAILED(rv)) return rv;
- return UpdateUIContents();
- }
- NS_IMETHODIMP
- nsCertTree::LoadCerts(uint32_t aType)
- {
- if (mTreeArray) {
- FreeCertArray();
- delete [] mTreeArray;
- mTreeArray = nullptr;
- mNumRows = 0;
- }
- ClearCompareHash();
- nsresult rv = GetCertsByType(aType, GetCompareFuncFromCertType(aType),
- &mCompareCache);
- if (NS_FAILED(rv)) return rv;
- return UpdateUIContents();
- }
- nsresult
- nsCertTree::UpdateUIContents()
- {
- uint32_t count = mDispInfo.Length();
- mNumOrgs = CountOrganizations();
- mTreeArray = new treeArrayEl[mNumOrgs];
- mCellText = nsArrayBase::Create();
- if (count) {
- uint32_t j = 0;
- nsCOMPtr<nsIX509Cert> orgCert = nullptr;
- nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(j)->mAddonInfo;
- if (addonInfo) {
- orgCert = addonInfo->mCert;
- }
- for (int32_t i=0; i<mNumOrgs; i++) {
- nsString &orgNameRef = mTreeArray[i].orgName;
- if (!orgCert) {
- mNSSComponent->GetPIPNSSBundleString("CertOrgUnknown", orgNameRef);
- }
- else {
- orgCert->GetIssuerOrganization(orgNameRef);
- if (orgNameRef.IsEmpty())
- orgCert->GetCommonName(orgNameRef);
- }
- mTreeArray[i].open = true;
- mTreeArray[i].certIndex = j;
- mTreeArray[i].numChildren = 1;
- if (++j >= count) break;
- nsCOMPtr<nsIX509Cert> nextCert = nullptr;
- nsCertAddonInfo *addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
- if (addonInfo) {
- nextCert = addonInfo->mCert;
- }
- while (0 == CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None)) {
- mTreeArray[i].numChildren++;
- if (++j >= count) break;
- nextCert = nullptr;
- addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
- if (addonInfo) {
- nextCert = addonInfo->mCert;
- }
- }
- orgCert = nextCert;
- }
- }
- if (mTree) {
- mTree->BeginUpdateBatch();
- mTree->RowCountChanged(0, -mNumRows);
- }
- mNumRows = count + mNumOrgs;
- if (mTree)
- mTree->EndUpdateBatch();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::DeleteEntryObject(uint32_t index)
- {
- if (!mTreeArray) {
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIX509CertDB> certdb =
- do_GetService("@mozilla.org/security/x509certdb;1");
- if (!certdb) {
- return NS_ERROR_FAILURE;
- }
- int i;
- uint32_t idx = 0, cIndex = 0, nc;
- // Loop over the threads
- for (i=0; i<mNumOrgs; i++) {
- if (index == idx)
- return NS_OK; // index is for thread
- idx++; // get past the thread
- nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
- if (index < idx + nc) { // cert is within range of this thread
- int32_t certIndex = cIndex + index - idx;
- bool canRemoveEntry = false;
- RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
- nullptr));
-
- // We will remove the element from the visual tree.
- // Only if we have a certdi, then we can check for additional actions.
- nsCOMPtr<nsIX509Cert> cert = nullptr;
- if (certdi) {
- if (certdi->mAddonInfo) {
- cert = certdi->mAddonInfo->mCert;
- }
- nsCertAddonInfo* addonInfo =
- certdi->mAddonInfo ? certdi->mAddonInfo.get() : nullptr;
- if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
- mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort);
- if (addonInfo) {
- addonInfo->mUsageCount--;
- if (addonInfo->mUsageCount == 0) {
- // The certificate stored in the database is no longer
- // referenced by any other object displayed.
- // That means we no longer need to keep it around
- // and really can remove it.
- canRemoveEntry = true;
- }
- }
- }
- else {
- if (addonInfo && addonInfo->mUsageCount > 1) {
- // user is trying to delete a perm trusted cert,
- // although there are still overrides stored,
- // so, we keep the cert, but remove the trust
- UniqueCERTCertificate nsscert(cert->GetCert());
- if (nsscert) {
- CERTCertTrust trust;
- memset((void*)&trust, 0, sizeof(trust));
- SECStatus srv = CERT_DecodeTrustString(&trust, ""); // no override
- if (srv == SECSuccess) {
- CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert.get(),
- &trust);
- }
- }
- }
- else {
- canRemoveEntry = true;
- }
- }
- }
- mDispInfo.RemoveElementAt(certIndex);
- if (canRemoveEntry) {
- RemoveCacheEntry(cert);
- certdb->DeleteCertificate(cert);
- }
- delete [] mTreeArray;
- mTreeArray = nullptr;
- return UpdateUIContents();
- }
- if (mTreeArray[i].open)
- idx += mTreeArray[i].numChildren;
- cIndex += mTreeArray[i].numChildren;
- if (idx > index)
- break;
- }
- return NS_ERROR_FAILURE;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Begin nsITreeView methods
- //
- /////////////////////////////////////////////////////////////////////////////
- NS_IMETHODIMP
- nsCertTree::GetCert(uint32_t aIndex, nsIX509Cert **_cert)
- {
- NS_ENSURE_ARG(_cert);
- *_cert = GetCertAtIndex(aIndex).take();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetTreeItem(uint32_t aIndex, nsICertTreeItem **_treeitem)
- {
- NS_ENSURE_ARG(_treeitem);
- RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex));
- if (!certdi)
- return NS_ERROR_FAILURE;
- *_treeitem = certdi;
- NS_IF_ADDREF(*_treeitem);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetRowCount(int32_t *aRowCount)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- uint32_t count = 0;
- for (int32_t i=0; i<mNumOrgs; i++) {
- if (mTreeArray[i].open) {
- count += mTreeArray[i].numChildren;
- }
- count++;
- }
- *aRowCount = count;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetSelection(nsITreeSelection * *aSelection)
- {
- *aSelection = mSelection;
- NS_IF_ADDREF(*aSelection);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::SetSelection(nsITreeSelection * aSelection)
- {
- mSelection = aSelection;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetRowProperties(int32_t index, nsAString& aProps)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetCellProperties(int32_t row, nsITreeColumn* col,
- nsAString& aProps)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsContainer(int32_t index, bool *_retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- treeArrayEl *el = GetThreadDescAtIndex(index);
- if (el) {
- *_retval = true;
- } else {
- *_retval = false;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsContainerOpen(int32_t index, bool *_retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- treeArrayEl *el = GetThreadDescAtIndex(index);
- if (el && el->open) {
- *_retval = true;
- } else {
- *_retval = false;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsContainerEmpty(int32_t index, bool *_retval)
- {
- *_retval = !mTreeArray;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsSeparator(int32_t index, bool *_retval)
- {
- *_retval = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetParentIndex(int32_t rowIndex, int32_t *_retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- int i, idx = 0;
- for (i = 0; i < mNumOrgs && idx < rowIndex; i++, idx++) {
- if (mTreeArray[i].open) {
- if (rowIndex <= idx + mTreeArray[i].numChildren) {
- *_retval = idx;
- return NS_OK;
- }
- idx += mTreeArray[i].numChildren;
- }
- }
- *_retval = -1;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::HasNextSibling(int32_t rowIndex, int32_t afterIndex,
- bool *_retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- int i, idx = 0;
- for (i = 0; i < mNumOrgs && idx <= rowIndex; i++, idx++) {
- if (mTreeArray[i].open) {
- idx += mTreeArray[i].numChildren;
- if (afterIndex <= idx) {
- *_retval = afterIndex < idx;
- return NS_OK;
- }
- }
- }
- *_retval = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetLevel(int32_t index, int32_t *_retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- treeArrayEl *el = GetThreadDescAtIndex(index);
- if (el) {
- *_retval = 0;
- } else {
- *_retval = 1;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetImageSrc(int32_t row, nsITreeColumn* col,
- nsAString& _retval)
- {
- _retval.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetCellValue(int32_t row, nsITreeColumn* col,
- nsAString& _retval)
- {
- _retval.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::GetCellText(int32_t row, nsITreeColumn* col,
- nsAString& _retval)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- nsresult rv = NS_OK;
- _retval.Truncate();
- const char16_t* colID;
- col->GetIdConst(&colID);
- treeArrayEl *el = GetThreadDescAtIndex(row);
- if (el) {
- if (NS_LITERAL_STRING("certcol").Equals(colID))
- _retval.Assign(el->orgName);
- else
- _retval.Truncate();
- return NS_OK;
- }
- int32_t absoluteCertOffset;
- RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(row, &absoluteCertOffset));
- if (!certdi)
- return NS_ERROR_FAILURE;
- nsCOMPtr<nsIX509Cert> cert = certdi->mCert;
- if (!cert && certdi->mAddonInfo) {
- cert = certdi->mAddonInfo->mCert;
- }
- int32_t colIndex;
- col->GetIndex(&colIndex);
- uint32_t arrayIndex=absoluteCertOffset+colIndex*(mNumRows-mNumOrgs);
- uint32_t arrayLength=0;
- if (mCellText) {
- mCellText->GetLength(&arrayLength);
- }
- if (arrayIndex < arrayLength) {
- nsCOMPtr<nsISupportsString> myString(do_QueryElementAt(mCellText, arrayIndex));
- if (myString) {
- myString->GetData(_retval);
- return NS_OK;
- }
- }
- if (NS_LITERAL_STRING("certcol").Equals(colID)) {
- if (!cert) {
- mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval);
- }
- else {
- rv = cert->GetCommonName(_retval);
- if (NS_FAILED(rv) || _retval.IsEmpty()) {
- // kaie: I didn't invent the idea to cut off anything before
- // the first colon. :-)
- nsAutoString nick;
- rv = cert->GetNickname(nick);
-
- nsAString::const_iterator start, end, end2;
- nick.BeginReading(start);
- nick.EndReading(end);
- end2 = end;
-
- if (FindInReadable(NS_LITERAL_STRING(":"), start, end)) {
- // found. end points to the first char after the colon,
- // that's what we want.
- _retval = Substring(end, end2);
- }
- else {
- _retval = nick;
- }
- }
- }
- } else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) {
- rv = cert->GetTokenName(_retval);
- } else if (NS_LITERAL_STRING("emailcol").Equals(colID) && cert) {
- rv = cert->GetEmailAddress(_retval);
- } else if (NS_LITERAL_STRING("issuedcol").Equals(colID) && cert) {
- nsCOMPtr<nsIX509CertValidity> validity;
- rv = cert->GetValidity(getter_AddRefs(validity));
- if (NS_SUCCEEDED(rv)) {
- validity->GetNotBeforeLocalDay(_retval);
- }
- } else if (NS_LITERAL_STRING("expiredcol").Equals(colID) && cert) {
- nsCOMPtr<nsIX509CertValidity> validity;
- rv = cert->GetValidity(getter_AddRefs(validity));
- if (NS_SUCCEEDED(rv)) {
- validity->GetNotAfterLocalDay(_retval);
- }
- } else if (NS_LITERAL_STRING("serialnumcol").Equals(colID) && cert) {
- rv = cert->GetSerialNumber(_retval);
- } else if (NS_LITERAL_STRING("sitecol").Equals(colID)) {
- if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
- nsAutoCString hostPort;
- nsCertOverrideService::GetHostWithPort(certdi->mAsciiHost, certdi->mPort, hostPort);
- _retval = NS_ConvertUTF8toUTF16(hostPort);
- }
- else {
- _retval = NS_LITERAL_STRING("*");
- }
- } else if (NS_LITERAL_STRING("lifetimecol").Equals(colID)) {
- const char *stringID =
- (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
- rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
- } else {
- return NS_ERROR_FAILURE;
- }
- if (mCellText) {
- nsCOMPtr<nsISupportsString> text(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
- text->SetData(_retval);
- mCellText->ReplaceElementAt(text, arrayIndex, false);
- }
- return rv;
- }
- NS_IMETHODIMP
- nsCertTree::SetTree(nsITreeBoxObject *tree)
- {
- mTree = tree;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::ToggleOpenState(int32_t index)
- {
- if (!mTreeArray)
- return NS_ERROR_NOT_INITIALIZED;
- treeArrayEl *el = GetThreadDescAtIndex(index);
- if (el) {
- el->open = !el->open;
- int32_t newChildren = (el->open) ? el->numChildren : -el->numChildren;
- if (mTree) mTree->RowCountChanged(index + 1, newChildren);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::CycleHeader(nsITreeColumn* col)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::SelectionChanged()
- {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_IMETHODIMP
- nsCertTree::CycleCell(int32_t row, nsITreeColumn* col)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval)
- {
- *_retval = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval)
- {
- *_retval = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::SetCellValue(int32_t row, nsITreeColumn* col,
- const nsAString& value)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::SetCellText(int32_t row, nsITreeColumn* col,
- const nsAString& value)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::PerformAction(const char16_t *action)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::PerformActionOnRow(const char16_t *action, int32_t row)
- {
- return NS_OK;
- }
- NS_IMETHODIMP
- nsCertTree::PerformActionOnCell(const char16_t *action, int32_t row,
- nsITreeColumn* col)
- {
- return NS_OK;
- }
- #ifdef DEBUG_CERT_TREE
- void
- nsCertTree::dumpMap()
- {
- for (int i=0; i<mNumOrgs; i++) {
- nsAutoString org(mTreeArray[i].orgName);
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ORG[%s]", NS_LossyConvertUTF16toASCII(org).get()));
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("OPEN[%d]", mTreeArray[i].open));
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("INDEX[%d]", mTreeArray[i].certIndex));
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NCHILD[%d]", mTreeArray[i].numChildren));
- }
- for (int i=0; i<mNumRows; i++) {
- treeArrayEl *el = GetThreadDescAtIndex(i);
- if (el) {
- nsAutoString td(el->orgName);
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("thread desc[%d]: %s", i, NS_LossyConvertUTF16toASCII(td).get()));
- }
- nsCOMPtr<nsIX509Cert> ct = GetCertAtIndex(i);
- if (ct) {
- char16_t *goo;
- ct->GetCommonName(&goo);
- nsAutoString doo(goo);
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("cert [%d]: %s", i, NS_LossyConvertUTF16toASCII(doo).get()));
- }
- }
- }
- #endif
- //
- // CanDrop
- //
- NS_IMETHODIMP nsCertTree::CanDrop(int32_t index, int32_t orientation,
- nsIDOMDataTransfer* aDataTransfer, bool *_retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- *_retval = false;
-
- return NS_OK;
- }
- //
- // Drop
- //
- NS_IMETHODIMP nsCertTree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer)
- {
- return NS_OK;
- }
- //
- // IsSorted
- //
- // ...
- //
- NS_IMETHODIMP nsCertTree::IsSorted(bool *_retval)
- {
- *_retval = false;
- return NS_OK;
- }
- #define RETURN_NOTHING
- void
- nsCertTree::CmpInitCriterion(nsIX509Cert *cert, CompareCacheHashEntry *entry,
- sortCriterion crit, int32_t level)
- {
- NS_ENSURE_TRUE(cert && entry, RETURN_NOTHING);
- entry->mCritInit[level] = true;
- nsXPIDLString &str = entry->mCrit[level];
-
- switch (crit) {
- case sort_IssuerOrg:
- cert->GetIssuerOrganization(str);
- if (str.IsEmpty())
- cert->GetCommonName(str);
- break;
- case sort_Org:
- cert->GetOrganization(str);
- break;
- case sort_Token:
- cert->GetTokenName(str);
- break;
- case sort_CommonName:
- cert->GetCommonName(str);
- break;
- case sort_IssuedDateDescending:
- {
- nsresult rv;
- nsCOMPtr<nsIX509CertValidity> validity;
- PRTime notBefore;
- rv = cert->GetValidity(getter_AddRefs(validity));
- if (NS_SUCCEEDED(rv)) {
- rv = validity->GetNotBefore(¬Before);
- }
- if (NS_SUCCEEDED(rv)) {
- PRExplodedTime explodedTime;
- PR_ExplodeTime(notBefore, PR_GMTParameters, &explodedTime);
- char datebuf[20]; // 4 + 2 + 2 + 2 + 2 + 2 + 1 = 15
- if (0 != PR_FormatTime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", &explodedTime)) {
- str = NS_ConvertASCIItoUTF16(nsDependentCString(datebuf));
- }
- }
- }
- break;
- case sort_Email:
- cert->GetEmailAddress(str);
- break;
- case sort_None:
- default:
- break;
- }
- }
- int32_t
- nsCertTree::CmpByCrit(nsIX509Cert *a, CompareCacheHashEntry *ace,
- nsIX509Cert *b, CompareCacheHashEntry *bce,
- sortCriterion crit, int32_t level)
- {
- NS_ENSURE_TRUE(a && ace && b && bce, 0);
- if (!ace->mCritInit[level]) {
- CmpInitCriterion(a, ace, crit, level);
- }
- if (!bce->mCritInit[level]) {
- CmpInitCriterion(b, bce, crit, level);
- }
- nsXPIDLString &str_a = ace->mCrit[level];
- nsXPIDLString &str_b = bce->mCrit[level];
- int32_t result;
- if (str_a && str_b)
- result = Compare(str_a, str_b, nsCaseInsensitiveStringComparator());
- else
- result = !str_a ? (!str_b ? 0 : -1) : 1;
- if (sort_IssuedDateDescending == crit)
- result *= -1; // reverse compare order
- return result;
- }
- int32_t
- nsCertTree::CmpBy(void *cache, nsIX509Cert *a, nsIX509Cert *b,
- sortCriterion c0, sortCriterion c1, sortCriterion c2)
- {
- // This will be called when comparing items for display sorting.
- // Some items might have no cert associated, so either a or b is null.
- // We want all those orphans show at the top of the list,
- // so we treat a null cert as "smaller" by returning -1.
- // We don't try to sort within the group of no-cert entries,
- // so we treat them as equal wrt sort order.
- if (!a && !b)
- return 0;
- if (!a)
- return -1;
- if (!b)
- return 1;
- NS_ENSURE_TRUE(cache && a && b, 0);
- CompareCacheHashEntry *ace = getCacheEntry(cache, a);
- CompareCacheHashEntry *bce = getCacheEntry(cache, b);
- int32_t cmp;
- cmp = CmpByCrit(a, ace, b, bce, c0, 0);
- if (cmp != 0)
- return cmp;
- if (c1 != sort_None) {
- cmp = CmpByCrit(a, ace, b, bce, c1, 1);
- if (cmp != 0)
- return cmp;
-
- if (c2 != sort_None) {
- return CmpByCrit(a, ace, b, bce, c2, 2);
- }
- }
- return cmp;
- }
- int32_t
- nsCertTree::CmpCACert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
- {
- // XXX we assume issuer org is always criterion 1
- return CmpBy(cache, a, b, sort_IssuerOrg, sort_Org, sort_Token);
- }
- int32_t
- nsCertTree::CmpWebSiteCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
- {
- // XXX we assume issuer org is always criterion 1
- return CmpBy(cache, a, b, sort_IssuerOrg, sort_CommonName, sort_None);
- }
- int32_t
- nsCertTree::CmpUserCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
- {
- // XXX we assume issuer org is always criterion 1
- return CmpBy(cache, a, b, sort_IssuerOrg, sort_Token, sort_IssuedDateDescending);
- }
- int32_t
- nsCertTree::CmpEmailCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
- {
- // XXX we assume issuer org is always criterion 1
- return CmpBy(cache, a, b, sort_IssuerOrg, sort_Email, sort_CommonName);
- }
|