certhigh.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  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 "nspr.h"
  5. #include "secerr.h"
  6. #include "secasn1.h"
  7. #include "seccomon.h"
  8. #include "pk11func.h"
  9. #include "certdb.h"
  10. #include "certt.h"
  11. #include "cert.h"
  12. #include "certxutl.h"
  13. #include "certi.h"
  14. #include "nsspki.h"
  15. #include "pki.h"
  16. #include "pkit.h"
  17. #include "pkitm.h"
  18. #include "pki3hack.h"
  19. PRBool
  20. CERT_MatchNickname(char *name1, char *name2)
  21. {
  22. char *nickname1 = NULL;
  23. char *nickname2 = NULL;
  24. char *token1;
  25. char *token2;
  26. /* first deal with the straight comparison */
  27. if (PORT_Strcmp(name1, name2) == 0) {
  28. return PR_TRUE;
  29. }
  30. /* we need to handle the case where one name has an explicit token and the other
  31. * doesn't */
  32. token1 = PORT_Strchr(name1, ':');
  33. token2 = PORT_Strchr(name2, ':');
  34. if ((token1 && token2) || (!token1 && !token2)) {
  35. /* either both token names are specified or neither are, not match */
  36. return PR_FALSE;
  37. }
  38. if (token1) {
  39. nickname1 = token1;
  40. nickname2 = name2;
  41. } else {
  42. nickname1 = token2;
  43. nickname2 = name1;
  44. }
  45. nickname1++;
  46. if (PORT_Strcmp(nickname1, nickname2) != 0) {
  47. return PR_FALSE;
  48. }
  49. /* Bug 1192443 - compare the other token with the internal slot here */
  50. return PR_TRUE;
  51. }
  52. /*
  53. * Find all user certificates that match the given criteria.
  54. *
  55. * "handle" - database to search
  56. * "usage" - certificate usage to match
  57. * "oneCertPerName" - if set then only return the "best" cert per
  58. * name
  59. * "validOnly" - only return certs that are curently valid
  60. * "proto_win" - window handle passed to pkcs11
  61. */
  62. CERTCertList *
  63. CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
  64. SECCertUsage usage,
  65. PRBool oneCertPerName,
  66. PRBool validOnly,
  67. void *proto_win)
  68. {
  69. CERTCertNicknames *nicknames = NULL;
  70. char **nnptr;
  71. int nn;
  72. CERTCertificate *cert = NULL;
  73. CERTCertList *certList = NULL;
  74. SECStatus rv;
  75. PRTime time;
  76. CERTCertListNode *node = NULL;
  77. CERTCertListNode *freenode = NULL;
  78. int n;
  79. time = PR_Now();
  80. nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
  81. proto_win);
  82. if ((nicknames == NULL) || (nicknames->numnicknames == 0)) {
  83. goto loser;
  84. }
  85. nnptr = nicknames->nicknames;
  86. nn = nicknames->numnicknames;
  87. while (nn > 0) {
  88. cert = NULL;
  89. /* use the pk11 call so that we pick up any certs on tokens,
  90. * which may require login
  91. */
  92. if (proto_win != NULL) {
  93. cert = PK11_FindCertFromNickname(*nnptr, proto_win);
  94. }
  95. /* Sigh, It turns out if the cert is already in the temp db, because
  96. * it's in the perm db, then the nickname lookup doesn't work.
  97. * since we already have the cert here, though, than we can just call
  98. * CERT_CreateSubjectCertList directly. For those cases where we didn't
  99. * find the cert in pkcs #11 (because we didn't have a password arg,
  100. * or because the nickname is for a peer, server, or CA cert, then we
  101. * go look the cert up.
  102. */
  103. if (cert == NULL) {
  104. cert = CERT_FindCertByNickname(handle, *nnptr);
  105. }
  106. if (cert != NULL) {
  107. /* collect certs for this nickname, sorting them into the list */
  108. certList = CERT_CreateSubjectCertList(certList, handle,
  109. &cert->derSubject, time, validOnly);
  110. CERT_FilterCertListForUserCerts(certList);
  111. /* drop the extra reference */
  112. CERT_DestroyCertificate(cert);
  113. }
  114. nnptr++;
  115. nn--;
  116. }
  117. /* remove certs with incorrect usage */
  118. rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
  119. if (rv != SECSuccess) {
  120. goto loser;
  121. }
  122. /* remove any extra certs for each name */
  123. if (oneCertPerName) {
  124. PRBool *flags;
  125. nn = nicknames->numnicknames;
  126. nnptr = nicknames->nicknames;
  127. if (!certList) {
  128. goto loser;
  129. }
  130. flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
  131. if (flags == NULL) {
  132. goto loser;
  133. }
  134. node = CERT_LIST_HEAD(certList);
  135. /* treverse all certs in the list */
  136. while (!CERT_LIST_END(node, certList)) {
  137. /* find matching nickname index */
  138. for (n = 0; n < nn; n++) {
  139. if (CERT_MatchNickname(nnptr[n], node->cert->nickname)) {
  140. /* We found a match. If this is the first one, then
  141. * set the flag and move on to the next cert. If this
  142. * is not the first one then delete it from the list.
  143. */
  144. if (flags[n]) {
  145. /* We have already seen a cert with this nickname,
  146. * so delete this one.
  147. */
  148. freenode = node;
  149. node = CERT_LIST_NEXT(node);
  150. CERT_RemoveCertListNode(freenode);
  151. } else {
  152. /* keep the first cert for each nickname, but set the
  153. * flag so we know to delete any others with the same
  154. * nickname.
  155. */
  156. flags[n] = PR_TRUE;
  157. node = CERT_LIST_NEXT(node);
  158. }
  159. break;
  160. }
  161. }
  162. if (n == nn) {
  163. /* if we get here it means that we didn't find a matching
  164. * nickname, which should not happen.
  165. */
  166. PORT_Assert(0);
  167. node = CERT_LIST_NEXT(node);
  168. }
  169. }
  170. PORT_Free(flags);
  171. }
  172. goto done;
  173. loser:
  174. if (certList != NULL) {
  175. CERT_DestroyCertList(certList);
  176. certList = NULL;
  177. }
  178. done:
  179. if (nicknames != NULL) {
  180. CERT_FreeNicknames(nicknames);
  181. }
  182. return (certList);
  183. }
  184. /*
  185. * Find a user certificate that matchs the given criteria.
  186. *
  187. * "handle" - database to search
  188. * "nickname" - nickname to match
  189. * "usage" - certificate usage to match
  190. * "validOnly" - only return certs that are curently valid
  191. * "proto_win" - window handle passed to pkcs11
  192. */
  193. CERTCertificate *
  194. CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
  195. const char *nickname,
  196. SECCertUsage usage,
  197. PRBool validOnly,
  198. void *proto_win)
  199. {
  200. CERTCertificate *cert = NULL;
  201. CERTCertList *certList = NULL;
  202. SECStatus rv;
  203. PRTime time;
  204. time = PR_Now();
  205. /* use the pk11 call so that we pick up any certs on tokens,
  206. * which may require login
  207. */
  208. /* XXX - why is this restricted? */
  209. if (proto_win != NULL) {
  210. cert = PK11_FindCertFromNickname(nickname, proto_win);
  211. }
  212. /* sigh, There are still problems find smart cards from the temp
  213. * db. This will get smart cards working again. The real fix
  214. * is to make sure we can search the temp db by their token nickname.
  215. */
  216. if (cert == NULL) {
  217. cert = CERT_FindCertByNickname(handle, nickname);
  218. }
  219. if (cert != NULL) {
  220. unsigned int requiredKeyUsage;
  221. unsigned int requiredCertType;
  222. rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
  223. &requiredKeyUsage, &requiredCertType);
  224. if (rv != SECSuccess) {
  225. /* drop the extra reference */
  226. CERT_DestroyCertificate(cert);
  227. cert = NULL;
  228. goto loser;
  229. }
  230. /* If we already found the right cert, just return it */
  231. if ((!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) == secCertTimeValid) &&
  232. (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
  233. (cert->nsCertType & requiredCertType) &&
  234. CERT_IsUserCert(cert)) {
  235. return (cert);
  236. }
  237. /* collect certs for this nickname, sorting them into the list */
  238. certList = CERT_CreateSubjectCertList(certList, handle,
  239. &cert->derSubject, time, validOnly);
  240. CERT_FilterCertListForUserCerts(certList);
  241. /* drop the extra reference */
  242. CERT_DestroyCertificate(cert);
  243. cert = NULL;
  244. }
  245. if (certList == NULL) {
  246. goto loser;
  247. }
  248. /* remove certs with incorrect usage */
  249. rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
  250. if (rv != SECSuccess) {
  251. goto loser;
  252. }
  253. if (!CERT_LIST_EMPTY(certList)) {
  254. cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
  255. }
  256. loser:
  257. if (certList != NULL) {
  258. CERT_DestroyCertList(certList);
  259. }
  260. return (cert);
  261. }
  262. CERTCertList *
  263. CERT_MatchUserCert(CERTCertDBHandle *handle,
  264. SECCertUsage usage,
  265. int nCANames, char **caNames,
  266. void *proto_win)
  267. {
  268. CERTCertList *certList = NULL;
  269. SECStatus rv;
  270. certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
  271. proto_win);
  272. if (certList == NULL) {
  273. goto loser;
  274. }
  275. rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
  276. if (rv != SECSuccess) {
  277. goto loser;
  278. }
  279. goto done;
  280. loser:
  281. if (certList != NULL) {
  282. CERT_DestroyCertList(certList);
  283. certList = NULL;
  284. }
  285. done:
  286. return (certList);
  287. }
  288. typedef struct stringNode {
  289. struct stringNode *next;
  290. char *string;
  291. } stringNode;
  292. static PRStatus
  293. CollectNicknames(NSSCertificate *c, void *data)
  294. {
  295. CERTCertNicknames *names;
  296. PRBool saveit = PR_FALSE;
  297. stringNode *node;
  298. int len;
  299. #ifdef notdef
  300. NSSTrustDomain *td;
  301. NSSTrust *trust;
  302. #endif
  303. char *stanNickname;
  304. char *nickname = NULL;
  305. names = (CERTCertNicknames *)data;
  306. stanNickname = nssCertificate_GetNickname(c, NULL);
  307. if (stanNickname) {
  308. nss_ZFreeIf(stanNickname);
  309. stanNickname = NULL;
  310. if (names->what == SEC_CERT_NICKNAMES_USER) {
  311. saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
  312. }
  313. #ifdef notdef
  314. else {
  315. td = NSSCertificate_GetTrustDomain(c);
  316. if (!td) {
  317. return PR_SUCCESS;
  318. }
  319. trust = nssTrustDomain_FindTrustForCertificate(td, c);
  320. switch (names->what) {
  321. case SEC_CERT_NICKNAMES_ALL:
  322. if ((trust->sslFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
  323. (trust->emailFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
  324. (trust->objectSigningFlags &
  325. (CERTDB_VALID_CA | CERTDB_VALID_PEER))) {
  326. saveit = PR_TRUE;
  327. }
  328. break;
  329. case SEC_CERT_NICKNAMES_SERVER:
  330. if (trust->sslFlags & CERTDB_VALID_PEER) {
  331. saveit = PR_TRUE;
  332. }
  333. break;
  334. case SEC_CERT_NICKNAMES_CA:
  335. if (((trust->sslFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
  336. ((trust->emailFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
  337. ((trust->objectSigningFlags & CERTDB_VALID_CA) ==
  338. CERTDB_VALID_CA)) {
  339. saveit = PR_TRUE;
  340. }
  341. break;
  342. }
  343. }
  344. #endif
  345. }
  346. /* traverse the list of collected nicknames and make sure we don't make
  347. * a duplicate
  348. */
  349. if (saveit) {
  350. nickname = STAN_GetCERTCertificateName(NULL, c);
  351. /* nickname can only be NULL here if we are having memory
  352. * alloc problems */
  353. if (nickname == NULL) {
  354. return PR_FAILURE;
  355. }
  356. node = (stringNode *)names->head;
  357. while (node != NULL) {
  358. if (PORT_Strcmp(nickname, node->string) == 0) {
  359. /* if the string matches, then don't save this one */
  360. saveit = PR_FALSE;
  361. break;
  362. }
  363. node = node->next;
  364. }
  365. }
  366. if (saveit) {
  367. /* allocate the node */
  368. node = (stringNode *)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
  369. if (node == NULL) {
  370. PORT_Free(nickname);
  371. return PR_FAILURE;
  372. }
  373. /* copy the string */
  374. len = PORT_Strlen(nickname) + 1;
  375. node->string = (char *)PORT_ArenaAlloc(names->arena, len);
  376. if (node->string == NULL) {
  377. PORT_Free(nickname);
  378. return PR_FAILURE;
  379. }
  380. PORT_Memcpy(node->string, nickname, len);
  381. /* link it into the list */
  382. node->next = (stringNode *)names->head;
  383. names->head = (void *)node;
  384. /* bump the count */
  385. names->numnicknames++;
  386. }
  387. if (nickname)
  388. PORT_Free(nickname);
  389. return (PR_SUCCESS);
  390. }
  391. CERTCertNicknames *
  392. CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
  393. {
  394. PLArenaPool *arena;
  395. CERTCertNicknames *names;
  396. int i;
  397. stringNode *node;
  398. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  399. if (arena == NULL) {
  400. PORT_SetError(SEC_ERROR_NO_MEMORY);
  401. return (NULL);
  402. }
  403. names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
  404. if (names == NULL) {
  405. goto loser;
  406. }
  407. names->arena = arena;
  408. names->head = NULL;
  409. names->numnicknames = 0;
  410. names->nicknames = NULL;
  411. names->what = what;
  412. names->totallen = 0;
  413. /* make sure we are logged in */
  414. (void)pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);
  415. NSSTrustDomain_TraverseCertificates(handle,
  416. CollectNicknames, (void *)names);
  417. if (names->numnicknames) {
  418. names->nicknames = (char **)PORT_ArenaAlloc(arena,
  419. names->numnicknames *
  420. sizeof(char *));
  421. if (names->nicknames == NULL) {
  422. goto loser;
  423. }
  424. node = (stringNode *)names->head;
  425. for (i = 0; i < names->numnicknames; i++) {
  426. PORT_Assert(node != NULL);
  427. names->nicknames[i] = node->string;
  428. names->totallen += PORT_Strlen(node->string);
  429. node = node->next;
  430. }
  431. PORT_Assert(node == NULL);
  432. }
  433. return (names);
  434. loser:
  435. PORT_FreeArena(arena, PR_FALSE);
  436. return (NULL);
  437. }
  438. void
  439. CERT_FreeNicknames(CERTCertNicknames *nicknames)
  440. {
  441. PORT_FreeArena(nicknames->arena, PR_FALSE);
  442. return;
  443. }
  444. /* [ FROM pcertdb.c ] */
  445. typedef struct dnameNode {
  446. struct dnameNode *next;
  447. SECItem name;
  448. } dnameNode;
  449. void
  450. CERT_FreeDistNames(CERTDistNames *names)
  451. {
  452. PORT_FreeArena(names->arena, PR_FALSE);
  453. return;
  454. }
  455. static SECStatus
  456. CollectDistNames(CERTCertificate *cert, SECItem *k, void *data)
  457. {
  458. CERTDistNames *names;
  459. PRBool saveit = PR_FALSE;
  460. CERTCertTrust trust;
  461. dnameNode *node;
  462. int len;
  463. names = (CERTDistNames *)data;
  464. if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
  465. /* only collect names of CAs trusted for issuing SSL clients */
  466. if (trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA) {
  467. saveit = PR_TRUE;
  468. }
  469. }
  470. if (saveit) {
  471. /* allocate the node */
  472. node = (dnameNode *)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
  473. if (node == NULL) {
  474. return (SECFailure);
  475. }
  476. /* copy the name */
  477. node->name.len = len = cert->derSubject.len;
  478. node->name.type = siBuffer;
  479. node->name.data = (unsigned char *)PORT_ArenaAlloc(names->arena, len);
  480. if (node->name.data == NULL) {
  481. return (SECFailure);
  482. }
  483. PORT_Memcpy(node->name.data, cert->derSubject.data, len);
  484. /* link it into the list */
  485. node->next = (dnameNode *)names->head;
  486. names->head = (void *)node;
  487. /* bump the count */
  488. names->nnames++;
  489. }
  490. return (SECSuccess);
  491. }
  492. /*
  493. * Return all of the CAs that are "trusted" for SSL.
  494. */
  495. CERTDistNames *
  496. CERT_DupDistNames(CERTDistNames *orig)
  497. {
  498. PLArenaPool *arena;
  499. CERTDistNames *names;
  500. int i;
  501. SECStatus rv;
  502. /* allocate an arena to use */
  503. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  504. if (arena == NULL) {
  505. PORT_SetError(SEC_ERROR_NO_MEMORY);
  506. return (NULL);
  507. }
  508. /* allocate the header structure */
  509. names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
  510. if (names == NULL) {
  511. goto loser;
  512. }
  513. /* initialize the header struct */
  514. names->arena = arena;
  515. names->head = NULL;
  516. names->nnames = orig->nnames;
  517. names->names = NULL;
  518. /* construct the array from the list */
  519. if (orig->nnames) {
  520. names->names = (SECItem *)PORT_ArenaNewArray(arena, SECItem,
  521. orig->nnames);
  522. if (names->names == NULL) {
  523. goto loser;
  524. }
  525. for (i = 0; i < orig->nnames; i++) {
  526. rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
  527. if (rv != SECSuccess) {
  528. goto loser;
  529. }
  530. }
  531. }
  532. return (names);
  533. loser:
  534. PORT_FreeArena(arena, PR_FALSE);
  535. return (NULL);
  536. }
  537. CERTDistNames *
  538. CERT_GetSSLCACerts(CERTCertDBHandle *handle)
  539. {
  540. PLArenaPool *arena;
  541. CERTDistNames *names;
  542. int i;
  543. SECStatus rv;
  544. dnameNode *node;
  545. /* allocate an arena to use */
  546. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  547. if (arena == NULL) {
  548. PORT_SetError(SEC_ERROR_NO_MEMORY);
  549. return (NULL);
  550. }
  551. /* allocate the header structure */
  552. names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
  553. if (names == NULL) {
  554. goto loser;
  555. }
  556. /* initialize the header struct */
  557. names->arena = arena;
  558. names->head = NULL;
  559. names->nnames = 0;
  560. names->names = NULL;
  561. /* collect the names from the database */
  562. rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
  563. if (rv) {
  564. goto loser;
  565. }
  566. /* construct the array from the list */
  567. if (names->nnames) {
  568. names->names = (SECItem *)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
  569. if (names->names == NULL) {
  570. goto loser;
  571. }
  572. node = (dnameNode *)names->head;
  573. for (i = 0; i < names->nnames; i++) {
  574. PORT_Assert(node != NULL);
  575. names->names[i] = node->name;
  576. node = node->next;
  577. }
  578. PORT_Assert(node == NULL);
  579. }
  580. return (names);
  581. loser:
  582. PORT_FreeArena(arena, PR_FALSE);
  583. return (NULL);
  584. }
  585. CERTDistNames *
  586. CERT_DistNamesFromCertList(CERTCertList *certList)
  587. {
  588. CERTDistNames *dnames = NULL;
  589. PLArenaPool *arena;
  590. CERTCertListNode *node = NULL;
  591. SECItem *names = NULL;
  592. int listLen = 0, i = 0;
  593. if (certList == NULL) {
  594. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  595. return NULL;
  596. }
  597. node = CERT_LIST_HEAD(certList);
  598. while (!CERT_LIST_END(node, certList)) {
  599. listLen += 1;
  600. node = CERT_LIST_NEXT(node);
  601. }
  602. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  603. if (arena == NULL)
  604. goto loser;
  605. dnames = PORT_ArenaZNew(arena, CERTDistNames);
  606. if (dnames == NULL)
  607. goto loser;
  608. dnames->arena = arena;
  609. dnames->nnames = listLen;
  610. dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
  611. if (names == NULL)
  612. goto loser;
  613. node = CERT_LIST_HEAD(certList);
  614. while (!CERT_LIST_END(node, certList)) {
  615. CERTCertificate *cert = node->cert;
  616. SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
  617. if (rv == SECFailure) {
  618. goto loser;
  619. }
  620. node = CERT_LIST_NEXT(node);
  621. }
  622. return dnames;
  623. loser:
  624. if (arena) {
  625. PORT_FreeArena(arena, PR_FALSE);
  626. }
  627. return NULL;
  628. }
  629. CERTDistNames *
  630. CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
  631. int nnames)
  632. {
  633. CERTDistNames *dnames = NULL;
  634. PLArenaPool *arena;
  635. int i, rv;
  636. SECItem *names = NULL;
  637. CERTCertificate *cert = NULL;
  638. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  639. if (arena == NULL)
  640. goto loser;
  641. dnames = PORT_ArenaZNew(arena, CERTDistNames);
  642. if (dnames == NULL)
  643. goto loser;
  644. dnames->arena = arena;
  645. dnames->nnames = nnames;
  646. dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
  647. if (names == NULL)
  648. goto loser;
  649. for (i = 0; i < nnames; i++) {
  650. cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
  651. if (cert == NULL)
  652. goto loser;
  653. rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
  654. if (rv == SECFailure)
  655. goto loser;
  656. CERT_DestroyCertificate(cert);
  657. }
  658. return dnames;
  659. loser:
  660. if (cert != NULL)
  661. CERT_DestroyCertificate(cert);
  662. if (arena != NULL)
  663. PORT_FreeArena(arena, PR_FALSE);
  664. return NULL;
  665. }
  666. /* [ from pcertdb.c - calls Ascii to Name ] */
  667. /*
  668. * Lookup a certificate in the database by name
  669. */
  670. CERTCertificate *
  671. CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
  672. {
  673. CERTName *name;
  674. SECItem *nameItem;
  675. CERTCertificate *cert = NULL;
  676. PLArenaPool *arena = NULL;
  677. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  678. if (arena == NULL) {
  679. goto loser;
  680. }
  681. name = CERT_AsciiToName(nameStr);
  682. if (name) {
  683. nameItem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
  684. CERT_NameTemplate);
  685. if (nameItem != NULL) {
  686. cert = CERT_FindCertByName(handle, nameItem);
  687. }
  688. CERT_DestroyName(name);
  689. }
  690. loser:
  691. if (arena) {
  692. PORT_FreeArena(arena, PR_FALSE);
  693. }
  694. return (cert);
  695. }
  696. /* From certv3.c */
  697. CERTCrlDistributionPoints *
  698. CERT_FindCRLDistributionPoints(CERTCertificate *cert)
  699. {
  700. SECItem encodedExtenValue;
  701. SECStatus rv;
  702. CERTCrlDistributionPoints *dps;
  703. encodedExtenValue.data = NULL;
  704. encodedExtenValue.len = 0;
  705. rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
  706. &encodedExtenValue);
  707. if (rv != SECSuccess) {
  708. return (NULL);
  709. }
  710. dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);
  711. PORT_Free(encodedExtenValue.data);
  712. return dps;
  713. }
  714. /* From crl.c */
  715. CERTSignedCrl *
  716. CERT_ImportCRL(CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
  717. {
  718. CERTSignedCrl *retCrl = NULL;
  719. PK11SlotInfo *slot = PK11_GetInternalKeySlot();
  720. retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
  721. CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
  722. PK11_FreeSlot(slot);
  723. return retCrl;
  724. }
  725. /* From certdb.c */
  726. static SECStatus
  727. cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
  728. {
  729. SECStatus rv;
  730. SECItem *derCert;
  731. CERTCertificate *cert = NULL;
  732. CERTCertificate *newcert = NULL;
  733. CERTCertDBHandle *handle;
  734. CERTCertTrust trust;
  735. PRBool isca;
  736. char *nickname;
  737. unsigned int certtype;
  738. PRBool istemp = PR_FALSE;
  739. handle = CERT_GetDefaultCertDB();
  740. while (numcerts--) {
  741. derCert = certs;
  742. certs++;
  743. /* decode my certificate */
  744. /* This use is ok -- only looks at decoded parts, calls NewTemp later */
  745. newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
  746. if (newcert == NULL) {
  747. goto loser;
  748. }
  749. if (!trusted) {
  750. /* make sure that cert is valid */
  751. rv = CERT_CertTimesValid(newcert);
  752. if (rv == SECFailure) {
  753. goto endloop;
  754. }
  755. }
  756. /* does it have the CA extension */
  757. /*
  758. * Make sure that if this is an intermediate CA in the chain that
  759. * it was given permission by its signer to be a CA.
  760. */
  761. isca = CERT_IsCACert(newcert, &certtype);
  762. if (!isca) {
  763. if (!trusted) {
  764. goto endloop;
  765. }
  766. trust.sslFlags = CERTDB_VALID_CA;
  767. trust.emailFlags = CERTDB_VALID_CA;
  768. trust.objectSigningFlags = CERTDB_VALID_CA;
  769. } else {
  770. /* SSL ca's must have the ssl bit set */
  771. if ((certUsage == certUsageSSLCA) &&
  772. ((certtype & NS_CERT_TYPE_SSL_CA) != NS_CERT_TYPE_SSL_CA)) {
  773. goto endloop;
  774. }
  775. /* it passed all of the tests, so lets add it to the database */
  776. /* mark it as a CA */
  777. PORT_Memset((void *)&trust, 0, sizeof(trust));
  778. switch (certUsage) {
  779. case certUsageSSLCA:
  780. trust.sslFlags = CERTDB_VALID_CA;
  781. break;
  782. case certUsageUserCertImport:
  783. if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
  784. trust.sslFlags = CERTDB_VALID_CA;
  785. }
  786. if ((certtype & NS_CERT_TYPE_EMAIL_CA) ==
  787. NS_CERT_TYPE_EMAIL_CA) {
  788. trust.emailFlags = CERTDB_VALID_CA;
  789. }
  790. if ((certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA) ==
  791. NS_CERT_TYPE_OBJECT_SIGNING_CA) {
  792. trust.objectSigningFlags = CERTDB_VALID_CA;
  793. }
  794. break;
  795. default:
  796. PORT_Assert(0);
  797. break;
  798. }
  799. }
  800. cert = CERT_NewTempCertificate(handle, derCert, NULL,
  801. PR_FALSE, PR_FALSE);
  802. if (cert == NULL) {
  803. goto loser;
  804. }
  805. /* if the cert is temp, make it perm; otherwise we're done */
  806. rv = CERT_GetCertIsTemp(cert, &istemp);
  807. if (rv != SECSuccess) {
  808. goto loser;
  809. }
  810. if (istemp) {
  811. /* get a default nickname for it */
  812. nickname = CERT_MakeCANickname(cert);
  813. rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
  814. /* free the nickname */
  815. if (nickname) {
  816. PORT_Free(nickname);
  817. }
  818. } else {
  819. rv = SECSuccess;
  820. }
  821. if (rv != SECSuccess) {
  822. goto loser;
  823. }
  824. endloop:
  825. if (newcert) {
  826. CERT_DestroyCertificate(newcert);
  827. newcert = NULL;
  828. }
  829. }
  830. rv = SECSuccess;
  831. goto done;
  832. loser:
  833. rv = SECFailure;
  834. done:
  835. if (newcert) {
  836. CERT_DestroyCertificate(newcert);
  837. newcert = NULL;
  838. }
  839. if (cert) {
  840. CERT_DestroyCertificate(cert);
  841. cert = NULL;
  842. }
  843. return (rv);
  844. }
  845. SECStatus
  846. CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
  847. {
  848. return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
  849. }
  850. SECStatus
  851. CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage)
  852. {
  853. return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
  854. }
  855. /* Moved from certdb.c */
  856. /*
  857. ** CERT_CertChainFromCert
  858. **
  859. ** Construct a CERTCertificateList consisting of the given certificate and all
  860. ** of the issuer certs until we either get to a self-signed cert or can't find
  861. ** an issuer. Since we don't know how many certs are in the chain we have to
  862. ** build a linked list first as we count them.
  863. */
  864. typedef struct certNode {
  865. struct certNode *next;
  866. CERTCertificate *cert;
  867. } certNode;
  868. CERTCertificateList *
  869. CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
  870. PRBool includeRoot)
  871. {
  872. CERTCertificateList *chain = NULL;
  873. NSSCertificate **stanChain;
  874. NSSCertificate *stanCert;
  875. PLArenaPool *arena;
  876. NSSUsage nssUsage;
  877. int i, len;
  878. NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
  879. NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();
  880. stanCert = STAN_GetNSSCertificate(cert);
  881. if (!stanCert) {
  882. /* error code is set */
  883. return NULL;
  884. }
  885. nssUsage.anyUsage = PR_FALSE;
  886. nssUsage.nss3usage = usage;
  887. nssUsage.nss3lookingForCA = PR_FALSE;
  888. stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
  889. CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
  890. if (!stanChain) {
  891. PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
  892. return NULL;
  893. }
  894. len = 0;
  895. stanCert = stanChain[0];
  896. while (stanCert) {
  897. stanCert = stanChain[++len];
  898. }
  899. arena = PORT_NewArena(4096);
  900. if (arena == NULL) {
  901. goto loser;
  902. }
  903. chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
  904. sizeof(CERTCertificateList));
  905. if (!chain)
  906. goto loser;
  907. chain->certs = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
  908. if (!chain->certs)
  909. goto loser;
  910. i = 0;
  911. stanCert = stanChain[i];
  912. while (stanCert) {
  913. SECItem derCert;
  914. CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
  915. if (!cCert) {
  916. goto loser;
  917. }
  918. derCert.len = (unsigned int)stanCert->encoding.size;
  919. derCert.data = (unsigned char *)stanCert->encoding.data;
  920. derCert.type = siBuffer;
  921. if (SECITEM_CopyItem(arena, &chain->certs[i], &derCert) != SECSuccess) {
  922. CERT_DestroyCertificate(cCert);
  923. goto loser;
  924. }
  925. stanCert = stanChain[++i];
  926. if (!stanCert && !cCert->isRoot) {
  927. /* reached the end of the chain, but the final cert is
  928. * not a root. Don't discard it.
  929. */
  930. includeRoot = PR_TRUE;
  931. }
  932. CERT_DestroyCertificate(cCert);
  933. }
  934. if (!includeRoot && len > 1) {
  935. chain->len = len - 1;
  936. } else {
  937. chain->len = len;
  938. }
  939. chain->arena = arena;
  940. nss_ZFreeIf(stanChain);
  941. return chain;
  942. loser:
  943. i = 0;
  944. stanCert = stanChain[i];
  945. while (stanCert) {
  946. CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
  947. if (cCert) {
  948. CERT_DestroyCertificate(cCert);
  949. }
  950. stanCert = stanChain[++i];
  951. }
  952. nss_ZFreeIf(stanChain);
  953. if (arena) {
  954. PORT_FreeArena(arena, PR_FALSE);
  955. }
  956. return NULL;
  957. }
  958. /* Builds a CERTCertificateList holding just one DER-encoded cert, namely
  959. ** the one for the cert passed as an argument.
  960. */
  961. CERTCertificateList *
  962. CERT_CertListFromCert(CERTCertificate *cert)
  963. {
  964. CERTCertificateList *chain = NULL;
  965. int rv;
  966. PLArenaPool *arena;
  967. /* arena for SecCertificateList */
  968. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  969. if (arena == NULL)
  970. goto no_memory;
  971. /* build the CERTCertificateList */
  972. chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
  973. if (chain == NULL)
  974. goto no_memory;
  975. chain->certs = (SECItem *)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
  976. if (chain->certs == NULL)
  977. goto no_memory;
  978. rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
  979. if (rv < 0)
  980. goto loser;
  981. chain->len = 1;
  982. chain->arena = arena;
  983. return chain;
  984. no_memory:
  985. PORT_SetError(SEC_ERROR_NO_MEMORY);
  986. loser:
  987. if (arena != NULL) {
  988. PORT_FreeArena(arena, PR_FALSE);
  989. }
  990. return NULL;
  991. }
  992. CERTCertificateList *
  993. CERT_DupCertList(const CERTCertificateList *oldList)
  994. {
  995. CERTCertificateList *newList = NULL;
  996. PLArenaPool *arena = NULL;
  997. SECItem *newItem;
  998. SECItem *oldItem;
  999. int len = oldList->len;
  1000. int rv;
  1001. /* arena for SecCertificateList */
  1002. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1003. if (arena == NULL)
  1004. goto no_memory;
  1005. /* now build the CERTCertificateList */
  1006. newList = PORT_ArenaNew(arena, CERTCertificateList);
  1007. if (newList == NULL)
  1008. goto no_memory;
  1009. newList->arena = arena;
  1010. newItem = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
  1011. if (newItem == NULL)
  1012. goto no_memory;
  1013. newList->certs = newItem;
  1014. newList->len = len;
  1015. for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
  1016. rv = SECITEM_CopyItem(arena, newItem, oldItem);
  1017. if (rv < 0)
  1018. goto loser;
  1019. }
  1020. return newList;
  1021. no_memory:
  1022. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1023. loser:
  1024. if (arena != NULL) {
  1025. PORT_FreeArena(arena, PR_FALSE);
  1026. }
  1027. return NULL;
  1028. }
  1029. void
  1030. CERT_DestroyCertificateList(CERTCertificateList *list)
  1031. {
  1032. PORT_FreeArena(list->arena, PR_FALSE);
  1033. }