mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
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:
parent
59fb02e06f
commit
82ee31efe8
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user