/* ** Delete trust objects matching the slot of the given certificate. ** Returns an error if any device fails to delete. */ NSS_EXTERN PRStatus STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c) { PRStatus nssrv = PR_SUCCESS; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); /* caller made sure nssTrust isn't NULL */ nssPKIObject *tobject = &nssTrust->object; nssPKIObject *cobject = &c->object; int i; /* Iterate through the cert and trust object instances looking for * those with matching pk11 slots to delete. Even if some device * can't delete we keep going. Keeping a status variable for the * loop so that once it's failed the other gets set. */ NSSRWLock_LockRead(td->tokensLock); nssPKIObject_Lock(cobject); for (i = 0; i < cobject->numInstances; i++) { nssCryptokiObject *cInstance = cobject->instances[i]; if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) { PRStatus status; if (!tobject->numInstances || !tobject->instances) continue; status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject); if (status == PR_FAILURE) { /* set the outer one but keep going */ nssrv = PR_FAILURE; } } } nssPKIObject_Unlock(cobject); NSSRWLock_UnlockRead(td->tokensLock); return nssrv; }
/* ** Delete trust objects matching the given slot. ** Returns error if a device fails to delete. ** ** This function has the side effect of moving the ** surviving entries to the front of the object list ** and nullifying the rest. */ static PRStatus DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject) { int numNotDestroyed = 0; /* the ones skipped plus the failures */ int failureCount = 0; /* actual deletion failures by devices */ unsigned int index; nssPKIObject_AddRef(tObject); nssPKIObject_Lock(tObject); /* Keep going even if a module fails to delete. */ for (index = 0; index < tObject->numInstances; index++) { nssCryptokiObject *instance = tObject->instances[index]; if (!instance) { continue; } /* ReadOnly and not matched treated the same */ if (PK11_IsReadOnly(instance->token->pk11slot) || pk11slot != instance->token->pk11slot) { tObject->instances[numNotDestroyed++] = instance; continue; } /* Here we have found a matching one */ tObject->instances[index] = NULL; if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) { nssCryptokiObject_Destroy(instance); } else { tObject->instances[numNotDestroyed++] = instance; failureCount++; } } if (numNotDestroyed == 0) { nss_ZFreeIf(tObject->instances); tObject->numInstances = 0; } else { tObject->numInstances = numNotDestroyed; } nssPKIObject_Unlock(tObject); nssPKIObject_Destroy(tObject); return failureCount == 0 ? PR_SUCCESS : PR_FAILURE; }
static NSSToken* stan_GetTrustToken ( NSSCertificate *c ) { NSSToken *ttok = NULL; NSSToken *rtok = NULL; NSSToken *tok = NULL; nssCryptokiObject **ip; nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); if (!instances) { return PR_FALSE; } for (ip = instances; *ip; ip++) { nssCryptokiObject *instance = *ip; nssCryptokiObject *to = nssToken_FindTrustForCertificate(instance->token, NULL, &c->encoding, &c->issuer, &c->serial, nssTokenSearchType_TokenOnly); NSSToken *ctok = instance->token; PRBool ro = PK11_IsReadOnly(ctok->pk11slot); if (to) { nssCryptokiObject_Destroy(to); ttok = ctok; if (!ro) { break; } } else { if (!rtok && ro) { rtok = ctok; } if (!tok && !ro) { tok = ctok; } } } nssCryptokiObjectArray_Destroy(instances); return ttok ? ttok : (tok ? tok : rtok); }
void nsNSSCertificate::destructorSafeDestroyNSSReference() { if (isAlreadyShutDown()) return; if (mPermDelete) { if (mCertType == nsNSSCertificate::USER_CERT) { nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext(); PK11_DeleteTokenCertAndKey(mCert, cxt); } else if (!PK11_IsReadOnly(mCert->slot)) { // If the list of built-ins does contain a non-removable // copy of this certificate, our call will not remove // the certificate permanently, but rather remove all trust. SEC_DeletePermCertificate(mCert); } } if (mCert) { CERT_DestroyCertificate(mCert); mCert = nullptr; } }
NSS_EXTERN PRStatus STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) { PRStatus nssrv; NSSCertificate *c = STAN_GetNSSCertificate(cc); NSSToken *tok; NSSTrustDomain *td; NSSTrust *nssTrust; NSSArena *arena; CERTCertTrust *oldTrust; CERTCertTrust *newTrust; nssListIterator *tokens; PRBool moving_object; nssCryptokiObject *newInstance; nssPKIObject *pkiob; if (c == NULL) { return PR_FAILURE; } oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); if (oldTrust) { if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { /* ... and the new trust is no different, done) */ return PR_SUCCESS; } else { /* take over memory already allocated in cc's arena */ newTrust = oldTrust; } } else { newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); } memcpy(newTrust, trust, sizeof(CERTCertTrust)); CERT_LockCertTrust(cc); cc->trust = newTrust; CERT_UnlockCertTrust(cc); /* Set the NSSCerticate's trust */ arena = nssArena_Create(); if (!arena) return PR_FAILURE; nssTrust = nss_ZNEW(arena, NSSTrust); if (!nssTrust) { nssArena_Destroy(arena); return PR_FAILURE; } pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock); if (!pkiob) { nssArena_Destroy(arena); return PR_FAILURE; } nssTrust->object = *pkiob; nssTrust->certificate = c; nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE); nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE); nssTrust->stepUpApproved = (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); if (c->object.cryptoContext != NULL) { /* The cert is in a context, set the trust there */ NSSCryptoContext *cc = c->object.cryptoContext; nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); if (nssrv != PR_SUCCESS) { goto done; } if (c->object.numInstances == 0) { /* The context is the only instance, finished */ goto done; } } td = STAN_GetDefaultTrustDomain(); tok = stan_GetTrustToken(c); moving_object = PR_FALSE; if (tok && PK11_IsReadOnly(tok->pk11slot)) { NSSRWLock_LockRead(td->tokensLock); tokens = nssList_CreateIterator(td->tokenList); if (!tokens) { nssrv = PR_FAILURE; NSSRWLock_UnlockRead(td->tokensLock); goto done; } for (tok = (NSSToken *)nssListIterator_Start(tokens); tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(tokens)) { if (!PK11_IsReadOnly(tok->pk11slot)) break; } nssListIterator_Finish(tokens); nssListIterator_Destroy(tokens); NSSRWLock_UnlockRead(td->tokensLock); moving_object = PR_TRUE; } if (tok) { if (moving_object) { /* this is kind of hacky. the softoken needs the cert * object in order to store trust. forcing it to be perm */ NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = NULL; if (PK11_IsInternal(tok->pk11slot)) { email = c->email; } newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); } newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); /* If the selected token can't handle trust, dump the trust on * the internal token */ if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = c->email; tok = PK11Slot_GetNSSToken(slot); PK11_FreeSlot(slot); newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); } if (newInstance) { nssCryptokiObject_Destroy(newInstance); nssrv = PR_SUCCESS; } else { nssrv = PR_FAILURE; } } else { nssrv = PR_FAILURE; } done: (void)nssTrust_Destroy(nssTrust); return nssrv; }