1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
54 CERT_MatchNickname(char *name1
, char *name2
) {
55 char *nickname1
= NULL
;
56 char *nickname2
= NULL
;
62 /* first deal with the straight comparison */
63 if (PORT_Strcmp(name1
, name2
) == 0) {
66 /* we need to handle the case where one name has an explicit token and the other
68 token1
= PORT_Strchr(name1
,':');
69 token2
= PORT_Strchr(name2
,':');
70 if ((token1
&& token2
) || (!token1
&& !token2
)) {
71 /* either both token names are specified or neither are, not match */
83 len
= nickname1
-token
;
85 if (PORT_Strcmp(nickname1
,nickname2
) != 0) {
88 /* compare the other token with the internal slot here */
93 * Find all user certificates that match the given criteria.
95 * "handle" - database to search
96 * "usage" - certificate usage to match
97 * "oneCertPerName" - if set then only return the "best" cert per
99 * "validOnly" - only return certs that are curently valid
100 * "proto_win" - window handle passed to pkcs11
103 CERT_FindUserCertsByUsage(CERTCertDBHandle
*handle
,
105 PRBool oneCertPerName
,
109 CERTCertNicknames
*nicknames
= NULL
;
112 CERTCertificate
*cert
= NULL
;
113 CERTCertList
*certList
= NULL
;
116 CERTCertListNode
*node
= NULL
;
117 CERTCertListNode
*freenode
= NULL
;
122 nicknames
= CERT_GetCertNicknames(handle
, SEC_CERT_NICKNAMES_USER
,
125 if ( ( nicknames
== NULL
) || ( nicknames
->numnicknames
== 0 ) ) {
129 nnptr
= nicknames
->nicknames
;
130 nn
= nicknames
->numnicknames
;
134 /* use the pk11 call so that we pick up any certs on tokens,
135 * which may require login
137 if ( proto_win
!= NULL
) {
138 cert
= PK11_FindCertFromNickname(*nnptr
,proto_win
);
141 /* Sigh, It turns out if the cert is already in the temp db, because
142 * it's in the perm db, then the nickname lookup doesn't work.
143 * since we already have the cert here, though, than we can just call
144 * CERT_CreateSubjectCertList directly. For those cases where we didn't
145 * find the cert in pkcs #11 (because we didn't have a password arg,
146 * or because the nickname is for a peer, server, or CA cert, then we
147 * go look the cert up.
150 cert
= CERT_FindCertByNickname(handle
,*nnptr
);
153 if ( cert
!= NULL
) {
154 /* collect certs for this nickname, sorting them into the list */
155 certList
= CERT_CreateSubjectCertList(certList
, handle
,
156 &cert
->derSubject
, time
, validOnly
);
158 CERT_FilterCertListForUserCerts(certList
);
160 /* drop the extra reference */
161 CERT_DestroyCertificate(cert
);
168 /* remove certs with incorrect usage */
169 rv
= CERT_FilterCertListByUsage(certList
, usage
, PR_FALSE
);
171 if ( rv
!= SECSuccess
) {
175 /* remove any extra certs for each name */
176 if ( oneCertPerName
) {
179 nn
= nicknames
->numnicknames
;
180 nnptr
= nicknames
->nicknames
;
182 flags
= (PRBool
*)PORT_ZAlloc(sizeof(PRBool
) * nn
);
183 if ( flags
== NULL
) {
187 node
= CERT_LIST_HEAD(certList
);
189 /* treverse all certs in the list */
190 while ( !CERT_LIST_END(node
, certList
) ) {
192 /* find matching nickname index */
193 for ( n
= 0; n
< nn
; n
++ ) {
194 if ( CERT_MatchNickname(nnptr
[n
], node
->cert
->nickname
) ) {
195 /* We found a match. If this is the first one, then
196 * set the flag and move on to the next cert. If this
197 * is not the first one then delete it from the list.
200 /* We have already seen a cert with this nickname,
201 * so delete this one.
204 node
= CERT_LIST_NEXT(node
);
205 CERT_RemoveCertListNode(freenode
);
207 /* keep the first cert for each nickname, but set the
208 * flag so we know to delete any others with the same
212 node
= CERT_LIST_NEXT(node
);
218 /* if we get here it means that we didn't find a matching
219 * nickname, which should not happen.
222 node
= CERT_LIST_NEXT(node
);
231 if ( certList
!= NULL
) {
232 CERT_DestroyCertList(certList
);
237 if ( nicknames
!= NULL
) {
238 CERT_FreeNicknames(nicknames
);
245 * Find a user certificate that matchs the given criteria.
247 * "handle" - database to search
248 * "nickname" - nickname to match
249 * "usage" - certificate usage to match
250 * "validOnly" - only return certs that are curently valid
251 * "proto_win" - window handle passed to pkcs11
254 CERT_FindUserCertByUsage(CERTCertDBHandle
*handle
,
255 const char *nickname
,
260 CERTCertificate
*cert
= NULL
;
261 CERTCertList
*certList
= NULL
;
267 /* use the pk11 call so that we pick up any certs on tokens,
268 * which may require login
270 /* XXX - why is this restricted? */
271 if ( proto_win
!= NULL
) {
272 cert
= PK11_FindCertFromNickname(nickname
,proto_win
);
276 /* sigh, There are still problems find smart cards from the temp
277 * db. This will get smart cards working again. The real fix
278 * is to make sure we can search the temp db by their token nickname.
281 cert
= CERT_FindCertByNickname(handle
,nickname
);
284 if ( cert
!= NULL
) {
285 unsigned int requiredKeyUsage
;
286 unsigned int requiredCertType
;
288 rv
= CERT_KeyUsageAndTypeForCertUsage(usage
, PR_FALSE
,
289 &requiredKeyUsage
, &requiredCertType
);
290 if ( rv
!= SECSuccess
) {
291 /* drop the extra reference */
292 CERT_DestroyCertificate(cert
);
296 /* If we already found the right cert, just return it */
297 if ( (!validOnly
|| CERT_CheckCertValidTimes(cert
, time
, PR_FALSE
)
298 == secCertTimeValid
) &&
299 (CERT_CheckKeyUsage(cert
, requiredKeyUsage
) == SECSuccess
) &&
300 (cert
->nsCertType
& requiredCertType
) &&
301 CERT_IsUserCert(cert
) ) {
305 /* collect certs for this nickname, sorting them into the list */
306 certList
= CERT_CreateSubjectCertList(certList
, handle
,
307 &cert
->derSubject
, time
, validOnly
);
309 CERT_FilterCertListForUserCerts(certList
);
311 /* drop the extra reference */
312 CERT_DestroyCertificate(cert
);
316 if ( certList
== NULL
) {
320 /* remove certs with incorrect usage */
321 rv
= CERT_FilterCertListByUsage(certList
, usage
, PR_FALSE
);
323 if ( rv
!= SECSuccess
) {
327 if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList
), certList
) ) {
328 cert
= CERT_DupCertificate(CERT_LIST_HEAD(certList
)->cert
);
332 if ( certList
!= NULL
) {
333 CERT_DestroyCertList(certList
);
340 CERT_MatchUserCert(CERTCertDBHandle
*handle
,
342 int nCANames
, char **caNames
,
345 CERTCertList
*certList
= NULL
;
348 certList
= CERT_FindUserCertsByUsage(handle
, usage
, PR_TRUE
, PR_TRUE
,
350 if ( certList
== NULL
) {
354 rv
= CERT_FilterCertListByCANames(certList
, nCANames
, caNames
, usage
);
355 if ( rv
!= SECSuccess
) {
362 if ( certList
!= NULL
) {
363 CERT_DestroyCertList(certList
);
373 typedef struct stringNode
{
374 struct stringNode
*next
;
379 CollectNicknames( NSSCertificate
*c
, void *data
)
381 CERTCertNicknames
*names
;
382 PRBool saveit
= PR_FALSE
;
390 char *nickname
= NULL
;
392 names
= (CERTCertNicknames
*)data
;
394 stanNickname
= nssCertificate_GetNickname(c
,NULL
);
396 if ( stanNickname
) {
397 if (names
->what
== SEC_CERT_NICKNAMES_USER
) {
398 saveit
= NSSCertificate_IsPrivateKeyAvailable(c
, NULL
, NULL
);
402 td
= NSSCertificate_GetTrustDomain(c
);
406 trust
= nssTrustDomain_FindTrustForCertificate(td
,c
);
408 switch(names
->what
) {
409 case SEC_CERT_NICKNAMES_ALL
:
410 if ((trust
->sslFlags
& (CERTDB_VALID_CA
|CERTDB_VALID_PEER
) ) ||
411 (trust
->emailFlags
& (CERTDB_VALID_CA
|CERTDB_VALID_PEER
) ) ||
412 (trust
->objectSigningFlags
&
413 (CERTDB_VALID_CA
|CERTDB_VALID_PEER
))) {
418 case SEC_CERT_NICKNAMES_SERVER
:
419 if ( trust
->sslFlags
& CERTDB_VALID_PEER
) {
424 case SEC_CERT_NICKNAMES_CA
:
425 if (((trust
->sslFlags
& CERTDB_VALID_CA
) == CERTDB_VALID_CA
)||
426 ((trust
->emailFlags
& CERTDB_VALID_CA
) == CERTDB_VALID_CA
) ||
427 ((trust
->objectSigningFlags
& CERTDB_VALID_CA
)
428 == CERTDB_VALID_CA
)) {
437 /* traverse the list of collected nicknames and make sure we don't make
441 nickname
= STAN_GetCERTCertificateName(NULL
, c
);
442 /* nickname can only be NULL here if we are having memory
444 if (nickname
== NULL
) {
447 node
= (stringNode
*)names
->head
;
448 while ( node
!= NULL
) {
449 if ( PORT_Strcmp(nickname
, node
->string
) == 0 ) {
450 /* if the string matches, then don't save this one */
460 /* allocate the node */
461 node
= (stringNode
*)PORT_ArenaAlloc(names
->arena
, sizeof(stringNode
));
462 if ( node
== NULL
) {
467 /* copy the string */
468 len
= PORT_Strlen(nickname
) + 1;
469 node
->string
= (char*)PORT_ArenaAlloc(names
->arena
, len
);
470 if ( node
->string
== NULL
) {
474 PORT_Memcpy(node
->string
, nickname
, len
);
476 /* link it into the list */
477 node
->next
= (stringNode
*)names
->head
;
478 names
->head
= (void *)node
;
481 names
->numnicknames
++;
484 if (nickname
) PORT_Free(nickname
);
489 CERT_GetCertNicknames(CERTCertDBHandle
*handle
, int what
, void *wincx
)
492 CERTCertNicknames
*names
;
496 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
497 if ( arena
== NULL
) {
498 PORT_SetError(SEC_ERROR_NO_MEMORY
);
502 names
= (CERTCertNicknames
*)PORT_ArenaAlloc(arena
, sizeof(CERTCertNicknames
));
503 if ( names
== NULL
) {
507 names
->arena
= arena
;
509 names
->numnicknames
= 0;
510 names
->nicknames
= NULL
;
514 /* make sure we are logged in */
515 (void) pk11_TraverseAllSlots(NULL
, NULL
, PR_TRUE
, wincx
);
517 NSSTrustDomain_TraverseCertificates(handle
,
518 CollectNicknames
, (void *)names
);
519 if ( names
->numnicknames
) {
520 names
->nicknames
= (char**)PORT_ArenaAlloc(arena
,
521 names
->numnicknames
* sizeof(char *));
523 if ( names
->nicknames
== NULL
) {
527 node
= (stringNode
*)names
->head
;
529 for ( i
= 0; i
< names
->numnicknames
; i
++ ) {
530 PORT_Assert(node
!= NULL
);
532 names
->nicknames
[i
] = node
->string
;
533 names
->totallen
+= PORT_Strlen(node
->string
);
537 PORT_Assert(node
== NULL
);
543 PORT_FreeArena(arena
, PR_FALSE
);
548 CERT_FreeNicknames(CERTCertNicknames
*nicknames
)
550 PORT_FreeArena(nicknames
->arena
, PR_FALSE
);
555 /* [ FROM pcertdb.c ] */
557 typedef struct dnameNode
{
558 struct dnameNode
*next
;
563 CERT_FreeDistNames(CERTDistNames
*names
)
565 PORT_FreeArena(names
->arena
, PR_FALSE
);
571 CollectDistNames( CERTCertificate
*cert
, SECItem
*k
, void *data
)
573 CERTDistNames
*names
;
574 PRBool saveit
= PR_FALSE
;
575 CERTCertTrust
*trust
;
579 names
= (CERTDistNames
*)data
;
584 /* only collect names of CAs trusted for issuing SSL clients */
585 if ( trust
->sslFlags
& CERTDB_TRUSTED_CLIENT_CA
) {
591 /* allocate the node */
592 node
= (dnameNode
*)PORT_ArenaAlloc(names
->arena
, sizeof(dnameNode
));
593 if ( node
== NULL
) {
598 node
->name
.len
= len
= cert
->derSubject
.len
;
599 node
->name
.type
= siBuffer
;
600 node
->name
.data
= (unsigned char*)PORT_ArenaAlloc(names
->arena
, len
);
601 if ( node
->name
.data
== NULL
) {
604 PORT_Memcpy(node
->name
.data
, cert
->derSubject
.data
, len
);
606 /* link it into the list */
607 node
->next
= (dnameNode
*)names
->head
;
608 names
->head
= (void *)node
;
618 * Return all of the CAs that are "trusted" for SSL.
621 CERT_GetSSLCACerts(CERTCertDBHandle
*handle
)
624 CERTDistNames
*names
;
629 /* allocate an arena to use */
630 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
631 if ( arena
== NULL
) {
632 PORT_SetError(SEC_ERROR_NO_MEMORY
);
636 /* allocate the header structure */
637 names
= (CERTDistNames
*)PORT_ArenaAlloc(arena
, sizeof(CERTDistNames
));
638 if ( names
== NULL
) {
642 /* initialize the header struct */
643 names
->arena
= arena
;
648 /* collect the names from the database */
649 rv
= PK11_TraverseSlotCerts(CollectDistNames
, (void *)names
, NULL
);
654 /* construct the array from the list */
655 if ( names
->nnames
) {
656 names
->names
= (SECItem
*)PORT_ArenaAlloc(arena
, names
->nnames
* sizeof(SECItem
));
658 if ( names
->names
== NULL
) {
662 node
= (dnameNode
*)names
->head
;
664 for ( i
= 0; i
< names
->nnames
; i
++ ) {
665 PORT_Assert(node
!= NULL
);
667 names
->names
[i
] = node
->name
;
671 PORT_Assert(node
== NULL
);
677 PORT_FreeArena(arena
, PR_FALSE
);
682 CERT_DistNamesFromNicknames(CERTCertDBHandle
*handle
, char **nicknames
,
685 CERTDistNames
*dnames
= NULL
;
688 SECItem
*names
= NULL
;
689 CERTCertificate
*cert
= NULL
;
691 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
692 if (arena
== NULL
) goto loser
;
693 dnames
= PORT_ArenaZNew(arena
, CERTDistNames
);
694 if (dnames
== NULL
) goto loser
;
696 dnames
->arena
= arena
;
697 dnames
->nnames
= nnames
;
698 dnames
->names
= names
= PORT_ArenaZNewArray(arena
, SECItem
, nnames
);
699 if (names
== NULL
) goto loser
;
701 for (i
= 0; i
< nnames
; i
++) {
702 cert
= CERT_FindCertByNicknameOrEmailAddr(handle
, nicknames
[i
]);
703 if (cert
== NULL
) goto loser
;
704 rv
= SECITEM_CopyItem(arena
, &names
[i
], &cert
->derSubject
);
705 if (rv
== SECFailure
) goto loser
;
706 CERT_DestroyCertificate(cert
);
712 CERT_DestroyCertificate(cert
);
714 PORT_FreeArena(arena
, PR_FALSE
);
718 /* [ from pcertdb.c - calls Ascii to Name ] */
720 * Lookup a certificate in the database by name
723 CERT_FindCertByNameString(CERTCertDBHandle
*handle
, char *nameStr
)
727 CERTCertificate
*cert
= NULL
;
728 PRArenaPool
*arena
= NULL
;
730 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
732 if ( arena
== NULL
) {
736 name
= CERT_AsciiToName(nameStr
);
739 nameItem
= SEC_ASN1EncodeItem (arena
, NULL
, (void *)name
,
741 if ( nameItem
!= NULL
) {
742 cert
= CERT_FindCertByName(handle
, nameItem
);
744 CERT_DestroyName(name
);
749 PORT_FreeArena(arena
, PR_FALSE
);
757 CERTCrlDistributionPoints
*
758 CERT_FindCRLDistributionPoints (CERTCertificate
*cert
)
760 SECItem encodedExtenValue
;
762 CERTCrlDistributionPoints
*dps
;
764 encodedExtenValue
.data
= NULL
;
765 encodedExtenValue
.len
= 0;
767 rv
= cert_FindExtension(cert
->extensions
, SEC_OID_X509_CRL_DIST_POINTS
,
769 if ( rv
!= SECSuccess
) {
773 dps
= CERT_DecodeCRLDistributionPoints(cert
->arena
, &encodedExtenValue
);
775 PORT_Free(encodedExtenValue
.data
);
781 CERTSignedCrl
* CERT_ImportCRL
782 (CERTCertDBHandle
*handle
, SECItem
*derCRL
, char *url
, int type
, void *wincx
)
784 CERTSignedCrl
* retCrl
= NULL
;
785 PK11SlotInfo
* slot
= PK11_GetInternalKeySlot();
786 retCrl
= PK11_ImportCRL(slot
, derCRL
, url
, type
, wincx
,
787 CRL_IMPORT_DEFAULT_OPTIONS
, NULL
, CRL_DECODE_DEFAULT_OPTIONS
);
795 cert_ImportCAChain(SECItem
*certs
, int numcerts
, SECCertUsage certUsage
, PRBool trusted
)
799 CERTCertificate
*cert
= NULL
;
800 CERTCertificate
*newcert
= NULL
;
801 CERTCertDBHandle
*handle
;
805 unsigned int certtype
;
807 handle
= CERT_GetDefaultCertDB();
813 /* decode my certificate */
814 /* This use is ok -- only looks at decoded parts, calls NewTemp later */
815 newcert
= CERT_DecodeDERCertificate(derCert
, PR_FALSE
, NULL
);
816 if ( newcert
== NULL
) {
821 /* make sure that cert is valid */
822 rv
= CERT_CertTimesValid(newcert
);
823 if ( rv
== SECFailure
) {
828 /* does it have the CA extension */
831 * Make sure that if this is an intermediate CA in the chain that
832 * it was given permission by its signer to be a CA.
834 isca
= CERT_IsCACert(newcert
, &certtype
);
840 trust
.sslFlags
= CERTDB_VALID_CA
;
841 trust
.emailFlags
= CERTDB_VALID_CA
;
842 trust
.objectSigningFlags
= CERTDB_VALID_CA
;
844 /* SSL ca's must have the ssl bit set */
845 if ( ( certUsage
== certUsageSSLCA
) &&
846 (( certtype
& NS_CERT_TYPE_SSL_CA
) != NS_CERT_TYPE_SSL_CA
)) {
850 /* it passed all of the tests, so lets add it to the database */
851 /* mark it as a CA */
852 PORT_Memset((void *)&trust
, 0, sizeof(trust
));
853 switch ( certUsage
) {
855 trust
.sslFlags
= CERTDB_VALID_CA
;
857 case certUsageUserCertImport
:
858 if ((certtype
& NS_CERT_TYPE_SSL_CA
) == NS_CERT_TYPE_SSL_CA
) {
859 trust
.sslFlags
= CERTDB_VALID_CA
;
861 if ((certtype
& NS_CERT_TYPE_EMAIL_CA
)
862 == NS_CERT_TYPE_EMAIL_CA
) {
863 trust
.emailFlags
= CERTDB_VALID_CA
;
865 if ( ( certtype
& NS_CERT_TYPE_OBJECT_SIGNING_CA
) ==
866 NS_CERT_TYPE_OBJECT_SIGNING_CA
) {
867 trust
.objectSigningFlags
= CERTDB_VALID_CA
;
876 cert
= CERT_NewTempCertificate(handle
, derCert
, NULL
,
878 if ( cert
== NULL
) {
882 /* if the cert is temp, make it perm; otherwise we're done */
884 /* get a default nickname for it */
885 nickname
= CERT_MakeCANickname(cert
);
887 rv
= CERT_AddTempCertToPerm(cert
, nickname
, &trust
);
889 /* free the nickname */
897 CERT_DestroyCertificate(cert
);
900 if ( rv
!= SECSuccess
) {
906 CERT_DestroyCertificate(newcert
);
919 CERT_DestroyCertificate(newcert
);
924 CERT_DestroyCertificate(cert
);
932 CERT_ImportCAChain(SECItem
*certs
, int numcerts
, SECCertUsage certUsage
)
934 return cert_ImportCAChain(certs
, numcerts
, certUsage
, PR_FALSE
);
938 CERT_ImportCAChainTrusted(SECItem
*certs
, int numcerts
, SECCertUsage certUsage
) {
939 return cert_ImportCAChain(certs
, numcerts
, certUsage
, PR_TRUE
);
942 /* Moved from certdb.c */
944 ** CERT_CertChainFromCert
946 ** Construct a CERTCertificateList consisting of the given certificate and all
947 ** of the issuer certs until we either get to a self-signed cert or can't find
948 ** an issuer. Since we don't know how many certs are in the chain we have to
949 ** build a linked list first as we count them.
952 typedef struct certNode
{
953 struct certNode
*next
;
954 CERTCertificate
*cert
;
957 CERTCertificateList
*
958 CERT_CertChainFromCert(CERTCertificate
*cert
, SECCertUsage usage
,
961 CERTCertificateList
*chain
= NULL
;
962 NSSCertificate
**stanChain
;
963 NSSCertificate
*stanCert
;
967 NSSTrustDomain
*td
= STAN_GetDefaultTrustDomain();
968 NSSCryptoContext
*cc
= STAN_GetDefaultCryptoContext();
970 stanCert
= STAN_GetNSSCertificate(cert
);
972 /* error code is set */
975 nssUsage
.anyUsage
= PR_FALSE
;
976 nssUsage
.nss3usage
= usage
;
977 nssUsage
.nss3lookingForCA
= PR_FALSE
;
978 stanChain
= NSSCertificate_BuildChain(stanCert
, NULL
, &nssUsage
, NULL
, NULL
,
979 CERT_MAX_CERT_CHAIN
, NULL
, NULL
, td
, cc
);
981 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER
);
986 stanCert
= stanChain
[0];
988 stanCert
= stanChain
[++len
];
991 arena
= PORT_NewArena(4096);
996 chain
= (CERTCertificateList
*)PORT_ArenaAlloc(arena
,
997 sizeof(CERTCertificateList
));
998 if (!chain
) goto loser
;
999 chain
->certs
= (SECItem
*)PORT_ArenaAlloc(arena
, len
* sizeof(SECItem
));
1000 if (!chain
->certs
) goto loser
;
1002 stanCert
= stanChain
[i
];
1005 CERTCertificate
*cCert
= STAN_GetCERTCertificate(stanCert
);
1009 derCert
.len
= (unsigned int)stanCert
->encoding
.size
;
1010 derCert
.data
= (unsigned char *)stanCert
->encoding
.data
;
1011 derCert
.type
= siBuffer
;
1012 SECITEM_CopyItem(arena
, &chain
->certs
[i
], &derCert
);
1013 stanCert
= stanChain
[++i
];
1014 if (!stanCert
&& !cCert
->isRoot
) {
1015 /* reached the end of the chain, but the final cert is
1016 * not a root. Don't discard it.
1018 includeRoot
= PR_TRUE
;
1020 CERT_DestroyCertificate(cCert
);
1022 if ( !includeRoot
&& len
> 1) {
1023 chain
->len
= len
- 1;
1028 chain
->arena
= arena
;
1029 nss_ZFreeIf(stanChain
);
1033 stanCert
= stanChain
[i
];
1035 CERTCertificate
*cCert
= STAN_GetCERTCertificate(stanCert
);
1037 CERT_DestroyCertificate(cCert
);
1039 stanCert
= stanChain
[++i
];
1041 nss_ZFreeIf(stanChain
);
1043 PORT_FreeArena(arena
, PR_FALSE
);
1048 /* Builds a CERTCertificateList holding just one DER-encoded cert, namely
1049 ** the one for the cert passed as an argument.
1051 CERTCertificateList
*
1052 CERT_CertListFromCert(CERTCertificate
*cert
)
1054 CERTCertificateList
*chain
= NULL
;
1058 /* arena for SecCertificateList */
1059 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1060 if (arena
== NULL
) goto no_memory
;
1062 /* build the CERTCertificateList */
1063 chain
= (CERTCertificateList
*)PORT_ArenaAlloc(arena
, sizeof(CERTCertificateList
));
1064 if (chain
== NULL
) goto no_memory
;
1065 chain
->certs
= (SECItem
*)PORT_ArenaAlloc(arena
, 1 * sizeof(SECItem
));
1066 if (chain
->certs
== NULL
) goto no_memory
;
1067 rv
= SECITEM_CopyItem(arena
, chain
->certs
, &(cert
->derCert
));
1068 if (rv
< 0) goto loser
;
1070 chain
->arena
= arena
;
1075 PORT_SetError(SEC_ERROR_NO_MEMORY
);
1077 if (arena
!= NULL
) {
1078 PORT_FreeArena(arena
, PR_FALSE
);
1083 CERTCertificateList
*
1084 CERT_DupCertList(CERTCertificateList
* oldList
)
1086 CERTCertificateList
*newList
= NULL
;
1087 PRArenaPool
*arena
= NULL
;
1090 int len
= oldList
->len
;
1093 /* arena for SecCertificateList */
1094 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1098 /* now build the CERTCertificateList */
1099 newList
= PORT_ArenaNew(arena
, CERTCertificateList
);
1100 if (newList
== NULL
)
1102 newList
->arena
= arena
;
1103 newItem
= (SECItem
*)PORT_ArenaAlloc(arena
, len
* sizeof(SECItem
));
1104 if (newItem
== NULL
)
1106 newList
->certs
= newItem
;
1109 for (oldItem
= oldList
->certs
; len
> 0; --len
, ++newItem
, ++oldItem
) {
1110 rv
= SECITEM_CopyItem(arena
, newItem
, oldItem
);
1117 PORT_SetError(SEC_ERROR_NO_MEMORY
);
1119 if (arena
!= NULL
) {
1120 PORT_FreeArena(arena
, PR_FALSE
);
1126 CERT_DestroyCertificateList(CERTCertificateList
*list
)
1128 PORT_FreeArena(list
->arena
, PR_FALSE
);