Bug 1596401 - rework certificate deletion so it happens immediately r=rmf

Differential Revision: https://phabricator.services.mozilla.com/D86775
This commit is contained in:
Dana Keeler 2020-08-17 23:23:03 +00:00
parent f68ef97340
commit 67e203a187
4 changed files with 35 additions and 60 deletions

View file

@ -228,13 +228,6 @@ interface nsIX509Cert : nsISupports {
[notxpcom, noscript, must_use]
CERTCertificatePtr getCert();
/**
* Either delete the certificate from all cert databases,
* or mark it as untrusted.
*/
[must_use]
void markForPermDeletion();
[notxpcom, noscript]
void SerializeToIPC(in IpcMessagePtr aMsg);

View file

@ -107,7 +107,6 @@ bool nsNSSCertificate::InitFromDER(char* certDER, int derLen) {
nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
: mCert(nullptr),
mPermDelete(false),
mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
mSubjectAltNames() {
if (cert) {
@ -118,24 +117,9 @@ nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
nsNSSCertificate::nsNSSCertificate()
: mCert(nullptr),
mPermDelete(false),
mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
mSubjectAltNames() {}
nsNSSCertificate::~nsNSSCertificate() {
if (mPermDelete) {
if (mCertType == nsNSSCertificate::USER_CERT) {
nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
PK11_DeleteTokenCertAndKey(mCert.get(), cxt);
} else if (mCert->slot && !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.get());
}
}
}
static uint32_t getCertType(CERTCertificate* cert) {
nsNSSCertTrust trust(cert->trust);
if (cert->nickname && trust.HasAnyUser()) {
@ -187,21 +171,6 @@ nsNSSCertificate::GetIsBuiltInRoot(bool* aIsBuiltInRoot) {
return NS_OK;
}
nsresult nsNSSCertificate::MarkForPermDeletion() {
// make sure user is logged in to the token
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
if (mCert->slot && PK11_NeedLogin(mCert->slot) &&
!PK11_NeedUserInit(mCert->slot) && !PK11_IsInternal(mCert->slot)) {
if (SECSuccess != PK11_Authenticate(mCert->slot, true, ctx)) {
return NS_ERROR_FAILURE;
}
}
mPermDelete = true;
return NS_OK;
}
/**
* Appends a pipnss bundle string to the given string.
*

View file

@ -68,10 +68,9 @@ class nsNSSCertificate final : public nsIX509Cert,
/* out */ nsCOMPtr<nsIX509Cert>& aRoot);
private:
virtual ~nsNSSCertificate();
virtual ~nsNSSCertificate() = default;
mozilla::UniqueCERTCertificate mCert;
bool mPermDelete;
uint32_t mCertType;
std::vector<nsString> mSubjectAltNames;
nsresult GetSortableDate(PRTime aTime, nsAString& _aSortableDate);

View file

@ -620,27 +620,41 @@ nsNSSCertificateDB::DeleteCertificate(nsIX509Cert* aCert) {
if (!cert) {
return NS_ERROR_FAILURE;
}
SECStatus srv = SECSuccess;
// Temporary certificates aren't on a slot and will go away when the
// nsIX509Cert is destructed.
if (cert->slot) {
uint32_t certType;
aCert->GetCertType(&certType);
if (NS_FAILED(aCert->MarkForPermDeletion())) {
nsresult rv = aCert->GetCertType(&certType);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (certType == nsIX509Cert::USER_CERT) {
SECStatus srv = PK11_Authenticate(cert->slot, true, nullptr);
if (srv != SECSuccess) {
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);
srv = ChangeCertTrustWithPossibleAuthentication(cert, trust.GetTrust(),
nullptr);
srv = PK11_DeleteTokenCertAndKey(cert.get(), nullptr);
if (srv != SECSuccess) {
return NS_ERROR_FAILURE;
}
} else {
// For certificates that can't be deleted (e.g. built-in roots), un-set
// all trust bits.
nsNSSCertTrust trust(0, 0);
SECStatus srv = ChangeCertTrustWithPossibleAuthentication(
cert, trust.GetTrust(), nullptr);
if (srv != SECSuccess) {
return NS_ERROR_FAILURE;
}
if (!PK11_IsReadOnly(cert->slot)) {
srv = SEC_DeletePermCertificate(cert.get());
if (srv != SECSuccess) {
return NS_ERROR_FAILURE;
}
}
}
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("cert deleted: %d", srv));
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
@ -649,7 +663,7 @@ nsNSSCertificateDB::DeleteCertificate(nsIX509Cert* aCert) {
nullptr);
}
return (srv) ? NS_ERROR_FAILURE : NS_OK;
return NS_OK;
}
NS_IMETHODIMP