static void cert_dump_iter(const void *k, void *v, void *a) { NSSCertificate *c = (NSSCertificate *)k; CERTCertificate *cert = STAN_GetCERTCertificate(c); printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName); }
NSS_IMPLEMENT nssDecodedCert * nssCertificate_GetDecoding ( NSSCertificate *c ) { nssDecodedCert* deco = NULL; if (c->type == NSSCertificateType_PKIX) { (void)STAN_GetCERTCertificate(c); } nssPKIObject_Lock(&c->object); if (!c->decoding) { deco = nssDecodedCert_Create(NULL, &c->encoding, c->type); PORT_Assert(!c->decoding); c->decoding = deco; } else { deco = c->decoding; } nssPKIObject_Unlock(&c->object); return deco; }
CERTCertificateList * CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, PRBool includeRoot) { CERTCertificateList *chain = NULL; NSSCertificate **stanChain; NSSCertificate *stanCert; PRArenaPool *arena; NSSUsage nssUsage; int i, len; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCryptoContext *cc = STAN_GetDefaultCryptoContext(); stanCert = STAN_GetNSSCertificate(cert); if (!stanCert) { /* error code is set */ return NULL; } nssUsage.anyUsage = PR_FALSE; nssUsage.nss3usage = usage; nssUsage.nss3lookingForCA = PR_FALSE; stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL, CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc); if (!stanChain) { PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); return NULL; } len = 0; stanCert = stanChain[0]; while (stanCert) { stanCert = stanChain[++len]; } arena = PORT_NewArena(4096); if (arena == NULL) { goto loser; } chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList)); if (!chain) goto loser; chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); if (!chain->certs) goto loser; i = 0; stanCert = stanChain[i]; while (stanCert) { SECItem derCert; CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); if (!cCert) { goto loser; } derCert.len = (unsigned int)stanCert->encoding.size; derCert.data = (unsigned char *)stanCert->encoding.data; derCert.type = siBuffer; SECITEM_CopyItem(arena, &chain->certs[i], &derCert); 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) { chain->len = len - 1; } else { chain->len = len; } chain->arena = arena; nss_ZFreeIf(stanChain); return chain; loser: i = 0; stanCert = stanChain[i]; while (stanCert) { CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); if (cCert) { CERT_DestroyCertificate(cCert); } stanCert = stanChain[++i]; } nss_ZFreeIf(stanChain); if (arena) { PORT_FreeArena(arena, PR_FALSE); } return 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; }