nsNSSCertificateDB.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  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 "nsNSSCertificateDB.h"
  5. #include "CertVerifier.h"
  6. #include "CryptoTask.h"
  7. #include "ExtendedValidation.h"
  8. #include "NSSCertDBTrustDomain.h"
  9. #include "SharedSSLState.h"
  10. #include "certdb.h"
  11. #include "mozilla/Base64.h"
  12. #include "mozilla/Casting.h"
  13. #include "mozilla/Unused.h"
  14. #include "nsArray.h"
  15. #include "nsArrayUtils.h"
  16. #include "nsCOMPtr.h"
  17. #include "nsCRT.h"
  18. #include "nsComponentManagerUtils.h"
  19. #include "nsICertificateDialogs.h"
  20. #include "nsIFile.h"
  21. #include "nsIMutableArray.h"
  22. #include "nsIObserverService.h"
  23. #include "nsIPrefBranch.h"
  24. #include "nsIPrefService.h"
  25. #include "nsIPrompt.h"
  26. #include "nsNSSCertHelper.h"
  27. #include "nsNSSCertTrust.h"
  28. #include "nsNSSCertificate.h"
  29. #include "nsNSSComponent.h"
  30. #include "nsNSSHelper.h"
  31. #include "nsNSSShutDown.h"
  32. #include "nsPK11TokenDB.h"
  33. #include "nsPKCS12Blob.h"
  34. #include "nsPromiseFlatString.h"
  35. #include "nsProxyRelease.h"
  36. #include "nsReadableUtils.h"
  37. #include "nsThreadUtils.h"
  38. #include "nspr.h"
  39. #include "pkix/Time.h"
  40. #include "pkix/pkixnss.h"
  41. #include "pkix/pkixtypes.h"
  42. #include "secasn1.h"
  43. #include "secder.h"
  44. #include "secerr.h"
  45. #include "ssl.h"
  46. #ifdef XP_WIN
  47. #include <winsock.h> // for ntohl
  48. #endif
  49. using namespace mozilla;
  50. using namespace mozilla::psm;
  51. using mozilla::psm::SharedSSLState;
  52. extern LazyLogModule gPIPNSSLog;
  53. static nsresult
  54. attemptToLogInWithDefaultPassword()
  55. {
  56. #ifdef NSS_DISABLE_DBM
  57. // The SQL NSS DB requires the user to be authenticated to set certificate
  58. // trust settings, even if the user's password is empty. To maintain
  59. // compatibility with the DBM-based database, try to log in with the
  60. // default empty password. This will allow, at least, tests that need to
  61. // change certificate trust to pass on all platforms. TODO(bug 978120): Do
  62. // proper testing and/or implement a better solution so that we are confident
  63. // that this does the correct thing outside of xpcshell tests too.
  64. UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
  65. if (!slot) {
  66. return MapSECStatus(SECFailure);
  67. }
  68. if (PK11_NeedUserInit(slot.get())) {
  69. // Ignore the return value. Presumably PK11_InitPin will fail if the user
  70. // has a non-default password.
  71. Unused << PK11_InitPin(slot.get(), nullptr, nullptr);
  72. }
  73. #endif
  74. return NS_OK;
  75. }
  76. NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB)
  77. nsNSSCertificateDB::~nsNSSCertificateDB()
  78. {
  79. nsNSSShutDownPreventionLock locker;
  80. if (isAlreadyShutDown()) {
  81. return;
  82. }
  83. shutdown(ShutdownCalledFrom::Object);
  84. }
  85. NS_IMETHODIMP
  86. nsNSSCertificateDB::FindCertByNickname(const nsAString& nickname,
  87. nsIX509Cert** _rvCert)
  88. {
  89. NS_ENSURE_ARG_POINTER(_rvCert);
  90. *_rvCert = nullptr;
  91. nsNSSShutDownPreventionLock locker;
  92. if (isAlreadyShutDown()) {
  93. return NS_ERROR_NOT_AVAILABLE;
  94. }
  95. char *asciiname = nullptr;
  96. NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
  97. asciiname = const_cast<char*>(aUtf8Nickname.get());
  98. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting \"%s\"\n", asciiname));
  99. UniqueCERTCertificate cert(PK11_FindCertFromNickname(asciiname, nullptr));
  100. if (!cert) {
  101. cert.reset(CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname));
  102. }
  103. if (cert) {
  104. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("got it\n"));
  105. nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert.get());
  106. if (pCert) {
  107. pCert.forget(_rvCert);
  108. return NS_OK;
  109. }
  110. }
  111. return NS_ERROR_FAILURE;
  112. }
  113. NS_IMETHODIMP
  114. nsNSSCertificateDB::FindCertByDBKey(const char* aDBKey,nsIX509Cert** _cert)
  115. {
  116. NS_ENSURE_ARG_POINTER(aDBKey);
  117. NS_ENSURE_ARG(aDBKey[0]);
  118. NS_ENSURE_ARG_POINTER(_cert);
  119. *_cert = nullptr;
  120. nsNSSShutDownPreventionLock locker;
  121. if (isAlreadyShutDown()) {
  122. return NS_ERROR_NOT_AVAILABLE;
  123. }
  124. UniqueCERTCertificate cert;
  125. nsresult rv = FindCertByDBKey(aDBKey, cert);
  126. if (NS_FAILED(rv)) {
  127. return rv;
  128. }
  129. // If we can't find the certificate, that's not an error. Just return null.
  130. if (!cert) {
  131. return NS_OK;
  132. }
  133. nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
  134. if (!nssCert) {
  135. return NS_ERROR_OUT_OF_MEMORY;
  136. }
  137. nssCert.forget(_cert);
  138. return NS_OK;
  139. }
  140. nsresult
  141. nsNSSCertificateDB::FindCertByDBKey(const char* aDBKey,
  142. UniqueCERTCertificate& cert)
  143. {
  144. static_assert(sizeof(uint64_t) == 8, "type size sanity check");
  145. static_assert(sizeof(uint32_t) == 4, "type size sanity check");
  146. // (From nsNSSCertificate::GetDbKey)
  147. // The format of the key is the base64 encoding of the following:
  148. // 4 bytes: {0, 0, 0, 0} (this was intended to be the module ID, but it was
  149. // never implemented)
  150. // 4 bytes: {0, 0, 0, 0} (this was intended to be the slot ID, but it was
  151. // never implemented)
  152. // 4 bytes: <serial number length in big-endian order>
  153. // 4 bytes: <DER-encoded issuer distinguished name length in big-endian order>
  154. // n bytes: <bytes of serial number>
  155. // m bytes: <DER-encoded issuer distinguished name>
  156. nsAutoCString decoded;
  157. nsAutoCString tmpDBKey(aDBKey);
  158. // Filter out any whitespace for backwards compatibility.
  159. tmpDBKey.StripWhitespace();
  160. nsresult rv = Base64Decode(tmpDBKey, decoded);
  161. if (NS_FAILED(rv)) {
  162. return rv;
  163. }
  164. if (decoded.Length() < 16) {
  165. return NS_ERROR_ILLEGAL_INPUT;
  166. }
  167. const char* reader = decoded.BeginReading();
  168. uint64_t zeroes = *BitwiseCast<const uint64_t*, const char*>(reader);
  169. if (zeroes != 0) {
  170. return NS_ERROR_ILLEGAL_INPUT;
  171. }
  172. reader += sizeof(uint64_t);
  173. // Note: We surround the ntohl() argument with parentheses to stop the macro
  174. // from thinking two arguments were passed.
  175. uint32_t serialNumberLen = ntohl(
  176. (*BitwiseCast<const uint32_t*, const char*>(reader)));
  177. reader += sizeof(uint32_t);
  178. uint32_t issuerLen = ntohl(
  179. (*BitwiseCast<const uint32_t*, const char*>(reader)));
  180. reader += sizeof(uint32_t);
  181. if (decoded.Length() != 16ULL + serialNumberLen + issuerLen) {
  182. return NS_ERROR_ILLEGAL_INPUT;
  183. }
  184. CERTIssuerAndSN issuerSN;
  185. issuerSN.serialNumber.len = serialNumberLen;
  186. issuerSN.serialNumber.data = BitwiseCast<unsigned char*, const char*>(reader);
  187. reader += serialNumberLen;
  188. issuerSN.derIssuer.len = issuerLen;
  189. issuerSN.derIssuer.data = BitwiseCast<unsigned char*, const char*>(reader);
  190. reader += issuerLen;
  191. MOZ_ASSERT(reader == decoded.EndReading());
  192. cert.reset(CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN));
  193. return NS_OK;
  194. }
  195. SECStatus
  196. collect_certs(void *arg, SECItem **certs, int numcerts)
  197. {
  198. CERTDERCerts *collectArgs;
  199. SECItem *cert;
  200. SECStatus rv;
  201. collectArgs = (CERTDERCerts *)arg;
  202. collectArgs->numcerts = numcerts;
  203. collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
  204. sizeof(SECItem) * numcerts);
  205. if (!collectArgs->rawCerts)
  206. return(SECFailure);
  207. cert = collectArgs->rawCerts;
  208. while ( numcerts-- ) {
  209. rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
  210. if ( rv == SECFailure )
  211. return(SECFailure);
  212. cert++;
  213. certs++;
  214. }
  215. return (SECSuccess);
  216. }
  217. CERTDERCerts*
  218. nsNSSCertificateDB::getCertsFromPackage(const UniquePLArenaPool& arena,
  219. uint8_t* data, uint32_t length,
  220. const nsNSSShutDownPreventionLock& /*proofOfLock*/)
  221. {
  222. CERTDERCerts* collectArgs = PORT_ArenaZNew(arena.get(), CERTDERCerts);
  223. if (!collectArgs) {
  224. return nullptr;
  225. }
  226. collectArgs->arena = arena.get();
  227. if (CERT_DecodeCertPackage(BitwiseCast<char*, uint8_t*>(data), length,
  228. collect_certs, collectArgs) != SECSuccess) {
  229. return nullptr;
  230. }
  231. return collectArgs;
  232. }
  233. nsresult
  234. nsNSSCertificateDB::handleCACertDownload(NotNull<nsIArray*> x509Certs,
  235. nsIInterfaceRequestor *ctx,
  236. const nsNSSShutDownPreventionLock &proofOfLock)
  237. {
  238. // First thing we have to do is figure out which certificate we're
  239. // gonna present to the user. The CA may have sent down a list of
  240. // certs which may or may not be a chained list of certs. Until
  241. // the day we can design some solid UI for the general case, we'll
  242. // code to the > 90% case. That case is where a CA sends down a
  243. // list that is a hierarchy whose root is either the first or
  244. // the last cert. What we're gonna do is compare the first
  245. // 2 entries, if the second was signed by the first, we assume
  246. // the root cert is the first cert and display it. Otherwise,
  247. // we compare the last 2 entries, if the second to last cert was
  248. // signed by the last cert, then we assume the last cert is the
  249. // root and display it.
  250. uint32_t numCerts;
  251. x509Certs->GetLength(&numCerts);
  252. NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
  253. if (numCerts == 0)
  254. return NS_OK; // Nothing to import, so nothing to do.
  255. nsCOMPtr<nsIX509Cert> certToShow;
  256. uint32_t selCertIndex;
  257. if (numCerts == 1) {
  258. // There's only one cert, so let's show it.
  259. selCertIndex = 0;
  260. certToShow = do_QueryElementAt(x509Certs, selCertIndex);
  261. } else {
  262. nsCOMPtr<nsIX509Cert> cert0; // first cert
  263. nsCOMPtr<nsIX509Cert> cert1; // second cert
  264. nsCOMPtr<nsIX509Cert> certn_2; // second to last cert
  265. nsCOMPtr<nsIX509Cert> certn_1; // last cert
  266. cert0 = do_QueryElementAt(x509Certs, 0);
  267. cert1 = do_QueryElementAt(x509Certs, 1);
  268. certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
  269. certn_1 = do_QueryElementAt(x509Certs, numCerts-1);
  270. nsXPIDLString cert0SubjectName;
  271. nsXPIDLString cert1IssuerName;
  272. nsXPIDLString certn_2IssuerName;
  273. nsXPIDLString certn_1SubjectName;
  274. cert0->GetSubjectName(cert0SubjectName);
  275. cert1->GetIssuerName(cert1IssuerName);
  276. certn_2->GetIssuerName(certn_2IssuerName);
  277. certn_1->GetSubjectName(certn_1SubjectName);
  278. if (cert1IssuerName.Equals(cert0SubjectName)) {
  279. // In this case, the first cert in the list signed the second,
  280. // so the first cert is the root. Let's display it.
  281. selCertIndex = 0;
  282. certToShow = cert0;
  283. } else
  284. if (certn_2IssuerName.Equals(certn_1SubjectName)) {
  285. // In this case the last cert has signed the second to last cert.
  286. // The last cert is the root, so let's display it.
  287. selCertIndex = numCerts-1;
  288. certToShow = certn_1;
  289. } else {
  290. // It's not a chain, so let's just show the first one in the
  291. // downloaded list.
  292. selCertIndex = 0;
  293. certToShow = cert0;
  294. }
  295. }
  296. if (!certToShow)
  297. return NS_ERROR_FAILURE;
  298. nsCOMPtr<nsICertificateDialogs> dialogs;
  299. nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs),
  300. NS_GET_IID(nsICertificateDialogs),
  301. NS_CERTIFICATEDIALOGS_CONTRACTID);
  302. if (NS_FAILED(rv)) {
  303. return rv;
  304. }
  305. UniqueCERTCertificate tmpCert(certToShow->GetCert());
  306. if (!tmpCert) {
  307. return NS_ERROR_FAILURE;
  308. }
  309. if (!CERT_IsCACert(tmpCert.get(), nullptr)) {
  310. DisplayCertificateAlert(ctx, "NotACACert", certToShow, proofOfLock);
  311. return NS_ERROR_FAILURE;
  312. }
  313. if (tmpCert->isperm) {
  314. DisplayCertificateAlert(ctx, "CaCertExists", certToShow, proofOfLock);
  315. return NS_ERROR_FAILURE;
  316. }
  317. uint32_t trustBits;
  318. bool allows;
  319. rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
  320. if (NS_FAILED(rv))
  321. return rv;
  322. if (!allows)
  323. return NS_ERROR_NOT_AVAILABLE;
  324. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trust is %d\n", trustBits));
  325. UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));
  326. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
  327. nsNSSCertTrust trust;
  328. trust.SetValidCA();
  329. trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
  330. !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
  331. !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));
  332. if (CERT_AddTempCertToPerm(tmpCert.get(), nickname.get(),
  333. trust.GetTrust()) != SECSuccess) {
  334. return NS_ERROR_FAILURE;
  335. }
  336. // Import additional delivered certificates that can be verified.
  337. // build a CertList for filtering
  338. UniqueCERTCertList certList(CERT_NewCertList());
  339. if (!certList) {
  340. return NS_ERROR_FAILURE;
  341. }
  342. // get all remaining certs into temp store
  343. for (uint32_t i=0; i<numCerts; i++) {
  344. if (i == selCertIndex) {
  345. // we already processed that one
  346. continue;
  347. }
  348. nsCOMPtr<nsIX509Cert> remainingCert = do_QueryElementAt(x509Certs, i);
  349. if (!remainingCert) {
  350. continue;
  351. }
  352. UniqueCERTCertificate tmpCert2(remainingCert->GetCert());
  353. if (!tmpCert2) {
  354. continue; // Let's try to import the rest of 'em
  355. }
  356. if (CERT_AddCertToListTail(certList.get(), tmpCert2.get()) != SECSuccess) {
  357. continue;
  358. }
  359. Unused << tmpCert2.release();
  360. }
  361. return ImportValidCACertsInList(certList, ctx, proofOfLock);
  362. }
  363. NS_IMETHODIMP
  364. nsNSSCertificateDB::ImportCertificates(uint8_t* data, uint32_t length,
  365. uint32_t type,
  366. nsIInterfaceRequestor* ctx)
  367. {
  368. nsNSSShutDownPreventionLock locker;
  369. if (isAlreadyShutDown()) {
  370. return NS_ERROR_NOT_AVAILABLE;
  371. }
  372. // We currently only handle CA certificates.
  373. if (type != nsIX509Cert::CA_CERT) {
  374. return NS_ERROR_FAILURE;
  375. }
  376. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  377. if (!arena) {
  378. return NS_ERROR_OUT_OF_MEMORY;
  379. }
  380. CERTDERCerts* certCollection = getCertsFromPackage(arena, data, length,
  381. locker);
  382. if (!certCollection) {
  383. return NS_ERROR_FAILURE;
  384. }
  385. nsCOMPtr<nsIMutableArray> array = nsArrayBase::Create();
  386. if (!array) {
  387. return NS_ERROR_FAILURE;
  388. }
  389. // Now let's create some certs to work with
  390. for (int i = 0; i < certCollection->numcerts; i++) {
  391. SECItem* currItem = &certCollection->rawCerts[i];
  392. nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::ConstructFromDER(
  393. BitwiseCast<char*, unsigned char*>(currItem->data), currItem->len);
  394. if (!cert) {
  395. return NS_ERROR_FAILURE;
  396. }
  397. nsresult rv = array->AppendElement(cert, false);
  398. if (NS_FAILED(rv)) {
  399. return rv;
  400. }
  401. }
  402. return handleCACertDownload(WrapNotNull(array), ctx, locker);
  403. }
  404. /**
  405. * Filters an array of certs by usage and imports them into temporary storage.
  406. *
  407. * @param numcerts
  408. * Size of the |certs| array.
  409. * @param certs
  410. * Pointer to array of certs to import.
  411. * @param usage
  412. * Usage the certs should be filtered on.
  413. * @param caOnly
  414. * Whether to import only CA certs.
  415. * @param filteredCerts
  416. * List of certs that weren't filtered out and were successfully imported.
  417. */
  418. static nsresult
  419. ImportCertsIntoTempStorage(int numcerts, SECItem* certs,
  420. const SECCertUsage usage, const bool caOnly,
  421. const nsNSSShutDownPreventionLock& /*proofOfLock*/,
  422. /*out*/ const UniqueCERTCertList& filteredCerts)
  423. {
  424. NS_ENSURE_ARG_MIN(numcerts, 1);
  425. NS_ENSURE_ARG_POINTER(certs);
  426. NS_ENSURE_ARG_POINTER(filteredCerts.get());
  427. // CERT_ImportCerts() expects an array of *pointers* to SECItems, so we have
  428. // to convert |certs| to such a format first.
  429. SECItem** ptrArray =
  430. static_cast<SECItem**>(PORT_Alloc(sizeof(SECItem*) * numcerts));
  431. if (!ptrArray) {
  432. return NS_ERROR_OUT_OF_MEMORY;
  433. }
  434. for (int i = 0; i < numcerts; i++) {
  435. ptrArray[i] = &certs[i];
  436. }
  437. CERTCertificate** importedCerts = nullptr;
  438. SECStatus srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), usage,
  439. numcerts, ptrArray, &importedCerts, false,
  440. caOnly, nullptr);
  441. PORT_Free(ptrArray);
  442. ptrArray = nullptr;
  443. if (srv != SECSuccess) {
  444. return NS_ERROR_FAILURE;
  445. }
  446. for (int i = 0; i < numcerts; i++) {
  447. if (!importedCerts[i]) {
  448. continue;
  449. }
  450. UniqueCERTCertificate cert(CERT_DupCertificate(importedCerts[i]));
  451. if (!cert) {
  452. continue;
  453. }
  454. if (CERT_AddCertToListTail(filteredCerts.get(), cert.get()) == SECSuccess) {
  455. Unused << cert.release();
  456. }
  457. }
  458. CERT_DestroyCertArray(importedCerts, numcerts);
  459. // CERT_ImportCerts() ignores its |usage| parameter, so we have to manually
  460. // filter out unwanted certs.
  461. if (CERT_FilterCertListByUsage(filteredCerts.get(), usage, caOnly)
  462. != SECSuccess) {
  463. return NS_ERROR_FAILURE;
  464. }
  465. return NS_OK;
  466. }
  467. static SECStatus
  468. ImportCertsIntoPermanentStorage(const UniqueCERTCertList& certChain,
  469. const SECCertUsage usage, const bool caOnly)
  470. {
  471. int chainLen = 0;
  472. for (CERTCertListNode *chainNode = CERT_LIST_HEAD(certChain);
  473. !CERT_LIST_END(chainNode, certChain);
  474. chainNode = CERT_LIST_NEXT(chainNode)) {
  475. chainLen++;
  476. }
  477. SECItem **rawArray;
  478. rawArray = (SECItem **) PORT_Alloc(chainLen * sizeof(SECItem *));
  479. if (!rawArray) {
  480. return SECFailure;
  481. }
  482. int i = 0;
  483. for (CERTCertListNode *chainNode = CERT_LIST_HEAD(certChain);
  484. !CERT_LIST_END(chainNode, certChain);
  485. chainNode = CERT_LIST_NEXT(chainNode), i++) {
  486. rawArray[i] = &chainNode->cert->derCert;
  487. }
  488. SECStatus srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), usage, chainLen,
  489. rawArray, nullptr, true, caOnly, nullptr);
  490. PORT_Free(rawArray);
  491. return srv;
  492. }
  493. NS_IMETHODIMP
  494. nsNSSCertificateDB::ImportEmailCertificate(uint8_t* data, uint32_t length,
  495. nsIInterfaceRequestor* ctx)
  496. {
  497. nsNSSShutDownPreventionLock locker;
  498. if (isAlreadyShutDown()) {
  499. return NS_ERROR_NOT_AVAILABLE;
  500. }
  501. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  502. if (!arena) {
  503. return NS_ERROR_OUT_OF_MEMORY;
  504. }
  505. CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
  506. if (!certCollection) {
  507. return NS_ERROR_FAILURE;
  508. }
  509. UniqueCERTCertList filteredCerts(CERT_NewCertList());
  510. if (!filteredCerts) {
  511. return NS_ERROR_FAILURE;
  512. }
  513. nsresult rv = ImportCertsIntoTempStorage(certCollection->numcerts,
  514. certCollection->rawCerts,
  515. certUsageEmailRecipient,
  516. false, locker, filteredCerts);
  517. if (NS_FAILED(rv)) {
  518. return rv;
  519. }
  520. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  521. if (!certVerifier) {
  522. return NS_ERROR_UNEXPECTED;
  523. }
  524. // Iterate through the filtered cert list and import verified certs into
  525. // permanent storage.
  526. // Note: We verify the certs in order to prevent DoS attacks. See Bug 249004.
  527. for (CERTCertListNode* node = CERT_LIST_HEAD(filteredCerts.get());
  528. !CERT_LIST_END(node, filteredCerts.get());
  529. node = CERT_LIST_NEXT(node)) {
  530. if (!node->cert) {
  531. continue;
  532. }
  533. UniqueCERTCertList certChain;
  534. mozilla::pkix::Result result =
  535. certVerifier->VerifyCert(node->cert, certificateUsageEmailRecipient,
  536. mozilla::pkix::Now(), ctx, nullptr, certChain);
  537. if (result != mozilla::pkix::Success) {
  538. nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
  539. DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, locker);
  540. continue;
  541. }
  542. SECStatus srv = ImportCertsIntoPermanentStorage(certChain,
  543. certUsageEmailRecipient,
  544. false);
  545. if (srv != SECSuccess) {
  546. return NS_ERROR_FAILURE;
  547. }
  548. CERT_SaveSMimeProfile(node->cert, nullptr, nullptr);
  549. }
  550. return NS_OK;
  551. }
  552. nsresult
  553. nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem* caCerts,
  554. nsIInterfaceRequestor* ctx,
  555. const nsNSSShutDownPreventionLock& proofOfLock)
  556. {
  557. UniqueCERTCertList filteredCerts(CERT_NewCertList());
  558. if (!filteredCerts) {
  559. return NS_ERROR_FAILURE;
  560. }
  561. nsresult rv = ImportCertsIntoTempStorage(numCACerts, caCerts, certUsageAnyCA,
  562. true, proofOfLock, filteredCerts);
  563. if (NS_FAILED(rv)) {
  564. return rv;
  565. }
  566. return ImportValidCACertsInList(filteredCerts, ctx, proofOfLock);
  567. }
  568. nsresult
  569. nsNSSCertificateDB::ImportValidCACertsInList(const UniqueCERTCertList& filteredCerts,
  570. nsIInterfaceRequestor* ctx,
  571. const nsNSSShutDownPreventionLock& proofOfLock)
  572. {
  573. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  574. if (!certVerifier) {
  575. return NS_ERROR_UNEXPECTED;
  576. }
  577. // Iterate through the filtered cert list and import verified certs into
  578. // permanent storage.
  579. // Note: We verify the certs in order to prevent DoS attacks. See Bug 249004.
  580. for (CERTCertListNode* node = CERT_LIST_HEAD(filteredCerts.get());
  581. !CERT_LIST_END(node, filteredCerts.get());
  582. node = CERT_LIST_NEXT(node)) {
  583. UniqueCERTCertList certChain;
  584. mozilla::pkix::Result result =
  585. certVerifier->VerifyCert(node->cert, certificateUsageVerifyCA,
  586. mozilla::pkix::Now(), ctx, nullptr, certChain);
  587. if (result != mozilla::pkix::Success) {
  588. nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
  589. DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, proofOfLock);
  590. continue;
  591. }
  592. SECStatus srv = ImportCertsIntoPermanentStorage(certChain, certUsageAnyCA,
  593. true);
  594. if (srv != SECSuccess) {
  595. return NS_ERROR_FAILURE;
  596. }
  597. }
  598. return NS_OK;
  599. }
  600. void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor *ctx,
  601. const char *stringID,
  602. nsIX509Cert *certToShow,
  603. const nsNSSShutDownPreventionLock &/*proofOfLock*/)
  604. {
  605. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  606. if (!NS_IsMainThread()) {
  607. NS_ERROR("nsNSSCertificateDB::DisplayCertificateAlert called off the main thread");
  608. return;
  609. }
  610. nsCOMPtr<nsIInterfaceRequestor> my_ctx = ctx;
  611. if (!my_ctx) {
  612. my_ctx = new PipUIContext();
  613. }
  614. // This shall be replaced by embedding ovverridable prompts
  615. // as discussed in bug 310446, and should make use of certToShow.
  616. nsresult rv;
  617. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  618. if (NS_SUCCEEDED(rv)) {
  619. nsAutoString tmpMessage;
  620. nssComponent->GetPIPNSSBundleString(stringID, tmpMessage);
  621. nsCOMPtr<nsIPrompt> prompt (do_GetInterface(my_ctx));
  622. if (!prompt) {
  623. return;
  624. }
  625. prompt->Alert(nullptr, tmpMessage.get());
  626. }
  627. }
  628. NS_IMETHODIMP
  629. nsNSSCertificateDB::ImportUserCertificate(uint8_t* data, uint32_t length,
  630. nsIInterfaceRequestor* ctx)
  631. {
  632. if (!NS_IsMainThread()) {
  633. NS_ERROR("nsNSSCertificateDB::ImportUserCertificate called off the main thread");
  634. return NS_ERROR_NOT_SAME_THREAD;
  635. }
  636. nsNSSShutDownPreventionLock locker;
  637. if (isAlreadyShutDown()) {
  638. return NS_ERROR_NOT_AVAILABLE;
  639. }
  640. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  641. if (!arena) {
  642. return NS_ERROR_OUT_OF_MEMORY;
  643. }
  644. CERTDERCerts* collectArgs = getCertsFromPackage(arena, data, length, locker);
  645. if (!collectArgs) {
  646. return NS_ERROR_FAILURE;
  647. }
  648. UniqueCERTCertificate cert(
  649. CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
  650. nullptr, false, true));
  651. if (!cert) {
  652. return NS_ERROR_FAILURE;
  653. }
  654. UniquePK11SlotInfo slot(PK11_KeyForCertExists(cert.get(), nullptr, ctx));
  655. if (!slot) {
  656. nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
  657. DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow, locker);
  658. return NS_ERROR_FAILURE;
  659. }
  660. slot = nullptr;
  661. /* pick a nickname for the cert */
  662. nsAutoCString nickname;
  663. if (cert->nickname) {
  664. nickname = cert->nickname;
  665. } else {
  666. get_default_nickname(cert.get(), ctx, nickname, locker);
  667. }
  668. /* user wants to import the cert */
  669. slot.reset(PK11_ImportCertForKey(cert.get(), nickname.get(), ctx));
  670. if (!slot) {
  671. return NS_ERROR_FAILURE;
  672. }
  673. slot = nullptr;
  674. {
  675. nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
  676. DisplayCertificateAlert(ctx, "UserCertImported", certToShow, locker);
  677. }
  678. int numCACerts = collectArgs->numcerts - 1;
  679. if (numCACerts) {
  680. SECItem* caCerts = collectArgs->rawCerts + 1;
  681. return ImportValidCACerts(numCACerts, caCerts, ctx, locker);
  682. }
  683. return NS_OK;
  684. }
  685. NS_IMETHODIMP
  686. nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
  687. {
  688. NS_ENSURE_ARG_POINTER(aCert);
  689. nsNSSShutDownPreventionLock locker;
  690. if (isAlreadyShutDown()) {
  691. return NS_ERROR_NOT_AVAILABLE;
  692. }
  693. UniqueCERTCertificate cert(aCert->GetCert());
  694. if (!cert) {
  695. return NS_ERROR_FAILURE;
  696. }
  697. SECStatus srv = SECSuccess;
  698. uint32_t certType;
  699. aCert->GetCertType(&certType);
  700. if (NS_FAILED(aCert->MarkForPermDeletion()))
  701. {
  702. return NS_ERROR_FAILURE;
  703. }
  704. if (cert->slot && certType != nsIX509Cert::USER_CERT) {
  705. // To delete a cert of a slot (builtin, most likely), mark it as
  706. // completely untrusted. This way we keep a copy cached in the
  707. // local database, and next time we try to load it off of the
  708. // external token/slot, we'll know not to trust it. We don't
  709. // want to do that with user certs, because a user may re-store
  710. // the cert onto the card again at which point we *will* want to
  711. // trust that cert if it chains up properly.
  712. nsNSSCertTrust trust(0, 0, 0);
  713. srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
  714. cert.get(), trust.GetTrust());
  715. }
  716. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("cert deleted: %d", srv));
  717. return (srv) ? NS_ERROR_FAILURE : NS_OK;
  718. }
  719. NS_IMETHODIMP
  720. nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert,
  721. uint32_t type,
  722. uint32_t trusted)
  723. {
  724. NS_ENSURE_ARG_POINTER(cert);
  725. nsNSSShutDownPreventionLock locker;
  726. if (isAlreadyShutDown()) {
  727. return NS_ERROR_NOT_AVAILABLE;
  728. }
  729. nsNSSCertTrust trust;
  730. nsresult rv;
  731. UniqueCERTCertificate nsscert(cert->GetCert());
  732. rv = attemptToLogInWithDefaultPassword();
  733. if (NS_WARN_IF(rv != NS_OK)) {
  734. return rv;
  735. }
  736. SECStatus srv;
  737. if (type == nsIX509Cert::CA_CERT) {
  738. // always start with untrusted and move up
  739. trust.SetValidCA();
  740. trust.AddCATrust(!!(trusted & nsIX509CertDB::TRUSTED_SSL),
  741. !!(trusted & nsIX509CertDB::TRUSTED_EMAIL),
  742. !!(trusted & nsIX509CertDB::TRUSTED_OBJSIGN));
  743. srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
  744. nsscert.get(),
  745. trust.GetTrust());
  746. } else if (type == nsIX509Cert::SERVER_CERT) {
  747. // always start with untrusted and move up
  748. trust.SetValidPeer();
  749. trust.AddPeerTrust(trusted & nsIX509CertDB::TRUSTED_SSL, 0, 0);
  750. srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
  751. nsscert.get(),
  752. trust.GetTrust());
  753. } else if (type == nsIX509Cert::EMAIL_CERT) {
  754. // always start with untrusted and move up
  755. trust.SetValidPeer();
  756. trust.AddPeerTrust(0, !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), 0);
  757. srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
  758. nsscert.get(),
  759. trust.GetTrust());
  760. } else {
  761. // ignore user certs
  762. return NS_OK;
  763. }
  764. return MapSECStatus(srv);
  765. }
  766. NS_IMETHODIMP
  767. nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
  768. uint32_t certType,
  769. uint32_t trustType,
  770. bool *_isTrusted)
  771. {
  772. NS_ENSURE_ARG_POINTER(_isTrusted);
  773. *_isTrusted = false;
  774. nsNSSShutDownPreventionLock locker;
  775. if (isAlreadyShutDown()) {
  776. return NS_ERROR_NOT_AVAILABLE;
  777. }
  778. SECStatus srv;
  779. UniqueCERTCertificate nsscert(cert->GetCert());
  780. CERTCertTrust nsstrust;
  781. srv = CERT_GetCertTrust(nsscert.get(), &nsstrust);
  782. if (srv != SECSuccess)
  783. return NS_ERROR_FAILURE;
  784. nsNSSCertTrust trust(&nsstrust);
  785. if (certType == nsIX509Cert::CA_CERT) {
  786. if (trustType & nsIX509CertDB::TRUSTED_SSL) {
  787. *_isTrusted = trust.HasTrustedCA(true, false, false);
  788. } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
  789. *_isTrusted = trust.HasTrustedCA(false, true, false);
  790. } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
  791. *_isTrusted = trust.HasTrustedCA(false, false, true);
  792. } else {
  793. return NS_ERROR_FAILURE;
  794. }
  795. } else if (certType == nsIX509Cert::SERVER_CERT) {
  796. if (trustType & nsIX509CertDB::TRUSTED_SSL) {
  797. *_isTrusted = trust.HasTrustedPeer(true, false, false);
  798. } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
  799. *_isTrusted = trust.HasTrustedPeer(false, true, false);
  800. } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
  801. *_isTrusted = trust.HasTrustedPeer(false, false, true);
  802. } else {
  803. return NS_ERROR_FAILURE;
  804. }
  805. } else if (certType == nsIX509Cert::EMAIL_CERT) {
  806. if (trustType & nsIX509CertDB::TRUSTED_SSL) {
  807. *_isTrusted = trust.HasTrustedPeer(true, false, false);
  808. } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
  809. *_isTrusted = trust.HasTrustedPeer(false, true, false);
  810. } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
  811. *_isTrusted = trust.HasTrustedPeer(false, false, true);
  812. } else {
  813. return NS_ERROR_FAILURE;
  814. }
  815. } /* user: ignore */
  816. return NS_OK;
  817. }
  818. NS_IMETHODIMP
  819. nsNSSCertificateDB::ImportCertsFromFile(nsIFile* aFile, uint32_t aType)
  820. {
  821. nsNSSShutDownPreventionLock locker;
  822. if (isAlreadyShutDown()) {
  823. return NS_ERROR_NOT_AVAILABLE;
  824. }
  825. NS_ENSURE_ARG(aFile);
  826. switch (aType) {
  827. case nsIX509Cert::CA_CERT:
  828. case nsIX509Cert::EMAIL_CERT:
  829. // good
  830. break;
  831. default:
  832. // not supported (yet)
  833. return NS_ERROR_FAILURE;
  834. }
  835. PRFileDesc* fd = nullptr;
  836. nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
  837. if (NS_FAILED(rv)) {
  838. return rv;
  839. }
  840. if (!fd) {
  841. return NS_ERROR_FAILURE;
  842. }
  843. PRFileInfo fileInfo;
  844. if (PR_GetOpenFileInfo(fd, &fileInfo) != PR_SUCCESS) {
  845. return NS_ERROR_FAILURE;
  846. }
  847. auto buf = MakeUnique<unsigned char[]>(fileInfo.size);
  848. int32_t bytesObtained = PR_Read(fd, buf.get(), fileInfo.size);
  849. PR_Close(fd);
  850. if (bytesObtained != fileInfo.size) {
  851. return NS_ERROR_FAILURE;
  852. }
  853. nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
  854. switch (aType) {
  855. case nsIX509Cert::CA_CERT:
  856. return ImportCertificates(buf.get(), bytesObtained, aType, cxt);
  857. case nsIX509Cert::EMAIL_CERT:
  858. return ImportEmailCertificate(buf.get(), bytesObtained, cxt);
  859. default:
  860. MOZ_ASSERT(false, "Unsupported type should have been filtered out");
  861. break;
  862. }
  863. return NS_ERROR_FAILURE;
  864. }
  865. NS_IMETHODIMP
  866. nsNSSCertificateDB::ImportPKCS12File(nsISupports* aToken, nsIFile* aFile)
  867. {
  868. nsNSSShutDownPreventionLock locker;
  869. if (isAlreadyShutDown()) {
  870. return NS_ERROR_NOT_AVAILABLE;
  871. }
  872. NS_ENSURE_ARG(aFile);
  873. nsPKCS12Blob blob;
  874. nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
  875. if (token) {
  876. blob.SetToken(token);
  877. }
  878. return blob.ImportFromFile(aFile);
  879. }
  880. NS_IMETHODIMP
  881. nsNSSCertificateDB::ExportPKCS12File(nsISupports* aToken,
  882. nsIFile* aFile,
  883. uint32_t count,
  884. nsIX509Cert** certs)
  885. {
  886. nsNSSShutDownPreventionLock locker;
  887. if (isAlreadyShutDown()) {
  888. return NS_ERROR_NOT_AVAILABLE;
  889. }
  890. NS_ENSURE_ARG(aFile);
  891. nsPKCS12Blob blob;
  892. if (count == 0) return NS_OK;
  893. nsCOMPtr<nsIPK11Token> localRef;
  894. if (!aToken) {
  895. UniquePK11SlotInfo keySlot(PK11_GetInternalKeySlot());
  896. if (!keySlot) {
  897. return NS_ERROR_FAILURE;
  898. }
  899. localRef = new nsPK11Token(keySlot.get());
  900. } else {
  901. localRef = do_QueryInterface(aToken);
  902. }
  903. blob.SetToken(localRef);
  904. return blob.ExportToFile(aFile, certs, count);
  905. }
  906. NS_IMETHODIMP
  907. nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString& aNickname,
  908. nsIX509Cert** _retval)
  909. {
  910. NS_ENSURE_ARG_POINTER(_retval);
  911. *_retval = nullptr;
  912. if (aNickname.IsEmpty())
  913. return NS_OK;
  914. nsNSSShutDownPreventionLock locker;
  915. if (isAlreadyShutDown()) {
  916. return NS_ERROR_NOT_AVAILABLE;
  917. }
  918. nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
  919. char *asciiname = nullptr;
  920. NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
  921. asciiname = const_cast<char*>(aUtf8Nickname.get());
  922. /* Find a good cert in the user's database */
  923. UniqueCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
  924. asciiname,
  925. certUsageEmailRecipient,
  926. true, ctx));
  927. if (!cert) {
  928. return NS_OK;
  929. }
  930. nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
  931. if (!nssCert) {
  932. return NS_ERROR_OUT_OF_MEMORY;
  933. }
  934. nssCert.forget(_retval);
  935. return NS_OK;
  936. }
  937. NS_IMETHODIMP
  938. nsNSSCertificateDB::FindEmailSigningCert(const nsAString& aNickname,
  939. nsIX509Cert** _retval)
  940. {
  941. NS_ENSURE_ARG_POINTER(_retval);
  942. *_retval = nullptr;
  943. if (aNickname.IsEmpty())
  944. return NS_OK;
  945. nsNSSShutDownPreventionLock locker;
  946. if (isAlreadyShutDown()) {
  947. return NS_ERROR_NOT_AVAILABLE;
  948. }
  949. nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
  950. char *asciiname = nullptr;
  951. NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
  952. asciiname = const_cast<char*>(aUtf8Nickname.get());
  953. /* Find a good cert in the user's database */
  954. UniqueCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
  955. asciiname,
  956. certUsageEmailSigner,
  957. true, ctx));
  958. if (!cert) {
  959. return NS_OK;
  960. }
  961. nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
  962. if (!nssCert) {
  963. return NS_ERROR_OUT_OF_MEMORY;
  964. }
  965. nssCert.forget(_retval);
  966. return NS_OK;
  967. }
  968. NS_IMETHODIMP
  969. nsNSSCertificateDB::FindCertByEmailAddress(const char* aEmailAddress,
  970. nsIX509Cert** _retval)
  971. {
  972. nsNSSShutDownPreventionLock locker;
  973. if (isAlreadyShutDown()) {
  974. return NS_ERROR_NOT_AVAILABLE;
  975. }
  976. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  977. NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
  978. UniqueCERTCertList certlist(
  979. PK11_FindCertsFromEmailAddress(aEmailAddress, nullptr));
  980. if (!certlist)
  981. return NS_ERROR_FAILURE;
  982. // certlist now contains certificates with the right email address,
  983. // but they might not have the correct usage or might even be invalid
  984. if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
  985. return NS_ERROR_FAILURE; // no certs found
  986. CERTCertListNode *node;
  987. // search for a valid certificate
  988. for (node = CERT_LIST_HEAD(certlist);
  989. !CERT_LIST_END(node, certlist);
  990. node = CERT_LIST_NEXT(node)) {
  991. UniqueCERTCertList unusedCertChain;
  992. mozilla::pkix::Result result =
  993. certVerifier->VerifyCert(node->cert, certificateUsageEmailRecipient,
  994. mozilla::pkix::Now(),
  995. nullptr /*XXX pinarg*/,
  996. nullptr /*hostname*/,
  997. unusedCertChain);
  998. if (result == mozilla::pkix::Success) {
  999. break;
  1000. }
  1001. }
  1002. if (CERT_LIST_END(node, certlist)) {
  1003. // no valid cert found
  1004. return NS_ERROR_FAILURE;
  1005. }
  1006. // node now contains the first valid certificate with correct usage
  1007. RefPtr<nsNSSCertificate> nssCert = nsNSSCertificate::Create(node->cert);
  1008. if (!nssCert)
  1009. return NS_ERROR_OUT_OF_MEMORY;
  1010. nssCert.forget(_retval);
  1011. return NS_OK;
  1012. }
  1013. NS_IMETHODIMP
  1014. nsNSSCertificateDB::ConstructX509FromBase64(const nsACString& base64,
  1015. /*out*/ nsIX509Cert** _retval)
  1016. {
  1017. nsNSSShutDownPreventionLock locker;
  1018. if (isAlreadyShutDown()) {
  1019. return NS_ERROR_NOT_AVAILABLE;
  1020. }
  1021. if (!_retval) {
  1022. return NS_ERROR_INVALID_POINTER;
  1023. }
  1024. // Base64Decode() doesn't consider a zero length input as an error, and just
  1025. // returns the empty string. We don't want this behavior, so the below check
  1026. // catches this case.
  1027. if (base64.Length() < 1) {
  1028. return NS_ERROR_ILLEGAL_VALUE;
  1029. }
  1030. nsAutoCString certDER;
  1031. nsresult rv = Base64Decode(base64, certDER);
  1032. if (NS_FAILED(rv)) {
  1033. return rv;
  1034. }
  1035. return ConstructX509(certDER.get(), certDER.Length(), _retval);
  1036. }
  1037. NS_IMETHODIMP
  1038. nsNSSCertificateDB::ConstructX509(const char* certDER,
  1039. uint32_t lengthDER,
  1040. nsIX509Cert** _retval)
  1041. {
  1042. nsNSSShutDownPreventionLock locker;
  1043. if (isAlreadyShutDown()) {
  1044. return NS_ERROR_NOT_AVAILABLE;
  1045. }
  1046. if (NS_WARN_IF(!_retval)) {
  1047. return NS_ERROR_INVALID_POINTER;
  1048. }
  1049. SECItem secitem_cert;
  1050. secitem_cert.type = siDERCertBuffer;
  1051. secitem_cert.data = (unsigned char*)certDER;
  1052. secitem_cert.len = lengthDER;
  1053. UniqueCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  1054. &secitem_cert, nullptr,
  1055. false, true));
  1056. if (!cert)
  1057. return (PORT_GetError() == SEC_ERROR_NO_MEMORY)
  1058. ? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
  1059. nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
  1060. if (!nssCert) {
  1061. return NS_ERROR_OUT_OF_MEMORY;
  1062. }
  1063. nssCert.forget(_retval);
  1064. return NS_OK;
  1065. }
  1066. void
  1067. nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
  1068. nsIInterfaceRequestor* ctx,
  1069. nsCString &nickname,
  1070. const nsNSSShutDownPreventionLock &/*proofOfLock*/)
  1071. {
  1072. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1073. nickname.Truncate();
  1074. nsresult rv;
  1075. CK_OBJECT_HANDLE keyHandle;
  1076. CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
  1077. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  1078. if (NS_FAILED(rv))
  1079. return;
  1080. nsAutoCString username;
  1081. UniquePORTString tempCN(CERT_GetCommonName(&cert->subject));
  1082. if (tempCN) {
  1083. username = tempCN.get();
  1084. }
  1085. nsAutoCString caname;
  1086. UniquePORTString tempIssuerOrg(CERT_GetOrgName(&cert->issuer));
  1087. if (tempIssuerOrg) {
  1088. caname = tempIssuerOrg.get();
  1089. }
  1090. nsAutoString tmpNickFmt;
  1091. nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt);
  1092. NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt);
  1093. nsAutoCString baseName;
  1094. baseName.AppendPrintf(nickFmt.get(), username.get(), caname.get());
  1095. if (baseName.IsEmpty()) {
  1096. return;
  1097. }
  1098. nickname = baseName;
  1099. /*
  1100. * We need to see if the private key exists on a token, if it does
  1101. * then we need to check for nicknames that already exist on the smart
  1102. * card.
  1103. */
  1104. UniquePK11SlotInfo slot(PK11_KeyForCertExists(cert, &keyHandle, ctx));
  1105. if (!slot)
  1106. return;
  1107. if (!PK11_IsInternal(slot.get())) {
  1108. nsAutoCString tmp;
  1109. tmp.AppendPrintf("%s:%s", PK11_GetTokenName(slot.get()), baseName.get());
  1110. if (tmp.IsEmpty()) {
  1111. nickname.Truncate();
  1112. return;
  1113. }
  1114. baseName = tmp;
  1115. nickname = baseName;
  1116. }
  1117. int count = 1;
  1118. while (true) {
  1119. if ( count > 1 ) {
  1120. nsAutoCString tmp;
  1121. tmp.AppendPrintf("%s #%d", baseName.get(), count);
  1122. if (tmp.IsEmpty()) {
  1123. nickname.Truncate();
  1124. return;
  1125. }
  1126. nickname = tmp;
  1127. }
  1128. UniqueCERTCertificate dummycert;
  1129. if (PK11_IsInternal(slot.get())) {
  1130. /* look up the nickname to make sure it isn't in use already */
  1131. dummycert.reset(CERT_FindCertByNickname(defaultcertdb, nickname.get()));
  1132. } else {
  1133. // Check the cert against others that already live on the smart card.
  1134. dummycert.reset(PK11_FindCertFromNickname(nickname.get(), ctx));
  1135. if (dummycert) {
  1136. // Make sure the subject names are different.
  1137. if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
  1138. {
  1139. /*
  1140. * There is another certificate with the same nickname and
  1141. * the same subject name on the smart card, so let's use this
  1142. * nickname.
  1143. */
  1144. dummycert = nullptr;
  1145. }
  1146. }
  1147. }
  1148. if (!dummycert) {
  1149. break;
  1150. }
  1151. count++;
  1152. }
  1153. }
  1154. NS_IMETHODIMP
  1155. nsNSSCertificateDB::AddCertFromBase64(const nsACString& aBase64,
  1156. const nsACString& aTrust,
  1157. const nsACString& /*aName*/)
  1158. {
  1159. nsNSSShutDownPreventionLock locker;
  1160. if (isAlreadyShutDown()) {
  1161. return NS_ERROR_NOT_AVAILABLE;
  1162. }
  1163. nsNSSCertTrust trust;
  1164. if (CERT_DecodeTrustString(trust.GetTrust(), PromiseFlatCString(aTrust).get())
  1165. != SECSuccess) {
  1166. return NS_ERROR_FAILURE;
  1167. }
  1168. nsCOMPtr<nsIX509Cert> newCert;
  1169. nsresult rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
  1170. if (NS_FAILED(rv)) {
  1171. return rv;
  1172. }
  1173. UniqueCERTCertificate tmpCert(newCert->GetCert());
  1174. if (!tmpCert) {
  1175. return NS_ERROR_FAILURE;
  1176. }
  1177. // If there's already a certificate that matches this one in the database, we
  1178. // still want to set its trust to the given value.
  1179. if (tmpCert->isperm) {
  1180. return SetCertTrustFromString(newCert, aTrust);
  1181. }
  1182. UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));
  1183. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
  1184. rv = attemptToLogInWithDefaultPassword();
  1185. if (NS_WARN_IF(rv != NS_OK)) {
  1186. return rv;
  1187. }
  1188. SECStatus srv = CERT_AddTempCertToPerm(tmpCert.get(), nickname.get(),
  1189. trust.GetTrust());
  1190. return MapSECStatus(srv);
  1191. }
  1192. NS_IMETHODIMP
  1193. nsNSSCertificateDB::AddCert(const nsACString& aCertDER, const nsACString& aTrust,
  1194. const nsACString& aName)
  1195. {
  1196. nsCString base64;
  1197. nsresult rv = Base64Encode(aCertDER, base64);
  1198. NS_ENSURE_SUCCESS(rv, rv);
  1199. return AddCertFromBase64(base64, aTrust, aName);
  1200. }
  1201. NS_IMETHODIMP
  1202. nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert* cert,
  1203. const nsACString& trustString)
  1204. {
  1205. NS_ENSURE_ARG(cert);
  1206. CERTCertTrust trust;
  1207. SECStatus srv = CERT_DecodeTrustString(&trust,
  1208. PromiseFlatCString(trustString).get());
  1209. if (srv != SECSuccess) {
  1210. return MapSECStatus(srv);
  1211. }
  1212. UniqueCERTCertificate nssCert(cert->GetCert());
  1213. nsresult rv = attemptToLogInWithDefaultPassword();
  1214. if (NS_WARN_IF(rv != NS_OK)) {
  1215. return rv;
  1216. }
  1217. srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nssCert.get(), &trust);
  1218. return MapSECStatus(srv);
  1219. }
  1220. NS_IMETHODIMP
  1221. nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
  1222. {
  1223. nsNSSShutDownPreventionLock locker;
  1224. if (isAlreadyShutDown()) {
  1225. return NS_ERROR_NOT_AVAILABLE;
  1226. }
  1227. nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
  1228. nsCOMPtr<nsIX509CertList> nssCertList;
  1229. UniqueCERTCertList certList(PK11_ListCerts(PK11CertListUnique, ctx));
  1230. // nsNSSCertList 1) adopts certList, and 2) handles the nullptr case fine.
  1231. // (returns an empty list)
  1232. nssCertList = new nsNSSCertList(Move(certList), locker);
  1233. nssCertList.forget(_retval);
  1234. return NS_OK;
  1235. }
  1236. NS_IMETHODIMP
  1237. nsNSSCertificateDB::GetEnterpriseRoots(nsIX509CertList** enterpriseRoots)
  1238. {
  1239. MOZ_ASSERT(NS_IsMainThread());
  1240. if (!NS_IsMainThread()) {
  1241. return NS_ERROR_NOT_SAME_THREAD;
  1242. }
  1243. NS_ENSURE_ARG_POINTER(enterpriseRoots);
  1244. nsNSSShutDownPreventionLock locker;
  1245. if (isAlreadyShutDown()) {
  1246. return NS_ERROR_NOT_AVAILABLE;
  1247. }
  1248. #ifdef XP_WIN
  1249. nsCOMPtr<nsINSSComponent> psm(do_GetService(PSM_COMPONENT_CONTRACTID));
  1250. if (!psm) {
  1251. return NS_ERROR_FAILURE;
  1252. }
  1253. return psm->GetEnterpriseRoots(enterpriseRoots);
  1254. #else
  1255. return NS_ERROR_NOT_IMPLEMENTED;
  1256. #endif
  1257. }
  1258. nsresult
  1259. VerifyCertAtTime(nsIX509Cert* aCert,
  1260. int64_t /*SECCertificateUsage*/ aUsage,
  1261. uint32_t aFlags,
  1262. const char* aHostname,
  1263. mozilla::pkix::Time aTime,
  1264. nsIX509CertList** aVerifiedChain,
  1265. bool* aHasEVPolicy,
  1266. int32_t* /*PRErrorCode*/ _retval,
  1267. const nsNSSShutDownPreventionLock& locker)
  1268. {
  1269. NS_ENSURE_ARG_POINTER(aCert);
  1270. NS_ENSURE_ARG_POINTER(aHasEVPolicy);
  1271. NS_ENSURE_ARG_POINTER(aVerifiedChain);
  1272. NS_ENSURE_ARG_POINTER(_retval);
  1273. *aVerifiedChain = nullptr;
  1274. *aHasEVPolicy = false;
  1275. *_retval = PR_UNKNOWN_ERROR;
  1276. UniqueCERTCertificate nssCert(aCert->GetCert());
  1277. if (!nssCert) {
  1278. return NS_ERROR_INVALID_ARG;
  1279. }
  1280. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  1281. NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
  1282. UniqueCERTCertList resultChain;
  1283. SECOidTag evOidPolicy;
  1284. mozilla::pkix::Result result;
  1285. if (aHostname && aUsage == certificateUsageSSLServer) {
  1286. result = certVerifier->VerifySSLServerCert(nssCert,
  1287. nullptr, // stapledOCSPResponse
  1288. nullptr, // sctsFromTLSExtension
  1289. aTime,
  1290. nullptr, // Assume no context
  1291. aHostname,
  1292. resultChain,
  1293. false, // don't save intermediates
  1294. aFlags,
  1295. NeckoOriginAttributes(),
  1296. &evOidPolicy);
  1297. } else {
  1298. result = certVerifier->VerifyCert(nssCert.get(), aUsage, aTime,
  1299. nullptr, // Assume no context
  1300. aHostname,
  1301. resultChain,
  1302. aFlags,
  1303. nullptr, // stapledOCSPResponse
  1304. nullptr, // sctsFromTLSExtension
  1305. NeckoOriginAttributes(),
  1306. &evOidPolicy);
  1307. }
  1308. nsCOMPtr<nsIX509CertList> nssCertList;
  1309. // This adopts the list
  1310. nssCertList = new nsNSSCertList(Move(resultChain), locker);
  1311. NS_ENSURE_TRUE(nssCertList, NS_ERROR_FAILURE);
  1312. *_retval = mozilla::pkix::MapResultToPRErrorCode(result);
  1313. if (result == mozilla::pkix::Success && evOidPolicy != SEC_OID_UNKNOWN) {
  1314. *aHasEVPolicy = true;
  1315. }
  1316. nssCertList.forget(aVerifiedChain);
  1317. return NS_OK;
  1318. }
  1319. NS_IMETHODIMP
  1320. nsNSSCertificateDB::VerifyCertNow(nsIX509Cert* aCert,
  1321. int64_t /*SECCertificateUsage*/ aUsage,
  1322. uint32_t aFlags,
  1323. const char* aHostname,
  1324. nsIX509CertList** aVerifiedChain,
  1325. bool* aHasEVPolicy,
  1326. int32_t* /*PRErrorCode*/ _retval)
  1327. {
  1328. nsNSSShutDownPreventionLock locker;
  1329. if (isAlreadyShutDown()) {
  1330. return NS_ERROR_NOT_AVAILABLE;
  1331. }
  1332. return ::VerifyCertAtTime(aCert, aUsage, aFlags, aHostname,
  1333. mozilla::pkix::Now(),
  1334. aVerifiedChain, aHasEVPolicy, _retval, locker);
  1335. }
  1336. NS_IMETHODIMP
  1337. nsNSSCertificateDB::VerifyCertAtTime(nsIX509Cert* aCert,
  1338. int64_t /*SECCertificateUsage*/ aUsage,
  1339. uint32_t aFlags,
  1340. const char* aHostname,
  1341. uint64_t aTime,
  1342. nsIX509CertList** aVerifiedChain,
  1343. bool* aHasEVPolicy,
  1344. int32_t* /*PRErrorCode*/ _retval)
  1345. {
  1346. nsNSSShutDownPreventionLock locker;
  1347. if (isAlreadyShutDown()) {
  1348. return NS_ERROR_NOT_AVAILABLE;
  1349. }
  1350. return ::VerifyCertAtTime(aCert, aUsage, aFlags, aHostname,
  1351. mozilla::pkix::TimeFromEpochInSeconds(aTime),
  1352. aVerifiedChain, aHasEVPolicy, _retval, locker);
  1353. }
  1354. class VerifyCertAtTimeTask final : public CryptoTask
  1355. {
  1356. public:
  1357. VerifyCertAtTimeTask(nsIX509Cert* aCert, int64_t aUsage, uint32_t aFlags,
  1358. const char* aHostname, uint64_t aTime,
  1359. nsICertVerificationCallback* aCallback)
  1360. : mCert(aCert)
  1361. , mUsage(aUsage)
  1362. , mFlags(aFlags)
  1363. , mHostname(aHostname)
  1364. , mTime(aTime)
  1365. , mCallback(new nsMainThreadPtrHolder<nsICertVerificationCallback>(aCallback))
  1366. , mPRErrorCode(SEC_ERROR_LIBRARY_FAILURE)
  1367. , mVerifiedCertList(nullptr)
  1368. , mHasEVPolicy(false)
  1369. {
  1370. }
  1371. private:
  1372. virtual nsresult CalculateResult() override
  1373. {
  1374. nsCOMPtr<nsIX509CertDB> certDB = do_GetService(NS_X509CERTDB_CONTRACTID);
  1375. if (!certDB) {
  1376. return NS_ERROR_FAILURE;
  1377. }
  1378. // Unfortunately mHostname will have made the empty string out of a null
  1379. // pointer passed in the constructor. If we pass the empty string on to
  1380. // VerifyCertAtTime with the usage certificateUsageSSLServer, it will call
  1381. // VerifySSLServerCert, which expects a non-empty hostname. To avoid this,
  1382. // check the length and use nullptr if appropriate.
  1383. const char* hostname = mHostname.Length() > 0 ? mHostname.get() : nullptr;
  1384. return certDB->VerifyCertAtTime(mCert, mUsage, mFlags, hostname, mTime,
  1385. getter_AddRefs(mVerifiedCertList),
  1386. &mHasEVPolicy, &mPRErrorCode);
  1387. }
  1388. // No NSS resources are directly held, so there is nothing to release.
  1389. virtual void ReleaseNSSResources() override { }
  1390. virtual void CallCallback(nsresult rv) override
  1391. {
  1392. if (NS_FAILED(rv)) {
  1393. Unused << mCallback->VerifyCertFinished(SEC_ERROR_LIBRARY_FAILURE,
  1394. nullptr, false);
  1395. } else {
  1396. Unused << mCallback->VerifyCertFinished(mPRErrorCode, mVerifiedCertList,
  1397. mHasEVPolicy);
  1398. }
  1399. }
  1400. nsCOMPtr<nsIX509Cert> mCert;
  1401. int64_t mUsage;
  1402. uint32_t mFlags;
  1403. nsCString mHostname;
  1404. uint64_t mTime;
  1405. nsMainThreadPtrHandle<nsICertVerificationCallback> mCallback;
  1406. int32_t mPRErrorCode;
  1407. nsCOMPtr<nsIX509CertList> mVerifiedCertList;
  1408. bool mHasEVPolicy;
  1409. };
  1410. NS_IMETHODIMP
  1411. nsNSSCertificateDB::AsyncVerifyCertAtTime(nsIX509Cert* aCert,
  1412. int64_t /*SECCertificateUsage*/ aUsage,
  1413. uint32_t aFlags,
  1414. const char* aHostname,
  1415. uint64_t aTime,
  1416. nsICertVerificationCallback* aCallback)
  1417. {
  1418. nsNSSShutDownPreventionLock locker;
  1419. if (isAlreadyShutDown()) {
  1420. return NS_ERROR_NOT_AVAILABLE;
  1421. }
  1422. RefPtr<VerifyCertAtTimeTask> task(new VerifyCertAtTimeTask(aCert, aUsage,
  1423. aFlags, aHostname,
  1424. aTime, aCallback));
  1425. return task->Dispatch("VerifyCert");
  1426. }
  1427. NS_IMETHODIMP
  1428. nsNSSCertificateDB::ClearOCSPCache()
  1429. {
  1430. nsNSSShutDownPreventionLock locker;
  1431. if (isAlreadyShutDown()) {
  1432. return NS_ERROR_NOT_AVAILABLE;
  1433. }
  1434. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  1435. NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
  1436. certVerifier->ClearOCSPCache();
  1437. return NS_OK;
  1438. }