diff options
author | Rob Crittenden <rcritten@redhat.com> | 2022-08-23 18:24:35 +0000 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2022-08-23 18:24:35 +0000 |
commit | 8c3a9f0bbc2a9c30abdf25aaf87d65f37284bda4 (patch) | |
tree | 5081ebffdbe553b2d98fb5a31e8907c47e8e9775 | |
parent | 2386c64d2cf4194c8f63ae2e8d5b9e83544679eb (diff) | |
download | nss-hg-8c3a9f0bbc2a9c30abdf25aaf87d65f37284bda4.tar.gz |
Bug 1782980, Fall back to the softokn when writing certificate trust r=rrelyea@redhat.com
Trust is stored in the softokn. When adding a certificate
or modifying the trust of a certificate in an external
token the operation may fail because the internal token
is not authenticated. Instead the provided token name
is authenticated multiple times (particularly in the case of
AddCert).
Catch a failed authentication to the provided token name
where the error is SEC_ERROR_TOKEN_NOT_LOGGED_IN and
attempt to authenticate to the softokn before calling
CERT_ChangeCertTrust.
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
-rw-r--r-- | cmd/certutil/certutil.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/cmd/certutil/certutil.c b/cmd/certutil/certutil.c index af72910f3..07b1ea51b 100644 --- a/cmd/certutil/certutil.c +++ b/cmd/certutil/certutil.c @@ -50,6 +50,35 @@ char *progName; +static SECStatus +ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, + CERTCertTrust *trust, PK11SlotInfo *slot, void *pwdata) +{ + SECStatus rv; + + rv = CERT_ChangeCertTrust(handle, cert, trust); + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); + if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { + PK11SlotInfo *internalslot; + internalslot = PK11_GetInternalKeySlot(); + rv = PK11_Authenticate(internalslot, PR_TRUE, pwdata); + if (rv != SECSuccess) { + SECU_PrintError(progName, + "could not authenticate to token %s.", + PK11_GetTokenName(internalslot)); + PK11_FreeSlot(internalslot); + return SECFailure; + } + PK11_FreeSlot(internalslot); + } + rv = CERT_ChangeCertTrust(handle, cert, trust); + } + } + return rv; +} + static CERTCertificateRequest * GetCertRequest(const SECItem *reqDER, void *pwarg) { @@ -149,24 +178,11 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, GEN_BREAK(SECFailure); } } - - rv = CERT_ChangeCertTrust(handle, cert, trust); + rv = ChangeCertTrust(handle, cert, trust, slot, pwdata); if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { - rv = PK11_Authenticate(slot, PR_TRUE, pwdata); - if (rv != SECSuccess) { - SECU_PrintError(progName, - "could not authenticate to token %s.", - PK11_GetTokenName(slot)); - GEN_BREAK(SECFailure); - } - rv = CERT_ChangeCertTrust(handle, cert, trust); - } - if (rv != SECSuccess) { - SECU_PrintError(progName, - "could not change trust on certificate"); - GEN_BREAK(SECFailure); - } + SECU_PrintError(progName, + "could not change trust on certificate"); + GEN_BREAK(SECFailure); } if (emailcert) { @@ -426,21 +442,10 @@ ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot, * a context, so NSS can't prompt for the password if it needs to. * check to see if the failure was token not logged in and * log in if need be. */ - rv = CERT_ChangeCertTrust(handle, cert, trust); + rv = ChangeCertTrust(handle, cert, trust, slot, pwdata); if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { - rv = PK11_Authenticate(slot, PR_TRUE, pwdata); - if (rv != SECSuccess) { - SECU_PrintError(progName, "could not authenticate to token %s.", - PK11_GetTokenName(slot)); - return SECFailure; - } - rv = CERT_ChangeCertTrust(handle, cert, trust); - } - if (rv != SECSuccess) { - SECU_PrintError(progName, "unable to modify trust attributes"); - return SECFailure; - } + SECU_PrintError(progName, "unable to modify trust attributes"); + return SECFailure; } CERT_DestroyCertificate(cert); PORT_Free(trust); |