|
Packit |
40b132 |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
40b132 |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
40b132 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
40b132 |
#include "nspr.h"
|
|
Packit |
40b132 |
#include "secerr.h"
|
|
Packit |
40b132 |
#include "secasn1.h"
|
|
Packit |
40b132 |
#include "seccomon.h"
|
|
Packit |
40b132 |
#include "pk11func.h"
|
|
Packit |
40b132 |
#include "certdb.h"
|
|
Packit |
40b132 |
#include "certt.h"
|
|
Packit |
40b132 |
#include "cert.h"
|
|
Packit |
40b132 |
#include "certxutl.h"
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
#include "nsspki.h"
|
|
Packit |
40b132 |
#include "pki.h"
|
|
Packit |
40b132 |
#include "pkit.h"
|
|
Packit |
40b132 |
#include "pkitm.h"
|
|
Packit |
40b132 |
#include "pki3hack.h"
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PRBool
|
|
Packit |
40b132 |
CERT_MatchNickname(char *name1, char *name2) {
|
|
Packit |
40b132 |
char *nickname1= NULL;
|
|
Packit |
40b132 |
char *nickname2 = NULL;
|
|
Packit |
40b132 |
char *token1;
|
|
Packit |
40b132 |
char *token2;
|
|
Packit |
40b132 |
char *token = NULL;
|
|
Packit |
40b132 |
int len;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* first deal with the straight comparison */
|
|
Packit |
40b132 |
if (PORT_Strcmp(name1, name2) == 0) {
|
|
Packit |
40b132 |
return PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
/* we need to handle the case where one name has an explicit token and the other
|
|
Packit |
40b132 |
* doesn't */
|
|
Packit |
40b132 |
token1 = PORT_Strchr(name1,':');
|
|
Packit |
40b132 |
token2 = PORT_Strchr(name2,':');
|
|
Packit |
40b132 |
if ((token1 && token2) || (!token1 && !token2)) {
|
|
Packit |
40b132 |
/* either both token names are specified or neither are, not match */
|
|
Packit |
40b132 |
return PR_FALSE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (token1) {
|
|
Packit |
40b132 |
token=name1;
|
|
Packit |
40b132 |
nickname1=token1;
|
|
Packit |
40b132 |
nickname2=name2;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
token=name2;
|
|
Packit |
40b132 |
nickname1=token2;
|
|
Packit |
40b132 |
nickname2=name1;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
len = nickname1-token;
|
|
Packit |
40b132 |
nickname1++;
|
|
Packit |
40b132 |
if (PORT_Strcmp(nickname1,nickname2) != 0) {
|
|
Packit |
40b132 |
return PR_FALSE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
/* compare the other token with the internal slot here */
|
|
Packit |
40b132 |
return PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Find all user certificates that match the given criteria.
|
|
Packit |
40b132 |
*
|
|
Packit |
40b132 |
* "handle" - database to search
|
|
Packit |
40b132 |
* "usage" - certificate usage to match
|
|
Packit |
40b132 |
* "oneCertPerName" - if set then only return the "best" cert per
|
|
Packit |
40b132 |
* name
|
|
Packit |
40b132 |
* "validOnly" - only return certs that are curently valid
|
|
Packit |
40b132 |
* "proto_win" - window handle passed to pkcs11
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
CERTCertList *
|
|
Packit |
40b132 |
CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
|
|
Packit |
40b132 |
SECCertUsage usage,
|
|
Packit |
40b132 |
PRBool oneCertPerName,
|
|
Packit |
40b132 |
PRBool validOnly,
|
|
Packit |
40b132 |
void *proto_win)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertNicknames *nicknames = NULL;
|
|
Packit |
40b132 |
char **nnptr;
|
|
Packit |
40b132 |
int nn;
|
|
Packit |
40b132 |
CERTCertificate *cert = NULL;
|
|
Packit |
40b132 |
CERTCertList *certList = NULL;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
PRTime time;
|
|
Packit |
40b132 |
CERTCertListNode *node = NULL;
|
|
Packit |
40b132 |
CERTCertListNode *freenode = NULL;
|
|
Packit |
40b132 |
int n;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
time = PR_Now();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
|
|
Packit |
40b132 |
proto_win);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
nnptr = nicknames->nicknames;
|
|
Packit |
40b132 |
nn = nicknames->numnicknames;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
while ( nn > 0 ) {
|
|
Packit |
40b132 |
cert = NULL;
|
|
Packit |
40b132 |
/* use the pk11 call so that we pick up any certs on tokens,
|
|
Packit |
40b132 |
* which may require login
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if ( proto_win != NULL ) {
|
|
Packit |
40b132 |
cert = PK11_FindCertFromNickname(*nnptr,proto_win);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* Sigh, It turns out if the cert is already in the temp db, because
|
|
Packit |
40b132 |
* it's in the perm db, then the nickname lookup doesn't work.
|
|
Packit |
40b132 |
* since we already have the cert here, though, than we can just call
|
|
Packit |
40b132 |
* CERT_CreateSubjectCertList directly. For those cases where we didn't
|
|
Packit |
40b132 |
* find the cert in pkcs #11 (because we didn't have a password arg,
|
|
Packit |
40b132 |
* or because the nickname is for a peer, server, or CA cert, then we
|
|
Packit |
40b132 |
* go look the cert up.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if (cert == NULL) {
|
|
Packit |
40b132 |
cert = CERT_FindCertByNickname(handle,*nnptr);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( cert != NULL ) {
|
|
Packit |
40b132 |
/* collect certs for this nickname, sorting them into the list */
|
|
Packit |
40b132 |
certList = CERT_CreateSubjectCertList(certList, handle,
|
|
Packit |
40b132 |
&cert->derSubject, time, validOnly);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERT_FilterCertListForUserCerts(certList);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* drop the extra reference */
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
nnptr++;
|
|
Packit |
40b132 |
nn--;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* remove certs with incorrect usage */
|
|
Packit |
40b132 |
rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* remove any extra certs for each name */
|
|
Packit |
40b132 |
if ( oneCertPerName ) {
|
|
Packit |
40b132 |
PRBool *flags;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
nn = nicknames->numnicknames;
|
|
Packit |
40b132 |
nnptr = nicknames->nicknames;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
|
|
Packit |
40b132 |
if ( flags == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
node = CERT_LIST_HEAD(certList);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* treverse all certs in the list */
|
|
Packit |
40b132 |
while ( !CERT_LIST_END(node, certList) ) {
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* find matching nickname index */
|
|
Packit |
40b132 |
for ( n = 0; n < nn; n++ ) {
|
|
Packit |
40b132 |
if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) {
|
|
Packit |
40b132 |
/* We found a match. If this is the first one, then
|
|
Packit |
40b132 |
* set the flag and move on to the next cert. If this
|
|
Packit |
40b132 |
* is not the first one then delete it from the list.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if ( flags[n] ) {
|
|
Packit |
40b132 |
/* We have already seen a cert with this nickname,
|
|
Packit |
40b132 |
* so delete this one.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
freenode = node;
|
|
Packit |
40b132 |
node = CERT_LIST_NEXT(node);
|
|
Packit |
40b132 |
CERT_RemoveCertListNode(freenode);
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
/* keep the first cert for each nickname, but set the
|
|
Packit |
40b132 |
* flag so we know to delete any others with the same
|
|
Packit |
40b132 |
* nickname.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
flags[n] = PR_TRUE;
|
|
Packit |
40b132 |
node = CERT_LIST_NEXT(node);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if ( n == nn ) {
|
|
Packit |
40b132 |
/* if we get here it means that we didn't find a matching
|
|
Packit |
40b132 |
* nickname, which should not happen.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
PORT_Assert(0);
|
|
Packit |
40b132 |
node = CERT_LIST_NEXT(node);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
PORT_Free(flags);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
goto done;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if ( certList != NULL ) {
|
|
Packit |
40b132 |
CERT_DestroyCertList(certList);
|
|
Packit |
40b132 |
certList = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
done:
|
|
Packit |
40b132 |
if ( nicknames != NULL ) {
|
|
Packit |
40b132 |
CERT_FreeNicknames(nicknames);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(certList);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Find a user certificate that matchs the given criteria.
|
|
Packit |
40b132 |
*
|
|
Packit |
40b132 |
* "handle" - database to search
|
|
Packit |
40b132 |
* "nickname" - nickname to match
|
|
Packit |
40b132 |
* "usage" - certificate usage to match
|
|
Packit |
40b132 |
* "validOnly" - only return certs that are curently valid
|
|
Packit |
40b132 |
* "proto_win" - window handle passed to pkcs11
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
CERTCertificate *
|
|
Packit |
40b132 |
CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
|
|
Packit |
40b132 |
const char *nickname,
|
|
Packit |
40b132 |
SECCertUsage usage,
|
|
Packit |
40b132 |
PRBool validOnly,
|
|
Packit |
40b132 |
void *proto_win)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertificate *cert = NULL;
|
|
Packit |
40b132 |
CERTCertList *certList = NULL;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
PRTime time;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
time = PR_Now();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* use the pk11 call so that we pick up any certs on tokens,
|
|
Packit |
40b132 |
* which may require login
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
/* XXX - why is this restricted? */
|
|
Packit |
40b132 |
if ( proto_win != NULL ) {
|
|
Packit |
40b132 |
cert = PK11_FindCertFromNickname(nickname,proto_win);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* sigh, There are still problems find smart cards from the temp
|
|
Packit |
40b132 |
* db. This will get smart cards working again. The real fix
|
|
Packit |
40b132 |
* is to make sure we can search the temp db by their token nickname.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if (cert == NULL) {
|
|
Packit |
40b132 |
cert = CERT_FindCertByNickname(handle,nickname);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( cert != NULL ) {
|
|
Packit |
40b132 |
unsigned int requiredKeyUsage;
|
|
Packit |
40b132 |
unsigned int requiredCertType;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
|
|
Packit |
40b132 |
&requiredKeyUsage, &requiredCertType);
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
/* drop the extra reference */
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
cert = NULL;
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
/* If we already found the right cert, just return it */
|
|
Packit |
40b132 |
if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE)
|
|
Packit |
40b132 |
== secCertTimeValid) &&
|
|
Packit |
40b132 |
(CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
|
|
Packit |
40b132 |
(cert->nsCertType & requiredCertType) &&
|
|
Packit |
40b132 |
CERT_IsUserCert(cert) ) {
|
|
Packit |
40b132 |
return(cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* collect certs for this nickname, sorting them into the list */
|
|
Packit |
40b132 |
certList = CERT_CreateSubjectCertList(certList, handle,
|
|
Packit |
40b132 |
&cert->derSubject, time, validOnly);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERT_FilterCertListForUserCerts(certList);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* drop the extra reference */
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
cert = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( certList == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* remove certs with incorrect usage */
|
|
Packit |
40b132 |
rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) {
|
|
Packit |
40b132 |
cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if ( certList != NULL ) {
|
|
Packit |
40b132 |
CERT_DestroyCertList(certList);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTCertList *
|
|
Packit |
40b132 |
CERT_MatchUserCert(CERTCertDBHandle *handle,
|
|
Packit |
40b132 |
SECCertUsage usage,
|
|
Packit |
40b132 |
int nCANames, char **caNames,
|
|
Packit |
40b132 |
void *proto_win)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertList *certList = NULL;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
|
|
Packit |
40b132 |
proto_win);
|
|
Packit |
40b132 |
if ( certList == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
goto done;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if ( certList != NULL ) {
|
|
Packit |
40b132 |
CERT_DestroyCertList(certList);
|
|
Packit |
40b132 |
certList = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
done:
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(certList);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
typedef struct stringNode {
|
|
Packit |
40b132 |
struct stringNode *next;
|
|
Packit |
40b132 |
char *string;
|
|
Packit |
40b132 |
} stringNode;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
static PRStatus
|
|
Packit |
40b132 |
CollectNicknames( NSSCertificate *c, void *data)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertNicknames *names;
|
|
Packit |
40b132 |
PRBool saveit = PR_FALSE;
|
|
Packit |
40b132 |
stringNode *node;
|
|
Packit |
40b132 |
int len;
|
|
Packit |
40b132 |
#ifdef notdef
|
|
Packit |
40b132 |
NSSTrustDomain *td;
|
|
Packit |
40b132 |
NSSTrust *trust;
|
|
Packit |
40b132 |
#endif
|
|
Packit |
40b132 |
char *stanNickname;
|
|
Packit |
40b132 |
char *nickname = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names = (CERTCertNicknames *)data;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
stanNickname = nssCertificate_GetNickname(c,NULL);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( stanNickname ) {
|
|
Packit |
40b132 |
nss_ZFreeIf(stanNickname);
|
|
Packit |
40b132 |
stanNickname = NULL;
|
|
Packit |
40b132 |
if (names->what == SEC_CERT_NICKNAMES_USER) {
|
|
Packit |
40b132 |
saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
#ifdef notdef
|
|
Packit |
40b132 |
else {
|
|
Packit |
40b132 |
td = NSSCertificate_GetTrustDomain(c);
|
|
Packit |
40b132 |
if (!td) {
|
|
Packit |
40b132 |
return PR_SUCCESS;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
trust = nssTrustDomain_FindTrustForCertificate(td,c);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
switch(names->what) {
|
|
Packit |
40b132 |
case SEC_CERT_NICKNAMES_ALL:
|
|
Packit |
40b132 |
if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
|
|
Packit |
40b132 |
(trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
|
|
Packit |
40b132 |
(trust->objectSigningFlags &
|
|
Packit |
40b132 |
(CERTDB_VALID_CA|CERTDB_VALID_PEER))) {
|
|
Packit |
40b132 |
saveit = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case SEC_CERT_NICKNAMES_SERVER:
|
|
Packit |
40b132 |
if ( trust->sslFlags & CERTDB_VALID_PEER ) {
|
|
Packit |
40b132 |
saveit = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case SEC_CERT_NICKNAMES_CA:
|
|
Packit |
40b132 |
if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)||
|
|
Packit |
40b132 |
((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) ||
|
|
Packit |
40b132 |
((trust->objectSigningFlags & CERTDB_VALID_CA )
|
|
Packit |
40b132 |
== CERTDB_VALID_CA)) {
|
|
Packit |
40b132 |
saveit = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
#endif
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* traverse the list of collected nicknames and make sure we don't make
|
|
Packit |
40b132 |
* a duplicate
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
if ( saveit ) {
|
|
Packit |
40b132 |
nickname = STAN_GetCERTCertificateName(NULL, c);
|
|
Packit |
40b132 |
/* nickname can only be NULL here if we are having memory
|
|
Packit |
40b132 |
* alloc problems */
|
|
Packit |
40b132 |
if (nickname == NULL) {
|
|
Packit |
40b132 |
return PR_FAILURE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
node = (stringNode *)names->head;
|
|
Packit |
40b132 |
while ( node != NULL ) {
|
|
Packit |
40b132 |
if ( PORT_Strcmp(nickname, node->string) == 0 ) {
|
|
Packit |
40b132 |
/* if the string matches, then don't save this one */
|
|
Packit |
40b132 |
saveit = PR_FALSE;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
node = node->next;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( saveit ) {
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* allocate the node */
|
|
Packit |
40b132 |
node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
|
|
Packit |
40b132 |
if ( node == NULL ) {
|
|
Packit |
40b132 |
PORT_Free(nickname);
|
|
Packit |
40b132 |
return PR_FAILURE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* copy the string */
|
|
Packit |
40b132 |
len = PORT_Strlen(nickname) + 1;
|
|
Packit |
40b132 |
node->string = (char*)PORT_ArenaAlloc(names->arena, len);
|
|
Packit |
40b132 |
if ( node->string == NULL ) {
|
|
Packit |
40b132 |
PORT_Free(nickname);
|
|
Packit |
40b132 |
return PR_FAILURE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
PORT_Memcpy(node->string, nickname, len);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* link it into the list */
|
|
Packit |
40b132 |
node->next = (stringNode *)names->head;
|
|
Packit |
40b132 |
names->head = (void *)node;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* bump the count */
|
|
Packit |
40b132 |
names->numnicknames++;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (nickname) PORT_Free(nickname);
|
|
Packit |
40b132 |
return(PR_SUCCESS);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTCertNicknames *
|
|
Packit |
40b132 |
CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
CERTCertNicknames *names;
|
|
Packit |
40b132 |
int i;
|
|
Packit |
40b132 |
stringNode *node;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if ( arena == NULL ) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
|
|
Packit |
40b132 |
if ( names == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names->arena = arena;
|
|
Packit |
40b132 |
names->head = NULL;
|
|
Packit |
40b132 |
names->numnicknames = 0;
|
|
Packit |
40b132 |
names->nicknames = NULL;
|
|
Packit |
40b132 |
names->what = what;
|
|
Packit |
40b132 |
names->totallen = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* make sure we are logged in */
|
|
Packit |
40b132 |
(void) pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
NSSTrustDomain_TraverseCertificates(handle,
|
|
Packit |
40b132 |
CollectNicknames, (void *)names);
|
|
Packit |
40b132 |
if ( names->numnicknames ) {
|
|
Packit |
40b132 |
names->nicknames = (char**)PORT_ArenaAlloc(arena,
|
|
Packit |
40b132 |
names->numnicknames * sizeof(char *));
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( names->nicknames == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
node = (stringNode *)names->head;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
for ( i = 0; i < names->numnicknames; i++ ) {
|
|
Packit |
40b132 |
PORT_Assert(node != NULL);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names->nicknames[i] = node->string;
|
|
Packit |
40b132 |
names->totallen += PORT_Strlen(node->string);
|
|
Packit |
40b132 |
node = node->next;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PORT_Assert(node == NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(names);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
CERT_FreeNicknames(CERTCertNicknames *nicknames)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PORT_FreeArena(nicknames->arena, PR_FALSE);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* [ FROM pcertdb.c ] */
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
typedef struct dnameNode {
|
|
Packit |
40b132 |
struct dnameNode *next;
|
|
Packit |
40b132 |
SECItem name;
|
|
Packit |
40b132 |
} dnameNode;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
CERT_FreeDistNames(CERTDistNames *names)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PORT_FreeArena(names->arena, PR_FALSE);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
static SECStatus
|
|
Packit |
40b132 |
CollectDistNames( CERTCertificate *cert, SECItem *k, void *data)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTDistNames *names;
|
|
Packit |
40b132 |
PRBool saveit = PR_FALSE;
|
|
Packit |
40b132 |
CERTCertTrust trust;
|
|
Packit |
40b132 |
dnameNode *node;
|
|
Packit |
40b132 |
int len;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names = (CERTDistNames *)data;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) {
|
|
Packit |
40b132 |
/* only collect names of CAs trusted for issuing SSL clients */
|
|
Packit |
40b132 |
if ( trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA ) {
|
|
Packit |
40b132 |
saveit = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( saveit ) {
|
|
Packit |
40b132 |
/* allocate the node */
|
|
Packit |
40b132 |
node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
|
|
Packit |
40b132 |
if ( node == NULL ) {
|
|
Packit |
40b132 |
return(SECFailure);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* copy the name */
|
|
Packit |
40b132 |
node->name.len = len = cert->derSubject.len;
|
|
Packit |
40b132 |
node->name.type = siBuffer;
|
|
Packit |
40b132 |
node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);
|
|
Packit |
40b132 |
if ( node->name.data == NULL ) {
|
|
Packit |
40b132 |
return(SECFailure);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
PORT_Memcpy(node->name.data, cert->derSubject.data, len);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* link it into the list */
|
|
Packit |
40b132 |
node->next = (dnameNode *)names->head;
|
|
Packit |
40b132 |
names->head = (void *)node;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* bump the count */
|
|
Packit |
40b132 |
names->nnames++;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(SECSuccess);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Return all of the CAs that are "trusted" for SSL.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
CERTDistNames *
|
|
Packit |
40b132 |
CERT_DupDistNames(CERTDistNames *orig)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
CERTDistNames *names;
|
|
Packit |
40b132 |
int i;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* allocate an arena to use */
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if (arena == NULL) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* allocate the header structure */
|
|
Packit |
40b132 |
names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
|
|
Packit |
40b132 |
if (names == NULL) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* initialize the header struct */
|
|
Packit |
40b132 |
names->arena = arena;
|
|
Packit |
40b132 |
names->head = NULL;
|
|
Packit |
40b132 |
names->nnames = orig->nnames;
|
|
Packit |
40b132 |
names->names = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* construct the array from the list */
|
|
Packit |
40b132 |
if (orig->nnames) {
|
|
Packit |
40b132 |
names->names = (SECItem*)PORT_ArenaNewArray(arena, SECItem,
|
|
Packit |
40b132 |
orig->nnames);
|
|
Packit |
40b132 |
if (names->names == NULL) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
for (i = 0; i < orig->nnames; i++) {
|
|
Packit |
40b132 |
rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
|
|
Packit |
40b132 |
if (rv != SECSuccess) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return(names);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTDistNames *
|
|
Packit |
40b132 |
CERT_GetSSLCACerts(CERTCertDBHandle *handle)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
CERTDistNames *names;
|
|
Packit |
40b132 |
int i;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
dnameNode *node;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* allocate an arena to use */
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if ( arena == NULL ) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* allocate the header structure */
|
|
Packit |
40b132 |
names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
|
|
Packit |
40b132 |
if ( names == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* initialize the header struct */
|
|
Packit |
40b132 |
names->arena = arena;
|
|
Packit |
40b132 |
names->head = NULL;
|
|
Packit |
40b132 |
names->nnames = 0;
|
|
Packit |
40b132 |
names->names = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* collect the names from the database */
|
|
Packit |
40b132 |
rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
|
|
Packit |
40b132 |
if ( rv ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* construct the array from the list */
|
|
Packit |
40b132 |
if ( names->nnames ) {
|
|
Packit |
40b132 |
names->names = (SECItem*)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( names->names == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
node = (dnameNode *)names->head;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
for ( i = 0; i < names->nnames; i++ ) {
|
|
Packit |
40b132 |
PORT_Assert(node != NULL);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
names->names[i] = node->name;
|
|
Packit |
40b132 |
node = node->next;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PORT_Assert(node == NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(names);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
return(NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTDistNames *
|
|
Packit |
40b132 |
CERT_DistNamesFromCertList(CERTCertList *certList)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTDistNames * dnames = NULL;
|
|
Packit |
40b132 |
PLArenaPool * arena;
|
|
Packit |
40b132 |
CERTCertListNode *node = NULL;
|
|
Packit |
40b132 |
SECItem * names = NULL;
|
|
Packit |
40b132 |
int listLen = 0, i = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (certList == NULL) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
node = CERT_LIST_HEAD(certList);
|
|
Packit |
40b132 |
while ( ! CERT_LIST_END(node, certList) ) {
|
|
Packit |
40b132 |
listLen += 1;
|
|
Packit |
40b132 |
node = CERT_LIST_NEXT(node);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if (arena == NULL) goto loser;
|
|
Packit |
40b132 |
dnames = PORT_ArenaZNew(arena, CERTDistNames);
|
|
Packit |
40b132 |
if (dnames == NULL) goto loser;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
dnames->arena = arena;
|
|
Packit |
40b132 |
dnames->nnames = listLen;
|
|
Packit |
40b132 |
dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
|
|
Packit |
40b132 |
if (names == NULL) goto loser;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
node = CERT_LIST_HEAD(certList);
|
|
Packit |
40b132 |
while ( ! CERT_LIST_END(node, certList) ) {
|
|
Packit |
40b132 |
CERTCertificate *cert = node->cert;
|
|
Packit |
40b132 |
SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
|
|
Packit |
40b132 |
if (rv == SECFailure) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
node = CERT_LIST_NEXT(node);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return dnames;
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if (arena) {
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTDistNames *
|
|
Packit |
40b132 |
CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
|
|
Packit |
40b132 |
int nnames)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTDistNames *dnames = NULL;
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
int i, rv;
|
|
Packit |
40b132 |
SECItem *names = NULL;
|
|
Packit |
40b132 |
CERTCertificate *cert = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if (arena == NULL) goto loser;
|
|
Packit |
40b132 |
dnames = PORT_ArenaZNew(arena, CERTDistNames);
|
|
Packit |
40b132 |
if (dnames == NULL) goto loser;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
dnames->arena = arena;
|
|
Packit |
40b132 |
dnames->nnames = nnames;
|
|
Packit |
40b132 |
dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
|
|
Packit |
40b132 |
if (names == NULL) goto loser;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
for (i = 0; i < nnames; i++) {
|
|
Packit |
40b132 |
cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
|
|
Packit |
40b132 |
if (cert == NULL) goto loser;
|
|
Packit |
40b132 |
rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
|
|
Packit |
40b132 |
if (rv == SECFailure) goto loser;
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return dnames;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if (cert != NULL)
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
if (arena != NULL)
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* [ from pcertdb.c - calls Ascii to Name ] */
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Lookup a certificate in the database by name
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
CERTCertificate *
|
|
Packit |
40b132 |
CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTName *name;
|
|
Packit |
40b132 |
SECItem *nameItem;
|
|
Packit |
40b132 |
CERTCertificate *cert = NULL;
|
|
Packit |
40b132 |
PLArenaPool *arena = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( arena == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
name = CERT_AsciiToName(nameStr);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( name ) {
|
|
Packit |
40b132 |
nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name,
|
|
Packit |
40b132 |
CERT_NameTemplate);
|
|
Packit |
40b132 |
if ( nameItem != NULL ) {
|
|
Packit |
40b132 |
cert = CERT_FindCertByName(handle, nameItem);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
CERT_DestroyName(name);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if ( arena ) {
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(cert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* From certv3.c */
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTCrlDistributionPoints *
|
|
Packit |
40b132 |
CERT_FindCRLDistributionPoints (CERTCertificate *cert)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECItem encodedExtenValue;
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
CERTCrlDistributionPoints *dps;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
encodedExtenValue.data = NULL;
|
|
Packit |
40b132 |
encodedExtenValue.len = 0;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
|
|
Packit |
40b132 |
&encodedExtenValue);
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
return (NULL);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
PORT_Free(encodedExtenValue.data);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return dps;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* From crl.c */
|
|
Packit |
40b132 |
CERTSignedCrl * CERT_ImportCRL
|
|
Packit |
40b132 |
(CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTSignedCrl* retCrl = NULL;
|
|
Packit |
40b132 |
PK11SlotInfo* slot = PK11_GetInternalKeySlot();
|
|
Packit |
40b132 |
retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
|
|
Packit |
40b132 |
CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
|
|
Packit |
40b132 |
PK11_FreeSlot(slot);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return retCrl;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* From certdb.c */
|
|
Packit |
40b132 |
static SECStatus
|
|
Packit |
40b132 |
cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
SECStatus rv;
|
|
Packit |
40b132 |
SECItem *derCert;
|
|
Packit |
40b132 |
CERTCertificate *cert = NULL;
|
|
Packit |
40b132 |
CERTCertificate *newcert = NULL;
|
|
Packit |
40b132 |
CERTCertDBHandle *handle;
|
|
Packit |
40b132 |
CERTCertTrust trust;
|
|
Packit |
40b132 |
PRBool isca;
|
|
Packit |
40b132 |
char *nickname;
|
|
Packit |
40b132 |
unsigned int certtype;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
handle = CERT_GetDefaultCertDB();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
while (numcerts--) {
|
|
Packit |
40b132 |
derCert = certs;
|
|
Packit |
40b132 |
certs++;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* decode my certificate */
|
|
Packit |
40b132 |
/* This use is ok -- only looks at decoded parts, calls NewTemp later */
|
|
Packit |
40b132 |
newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
|
|
Packit |
40b132 |
if ( newcert == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if (!trusted) {
|
|
Packit |
40b132 |
/* make sure that cert is valid */
|
|
Packit |
40b132 |
rv = CERT_CertTimesValid(newcert);
|
|
Packit |
40b132 |
if ( rv == SECFailure ) {
|
|
Packit |
40b132 |
goto endloop;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* does it have the CA extension */
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
* Make sure that if this is an intermediate CA in the chain that
|
|
Packit |
40b132 |
* it was given permission by its signer to be a CA.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
isca = CERT_IsCACert(newcert, &certtype);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( !isca ) {
|
|
Packit |
40b132 |
if (!trusted) {
|
|
Packit |
40b132 |
goto endloop;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
trust.sslFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
trust.emailFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
trust.objectSigningFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
/* SSL ca's must have the ssl bit set */
|
|
Packit |
40b132 |
if ( ( certUsage == certUsageSSLCA ) &&
|
|
Packit |
40b132 |
(( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) {
|
|
Packit |
40b132 |
goto endloop;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* it passed all of the tests, so lets add it to the database */
|
|
Packit |
40b132 |
/* mark it as a CA */
|
|
Packit |
40b132 |
PORT_Memset((void *)&trust, 0, sizeof(trust));
|
|
Packit |
40b132 |
switch ( certUsage ) {
|
|
Packit |
40b132 |
case certUsageSSLCA:
|
|
Packit |
40b132 |
trust.sslFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
case certUsageUserCertImport:
|
|
Packit |
40b132 |
if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
|
|
Packit |
40b132 |
trust.sslFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if ((certtype & NS_CERT_TYPE_EMAIL_CA)
|
|
Packit |
40b132 |
== NS_CERT_TYPE_EMAIL_CA ) {
|
|
Packit |
40b132 |
trust.emailFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) ==
|
|
Packit |
40b132 |
NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
|
|
Packit |
40b132 |
trust.objectSigningFlags = CERTDB_VALID_CA;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
default:
|
|
Packit |
40b132 |
PORT_Assert(0);
|
|
Packit |
40b132 |
break;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
cert = CERT_NewTempCertificate(handle, derCert, NULL,
|
|
Packit |
40b132 |
PR_FALSE, PR_FALSE);
|
|
Packit |
40b132 |
if ( cert == NULL ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* if the cert is temp, make it perm; otherwise we're done */
|
|
Packit |
40b132 |
if (cert->istemp) {
|
|
Packit |
40b132 |
/* get a default nickname for it */
|
|
Packit |
40b132 |
nickname = CERT_MakeCANickname(cert);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* free the nickname */
|
|
Packit |
40b132 |
if ( nickname ) {
|
|
Packit |
40b132 |
PORT_Free(nickname);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
cert = NULL;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( rv != SECSuccess ) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
endloop:
|
|
Packit |
40b132 |
if ( newcert ) {
|
|
Packit |
40b132 |
CERT_DestroyCertificate(newcert);
|
|
Packit |
40b132 |
newcert = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
rv = SECSuccess;
|
|
Packit |
40b132 |
goto done;
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
rv = SECFailure;
|
|
Packit |
40b132 |
done:
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( newcert ) {
|
|
Packit |
40b132 |
CERT_DestroyCertificate(newcert);
|
|
Packit |
40b132 |
newcert = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
if ( cert ) {
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cert);
|
|
Packit |
40b132 |
cert = NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return(rv);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
SECStatus
|
|
Packit |
40b132 |
CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage) {
|
|
Packit |
40b132 |
return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* Moved from certdb.c */
|
|
Packit |
40b132 |
/*
|
|
Packit |
40b132 |
** CERT_CertChainFromCert
|
|
Packit |
40b132 |
**
|
|
Packit |
40b132 |
** Construct a CERTCertificateList consisting of the given certificate and all
|
|
Packit |
40b132 |
** of the issuer certs until we either get to a self-signed cert or can't find
|
|
Packit |
40b132 |
** an issuer. Since we don't know how many certs are in the chain we have to
|
|
Packit |
40b132 |
** build a linked list first as we count them.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
typedef struct certNode {
|
|
Packit |
40b132 |
struct certNode *next;
|
|
Packit |
40b132 |
CERTCertificate *cert;
|
|
Packit |
40b132 |
} certNode;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTCertificateList *
|
|
Packit |
40b132 |
CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
|
|
Packit |
40b132 |
PRBool includeRoot)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertificateList *chain = NULL;
|
|
Packit |
40b132 |
NSSCertificate **stanChain;
|
|
Packit |
40b132 |
NSSCertificate *stanCert;
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
NSSUsage nssUsage;
|
|
Packit |
40b132 |
int i, len;
|
|
Packit |
40b132 |
NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
|
|
Packit |
40b132 |
NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
stanCert = STAN_GetNSSCertificate(cert);
|
|
Packit |
40b132 |
if (!stanCert) {
|
|
Packit |
40b132 |
/* error code is set */
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
nssUsage.anyUsage = PR_FALSE;
|
|
Packit |
40b132 |
nssUsage.nss3usage = usage;
|
|
Packit |
40b132 |
nssUsage.nss3lookingForCA = PR_FALSE;
|
|
Packit |
40b132 |
stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
|
|
Packit |
40b132 |
CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
|
|
Packit |
40b132 |
if (!stanChain) {
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
len = 0;
|
|
Packit |
40b132 |
stanCert = stanChain[0];
|
|
Packit |
40b132 |
while (stanCert) {
|
|
Packit |
40b132 |
stanCert = stanChain[++len];
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
arena = PORT_NewArena(4096);
|
|
Packit |
40b132 |
if (arena == NULL) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
|
|
Packit |
40b132 |
sizeof(CERTCertificateList));
|
|
Packit |
40b132 |
if (!chain) goto loser;
|
|
Packit |
40b132 |
chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
|
|
Packit |
40b132 |
if (!chain->certs) goto loser;
|
|
Packit |
40b132 |
i = 0;
|
|
Packit |
40b132 |
stanCert = stanChain[i];
|
|
Packit |
40b132 |
while (stanCert) {
|
|
Packit |
40b132 |
SECItem derCert;
|
|
Packit |
40b132 |
CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
|
|
Packit |
40b132 |
if (!cCert) {
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
derCert.len = (unsigned int)stanCert->encoding.size;
|
|
Packit |
40b132 |
derCert.data = (unsigned char *)stanCert->encoding.data;
|
|
Packit |
40b132 |
derCert.type = siBuffer;
|
|
Packit |
40b132 |
SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
|
|
Packit |
40b132 |
stanCert = stanChain[++i];
|
|
Packit |
40b132 |
if (!stanCert && !cCert->isRoot) {
|
|
Packit |
40b132 |
/* reached the end of the chain, but the final cert is
|
|
Packit |
40b132 |
* not a root. Don't discard it.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
includeRoot = PR_TRUE;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cCert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if ( !includeRoot && len > 1) {
|
|
Packit |
40b132 |
chain->len = len - 1;
|
|
Packit |
40b132 |
} else {
|
|
Packit |
40b132 |
chain->len = len;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
chain->arena = arena;
|
|
Packit |
40b132 |
nss_ZFreeIf(stanChain);
|
|
Packit |
40b132 |
return chain;
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
i = 0;
|
|
Packit |
40b132 |
stanCert = stanChain[i];
|
|
Packit |
40b132 |
while (stanCert) {
|
|
Packit |
40b132 |
CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
|
|
Packit |
40b132 |
if (cCert) {
|
|
Packit |
40b132 |
CERT_DestroyCertificate(cCert);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
stanCert = stanChain[++i];
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
nss_ZFreeIf(stanChain);
|
|
Packit |
40b132 |
if (arena) {
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* Builds a CERTCertificateList holding just one DER-encoded cert, namely
|
|
Packit |
40b132 |
** the one for the cert passed as an argument.
|
|
Packit |
40b132 |
*/
|
|
Packit |
40b132 |
CERTCertificateList *
|
|
Packit |
40b132 |
CERT_CertListFromCert(CERTCertificate *cert)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertificateList *chain = NULL;
|
|
Packit |
40b132 |
int rv;
|
|
Packit |
40b132 |
PLArenaPool *arena;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* arena for SecCertificateList */
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if (arena == NULL) goto no_memory;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* build the CERTCertificateList */
|
|
Packit |
40b132 |
chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
|
|
Packit |
40b132 |
if (chain == NULL) goto no_memory;
|
|
Packit |
40b132 |
chain->certs = (SECItem*)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
|
|
Packit |
40b132 |
if (chain->certs == NULL) goto no_memory;
|
|
Packit |
40b132 |
rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
|
|
Packit |
40b132 |
if (rv < 0) goto loser;
|
|
Packit |
40b132 |
chain->len = 1;
|
|
Packit |
40b132 |
chain->arena = arena;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
return chain;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
no_memory:
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if (arena != NULL) {
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
CERTCertificateList *
|
|
Packit |
40b132 |
CERT_DupCertList(const CERTCertificateList * oldList)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
CERTCertificateList *newList = NULL;
|
|
Packit |
40b132 |
PLArenaPool *arena = NULL;
|
|
Packit |
40b132 |
SECItem *newItem;
|
|
Packit |
40b132 |
SECItem *oldItem;
|
|
Packit |
40b132 |
int len = oldList->len;
|
|
Packit |
40b132 |
int rv;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* arena for SecCertificateList */
|
|
Packit |
40b132 |
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
Packit |
40b132 |
if (arena == NULL)
|
|
Packit |
40b132 |
goto no_memory;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
/* now build the CERTCertificateList */
|
|
Packit |
40b132 |
newList = PORT_ArenaNew(arena, CERTCertificateList);
|
|
Packit |
40b132 |
if (newList == NULL)
|
|
Packit |
40b132 |
goto no_memory;
|
|
Packit |
40b132 |
newList->arena = arena;
|
|
Packit |
40b132 |
newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
|
|
Packit |
40b132 |
if (newItem == NULL)
|
|
Packit |
40b132 |
goto no_memory;
|
|
Packit |
40b132 |
newList->certs = newItem;
|
|
Packit |
40b132 |
newList->len = len;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
|
|
Packit |
40b132 |
rv = SECITEM_CopyItem(arena, newItem, oldItem);
|
|
Packit |
40b132 |
if (rv < 0)
|
|
Packit |
40b132 |
goto loser;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return newList;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
no_memory:
|
|
Packit |
40b132 |
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
Packit |
40b132 |
loser:
|
|
Packit |
40b132 |
if (arena != NULL) {
|
|
Packit |
40b132 |
PORT_FreeArena(arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return NULL;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
void
|
|
Packit |
40b132 |
CERT_DestroyCertificateList(CERTCertificateList *list)
|
|
Packit |
40b132 |
{
|
|
Packit |
40b132 |
PORT_FreeArena(list->arena, PR_FALSE);
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|