Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "nsCertTree.h"
6 :
7 : #include "ScopedNSSTypes.h"
8 : #include "mozilla/Logging.h"
9 : #include "nsArray.h"
10 : #include "nsArrayUtils.h"
11 : #include "nsHashKeys.h"
12 : #include "nsISupportsPrimitives.h"
13 : #include "nsITreeColumns.h"
14 : #include "nsIX509CertDB.h"
15 : #include "nsIX509Cert.h"
16 : #include "nsIX509CertValidity.h"
17 : #include "nsNSSCertHelper.h"
18 : #include "nsNSSCertificate.h"
19 : #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
20 : #include "nsNSSHelper.h"
21 : #include "nsReadableUtils.h"
22 : #include "nsTHashtable.h"
23 : #include "nsUnicharUtils.h"
24 : #include "nsXPCOMCID.h"
25 : #include "nsXPIDLString.h"
26 : #include "pkix/pkixtypes.h"
27 :
28 : using namespace mozilla;
29 :
30 : extern LazyLogModule gPIPNSSLog;
31 :
32 : static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID);
33 :
34 : // treeArrayElStr
35 : //
36 : // structure used to hold map of tree. Each thread (an organization
37 : // field from a cert) has an element in the array. The numChildren field
38 : // stores the number of certs corresponding to that thread.
39 0 : struct treeArrayElStr {
40 : nsString orgName; /* heading for thread */
41 : bool open; /* toggle open state for thread */
42 : int32_t certIndex; /* index into cert array for 1st cert */
43 : int32_t numChildren; /* number of chidren (certs) for thread */
44 : };
45 :
46 0 : CompareCacheHashEntryPtr::CompareCacheHashEntryPtr()
47 : {
48 0 : entry = new CompareCacheHashEntry;
49 0 : }
50 :
51 0 : CompareCacheHashEntryPtr::~CompareCacheHashEntryPtr()
52 : {
53 0 : delete entry;
54 0 : }
55 :
56 0 : CompareCacheHashEntry::CompareCacheHashEntry()
57 0 : :key(nullptr)
58 : {
59 0 : for (int i = 0; i < max_criterions; ++i) {
60 0 : mCritInit[i] = false;
61 : }
62 0 : }
63 :
64 : static bool
65 0 : CompareCacheMatchEntry(const PLDHashEntryHdr *hdr, const void *key)
66 : {
67 0 : const CompareCacheHashEntryPtr *entryPtr = static_cast<const CompareCacheHashEntryPtr*>(hdr);
68 0 : return entryPtr->entry->key == key;
69 : }
70 :
71 : static void
72 0 : CompareCacheInitEntry(PLDHashEntryHdr *hdr, const void *key)
73 : {
74 0 : new (hdr) CompareCacheHashEntryPtr();
75 0 : CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
76 0 : entryPtr->entry->key = (void*)key;
77 0 : }
78 :
79 : static void
80 0 : CompareCacheClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
81 : {
82 0 : CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
83 0 : entryPtr->~CompareCacheHashEntryPtr();
84 0 : }
85 :
86 : static const PLDHashTableOps gMapOps = {
87 : PLDHashTable::HashVoidPtrKeyStub,
88 : CompareCacheMatchEntry,
89 : PLDHashTable::MoveEntryStub,
90 : CompareCacheClearEntry,
91 : CompareCacheInitEntry
92 : };
93 :
94 0 : NS_IMPL_ISUPPORTS0(nsCertAddonInfo)
95 0 : NS_IMPL_ISUPPORTS(nsCertTreeDispInfo, nsICertTreeItem)
96 :
97 0 : nsCertTreeDispInfo::nsCertTreeDispInfo()
98 : : mAddonInfo(nullptr)
99 : , mTypeOfEntry(direct_db)
100 : , mPort(-1)
101 : , mOverrideBits(nsCertOverride::OverrideBits::None)
102 0 : , mIsTemporary(true)
103 : {
104 0 : }
105 :
106 0 : nsCertTreeDispInfo::nsCertTreeDispInfo(nsCertTreeDispInfo &other)
107 : {
108 0 : mAddonInfo = other.mAddonInfo;
109 0 : mTypeOfEntry = other.mTypeOfEntry;
110 0 : mAsciiHost = other.mAsciiHost;
111 0 : mPort = other.mPort;
112 0 : mOverrideBits = other.mOverrideBits;
113 0 : mIsTemporary = other.mIsTemporary;
114 0 : mCert = other.mCert;
115 0 : }
116 :
117 0 : nsCertTreeDispInfo::~nsCertTreeDispInfo()
118 : {
119 0 : }
120 :
121 : NS_IMETHODIMP
122 0 : nsCertTreeDispInfo::GetCert(nsIX509Cert **_cert)
123 : {
124 0 : NS_ENSURE_ARG(_cert);
125 0 : if (mCert) {
126 : // we may already have the cert for temporary overrides
127 0 : *_cert = mCert;
128 0 : NS_IF_ADDREF(*_cert);
129 0 : return NS_OK;
130 : }
131 0 : if (mAddonInfo) {
132 0 : *_cert = mAddonInfo->mCert.get();
133 0 : NS_IF_ADDREF(*_cert);
134 : }
135 : else {
136 0 : *_cert = nullptr;
137 : }
138 0 : return NS_OK;
139 : }
140 :
141 : NS_IMETHODIMP
142 0 : nsCertTreeDispInfo::GetHostPort(nsAString &aHostPort)
143 : {
144 0 : nsAutoCString hostPort;
145 0 : nsCertOverrideService::GetHostWithPort(mAsciiHost, mPort, hostPort);
146 0 : aHostPort = NS_ConvertUTF8toUTF16(hostPort);
147 0 : return NS_OK;
148 : }
149 :
150 0 : NS_IMPL_ISUPPORTS(nsCertTree, nsICertTree, nsITreeView)
151 :
152 0 : nsCertTree::nsCertTree()
153 : : mTreeArray(nullptr)
154 : , mCompareCache(&gMapOps, sizeof(CompareCacheHashEntryPtr),
155 0 : kInitialCacheLength)
156 : {
157 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
158 :
159 0 : mNSSComponent = do_GetService(kNSSComponentCID);
160 0 : mOverrideService = do_GetService("@mozilla.org/security/certoverride;1");
161 : // Might be a different service if someone is overriding the contract
162 : nsCOMPtr<nsICertOverrideService> origCertOverride =
163 0 : do_GetService(kCertOverrideCID);
164 : mOriginalOverrideService =
165 0 : static_cast<nsCertOverrideService*>(origCertOverride.get());
166 0 : mCellText = nullptr;
167 0 : }
168 :
169 0 : void nsCertTree::ClearCompareHash()
170 : {
171 0 : mCompareCache.ClearAndPrepareForLength(kInitialCacheLength);
172 0 : }
173 :
174 0 : nsCertTree::~nsCertTree()
175 : {
176 0 : delete [] mTreeArray;
177 0 : }
178 :
179 : void
180 0 : nsCertTree::FreeCertArray()
181 : {
182 0 : mDispInfo.Clear();
183 0 : }
184 :
185 : CompareCacheHashEntry*
186 0 : nsCertTree::getCacheEntry(void* cache, void* aCert)
187 : {
188 0 : PLDHashTable& aCompareCache = *static_cast<PLDHashTable*>(cache);
189 : auto entryPtr = static_cast<CompareCacheHashEntryPtr*>
190 0 : (aCompareCache.Add(aCert, fallible));
191 0 : return entryPtr ? entryPtr->entry : nullptr;
192 : }
193 :
194 0 : void nsCertTree::RemoveCacheEntry(void *key)
195 : {
196 0 : mCompareCache.Remove(key);
197 0 : }
198 :
199 : // CountOrganizations
200 : //
201 : // Count the number of different organizations encountered in the cert
202 : // list.
203 : int32_t
204 0 : nsCertTree::CountOrganizations()
205 : {
206 : uint32_t i, certCount;
207 0 : certCount = mDispInfo.Length();
208 0 : if (certCount == 0) return 0;
209 0 : nsCOMPtr<nsIX509Cert> orgCert = nullptr;
210 0 : nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(0)->mAddonInfo;
211 0 : if (addonInfo) {
212 0 : orgCert = addonInfo->mCert;
213 : }
214 0 : nsCOMPtr<nsIX509Cert> nextCert = nullptr;
215 0 : int32_t orgCount = 1;
216 0 : for (i=1; i<certCount; i++) {
217 0 : nextCert = nullptr;
218 0 : addonInfo = mDispInfo.SafeElementAt(i, nullptr)->mAddonInfo;
219 0 : if (addonInfo) {
220 0 : nextCert = addonInfo->mCert;
221 : }
222 : // XXX we assume issuer org is always criterion 1
223 0 : if (CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None) != 0) {
224 0 : orgCert = nextCert;
225 0 : orgCount++;
226 : }
227 : }
228 0 : return orgCount;
229 : }
230 :
231 : // GetThreadDescAtIndex
232 : //
233 : // If the row at index is an organization thread, return the collection
234 : // associated with that thread. Otherwise, return null.
235 : treeArrayEl *
236 0 : nsCertTree::GetThreadDescAtIndex(int32_t index)
237 : {
238 0 : int i, idx=0;
239 0 : if (index < 0) return nullptr;
240 0 : for (i=0; i<mNumOrgs; i++) {
241 0 : if (index == idx) {
242 0 : return &mTreeArray[i];
243 : }
244 0 : if (mTreeArray[i].open) {
245 0 : idx += mTreeArray[i].numChildren;
246 : }
247 0 : idx++;
248 0 : if (idx > index) break;
249 : }
250 0 : return nullptr;
251 : }
252 :
253 : // GetCertAtIndex
254 : //
255 : // If the row at index is a cert, return that cert. Otherwise, return null.
256 : already_AddRefed<nsIX509Cert>
257 0 : nsCertTree::GetCertAtIndex(int32_t index, int32_t *outAbsoluteCertOffset)
258 : {
259 : RefPtr<nsCertTreeDispInfo> certdi(
260 0 : GetDispInfoAtIndex(index, outAbsoluteCertOffset));
261 0 : if (!certdi)
262 0 : return nullptr;
263 :
264 0 : nsCOMPtr<nsIX509Cert> ret;
265 0 : if (certdi->mCert) {
266 0 : ret = certdi->mCert;
267 0 : } else if (certdi->mAddonInfo) {
268 0 : ret = certdi->mAddonInfo->mCert;
269 : }
270 0 : return ret.forget();
271 : }
272 :
273 : // If the row at index is a cert, return that cert. Otherwise, return null.
274 : already_AddRefed<nsCertTreeDispInfo>
275 0 : nsCertTree::GetDispInfoAtIndex(int32_t index,
276 : int32_t *outAbsoluteCertOffset)
277 : {
278 0 : int i, idx = 0, cIndex = 0, nc;
279 0 : if (index < 0) return nullptr;
280 : // Loop over the threads
281 0 : for (i=0; i<mNumOrgs; i++) {
282 0 : if (index == idx) return nullptr; // index is for thread
283 0 : idx++; // get past the thread
284 0 : nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
285 0 : if (index < idx + nc) { // cert is within range of this thread
286 0 : int32_t certIndex = cIndex + index - idx;
287 0 : if (outAbsoluteCertOffset)
288 0 : *outAbsoluteCertOffset = certIndex;
289 : RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
290 0 : nullptr));
291 0 : if (certdi) {
292 0 : return certdi.forget();
293 : }
294 0 : break;
295 : }
296 0 : if (mTreeArray[i].open)
297 0 : idx += mTreeArray[i].numChildren;
298 0 : cIndex += mTreeArray[i].numChildren;
299 0 : if (idx > index) break;
300 : }
301 0 : return nullptr;
302 : }
303 :
304 : nsCertTree::nsCertCompareFunc
305 0 : nsCertTree::GetCompareFuncFromCertType(uint32_t aType)
306 : {
307 0 : switch (aType) {
308 : case nsIX509Cert::ANY_CERT:
309 : case nsIX509Cert::USER_CERT:
310 0 : return CmpUserCert;
311 : case nsIX509Cert::CA_CERT:
312 0 : return CmpCACert;
313 : case nsIX509Cert::EMAIL_CERT:
314 0 : return CmpEmailCert;
315 : case nsIX509Cert::SERVER_CERT:
316 : default:
317 0 : return CmpWebSiteCert;
318 : }
319 : }
320 :
321 0 : struct nsCertAndArrayAndPositionAndCounterAndTracker
322 : {
323 : RefPtr<nsCertAddonInfo> certai;
324 : nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
325 : int position;
326 : int counter;
327 : nsTHashtable<nsCStringHashKey> *tracker;
328 : };
329 :
330 : // Used to enumerate host:port overrides that match a stored
331 : // certificate, creates and adds a display-info-object to the
332 : // provided array. Increments insert position and entry counter.
333 : // We remove the given key from the tracker, which is used to
334 : // track entries that have not yet been handled.
335 : // The created display-info references the cert, so make a note
336 : // of that by incrementing the cert usage counter.
337 : static void
338 0 : MatchingCertOverridesCallback(const nsCertOverride &aSettings,
339 : void *aUserData)
340 : {
341 : nsCertAndArrayAndPositionAndCounterAndTracker *cap =
342 0 : (nsCertAndArrayAndPositionAndCounterAndTracker*)aUserData;
343 0 : if (!cap)
344 0 : return;
345 :
346 0 : nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
347 0 : if (certdi) {
348 0 : if (cap->certai)
349 0 : cap->certai->mUsageCount++;
350 0 : certdi->mAddonInfo = cap->certai;
351 0 : certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
352 0 : certdi->mAsciiHost = aSettings.mAsciiHost;
353 0 : certdi->mPort = aSettings.mPort;
354 0 : certdi->mOverrideBits = aSettings.mOverrideBits;
355 0 : certdi->mIsTemporary = aSettings.mIsTemporary;
356 0 : certdi->mCert = aSettings.mCert;
357 0 : cap->array->InsertElementAt(cap->position, certdi);
358 0 : cap->position++;
359 0 : cap->counter++;
360 : }
361 :
362 : // this entry is now associated to a displayed cert, remove
363 : // it from the list of remaining entries
364 0 : nsAutoCString hostPort;
365 0 : nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
366 0 : cap->tracker->RemoveEntry(hostPort);
367 : }
368 :
369 : // Used to collect a list of the (unique) host:port keys
370 : // for all stored overrides.
371 : static void
372 0 : CollectAllHostPortOverridesCallback(const nsCertOverride &aSettings,
373 : void *aUserData)
374 : {
375 : nsTHashtable<nsCStringHashKey> *collectorTable =
376 0 : (nsTHashtable<nsCStringHashKey> *)aUserData;
377 0 : if (!collectorTable)
378 0 : return;
379 :
380 0 : nsAutoCString hostPort;
381 0 : nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
382 0 : collectorTable->PutEntry(hostPort);
383 : }
384 :
385 : struct nsArrayAndPositionAndCounterAndTracker
386 : {
387 : nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
388 : int position;
389 : int counter;
390 : nsTHashtable<nsCStringHashKey> *tracker;
391 : };
392 :
393 : // Used when enumerating the stored host:port overrides where
394 : // no associated certificate was found in the NSS database.
395 : static void
396 0 : AddRemaningHostPortOverridesCallback(const nsCertOverride &aSettings,
397 : void *aUserData)
398 : {
399 : nsArrayAndPositionAndCounterAndTracker *cap =
400 0 : (nsArrayAndPositionAndCounterAndTracker*)aUserData;
401 0 : if (!cap)
402 0 : return;
403 :
404 0 : nsAutoCString hostPort;
405 0 : nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
406 0 : if (!cap->tracker->GetEntry(hostPort))
407 0 : return;
408 :
409 : // This entry is not associated to any stored cert,
410 : // so we still need to display it.
411 :
412 0 : nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
413 0 : if (certdi) {
414 0 : certdi->mAddonInfo = nullptr;
415 0 : certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
416 0 : certdi->mAsciiHost = aSettings.mAsciiHost;
417 0 : certdi->mPort = aSettings.mPort;
418 0 : certdi->mOverrideBits = aSettings.mOverrideBits;
419 0 : certdi->mIsTemporary = aSettings.mIsTemporary;
420 0 : certdi->mCert = aSettings.mCert;
421 0 : cap->array->InsertElementAt(cap->position, certdi);
422 0 : cap->position++;
423 0 : cap->counter++;
424 : }
425 : }
426 :
427 : nsresult
428 0 : nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList,
429 : uint32_t aWantedType,
430 : nsCertCompareFunc aCertCmpFn,
431 : void *aCertCmpFnArg)
432 : {
433 0 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetCertsByTypeFromCertList"));
434 0 : if (!aCertList)
435 0 : return NS_ERROR_FAILURE;
436 :
437 0 : if (!mOriginalOverrideService)
438 0 : return NS_ERROR_FAILURE;
439 :
440 0 : nsTHashtable<nsCStringHashKey> allHostPortOverrideKeys;
441 :
442 0 : if (aWantedType == nsIX509Cert::SERVER_CERT) {
443 : mOriginalOverrideService->
444 0 : EnumerateCertOverrides(nullptr,
445 : CollectAllHostPortOverridesCallback,
446 0 : &allHostPortOverrideKeys);
447 : }
448 :
449 : CERTCertListNode *node;
450 0 : int count = 0;
451 0 : for (node = CERT_LIST_HEAD(aCertList);
452 0 : !CERT_LIST_END(node, aCertList);
453 0 : node = CERT_LIST_NEXT(node)) {
454 :
455 0 : bool wantThisCert = (aWantedType == nsIX509Cert::ANY_CERT);
456 0 : bool wantThisCertIfNoOverrides = false;
457 0 : bool wantThisCertIfHaveOverrides = false;
458 0 : bool addOverrides = false;
459 :
460 0 : if (!wantThisCert) {
461 0 : uint32_t thisCertType = getCertType(node->cert);
462 :
463 : // The output from getCertType is a "guess", which can be wrong.
464 : // The guess is based on stored trust flags, but for the host:port
465 : // overrides, we are storing certs without any trust flags associated.
466 : // So we must check whether the cert really belongs to the
467 : // server, email or unknown tab. We will lookup the cert in the override
468 : // list to come to the decision. Unfortunately, the lookup in the
469 : // override list is quite expensive. Therefore we are using this
470 : // lengthy if/else statement to minimize
471 : // the number of override-list-lookups.
472 :
473 0 : if (aWantedType == nsIX509Cert::SERVER_CERT
474 0 : && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
475 : // This unknown cert was stored without trust
476 : // Are there host:port based overrides stored?
477 : // If yes, display them.
478 0 : addOverrides = true;
479 : }
480 : else
481 0 : if (aWantedType == nsIX509Cert::UNKNOWN_CERT
482 0 : && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
483 : // This unknown cert was stored without trust.
484 : // If there are associated overrides, do not show as unknown.
485 : // If there are no associated overrides, display as unknown.
486 0 : wantThisCertIfNoOverrides = true;
487 : }
488 : else
489 0 : if (aWantedType == nsIX509Cert::SERVER_CERT
490 0 : && thisCertType == nsIX509Cert::SERVER_CERT) {
491 : // This server cert is explicitly marked as a web site peer,
492 : // with or without trust, but editable, so show it
493 0 : wantThisCert = true;
494 : // Are there host:port based overrides stored?
495 : // If yes, display them.
496 0 : addOverrides = true;
497 : }
498 : else
499 0 : if (aWantedType == nsIX509Cert::SERVER_CERT
500 0 : && thisCertType == nsIX509Cert::EMAIL_CERT) {
501 : // This cert might have been categorized as an email cert
502 : // because it carries an email address. But is it really one?
503 : // Our cert categorization is uncertain when it comes to
504 : // distinguish between email certs and web site certs.
505 : // So, let's see if we have an override for that cert
506 : // and if there is, conclude it's really a web site cert.
507 0 : addOverrides = true;
508 : }
509 : else
510 0 : if (aWantedType == nsIX509Cert::EMAIL_CERT
511 0 : && thisCertType == nsIX509Cert::EMAIL_CERT) {
512 : // This cert might have been categorized as an email cert
513 : // because it carries an email address. But is it really one?
514 : // Our cert categorization is uncertain when it comes to
515 : // distinguish between email certs and web site certs.
516 : // So, let's see if we have an override for that cert
517 : // and if there is, conclude it's really a web site cert.
518 0 : wantThisCertIfNoOverrides = true;
519 : }
520 : else
521 0 : if (thisCertType == aWantedType) {
522 0 : wantThisCert = true;
523 : }
524 : }
525 :
526 0 : nsCOMPtr<nsIX509Cert> pipCert = nsNSSCertificate::Create(node->cert);
527 0 : if (!pipCert)
528 0 : return NS_ERROR_OUT_OF_MEMORY;
529 :
530 0 : if (wantThisCertIfNoOverrides || wantThisCertIfHaveOverrides) {
531 0 : uint32_t ocount = 0;
532 : nsresult rv =
533 0 : mOverrideService->IsCertUsedForOverrides(pipCert,
534 : true, // we want temporaries
535 : true, // we want permanents
536 0 : &ocount);
537 0 : if (wantThisCertIfNoOverrides) {
538 0 : if (NS_FAILED(rv) || ocount == 0) {
539 : // no overrides for this cert
540 0 : wantThisCert = true;
541 : }
542 : }
543 :
544 0 : if (wantThisCertIfHaveOverrides) {
545 0 : if (NS_SUCCEEDED(rv) && ocount > 0) {
546 : // there are overrides for this cert
547 0 : wantThisCert = true;
548 : }
549 : }
550 : }
551 :
552 0 : RefPtr<nsCertAddonInfo> certai(new nsCertAddonInfo);
553 0 : certai->mCert = pipCert;
554 0 : certai->mUsageCount = 0;
555 :
556 0 : if (wantThisCert || addOverrides) {
557 0 : int InsertPosition = 0;
558 0 : for (; InsertPosition < count; ++InsertPosition) {
559 0 : nsCOMPtr<nsIX509Cert> cert = nullptr;
560 : RefPtr<nsCertTreeDispInfo> elem(
561 0 : mDispInfo.SafeElementAt(InsertPosition, nullptr));
562 0 : if (elem && elem->mAddonInfo) {
563 0 : cert = elem->mAddonInfo->mCert;
564 : }
565 0 : if ((*aCertCmpFn)(aCertCmpFnArg, pipCert, cert) < 0) {
566 0 : break;
567 : }
568 : }
569 0 : if (wantThisCert) {
570 0 : nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
571 0 : certdi->mAddonInfo = certai;
572 0 : certai->mUsageCount++;
573 0 : certdi->mTypeOfEntry = nsCertTreeDispInfo::direct_db;
574 : // not necessary: certdi->mAsciiHost.Clear(); certdi->mPort = -1;
575 0 : certdi->mOverrideBits = nsCertOverride::OverrideBits::None;
576 0 : certdi->mIsTemporary = false;
577 0 : mDispInfo.InsertElementAt(InsertPosition, certdi);
578 0 : ++count;
579 0 : ++InsertPosition;
580 : }
581 0 : if (addOverrides) {
582 0 : nsCertAndArrayAndPositionAndCounterAndTracker cap;
583 0 : cap.certai = certai;
584 0 : cap.array = &mDispInfo;
585 0 : cap.position = InsertPosition;
586 0 : cap.counter = 0;
587 0 : cap.tracker = &allHostPortOverrideKeys;
588 :
589 : mOriginalOverrideService->
590 0 : EnumerateCertOverrides(pipCert, MatchingCertOverridesCallback, &cap);
591 0 : count += cap.counter;
592 : }
593 : }
594 : }
595 :
596 0 : if (aWantedType == nsIX509Cert::SERVER_CERT) {
597 : nsArrayAndPositionAndCounterAndTracker cap;
598 0 : cap.array = &mDispInfo;
599 0 : cap.position = 0;
600 0 : cap.counter = 0;
601 0 : cap.tracker = &allHostPortOverrideKeys;
602 : mOriginalOverrideService->
603 0 : EnumerateCertOverrides(nullptr, AddRemaningHostPortOverridesCallback, &cap);
604 : }
605 :
606 0 : return NS_OK;
607 : }
608 :
609 : nsresult
610 0 : nsCertTree::GetCertsByType(uint32_t aType,
611 : nsCertCompareFunc aCertCmpFn,
612 : void *aCertCmpFnArg)
613 : {
614 0 : nsNSSShutDownPreventionLock locker;
615 0 : nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
616 0 : UniqueCERTCertList certList(PK11_ListCerts(PK11CertListUnique, cxt));
617 0 : return GetCertsByTypeFromCertList(certList.get(), aType, aCertCmpFn,
618 0 : aCertCmpFnArg);
619 : }
620 :
621 : nsresult
622 0 : nsCertTree::GetCertsByTypeFromCache(nsIX509CertList *aCache,
623 : uint32_t aType,
624 : nsCertCompareFunc aCertCmpFn,
625 : void *aCertCmpFnArg)
626 : {
627 0 : NS_ENSURE_ARG_POINTER(aCache);
628 : // GetRawCertList checks for NSS shutdown since we can't do it ourselves here
629 : // easily. We still have to acquire a shutdown prevention lock to prevent NSS
630 : // shutting down after GetRawCertList has returned. While cumbersome, this is
631 : // at least mostly correct. The rest of this implementation doesn't even go
632 : // this far in attempting to check for or prevent NSS shutdown at the
633 : // appropriate times. If this were reimplemented at a higher level using
634 : // more encapsulated types that handled NSS shutdown themselves, we wouldn't
635 : // be having these kinds of problems.
636 0 : nsNSSShutDownPreventionLock locker;
637 0 : CERTCertList* certList = aCache->GetRawCertList();
638 0 : if (!certList)
639 0 : return NS_ERROR_FAILURE;
640 0 : return GetCertsByTypeFromCertList(certList, aType, aCertCmpFn, aCertCmpFnArg);
641 : }
642 :
643 : // LoadCerts
644 : //
645 : // Load all of the certificates in the DB for this type. Sort them
646 : // by token, organization, then common name.
647 : NS_IMETHODIMP
648 0 : nsCertTree::LoadCertsFromCache(nsIX509CertList *aCache, uint32_t aType)
649 : {
650 0 : if (mTreeArray) {
651 0 : FreeCertArray();
652 0 : delete [] mTreeArray;
653 0 : mTreeArray = nullptr;
654 0 : mNumRows = 0;
655 : }
656 0 : ClearCompareHash();
657 :
658 0 : nsresult rv = GetCertsByTypeFromCache(aCache, aType,
659 : GetCompareFuncFromCertType(aType),
660 0 : &mCompareCache);
661 0 : if (NS_FAILED(rv)) return rv;
662 0 : return UpdateUIContents();
663 : }
664 :
665 : NS_IMETHODIMP
666 0 : nsCertTree::LoadCerts(uint32_t aType)
667 : {
668 0 : if (mTreeArray) {
669 0 : FreeCertArray();
670 0 : delete [] mTreeArray;
671 0 : mTreeArray = nullptr;
672 0 : mNumRows = 0;
673 : }
674 0 : ClearCompareHash();
675 :
676 0 : nsresult rv = GetCertsByType(aType, GetCompareFuncFromCertType(aType),
677 0 : &mCompareCache);
678 0 : if (NS_FAILED(rv)) return rv;
679 0 : return UpdateUIContents();
680 : }
681 :
682 : nsresult
683 0 : nsCertTree::UpdateUIContents()
684 : {
685 0 : uint32_t count = mDispInfo.Length();
686 0 : mNumOrgs = CountOrganizations();
687 0 : mTreeArray = new treeArrayEl[mNumOrgs];
688 :
689 0 : mCellText = nsArrayBase::Create();
690 :
691 0 : if (count) {
692 0 : uint32_t j = 0;
693 0 : nsCOMPtr<nsIX509Cert> orgCert = nullptr;
694 0 : nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(j)->mAddonInfo;
695 0 : if (addonInfo) {
696 0 : orgCert = addonInfo->mCert;
697 : }
698 0 : for (int32_t i=0; i<mNumOrgs; i++) {
699 0 : nsString &orgNameRef = mTreeArray[i].orgName;
700 0 : if (!orgCert) {
701 0 : mNSSComponent->GetPIPNSSBundleString("CertOrgUnknown", orgNameRef);
702 : }
703 : else {
704 0 : orgCert->GetIssuerOrganization(orgNameRef);
705 0 : if (orgNameRef.IsEmpty())
706 0 : orgCert->GetCommonName(orgNameRef);
707 : }
708 0 : mTreeArray[i].open = true;
709 0 : mTreeArray[i].certIndex = j;
710 0 : mTreeArray[i].numChildren = 1;
711 0 : if (++j >= count) break;
712 0 : nsCOMPtr<nsIX509Cert> nextCert = nullptr;
713 0 : nsCertAddonInfo *addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
714 0 : if (addonInfo) {
715 0 : nextCert = addonInfo->mCert;
716 : }
717 0 : while (0 == CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None)) {
718 0 : mTreeArray[i].numChildren++;
719 0 : if (++j >= count) break;
720 0 : nextCert = nullptr;
721 0 : addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
722 0 : if (addonInfo) {
723 0 : nextCert = addonInfo->mCert;
724 : }
725 : }
726 0 : orgCert = nextCert;
727 : }
728 : }
729 0 : if (mTree) {
730 0 : mTree->BeginUpdateBatch();
731 0 : mTree->RowCountChanged(0, -mNumRows);
732 : }
733 0 : mNumRows = count + mNumOrgs;
734 0 : if (mTree)
735 0 : mTree->EndUpdateBatch();
736 0 : return NS_OK;
737 : }
738 :
739 : NS_IMETHODIMP
740 0 : nsCertTree::DeleteEntryObject(uint32_t index)
741 : {
742 0 : if (!mTreeArray) {
743 0 : return NS_ERROR_FAILURE;
744 : }
745 :
746 : nsCOMPtr<nsIX509CertDB> certdb =
747 0 : do_GetService("@mozilla.org/security/x509certdb;1");
748 0 : if (!certdb) {
749 0 : return NS_ERROR_FAILURE;
750 : }
751 :
752 : int i;
753 0 : uint32_t idx = 0, cIndex = 0, nc;
754 : // Loop over the threads
755 0 : for (i=0; i<mNumOrgs; i++) {
756 0 : if (index == idx)
757 0 : return NS_OK; // index is for thread
758 0 : idx++; // get past the thread
759 0 : nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
760 0 : if (index < idx + nc) { // cert is within range of this thread
761 0 : int32_t certIndex = cIndex + index - idx;
762 :
763 0 : bool canRemoveEntry = false;
764 : RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
765 0 : nullptr));
766 :
767 : // We will remove the element from the visual tree.
768 : // Only if we have a certdi, then we can check for additional actions.
769 0 : nsCOMPtr<nsIX509Cert> cert = nullptr;
770 0 : if (certdi) {
771 0 : if (certdi->mAddonInfo) {
772 0 : cert = certdi->mAddonInfo->mCert;
773 : }
774 : nsCertAddonInfo* addonInfo =
775 0 : certdi->mAddonInfo ? certdi->mAddonInfo.get() : nullptr;
776 0 : if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
777 0 : mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort);
778 0 : if (addonInfo) {
779 0 : addonInfo->mUsageCount--;
780 0 : if (addonInfo->mUsageCount == 0) {
781 : // The certificate stored in the database is no longer
782 : // referenced by any other object displayed.
783 : // That means we no longer need to keep it around
784 : // and really can remove it.
785 0 : canRemoveEntry = true;
786 : }
787 : }
788 : }
789 : else {
790 0 : if (addonInfo && addonInfo->mUsageCount > 1) {
791 : // user is trying to delete a perm trusted cert,
792 : // although there are still overrides stored,
793 : // so, we keep the cert, but remove the trust
794 :
795 0 : UniqueCERTCertificate nsscert(cert->GetCert());
796 :
797 0 : if (nsscert) {
798 : CERTCertTrust trust;
799 0 : memset((void*)&trust, 0, sizeof(trust));
800 :
801 0 : SECStatus srv = CERT_DecodeTrustString(&trust, ""); // no override
802 0 : if (srv == SECSuccess) {
803 0 : CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert.get(),
804 0 : &trust);
805 : }
806 0 : }
807 : }
808 : else {
809 0 : canRemoveEntry = true;
810 : }
811 : }
812 : }
813 :
814 0 : mDispInfo.RemoveElementAt(certIndex);
815 :
816 0 : if (canRemoveEntry) {
817 0 : RemoveCacheEntry(cert);
818 0 : certdb->DeleteCertificate(cert);
819 : }
820 :
821 0 : delete [] mTreeArray;
822 0 : mTreeArray = nullptr;
823 0 : return UpdateUIContents();
824 : }
825 0 : if (mTreeArray[i].open)
826 0 : idx += mTreeArray[i].numChildren;
827 0 : cIndex += mTreeArray[i].numChildren;
828 0 : if (idx > index)
829 0 : break;
830 : }
831 0 : return NS_ERROR_FAILURE;
832 : }
833 :
834 : //////////////////////////////////////////////////////////////////////////////
835 : //
836 : // Begin nsITreeView methods
837 : //
838 : /////////////////////////////////////////////////////////////////////////////
839 :
840 : NS_IMETHODIMP
841 0 : nsCertTree::GetCert(uint32_t aIndex, nsIX509Cert **_cert)
842 : {
843 0 : NS_ENSURE_ARG(_cert);
844 0 : *_cert = GetCertAtIndex(aIndex).take();
845 0 : return NS_OK;
846 : }
847 :
848 : NS_IMETHODIMP
849 0 : nsCertTree::GetTreeItem(uint32_t aIndex, nsICertTreeItem **_treeitem)
850 : {
851 0 : NS_ENSURE_ARG(_treeitem);
852 :
853 0 : RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex));
854 0 : if (!certdi)
855 0 : return NS_ERROR_FAILURE;
856 :
857 0 : *_treeitem = certdi;
858 0 : NS_IF_ADDREF(*_treeitem);
859 0 : return NS_OK;
860 : }
861 :
862 : NS_IMETHODIMP
863 0 : nsCertTree::GetRowCount(int32_t *aRowCount)
864 : {
865 0 : if (!mTreeArray)
866 0 : return NS_ERROR_NOT_INITIALIZED;
867 0 : uint32_t count = 0;
868 0 : for (int32_t i=0; i<mNumOrgs; i++) {
869 0 : if (mTreeArray[i].open) {
870 0 : count += mTreeArray[i].numChildren;
871 : }
872 0 : count++;
873 : }
874 0 : *aRowCount = count;
875 0 : return NS_OK;
876 : }
877 :
878 : NS_IMETHODIMP
879 0 : nsCertTree::GetSelection(nsITreeSelection * *aSelection)
880 : {
881 0 : *aSelection = mSelection;
882 0 : NS_IF_ADDREF(*aSelection);
883 0 : return NS_OK;
884 : }
885 :
886 : NS_IMETHODIMP
887 0 : nsCertTree::SetSelection(nsITreeSelection * aSelection)
888 : {
889 0 : mSelection = aSelection;
890 0 : return NS_OK;
891 : }
892 :
893 : NS_IMETHODIMP
894 0 : nsCertTree::GetRowProperties(int32_t index, nsAString& aProps)
895 : {
896 0 : return NS_OK;
897 : }
898 :
899 : NS_IMETHODIMP
900 0 : nsCertTree::GetCellProperties(int32_t row, nsITreeColumn* col,
901 : nsAString& aProps)
902 : {
903 0 : return NS_OK;
904 : }
905 :
906 : NS_IMETHODIMP
907 0 : nsCertTree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
908 : {
909 0 : return NS_OK;
910 : }
911 : NS_IMETHODIMP
912 0 : nsCertTree::IsContainer(int32_t index, bool *_retval)
913 : {
914 0 : if (!mTreeArray)
915 0 : return NS_ERROR_NOT_INITIALIZED;
916 0 : treeArrayEl *el = GetThreadDescAtIndex(index);
917 0 : if (el) {
918 0 : *_retval = true;
919 : } else {
920 0 : *_retval = false;
921 : }
922 0 : return NS_OK;
923 : }
924 :
925 : NS_IMETHODIMP
926 0 : nsCertTree::IsContainerOpen(int32_t index, bool *_retval)
927 : {
928 0 : if (!mTreeArray)
929 0 : return NS_ERROR_NOT_INITIALIZED;
930 0 : treeArrayEl *el = GetThreadDescAtIndex(index);
931 0 : if (el && el->open) {
932 0 : *_retval = true;
933 : } else {
934 0 : *_retval = false;
935 : }
936 0 : return NS_OK;
937 : }
938 :
939 : NS_IMETHODIMP
940 0 : nsCertTree::IsContainerEmpty(int32_t index, bool *_retval)
941 : {
942 0 : *_retval = !mTreeArray;
943 0 : return NS_OK;
944 : }
945 :
946 : NS_IMETHODIMP
947 0 : nsCertTree::IsSeparator(int32_t index, bool *_retval)
948 : {
949 0 : *_retval = false;
950 0 : return NS_OK;
951 : }
952 :
953 : NS_IMETHODIMP
954 0 : nsCertTree::GetParentIndex(int32_t rowIndex, int32_t *_retval)
955 : {
956 0 : if (!mTreeArray)
957 0 : return NS_ERROR_NOT_INITIALIZED;
958 0 : int i, idx = 0;
959 0 : for (i = 0; i < mNumOrgs && idx < rowIndex; i++, idx++) {
960 0 : if (mTreeArray[i].open) {
961 0 : if (rowIndex <= idx + mTreeArray[i].numChildren) {
962 0 : *_retval = idx;
963 0 : return NS_OK;
964 : }
965 0 : idx += mTreeArray[i].numChildren;
966 : }
967 : }
968 0 : *_retval = -1;
969 0 : return NS_OK;
970 : }
971 :
972 : NS_IMETHODIMP
973 0 : nsCertTree::HasNextSibling(int32_t rowIndex, int32_t afterIndex,
974 : bool *_retval)
975 : {
976 0 : if (!mTreeArray)
977 0 : return NS_ERROR_NOT_INITIALIZED;
978 :
979 0 : int i, idx = 0;
980 0 : for (i = 0; i < mNumOrgs && idx <= rowIndex; i++, idx++) {
981 0 : if (mTreeArray[i].open) {
982 0 : idx += mTreeArray[i].numChildren;
983 0 : if (afterIndex <= idx) {
984 0 : *_retval = afterIndex < idx;
985 0 : return NS_OK;
986 : }
987 : }
988 : }
989 0 : *_retval = false;
990 0 : return NS_OK;
991 : }
992 :
993 : NS_IMETHODIMP
994 0 : nsCertTree::GetLevel(int32_t index, int32_t *_retval)
995 : {
996 0 : if (!mTreeArray)
997 0 : return NS_ERROR_NOT_INITIALIZED;
998 0 : treeArrayEl *el = GetThreadDescAtIndex(index);
999 0 : if (el) {
1000 0 : *_retval = 0;
1001 : } else {
1002 0 : *_retval = 1;
1003 : }
1004 0 : return NS_OK;
1005 : }
1006 :
1007 : NS_IMETHODIMP
1008 0 : nsCertTree::GetImageSrc(int32_t row, nsITreeColumn* col,
1009 : nsAString& _retval)
1010 : {
1011 0 : _retval.Truncate();
1012 0 : return NS_OK;
1013 : }
1014 :
1015 : NS_IMETHODIMP
1016 0 : nsCertTree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
1017 : {
1018 0 : return NS_OK;
1019 : }
1020 :
1021 : NS_IMETHODIMP
1022 0 : nsCertTree::GetCellValue(int32_t row, nsITreeColumn* col,
1023 : nsAString& _retval)
1024 : {
1025 0 : _retval.Truncate();
1026 0 : return NS_OK;
1027 : }
1028 :
1029 : NS_IMETHODIMP
1030 0 : nsCertTree::GetCellText(int32_t row, nsITreeColumn* col,
1031 : nsAString& _retval)
1032 : {
1033 0 : if (!mTreeArray)
1034 0 : return NS_ERROR_NOT_INITIALIZED;
1035 :
1036 0 : nsresult rv = NS_OK;
1037 0 : _retval.Truncate();
1038 :
1039 : const char16_t* colID;
1040 0 : col->GetIdConst(&colID);
1041 :
1042 0 : treeArrayEl *el = GetThreadDescAtIndex(row);
1043 0 : if (el) {
1044 0 : if (NS_LITERAL_STRING("certcol").Equals(colID))
1045 0 : _retval.Assign(el->orgName);
1046 : else
1047 0 : _retval.Truncate();
1048 0 : return NS_OK;
1049 : }
1050 :
1051 : int32_t absoluteCertOffset;
1052 0 : RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(row, &absoluteCertOffset));
1053 0 : if (!certdi)
1054 0 : return NS_ERROR_FAILURE;
1055 :
1056 0 : nsCOMPtr<nsIX509Cert> cert = certdi->mCert;
1057 0 : if (!cert && certdi->mAddonInfo) {
1058 0 : cert = certdi->mAddonInfo->mCert;
1059 : }
1060 :
1061 : int32_t colIndex;
1062 0 : col->GetIndex(&colIndex);
1063 0 : uint32_t arrayIndex=absoluteCertOffset+colIndex*(mNumRows-mNumOrgs);
1064 0 : uint32_t arrayLength=0;
1065 0 : if (mCellText) {
1066 0 : mCellText->GetLength(&arrayLength);
1067 : }
1068 0 : if (arrayIndex < arrayLength) {
1069 0 : nsCOMPtr<nsISupportsString> myString(do_QueryElementAt(mCellText, arrayIndex));
1070 0 : if (myString) {
1071 0 : myString->GetData(_retval);
1072 0 : return NS_OK;
1073 : }
1074 : }
1075 :
1076 0 : if (NS_LITERAL_STRING("certcol").Equals(colID)) {
1077 0 : if (!cert) {
1078 0 : rv = mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval);
1079 : } else {
1080 0 : rv = cert->GetDisplayName(_retval);
1081 : }
1082 0 : } else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) {
1083 0 : rv = cert->GetTokenName(_retval);
1084 0 : } else if (NS_LITERAL_STRING("emailcol").Equals(colID) && cert) {
1085 0 : rv = cert->GetEmailAddress(_retval);
1086 0 : } else if (NS_LITERAL_STRING("issuedcol").Equals(colID) && cert) {
1087 0 : nsCOMPtr<nsIX509CertValidity> validity;
1088 :
1089 0 : rv = cert->GetValidity(getter_AddRefs(validity));
1090 0 : if (NS_SUCCEEDED(rv)) {
1091 0 : validity->GetNotBeforeLocalDay(_retval);
1092 : }
1093 0 : } else if (NS_LITERAL_STRING("expiredcol").Equals(colID) && cert) {
1094 0 : nsCOMPtr<nsIX509CertValidity> validity;
1095 :
1096 0 : rv = cert->GetValidity(getter_AddRefs(validity));
1097 0 : if (NS_SUCCEEDED(rv)) {
1098 0 : validity->GetNotAfterLocalDay(_retval);
1099 : }
1100 0 : } else if (NS_LITERAL_STRING("serialnumcol").Equals(colID) && cert) {
1101 0 : rv = cert->GetSerialNumber(_retval);
1102 0 : } else if (NS_LITERAL_STRING("sitecol").Equals(colID)) {
1103 0 : if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
1104 0 : nsAutoCString hostPort;
1105 0 : nsCertOverrideService::GetHostWithPort(certdi->mAsciiHost, certdi->mPort, hostPort);
1106 0 : _retval = NS_ConvertUTF8toUTF16(hostPort);
1107 : }
1108 : else {
1109 0 : _retval = NS_LITERAL_STRING("*");
1110 : }
1111 0 : } else if (NS_LITERAL_STRING("lifetimecol").Equals(colID)) {
1112 : const char *stringID =
1113 0 : (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
1114 0 : rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
1115 : } else {
1116 0 : return NS_ERROR_FAILURE;
1117 : }
1118 0 : if (mCellText) {
1119 0 : nsCOMPtr<nsISupportsString> text(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
1120 0 : NS_ENSURE_SUCCESS(rv, rv);
1121 0 : text->SetData(_retval);
1122 0 : mCellText->ReplaceElementAt(text, arrayIndex, false);
1123 : }
1124 0 : return rv;
1125 : }
1126 :
1127 : NS_IMETHODIMP
1128 0 : nsCertTree::SetTree(nsITreeBoxObject *tree)
1129 : {
1130 0 : mTree = tree;
1131 0 : return NS_OK;
1132 : }
1133 :
1134 : NS_IMETHODIMP
1135 0 : nsCertTree::ToggleOpenState(int32_t index)
1136 : {
1137 0 : if (!mTreeArray)
1138 0 : return NS_ERROR_NOT_INITIALIZED;
1139 0 : treeArrayEl *el = GetThreadDescAtIndex(index);
1140 0 : if (el) {
1141 0 : el->open = !el->open;
1142 0 : int32_t newChildren = (el->open) ? el->numChildren : -el->numChildren;
1143 0 : if (mTree) mTree->RowCountChanged(index + 1, newChildren);
1144 : }
1145 0 : return NS_OK;
1146 : }
1147 :
1148 : NS_IMETHODIMP
1149 0 : nsCertTree::CycleHeader(nsITreeColumn* col)
1150 : {
1151 0 : return NS_OK;
1152 : }
1153 :
1154 : NS_IMETHODIMP
1155 0 : nsCertTree::SelectionChanged()
1156 : {
1157 0 : return NS_ERROR_NOT_IMPLEMENTED;
1158 : }
1159 :
1160 : NS_IMETHODIMP
1161 0 : nsCertTree::CycleCell(int32_t row, nsITreeColumn* col)
1162 : {
1163 0 : return NS_OK;
1164 : }
1165 :
1166 : NS_IMETHODIMP
1167 0 : nsCertTree::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval)
1168 : {
1169 0 : *_retval = false;
1170 0 : return NS_OK;
1171 : }
1172 :
1173 : NS_IMETHODIMP
1174 0 : nsCertTree::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval)
1175 : {
1176 0 : *_retval = false;
1177 0 : return NS_OK;
1178 : }
1179 :
1180 : NS_IMETHODIMP
1181 0 : nsCertTree::SetCellValue(int32_t row, nsITreeColumn* col,
1182 : const nsAString& value)
1183 : {
1184 0 : return NS_OK;
1185 : }
1186 :
1187 : NS_IMETHODIMP
1188 0 : nsCertTree::SetCellText(int32_t row, nsITreeColumn* col,
1189 : const nsAString& value)
1190 : {
1191 0 : return NS_OK;
1192 : }
1193 :
1194 : NS_IMETHODIMP
1195 0 : nsCertTree::PerformAction(const char16_t *action)
1196 : {
1197 0 : return NS_OK;
1198 : }
1199 :
1200 : NS_IMETHODIMP
1201 0 : nsCertTree::PerformActionOnRow(const char16_t *action, int32_t row)
1202 : {
1203 0 : return NS_OK;
1204 : }
1205 :
1206 : NS_IMETHODIMP
1207 0 : nsCertTree::PerformActionOnCell(const char16_t *action, int32_t row,
1208 : nsITreeColumn* col)
1209 : {
1210 0 : return NS_OK;
1211 : }
1212 :
1213 : #ifdef DEBUG_CERT_TREE
1214 : void
1215 : nsCertTree::dumpMap()
1216 : {
1217 : for (int i=0; i<mNumOrgs; i++) {
1218 : nsAutoString org(mTreeArray[i].orgName);
1219 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("ORG[%s]", NS_LossyConvertUTF16toASCII(org).get()));
1220 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("OPEN[%d]", mTreeArray[i].open));
1221 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("INDEX[%d]", mTreeArray[i].certIndex));
1222 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NCHILD[%d]", mTreeArray[i].numChildren));
1223 : }
1224 : for (int i=0; i<mNumRows; i++) {
1225 : treeArrayEl *el = GetThreadDescAtIndex(i);
1226 : if (el) {
1227 : nsAutoString td(el->orgName);
1228 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("thread desc[%d]: %s", i, NS_LossyConvertUTF16toASCII(td).get()));
1229 : }
1230 : nsCOMPtr<nsIX509Cert> ct = GetCertAtIndex(i);
1231 : if (ct) {
1232 : char16_t *goo;
1233 : ct->GetCommonName(&goo);
1234 : nsAutoString doo(goo);
1235 : MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("cert [%d]: %s", i, NS_LossyConvertUTF16toASCII(doo).get()));
1236 : }
1237 : }
1238 : }
1239 : #endif
1240 :
1241 : //
1242 : // CanDrop
1243 : //
1244 0 : NS_IMETHODIMP nsCertTree::CanDrop(int32_t index, int32_t orientation,
1245 : nsIDOMDataTransfer* aDataTransfer, bool *_retval)
1246 : {
1247 0 : NS_ENSURE_ARG_POINTER(_retval);
1248 0 : *_retval = false;
1249 :
1250 0 : return NS_OK;
1251 : }
1252 :
1253 :
1254 : //
1255 : // Drop
1256 : //
1257 0 : NS_IMETHODIMP nsCertTree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer)
1258 : {
1259 0 : return NS_OK;
1260 : }
1261 :
1262 :
1263 : //
1264 : // IsSorted
1265 : //
1266 : // ...
1267 : //
1268 0 : NS_IMETHODIMP nsCertTree::IsSorted(bool *_retval)
1269 : {
1270 0 : *_retval = false;
1271 0 : return NS_OK;
1272 : }
1273 :
1274 : #define RETURN_NOTHING
1275 :
1276 : void
1277 0 : nsCertTree::CmpInitCriterion(nsIX509Cert *cert, CompareCacheHashEntry *entry,
1278 : sortCriterion crit, int32_t level)
1279 : {
1280 0 : NS_ENSURE_TRUE(cert && entry, RETURN_NOTHING);
1281 :
1282 0 : entry->mCritInit[level] = true;
1283 0 : nsXPIDLString &str = entry->mCrit[level];
1284 :
1285 0 : switch (crit) {
1286 : case sort_IssuerOrg:
1287 0 : cert->GetIssuerOrganization(str);
1288 0 : if (str.IsEmpty())
1289 0 : cert->GetCommonName(str);
1290 0 : break;
1291 : case sort_Org:
1292 0 : cert->GetOrganization(str);
1293 0 : break;
1294 : case sort_Token:
1295 0 : cert->GetTokenName(str);
1296 0 : break;
1297 : case sort_CommonName:
1298 0 : cert->GetCommonName(str);
1299 0 : break;
1300 : case sort_IssuedDateDescending:
1301 : {
1302 : nsresult rv;
1303 0 : nsCOMPtr<nsIX509CertValidity> validity;
1304 : PRTime notBefore;
1305 :
1306 0 : rv = cert->GetValidity(getter_AddRefs(validity));
1307 0 : if (NS_SUCCEEDED(rv)) {
1308 0 : rv = validity->GetNotBefore(¬Before);
1309 : }
1310 :
1311 0 : if (NS_SUCCEEDED(rv)) {
1312 : PRExplodedTime explodedTime;
1313 0 : PR_ExplodeTime(notBefore, PR_GMTParameters, &explodedTime);
1314 : char datebuf[20]; // 4 + 2 + 2 + 2 + 2 + 2 + 1 = 15
1315 0 : if (0 != PR_FormatTime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", &explodedTime)) {
1316 0 : str = NS_ConvertASCIItoUTF16(nsDependentCString(datebuf));
1317 : }
1318 : }
1319 : }
1320 0 : break;
1321 : case sort_Email:
1322 0 : cert->GetEmailAddress(str);
1323 0 : break;
1324 : case sort_None:
1325 : default:
1326 0 : break;
1327 : }
1328 : }
1329 :
1330 : int32_t
1331 0 : nsCertTree::CmpByCrit(nsIX509Cert *a, CompareCacheHashEntry *ace,
1332 : nsIX509Cert *b, CompareCacheHashEntry *bce,
1333 : sortCriterion crit, int32_t level)
1334 : {
1335 0 : NS_ENSURE_TRUE(a && ace && b && bce, 0);
1336 :
1337 0 : if (!ace->mCritInit[level]) {
1338 0 : CmpInitCriterion(a, ace, crit, level);
1339 : }
1340 :
1341 0 : if (!bce->mCritInit[level]) {
1342 0 : CmpInitCriterion(b, bce, crit, level);
1343 : }
1344 :
1345 0 : nsXPIDLString &str_a = ace->mCrit[level];
1346 0 : nsXPIDLString &str_b = bce->mCrit[level];
1347 :
1348 : int32_t result;
1349 0 : if (str_a && str_b)
1350 0 : result = Compare(str_a, str_b, nsCaseInsensitiveStringComparator());
1351 : else
1352 0 : result = !str_a ? (!str_b ? 0 : -1) : 1;
1353 :
1354 0 : if (sort_IssuedDateDescending == crit)
1355 0 : result *= -1; // reverse compare order
1356 :
1357 0 : return result;
1358 : }
1359 :
1360 : int32_t
1361 0 : nsCertTree::CmpBy(void *cache, nsIX509Cert *a, nsIX509Cert *b,
1362 : sortCriterion c0, sortCriterion c1, sortCriterion c2)
1363 : {
1364 : // This will be called when comparing items for display sorting.
1365 : // Some items might have no cert associated, so either a or b is null.
1366 : // We want all those orphans show at the top of the list,
1367 : // so we treat a null cert as "smaller" by returning -1.
1368 : // We don't try to sort within the group of no-cert entries,
1369 : // so we treat them as equal wrt sort order.
1370 :
1371 0 : if (!a && !b)
1372 0 : return 0;
1373 :
1374 0 : if (!a)
1375 0 : return -1;
1376 :
1377 0 : if (!b)
1378 0 : return 1;
1379 :
1380 0 : NS_ENSURE_TRUE(cache && a && b, 0);
1381 :
1382 0 : CompareCacheHashEntry *ace = getCacheEntry(cache, a);
1383 0 : CompareCacheHashEntry *bce = getCacheEntry(cache, b);
1384 :
1385 : int32_t cmp;
1386 0 : cmp = CmpByCrit(a, ace, b, bce, c0, 0);
1387 0 : if (cmp != 0)
1388 0 : return cmp;
1389 :
1390 0 : if (c1 != sort_None) {
1391 0 : cmp = CmpByCrit(a, ace, b, bce, c1, 1);
1392 0 : if (cmp != 0)
1393 0 : return cmp;
1394 :
1395 0 : if (c2 != sort_None) {
1396 0 : return CmpByCrit(a, ace, b, bce, c2, 2);
1397 : }
1398 : }
1399 :
1400 0 : return cmp;
1401 : }
1402 :
1403 : int32_t
1404 0 : nsCertTree::CmpCACert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
1405 : {
1406 : // XXX we assume issuer org is always criterion 1
1407 0 : return CmpBy(cache, a, b, sort_IssuerOrg, sort_Org, sort_Token);
1408 : }
1409 :
1410 : int32_t
1411 0 : nsCertTree::CmpWebSiteCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
1412 : {
1413 : // XXX we assume issuer org is always criterion 1
1414 0 : return CmpBy(cache, a, b, sort_IssuerOrg, sort_CommonName, sort_None);
1415 : }
1416 :
1417 : int32_t
1418 0 : nsCertTree::CmpUserCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
1419 : {
1420 : // XXX we assume issuer org is always criterion 1
1421 0 : return CmpBy(cache, a, b, sort_IssuerOrg, sort_Token, sort_IssuedDateDescending);
1422 : }
1423 :
1424 : int32_t
1425 0 : nsCertTree::CmpEmailCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
1426 : {
1427 : // XXX we assume issuer org is always criterion 1
1428 0 : return CmpBy(cache, a, b, sort_IssuerOrg, sort_Email, sort_CommonName);
1429 : }
1430 :
|