/************************************************************************** * * C h a n g e T r u s t A t t r i b u t e s */ static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts) { CERTCertTrust * trust; if (!db || !cert || !trusts) { PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n"); errorCount++; return SECFailure; } trust = (CERTCertTrust * ) PORT_ZAlloc(sizeof(CERTCertTrust)); if (!trust) { PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate " "CERTCertTrust\n"); errorCount++; return SECFailure; } if ( CERT_DecodeTrustString(trust, trusts) ) { return SECFailure; } if ( CERT_ChangeCertTrust(db, cert, trust) ) { PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n", cert->nickname ? cert->nickname : ""); errorCount++; return SECFailure; } return SECSuccess; }
/* Add the server's certificate to our database of trusted servers. */ static SECStatus trustNewServer (CERTCertificate *serverCert) { SECStatus secStatus; CERTCertTrust *trust = NULL; PK11SlotInfo *slot; /* Import the certificate. */ slot = PK11_GetInternalKeySlot();; secStatus = PK11_ImportCert(slot, serverCert, CK_INVALID_HANDLE, "stap-server", PR_FALSE); if (secStatus != SECSuccess) goto done; /* Make it a trusted peer. */ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); if (! trust) { secStatus = SECFailure; goto done; } secStatus = CERT_DecodeTrustString(trust, "P,P,P"); if (secStatus != SECSuccess) goto done; secStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), serverCert, trust); if (secStatus != SECSuccess) goto done; done: if (trust) PORT_Free(trust); return secStatus; }
/* * void deleteCertificate(in nsIX509Cert aCert); */ NS_IMETHODIMP nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert) { nsNSSShutDownPreventionLock locker; nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert); CERTCertificate *cert = nssCert->GetCert(); if (!cert) return NS_ERROR_FAILURE; CERTCertificateCleaner certCleaner(cert); SECStatus srv = SECSuccess; PRUint32 certType; nssCert->GetCertType(&certType); if (NS_FAILED(nssCert->MarkForPermDeletion())) { return NS_ERROR_FAILURE; } if (cert->slot && certType != nsIX509Cert::USER_CERT) { // To delete a cert of a slot (builtin, most likely), mark it as // completely untrusted. This way we keep a copy cached in the // local database, and next time we try to load it off of the // external token/slot, we'll know not to trust it. We don't // want to do that with user certs, because a user may re-store // the cert onto the card again at which point we *will* want to // trust that cert if it chains up properly. nsNSSCertTrust trust(0, 0, 0); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust()); } PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert deleted: %d", srv)); return (srv) ? NS_ERROR_FAILURE : NS_OK; }
/* * void setCertTrust(in nsIX509Cert cert, * in unsigned long type, * in unsigned long trust); */ NS_IMETHODIMP nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert, PRUint32 type, PRUint32 trusted) { nsNSSShutDownPreventionLock locker; SECStatus srv; nsNSSCertTrust trust; nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert); if (!pipCert) return NS_ERROR_FAILURE; CERTCertificate *nsscert = pipCert->GetCert(); CERTCertificateCleaner certCleaner(nsscert); if (type == nsIX509Cert::CA_CERT) { // always start with untrusted and move up trust.SetValidCA(); trust.AddCATrust(!!(trusted & nsIX509CertDB::TRUSTED_SSL), !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), !!(trusted & nsIX509CertDB::TRUSTED_OBJSIGN)); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, trust.GetTrust()); } else if (type == nsIX509Cert::SERVER_CERT) { // always start with untrusted and move up trust.SetValidPeer(); trust.AddPeerTrust(trusted & nsIX509CertDB::TRUSTED_SSL, 0, 0); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, trust.GetTrust()); } else if (type == nsIX509Cert::EMAIL_CERT) { // always start with untrusted and move up trust.SetValidPeer(); trust.AddPeerTrust(0, !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), 0); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, trust.GetTrust()); } else { // ignore user certs return NS_OK; } return (srv) ? NS_ERROR_FAILURE : NS_OK; }
int sxi_ssl_usertrusted(sxc_client_t *sx, curlev_t *ev, const struct curl_tlssessioninfo *info) { CERTCertificate *cert; int rc = cert_from_sessioninfo(sx, info, &cert); if (rc) return rc; /* workaround for NSS cache: * if we run with verify_peer on, it remember that certificate was * not trusted because it was self-signed. * Then even if we explicitly add it as trusted in curl, it still * considers it as untrusted. * So explicitly set trust settings here. If we reached this place * then NSS already validated the certificate and the user accepted the certificate. * */ CERTCertTrust none; CERT_DecodeTrustString(&none, "PT,PT,PT"); CERT_ChangeCertTrust(NULL, cert, &none); return 0; }
// Based on nsNSSCertificateDB::SetCertTrust. bool SetCertTrust(const net::X509Certificate* cert, net::CertType type, net::NSSCertDatabase::TrustBits trustBits) { const unsigned kSSLTrustBits = net::NSSCertDatabase::TRUSTED_SSL | net::NSSCertDatabase::DISTRUSTED_SSL; const unsigned kEmailTrustBits = net::NSSCertDatabase::TRUSTED_EMAIL | net::NSSCertDatabase::DISTRUSTED_EMAIL; const unsigned kObjSignTrustBits = net::NSSCertDatabase::TRUSTED_OBJ_SIGN | net::NSSCertDatabase::DISTRUSTED_OBJ_SIGN; if ((trustBits & kSSLTrustBits) == kSSLTrustBits || (trustBits & kEmailTrustBits) == kEmailTrustBits || (trustBits & kObjSignTrustBits) == kObjSignTrustBits) { LOG(ERROR) << "SetCertTrust called with conflicting trust bits " << trustBits; NOTREACHED(); return false; } SECStatus srv; CERTCertificate *nsscert = cert->os_cert_handle(); if (type == net::CA_CERT) { // Note that we start with CERTDB_VALID_CA for default trust and explicit // trust, but explicitly distrusted usages will be set to // CERTDB_TERMINAL_RECORD only. CERTCertTrust trust = {CERTDB_VALID_CA, CERTDB_VALID_CA, CERTDB_VALID_CA}; if (trustBits & net::NSSCertDatabase::DISTRUSTED_SSL) trust.sslFlags = CERTDB_TERMINAL_RECORD; else if (trustBits & net::NSSCertDatabase::TRUSTED_SSL) trust.sslFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; if (trustBits & net::NSSCertDatabase::DISTRUSTED_EMAIL) trust.emailFlags = CERTDB_TERMINAL_RECORD; else if (trustBits & net::NSSCertDatabase::TRUSTED_EMAIL) trust.emailFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; if (trustBits & net::NSSCertDatabase::DISTRUSTED_OBJ_SIGN) trust.objectSigningFlags = CERTDB_TERMINAL_RECORD; else if (trustBits & net::NSSCertDatabase::TRUSTED_OBJ_SIGN) trust.objectSigningFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust); } else if (type == net::SERVER_CERT) { CERTCertTrust trust = {0}; // We only modify the sslFlags, so copy the other flags. CERT_GetCertTrust(nsscert, &trust); trust.sslFlags = 0; if (trustBits & net::NSSCertDatabase::DISTRUSTED_SSL) trust.sslFlags |= CERTDB_TERMINAL_RECORD; else if (trustBits & net::NSSCertDatabase::TRUSTED_SSL) trust.sslFlags |= CERTDB_TRUSTED | CERTDB_TERMINAL_RECORD; srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust); } else { // ignore user and email/unknown certs return true; } if (srv != SECSuccess) LOG(ERROR) << "SetCertTrust failed with error " << PORT_GetError(); return srv == SECSuccess; }
NS_IMETHODIMP nsCertTree::DeleteEntryObject(PRUint32 index) { if (!mTreeArray) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIX509CertDB> certdb = do_GetService("@mozilla.org/security/x509certdb;1"); if (!certdb) { return NS_ERROR_FAILURE; } int i; PRUint32 idx = 0, cIndex = 0, nc; // Loop over the threads for (i=0; i<mNumOrgs; i++) { if (index == idx) return NS_OK; // index is for thread idx++; // get past the thread nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0; if (index < idx + nc) { // cert is within range of this thread PRInt32 certIndex = cIndex + index - idx; bool canRemoveEntry = false; nsRefPtr<nsCertTreeDispInfo> certdi = mDispInfo.SafeElementAt(certIndex, NULL); // We will remove the element from the visual tree. // Only if we have a certdi, then we can check for additional actions. nsCOMPtr<nsIX509Cert> cert = nsnull; if (certdi) { if (certdi->mAddonInfo) { cert = certdi->mAddonInfo->mCert; } nsCertAddonInfo *addonInfo = certdi->mAddonInfo ? certdi->mAddonInfo : nsnull; if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) { mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort); if (addonInfo) { addonInfo->mUsageCount--; if (addonInfo->mUsageCount == 0) { // The certificate stored in the database is no longer // referenced by any other object displayed. // That means we no longer need to keep it around // and really can remove it. canRemoveEntry = true; } } } else { if (addonInfo && addonInfo->mUsageCount > 1) { // user is trying to delete a perm trusted cert, // although there are still overrides stored, // so, we keep the cert, but remove the trust CERTCertificate *nsscert = nsnull; CERTCertificateCleaner nsscertCleaner(nsscert); nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(cert); if (cert2) { nsscert = cert2->GetCert(); } if (nsscert) { CERTCertTrust trust; memset((void*)&trust, 0, sizeof(trust)); SECStatus srv = CERT_DecodeTrustString(&trust, ""); // no override if (srv == SECSuccess) { CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust); } } } else { canRemoveEntry = true; } } } mDispInfo.RemoveElementAt(certIndex); if (canRemoveEntry) { RemoveCacheEntry(cert); certdb->DeleteCertificate(cert); } delete [] mTreeArray; mTreeArray = nsnull; return UpdateUIContents(); } if (mTreeArray[i].open) idx += mTreeArray[i].numChildren; cIndex += mTreeArray[i].numChildren; if (idx > index) break; } return NS_ERROR_FAILURE; }
NS_IMETHODIMP nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, nsIInterfaceRequestor *ctx) { nsNSSShutDownPreventionLock locker; SECStatus srv = SECFailure; nsresult nsrv = NS_OK; CERTCertificate * cert; SECItem **rawCerts = nsnull; int numcerts; int i; nsNSSCertTrust trust; char *serverNickname = nsnull; PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return NS_ERROR_OUT_OF_MEMORY; CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length); if (!certCollection) { PORT_FreeArena(arena, PR_FALSE); return NS_ERROR_FAILURE; } cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts, (char *)NULL, PR_FALSE, PR_TRUE); if (!cert) { nsrv = NS_ERROR_FAILURE; goto loser; } numcerts = certCollection->numcerts; rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts); if ( !rawCerts ) { nsrv = NS_ERROR_FAILURE; goto loser; } for ( i = 0; i < numcerts; i++ ) { rawCerts[i] = &certCollection->rawCerts[i]; } serverNickname = nsNSSCertificate::defaultServerNickname(cert); srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer, numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE, serverNickname); PR_FREEIF(serverNickname); if ( srv != SECSuccess ) { nsrv = NS_ERROR_FAILURE; goto loser; } trust.SetValidServerPeer(); srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust()); if ( srv != SECSuccess ) { nsrv = NS_ERROR_FAILURE; goto loser; } loser: PORT_Free(rawCerts); if (cert) CERT_DestroyCertificate(cert); if (arena) PORT_FreeArena(arena, PR_TRUE); return nsrv; }