Coverage Report

Created: 2018-09-25 14:53

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