1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/src/nsCertTree.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1592 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsCertTree.h" 1.9 + 1.10 +#include "pkix/pkixtypes.h" 1.11 +#include "nsNSSComponent.h" // for PIPNSS string bundle calls. 1.12 +#include "nsITreeColumns.h" 1.13 +#include "nsIX509Cert.h" 1.14 +#include "nsIX509CertValidity.h" 1.15 +#include "nsIX509CertDB.h" 1.16 +#include "nsXPIDLString.h" 1.17 +#include "nsReadableUtils.h" 1.18 +#include "nsUnicharUtils.h" 1.19 +#include "nsNSSCertificate.h" 1.20 +#include "nsNSSCertHelper.h" 1.21 +#include "nsINSSCertCache.h" 1.22 +#include "nsIMutableArray.h" 1.23 +#include "nsArrayUtils.h" 1.24 +#include "nsISupportsPrimitives.h" 1.25 +#include "nsXPCOMCID.h" 1.26 +#include "nsTHashtable.h" 1.27 +#include "nsHashKeys.h" 1.28 + 1.29 +#include "prlog.h" 1.30 + 1.31 +using namespace mozilla; 1.32 + 1.33 +#ifdef PR_LOGGING 1.34 +extern PRLogModuleInfo* gPIPNSSLog; 1.35 +#endif 1.36 + 1.37 +static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID); 1.38 + 1.39 +// treeArrayElStr 1.40 +// 1.41 +// structure used to hold map of tree. Each thread (an organization 1.42 +// field from a cert) has an element in the array. The numChildren field 1.43 +// stores the number of certs corresponding to that thread. 1.44 +struct treeArrayElStr { 1.45 + nsString orgName; /* heading for thread */ 1.46 + bool open; /* toggle open state for thread */ 1.47 + int32_t certIndex; /* index into cert array for 1st cert */ 1.48 + int32_t numChildren; /* number of chidren (certs) for thread */ 1.49 +}; 1.50 + 1.51 +CompareCacheHashEntryPtr::CompareCacheHashEntryPtr() 1.52 +{ 1.53 + entry = new CompareCacheHashEntry; 1.54 +} 1.55 + 1.56 +CompareCacheHashEntryPtr::~CompareCacheHashEntryPtr() 1.57 +{ 1.58 + delete entry; 1.59 +} 1.60 + 1.61 +CompareCacheHashEntry::CompareCacheHashEntry() 1.62 +:key(nullptr) 1.63 +{ 1.64 + for (int i = 0; i < max_criterions; ++i) { 1.65 + mCritInit[i] = false; 1.66 + } 1.67 +} 1.68 + 1.69 +static bool 1.70 +CompareCacheMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr, 1.71 + const void *key) 1.72 +{ 1.73 + const CompareCacheHashEntryPtr *entryPtr = static_cast<const CompareCacheHashEntryPtr*>(hdr); 1.74 + return entryPtr->entry->key == key; 1.75 +} 1.76 + 1.77 +static bool 1.78 +CompareCacheInitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.79 + const void *key) 1.80 +{ 1.81 + new (hdr) CompareCacheHashEntryPtr(); 1.82 + CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr); 1.83 + if (!entryPtr->entry) { 1.84 + return false; 1.85 + } 1.86 + entryPtr->entry->key = (void*)key; 1.87 + return true; 1.88 +} 1.89 + 1.90 +static void 1.91 +CompareCacheClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr) 1.92 +{ 1.93 + CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr); 1.94 + entryPtr->~CompareCacheHashEntryPtr(); 1.95 +} 1.96 + 1.97 +static const PLDHashTableOps gMapOps = { 1.98 + PL_DHashAllocTable, 1.99 + PL_DHashFreeTable, 1.100 + PL_DHashVoidPtrKeyStub, 1.101 + CompareCacheMatchEntry, 1.102 + PL_DHashMoveEntryStub, 1.103 + CompareCacheClearEntry, 1.104 + PL_DHashFinalizeStub, 1.105 + CompareCacheInitEntry 1.106 +}; 1.107 + 1.108 +NS_IMPL_ISUPPORTS0(nsCertAddonInfo) 1.109 +NS_IMPL_ISUPPORTS(nsCertTreeDispInfo, nsICertTreeItem) 1.110 + 1.111 +nsCertTreeDispInfo::nsCertTreeDispInfo() 1.112 +:mAddonInfo(nullptr) 1.113 +,mTypeOfEntry(direct_db) 1.114 +,mPort(-1) 1.115 +,mOverrideBits(nsCertOverride::ob_None) 1.116 +,mIsTemporary(true) 1.117 +{ 1.118 +} 1.119 + 1.120 +nsCertTreeDispInfo::nsCertTreeDispInfo(nsCertTreeDispInfo &other) 1.121 +{ 1.122 + mAddonInfo = other.mAddonInfo; 1.123 + mTypeOfEntry = other.mTypeOfEntry; 1.124 + mAsciiHost = other.mAsciiHost; 1.125 + mPort = other.mPort; 1.126 + mOverrideBits = other.mOverrideBits; 1.127 + mIsTemporary = other.mIsTemporary; 1.128 + mCert = other.mCert; 1.129 +} 1.130 + 1.131 +nsCertTreeDispInfo::~nsCertTreeDispInfo() 1.132 +{ 1.133 +} 1.134 + 1.135 +NS_IMETHODIMP 1.136 +nsCertTreeDispInfo::GetCert(nsIX509Cert **_cert) 1.137 +{ 1.138 + NS_ENSURE_ARG(_cert); 1.139 + if (mCert) { 1.140 + // we may already have the cert for temporary overrides 1.141 + *_cert = mCert; 1.142 + NS_IF_ADDREF(*_cert); 1.143 + return NS_OK; 1.144 + } 1.145 + if (mAddonInfo) { 1.146 + *_cert = mAddonInfo->mCert.get(); 1.147 + NS_IF_ADDREF(*_cert); 1.148 + } 1.149 + else { 1.150 + *_cert = nullptr; 1.151 + } 1.152 + return NS_OK; 1.153 +} 1.154 + 1.155 +NS_IMETHODIMP 1.156 +nsCertTreeDispInfo::GetHostPort(nsAString &aHostPort) 1.157 +{ 1.158 + nsAutoCString hostPort; 1.159 + nsCertOverrideService::GetHostWithPort(mAsciiHost, mPort, hostPort); 1.160 + aHostPort = NS_ConvertUTF8toUTF16(hostPort); 1.161 + return NS_OK; 1.162 +} 1.163 + 1.164 +NS_IMPL_ISUPPORTS(nsCertTree, nsICertTree, nsITreeView) 1.165 + 1.166 +nsCertTree::nsCertTree() : mTreeArray(nullptr) 1.167 +{ 1.168 + static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); 1.169 + 1.170 + mCompareCache.ops = nullptr; 1.171 + mNSSComponent = do_GetService(kNSSComponentCID); 1.172 + mOverrideService = do_GetService("@mozilla.org/security/certoverride;1"); 1.173 + // Might be a different service if someone is overriding the contract 1.174 + nsCOMPtr<nsICertOverrideService> origCertOverride = 1.175 + do_GetService(kCertOverrideCID); 1.176 + mOriginalOverrideService = 1.177 + static_cast<nsCertOverrideService*>(origCertOverride.get()); 1.178 + mCellText = nullptr; 1.179 +} 1.180 + 1.181 +void nsCertTree::ClearCompareHash() 1.182 +{ 1.183 + if (mCompareCache.ops) { 1.184 + PL_DHashTableFinish(&mCompareCache); 1.185 + mCompareCache.ops = nullptr; 1.186 + } 1.187 +} 1.188 + 1.189 +nsresult nsCertTree::InitCompareHash() 1.190 +{ 1.191 + ClearCompareHash(); 1.192 + if (!PL_DHashTableInit(&mCompareCache, &gMapOps, nullptr, 1.193 + sizeof(CompareCacheHashEntryPtr), 128, fallible_t())) { 1.194 + mCompareCache.ops = nullptr; 1.195 + return NS_ERROR_OUT_OF_MEMORY; 1.196 + } 1.197 + return NS_OK; 1.198 +} 1.199 + 1.200 +nsCertTree::~nsCertTree() 1.201 +{ 1.202 + ClearCompareHash(); 1.203 + delete [] mTreeArray; 1.204 +} 1.205 + 1.206 +void 1.207 +nsCertTree::FreeCertArray() 1.208 +{ 1.209 + mDispInfo.Clear(); 1.210 +} 1.211 + 1.212 +CompareCacheHashEntry * 1.213 +nsCertTree::getCacheEntry(void *cache, void *aCert) 1.214 +{ 1.215 + PLDHashTable &aCompareCache = *reinterpret_cast<PLDHashTable*>(cache); 1.216 + CompareCacheHashEntryPtr *entryPtr = 1.217 + static_cast<CompareCacheHashEntryPtr*> 1.218 + (PL_DHashTableOperate(&aCompareCache, aCert, PL_DHASH_ADD)); 1.219 + return entryPtr ? entryPtr->entry : nullptr; 1.220 +} 1.221 + 1.222 +void nsCertTree::RemoveCacheEntry(void *key) 1.223 +{ 1.224 + PL_DHashTableOperate(&mCompareCache, key, PL_DHASH_REMOVE); 1.225 +} 1.226 + 1.227 +// CountOrganizations 1.228 +// 1.229 +// Count the number of different organizations encountered in the cert 1.230 +// list. 1.231 +int32_t 1.232 +nsCertTree::CountOrganizations() 1.233 +{ 1.234 + uint32_t i, certCount; 1.235 + certCount = mDispInfo.Length(); 1.236 + if (certCount == 0) return 0; 1.237 + nsCOMPtr<nsIX509Cert> orgCert = nullptr; 1.238 + nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(0)->mAddonInfo; 1.239 + if (addonInfo) { 1.240 + orgCert = addonInfo->mCert; 1.241 + } 1.242 + nsCOMPtr<nsIX509Cert> nextCert = nullptr; 1.243 + int32_t orgCount = 1; 1.244 + for (i=1; i<certCount; i++) { 1.245 + nextCert = nullptr; 1.246 + addonInfo = mDispInfo.SafeElementAt(i, nullptr)->mAddonInfo; 1.247 + if (addonInfo) { 1.248 + nextCert = addonInfo->mCert; 1.249 + } 1.250 + // XXX we assume issuer org is always criterion 1 1.251 + if (CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None) != 0) { 1.252 + orgCert = nextCert; 1.253 + orgCount++; 1.254 + } 1.255 + } 1.256 + return orgCount; 1.257 +} 1.258 + 1.259 +// GetThreadDescAtIndex 1.260 +// 1.261 +// If the row at index is an organization thread, return the collection 1.262 +// associated with that thread. Otherwise, return null. 1.263 +treeArrayEl * 1.264 +nsCertTree::GetThreadDescAtIndex(int32_t index) 1.265 +{ 1.266 + int i, idx=0; 1.267 + if (index < 0) return nullptr; 1.268 + for (i=0; i<mNumOrgs; i++) { 1.269 + if (index == idx) { 1.270 + return &mTreeArray[i]; 1.271 + } 1.272 + if (mTreeArray[i].open) { 1.273 + idx += mTreeArray[i].numChildren; 1.274 + } 1.275 + idx++; 1.276 + if (idx > index) break; 1.277 + } 1.278 + return nullptr; 1.279 +} 1.280 + 1.281 +// GetCertAtIndex 1.282 +// 1.283 +// If the row at index is a cert, return that cert. Otherwise, return null. 1.284 +already_AddRefed<nsIX509Cert> 1.285 +nsCertTree::GetCertAtIndex(int32_t index, int32_t *outAbsoluteCertOffset) 1.286 +{ 1.287 + RefPtr<nsCertTreeDispInfo> certdi( 1.288 + GetDispInfoAtIndex(index, outAbsoluteCertOffset)); 1.289 + if (!certdi) 1.290 + return nullptr; 1.291 + 1.292 + nsCOMPtr<nsIX509Cert> ret; 1.293 + if (certdi->mCert) { 1.294 + ret = certdi->mCert; 1.295 + } else if (certdi->mAddonInfo) { 1.296 + ret = certdi->mAddonInfo->mCert; 1.297 + } 1.298 + return ret.forget(); 1.299 +} 1.300 + 1.301 +// If the row at index is a cert, return that cert. Otherwise, return null. 1.302 +TemporaryRef<nsCertTreeDispInfo> 1.303 +nsCertTree::GetDispInfoAtIndex(int32_t index, 1.304 + int32_t *outAbsoluteCertOffset) 1.305 +{ 1.306 + int i, idx = 0, cIndex = 0, nc; 1.307 + if (index < 0) return nullptr; 1.308 + // Loop over the threads 1.309 + for (i=0; i<mNumOrgs; i++) { 1.310 + if (index == idx) return nullptr; // index is for thread 1.311 + idx++; // get past the thread 1.312 + nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0; 1.313 + if (index < idx + nc) { // cert is within range of this thread 1.314 + int32_t certIndex = cIndex + index - idx; 1.315 + if (outAbsoluteCertOffset) 1.316 + *outAbsoluteCertOffset = certIndex; 1.317 + RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex, 1.318 + nullptr)); 1.319 + if (certdi) { 1.320 + return certdi.forget(); 1.321 + } 1.322 + break; 1.323 + } 1.324 + if (mTreeArray[i].open) 1.325 + idx += mTreeArray[i].numChildren; 1.326 + cIndex += mTreeArray[i].numChildren; 1.327 + if (idx > index) break; 1.328 + } 1.329 + return nullptr; 1.330 +} 1.331 + 1.332 +nsCertTree::nsCertCompareFunc 1.333 +nsCertTree::GetCompareFuncFromCertType(uint32_t aType) 1.334 +{ 1.335 + switch (aType) { 1.336 + case nsIX509Cert2::ANY_CERT: 1.337 + case nsIX509Cert::USER_CERT: 1.338 + return CmpUserCert; 1.339 + case nsIX509Cert::CA_CERT: 1.340 + return CmpCACert; 1.341 + case nsIX509Cert::EMAIL_CERT: 1.342 + return CmpEmailCert; 1.343 + case nsIX509Cert::SERVER_CERT: 1.344 + default: 1.345 + return CmpWebSiteCert; 1.346 + } 1.347 +} 1.348 + 1.349 +struct nsCertAndArrayAndPositionAndCounterAndTracker 1.350 +{ 1.351 + RefPtr<nsCertAddonInfo> certai; 1.352 + nsTArray< RefPtr<nsCertTreeDispInfo> > *array; 1.353 + int position; 1.354 + int counter; 1.355 + nsTHashtable<nsCStringHashKey> *tracker; 1.356 +}; 1.357 + 1.358 +// Used to enumerate host:port overrides that match a stored 1.359 +// certificate, creates and adds a display-info-object to the 1.360 +// provided array. Increments insert position and entry counter. 1.361 +// We remove the given key from the tracker, which is used to 1.362 +// track entries that have not yet been handled. 1.363 +// The created display-info references the cert, so make a note 1.364 +// of that by incrementing the cert usage counter. 1.365 +static void 1.366 +MatchingCertOverridesCallback(const nsCertOverride &aSettings, 1.367 + void *aUserData) 1.368 +{ 1.369 + nsCertAndArrayAndPositionAndCounterAndTracker *cap = 1.370 + (nsCertAndArrayAndPositionAndCounterAndTracker*)aUserData; 1.371 + if (!cap) 1.372 + return; 1.373 + 1.374 + nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo; 1.375 + if (certdi) { 1.376 + if (cap->certai) 1.377 + cap->certai->mUsageCount++; 1.378 + certdi->mAddonInfo = cap->certai; 1.379 + certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override; 1.380 + certdi->mAsciiHost = aSettings.mAsciiHost; 1.381 + certdi->mPort = aSettings.mPort; 1.382 + certdi->mOverrideBits = aSettings.mOverrideBits; 1.383 + certdi->mIsTemporary = aSettings.mIsTemporary; 1.384 + certdi->mCert = aSettings.mCert; 1.385 + cap->array->InsertElementAt(cap->position, certdi); 1.386 + cap->position++; 1.387 + cap->counter++; 1.388 + } 1.389 + 1.390 + // this entry is now associated to a displayed cert, remove 1.391 + // it from the list of remaining entries 1.392 + nsAutoCString hostPort; 1.393 + nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort); 1.394 + cap->tracker->RemoveEntry(hostPort); 1.395 +} 1.396 + 1.397 +// Used to collect a list of the (unique) host:port keys 1.398 +// for all stored overrides. 1.399 +static void 1.400 +CollectAllHostPortOverridesCallback(const nsCertOverride &aSettings, 1.401 + void *aUserData) 1.402 +{ 1.403 + nsTHashtable<nsCStringHashKey> *collectorTable = 1.404 + (nsTHashtable<nsCStringHashKey> *)aUserData; 1.405 + if (!collectorTable) 1.406 + return; 1.407 + 1.408 + nsAutoCString hostPort; 1.409 + nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort); 1.410 + collectorTable->PutEntry(hostPort); 1.411 +} 1.412 + 1.413 +struct nsArrayAndPositionAndCounterAndTracker 1.414 +{ 1.415 + nsTArray< RefPtr<nsCertTreeDispInfo> > *array; 1.416 + int position; 1.417 + int counter; 1.418 + nsTHashtable<nsCStringHashKey> *tracker; 1.419 +}; 1.420 + 1.421 +// Used when enumerating the stored host:port overrides where 1.422 +// no associated certificate was found in the NSS database. 1.423 +static void 1.424 +AddRemaningHostPortOverridesCallback(const nsCertOverride &aSettings, 1.425 + void *aUserData) 1.426 +{ 1.427 + nsArrayAndPositionAndCounterAndTracker *cap = 1.428 + (nsArrayAndPositionAndCounterAndTracker*)aUserData; 1.429 + if (!cap) 1.430 + return; 1.431 + 1.432 + nsAutoCString hostPort; 1.433 + nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort); 1.434 + if (!cap->tracker->GetEntry(hostPort)) 1.435 + return; 1.436 + 1.437 + // This entry is not associated to any stored cert, 1.438 + // so we still need to display it. 1.439 + 1.440 + nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo; 1.441 + if (certdi) { 1.442 + certdi->mAddonInfo = nullptr; 1.443 + certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override; 1.444 + certdi->mAsciiHost = aSettings.mAsciiHost; 1.445 + certdi->mPort = aSettings.mPort; 1.446 + certdi->mOverrideBits = aSettings.mOverrideBits; 1.447 + certdi->mIsTemporary = aSettings.mIsTemporary; 1.448 + certdi->mCert = aSettings.mCert; 1.449 + cap->array->InsertElementAt(cap->position, certdi); 1.450 + cap->position++; 1.451 + cap->counter++; 1.452 + } 1.453 +} 1.454 + 1.455 +nsresult 1.456 +nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList, 1.457 + uint32_t aWantedType, 1.458 + nsCertCompareFunc aCertCmpFn, 1.459 + void *aCertCmpFnArg) 1.460 +{ 1.461 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("GetCertsByTypeFromCertList")); 1.462 + if (!aCertList) 1.463 + return NS_ERROR_FAILURE; 1.464 + 1.465 + if (!mOriginalOverrideService) 1.466 + return NS_ERROR_FAILURE; 1.467 + 1.468 + nsTHashtable<nsCStringHashKey> allHostPortOverrideKeys; 1.469 + 1.470 + if (aWantedType == nsIX509Cert::SERVER_CERT) { 1.471 + mOriginalOverrideService-> 1.472 + EnumerateCertOverrides(nullptr, 1.473 + CollectAllHostPortOverridesCallback, 1.474 + &allHostPortOverrideKeys); 1.475 + } 1.476 + 1.477 + CERTCertListNode *node; 1.478 + int count = 0; 1.479 + for (node = CERT_LIST_HEAD(aCertList); 1.480 + !CERT_LIST_END(node, aCertList); 1.481 + node = CERT_LIST_NEXT(node)) { 1.482 + 1.483 + bool wantThisCert = (aWantedType == nsIX509Cert2::ANY_CERT); 1.484 + bool wantThisCertIfNoOverrides = false; 1.485 + bool wantThisCertIfHaveOverrides = false; 1.486 + bool addOverrides = false; 1.487 + 1.488 + if (!wantThisCert) { 1.489 + uint32_t thisCertType = getCertType(node->cert); 1.490 + 1.491 + // The output from getCertType is a "guess", which can be wrong. 1.492 + // The guess is based on stored trust flags, but for the host:port 1.493 + // overrides, we are storing certs without any trust flags associated. 1.494 + // So we must check whether the cert really belongs to the 1.495 + // server, email or unknown tab. We will lookup the cert in the override 1.496 + // list to come to the decision. Unfortunately, the lookup in the 1.497 + // override list is quite expensive. Therefore we are using this 1.498 + // lengthy if/else statement to minimize 1.499 + // the number of override-list-lookups. 1.500 + 1.501 + if (aWantedType == nsIX509Cert::SERVER_CERT 1.502 + && thisCertType == nsIX509Cert::UNKNOWN_CERT) { 1.503 + // This unknown cert was stored without trust 1.504 + // Are there host:port based overrides stored? 1.505 + // If yes, display them. 1.506 + addOverrides = true; 1.507 + } 1.508 + else 1.509 + if (aWantedType == nsIX509Cert::UNKNOWN_CERT 1.510 + && thisCertType == nsIX509Cert::UNKNOWN_CERT) { 1.511 + // This unknown cert was stored without trust. 1.512 + // If there are associated overrides, do not show as unknown. 1.513 + // If there are no associated overrides, display as unknown. 1.514 + wantThisCertIfNoOverrides = true; 1.515 + } 1.516 + else 1.517 + if (aWantedType == nsIX509Cert::SERVER_CERT 1.518 + && thisCertType == nsIX509Cert::SERVER_CERT) { 1.519 + // This server cert is explicitly marked as a web site peer, 1.520 + // with or without trust, but editable, so show it 1.521 + wantThisCert = true; 1.522 + // Are there host:port based overrides stored? 1.523 + // If yes, display them. 1.524 + addOverrides = true; 1.525 + } 1.526 + else 1.527 + if (aWantedType == nsIX509Cert::SERVER_CERT 1.528 + && thisCertType == nsIX509Cert::EMAIL_CERT) { 1.529 + // This cert might have been categorized as an email cert 1.530 + // because it carries an email address. But is it really one? 1.531 + // Our cert categorization is uncertain when it comes to 1.532 + // distinguish between email certs and web site certs. 1.533 + // So, let's see if we have an override for that cert 1.534 + // and if there is, conclude it's really a web site cert. 1.535 + addOverrides = true; 1.536 + } 1.537 + else 1.538 + if (aWantedType == nsIX509Cert::EMAIL_CERT 1.539 + && thisCertType == nsIX509Cert::EMAIL_CERT) { 1.540 + // This cert might have been categorized as an email cert 1.541 + // because it carries an email address. But is it really one? 1.542 + // Our cert categorization is uncertain when it comes to 1.543 + // distinguish between email certs and web site certs. 1.544 + // So, let's see if we have an override for that cert 1.545 + // and if there is, conclude it's really a web site cert. 1.546 + wantThisCertIfNoOverrides = true; 1.547 + } 1.548 + else 1.549 + if (thisCertType == aWantedType) { 1.550 + wantThisCert = true; 1.551 + } 1.552 + } 1.553 + 1.554 + nsCOMPtr<nsIX509Cert> pipCert = nsNSSCertificate::Create(node->cert); 1.555 + if (!pipCert) 1.556 + return NS_ERROR_OUT_OF_MEMORY; 1.557 + 1.558 + if (wantThisCertIfNoOverrides || wantThisCertIfHaveOverrides) { 1.559 + uint32_t ocount = 0; 1.560 + nsresult rv = 1.561 + mOverrideService->IsCertUsedForOverrides(pipCert, 1.562 + true, // we want temporaries 1.563 + true, // we want permanents 1.564 + &ocount); 1.565 + if (wantThisCertIfNoOverrides) { 1.566 + if (NS_FAILED(rv) || ocount == 0) { 1.567 + // no overrides for this cert 1.568 + wantThisCert = true; 1.569 + } 1.570 + } 1.571 + 1.572 + if (wantThisCertIfHaveOverrides) { 1.573 + if (NS_SUCCEEDED(rv) && ocount > 0) { 1.574 + // there are overrides for this cert 1.575 + wantThisCert = true; 1.576 + } 1.577 + } 1.578 + } 1.579 + 1.580 + RefPtr<nsCertAddonInfo> certai(new nsCertAddonInfo); 1.581 + certai->mCert = pipCert; 1.582 + certai->mUsageCount = 0; 1.583 + 1.584 + if (wantThisCert || addOverrides) { 1.585 + int InsertPosition = 0; 1.586 + for (; InsertPosition < count; ++InsertPosition) { 1.587 + nsCOMPtr<nsIX509Cert> cert = nullptr; 1.588 + RefPtr<nsCertTreeDispInfo> elem( 1.589 + mDispInfo.SafeElementAt(InsertPosition, nullptr)); 1.590 + if (elem && elem->mAddonInfo) { 1.591 + cert = elem->mAddonInfo->mCert; 1.592 + } 1.593 + if ((*aCertCmpFn)(aCertCmpFnArg, pipCert, cert) < 0) { 1.594 + break; 1.595 + } 1.596 + } 1.597 + if (wantThisCert) { 1.598 + nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo; 1.599 + certdi->mAddonInfo = certai; 1.600 + certai->mUsageCount++; 1.601 + certdi->mTypeOfEntry = nsCertTreeDispInfo::direct_db; 1.602 + // not necessary: certdi->mAsciiHost.Clear(); certdi->mPort = -1; 1.603 + certdi->mOverrideBits = nsCertOverride::ob_None; 1.604 + certdi->mIsTemporary = false; 1.605 + mDispInfo.InsertElementAt(InsertPosition, certdi); 1.606 + ++count; 1.607 + ++InsertPosition; 1.608 + } 1.609 + if (addOverrides) { 1.610 + nsCertAndArrayAndPositionAndCounterAndTracker cap; 1.611 + cap.certai = certai; 1.612 + cap.array = &mDispInfo; 1.613 + cap.position = InsertPosition; 1.614 + cap.counter = 0; 1.615 + cap.tracker = &allHostPortOverrideKeys; 1.616 + 1.617 + mOriginalOverrideService-> 1.618 + EnumerateCertOverrides(pipCert, MatchingCertOverridesCallback, &cap); 1.619 + count += cap.counter; 1.620 + } 1.621 + } 1.622 + } 1.623 + 1.624 + if (aWantedType == nsIX509Cert::SERVER_CERT) { 1.625 + nsArrayAndPositionAndCounterAndTracker cap; 1.626 + cap.array = &mDispInfo; 1.627 + cap.position = 0; 1.628 + cap.counter = 0; 1.629 + cap.tracker = &allHostPortOverrideKeys; 1.630 + mOriginalOverrideService-> 1.631 + EnumerateCertOverrides(nullptr, AddRemaningHostPortOverridesCallback, &cap); 1.632 + } 1.633 + 1.634 + return NS_OK; 1.635 +} 1.636 + 1.637 +nsresult 1.638 +nsCertTree::GetCertsByType(uint32_t aType, 1.639 + nsCertCompareFunc aCertCmpFn, 1.640 + void *aCertCmpFnArg) 1.641 +{ 1.642 + nsNSSShutDownPreventionLock locker; 1.643 + nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext(); 1.644 + mozilla::pkix::ScopedCERTCertList certList( 1.645 + PK11_ListCerts(PK11CertListUnique, cxt)); 1.646 + return GetCertsByTypeFromCertList(certList.get(), aType, aCertCmpFn, 1.647 + aCertCmpFnArg); 1.648 +} 1.649 + 1.650 +nsresult 1.651 +nsCertTree::GetCertsByTypeFromCache(nsINSSCertCache *aCache, 1.652 + uint32_t aType, 1.653 + nsCertCompareFunc aCertCmpFn, 1.654 + void *aCertCmpFnArg) 1.655 +{ 1.656 + NS_ENSURE_ARG_POINTER(aCache); 1.657 + CERTCertList *certList = reinterpret_cast<CERTCertList*>(aCache->GetCachedCerts()); 1.658 + if (!certList) 1.659 + return NS_ERROR_FAILURE; 1.660 + return GetCertsByTypeFromCertList(certList, aType, aCertCmpFn, aCertCmpFnArg); 1.661 +} 1.662 + 1.663 +// LoadCerts 1.664 +// 1.665 +// Load all of the certificates in the DB for this type. Sort them 1.666 +// by token, organization, then common name. 1.667 +NS_IMETHODIMP 1.668 +nsCertTree::LoadCertsFromCache(nsINSSCertCache *aCache, uint32_t aType) 1.669 +{ 1.670 + if (mTreeArray) { 1.671 + FreeCertArray(); 1.672 + delete [] mTreeArray; 1.673 + mTreeArray = nullptr; 1.674 + mNumRows = 0; 1.675 + } 1.676 + nsresult rv = InitCompareHash(); 1.677 + if (NS_FAILED(rv)) return rv; 1.678 + 1.679 + rv = GetCertsByTypeFromCache(aCache, aType, 1.680 + GetCompareFuncFromCertType(aType), &mCompareCache); 1.681 + if (NS_FAILED(rv)) return rv; 1.682 + return UpdateUIContents(); 1.683 +} 1.684 + 1.685 +NS_IMETHODIMP 1.686 +nsCertTree::LoadCerts(uint32_t aType) 1.687 +{ 1.688 + if (mTreeArray) { 1.689 + FreeCertArray(); 1.690 + delete [] mTreeArray; 1.691 + mTreeArray = nullptr; 1.692 + mNumRows = 0; 1.693 + } 1.694 + nsresult rv = InitCompareHash(); 1.695 + if (NS_FAILED(rv)) return rv; 1.696 + 1.697 + rv = GetCertsByType(aType, 1.698 + GetCompareFuncFromCertType(aType), &mCompareCache); 1.699 + if (NS_FAILED(rv)) return rv; 1.700 + return UpdateUIContents(); 1.701 +} 1.702 + 1.703 +nsresult 1.704 +nsCertTree::UpdateUIContents() 1.705 +{ 1.706 + uint32_t count = mDispInfo.Length(); 1.707 + mNumOrgs = CountOrganizations(); 1.708 + mTreeArray = new treeArrayEl[mNumOrgs]; 1.709 + 1.710 + mCellText = do_CreateInstance(NS_ARRAY_CONTRACTID); 1.711 + 1.712 +if (count) { 1.713 + uint32_t j = 0; 1.714 + nsCOMPtr<nsIX509Cert> orgCert = nullptr; 1.715 + nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(j)->mAddonInfo; 1.716 + if (addonInfo) { 1.717 + orgCert = addonInfo->mCert; 1.718 + } 1.719 + for (int32_t i=0; i<mNumOrgs; i++) { 1.720 + nsString &orgNameRef = mTreeArray[i].orgName; 1.721 + if (!orgCert) { 1.722 + mNSSComponent->GetPIPNSSBundleString("CertOrgUnknown", orgNameRef); 1.723 + } 1.724 + else { 1.725 + orgCert->GetIssuerOrganization(orgNameRef); 1.726 + if (orgNameRef.IsEmpty()) 1.727 + orgCert->GetCommonName(orgNameRef); 1.728 + } 1.729 + mTreeArray[i].open = true; 1.730 + mTreeArray[i].certIndex = j; 1.731 + mTreeArray[i].numChildren = 1; 1.732 + if (++j >= count) break; 1.733 + nsCOMPtr<nsIX509Cert> nextCert = nullptr; 1.734 + nsCertAddonInfo *addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo; 1.735 + if (addonInfo) { 1.736 + nextCert = addonInfo->mCert; 1.737 + } 1.738 + while (0 == CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None)) { 1.739 + mTreeArray[i].numChildren++; 1.740 + if (++j >= count) break; 1.741 + nextCert = nullptr; 1.742 + addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo; 1.743 + if (addonInfo) { 1.744 + nextCert = addonInfo->mCert; 1.745 + } 1.746 + } 1.747 + orgCert = nextCert; 1.748 + } 1.749 +} 1.750 + if (mTree) { 1.751 + mTree->BeginUpdateBatch(); 1.752 + mTree->RowCountChanged(0, -mNumRows); 1.753 + } 1.754 + mNumRows = count + mNumOrgs; 1.755 + if (mTree) 1.756 + mTree->EndUpdateBatch(); 1.757 + return NS_OK; 1.758 +} 1.759 + 1.760 +NS_IMETHODIMP 1.761 +nsCertTree::DeleteEntryObject(uint32_t index) 1.762 +{ 1.763 + if (!mTreeArray) { 1.764 + return NS_ERROR_FAILURE; 1.765 + } 1.766 + 1.767 + nsCOMPtr<nsIX509CertDB> certdb = 1.768 + do_GetService("@mozilla.org/security/x509certdb;1"); 1.769 + if (!certdb) { 1.770 + return NS_ERROR_FAILURE; 1.771 + } 1.772 + 1.773 + int i; 1.774 + uint32_t idx = 0, cIndex = 0, nc; 1.775 + // Loop over the threads 1.776 + for (i=0; i<mNumOrgs; i++) { 1.777 + if (index == idx) 1.778 + return NS_OK; // index is for thread 1.779 + idx++; // get past the thread 1.780 + nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0; 1.781 + if (index < idx + nc) { // cert is within range of this thread 1.782 + int32_t certIndex = cIndex + index - idx; 1.783 + 1.784 + bool canRemoveEntry = false; 1.785 + RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex, 1.786 + nullptr)); 1.787 + 1.788 + // We will remove the element from the visual tree. 1.789 + // Only if we have a certdi, then we can check for additional actions. 1.790 + nsCOMPtr<nsIX509Cert> cert = nullptr; 1.791 + if (certdi) { 1.792 + if (certdi->mAddonInfo) { 1.793 + cert = certdi->mAddonInfo->mCert; 1.794 + } 1.795 + nsCertAddonInfo *addonInfo = certdi->mAddonInfo ? certdi->mAddonInfo : nullptr; 1.796 + if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) { 1.797 + mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort); 1.798 + if (addonInfo) { 1.799 + addonInfo->mUsageCount--; 1.800 + if (addonInfo->mUsageCount == 0) { 1.801 + // The certificate stored in the database is no longer 1.802 + // referenced by any other object displayed. 1.803 + // That means we no longer need to keep it around 1.804 + // and really can remove it. 1.805 + canRemoveEntry = true; 1.806 + } 1.807 + } 1.808 + } 1.809 + else { 1.810 + if (addonInfo && addonInfo->mUsageCount > 1) { 1.811 + // user is trying to delete a perm trusted cert, 1.812 + // although there are still overrides stored, 1.813 + // so, we keep the cert, but remove the trust 1.814 + 1.815 + mozilla::pkix::ScopedCERTCertificate nsscert; 1.816 + 1.817 + nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(cert); 1.818 + if (cert2) { 1.819 + nsscert = cert2->GetCert(); 1.820 + } 1.821 + 1.822 + if (nsscert) { 1.823 + CERTCertTrust trust; 1.824 + memset((void*)&trust, 0, sizeof(trust)); 1.825 + 1.826 + SECStatus srv = CERT_DecodeTrustString(&trust, ""); // no override 1.827 + if (srv == SECSuccess) { 1.828 + CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert.get(), 1.829 + &trust); 1.830 + } 1.831 + } 1.832 + } 1.833 + else { 1.834 + canRemoveEntry = true; 1.835 + } 1.836 + } 1.837 + } 1.838 + 1.839 + mDispInfo.RemoveElementAt(certIndex); 1.840 + 1.841 + if (canRemoveEntry) { 1.842 + RemoveCacheEntry(cert); 1.843 + certdb->DeleteCertificate(cert); 1.844 + } 1.845 + 1.846 + delete [] mTreeArray; 1.847 + mTreeArray = nullptr; 1.848 + return UpdateUIContents(); 1.849 + } 1.850 + if (mTreeArray[i].open) 1.851 + idx += mTreeArray[i].numChildren; 1.852 + cIndex += mTreeArray[i].numChildren; 1.853 + if (idx > index) 1.854 + break; 1.855 + } 1.856 + return NS_ERROR_FAILURE; 1.857 +} 1.858 + 1.859 +////////////////////////////////////////////////////////////////////////////// 1.860 +// 1.861 +// Begin nsITreeView methods 1.862 +// 1.863 +///////////////////////////////////////////////////////////////////////////// 1.864 + 1.865 +/* nsIX509Cert getCert(in unsigned long index); */ 1.866 +NS_IMETHODIMP 1.867 +nsCertTree::GetCert(uint32_t aIndex, nsIX509Cert **_cert) 1.868 +{ 1.869 + NS_ENSURE_ARG(_cert); 1.870 + *_cert = GetCertAtIndex(aIndex).take(); 1.871 + return NS_OK; 1.872 +} 1.873 + 1.874 +NS_IMETHODIMP 1.875 +nsCertTree::GetTreeItem(uint32_t aIndex, nsICertTreeItem **_treeitem) 1.876 +{ 1.877 + NS_ENSURE_ARG(_treeitem); 1.878 + 1.879 + RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex)); 1.880 + if (!certdi) 1.881 + return NS_ERROR_FAILURE; 1.882 + 1.883 + *_treeitem = certdi; 1.884 + NS_IF_ADDREF(*_treeitem); 1.885 + return NS_OK; 1.886 +} 1.887 + 1.888 +NS_IMETHODIMP 1.889 +nsCertTree::IsHostPortOverride(uint32_t aIndex, bool *_retval) 1.890 +{ 1.891 + NS_ENSURE_ARG(_retval); 1.892 + 1.893 + RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex)); 1.894 + if (!certdi) 1.895 + return NS_ERROR_FAILURE; 1.896 + 1.897 + *_retval = (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override); 1.898 + return NS_OK; 1.899 +} 1.900 + 1.901 +/* readonly attribute long rowCount; */ 1.902 +NS_IMETHODIMP 1.903 +nsCertTree::GetRowCount(int32_t *aRowCount) 1.904 +{ 1.905 + if (!mTreeArray) 1.906 + return NS_ERROR_NOT_INITIALIZED; 1.907 + uint32_t count = 0; 1.908 + for (int32_t i=0; i<mNumOrgs; i++) { 1.909 + if (mTreeArray[i].open) { 1.910 + count += mTreeArray[i].numChildren; 1.911 + } 1.912 + count++; 1.913 + } 1.914 + *aRowCount = count; 1.915 + return NS_OK; 1.916 +} 1.917 + 1.918 +/* attribute nsITreeSelection selection; */ 1.919 +NS_IMETHODIMP 1.920 +nsCertTree::GetSelection(nsITreeSelection * *aSelection) 1.921 +{ 1.922 + *aSelection = mSelection; 1.923 + NS_IF_ADDREF(*aSelection); 1.924 + return NS_OK; 1.925 +} 1.926 + 1.927 +NS_IMETHODIMP 1.928 +nsCertTree::SetSelection(nsITreeSelection * aSelection) 1.929 +{ 1.930 + mSelection = aSelection; 1.931 + return NS_OK; 1.932 +} 1.933 + 1.934 +NS_IMETHODIMP 1.935 +nsCertTree::GetRowProperties(int32_t index, nsAString& aProps) 1.936 +{ 1.937 + return NS_OK; 1.938 +} 1.939 + 1.940 +NS_IMETHODIMP 1.941 +nsCertTree::GetCellProperties(int32_t row, nsITreeColumn* col, 1.942 + nsAString& aProps) 1.943 +{ 1.944 + return NS_OK; 1.945 +} 1.946 + 1.947 +NS_IMETHODIMP 1.948 +nsCertTree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps) 1.949 +{ 1.950 + return NS_OK; 1.951 +} 1.952 +/* boolean isContainer (in long index); */ 1.953 +NS_IMETHODIMP 1.954 +nsCertTree::IsContainer(int32_t index, bool *_retval) 1.955 +{ 1.956 + if (!mTreeArray) 1.957 + return NS_ERROR_NOT_INITIALIZED; 1.958 + treeArrayEl *el = GetThreadDescAtIndex(index); 1.959 + if (el) { 1.960 + *_retval = true; 1.961 + } else { 1.962 + *_retval = false; 1.963 + } 1.964 + return NS_OK; 1.965 +} 1.966 + 1.967 +/* boolean isContainerOpen (in long index); */ 1.968 +NS_IMETHODIMP 1.969 +nsCertTree::IsContainerOpen(int32_t index, bool *_retval) 1.970 +{ 1.971 + if (!mTreeArray) 1.972 + return NS_ERROR_NOT_INITIALIZED; 1.973 + treeArrayEl *el = GetThreadDescAtIndex(index); 1.974 + if (el && el->open) { 1.975 + *_retval = true; 1.976 + } else { 1.977 + *_retval = false; 1.978 + } 1.979 + return NS_OK; 1.980 +} 1.981 + 1.982 +/* boolean isContainerEmpty (in long index); */ 1.983 +NS_IMETHODIMP 1.984 +nsCertTree::IsContainerEmpty(int32_t index, bool *_retval) 1.985 +{ 1.986 + *_retval = !mTreeArray; 1.987 + return NS_OK; 1.988 +} 1.989 + 1.990 +/* boolean isSeparator (in long index); */ 1.991 +NS_IMETHODIMP 1.992 +nsCertTree::IsSeparator(int32_t index, bool *_retval) 1.993 +{ 1.994 + *_retval = false; 1.995 + return NS_OK; 1.996 +} 1.997 + 1.998 +/* long getParentIndex (in long rowIndex); */ 1.999 +NS_IMETHODIMP 1.1000 +nsCertTree::GetParentIndex(int32_t rowIndex, int32_t *_retval) 1.1001 +{ 1.1002 + if (!mTreeArray) 1.1003 + return NS_ERROR_NOT_INITIALIZED; 1.1004 + int i, idx = 0; 1.1005 + for (i = 0; i < mNumOrgs && idx < rowIndex; i++, idx++) { 1.1006 + if (mTreeArray[i].open) { 1.1007 + if (rowIndex <= idx + mTreeArray[i].numChildren) { 1.1008 + *_retval = idx; 1.1009 + return NS_OK; 1.1010 + } 1.1011 + idx += mTreeArray[i].numChildren; 1.1012 + } 1.1013 + } 1.1014 + *_retval = -1; 1.1015 + return NS_OK; 1.1016 +} 1.1017 + 1.1018 +/* boolean hasNextSibling (in long rowIndex, in long afterIndex); */ 1.1019 +NS_IMETHODIMP 1.1020 +nsCertTree::HasNextSibling(int32_t rowIndex, int32_t afterIndex, 1.1021 + bool *_retval) 1.1022 +{ 1.1023 + if (!mTreeArray) 1.1024 + return NS_ERROR_NOT_INITIALIZED; 1.1025 + 1.1026 + int i, idx = 0; 1.1027 + for (i = 0; i < mNumOrgs && idx <= rowIndex; i++, idx++) { 1.1028 + if (mTreeArray[i].open) { 1.1029 + idx += mTreeArray[i].numChildren; 1.1030 + if (afterIndex <= idx) { 1.1031 + *_retval = afterIndex < idx; 1.1032 + return NS_OK; 1.1033 + } 1.1034 + } 1.1035 + } 1.1036 + *_retval = false; 1.1037 + return NS_OK; 1.1038 +} 1.1039 + 1.1040 +/* long getLevel (in long index); */ 1.1041 +NS_IMETHODIMP 1.1042 +nsCertTree::GetLevel(int32_t index, int32_t *_retval) 1.1043 +{ 1.1044 + if (!mTreeArray) 1.1045 + return NS_ERROR_NOT_INITIALIZED; 1.1046 + treeArrayEl *el = GetThreadDescAtIndex(index); 1.1047 + if (el) { 1.1048 + *_retval = 0; 1.1049 + } else { 1.1050 + *_retval = 1; 1.1051 + } 1.1052 + return NS_OK; 1.1053 +} 1.1054 + 1.1055 +/* Astring getImageSrc (in long row, in nsITreeColumn col); */ 1.1056 +NS_IMETHODIMP 1.1057 +nsCertTree::GetImageSrc(int32_t row, nsITreeColumn* col, 1.1058 + nsAString& _retval) 1.1059 +{ 1.1060 + _retval.Truncate(); 1.1061 + return NS_OK; 1.1062 +} 1.1063 + 1.1064 +/* long getProgressMode (in long row, in nsITreeColumn col); */ 1.1065 +NS_IMETHODIMP 1.1066 +nsCertTree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval) 1.1067 +{ 1.1068 + return NS_OK; 1.1069 +} 1.1070 + 1.1071 +/* Astring getCellValue (in long row, in nsITreeColumn col); */ 1.1072 +NS_IMETHODIMP 1.1073 +nsCertTree::GetCellValue(int32_t row, nsITreeColumn* col, 1.1074 + nsAString& _retval) 1.1075 +{ 1.1076 + _retval.Truncate(); 1.1077 + return NS_OK; 1.1078 +} 1.1079 + 1.1080 +/* Astring getCellText (in long row, in nsITreeColumn col); */ 1.1081 +NS_IMETHODIMP 1.1082 +nsCertTree::GetCellText(int32_t row, nsITreeColumn* col, 1.1083 + nsAString& _retval) 1.1084 +{ 1.1085 + if (!mTreeArray) 1.1086 + return NS_ERROR_NOT_INITIALIZED; 1.1087 + 1.1088 + nsresult rv; 1.1089 + _retval.Truncate(); 1.1090 + 1.1091 + const char16_t* colID; 1.1092 + col->GetIdConst(&colID); 1.1093 + 1.1094 + treeArrayEl *el = GetThreadDescAtIndex(row); 1.1095 + if (el) { 1.1096 + if (NS_LITERAL_STRING("certcol").Equals(colID)) 1.1097 + _retval.Assign(el->orgName); 1.1098 + else 1.1099 + _retval.Truncate(); 1.1100 + return NS_OK; 1.1101 + } 1.1102 + 1.1103 + int32_t absoluteCertOffset; 1.1104 + RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(row, &absoluteCertOffset)); 1.1105 + if (!certdi) 1.1106 + return NS_ERROR_FAILURE; 1.1107 + 1.1108 + nsCOMPtr<nsIX509Cert> cert = certdi->mCert; 1.1109 + if (!cert && certdi->mAddonInfo) { 1.1110 + cert = certdi->mAddonInfo->mCert; 1.1111 + } 1.1112 + 1.1113 + int32_t colIndex; 1.1114 + col->GetIndex(&colIndex); 1.1115 + uint32_t arrayIndex=absoluteCertOffset+colIndex*(mNumRows-mNumOrgs); 1.1116 + uint32_t arrayLength=0; 1.1117 + if (mCellText) { 1.1118 + mCellText->GetLength(&arrayLength); 1.1119 + } 1.1120 + if (arrayIndex < arrayLength) { 1.1121 + nsCOMPtr<nsISupportsString> myString(do_QueryElementAt(mCellText, arrayIndex)); 1.1122 + if (myString) { 1.1123 + myString->GetData(_retval); 1.1124 + return NS_OK; 1.1125 + } 1.1126 + } 1.1127 + 1.1128 + if (NS_LITERAL_STRING("certcol").Equals(colID)) { 1.1129 + if (!cert) { 1.1130 + mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval); 1.1131 + } 1.1132 + else { 1.1133 + rv = cert->GetCommonName(_retval); 1.1134 + if (NS_FAILED(rv) || _retval.IsEmpty()) { 1.1135 + // kaie: I didn't invent the idea to cut off anything before 1.1136 + // the first colon. :-) 1.1137 + nsAutoString nick; 1.1138 + rv = cert->GetNickname(nick); 1.1139 + 1.1140 + nsAString::const_iterator start, end, end2; 1.1141 + nick.BeginReading(start); 1.1142 + nick.EndReading(end); 1.1143 + end2 = end; 1.1144 + 1.1145 + if (FindInReadable(NS_LITERAL_STRING(":"), start, end)) { 1.1146 + // found. end points to the first char after the colon, 1.1147 + // that's what we want. 1.1148 + _retval = Substring(end, end2); 1.1149 + } 1.1150 + else { 1.1151 + _retval = nick; 1.1152 + } 1.1153 + } 1.1154 + } 1.1155 + } else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) { 1.1156 + rv = cert->GetTokenName(_retval); 1.1157 + } else if (NS_LITERAL_STRING("emailcol").Equals(colID) && cert) { 1.1158 + rv = cert->GetEmailAddress(_retval); 1.1159 + } else if (NS_LITERAL_STRING("purposecol").Equals(colID) && mNSSComponent && cert) { 1.1160 + uint32_t verified; 1.1161 + 1.1162 + nsAutoString theUsages; 1.1163 + rv = cert->GetUsagesString(false, &verified, theUsages); // allow OCSP 1.1164 + if (NS_FAILED(rv)) { 1.1165 + verified = nsIX509Cert::NOT_VERIFIED_UNKNOWN; 1.1166 + } 1.1167 + 1.1168 + switch (verified) { 1.1169 + case nsIX509Cert::VERIFIED_OK: 1.1170 + _retval = theUsages; 1.1171 + break; 1.1172 + 1.1173 + case nsIX509Cert::CERT_REVOKED: 1.1174 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyRevoked", _retval); 1.1175 + break; 1.1176 + case nsIX509Cert::CERT_EXPIRED: 1.1177 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyExpired", _retval); 1.1178 + break; 1.1179 + case nsIX509Cert::CERT_NOT_TRUSTED: 1.1180 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyNotTrusted", _retval); 1.1181 + break; 1.1182 + case nsIX509Cert::ISSUER_NOT_TRUSTED: 1.1183 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerNotTrusted", _retval); 1.1184 + break; 1.1185 + case nsIX509Cert::ISSUER_UNKNOWN: 1.1186 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerUnknown", _retval); 1.1187 + break; 1.1188 + case nsIX509Cert::INVALID_CA: 1.1189 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyInvalidCA", _retval); 1.1190 + break; 1.1191 + case nsIX509Cert::SIGNATURE_ALGORITHM_DISABLED: 1.1192 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyDisabledAlgorithm", _retval); 1.1193 + break; 1.1194 + case nsIX509Cert::NOT_VERIFIED_UNKNOWN: 1.1195 + case nsIX509Cert::USAGE_NOT_ALLOWED: 1.1196 + default: 1.1197 + rv = mNSSComponent->GetPIPNSSBundleString("VerifyUnknown", _retval); 1.1198 + break; 1.1199 + } 1.1200 + } else if (NS_LITERAL_STRING("issuedcol").Equals(colID) && cert) { 1.1201 + nsCOMPtr<nsIX509CertValidity> validity; 1.1202 + 1.1203 + rv = cert->GetValidity(getter_AddRefs(validity)); 1.1204 + if (NS_SUCCEEDED(rv)) { 1.1205 + validity->GetNotBeforeLocalDay(_retval); 1.1206 + } 1.1207 + } else if (NS_LITERAL_STRING("expiredcol").Equals(colID) && cert) { 1.1208 + nsCOMPtr<nsIX509CertValidity> validity; 1.1209 + 1.1210 + rv = cert->GetValidity(getter_AddRefs(validity)); 1.1211 + if (NS_SUCCEEDED(rv)) { 1.1212 + validity->GetNotAfterLocalDay(_retval); 1.1213 + } 1.1214 + } else if (NS_LITERAL_STRING("serialnumcol").Equals(colID) && cert) { 1.1215 + rv = cert->GetSerialNumber(_retval); 1.1216 + 1.1217 + 1.1218 + } else if (NS_LITERAL_STRING("overridetypecol").Equals(colID)) { 1.1219 + // default to classic permanent-trust 1.1220 + nsCertOverride::OverrideBits ob = nsCertOverride::ob_Untrusted; 1.1221 + if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) { 1.1222 + ob = certdi->mOverrideBits; 1.1223 + } 1.1224 + nsAutoCString temp; 1.1225 + nsCertOverride::convertBitsToString(ob, temp); 1.1226 + _retval = NS_ConvertUTF8toUTF16(temp); 1.1227 + } else if (NS_LITERAL_STRING("sitecol").Equals(colID)) { 1.1228 + if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) { 1.1229 + nsAutoCString hostPort; 1.1230 + nsCertOverrideService::GetHostWithPort(certdi->mAsciiHost, certdi->mPort, hostPort); 1.1231 + _retval = NS_ConvertUTF8toUTF16(hostPort); 1.1232 + } 1.1233 + else { 1.1234 + _retval = NS_LITERAL_STRING("*"); 1.1235 + } 1.1236 + } else if (NS_LITERAL_STRING("lifetimecol").Equals(colID)) { 1.1237 + const char *stringID = 1.1238 + (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent"; 1.1239 + rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval); 1.1240 + } else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) { 1.1241 + nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert); 1.1242 + uint32_t type = nsIX509Cert::UNKNOWN_CERT; 1.1243 + 1.1244 + if (pipCert) { 1.1245 + rv = pipCert->GetCertType(&type); 1.1246 + } 1.1247 + 1.1248 + switch (type) { 1.1249 + case nsIX509Cert::USER_CERT: 1.1250 + rv = mNSSComponent->GetPIPNSSBundleString("CertUser", _retval); 1.1251 + break; 1.1252 + case nsIX509Cert::CA_CERT: 1.1253 + rv = mNSSComponent->GetPIPNSSBundleString("CertCA", _retval); 1.1254 + break; 1.1255 + case nsIX509Cert::SERVER_CERT: 1.1256 + rv = mNSSComponent->GetPIPNSSBundleString("CertSSL", _retval); 1.1257 + break; 1.1258 + case nsIX509Cert::EMAIL_CERT: 1.1259 + rv = mNSSComponent->GetPIPNSSBundleString("CertEmail", _retval); 1.1260 + break; 1.1261 + default: 1.1262 + rv = mNSSComponent->GetPIPNSSBundleString("CertUnknown", _retval); 1.1263 + break; 1.1264 + } 1.1265 + 1.1266 + } else { 1.1267 + return NS_ERROR_FAILURE; 1.1268 + } 1.1269 + if (mCellText) { 1.1270 + nsCOMPtr<nsISupportsString> text(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv)); 1.1271 + NS_ENSURE_SUCCESS(rv, rv); 1.1272 + text->SetData(_retval); 1.1273 + mCellText->ReplaceElementAt(text, arrayIndex, false); 1.1274 + } 1.1275 + return rv; 1.1276 +} 1.1277 + 1.1278 +/* void setTree (in nsITreeBoxObject tree); */ 1.1279 +NS_IMETHODIMP 1.1280 +nsCertTree::SetTree(nsITreeBoxObject *tree) 1.1281 +{ 1.1282 + mTree = tree; 1.1283 + return NS_OK; 1.1284 +} 1.1285 + 1.1286 +/* void toggleOpenState (in long index); */ 1.1287 +NS_IMETHODIMP 1.1288 +nsCertTree::ToggleOpenState(int32_t index) 1.1289 +{ 1.1290 + if (!mTreeArray) 1.1291 + return NS_ERROR_NOT_INITIALIZED; 1.1292 + treeArrayEl *el = GetThreadDescAtIndex(index); 1.1293 + if (el) { 1.1294 + el->open = !el->open; 1.1295 + int32_t newChildren = (el->open) ? el->numChildren : -el->numChildren; 1.1296 + if (mTree) mTree->RowCountChanged(index + 1, newChildren); 1.1297 + } 1.1298 + return NS_OK; 1.1299 +} 1.1300 + 1.1301 +/* void cycleHeader (in nsITreeColumn); */ 1.1302 +NS_IMETHODIMP 1.1303 +nsCertTree::CycleHeader(nsITreeColumn* col) 1.1304 +{ 1.1305 + return NS_OK; 1.1306 +} 1.1307 + 1.1308 +/* void selectionChanged (); */ 1.1309 +NS_IMETHODIMP 1.1310 +nsCertTree::SelectionChanged() 1.1311 +{ 1.1312 + return NS_ERROR_NOT_IMPLEMENTED; 1.1313 +} 1.1314 + 1.1315 +/* void cycleCell (in long row, in nsITreeColumn col); */ 1.1316 +NS_IMETHODIMP 1.1317 +nsCertTree::CycleCell(int32_t row, nsITreeColumn* col) 1.1318 +{ 1.1319 + return NS_OK; 1.1320 +} 1.1321 + 1.1322 +/* boolean isEditable (in long row, in nsITreeColumn col); */ 1.1323 +NS_IMETHODIMP 1.1324 +nsCertTree::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval) 1.1325 +{ 1.1326 + *_retval = false; 1.1327 + return NS_OK; 1.1328 +} 1.1329 + 1.1330 +/* boolean isSelectable (in long row, in nsITreeColumn col); */ 1.1331 +NS_IMETHODIMP 1.1332 +nsCertTree::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval) 1.1333 +{ 1.1334 + *_retval = false; 1.1335 + return NS_OK; 1.1336 +} 1.1337 + 1.1338 +/* void setCellValue (in long row, in nsITreeColumn col, in AString value); */ 1.1339 +NS_IMETHODIMP 1.1340 +nsCertTree::SetCellValue(int32_t row, nsITreeColumn* col, 1.1341 + const nsAString& value) 1.1342 +{ 1.1343 + return NS_OK; 1.1344 +} 1.1345 + 1.1346 +/* void setCellText (in long row, in nsITreeColumn col, in AString value); */ 1.1347 +NS_IMETHODIMP 1.1348 +nsCertTree::SetCellText(int32_t row, nsITreeColumn* col, 1.1349 + const nsAString& value) 1.1350 +{ 1.1351 + return NS_OK; 1.1352 +} 1.1353 + 1.1354 +/* void performAction (in wstring action); */ 1.1355 +NS_IMETHODIMP 1.1356 +nsCertTree::PerformAction(const char16_t *action) 1.1357 +{ 1.1358 + return NS_OK; 1.1359 +} 1.1360 + 1.1361 +/* void performActionOnRow (in wstring action, in long row); */ 1.1362 +NS_IMETHODIMP 1.1363 +nsCertTree::PerformActionOnRow(const char16_t *action, int32_t row) 1.1364 +{ 1.1365 + return NS_OK; 1.1366 +} 1.1367 + 1.1368 +/* void performActionOnCell (in wstring action, in long row, 1.1369 + * in wstring colID); 1.1370 + */ 1.1371 +NS_IMETHODIMP 1.1372 +nsCertTree::PerformActionOnCell(const char16_t *action, int32_t row, 1.1373 + nsITreeColumn* col) 1.1374 +{ 1.1375 + return NS_OK; 1.1376 +} 1.1377 + 1.1378 +#ifdef DEBUG_CERT_TREE 1.1379 +void 1.1380 +nsCertTree::dumpMap() 1.1381 +{ 1.1382 + for (int i=0; i<mNumOrgs; i++) { 1.1383 + nsAutoString org(mTreeArray[i].orgName); 1.1384 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("ORG[%s]", NS_LossyConvertUTF16toASCII(org).get())); 1.1385 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("OPEN[%d]", mTreeArray[i].open)); 1.1386 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("INDEX[%d]", mTreeArray[i].certIndex)); 1.1387 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NCHILD[%d]", mTreeArray[i].numChildren)); 1.1388 + } 1.1389 + for (int i=0; i<mNumRows; i++) { 1.1390 + treeArrayEl *el = GetThreadDescAtIndex(i); 1.1391 + if (el) { 1.1392 + nsAutoString td(el->orgName); 1.1393 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("thread desc[%d]: %s", i, NS_LossyConvertUTF16toASCII(td).get())); 1.1394 + } 1.1395 + nsCOMPtr<nsIX509Cert> ct = GetCertAtIndex(i); 1.1396 + if (ct) { 1.1397 + char16_t *goo; 1.1398 + ct->GetCommonName(&goo); 1.1399 + nsAutoString doo(goo); 1.1400 + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert [%d]: %s", i, NS_LossyConvertUTF16toASCII(doo).get())); 1.1401 + } 1.1402 + } 1.1403 +} 1.1404 +#endif 1.1405 + 1.1406 +// 1.1407 +// CanDrop 1.1408 +// 1.1409 +NS_IMETHODIMP nsCertTree::CanDrop(int32_t index, int32_t orientation, 1.1410 + nsIDOMDataTransfer* aDataTransfer, bool *_retval) 1.1411 +{ 1.1412 + NS_ENSURE_ARG_POINTER(_retval); 1.1413 + *_retval = false; 1.1414 + 1.1415 + return NS_OK; 1.1416 +} 1.1417 + 1.1418 + 1.1419 +// 1.1420 +// Drop 1.1421 +// 1.1422 +NS_IMETHODIMP nsCertTree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer) 1.1423 +{ 1.1424 + return NS_OK; 1.1425 +} 1.1426 + 1.1427 + 1.1428 +// 1.1429 +// IsSorted 1.1430 +// 1.1431 +// ... 1.1432 +// 1.1433 +NS_IMETHODIMP nsCertTree::IsSorted(bool *_retval) 1.1434 +{ 1.1435 + *_retval = false; 1.1436 + return NS_OK; 1.1437 +} 1.1438 + 1.1439 +#define RETURN_NOTHING 1.1440 + 1.1441 +void 1.1442 +nsCertTree::CmpInitCriterion(nsIX509Cert *cert, CompareCacheHashEntry *entry, 1.1443 + sortCriterion crit, int32_t level) 1.1444 +{ 1.1445 + NS_ENSURE_TRUE(cert && entry, RETURN_NOTHING); 1.1446 + 1.1447 + entry->mCritInit[level] = true; 1.1448 + nsXPIDLString &str = entry->mCrit[level]; 1.1449 + 1.1450 + switch (crit) { 1.1451 + case sort_IssuerOrg: 1.1452 + cert->GetIssuerOrganization(str); 1.1453 + if (str.IsEmpty()) 1.1454 + cert->GetCommonName(str); 1.1455 + break; 1.1456 + case sort_Org: 1.1457 + cert->GetOrganization(str); 1.1458 + break; 1.1459 + case sort_Token: 1.1460 + cert->GetTokenName(str); 1.1461 + break; 1.1462 + case sort_CommonName: 1.1463 + cert->GetCommonName(str); 1.1464 + break; 1.1465 + case sort_IssuedDateDescending: 1.1466 + { 1.1467 + nsresult rv; 1.1468 + nsCOMPtr<nsIX509CertValidity> validity; 1.1469 + PRTime notBefore; 1.1470 + 1.1471 + rv = cert->GetValidity(getter_AddRefs(validity)); 1.1472 + if (NS_SUCCEEDED(rv)) { 1.1473 + rv = validity->GetNotBefore(¬Before); 1.1474 + } 1.1475 + 1.1476 + if (NS_SUCCEEDED(rv)) { 1.1477 + PRExplodedTime explodedTime; 1.1478 + PR_ExplodeTime(notBefore, PR_GMTParameters, &explodedTime); 1.1479 + char datebuf[20]; // 4 + 2 + 2 + 2 + 2 + 2 + 1 = 15 1.1480 + if (0 != PR_FormatTime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", &explodedTime)) { 1.1481 + str = NS_ConvertASCIItoUTF16(nsDependentCString(datebuf)); 1.1482 + } 1.1483 + } 1.1484 + } 1.1485 + break; 1.1486 + case sort_Email: 1.1487 + cert->GetEmailAddress(str); 1.1488 + break; 1.1489 + case sort_None: 1.1490 + default: 1.1491 + break; 1.1492 + } 1.1493 +} 1.1494 + 1.1495 +int32_t 1.1496 +nsCertTree::CmpByCrit(nsIX509Cert *a, CompareCacheHashEntry *ace, 1.1497 + nsIX509Cert *b, CompareCacheHashEntry *bce, 1.1498 + sortCriterion crit, int32_t level) 1.1499 +{ 1.1500 + NS_ENSURE_TRUE(a && ace && b && bce, 0); 1.1501 + 1.1502 + if (!ace->mCritInit[level]) { 1.1503 + CmpInitCriterion(a, ace, crit, level); 1.1504 + } 1.1505 + 1.1506 + if (!bce->mCritInit[level]) { 1.1507 + CmpInitCriterion(b, bce, crit, level); 1.1508 + } 1.1509 + 1.1510 + nsXPIDLString &str_a = ace->mCrit[level]; 1.1511 + nsXPIDLString &str_b = bce->mCrit[level]; 1.1512 + 1.1513 + int32_t result; 1.1514 + if (str_a && str_b) 1.1515 + result = Compare(str_a, str_b, nsCaseInsensitiveStringComparator()); 1.1516 + else 1.1517 + result = !str_a ? (!str_b ? 0 : -1) : 1; 1.1518 + 1.1519 + if (sort_IssuedDateDescending == crit) 1.1520 + result *= -1; // reverse compare order 1.1521 + 1.1522 + return result; 1.1523 +} 1.1524 + 1.1525 +int32_t 1.1526 +nsCertTree::CmpBy(void *cache, nsIX509Cert *a, nsIX509Cert *b, 1.1527 + sortCriterion c0, sortCriterion c1, sortCriterion c2) 1.1528 +{ 1.1529 + // This will be called when comparing items for display sorting. 1.1530 + // Some items might have no cert associated, so either a or b is null. 1.1531 + // We want all those orphans show at the top of the list, 1.1532 + // so we treat a null cert as "smaller" by returning -1. 1.1533 + // We don't try to sort within the group of no-cert entries, 1.1534 + // so we treat them as equal wrt sort order. 1.1535 + 1.1536 + if (!a && !b) 1.1537 + return 0; 1.1538 + 1.1539 + if (!a) 1.1540 + return -1; 1.1541 + 1.1542 + if (!b) 1.1543 + return 1; 1.1544 + 1.1545 + NS_ENSURE_TRUE(cache && a && b, 0); 1.1546 + 1.1547 + CompareCacheHashEntry *ace = getCacheEntry(cache, a); 1.1548 + CompareCacheHashEntry *bce = getCacheEntry(cache, b); 1.1549 + 1.1550 + int32_t cmp; 1.1551 + cmp = CmpByCrit(a, ace, b, bce, c0, 0); 1.1552 + if (cmp != 0) 1.1553 + return cmp; 1.1554 + 1.1555 + if (c1 != sort_None) { 1.1556 + cmp = CmpByCrit(a, ace, b, bce, c1, 1); 1.1557 + if (cmp != 0) 1.1558 + return cmp; 1.1559 + 1.1560 + if (c2 != sort_None) { 1.1561 + return CmpByCrit(a, ace, b, bce, c2, 2); 1.1562 + } 1.1563 + } 1.1564 + 1.1565 + return cmp; 1.1566 +} 1.1567 + 1.1568 +int32_t 1.1569 +nsCertTree::CmpCACert(void *cache, nsIX509Cert *a, nsIX509Cert *b) 1.1570 +{ 1.1571 + // XXX we assume issuer org is always criterion 1 1.1572 + return CmpBy(cache, a, b, sort_IssuerOrg, sort_Org, sort_Token); 1.1573 +} 1.1574 + 1.1575 +int32_t 1.1576 +nsCertTree::CmpWebSiteCert(void *cache, nsIX509Cert *a, nsIX509Cert *b) 1.1577 +{ 1.1578 + // XXX we assume issuer org is always criterion 1 1.1579 + return CmpBy(cache, a, b, sort_IssuerOrg, sort_CommonName, sort_None); 1.1580 +} 1.1581 + 1.1582 +int32_t 1.1583 +nsCertTree::CmpUserCert(void *cache, nsIX509Cert *a, nsIX509Cert *b) 1.1584 +{ 1.1585 + // XXX we assume issuer org is always criterion 1 1.1586 + return CmpBy(cache, a, b, sort_IssuerOrg, sort_Token, sort_IssuedDateDescending); 1.1587 +} 1.1588 + 1.1589 +int32_t 1.1590 +nsCertTree::CmpEmailCert(void *cache, nsIX509Cert *a, nsIX509Cert *b) 1.1591 +{ 1.1592 + // XXX we assume issuer org is always criterion 1 1.1593 + return CmpBy(cache, a, b, sort_IssuerOrg, sort_Email, sort_CommonName); 1.1594 +} 1.1595 +