certhigh.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:26k
源码类别:

CA认证

开发平台:

WINDOWS

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