certmonger/SOURCES/0003-Use-the-correct-slot-when-saving-certificates-in-NSS.patch

1017 lines
34 KiB
Diff
Raw Normal View History

2019-05-07 13:10:24 +00:00
From 3da0e186904ad81dd87cf74bfae88270f14bb770 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Tue, 21 Aug 2018 17:25:21 -0400
Subject: [PATCH 1/7] Use the correct slot when saving certificates in NSS
Certificates were always stored in the NSS certdb.
---
src/certsave-n.c | 915 ++++++++++++++++++++++++++++---------------------------
1 file changed, 474 insertions(+), 441 deletions(-)
diff --git a/src/certsave-n.c b/src/certsave-n.c
index 8e15a18a..af176ce5 100644
--- a/src/certsave-n.c
+++ b/src/certsave-n.c
@@ -92,7 +92,11 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry,
SECStatus error;
SECItem *item, subject;
char *p, *q, *pin;
+ const char *token;
const char *es;
+ PK11SlotList *slotlist;
+ PK11SlotListElement *sle;
+ CK_MECHANISM_TYPE mech;
NSSInitContext *ctx;
CERTCertDBHandle *certdb;
CERTCertList *certlist;
@@ -192,231 +196,253 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry,
}
_exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
}
- /* Be ready to count our uses of a PIN. */
- memset(&cb_data, 0, sizeof(cb_data));
- cb_data.entry = entry;
- cb_data.n_attempts = 0;
- pin = NULL;
- if (cm_pin_read_for_key(entry, &pin) != 0) {
- cm_log(1, "Error reading PIN for key store, "
- "failing to save certificate.\n");
+ /* Find the tokens that we might use for cert storage. */
+ mech = CKM_RSA_X_509;
+ slotlist = PK11_GetAllTokens(mech, PR_FALSE, PR_FALSE, NULL);
+ if (slotlist == NULL) {
+ cm_log(1, "Error getting list of tokens.\n");
PORT_FreeArena(arena, PR_TRUE);
- error = NSS_ShutdownContext(ctx);
- if (error != SECSuccess) {
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
cm_log(1, "Error shutting down NSS.\n");
}
- _exit(CM_CERTSAVE_STATUS_AUTH);
+ _exit(2);
}
- /* Set a PIN if we're supposed to be using one and aren't using
- * one yet in this database. */
- if (PK11_NeedUserInit(PK11_GetInternalKeySlot())) {
- PK11_InitPin(PK11_GetInternalKeySlot(), NULL,
- pin ? pin : "");
- ec = PORT_GetError();
- if (ec != 0) {
- es = PR_ErrorToName(ec);
+ /* Walk the list looking for the requested slot, or the first one if
+ * none was requested. */
+ if (cm_pin_read_for_cert(entry, &pin) != 0) {
+ cm_log(1, "Error reading PIN for cert db.\n");
+ _exit(CM_SUB_STATUS_ERROR_AUTH);
+ }
+ PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb);
+ for (sle = slotlist->head;
+ ((sle != NULL) && (sle->slot != NULL));
+ sle = sle->next)
+ {
+ /* Log the slot's name. */
+ token = PK11_GetTokenName(sle->slot);
+ if (token != NULL) {
+ cm_log(3, "Found token '%s'.\n", token);
} else {
- es = NULL;
+ cm_log(3, "Found unnamed token.\n");
}
- if (PK11_NeedUserInit(PK11_GetInternalKeySlot())) {
- if (es != NULL) {
- cm_log(1, "Key storage slot still "
- "needs user PIN to be set: "
- "%s.\n", es);
- } else {
- cm_log(1, "Key storage slot still "
- "needs user PIN to be set.\n");
- }
+ /* If we're looking for a specific slot, and this isn't it,
+ * keep going. */
+ if ((entry->cm_cert_token != NULL) &&
+ ((token == NULL) ||
+ (strcmp(entry->cm_cert_token, token) != 0))) {
+ if (token != NULL) {
+ cm_log(1,
+ "Token is named \"%s\", not \"%s\", "
+ "skipping.\n",
+ token, entry->cm_cert_token);
+ } else {
+ cm_log(1,
+ "Token is unnamed, not \"%s\", "
+ "skipping.\n",
+ entry->cm_cert_token);
+ }
+ goto next_slot;
+ }
+ /* Be ready to count our uses of a PIN. */
+ memset(&cb_data, 0, sizeof(cb_data));
+ cb_data.entry = entry;
+ cb_data.n_attempts = 0;
+ pin = NULL;
+ if (cm_pin_read_for_key(entry, &pin) != 0) {
+ cm_log(1, "Error reading PIN for key store, "
+ "failing to save certificate.\n");
PORT_FreeArena(arena, PR_TRUE);
error = NSS_ShutdownContext(ctx);
if (error != SECSuccess) {
cm_log(1, "Error shutting down NSS.\n");
}
- switch (ec) {
- case PR_NO_ACCESS_RIGHTS_ERROR: /* EACCES or EPERM */
- _exit(CM_CERTSAVE_STATUS_PERMS);
- break;
- default:
- _exit(CM_CERTSAVE_STATUS_AUTH);
- break;
- }
+ _exit(CM_CERTSAVE_STATUS_AUTH);
}
- /* We're authenticated now, so count this as a use of
- * the PIN. */
- if ((pin != NULL) && (strlen(pin) > 0)) {
- cb_data.n_attempts++;
- }
- }
- /* Log in, if case we need to muck around with the key
- * database. */
- PK11_SetPasswordFunc(&cm_pin_read_for_key_nss_cb);
- error = PK11_Authenticate(PK11_GetInternalKeySlot(), PR_TRUE,
- &cb_data);
- ec = PORT_GetError();
- if (error != SECSuccess) {
- if (ec != 0) {
+ if (PK11_NeedUserInit(sle->slot)) {
+ PK11_InitPin(sle->slot, NULL, pin ? pin : "");
+ ec = PORT_GetError();
es = PR_ErrorToName(ec);
- } else {
- es = NULL;
- }
- if (es != NULL) {
- cm_log(1, "Error authenticating to key store: %s.\n",
- es);
- } else {
- cm_log(1, "Error authenticating to key store.\n");
- }
- PORT_FreeArena(arena, PR_TRUE);
- error = NSS_ShutdownContext(ctx);
- if (error != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
- }
- _exit(CM_CERTSAVE_STATUS_AUTH);
- }
- if ((pin != NULL) &&
- (strlen(pin) > 0) &&
- (cb_data.n_attempts == 0)) {
- cm_log(1, "PIN was not needed to auth to key "
- "store, though one was provided. "
- "Treating this as an error.\n");
- PORT_FreeArena(arena, PR_TRUE);
- error = NSS_ShutdownContext(ctx);
- if (error != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
- }
- _exit(CM_CERTSAVE_STATUS_AUTH);
- }
- certdb = CERT_GetDefaultCertDB();
- if (certdb != NULL) {
- /* Strip the header and footer. */
- p = entry->cm_cert;
- q = NULL;
- if (p != NULL) {
- while (strncmp(p, "-----BEGIN ", 11) == 0) {
- p += strcspn(p, "\r\n");
- p += strspn(p, "\r\n");
+ if (PK11_NeedUserInit(sle->slot)) {
+ if (es != NULL) {
+ cm_log(1, "Key storage slot still "
+ "needs user PIN to be set: "
+ "%s.\n", es);
+ } else {
+ cm_log(1, "Key storage slot still "
+ "needs user PIN to be set.\n");
+ }
+ PORT_FreeArena(arena, PR_TRUE);
+ error = NSS_ShutdownContext(ctx);
+ if (error != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ switch (ec) {
+ case PR_NO_ACCESS_RIGHTS_ERROR: /* EACCES or EPERM */
+ _exit(CM_CERTSAVE_STATUS_PERMS);
+ break;
+ default:
+ _exit(CM_CERTSAVE_STATUS_AUTH);
+ break;
+ }
}
- q = strstr(p, "-----END");
+ /* count this as use of the PIN */
+ cb_data.n_attempts++;
}
- if ((q == NULL) || (*p == '\0')) {
- cm_log(1, "Unable to parse certificate.\n");
- PORT_FreeArena(arena, PR_TRUE);
- if (NSS_ShutdownContext(ctx) != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
+ if (PK11_NeedLogin(sle->slot)) {
+ error = PK11_Authenticate(sle->slot, PR_TRUE, &cb_data);
+ if (error != SECSuccess) {
+ cm_log(1, "Error authenticating to cert db for token "
+ "%s.\n", token);
+ goto next_slot;
}
- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
+ cb_data.n_attempts++;
}
- /* Handle the base64 decode. */
- item = NSSBase64_DecodeBuffer(arena, NULL, p, q - p);
- if (item == NULL) {
- cm_log(1, "Unable to decode certificate "
- "into buffer.\n");
+ if ((pin != NULL) &&
+ (strlen(pin) > 0) &&
+ (cb_data.n_attempts == 0)) {
+ cm_log(1, "PIN was not needed to auth to key "
+ "store, though one was provided. "
+ "Treating this as an error.\n");
PORT_FreeArena(arena, PR_TRUE);
- if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ error = NSS_ShutdownContext(ctx);
+ if (error != SECSuccess) {
cm_log(1, "Error shutting down NSS.\n");
}
- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
+ _exit(CM_CERTSAVE_STATUS_AUTH);
}
- /* Do a "shallow" decode to pull out the subject name
- * so that we can check for a conflict. */
- memset(&csdata, 0, sizeof(csdata));
- if (SEC_ASN1DecodeItem(arena, &csdata,
- CERT_SignedDataTemplate,
- item) != SECSuccess) {
- cm_log(1, "Unable to decode certificate "
- "signed data into buffer.\n");
- PORT_FreeArena(arena, PR_TRUE);
- if (NSS_ShutdownContext(ctx) != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
+ certdb = CERT_GetDefaultCertDB();
+ if (certdb != NULL) {
+ /* Strip the header and footer. */
+ p = entry->cm_cert;
+ q = NULL;
+ if (p != NULL) {
+ while (strncmp(p, "-----BEGIN ", 11) == 0) {
+ p += strcspn(p, "\r\n");
+ p += strspn(p, "\r\n");
+ }
+ q = strstr(p, "-----END");
}
- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
- }
- memset(&cert, 0, sizeof(cert));
- if (SEC_ASN1DecodeItem(arena, &cert,
- CERT_CertificateTemplate,
- &csdata.data) != SECSuccess) {
- cm_log(1, "Unable to decode certificate "
- "data into buffer.\n");
- PORT_FreeArena(arena, PR_TRUE);
- if (NSS_ShutdownContext(ctx) != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
+ if ((q == NULL) || (*p == '\0')) {
+ cm_log(1, "Unable to parse certificate.\n");
+ PORT_FreeArena(arena, PR_TRUE);
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
}
- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
- }
- subject = cert.derSubject;
- /* Ask NSS if there would be a conflict. */
- have_trust = PR_FALSE;
- if (SEC_CertNicknameConflict(entry->cm_cert_nickname,
- &subject,
- certdb)) {
- /* Delete the certificate that's already there
- * with the nickname we want, otherwise our
- * cert with a different subject name will be
- * discarded. */
- certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname,
- NULL);
+ /* Handle the base64 decode. */
+ item = NSSBase64_DecodeBuffer(arena, NULL, p, q - p);
+ if (item == NULL) {
+ cm_log(1, "Unable to decode certificate "
+ "into buffer.\n");
+ PORT_FreeArena(arena, PR_TRUE);
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
+ }
+ /* Do a "shallow" decode to pull out the subject name
+ * so that we can check for a conflict. */
+ memset(&csdata, 0, sizeof(csdata));
+ if (SEC_ASN1DecodeItem(arena, &csdata,
+ CERT_SignedDataTemplate,
+ item) != SECSuccess) {
+ cm_log(1, "Unable to decode certificate "
+ "signed data into buffer.\n");
+ PORT_FreeArena(arena, PR_TRUE);
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
+ }
+ memset(&cert, 0, sizeof(cert));
+ if (SEC_ASN1DecodeItem(arena, &cert,
+ CERT_CertificateTemplate,
+ &csdata.data) != SECSuccess) {
+ cm_log(1, "Unable to decode certificate "
+ "data into buffer.\n");
+ PORT_FreeArena(arena, PR_TRUE);
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR);
+ }
+ subject = cert.derSubject;
+ /* Ask NSS if there would be a conflict. */
+ have_trust = PR_FALSE;
+ if (SEC_CertNicknameConflict(entry->cm_cert_nickname,
+ &subject,
+ certdb)) {
+ /* Delete the certificate that's already there
+ * with the nickname we want, otherwise our
+ * cert with a different subject name will be
+ * discarded. */
+ certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname,
+ NULL);
+ if (certlist != NULL) {
+ /* Look for certs with different
+ * subject names but the same nickname,
+ * because they've got to go. */
+ for (node = CERT_LIST_HEAD(certlist);
+ (node != NULL) &&
+ !CERT_LIST_EMPTY(certlist) &&
+ !CERT_LIST_END(node, certlist);
+ node = CERT_LIST_NEXT(node)) {
+ if (!SECITEM_ItemsAreEqual(&subject,
+ &node->cert->derSubject)) {
+ cm_log(3, "Found a "
+ "certificate "
+ "with the same "
+ "nickname but "
+ "different "
+ "subject, "
+ "removing "
+ "certificate "
+ "\"%s\" with "
+ "subject "
+ "\"%s\".\n",
+ node->cert->nickname,
+ node->cert->subjectName ?
+ node->cert->subjectName :
+ "");
+ /* Get a handle for
+ * this certificate's
+ * private key, in case
+ * we need to remove
+ * it. */
+ privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
+ privkeys = add_privkey_to_list(privkeys, privkey);
+ SEC_DeletePermCertificate(node->cert);
+ }
+ }
+ CERT_DestroyCertList(certlist);
+ }
+ } else {
+ cm_log(3, "No duplicate nickname entries.\n");
+ }
+ /* This certificate's subject may already be present
+ * with a different nickname. Delete those, too. */
+ certlist = CERT_CreateSubjectCertList(NULL, certdb,
+ &subject,
+ PR_FALSE,
+ PR_FALSE);
if (certlist != NULL) {
- /* Look for certs with different
- * subject names but the same nickname,
- * because they've got to go. */
+ /* Look for certs with different nicknames but
+ * the same subject name, because those have
+ * got to go. */
+ i = 0;
for (node = CERT_LIST_HEAD(certlist);
(node != NULL) &&
!CERT_LIST_EMPTY(certlist) &&
!CERT_LIST_END(node, certlist);
node = CERT_LIST_NEXT(node)) {
- if (!SECITEM_ItemsAreEqual(&subject,
- &node->cert->derSubject)) {
+ if ((node->cert->nickname != NULL) &&
+ (strcmp(entry->cm_cert_nickname,
+ node->cert->nickname) != 0))
+ {
+ i++;
cm_log(3, "Found a "
- "certificate "
- "with the same "
- "nickname but "
- "different "
- "subject, "
- "removing "
- "certificate "
- "\"%s\" with "
- "subject "
- "\"%s\".\n",
- node->cert->nickname,
- node->cert->subjectName ?
- node->cert->subjectName :
- "");
- /* Get a handle for
- * this certificate's
- * private key, in case
- * we need to remove
- * it. */
- privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
- privkeys = add_privkey_to_list(privkeys, privkey);
- SEC_DeletePermCertificate(node->cert);
- }
- }
- CERT_DestroyCertList(certlist);
- }
- } else {
- cm_log(3, "No duplicate nickname entries.\n");
- }
- /* This certificate's subject may already be present
- * with a different nickname. Delete those, too. */
- certlist = CERT_CreateSubjectCertList(NULL, certdb,
- &subject,
- PR_FALSE,
- PR_FALSE);
- if (certlist != NULL) {
- /* Look for certs with different nicknames but
- * the same subject name, because those have
- * got to go. */
- i = 0;
- for (node = CERT_LIST_HEAD(certlist);
- (node != NULL) &&
- !CERT_LIST_EMPTY(certlist) &&
- !CERT_LIST_END(node, certlist);
- node = CERT_LIST_NEXT(node)) {
- if ((node->cert->nickname != NULL) &&
- (strcmp(entry->cm_cert_nickname,
- node->cert->nickname) != 0)) {
- i++;
- cm_log(3, "Found a "
- "certificate with a "
+ "certificate with a "
"different nickname but "
"the same subject, "
"removing certificate "
@@ -426,284 +452,291 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry,
node->cert->subjectName ?
node->cert->subjectName :
"");
- /* Get a handle for this
- * certificate's private key,
- * in case we need to remove
- * it. */
- privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
- privkeys = add_privkey_to_list(privkeys, privkey);
- SEC_DeletePermCertificate(node->cert);
- } else {
- /* Same nickname, and we
- * already know it has the same
- * subject name. Save its
- * trust. */
- if (!have_trust) {
- if (CERT_GetCertTrust(node->cert,
+ /* Get a handle for this
+ * certificate's private key,
+ * in case we need to remove
+ * it. */
+ privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
+ privkeys = add_privkey_to_list(privkeys, privkey);
+ SEC_DeletePermCertificate(node->cert);
+ } else {
+ /* Same nickname, and we
+ * already know it has the same
+ * subject name. Save its
+ * trust. */
+ if (!have_trust) {
+ if (CERT_GetCertTrust(node->cert,
&trust) == SECSuccess) {
- have_trust = PR_TRUE;
+ have_trust = PR_TRUE;
+ }
}
}
}
- }
- if (i == 0) {
- cm_log(3, "No duplicate subject name entries.\n");
- }
- CERT_DestroyCertList(certlist);
- } else {
- cm_log(3, "No duplicate subject name entries.\n");
- }
- /* Make one more attempt at finding an existing trust
- * value. */
- if (!have_trust) {
- oldcert = PK11_FindCertFromNickname(entry->cm_cert_nickname, NULL);
- if (oldcert != NULL) {
- if (CERT_GetCertTrust(oldcert,
- &trust) == SECSuccess) {
- have_trust = PR_TRUE;
+ if (i == 0) {
+ cm_log(3, "No duplicate subject name entries.\n");
}
- CERT_DestroyCertificate(oldcert);
+ CERT_DestroyCertList(certlist);
+ } else {
+ cm_log(3, "No duplicate subject name entries.\n");
}
- }
- /* Import the certificate. */
- returned = NULL;
- error = CERT_ImportCerts(certdb,
- certUsageUserCertImport,
- 1, &item, &returned,
- PR_TRUE,
- PR_FALSE,
- entry->cm_cert_nickname);
- ec = PORT_GetError();
- if (error == SECSuccess) {
- /* If NSS uses SQL DB storage, CERT_ImportCerts creates
- * an incomplete internal state (the cert isn't
- * associated with the private key, and calling
- * PK11_FindKeyByAnyCert returns no result).
- * As a workaround, we import the cert again using
- * PK11_ImportCert, which magically fixes the issue.
- * See rhbz#1532188 */
- error = PK11_ImportCert(PK11_GetInternalKeySlot(),
- returned[0],
- CK_INVALID_HANDLE,
- returned[0]->nickname,
- PR_FALSE);
- }
- if (error == SECSuccess) {
- cm_log(1, "Imported certificate \"%s\", got "
- "nickname \"%s\".\n",
- entry->cm_cert_nickname,
- returned[0]->nickname);
- status = 0;
- /* Set the trust on the new certificate,
- * perhaps matching the trust on an
- * already-present certificate with the same
- * nickname. */
+ /* Make one more attempt at finding an existing trust
+ * value. */
if (!have_trust) {
- memset(&trust, 0, sizeof(trust));
- trust.sslFlags = CERTDB_USER;
- trust.emailFlags = CERTDB_USER;
- trust.objectSigningFlags = CERTDB_USER;
+ oldcert = PK11_FindCertFromNickname(entry->cm_cert_nickname, NULL);
+ if (oldcert != NULL) {
+ if (CERT_GetCertTrust(oldcert,
+ &trust) == SECSuccess) {
+ have_trust = PR_TRUE;
+ }
+ CERT_DestroyCertificate(oldcert);
+ }
}
- error = CERT_ChangeCertTrust(certdb,
- returned[0],
- &trust);
+ /* Import the certificate. */
+ returned = NULL;
+ error = CERT_ImportCerts(certdb,
+ certUsageUserCertImport,
+ 1, &item, &returned,
+ PR_TRUE,
+ PR_FALSE,
+ entry->cm_cert_nickname);
ec = PORT_GetError();
- if (error != SECSuccess) {
+ if (error == SECSuccess) {
+ /* If NSS uses SQL DB storage, CERT_ImportCerts creates
+ * an incomplete internal state (the cert isn't
+ * associated with the private key, and calling
+ * PK11_FindKeyByAnyCert returns no result).
+ * As a workaround, we import the cert again using
+ * PK11_ImportCert, which magically fixes the issue.
+ * See rhbz#1532188 */
+ error = PK11_ImportCert(sle->slot,
+ returned[0],
+ CK_INVALID_HANDLE,
+ returned[0]->nickname,
+ PR_FALSE);
+ }
+ if (error == SECSuccess) {
+ cm_log(1, "Imported certificate \"%s\", got "
+ "nickname \"%s\".\n",
+ entry->cm_cert_nickname,
+ returned[0]->nickname);
+ status = 0;
+ /* Set the trust on the new certificate,
+ * perhaps matching the trust on an
+ * already-present certificate with the same
+ * nickname. */
+ if (!have_trust) {
+ memset(&trust, 0, sizeof(trust));
+ trust.sslFlags = CERTDB_USER;
+ trust.emailFlags = CERTDB_USER;
+ trust.objectSigningFlags = CERTDB_USER;
+ }
+ error = CERT_ChangeCertTrust(certdb,
+ returned[0],
+ &trust);
+ ec = PORT_GetError();
+ if (error != SECSuccess) {
+ if (ec != 0) {
+ es = PR_ErrorToName(ec);
+ } else {
+ es = NULL;
+ }
+ if (es != NULL) {
+ cm_log(0, "Error setting trust "
+ "on certificate \"%s\": "
+ "%s.\n",
+ entry->cm_cert_nickname, es);
+ } else {
+ cm_log(0, "Error setting trust "
+ "on certificate \"%s\".\n",
+ entry->cm_cert_nickname);
+ }
+ }
+ /* Delete any other certificates that are there
+ * with the same nickname. While NSS's
+ * database allows duplicates so long as they
+ * have the same subject name and nickname,
+ * several APIs and many applications can't
+ * dependably find the right one among more
+ * than one. So bye-bye, old certificates. */
+ certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname,
+ NULL);
+ if (certlist != NULL) {
+ /* Look for certs with contents. */
+ for (node = CERT_LIST_HEAD(certlist);
+ (node != NULL) &&
+ !CERT_LIST_EMPTY(certlist) &&
+ !CERT_LIST_END(node, certlist);
+ node = CERT_LIST_NEXT(node)) {
+ if (!SECITEM_ItemsAreEqual(item,
+ &node->cert->derCert)) {
+ cm_log(3, "Found a "
+ "certificate "
+ "with the same "
+ "nickname and "
+ "subject, but "
+ "different "
+ "contents, "
+ "removing it.\n");
+ /* Get a handle for
+ * this certificate's
+ * private key, in case
+ * we need to remove
+ * it. */
+ privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
+ privkeys = add_privkey_to_list(privkeys, privkey);
+ SEC_DeletePermCertificate(node->cert);
+ }
+ }
+ CERT_DestroyCertList(certlist);
+ }
+ } else {
if (ec != 0) {
es = PR_ErrorToName(ec);
} else {
es = NULL;
}
if (es != NULL) {
- cm_log(0, "Error setting trust "
- "on certificate \"%s\": "
- "%s.\n",
- entry->cm_cert_nickname, es);
+ cm_log(0, "Error importing certificate "
+ "into NSSDB \"%s\": %s.\n",
+ entry->cm_cert_storage_location,
+ es);
} else {
- cm_log(0, "Error setting trust "
- "on certificate \"%s\".\n",
- entry->cm_cert_nickname);
+ cm_log(0, "Error importing certificate "
+ "into NSSDB \"%s\".\n",
+ entry->cm_cert_storage_location);
}
- }
- /* Delete any other certificates that are there
- * with the same nickname. While NSS's
- * database allows duplicates so long as they
- * have the same subject name and nickname,
- * several APIs and many applications can't
- * dependably find the right one among more
- * than one. So bye-bye, old certificates. */
- certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname,
- NULL);
- if (certlist != NULL) {
- /* Look for certs with contents. */
- for (node = CERT_LIST_HEAD(certlist);
- (node != NULL) &&
- !CERT_LIST_EMPTY(certlist) &&
- !CERT_LIST_END(node, certlist);
- node = CERT_LIST_NEXT(node)) {
- if (!SECITEM_ItemsAreEqual(item,
- &node->cert->derCert)) {
- cm_log(3, "Found a "
- "certificate "
- "with the same "
- "nickname and "
- "subject, but "
- "different "
- "contents, "
- "removing it.\n");
- /* Get a handle for
- * this certificate's
- * private key, in case
- * we need to remove
- * it. */
- privkey = PK11_FindKeyByAnyCert(node->cert, NULL);
- privkeys = add_privkey_to_list(privkeys, privkey);
- SEC_DeletePermCertificate(node->cert);
- }
+ switch (ec) {
+ case PR_NO_ACCESS_RIGHTS_ERROR: /* ACCES/PERM */
+ status = CM_CERTSAVE_STATUS_PERMS;
+ break;
+ default:
+ status = CM_CERTSAVE_STATUS_INTERNAL_ERROR;
+ break;
}
- CERT_DestroyCertList(certlist);
- }
- } else {
- if (ec != 0) {
- es = PR_ErrorToName(ec);
- } else {
- es = NULL;
}
- if (es != NULL) {
- cm_log(0, "Error importing certificate "
- "into NSSDB \"%s\": %s.\n",
- entry->cm_cert_storage_location,
- es);
- } else {
- cm_log(0, "Error importing certificate "
- "into NSSDB \"%s\".\n",
- entry->cm_cert_storage_location);
- }
- switch (ec) {
- case PR_NO_ACCESS_RIGHTS_ERROR: /* ACCES/PERM */
- status = CM_CERTSAVE_STATUS_PERMS;
- break;
- default:
- status = CM_CERTSAVE_STATUS_INTERNAL_ERROR;
- break;
+ /* If we managed to import the certificate, mark its
+ * key for having its nickname removed. */
+ if ((returned != NULL) && (returned[0] != NULL)) {
+ privkey = PK11_FindKeyByAnyCert(returned[0], NULL);
+ privkeys = add_privkey_to_list(privkeys, privkey);
+ CERT_DestroyCertArray(returned, 1);
}
- }
- /* If we managed to import the certificate, mark its
- * key for having its nickname removed. */
- if ((returned != NULL) && (returned[0] != NULL)) {
- privkey = PK11_FindKeyByAnyCert(returned[0], NULL);
- privkeys = add_privkey_to_list(privkeys, privkey);
- CERT_DestroyCertArray(returned, 1);
- }
- /* In case we're rekeying, but failed, mark the
- * candidate key for name-clearing or removal, too. */
- if ((entry->cm_key_next_marker != NULL) &&
- (strlen(entry->cm_key_next_marker) > 0)) {
- p = util_build_next_nickname(entry->cm_key_nickname,
- entry->cm_key_next_marker);
- privkeylist = PK11_ListPrivKeysInSlot(PK11_GetInternalKeySlot(), p, NULL);
- if (privkeylist != NULL) {
- for (knode = PRIVKEY_LIST_HEAD(privkeylist);
- !PRIVKEY_LIST_EMPTY(privkeylist) &&
- !PRIVKEY_LIST_END(knode, privkeylist);
- knode = PRIVKEY_LIST_NEXT(knode)) {
- q = PK11_GetPrivateKeyNickname(knode->key);
- if ((q != NULL) &&
- (strcmp(p, q) == 0)) {
- privkey = SECKEY_CopyPrivateKey(knode->key);
- privkeys = add_privkey_to_list(privkeys, privkey);
- break;
+ /* In case we're rekeying, but failed, mark the
+ * candidate key for name-clearing or removal, too. */
+ if ((entry->cm_key_next_marker != NULL) &&
+ (strlen(entry->cm_key_next_marker) > 0)) {
+ p = util_build_next_nickname(entry->cm_key_nickname,
+ entry->cm_key_next_marker);
+ privkeylist = PK11_ListPrivKeysInSlot(sle->slot, p, NULL);
+ if (privkeylist != NULL) {
+ for (knode = PRIVKEY_LIST_HEAD(privkeylist);
+ !PRIVKEY_LIST_EMPTY(privkeylist) &&
+ !PRIVKEY_LIST_END(knode, privkeylist);
+ knode = PRIVKEY_LIST_NEXT(knode)) {
+ q = PK11_GetPrivateKeyNickname(knode->key);
+ if ((q != NULL) &&
+ (strcmp(p, q) == 0)) {
+ privkey = SECKEY_CopyPrivateKey(knode->key);
+ privkeys = add_privkey_to_list(privkeys, privkey);
+ break;
+ }
}
+ SECKEY_DestroyPrivateKeyList(privkeylist);
}
- SECKEY_DestroyPrivateKeyList(privkeylist);
}
- }
- if (privkeys != NULL) {
- /* Check if any certificates are still using
- * the keys that correspond to certificates
- * that we removed. */
- for (i = 0; privkeys[i] != NULL; i++) {
- privkey = privkeys[i];
- oldcert = PK11_GetCertFromPrivateKey(privkey);
- if (!entry->cm_key_preserve && (oldcert == NULL)) {
- /* We're not preserving
- * orphaned keys, so remove
- * this one. No need to mess
- * with its nickname first. */
- PK11_DeleteTokenPrivateKey(privkey, PR_FALSE);
- if (error == SECSuccess) {
- cm_log(3, "Removed old key.\n");
- } else {
- ec = PORT_GetError();
- if (ec != 0) {
- es = PR_ErrorToName(ec);
+ if (privkeys != NULL) {
+ /* Check if any certificates are still using
+ * the keys that correspond to certificates
+ * that we removed. */
+ for (i = 0; privkeys[i] != NULL; i++) {
+ privkey = privkeys[i];
+ oldcert = PK11_GetCertFromPrivateKey(privkey);
+ if (!entry->cm_key_preserve && (oldcert == NULL)) {
+ /* We're not preserving
+ * orphaned keys, so remove
+ * this one. No need to mess
+ * with its nickname first. */
+ PK11_DeleteTokenPrivateKey(privkey, PR_FALSE);
+ if (error == SECSuccess) {
+ cm_log(3, "Removed old key.\n");
} else {
- es = NULL;
+ ec = PORT_GetError();
+ if (ec != 0) {
+ es = PR_ErrorToName(ec);
+ } else {
+ es = NULL;
+ }
+ if (es != NULL) {
+ cm_log(0, "Failed "
+ "to remove "
+ "old key: "
+ "%s.\n", es);
+ } else {
+ cm_log(0, "Failed "
+ "to remove "
+ "old key.\n");
+ }
}
- if (es != NULL) {
- cm_log(0, "Failed "
- "to remove "
- "old key: "
- "%s.\n", es);
- } else {
- cm_log(0, "Failed "
- "to remove "
- "old key.\n");
- }
- }
- } else {
- /* Remove the explicit
- * nickname, so that the key
- * will have to be found using
- * the certificate's nickname,
- * and certutil will display
- * the matching certificate's
- * nickname when it's asked to
- * list the keys in the
- * database. */
- error = PK11_SetPrivateKeyNickname(privkey, "");
- if (error == SECSuccess) {
- cm_log(3, "Removed "
- "name from old "
- "key.\n");
} else {
- ec = PORT_GetError();
- if (ec != 0) {
- es = PR_ErrorToName(ec);
+ /* Remove the explicit
+ * nickname, so that the key
+ * will have to be found using
+ * the certificate's nickname,
+ * and certutil will display
+ * the matching certificate's
+ * nickname when it's asked to
+ * list the keys in the
+ * database. */
+ error = PK11_SetPrivateKeyNickname(privkey, "");
+ if (error == SECSuccess) {
+ cm_log(3, "Removed "
+ "name from old "
+ "key.\n");
} else {
- es = NULL;
- }
- if (es != NULL) {
- cm_log(0, "Failed "
- "to unname "
- "old key: "
- "%s.\n", es);
- } else {
- cm_log(0, "Failed "
- "to unname "
- "old key.\n");
+ ec = PORT_GetError();
+ if (ec != 0) {
+ es = PR_ErrorToName(ec);
+ } else {
+ es = NULL;
+ }
+ if (es != NULL) {
+ cm_log(0, "Failed "
+ "to unname "
+ "old key: "
+ "%s.\n", es);
+ } else {
+ cm_log(0, "Failed "
+ "to unname "
+ "old key.\n");
+ }
}
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (oldcert != NULL) {
+ CERT_DestroyCertificate(oldcert);
}
- SECKEY_DestroyPrivateKey(privkey);
- }
- if (oldcert != NULL) {
- CERT_DestroyCertificate(oldcert);
}
+ free(privkeys);
}
- free(privkeys);
+ } else {
+ cm_log(1, "Error getting handle to default NSS DB.\n");
}
- } else {
- cm_log(1, "Error getting handle to default NSS DB.\n");
- }
- PORT_FreeArena(arena, PR_TRUE);
- if (NSS_ShutdownContext(ctx) != SECSuccess) {
- cm_log(1, "Error shutting down NSS.\n");
- }
- /* Fixup the ownership and permissions on the key and
- * certificate databases. */
- util_set_db_entry_key_owner(entry->cm_key_storage_location, entry);
- util_set_db_entry_cert_owner(entry->cm_cert_storage_location, entry);
- }
+ PORT_FreeArena(arena, PR_TRUE);
+ if (NSS_ShutdownContext(ctx) != SECSuccess) {
+ cm_log(1, "Error shutting down NSS.\n");
+ }
+ /* Fixup the ownership and permissions on the key and
+ * certificate databases. */
+ util_set_db_entry_key_owner(entry->cm_key_storage_location, entry);
+ util_set_db_entry_cert_owner(entry->cm_cert_storage_location, entry);
+ break;
+next_slot:
+ if (sle == slotlist->tail) {
+ break;
+ }
+ } /* for slot loop */
+ } /* ctx == NULL */
+
if (status != 0) {
_exit(status);
}
--
2.14.4