/* CERT_FilterCertListByUsage */ static PRBool nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage) { CERTCertificate *cc; unsigned int requiredKeyUsage = 0; unsigned int requiredCertType = 0; SECStatus secrv; PRBool match; PRBool ca; /* This is for NSS 3.3 functions that do not specify a usage */ if (usage->anyUsage) { return PR_TRUE; } ca = usage->nss3lookingForCA; secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca, &requiredKeyUsage, &requiredCertType); if (secrv != SECSuccess) { return PR_FALSE; } cc = (CERTCertificate *)dc->data; secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage); match = (PRBool)(secrv == SECSuccess); if (match) { unsigned int certType = 0; if (ca) { (void)CERT_IsCACert(cc, &certType); } else { certType = cc->nsCertType; } if (!(certType & requiredCertType)) { match = PR_FALSE; } } return match; }
/* * Find a user certificate that matchs the given criteria. * * "handle" - database to search * "nickname" - nickname to match * "usage" - certificate usage to match * "validOnly" - only return certs that are curently valid * "proto_win" - window handle passed to pkcs11 */ CERTCertificate * CERT_FindUserCertByUsage(CERTCertDBHandle *handle, const char *nickname, SECCertUsage usage, PRBool validOnly, void *proto_win) { CERTCertificate *cert = NULL; CERTCertList *certList = NULL; SECStatus rv; int64 time; time = PR_Now(); /* use the pk11 call so that we pick up any certs on tokens, * which may require login */ /* XXX - why is this restricted? */ if ( proto_win != NULL ) { cert = PK11_FindCertFromNickname(nickname,proto_win); } /* sigh, There are still problems find smart cards from the temp * db. This will get smart cards working again. The real fix * is to make sure we can search the temp db by their token nickname. */ if (cert == NULL) { cert = CERT_FindCertByNickname(handle,nickname); } if ( cert != NULL ) { unsigned int requiredKeyUsage; unsigned int requiredCertType; rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE, &requiredKeyUsage, &requiredCertType); if ( rv != SECSuccess ) { /* drop the extra reference */ CERT_DestroyCertificate(cert); cert = NULL; goto loser; } /* If we already found the right cert, just return it */ if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) == secCertTimeValid) && (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) && (cert->nsCertType & requiredCertType) && CERT_IsUserCert(cert) ) { return(cert); } /* collect certs for this nickname, sorting them into the list */ certList = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, time, validOnly); CERT_FilterCertListForUserCerts(certList); /* drop the extra reference */ CERT_DestroyCertificate(cert); cert = NULL; } if ( certList == NULL ) { goto loser; } /* remove certs with incorrect usage */ rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) { cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert); } loser: if ( certList != NULL ) { CERT_DestroyCertList(certList); } return(cert); }