nsCertTree.cpp 40 KB

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