From 54f285d57ada65fc7774e82e2f0d10c35060d7ed Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 23:30:06 +0200 Subject: [PATCH] correctly handle readers that have been removed --- src/libopensc/opensc.h | 1 + src/libopensc/reader-pcsc.c | 23 +++++++++++++++-------- src/pkcs11/slot.c | 14 +++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 7964b311..90f0e2e0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -286,6 +286,7 @@ struct sc_reader_driver { #define SC_READER_CARD_INUSE 0x00000004 #define SC_READER_CARD_EXCLUSIVE 0x00000008 #define SC_READER_HAS_WAITING_AREA 0x00000010 +#define SC_READER_REMOVED 0x00000020 /* reader capabilities */ #define SC_READER_CAP_DISPLAY 0x00000001 diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 06192cf3..32007394 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -949,6 +949,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) char *reader_buf = NULL, *reader_name; const char *mszGroups = NULL; int ret = SC_ERROR_INTERNAL; + size_t i; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -958,7 +959,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Probing pcsc readers"); + /* temporarily mark all readers as removed */ + for (i=0;i < sc_ctx_get_reader_count(ctx);i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + reader->flags |= SC_READER_REMOVED; + } + + sc_log(ctx, "Probing PC/SC readers"); do { if (gpriv->pcsc_ctx == -1) { @@ -980,7 +987,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Establish pcsc context"); + sc_log(ctx, "Establish PC/SC context"); rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); @@ -1007,28 +1014,28 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) { - sc_reader_t *reader = NULL; + sc_reader_t *reader = NULL, *old_reader; struct pcsc_private_data *priv = NULL; - unsigned int i; int found = 0; for (i=0;i < sc_ctx_get_reader_count(ctx) && !found;i++) { - sc_reader_t *reader2 = sc_ctx_get_reader(ctx, i); - if (reader2 == NULL) { + old_reader = sc_ctx_get_reader(ctx, i); + if (old_reader == NULL) { ret = SC_ERROR_INTERNAL; goto err1; } - if (!strcmp(reader2->name, reader_name)) { + if (!strcmp(old_reader->name, reader_name)) { found = 1; } } /* Reader already available, skip */ if (found) { + old_reader->flags &= ~SC_READER_REMOVED; continue; } - sc_log(ctx, "Found new pcsc reader '%s'", reader_name); + sc_log(ctx, "Found new PC/SC reader '%s'", reader_name); if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 87b1e3dd..9f2ae484 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -330,9 +330,13 @@ card_detect_all(void) /* Detect cards in all initialized readers */ for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); - if (!reader_get_slot(reader)) - initialize_reader(reader); - card_detect(sc_ctx_get_reader(context, i)); + if (reader->flags & SC_READER_REMOVED) { + card_removed(reader); + } else { + if (!reader_get_slot(reader)) + initialize_reader(reader); + card_detect(sc_ctx_get_reader(context, i)); + } } sc_log(context, "All cards detected"); return CKR_OK; @@ -420,7 +424,7 @@ CK_RV slot_token_removed(CK_SLOT_ID id) /* Release framework stuff */ if (slot->card != NULL) { if (slot->fw_data != NULL && - slot->card->framework != NULL && slot->card->framework->release_token != NULL) + slot->card->framework != NULL && slot->card->framework->release_token != NULL) slot->card->framework->release_token(slot->card, slot->fw_data); } @@ -446,7 +450,7 @@ CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask) sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); sc_log(context, "slot 0x%lx token: %d events: 0x%02X",slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT), slot->events); if ((slot->events & SC_EVENT_CARD_INSERTED) - && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { /* If a token has not been initialized, clear the inserted event */ slot->events &= ~SC_EVENT_CARD_INSERTED; }