mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
bug 171224, changes to path construction
r=nelsonb
This commit is contained in:
parent
cc93338c09
commit
6199159d80
@ -34,7 +34,7 @@
|
|||||||
/*
|
/*
|
||||||
* Certificate handling code
|
* Certificate handling code
|
||||||
*
|
*
|
||||||
* $Id: certdb.c,v 1.42 2002/08/24 00:45:55 jpierre%netscape.com Exp $
|
* $Id: certdb.c,v 1.43 2002/10/01 14:32:07 ian.mcgreer%sun.com Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nssilock.h"
|
#include "nssilock.h"
|
||||||
@ -725,6 +725,64 @@ cert_GetKeyID(CERTCertificate *cert)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
cert_IsRootCert(CERTCertificate *cert)
|
||||||
|
{
|
||||||
|
SECStatus rv;
|
||||||
|
SECItem tmpitem;
|
||||||
|
|
||||||
|
/* cache the authKeyID extension, if present */
|
||||||
|
cert->authKeyID = CERT_FindAuthKeyIDExten(cert->arena, cert);
|
||||||
|
|
||||||
|
/* it MUST be self-issued to be a root */
|
||||||
|
if (cert->derIssuer.len == 0 ||
|
||||||
|
!SECITEM_ItemsAreEqual(&cert->derIssuer, &cert->derSubject))
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the authKeyID extension */
|
||||||
|
if (cert->authKeyID) {
|
||||||
|
/* authority key identifier is present */
|
||||||
|
if (cert->authKeyID->keyID.len > 0) {
|
||||||
|
/* the keyIdentifier field is set, look for subjectKeyID */
|
||||||
|
rv = CERT_FindSubjectKeyIDExten(cert, &tmpitem);
|
||||||
|
if (rv == SECSuccess) {
|
||||||
|
PRBool match;
|
||||||
|
/* also present, they MUST match for it to be a root */
|
||||||
|
match = SECITEM_ItemsAreEqual(&cert->authKeyID->keyID,
|
||||||
|
&tmpitem);
|
||||||
|
PORT_Free(tmpitem.data);
|
||||||
|
if (!match) return PR_FALSE; /* else fall through */
|
||||||
|
} else {
|
||||||
|
/* the subject key ID is required when AKI is present */
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cert->authKeyID->authCertIssuer) {
|
||||||
|
SECItem *caName;
|
||||||
|
caName = (SECItem *)CERT_GetGeneralNameByType(
|
||||||
|
cert->authKeyID->authCertIssuer,
|
||||||
|
certDirectoryName, PR_TRUE);
|
||||||
|
if (caName) {
|
||||||
|
if (!SECITEM_ItemsAreEqual(&cert->derIssuer, caName)) {
|
||||||
|
return PR_FALSE;
|
||||||
|
} /* else fall through */
|
||||||
|
} /* else ??? could not get general name as directory name? */
|
||||||
|
}
|
||||||
|
if (cert->authKeyID->authCertSerialNumber.len > 0) {
|
||||||
|
if (!SECITEM_ItemsAreEqual(&cert->serialNumber,
|
||||||
|
&cert->authKeyID->authCertSerialNumber)) {
|
||||||
|
return PR_FALSE;
|
||||||
|
} /* else fall through */
|
||||||
|
}
|
||||||
|
/* all of the AKI fields that were present passed the test */
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
/* else the AKI was not present, so this is a root */
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* take a DER certificate and decode it into a certificate structure
|
* take a DER certificate and decode it into a certificate structure
|
||||||
*/
|
*/
|
||||||
@ -824,6 +882,9 @@ CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
|
|||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* determine if this is a root cert */
|
||||||
|
cert->isRoot = cert_IsRootCert(cert);
|
||||||
|
|
||||||
tmpname = CERT_NameToAscii(&cert->subject);
|
tmpname = CERT_NameToAscii(&cert->subject);
|
||||||
if ( tmpname != NULL ) {
|
if ( tmpname != NULL ) {
|
||||||
cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname);
|
cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname);
|
||||||
@ -1769,6 +1830,14 @@ CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the isRoot flag trumps all */
|
||||||
|
if (cert->isRoot) {
|
||||||
|
ret = PR_TRUE;
|
||||||
|
/* set only these by default, same as above */
|
||||||
|
type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
|
||||||
|
}
|
||||||
|
|
||||||
if ( rettype != NULL ) {
|
if ( rettype != NULL ) {
|
||||||
*rettype = type;
|
*rettype = type;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
/*
|
/*
|
||||||
* certt.h - public data structures for the certificate library
|
* certt.h - public data structures for the certificate library
|
||||||
*
|
*
|
||||||
* $Id: certt.h,v 1.20 2002/08/07 03:42:45 jpierre%netscape.com Exp $
|
* $Id: certt.h,v 1.21 2002/10/01 14:32:09 ian.mcgreer%sun.com Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _CERTT_H_
|
#ifndef _CERTT_H_
|
||||||
#define _CERTT_H_
|
#define _CERTT_H_
|
||||||
@ -285,13 +285,17 @@ struct CERTCertificateStr {
|
|||||||
*/
|
*/
|
||||||
CERTSubjectList *subjectList;
|
CERTSubjectList *subjectList;
|
||||||
|
|
||||||
|
/* these belong in the static section, but are here to maintain
|
||||||
|
* the structure's integrity
|
||||||
|
*/
|
||||||
|
CERTAuthKeyID * authKeyID; /* x509v3 authority key identifier */
|
||||||
|
PRBool isRoot; /* cert is the end of a chain */
|
||||||
|
|
||||||
/* these fields are used by client GUI code to keep track of ssl sockets
|
/* these fields are used by client GUI code to keep track of ssl sockets
|
||||||
* that are blocked waiting on GUI feedback related to this cert.
|
* that are blocked waiting on GUI feedback related to this cert.
|
||||||
* XXX - these should be moved into some sort of application specific
|
* XXX - these should be moved into some sort of application specific
|
||||||
* data structure. They are only used by the browser right now.
|
* data structure. They are only used by the browser right now.
|
||||||
*/
|
*/
|
||||||
struct SECSocketNode *socketlist;
|
|
||||||
int socketcount;
|
|
||||||
struct SECSocketNode *authsocketlist;
|
struct SECSocketNode *authsocketlist;
|
||||||
int series; /* was int authsocketcount; record the series of the pkcs11ID */
|
int series; /* was int authsocketcount; record the series of the pkcs11ID */
|
||||||
|
|
||||||
|
@ -1111,8 +1111,14 @@ loser:
|
|||||||
derCert.data = (unsigned char *)stanCert->encoding.data;
|
derCert.data = (unsigned char *)stanCert->encoding.data;
|
||||||
derCert.type = siBuffer;
|
derCert.type = siBuffer;
|
||||||
SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
|
SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
|
||||||
CERT_DestroyCertificate(cCert);
|
|
||||||
stanCert = stanChain[++i];
|
stanCert = stanChain[++i];
|
||||||
|
if (!stanCert && !cCert->isRoot) {
|
||||||
|
/* reached the end of the chain, but the final cert is
|
||||||
|
* not a root. Don't discard it.
|
||||||
|
*/
|
||||||
|
includeRoot = PR_TRUE;
|
||||||
|
}
|
||||||
|
CERT_DestroyCertificate(cCert);
|
||||||
}
|
}
|
||||||
if ( !includeRoot && len > 1) {
|
if ( !includeRoot && len > 1) {
|
||||||
chain->len = len - 1;
|
chain->len = len - 1;
|
||||||
|
@ -619,7 +619,6 @@ cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
|
|||||||
PRBool isca;
|
PRBool isca;
|
||||||
PRBool isFortezzaV1 = PR_FALSE;
|
PRBool isFortezzaV1 = PR_FALSE;
|
||||||
SECStatus rv;
|
SECStatus rv;
|
||||||
SECComparison rvCompare;
|
|
||||||
SECStatus rvFinal = SECSuccess;
|
SECStatus rvFinal = SECSuccess;
|
||||||
int count;
|
int count;
|
||||||
int currentPathLen = -1;
|
int currentPathLen = -1;
|
||||||
@ -924,9 +923,7 @@ cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
|
|||||||
/* make sure that the issuer is not self signed. If it is, then
|
/* make sure that the issuer is not self signed. If it is, then
|
||||||
* stop here to prevent looping.
|
* stop here to prevent looping.
|
||||||
*/
|
*/
|
||||||
rvCompare = SECITEM_CompareItem(&issuerCert->derSubject,
|
if (issuerCert->isRoot) {
|
||||||
&issuerCert->derIssuer);
|
|
||||||
if (rvCompare == SECEqual) {
|
|
||||||
PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
|
PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
|
||||||
LOG_ERROR(log, issuerCert, count+1, 0);
|
LOG_ERROR(log, issuerCert, count+1, 0);
|
||||||
goto loser;
|
goto loser;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.43 $ $Date: 2002/09/23 21:32:31 $ $Name: $";
|
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.44 $ $Date: 2002/10/01 14:32:15 $ $Name: $";
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
#ifndef NSSPKI_H
|
#ifndef NSSPKI_H
|
||||||
@ -280,20 +280,48 @@ nssCertificate_GetDecoding (
|
|||||||
static NSSCertificate **
|
static NSSCertificate **
|
||||||
filter_subject_certs_for_id (
|
filter_subject_certs_for_id (
|
||||||
NSSCertificate **subjectCerts,
|
NSSCertificate **subjectCerts,
|
||||||
NSSItem *id
|
void *id
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NSSCertificate **si;
|
NSSCertificate **si;
|
||||||
nssDecodedCert *dcp;
|
nssDecodedCert *dcp;
|
||||||
int nextOpenSlot = 0;
|
int nextOpenSlot = 0;
|
||||||
|
int i;
|
||||||
|
nssCertIDMatch matchLevel = nssCertIDMatch_Unknown;
|
||||||
|
nssCertIDMatch match;
|
||||||
|
|
||||||
/* walk the subject certs */
|
/* walk the subject certs */
|
||||||
for (si = subjectCerts; *si; si++) {
|
for (si = subjectCerts; *si; si++) {
|
||||||
dcp = nssCertificate_GetDecoding(*si);
|
dcp = nssCertificate_GetDecoding(*si);
|
||||||
if (dcp->matchIdentifier(dcp, id)) {
|
if (!dcp) {
|
||||||
/* this cert has the correct identifier */
|
NSSCertificate_Destroy(*si);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match = dcp->matchIdentifier(dcp, id);
|
||||||
|
switch (match) {
|
||||||
|
case nssCertIDMatch_Yes:
|
||||||
|
if (matchLevel == nssCertIDMatch_Unknown) {
|
||||||
|
/* we have non-definitive matches, forget them */
|
||||||
|
for (i = 0; i < nextOpenSlot; i++) {
|
||||||
|
NSSCertificate_Destroy(subjectCerts[i]);
|
||||||
|
subjectCerts[i] = NULL;
|
||||||
|
}
|
||||||
|
nextOpenSlot = 0;
|
||||||
|
/* only keep definitive matches from now on */
|
||||||
|
matchLevel = nssCertIDMatch_Yes;
|
||||||
|
}
|
||||||
|
/* keep the cert */
|
||||||
subjectCerts[nextOpenSlot++] = *si;
|
subjectCerts[nextOpenSlot++] = *si;
|
||||||
} else {
|
break;
|
||||||
|
case nssCertIDMatch_Unknown:
|
||||||
|
if (matchLevel == nssCertIDMatch_Unknown) {
|
||||||
|
/* only have non-definitive matches so far, keep it */
|
||||||
|
subjectCerts[nextOpenSlot++] = *si;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* else fall through, we have a definitive match already */
|
||||||
|
case nssCertIDMatch_No:
|
||||||
|
default:
|
||||||
NSSCertificate_Destroy(*si);
|
NSSCertificate_Destroy(*si);
|
||||||
*si = NULL;
|
*si = NULL;
|
||||||
}
|
}
|
||||||
@ -302,6 +330,28 @@ filter_subject_certs_for_id (
|
|||||||
return subjectCerts;
|
return subjectCerts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NSSCertificate **
|
||||||
|
filter_certs_for_valid_issuers (
|
||||||
|
NSSCertificate **certs
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NSSCertificate **cp;
|
||||||
|
nssDecodedCert *dcp;
|
||||||
|
int nextOpenSlot = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (cp = certs; *cp; cp++) {
|
||||||
|
dcp = nssCertificate_GetDecoding(*cp);
|
||||||
|
if (dcp && dcp->isValidIssuer(dcp)) {
|
||||||
|
certs[nextOpenSlot++] = *cp;
|
||||||
|
} else {
|
||||||
|
NSSCertificate_Destroy(*cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
certs[nextOpenSlot] = NULL;
|
||||||
|
return certs;
|
||||||
|
}
|
||||||
|
|
||||||
static NSSCertificate *
|
static NSSCertificate *
|
||||||
find_cert_issuer (
|
find_cert_issuer (
|
||||||
NSSCertificate *c,
|
NSSCertificate *c,
|
||||||
@ -343,15 +393,15 @@ find_cert_issuer (
|
|||||||
certs = nssCertificateArray_Join(ccIssuers, tdIssuers);
|
certs = nssCertificateArray_Join(ccIssuers, tdIssuers);
|
||||||
if (certs) {
|
if (certs) {
|
||||||
nssDecodedCert *dc = NULL;
|
nssDecodedCert *dc = NULL;
|
||||||
NSSItem *issuerID = NULL;
|
void *issuerID = NULL;
|
||||||
dc = nssCertificate_GetDecoding(c);
|
dc = nssCertificate_GetDecoding(c);
|
||||||
if (dc) {
|
if (dc) {
|
||||||
issuerID = dc->getIssuerIdentifier(dc);
|
issuerID = dc->getIssuerIdentifier(dc);
|
||||||
}
|
}
|
||||||
if (issuerID) {
|
if (issuerID) {
|
||||||
certs = filter_subject_certs_for_id(certs, issuerID);
|
certs = filter_subject_certs_for_id(certs, issuerID);
|
||||||
nssItem_Destroy(issuerID);
|
|
||||||
}
|
}
|
||||||
|
certs = filter_certs_for_valid_issuers(certs);
|
||||||
issuer = nssCertificateArray_FindBestCertificate(certs,
|
issuer = nssCertificateArray_FindBestCertificate(certs,
|
||||||
timeOpt,
|
timeOpt,
|
||||||
usage,
|
usage,
|
||||||
@ -378,18 +428,22 @@ nssCertificate_BuildChain (
|
|||||||
PRStatus *statusOpt
|
PRStatus *statusOpt
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PRStatus status;
|
|
||||||
NSSCertificate **rvChain;
|
NSSCertificate **rvChain;
|
||||||
#ifdef NSS_3_4_CODE
|
#ifdef NSS_3_4_CODE
|
||||||
NSSCertificate *cp;
|
NSSCertificate *cp;
|
||||||
|
CERTCertificate *cCert;
|
||||||
#endif
|
#endif
|
||||||
|
NSSUsage issuerUsage = *usage;
|
||||||
NSSTrustDomain *td;
|
NSSTrustDomain *td;
|
||||||
nssPKIObjectCollection *collection;
|
nssPKIObjectCollection *collection;
|
||||||
|
|
||||||
td = NSSCertificate_GetTrustDomain(c);
|
td = NSSCertificate_GetTrustDomain(c);
|
||||||
#ifdef NSS_3_4_CODE
|
#ifdef NSS_3_4_CODE
|
||||||
if (!td) {
|
if (!td) {
|
||||||
td = STAN_GetDefaultTrustDomain();
|
td = STAN_GetDefaultTrustDomain();
|
||||||
}
|
}
|
||||||
|
/* bump the usage up to CA level */
|
||||||
|
issuerUsage.nss3lookingForCA = PR_TRUE;
|
||||||
#endif
|
#endif
|
||||||
if (statusOpt) *statusOpt = PR_SUCCESS;
|
if (statusOpt) *statusOpt = PR_SUCCESS;
|
||||||
collection = nssCertificateCollection_Create(td, NULL);
|
collection = nssCertificateCollection_Create(td, NULL);
|
||||||
@ -401,24 +455,22 @@ nssCertificate_BuildChain (
|
|||||||
if (rvLimit == 1) {
|
if (rvLimit == 1) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
while (!nssItem_Equal(&c->subject, &c->issuer, &status)) {
|
/* XXX This breaks code for which NSS_3_4_CODE is not defined (pure
|
||||||
|
* 4.0 builds). That won't affect the tip. But be careful
|
||||||
|
* when merging 4.0!!!
|
||||||
|
*/
|
||||||
|
while (c != (NSSCertificate *)NULL) {
|
||||||
#ifdef NSS_3_4_CODE
|
#ifdef NSS_3_4_CODE
|
||||||
|
cCert = STAN_GetCERTCertificate(c);
|
||||||
|
if (cCert->isRoot) {
|
||||||
|
/* not including the issuer of the self-signed cert, which is,
|
||||||
|
* of course, itself
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
cp = c;
|
cp = c;
|
||||||
#endif
|
#endif
|
||||||
c = find_cert_issuer(c, timeOpt, usage, policiesOpt);
|
c = find_cert_issuer(c, timeOpt, &issuerUsage, policiesOpt);
|
||||||
#ifdef NSS_3_4_CODE
|
|
||||||
if (!c) {
|
|
||||||
PRBool tmpca = usage->nss3lookingForCA;
|
|
||||||
usage->nss3lookingForCA = PR_TRUE;
|
|
||||||
c = find_cert_issuer(cp, timeOpt, usage, policiesOpt);
|
|
||||||
if (!c && !usage->anyUsage) {
|
|
||||||
usage->anyUsage = PR_TRUE;
|
|
||||||
c = find_cert_issuer(cp, timeOpt, usage, policiesOpt);
|
|
||||||
usage->anyUsage = PR_FALSE;
|
|
||||||
}
|
|
||||||
usage->nss3lookingForCA = tmpca;
|
|
||||||
}
|
|
||||||
#endif /* NSS_3_4_CODE */
|
|
||||||
if (c) {
|
if (c) {
|
||||||
nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
|
nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c);
|
||||||
nssCertificate_Destroy(c); /* collection has it */
|
nssCertificate_Destroy(c); /* collection has it */
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.69 $ $Date: 2002/09/30 20:33:44 $ $Name: $";
|
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.70 $ $Date: 2002/10/01 14:32:15 $ $Name: $";
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -231,61 +231,75 @@ nss3certificate_getIdentifier(nssDecodedCert *dc)
|
|||||||
return rvID;
|
return rvID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSSItem *
|
static void *
|
||||||
nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
|
nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
|
||||||
{
|
{
|
||||||
CERTCertificate *c = (CERTCertificate *)dc->data;
|
CERTCertificate *c = (CERTCertificate *)dc->data;
|
||||||
CERTAuthKeyID *cAuthKeyID;
|
return (void *)c->authKeyID;
|
||||||
PRArenaPool *tmpArena = NULL;
|
}
|
||||||
NSSItem *rvID = NULL;
|
|
||||||
tmpArena = PORT_NewArena(512);
|
static nssCertIDMatch
|
||||||
cAuthKeyID = CERT_FindAuthKeyIDExten(tmpArena, c);
|
nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
|
||||||
if (cAuthKeyID == NULL) {
|
{
|
||||||
goto done;
|
CERTCertificate *c = (CERTCertificate *)dc->data;
|
||||||
|
CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
|
||||||
|
SECItem skid;
|
||||||
|
nssCertIDMatch match = nssCertIDMatch_Unknown;
|
||||||
|
|
||||||
|
/* keyIdentifier */
|
||||||
|
if (authKeyID->keyID.len > 0) {
|
||||||
|
if (CERT_FindSubjectKeyIDExten(c, &skid) == SECSuccess) {
|
||||||
|
PRBool skiEqual;
|
||||||
|
skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
|
||||||
|
PORT_Free(skid.data);
|
||||||
|
if (skiEqual) {
|
||||||
|
/* change the state to positive match, but keep going */
|
||||||
|
match = nssCertIDMatch_Yes;
|
||||||
|
} else {
|
||||||
|
/* exit immediately on failure */
|
||||||
|
return nssCertIDMatch_No;
|
||||||
|
}
|
||||||
|
} /* else fall through */
|
||||||
}
|
}
|
||||||
if (cAuthKeyID->keyID.data) {
|
|
||||||
rvID = nssItem_Create(NULL, NULL, cAuthKeyID->keyID.len,
|
/* issuer/serial (treated as pair) */
|
||||||
cAuthKeyID->keyID.data);
|
if (authKeyID->authCertIssuer) {
|
||||||
} else if (cAuthKeyID->authCertIssuer) {
|
|
||||||
SECItem *caName = NULL;
|
SECItem *caName = NULL;
|
||||||
CERTIssuerAndSN issuerSN;
|
SECItem *caSN = &authKeyID->authCertSerialNumber;
|
||||||
CERTCertificate *issuer = NULL;
|
|
||||||
|
|
||||||
caName = (SECItem *)CERT_GetGeneralNameByType(
|
caName = (SECItem *)CERT_GetGeneralNameByType(
|
||||||
cAuthKeyID->authCertIssuer,
|
authKeyID->authCertIssuer,
|
||||||
certDirectoryName, PR_TRUE);
|
certDirectoryName, PR_TRUE);
|
||||||
if (caName == NULL) {
|
if (caName == NULL) {
|
||||||
goto done;
|
/* this is some kind of error, so treat it as unknown */
|
||||||
|
return nssCertIDMatch_Unknown;
|
||||||
}
|
}
|
||||||
issuerSN.derIssuer.data = caName->data;
|
if (SECITEM_ItemsAreEqual(&c->derSubject, caName) &&
|
||||||
issuerSN.derIssuer.len = caName->len;
|
SECITEM_ItemsAreEqual(&c->serialNumber, caSN))
|
||||||
issuerSN.derIssuer.type = siBuffer;
|
{
|
||||||
issuerSN.serialNumber.data = cAuthKeyID->authCertSerialNumber.data;
|
/* change the state to positive match, but keep going */
|
||||||
issuerSN.serialNumber.len = cAuthKeyID->authCertSerialNumber.len;
|
match = nssCertIDMatch_Yes;
|
||||||
issuerSN.serialNumber.type = siBuffer;
|
} else {
|
||||||
issuer = PK11_FindCertByIssuerAndSN(NULL, &issuerSN, NULL);
|
/* exit immediately on failure */
|
||||||
if (issuer) {
|
return nssCertIDMatch_No;
|
||||||
rvID = nssItem_Create(NULL, NULL, issuer->subjectKeyID.len,
|
|
||||||
issuer->subjectKeyID.data);
|
|
||||||
CERT_DestroyCertificate(issuer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
if (tmpArena) PORT_FreeArena(tmpArena, PR_FALSE);
|
/* If the issued cert has a keyIdentifier field with a value, but
|
||||||
return rvID;
|
* this issuer cert does not have a subjectKeyID extension, and
|
||||||
|
* the issuer/serial number fields of the authKeyID extension
|
||||||
|
* are empty, the state will be Unknown. Otherwise it should have
|
||||||
|
* been set to Yes.
|
||||||
|
*/
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRBool
|
static PRBool
|
||||||
nss3certificate_matchIdentifier(nssDecodedCert *dc, NSSItem *id)
|
nss3certificate_isValidIssuer(nssDecodedCert *dc)
|
||||||
{
|
{
|
||||||
CERTCertificate *c = (CERTCertificate *)dc->data;
|
CERTCertificate *c = (CERTCertificate *)dc->data;
|
||||||
SECItem *subjectKeyID, authKeyID;
|
unsigned int ignore;
|
||||||
subjectKeyID = &c->subjectKeyID;
|
return CERT_IsCACert(c, &ignore);
|
||||||
SECITEM_FROM_NSSITEM(&authKeyID, id);
|
|
||||||
if (SECITEM_CompareItem(subjectKeyID, &authKeyID) == SECEqual) {
|
|
||||||
return PR_TRUE;
|
|
||||||
}
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSSUsage *
|
static NSSUsage *
|
||||||
@ -331,6 +345,11 @@ nss3certificate_matchUsage(nssDecodedCert *dc, NSSUsage *usage)
|
|||||||
CERTCertificate *cc = (CERTCertificate *)dc->data;
|
CERTCertificate *cc = (CERTCertificate *)dc->data;
|
||||||
SECCertUsage secUsage = usage->nss3usage;
|
SECCertUsage secUsage = usage->nss3usage;
|
||||||
PRBool ca = usage->nss3lookingForCA;
|
PRBool ca = usage->nss3lookingForCA;
|
||||||
|
|
||||||
|
/* This is for NSS 3.3 functions that do not specify a usage */
|
||||||
|
if (usage->anyUsage) {
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
secrv = CERT_KeyUsageAndTypeForCertUsage(secUsage, ca,
|
secrv = CERT_KeyUsageAndTypeForCertUsage(secUsage, ca,
|
||||||
&requiredKeyUsage,
|
&requiredKeyUsage,
|
||||||
&requiredCertType);
|
&requiredCertType);
|
||||||
@ -391,6 +410,7 @@ nssDecodedPKIXCertificate_Create (
|
|||||||
rvDC->getIdentifier = nss3certificate_getIdentifier;
|
rvDC->getIdentifier = nss3certificate_getIdentifier;
|
||||||
rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
|
rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
|
||||||
rvDC->matchIdentifier = nss3certificate_matchIdentifier;
|
rvDC->matchIdentifier = nss3certificate_matchIdentifier;
|
||||||
|
rvDC->isValidIssuer = nss3certificate_isValidIssuer;
|
||||||
rvDC->getUsage = nss3certificate_getUsage;
|
rvDC->getUsage = nss3certificate_getUsage;
|
||||||
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
||||||
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
||||||
@ -413,6 +433,7 @@ create_decoded_pkix_cert_from_nss3cert (
|
|||||||
rvDC->getIdentifier = nss3certificate_getIdentifier;
|
rvDC->getIdentifier = nss3certificate_getIdentifier;
|
||||||
rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
|
rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
|
||||||
rvDC->matchIdentifier = nss3certificate_matchIdentifier;
|
rvDC->matchIdentifier = nss3certificate_matchIdentifier;
|
||||||
|
rvDC->isValidIssuer = nss3certificate_isValidIssuer;
|
||||||
rvDC->getUsage = nss3certificate_getUsage;
|
rvDC->getUsage = nss3certificate_getUsage;
|
||||||
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
||||||
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.15 $ $Date: 2002/09/23 21:32:33 $ $Name: $";
|
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.16 $ $Date: 2002/10/01 14:32:15 $ $Name: $";
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
#ifndef DEV_H
|
#ifndef DEV_H
|
||||||
@ -429,6 +429,9 @@ nssCertificateArray_FindBestCertificate (
|
|||||||
{
|
{
|
||||||
NSSCertificate *bestCert = NULL;
|
NSSCertificate *bestCert = NULL;
|
||||||
NSSTime *time, sTime;
|
NSSTime *time, sTime;
|
||||||
|
PRBool haveUsageMatch = PR_FALSE;
|
||||||
|
PRBool thisCertMatches;
|
||||||
|
|
||||||
if (timeOpt) {
|
if (timeOpt) {
|
||||||
time = timeOpt;
|
time = timeOpt;
|
||||||
} else {
|
} else {
|
||||||
@ -442,32 +445,31 @@ nssCertificateArray_FindBestCertificate (
|
|||||||
nssDecodedCert *dc, *bestdc;
|
nssDecodedCert *dc, *bestdc;
|
||||||
NSSCertificate *c = *certs;
|
NSSCertificate *c = *certs;
|
||||||
dc = nssCertificate_GetDecoding(c);
|
dc = nssCertificate_GetDecoding(c);
|
||||||
|
if (!dc) continue;
|
||||||
|
thisCertMatches = dc->matchUsage(dc, usage);
|
||||||
if (!bestCert) {
|
if (!bestCert) {
|
||||||
/* take the first cert with matching usage */
|
/* always take the first cert, but remember whether or not
|
||||||
#ifdef NSS_3_4_CODE
|
* the usage matched
|
||||||
if (usage->anyUsage) {
|
*/
|
||||||
#else
|
bestCert = nssCertificate_AddRef(c);
|
||||||
if (!usage || usage->anyUsage) {
|
haveUsageMatch = thisCertMatches;
|
||||||
#endif
|
|
||||||
bestCert = nssCertificate_AddRef(c);
|
|
||||||
} else {
|
|
||||||
if (dc->matchUsage(dc, usage)) {
|
|
||||||
bestCert = nssCertificate_AddRef(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* already have a cert for this usage, if this cert doesn't have
|
if (haveUsageMatch && !thisCertMatches) {
|
||||||
* the correct usage, continue
|
/* if already have a cert for this usage, and if this cert
|
||||||
* if ths cert does match usage, defer to time/policies
|
* doesn't have the correct usage, continue
|
||||||
*/
|
*/
|
||||||
#ifdef NSS_3_4_CODE
|
continue;
|
||||||
if (!usage->anyUsage && !dc->matchUsage(dc, usage)) {
|
} else if (!haveUsageMatch && thisCertMatches) {
|
||||||
#else
|
/* this one does match usage, replace the other */
|
||||||
if (PR_TRUE) {
|
nssCertificate_Destroy(bestCert);
|
||||||
#endif
|
bestCert = nssCertificate_AddRef(c);
|
||||||
|
haveUsageMatch = PR_TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* this cert match as well as any cert we've found so far,
|
||||||
|
* defer to time/policies
|
||||||
|
* */
|
||||||
}
|
}
|
||||||
bestdc = nssCertificate_GetDecoding(bestCert);
|
bestdc = nssCertificate_GetDecoding(bestCert);
|
||||||
/* time */
|
/* time */
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#define PKITM_H
|
#define PKITM_H
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static const char PKITM_CVS_ID[] = "@(#) $RCSfile: pkitm.h,v $ $Revision: 1.9 $ $Date: 2002/04/18 17:30:04 $ $Name: $";
|
static const char PKITM_CVS_ID[] = "@(#) $RCSfile: pkitm.h,v $ $Revision: 1.10 $ $Date: 2002/10/01 14:32:15 $ $Name: $";
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -54,6 +54,12 @@ static const char PKITM_CVS_ID[] = "@(#) $RCSfile: pkitm.h,v $ $Revision: 1.9 $
|
|||||||
|
|
||||||
PR_BEGIN_EXTERN_C
|
PR_BEGIN_EXTERN_C
|
||||||
|
|
||||||
|
typedef enum nssCertIDMatchEnum {
|
||||||
|
nssCertIDMatch_Yes = 0,
|
||||||
|
nssCertIDMatch_No = 1,
|
||||||
|
nssCertIDMatch_Unknown = 2
|
||||||
|
} nssCertIDMatch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nssDecodedCert
|
* nssDecodedCert
|
||||||
*
|
*
|
||||||
@ -68,9 +74,11 @@ struct nssDecodedCertStr {
|
|||||||
/* returns the unique identifier for the cert */
|
/* returns the unique identifier for the cert */
|
||||||
NSSItem * (*getIdentifier)(nssDecodedCert *dc);
|
NSSItem * (*getIdentifier)(nssDecodedCert *dc);
|
||||||
/* returns the unique identifier for this cert's issuer */
|
/* returns the unique identifier for this cert's issuer */
|
||||||
NSSItem * (*getIssuerIdentifier)(nssDecodedCert *dc);
|
void * (*getIssuerIdentifier)(nssDecodedCert *dc);
|
||||||
/* is id the identifier for this cert? */
|
/* is id the identifier for this cert? */
|
||||||
PRBool (*matchIdentifier)(nssDecodedCert *dc, NSSItem *id);
|
nssCertIDMatch (*matchIdentifier)(nssDecodedCert *dc, void *id);
|
||||||
|
/* is this cert a valid CA cert? */
|
||||||
|
PRBool (*isValidIssuer)(nssDecodedCert *dc);
|
||||||
/* returns the cert usage */
|
/* returns the cert usage */
|
||||||
NSSUsage * (*getUsage)(nssDecodedCert *dc);
|
NSSUsage * (*getUsage)(nssDecodedCert *dc);
|
||||||
/* is time within the validity period of the cert? */
|
/* is time within the validity period of the cert? */
|
||||||
|
Loading…
Reference in New Issue
Block a user