pkcs11: reclaim unused slots based on reader description

When a reader is removed and reattached, this re-uses the old slot
without relying on the fact that the sc_reader_t is unchanged.
This commit is contained in:
Frank Morgner 2020-03-03 15:09:17 +01:00
parent ce704f5eb1
commit 5b9af96851
2 changed files with 41 additions and 10 deletions

View File

@ -468,8 +468,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
for (i=0; i<list_size(&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;
* - without token(s), one empty slot per reader;
* - without token(s), at least one empty slot per reader;
* - any slot with token;
* - any slot that has already been seen;
*/
@ -550,7 +549,7 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
sc_log(context, "C_GetSlotInfo(0x%lx)", slotID);
if (sc_pkcs11_conf.init_sloppy) {
/* Most likely virtual_slots only contains the hotplug slot and has not
/* Most likely virtual_slots is empty and has not
* been initialized because the caller has *not* called C_GetSlotList
* before C_GetSlotInfo, as required by PKCS#11. Initialize
* virtual_slots to make things work and hope the caller knows what

View File

@ -37,15 +37,26 @@ static struct sc_pkcs11_framework_ops *frameworks[] = {
NULL
};
static struct sc_pkcs11_slot * reader_get_slot(sc_reader_t *reader)
static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader)
{
unsigned int i;
CK_UTF8CHAR slotDescription[64];
CK_UTF8CHAR manufacturerID[32];
strcpy_bp(slotDescription, reader->name, 64);
strcpy_bp(manufacturerID, reader->vendor, 32);
/* Locate a slot related to the reader */
for (i = 0; i<list_size(&virtual_slots); i++) {
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
if (slot->reader == reader)
return slot;
if (slot->reader == NULL && reader != NULL
&& 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64)
&& 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32)
&& slot->slot_info.hardwareVersion.major == reader->version_major
&& slot->slot_info.hardwareVersion.minor == reader->version_minor)
return slot;
}
return NULL;
}
@ -82,8 +93,8 @@ static int object_list_seeker(const void *el, const void *key)
CK_RV create_slot(sc_reader_t *reader)
{
/* find unused virtual hotplug slots */
struct sc_pkcs11_slot *slot = reader_get_slot(NULL);
/* find unused slots previously allocated for the same reader */
struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader);
/* create a new slot if no empty slot is available */
if (!slot) {
@ -373,11 +384,32 @@ card_detect_all(void)
* possible according to PKCS#11 2.20 and later, because NSS can't
* handle a shrinking slot list
* https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */
/* Instead, remove the releation between reader and slot */
for (i = 0; i<list_size(&virtual_slots); i++) {
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
if (slot->reader == reader) {
slot->reader = NULL;
}
}
} else {
if (!reader_get_slot(reader))
initialize_reader(reader);
else
card_detect(sc_ctx_get_reader(context, i));
/* Locate a slot related to the reader */
int found = 0;
for (i = 0; i<list_size(&virtual_slots); i++) {
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
if (slot->reader == reader) {
found = 1;
break;
}
}
if (!found) {
for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) {
CK_RV rv = create_slot(reader);
if (rv != CKR_OK)
return rv;
}
}
card_detect(reader);
}
}
sc_log(context, "All cards detected");