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