summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2022-08-23 18:24:35 +0000
committerRob Crittenden <rcritten@redhat.com>2022-08-23 18:24:35 +0000
commit8c3a9f0bbc2a9c30abdf25aaf87d65f37284bda4 (patch)
tree5081ebffdbe553b2d98fb5a31e8907c47e8e9775
parent2386c64d2cf4194c8f63ae2e8d5b9e83544679eb (diff)
downloadnss-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.c67
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);