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