NSS_IMPLEMENT PRStatus nssCertificate_Destroy ( NSSCertificate *c ) { nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; if (c) { PRUint32 i; nssDecodedCert *dc = c->decoding; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCryptoContext *cc = c->object.cryptoContext; PR_ASSERT(c->object.refCount > 0); /* --- LOCK storage --- */ if (cc) { nssCertificateStore_Lock(cc->certStore, &lockTrace); } else { nssTrustDomain_LockCertCache(td); } if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) { /* --- remove cert and UNLOCK storage --- */ if (cc) { nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); } else { nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); nssTrustDomain_UnlockCertCache(td); } /* free cert data */ for (i=0; i<c->object.numInstances; i++) { nssCryptokiObject_Destroy(c->object.instances[i]); } nssPKIObject_DestroyLock(&c->object); nssArena_Destroy(c->object.arena); nssDecodedCert_Destroy(dc); } else { /* --- UNLOCK storage --- */ if (cc) { nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); } else { nssTrustDomain_UnlockCertCache(td); } } } return PR_SUCCESS; }
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; }