fix for bug 120824; functions which collect certs based on subject need to examine *both* the temp and perm stores

This commit is contained in:
ian.mcgreer%sun.com 2002-01-22 21:56:19 +00:00
parent 59fb02e06f
commit 82ee31efe8
2 changed files with 201 additions and 101 deletions

View File

@ -267,24 +267,44 @@ CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndS
return cert;
}
static NSSCertificate *
get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
{
nssBestCertificateCB best;
NSSUsage usage;
usage.anyUsage = PR_TRUE;
nssBestCertificate_SetArgs(&best, NULL, &usage, NULL);
if (ct) {
nssBestCertificate_Callback(ct, (void *)&best);
}
if (cp) {
nssBestCertificate_Callback(cp, (void *)&best);
}
return best.cert;
}
CERTCertificate *
CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name)
{
NSSCertificate *c;
NSSCertificate *cp, *ct, *c;
NSSDER subject;
NSSUsage usage;
NSSCryptoContext *cc;
NSSITEM_FROM_SECITEM(&subject, name);
usage.anyUsage = PR_TRUE;
cc = STAN_GetDefaultCryptoContext();
c = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject,
NULL, &usage, NULL);
if (!c) {
c = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject,
NULL, &usage, NULL);
if (!c) return NULL;
ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject,
NULL, &usage, NULL);
cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject,
NULL, &usage, NULL);
c = get_best_temp_or_perm(ct, cp);
if (ct) NSSCertificate_Destroy(ct);
if (cp) NSSCertificate_Destroy(cp);
if (c) {
return STAN_GetCERTCertificate(c);
} else {
return NULL;
}
return STAN_GetCERTCertificate(c);
}
CERTCertificate *
@ -310,16 +330,27 @@ CERTCertificate *
CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname)
{
NSSCryptoContext *cc;
NSSCertificate *c;
NSSCertificate *c, *ct;
CERTCertificate *cert;
NSSUsage usage;
usage.anyUsage = PR_TRUE;
cc = STAN_GetDefaultCryptoContext();
c = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname,
ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname,
NULL, &usage, NULL);
cert = PK11_FindCertFromNickname(nickname, NULL);
c = NULL;
if (cert) {
c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
CERT_DestroyCertificate(cert);
if (ct) NSSCertificate_Destroy(ct);
} else {
c = ct;
}
if (c) {
return STAN_GetCERTCertificate(c);
} else {
return NULL;
}
return PK11_FindCertFromNickname(nickname, NULL);
}
CERTCertificate *
@ -343,21 +374,48 @@ CERTCertificate *
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *name)
{
NSSCryptoContext *cc;
NSSCertificate *c;
NSSCertificate *c, *ct;
CERTCertificate *cert;
NSSUsage usage;
usage.anyUsage = PR_TRUE;
cc = STAN_GetDefaultCryptoContext();
c = NSSCryptoContext_FindBestCertificateByNickname(cc, name,
ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name,
NULL, &usage, NULL);
if (!ct) {
ct = NSSCryptoContext_FindBestCertificateByEmail(cc, name,
NULL, &usage, NULL);
}
cert = PK11_FindCertFromNickname(name, NULL);
if (cert) {
c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
CERT_DestroyCertificate(cert);
if (ct) NSSCertificate_Destroy(ct);
} else {
c = ct;
}
if (c) {
return STAN_GetCERTCertificate(c);
}
c = NSSCryptoContext_FindBestCertificateByEmail(cc, name,
NULL, &usage, NULL);
if (c) {
return STAN_GetCERTCertificate(c);
return NULL;
}
static void
add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
PRBool validOnly, int64 sorttime)
{
SECStatus secrv;
if (!validOnly ||
CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE)
== secCertTimeValid) {
secrv = CERT_AddCertToListSorted(certList, cert,
CERT_SortCBValidity,
(void *)&sorttime);
if (secrv != SECSuccess) {
CERT_DestroyCertificate(cert);
}
} else {
CERT_DestroyCertificate(cert);
}
return PK11_FindCertFromNickname(name, NULL);
}
CERTCertList *
@ -365,54 +423,53 @@ CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle,
SECItem *name, int64 sorttime, PRBool validOnly)
{
NSSCryptoContext *cc;
NSSCertificate **subjectCerts;
NSSCertificate *c;
NSSCertificate **tSubjectCerts, **pSubjectCerts;
NSSCertificate **ci;
CERTCertificate *cert;
NSSDER subject;
PRUint32 i;
SECStatus secrv;
PRBool myList = PR_FALSE;
cc = STAN_GetDefaultCryptoContext();
NSSITEM_FROM_SECITEM(&subject, name);
subjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc,
&subject,
NULL,
0,
NULL);
if (!subjectCerts) {
subjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle,
&subject,
NULL,
0,
NULL);
if (!subjectCerts) {
return NULL;
}
/* Collect both temp and perm certs for the subject */
tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc,
&subject,
NULL,
0,
NULL);
pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle,
&subject,
NULL,
0,
NULL);
if (!tSubjectCerts && !pSubjectCerts) {
return NULL;
}
i = 0;
if (certList == NULL && subjectCerts) {
if (certList == NULL) {
certList = CERT_NewCertList();
myList = PR_TRUE;
if (!certList) goto loser;
}
while ((c = subjectCerts[i++])) {
CERTCertificate *cc = STAN_GetCERTCertificate(c);
if (!validOnly ||
CERT_CheckCertValidTimes(cc, sorttime, PR_FALSE)
== secCertTimeValid) {
secrv = CERT_AddCertToListSorted(certList, cc,
CERT_SortCBValidity,
(void *)&sorttime);
if (secrv != SECSuccess) {
CERT_DestroyCertificate(cc);
goto loser;
}
} else {
CERT_DestroyCertificate(cc);
}
/* Iterate over the matching temp certs. Add them to the list */
ci = tSubjectCerts;
while (ci && *ci) {
cert = STAN_GetCERTCertificate(*ci);
add_to_subject_list(certList, cert, validOnly, sorttime);
ci++;
}
nss_ZFreeIf(subjectCerts);
/* Iterate over the matching perm certs. Add them to the list */
ci = pSubjectCerts;
while (ci && *ci) {
cert = STAN_GetCERTCertificate(*ci);
add_to_subject_list(certList, cert, validOnly, sorttime);
ci++;
}
nss_ZFreeIf(tSubjectCerts);
nss_ZFreeIf(pSubjectCerts);
return certList;
loser:
nss_ZFreeIf(subjectCerts);
if (certList != NULL) {
nss_ZFreeIf(tSubjectCerts);
nss_ZFreeIf(pSubjectCerts);
if (myList && certList != NULL) {
CERT_DestroyCertList(certList);
}
return NULL;

View File

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.25 $ $Date: 2002/01/10 20:24:46 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.26 $ $Date: 2002/01/22 21:56:16 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSPKI_H
@ -190,6 +190,41 @@ nssCertificate_GetDecoding
return c->decoding;
}
static void
nssCertificateArray_Destroy
(
NSSCertificate **certArray
)
{
NSSCertificate **ci;
ci = certArray;
while (ci && *ci) {
NSSCertificate_Destroy(*ci);
ci++;
}
nss_ZFreeIf(certArray);
}
static NSSCertificate *
filter_subject_certs_for_id(NSSCertificate **subjectCerts, NSSItem *id)
{
NSSCertificate **si;
NSSCertificate *rvCert = NULL;
nssDecodedCert *dcp;
/* walk the subject certs */
si = subjectCerts;
while (*si) {
dcp = nssCertificate_GetDecoding(*si);
if (dcp->matchIdentifier(dcp, id)) {
/* this cert has the correct identifier */
rvCert = nssCertificate_AddRef(*si);
break;
}
si++;
}
return rvCert;
}
static NSSCertificate *
find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id)
{
@ -205,8 +240,12 @@ find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id)
NULL,
0,
NULL);
if (subjectCerts) {
rvCert = filter_subject_certs_for_id(subjectCerts, id);
nssCertificateArray_Destroy(subjectCerts);
}
}
if (!subjectCerts) {
if (!rvCert) {
/* The general behavior of NSS <3.4 seems to be that if the search
* turns up empty in the temp db, fall back to the perm db,
* irregardless of whether or not the cert itself is perm or temp.
@ -218,29 +257,10 @@ find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id)
NULL,
0,
NULL);
}
if (subjectCerts) {
NSSCertificate *p;
nssDecodedCert *dcp;
int i = 0;
/* walk the subject certs */
while ((p = subjectCerts[i++])) {
dcp = nssCertificate_GetDecoding(p);
if (dcp->matchIdentifier(dcp, id)) {
/* this cert has the correct identifier */
rvCert = p;
/* now free all the remaining subject certs */
while ((p = subjectCerts[i++])) {
NSSCertificate_Destroy(p);
}
/* and exit */
break;
} else {
/* cert didn't have the correct identifier, so free it */
NSSCertificate_Destroy(p);
}
if (subjectCerts) {
rvCert = filter_subject_certs_for_id(subjectCerts, id);
nssCertificateArray_Destroy(subjectCerts);
}
nss_ZFreeIf(subjectCerts);
}
return rvCert;
}
@ -269,6 +289,7 @@ NSSCertificate_BuildChain
NSSTrustDomain *td;
NSSCryptoContext *cc;
nssDecodedCert *dc;
NSSCertificate *ct, *cp;
cc = c->object.cryptoContext; /* NSSCertificate_GetCryptoContext(c); */
td = NSSCertificate_GetTrustDomain(c);
#ifdef NSS_3_4_CODE
@ -292,25 +313,26 @@ NSSCertificate_BuildChain
goto finish;
}
} else {
nssBestCertificateCB best;
NSSDER *issuer = &c->issuer;
#ifdef NSS_3_4_CODE
PRBool tmpca = usage->nss3lookingForCA;
usage->nss3lookingForCA = PR_TRUE;
#endif
c = NULL;
c = ct = cp = NULL;
if (cc) {
c = NSSCryptoContext_FindBestCertificateBySubject(cc,
issuer,
timeOpt,
usage,
policiesOpt);
ct = NSSCryptoContext_FindBestCertificateBySubject(cc,
issuer,
timeOpt,
usage,
policiesOpt);
/* Mimic functionality from CERT_FindCertIssuer. If a matching
* cert (based on trust & usage) cannot be found, just take the
* newest cert with the correct subject.
*/
if (!c && !usage->anyUsage) {
if (!ct && !usage->anyUsage) {
usage->anyUsage = PR_TRUE;
c = NSSCryptoContext_FindBestCertificateBySubject(cc,
ct = NSSCryptoContext_FindBestCertificateBySubject(cc,
issuer,
timeOpt,
usage,
@ -318,26 +340,47 @@ NSSCertificate_BuildChain
usage->anyUsage = PR_FALSE;
}
}
if (!c) {
c = NSSTrustDomain_FindBestCertificateBySubject(td,
issuer,
timeOpt,
usage,
policiesOpt);
}
cp = NSSTrustDomain_FindBestCertificateBySubject(td,
issuer,
timeOpt,
usage,
policiesOpt);
/* Mimic functionality from CERT_FindCertIssuer. If a matching
* cert (based on trust & usage) cannot be found, just take the
* newest cert with the correct subject.
*/
if (!c && !usage->anyUsage) {
if (!cp && !usage->anyUsage) {
usage->anyUsage = PR_TRUE;
c = NSSTrustDomain_FindBestCertificateBySubject(td,
issuer,
timeOpt,
usage,
policiesOpt);
cp = NSSTrustDomain_FindBestCertificateBySubject(td,
issuer,
timeOpt,
usage,
policiesOpt);
usage->anyUsage = PR_FALSE;
}
nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt);
/* Take the better of the best temp and best perm cert, according
* to the given usage
*/
if (ct) {
nssBestCertificate_Callback(ct, (void *)&best);
}
if (cp) {
nssBestCertificate_Callback(cp, (void *)&best);
}
if (!best.cert) {
best.usage->anyUsage = PR_TRUE;
/* Take the newest of the best temp and best perm cert */
if (ct) {
nssBestCertificate_Callback(ct, (void *)&best);
}
if (cp) {
nssBestCertificate_Callback(cp, (void *)&best);
}
}
if (ct) NSSCertificate_Destroy(ct);
if (cp) NSSCertificate_Destroy(cp);
c = best.cert;
#ifdef NSS_3_4_CODE
usage->nss3lookingForCA = tmpca;
#endif