/* void deleteCert (in nsIX509Cert cert); */ NS_IMETHODIMP nsNSSCertList::DeleteCert(nsIX509Cert *aCert) { /* This should be a query interface, but currently this his how the * rest of PSM is working */ nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert); CERTCertificate *cert = nssCert->GetCert(); CERTCertListNode *node; if (cert == nullptr) { NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate."); return NS_ERROR_FAILURE; } if (mCertList == nullptr) { NS_ERROR("Somehow got nullptr for mCertList in nsNSSCertList."); return NS_ERROR_FAILURE; } for (node = CERT_LIST_HEAD(mCertList); !CERT_LIST_END(node,mCertList); node = CERT_LIST_NEXT(node)) { if (node->cert == cert) { CERT_RemoveCertListNode(node); return NS_OK; } } return NS_OK; /* should we fail if we couldn't find it? */ }
/* nsISupports getNext(); */ NS_IMETHODIMP nsNSSCertListEnumerator::GetNext(nsISupports **_retval) { NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE); CERTCertListNode *node = CERT_LIST_HEAD(mCertList); if (CERT_LIST_END(node, mCertList)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(node->cert); if (!nssCert) { return NS_ERROR_OUT_OF_MEMORY; } *_retval = nssCert; NS_ADDREF(*_retval); CERT_RemoveCertListNode(node); return NS_OK; }
/* * Find all user certificates that match the given criteria. * * "handle" - database to search * "usage" - certificate usage to match * "oneCertPerName" - if set then only return the "best" cert per * name * "validOnly" - only return certs that are curently valid * "proto_win" - window handle passed to pkcs11 */ CERTCertList * CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, SECCertUsage usage, PRBool oneCertPerName, PRBool validOnly, void *proto_win) { CERTCertNicknames *nicknames = NULL; char **nnptr; int nn; CERTCertificate *cert = NULL; CERTCertList *certList = NULL; SECStatus rv; int64 time; CERTCertListNode *node = NULL; CERTCertListNode *freenode = NULL; int n; time = PR_Now(); nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER, proto_win); if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) { goto loser; } nnptr = nicknames->nicknames; nn = nicknames->numnicknames; while ( nn > 0 ) { cert = NULL; /* use the pk11 call so that we pick up any certs on tokens, * which may require login */ if ( proto_win != NULL ) { cert = PK11_FindCertFromNickname(*nnptr,proto_win); } /* Sigh, It turns out if the cert is already in the temp db, because * it's in the perm db, then the nickname lookup doesn't work. * since we already have the cert here, though, than we can just call * CERT_CreateSubjectCertList directly. For those cases where we didn't * find the cert in pkcs #11 (because we didn't have a password arg, * or because the nickname is for a peer, server, or CA cert, then we * go look the cert up. */ if (cert == NULL) { cert = CERT_FindCertByNickname(handle,*nnptr); } if ( cert != NULL ) { /* 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); } nnptr++; nn--; } /* remove certs with incorrect usage */ rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } /* remove any extra certs for each name */ if ( oneCertPerName ) { PRBool *flags; nn = nicknames->numnicknames; nnptr = nicknames->nicknames; flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn); if ( flags == NULL ) { goto loser; } node = CERT_LIST_HEAD(certList); /* treverse all certs in the list */ while ( !CERT_LIST_END(node, certList) ) { /* find matching nickname index */ for ( n = 0; n < nn; n++ ) { if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) { /* We found a match. If this is the first one, then * set the flag and move on to the next cert. If this * is not the first one then delete it from the list. */ if ( flags[n] ) { /* We have already seen a cert with this nickname, * so delete this one. */ freenode = node; node = CERT_LIST_NEXT(node); CERT_RemoveCertListNode(freenode); } else { /* keep the first cert for each nickname, but set the * flag so we know to delete any others with the same * nickname. */ flags[n] = PR_TRUE; node = CERT_LIST_NEXT(node); } break; } } if ( n == nn ) { /* if we get here it means that we didn't find a matching * nickname, which should not happen. */ PORT_Assert(0); node = CERT_LIST_NEXT(node); } } PORT_Free(flags); } goto done; loser: if ( certList != NULL ) { CERT_DestroyCertList(certList); certList = NULL; } done: if ( nicknames != NULL ) { CERT_FreeNicknames(nicknames); } return(certList); }