[pkg-opensc-commit] [opensc] 150/295: pkcs11: don't shrink the number of slots
Eric Dorland
eric at moszumanska.debian.org
Sat Jun 24 21:11:26 UTC 2017
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository opensc.
commit 24b7507a69704f69e371834953cf78cffec104b0
Author: Frank Morgner <frankmorgner at gmail.com>
Date: Sat Sep 3 00:46:48 2016 +0200
pkcs11: don't shrink the number of slots
... as required by PKCS#11 2.30, if the application doesn't call
`C_GetSlotList` with `NULL`.
Fixes ghost tokens in Firefox when detaching a reader that contained a
card.
Fixes https://github.com/OpenSC/OpenSC/issues/629
---
src/pkcs11/framework-pkcs15.c | 3 +++
src/pkcs11/pkcs11-global.c | 10 ++++---
src/pkcs11/sc-pkcs11.h | 7 +++++
src/pkcs11/slot.c | 63 +++++++++++++++++++++++++++++--------------
4 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
index c5c8a1a..0c0af88 100644
--- a/src/pkcs11/framework-pkcs15.c
+++ b/src/pkcs11/framework-pkcs15.c
@@ -486,6 +486,9 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
goto out;
}
+ if (slot->p11card == NULL)
+ return CKR_TOKEN_NOT_PRESENT;
+
fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx];
if (!fw_data)
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetTokenInfo");
diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c
index 11a49ac..9fd0f09 100644
--- a/src/pkcs11/pkcs11-global.c
+++ b/src/pkcs11/pkcs11-global.c
@@ -405,16 +405,20 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
prev_reader = NULL;
numMatches = 0;
for (i=0; i<list_size(&virtual_slots); i++) {
- slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
+ slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
/* the list of available slots contains:
* - if present, virtual hotplug slot;
* - any slot with token;
* - without token(s), one empty slot per reader;
+ * - any slot that has already been seen;
*/
- if ((!tokenPresent && !slot->reader)
+ if ((!tokenPresent && !slot->reader)
|| (!tokenPresent && slot->reader != prev_reader)
- || (slot->slot_info.flags & CKF_TOKEN_PRESENT))
+ || (slot->slot_info.flags & CKF_TOKEN_PRESENT)
+ || (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) {
found[numMatches++] = slot->id;
+ slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN;
+ }
prev_reader = slot->reader;
}
diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h
index ab05ba6..5b51234 100644
--- a/src/pkcs11/sc-pkcs11.h
+++ b/src/pkcs11/sc-pkcs11.h
@@ -205,6 +205,12 @@ struct sc_pkcs11_card {
unsigned int nmechanisms;
};
+/* If the slot did already show with `C_GetSlotList`, then we need to keep this
+ * slot alive. PKCS#11 2.30 allows allows adding but not removing slots until
+ * the application calls `C_GetSlotList` with `NULL`. This flag tracks the
+ * visibility to the application */
+#define SC_PKCS11_SLOT_FLAG_SEEN 1
+
struct sc_pkcs11_slot {
CK_SLOT_ID id; /* ID of the slot */
int login_user; /* Currently logged in user */
@@ -221,6 +227,7 @@ struct sc_pkcs11_slot {
int fw_data_idx; /* Index of framework data */
struct sc_app_info *app_info; /* Application assosiated to slot */
list_t logins; /* tracks all calls to C_Login if atomic operations are requested */
+ int flags;
};
typedef struct sc_pkcs11_slot sc_pkcs11_slot_t;
diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c
index 45be6d4..ba5e4f4 100644
--- a/src/pkcs11/slot.c
+++ b/src/pkcs11/slot.c
@@ -75,26 +75,39 @@ static int object_list_seeker(const void *el, const void *key)
CK_RV create_slot(sc_reader_t *reader)
{
- struct sc_pkcs11_slot *slot;
+ /* find unused virtual hotplug slots */
+ struct sc_pkcs11_slot *slot = reader_get_slot(NULL);
- if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots)
- return CKR_FUNCTION_FAILED;
+ /* create a new slot if no empty slot is available */
+ if (!slot) {
+ if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots)
+ return CKR_FUNCTION_FAILED;
- slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot));
- if (!slot)
- return CKR_HOST_MEMORY;
+ slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot));
+ if (!slot)
+ return CKR_HOST_MEMORY;
- list_append(&virtual_slots, slot);
- slot->login_user = -1;
- slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
- sc_log(context, "Creating slot with id 0x%lx", slot->id);
+ list_append(&virtual_slots, slot);
+ list_init(&slot->objects);
+ list_attributes_seeker(&slot->objects, object_list_seeker);
+
+ list_init(&slot->logins);
+ } else {
+ /* reuse the old list of logins/objects since they should be empty */
+ list_t logins = slot->logins;
+ list_t objects = slot->objects;
- list_init(&slot->objects);
- list_attributes_seeker(&slot->objects, object_list_seeker);
+ memset(slot, 0, sizeof *slot);
- list_init(&slot->logins);
+ slot->logins = logins;
+ slot->objects = objects;
+ }
+ slot->login_user = -1;
+ slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
init_slot_info(&slot->slot_info);
+ sc_log(context, "Initializing slot with id 0x%lx", slot->id);
+
if (reader != NULL) {
slot->reader = reader;
strcpy_bp(slot->slot_info.manufacturerID, reader->vendor, 32);
@@ -106,13 +119,21 @@ CK_RV create_slot(sc_reader_t *reader)
return CKR_OK;
}
-void delete_slot(struct sc_pkcs11_slot *slot)
+void empty_slot(struct sc_pkcs11_slot *slot)
{
if (slot) {
- list_destroy(&slot->objects);
- list_destroy(&slot->logins);
- list_delete(&virtual_slots, slot);
- free(slot);
+ if (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN) {
+ /* Keep the slot visible to the application. The slot's state has
+ * already been reset by `slot_token_removed()`, lists have been
+ * emptied. We replace the reader with a virtual hotplug slot. */
+ slot->reader = NULL;
+ init_slot_info(&slot->slot_info);
+ } else {
+ list_destroy(&slot->objects);
+ list_destroy(&slot->logins);
+ list_delete(&virtual_slots, slot);
+ free(slot);
+ }
}
}
@@ -343,7 +364,7 @@ card_detect_all(void)
struct sc_pkcs11_slot *slot;
card_removed(reader);
while ((slot = reader_get_slot(reader))) {
- delete_slot(slot);
+ empty_slot(slot);
}
_sc_delete_reader(context, reader);
i--;
@@ -444,17 +465,19 @@ CK_RV slot_token_removed(CK_SLOT_ID id)
slot->p11card->framework->release_token(slot->p11card, slot->fw_data);
slot->fw_data = NULL;
}
+ slot->p11card = NULL;
}
/* Reset relevant slot properties */
slot->slot_info.flags &= ~CKF_TOKEN_PRESENT;
slot->login_user = -1;
pop_all_login_states(slot);
- slot->p11card = NULL;
if (token_was_present)
slot->events = SC_EVENT_CARD_REMOVED;
+ memset(&slot->token_info, 0, sizeof slot->token_info);
+
return CKR_OK;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git
More information about the pkg-opensc-commit
mailing list