CERTCertificate * CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) { NSSCertificate *cp, *ct, *c; NSSDER subject; NSSUsage usage; NSSCryptoContext *cc; NSSITEM_FROM_SECITEM(&subject, name); usage.anyUsage = PR_TRUE; cc = STAN_GetDefaultCryptoContext(); 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) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); } if (cp) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp)); } return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; }
CERTCertificate * CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname) { NSSCryptoContext *cc; NSSCertificate *c, *ct; CERTCertificate *cert; NSSUsage usage; usage.anyUsage = PR_TRUE; cc = STAN_GetDefaultCryptoContext(); 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) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); } } else { c = ct; } return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; }
CERTCertificate * CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name) { NSSCryptoContext *cc; NSSCertificate *c, *ct; CERTCertificate *cert; NSSUsage usage; if (NULL == name) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } usage.anyUsage = PR_TRUE; cc = STAN_GetDefaultCryptoContext(); ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, NULL, &usage, NULL); if (!ct && PORT_Strchr(name, '@') != NULL) { char* lowercaseName = CERT_FixupEmailAddr(name); if (lowercaseName) { ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, NULL, &usage, NULL); PORT_Free(lowercaseName); } } cert = PK11_FindCertFromNickname(name, NULL); if (cert) { c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); CERT_DestroyCertificate(cert); if (ct) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); } } else { c = ct; } return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; }
CERTCertificate * CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) { NSSCryptoContext *cc; NSSCertificate *c; NSSDER encoding; NSSITEM_FROM_SECITEM(&encoding, derCert); cc = STAN_GetDefaultCryptoContext(); c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); if (!c) { c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, &encoding); if (!c) return NULL; } return STAN_GetCERTCertificateOrRelease(c); }
CERTCertList * CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, const SECItem *name, PRTime sorttime, PRBool validOnly) { NSSCryptoContext *cc; NSSCertificate **tSubjectCerts, **pSubjectCerts; NSSCertificate **ci; CERTCertificate *cert; NSSDER subject; PRBool myList = PR_FALSE; cc = STAN_GetDefaultCryptoContext(); NSSITEM_FROM_SECITEM(&subject, name); /* 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; } if (certList == NULL) { certList = CERT_NewCertList(); myList = PR_TRUE; if (!certList) goto loser; } /* Iterate over the matching temp certs. Add them to the list */ ci = tSubjectCerts; while (ci && *ci) { cert = STAN_GetCERTCertificateOrRelease(*ci); /* *ci may be invalid at this point, don't reference it again */ if (cert) { /* NOTE: add_to_subject_list adopts the incoming cert. */ add_to_subject_list(certList, cert, validOnly, sorttime); } ci++; } /* Iterate over the matching perm certs. Add them to the list */ ci = pSubjectCerts; while (ci && *ci) { cert = STAN_GetCERTCertificateOrRelease(*ci); /* *ci may be invalid at this point, don't reference it again */ if (cert) { /* NOTE: add_to_subject_list adopts the incoming cert. */ add_to_subject_list(certList, cert, validOnly, sorttime); } ci++; } /* all the references have been adopted or freed at this point, just * free the arrays now */ nss_ZFreeIf(tSubjectCerts); nss_ZFreeIf(pSubjectCerts); return certList; loser: /* need to free the references in tSubjectCerts and pSubjectCerts! */ nssCertificateArray_Destroy(tSubjectCerts); nssCertificateArray_Destroy(pSubjectCerts); if (myList && certList != NULL) { CERT_DestroyCertList(certList); } return NULL; }
static CERTCertificate * common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, const char *name, PRBool anyUsage, SECCertUsage lookingForUsage) { NSSCryptoContext *cc; NSSCertificate *c, *ct; CERTCertificate *cert = NULL; NSSUsage usage; CERTCertList *certlist; if (NULL == name) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } usage.anyUsage = anyUsage; if (!anyUsage) { usage.nss3lookingForCA = PR_FALSE; usage.nss3usage = lookingForUsage; } cc = STAN_GetDefaultCryptoContext(); ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, NULL, &usage, NULL); if (!ct && PORT_Strchr(name, '@') != NULL) { char *lowercaseName = CERT_FixupEmailAddr(name); if (lowercaseName) { ct = NSSCryptoContext_FindBestCertificateByEmail( cc, lowercaseName, NULL, &usage, NULL); PORT_Free(lowercaseName); } } if (anyUsage) { cert = PK11_FindCertFromNickname(name, NULL); } else { if (ct) { /* Does ct really have the required usage? */ nssDecodedCert *dc; dc = nssCertificate_GetDecoding(ct); if (!dc->matchUsage(dc, &usage)) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); ct = NULL; } } certlist = PK11_FindCertsFromNickname(name, NULL); if (certlist) { SECStatus rv = CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE); if (SECSuccess == rv && !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert); } CERT_DestroyCertList(certlist); } } if (cert) { c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); CERT_DestroyCertificate(cert); if (ct) { CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); } } else { c = ct; } return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; }
CERTCertificate * CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, PRBool isperm, PRBool copyDER) { NSSCertificate *c; CERTCertificate *cc; NSSCertificate *tempCert = NULL; nssPKIObject *pkio; NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); if (!isperm) { NSSDER encoding; NSSITEM_FROM_SECITEM(&encoding, derCert); /* First, see if it is already a temp cert */ c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, &encoding); if (!c) { /* Then, see if it is already a perm cert */ c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, &encoding); } if (c) { /* actually, that search ends up going by issuer/serial, * so it is still possible to return a cert with the same * issuer/serial but a different encoding, and we're * going to reject that */ if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { nssCertificate_Destroy(c); PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); cc = NULL; } else { cc = STAN_GetCERTCertificateOrRelease(c); if (cc == NULL) { CERT_MapStanError(); } } return cc; } } pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); if (!pkio) { CERT_MapStanError(); return NULL; } c = nss_ZNEW(pkio->arena, NSSCertificate); if (!c) { CERT_MapStanError(); nssPKIObject_Destroy(pkio); return NULL; } c->object = *pkio; if (copyDER) { nssItem_Create(c->object.arena, &c->encoding, derCert->len, derCert->data); } else { NSSITEM_FROM_SECITEM(&c->encoding, derCert); } /* Forces a decoding of the cert in order to obtain the parts used * below */ /* 'c' is not adopted here, if we fail loser frees what has been * allocated so far for 'c' */ cc = STAN_GetCERTCertificate(c); if (!cc) { CERT_MapStanError(); goto loser; } nssItem_Create(c->object.arena, &c->issuer, cc->derIssuer.len, cc->derIssuer.data); nssItem_Create(c->object.arena, &c->subject, cc->derSubject.len, cc->derSubject.data); if (PR_TRUE) { /* CERTCertificate stores serial numbers decoded. I need the DER * here. sigh. */ SECItem derSerial = { 0 }; CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); if (!derSerial.data) goto loser; nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); PORT_Free(derSerial.data); } if (nickname) { c->object.tempName = nssUTF8_Create(c->object.arena, nssStringType_UTF8String, (NSSUTF8 *)nickname, PORT_Strlen(nickname)); } if (cc->emailAddr && cc->emailAddr[0]) { c->email = nssUTF8_Create( c->object.arena, nssStringType_PrintableString, (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr)); } tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); if (!tempCert) { CERT_MapStanError(); goto loser; } /* destroy our copy */ NSSCertificate_Destroy(c); /* and use the stored entry */ c = tempCert; cc = STAN_GetCERTCertificateOrRelease(c); if (!cc) { /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ CERT_MapStanError(); return NULL; } cc->istemp = PR_TRUE; cc->isperm = PR_FALSE; return cc; loser: /* Perhaps this should be nssCertificate_Destroy(c) */ nssPKIObject_Destroy(&c->object); return NULL; }
SECStatus __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, CERTCertTrust *trust) { NSSUTF8 *stanNick; PK11SlotInfo *slot; NSSToken *internal; NSSCryptoContext *context; nssCryptokiObject *permInstance; NSSCertificate *c = STAN_GetNSSCertificate(cert); nssCertificateStoreTrace lockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; nssCertificateStoreTrace unlockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; SECStatus rv; PRStatus ret; if (c == NULL) { CERT_MapStanError(); return SECFailure; } context = c->object.cryptoContext; if (!context) { PORT_SetError(SEC_ERROR_ADDING_CERT); return SECFailure; /* wasn't a temp cert */ } stanNick = nssCertificate_GetNickname(c, NULL); if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { /* different: take the new nickname */ cert->nickname = NULL; nss_ZFreeIf(stanNick); stanNick = NULL; } if (!stanNick && nickname) { /* Either there was no nickname yet, or we have a new nickname */ stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL); } /* else: old stanNick is identical to new nickname */ /* Delete the temp instance */ nssCertificateStore_Lock(context->certStore, &lockTrace); nssCertificateStore_RemoveCertLOCKED(context->certStore, c); nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); c->object.cryptoContext = NULL; /* Import the perm instance onto the internal token */ slot = PK11_GetInternalKeySlot(); internal = PK11Slot_GetNSSToken(slot); permInstance = nssToken_ImportCertificate( internal, NULL, NSSCertificateType_PKIX, &c->id, stanNick, &c->encoding, &c->issuer, &c->subject, &c->serial, cert->emailAddr, PR_TRUE); nss_ZFreeIf(stanNick); stanNick = NULL; PK11_FreeSlot(slot); if (!permInstance) { if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); } return SECFailure; } nssPKIObject_AddInstance(&c->object, permInstance); nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); /* reset the CERTCertificate fields */ cert->nssCertificate = NULL; cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */ if (!cert) { CERT_MapStanError(); return SECFailure; } cert->istemp = PR_FALSE; cert->isperm = PR_TRUE; if (!trust) { return SECSuccess; } ret = STAN_ChangeCertTrust(cert, trust); rv = SECSuccess; if (ret != PR_SUCCESS) { rv = SECFailure; CERT_MapStanError(); } return rv; }