From cb047d6a6aeb85acae9e568b2096a2d5bd779786 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Wed, 27 Sep 2023 13:48:34 +0000 Subject: [PATCH] import CS opensc-0.20.0-6.el8 --- SOURCES/opensc-0.20.0-CVE-2023-2977.patch | 50 + SOURCES/opensc-0.20.0-idprime.patch | 25 + SOURCES/opensc-0.20.0-reader-removal.patch | 2173 ++++++++++++++++++++ SPECS/opensc.spec | 35 +- 4 files changed, 2282 insertions(+), 1 deletion(-) create mode 100644 SOURCES/opensc-0.20.0-CVE-2023-2977.patch create mode 100644 SOURCES/opensc-0.20.0-idprime.patch create mode 100644 SOURCES/opensc-0.20.0-reader-removal.patch diff --git a/SOURCES/opensc-0.20.0-CVE-2023-2977.patch b/SOURCES/opensc-0.20.0-CVE-2023-2977.patch new file mode 100644 index 0000000..8d3d4fd --- /dev/null +++ b/SOURCES/opensc-0.20.0-CVE-2023-2977.patch @@ -0,0 +1,50 @@ +From 81944d1529202bd28359bede57c0a15deb65ba8a Mon Sep 17 00:00:00 2001 +From: fullwaywang +Date: Mon, 29 May 2023 10:38:48 +0800 +Subject: [PATCH] pkcs15init: correct left length calculation to fix buffer + overrun bug. Fixes #2785 + +--- + src/pkcs15init/pkcs15-cardos.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs15init/pkcs15-cardos.c b/src/pkcs15init/pkcs15-cardos.c +index 9715cf390f..f41f73c349 100644 +--- a/src/pkcs15init/pkcs15-cardos.c ++++ b/src/pkcs15init/pkcs15-cardos.c +@@ -872,7 +872,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + sc_apdu_t apdu; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + int r; +- const u8 *p = rbuf, *q; ++ const u8 *p = rbuf, *q, *pp; + size_t len, tlen = 0, ilen = 0; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88); +@@ -888,13 +888,13 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + return 0; + + while (len != 0) { +- p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); +- if (p == NULL) ++ pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); ++ if (pp == NULL) + return 0; + if (card->type == SC_CARD_TYPE_CARDOS_M4_3) { + /* the verifyRC package on CardOS 4.3B use Manufacturer ID 0x01 */ + /* and Package Number 0x07 */ +- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen); ++ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x07) +@@ -902,7 +902,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card) + } else if (card->type == SC_CARD_TYPE_CARDOS_M4_4) { + /* the verifyRC package on CardOS 4.4 use Manufacturer ID 0x03 */ + /* and Package Number 0x02 */ +- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x03, &ilen); ++ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x03, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x02) + diff --git a/SOURCES/opensc-0.20.0-idprime.patch b/SOURCES/opensc-0.20.0-idprime.patch new file mode 100644 index 0000000..7b9b346 --- /dev/null +++ b/SOURCES/opensc-0.20.0-idprime.patch @@ -0,0 +1,25 @@ +From 34dad7f543f006ad269ce1f935a9e8d3e3a83db7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 3 Feb 2020 16:40:51 +0100 +Subject: [PATCH] idprime: Add missing terminator in ATR list + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20510 +--- + src/libopensc/card-idprime.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c +index 744d5189b9..9f5adde9d2 100644 +--- a/src/libopensc/card-idprime.c ++++ b/src/libopensc/card-idprime.c +@@ -52,6 +52,7 @@ static const struct sc_atr_table idprime_atrs[] = { + "ff:ff:00:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff", + "Gemalto IDPrime MD 8840, 3840, 3810, 840 and 830 Cards", + SC_CARD_TYPE_IDPRIME_GENERIC, 0, NULL }, ++ { NULL, NULL, NULL, 0, 0, NULL } + }; + + static const sc_path_t idprime_path = { + diff --git a/SOURCES/opensc-0.20.0-reader-removal.patch b/SOURCES/opensc-0.20.0-reader-removal.patch new file mode 100644 index 0000000..b2951dc --- /dev/null +++ b/SOURCES/opensc-0.20.0-reader-removal.patch @@ -0,0 +1,2173 @@ +From 31d8c2dfd14ed01b430def2f46cc718ef4b595fc Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 19 Feb 2020 16:09:20 +0100 +Subject: [PATCH] Revert "pkcs11: fixed slotIDs when a new slot list is + requested" + +This reverts commit 7fb72ccf7bf3ca2ff3979b7ffbb690eed41ddb5f. +--- + src/pkcs11/pkcs11-global.c | 22 +--------------------- + src/pkcs11/slot.c | 2 +- + 2 files changed, 2 insertions(+), 22 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 71e13831..c51f2fb9 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -451,13 +451,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + pSlotList==NULL_PTR? "plug-n-play":"refresh"); + + /* Slot list can only change in v2.20 */ +- if (pSlotList == NULL_PTR) { ++ if (pSlotList == NULL_PTR) + sc_ctx_detect_readers(context); +- for (i=0; iflags &= ~SC_PKCS11_SLOT_FLAG_SEEN; +- } +- } + + card_detect_all(); + +@@ -488,21 +483,6 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + prev_reader = slot->reader; + } + +- /* Slot list can only change in v2.20 */ +- if (pSlotList == NULL_PTR) { +- /* slot->id is derived from its location in the list virtual_slots. +- * When the slot list changes, so does slot->id, so we reindex the +- * slots here the same way it is done in `create_slot()` +- * +- * TODO use a persistent CK_SLOT_ID, e.g. by using something like +- * `slot->id = sc_crc32(slot, sizeof *slot);` (this example, however, +- * is currently not thread safe). */ +- for (i=0; iid = (CK_SLOT_ID) list_locate(&virtual_slots, slot); +- } +- } +- + if (pSlotList == NULL_PTR) { + sc_log(context, "was only a size inquiry (%lu)\n", numMatches); + *pulCount = numMatches; +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index 423457b4..12dea459 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -115,6 +115,7 @@ CK_RV create_slot(sc_reader_t *reader) + } + + slot->login_user = -1; ++ slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); + init_slot_info(&slot->slot_info, reader); + sc_log(context, "Initializing slot with id 0x%lx", slot->id); + +@@ -125,7 +126,6 @@ CK_RV create_slot(sc_reader_t *reader) + slot->slot_info.hardwareVersion.major = reader->version_major; + slot->slot_info.hardwareVersion.minor = reader->version_minor; + } +- slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); + + return CKR_OK; + } +-- +2.40.1 + +From 8f4a6c703b5ae7d4f44cf33c85330171afa917bf Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 20 Feb 2020 01:42:18 +0100 +Subject: [PATCH] align comment with implementation order + +--- + src/pkcs11/pkcs11-global.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index c51f2fb9..b1e0ab57 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -469,8 +469,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + 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 with token; + * - any slot that has already been seen; + */ + if ((!tokenPresent && !slot->reader) +@@ -504,10 +504,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + sc_log(context, "returned %lu slots\n", numMatches); + + out: +- if (found != NULL) { +- free (found); +- found = NULL; +- } ++ free (found); + sc_pkcs11_unlock(); + return rv; + } +-- +2.40.1 + + + + +From bae42473f68e7ca15fcf273348019361ccdc4e59 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Tue, 25 Feb 2020 20:24:00 -0600 +Subject: [PATCH 2/7] Improved Handling of PKCS11 Slots + +OpenSC PKCS11 now retains slots even when the reader is removed. +It can do this because existing OpenSC reader handling in ctx.c, +reader-pcsc.c and PC/SC allow OpenSC to do this. + +This simplifies the code, and allow a reader to be reinserted +and use the existing slot. This matching is actually done +in reader-pcsc.c because PC/SC returns the unique ids based on +the OS reader names. This is then used as the manufacturerID + +By not deleting slots the slot list can only increase which is a +restriction of Firefox. It does not fix all the Firefox issues, but +it does not go into a loop, when all the readers are removed. + +The defaults in opensc.conf for max-virtual-readers and slots-per-card +allow for 4 different readers used during one session. + + On branch PKCS11-SLOTS-3 + Changes to be committed: + modified: sc-pkcs11.h + modified: slot.c +--- + src/pkcs11/sc-pkcs11.h | 5 +++++ + src/pkcs11/slot.c | 43 ++++++++++++++++++++++++------------------ + 2 files changed, 30 insertions(+), 18 deletions(-) + +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index 4309b63116..55236d2163 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -206,6 +206,11 @@ struct sc_pkcs11_card { + * the application calls `C_GetSlotList` with `NULL`. This flag tracks the + * visibility to the application */ + #define SC_PKCS11_SLOT_FLAG_SEEN 1 ++/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains ++ * readers which have been removed retain removed readers. ++ * Take advantage of this feature to allow for reinsertion of a reader*/ ++#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 ++ + + struct sc_pkcs11_slot { + CK_SLOT_ID id; /* ID of the slot */ +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index 12dea4599c..daaac6bb19 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -133,18 +133,8 @@ CK_RV create_slot(sc_reader_t *reader) + void empty_slot(struct sc_pkcs11_slot *slot) + { + if (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, NULL); +- } else { +- list_destroy(&slot->objects); +- list_destroy(&slot->logins); +- list_delete(&virtual_slots, slot); +- free(slot); +- } ++ list_clear(&slot->objects); ++ list_clear(&slot->logins); + } + } + +@@ -383,21 +373,38 @@ CK_RV card_detect(sc_reader_t *reader) + CK_RV + card_detect_all(void) + { +- unsigned int i; ++ unsigned int i, j; + + sc_log(context, "Detect all cards"); + /* 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); ++ int removed = 0; /* have we called card_removed for this reader */ ++ + if (reader->flags & SC_READER_REMOVED) { + struct sc_pkcs11_slot *slot; +- card_removed(reader); +- while ((slot = reader_get_slot(reader))) { +- empty_slot(slot); ++ /* look at all slots to call card_removed amd empty_slot */ ++ for (j = 0; jreader == reader) { ++ if (!removed) { ++ card_removed(reader); ++ removed = 1; /* only need to call once for this reader */ ++ } ++ if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { ++ empty_slot(slot); ++ slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; ++ } ++ } + } +- _sc_delete_reader(context, reader); +- i--; + } else { ++ struct sc_pkcs11_slot *slot; ++ for (j = 0; jreader == reader) ++ slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; ++ } ++ + if (!reader_get_slot(reader)) + initialize_reader(reader); + else + +From cf4f21236060c35e566de2712a6a54ea0e2eabe5 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 2 Mar 2020 22:24:54 +0100 +Subject: [PATCH 3/7] pkcs11: simpify reader removal + +- reader (slot) description is already initialized init_slot_info() +- objects and logins are already released in slot_token_removed +--- + src/pkcs11/pkcs11-global.c | 4 +--- + src/pkcs11/sc-pkcs11.h | 11 ---------- + src/pkcs11/slot.c | 43 ++++++-------------------------------- + 3 files changed, 7 insertions(+), 51 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index b1e0ab57c9..25c4cd362e 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -475,10 +475,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + */ + if ((!tokenPresent && !slot->reader) + || (!tokenPresent && slot->reader != prev_reader) +- || (slot->slot_info.flags & CKF_TOKEN_PRESENT) +- || (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) { ++ || (slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + 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 55236d2163..16e8fdf797 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -201,16 +201,6 @@ 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 +-/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains +- * readers which have been removed retain removed readers. +- * Take advantage of this feature to allow for reinsertion of a reader*/ +-#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 +- + + struct sc_pkcs11_slot { + CK_SLOT_ID id; /* ID of the slot */ +@@ -232,7 +222,6 @@ struct sc_pkcs11_slot { + }; + typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; + +- + /* Forward decl */ + typedef struct sc_pkcs11_operation sc_pkcs11_operation_t; + +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index daaac6bb19..2fb495d295 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -121,24 +121,11 @@ CK_RV create_slot(sc_reader_t *reader) + + if (reader != NULL) { + slot->reader = reader; +- strcpy_bp(slot->slot_info.manufacturerID, reader->vendor, 32); +- strcpy_bp(slot->slot_info.slotDescription, reader->name, 64); +- slot->slot_info.hardwareVersion.major = reader->version_major; +- slot->slot_info.hardwareVersion.minor = reader->version_minor; + } + + return CKR_OK; + } + +-void empty_slot(struct sc_pkcs11_slot *slot) +-{ +- if (slot) { +- list_clear(&slot->objects); +- list_clear(&slot->logins); +- } +-} +- +- + /* create slots associated with a reader, called whenever a reader is seen. */ + CK_RV initialize_reader(sc_reader_t *reader) + { +@@ -373,38 +360,20 @@ CK_RV card_detect(sc_reader_t *reader) + CK_RV + card_detect_all(void) + { +- unsigned int i, j; ++ unsigned int i; + + sc_log(context, "Detect all cards"); + /* 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); +- int removed = 0; /* have we called card_removed for this reader */ + + if (reader->flags & SC_READER_REMOVED) { +- struct sc_pkcs11_slot *slot; +- /* look at all slots to call card_removed amd empty_slot */ +- for (j = 0; jreader == reader) { +- if (!removed) { +- card_removed(reader); +- removed = 1; /* only need to call once for this reader */ +- } +- if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { +- empty_slot(slot); +- slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; +- } +- } +- } ++ card_removed(reader); ++ /* do not remove slots related to this reader which would be ++ * 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 */ + } else { +- struct sc_pkcs11_slot *slot; +- for (j = 0; jreader == reader) +- slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; +- } +- + if (!reader_get_slot(reader)) + initialize_reader(reader); + else + +From 87d2798e72ab940b7f7a57490663751ae4dc8842 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Tue, 3 Mar 2020 12:38:37 +0100 +Subject: [PATCH 4/7] removed unused plug_and_play parameter + +see 1fb741338a010515b35f28cd9c769561f3e574a2 +--- + src/pkcs11/sc-pkcs11.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index 16e8fdf797..c3a13934bc 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -65,7 +65,6 @@ struct sc_pkcs11_slot; + struct sc_pkcs11_card; + + struct sc_pkcs11_config { +- unsigned int plug_and_play; + unsigned int max_virtual_slots; + unsigned int slots_per_card; + unsigned char lock_login; + +From cc4d4ff0b069c5517cce1ccbd374b6a18d61e020 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Tue, 3 Mar 2020 15:09:17 +0100 +Subject: [PATCH 5/7] 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. +--- + src/pkcs11/pkcs11-global.c | 5 ++--- + src/pkcs11/slot.c | 46 ++++++++++++++++++++++++++++++++------ + 2 files changed, 41 insertions(+), 10 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 25c4cd362e..95c37f3c72 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -468,8 +468,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + for (i=0; iname, 64); ++ strcpy_bp(manufacturerID, reader->vendor, 32); + + /* Locate a slot related to the reader */ + for (i = 0; ireader == 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; ireader == 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; ireader == 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"); + +From 61a2c6aaff0aa3add222f8560a8075637ee9b1fd Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 13 Jan 2020 17:21:18 +0100 +Subject: [PATCH 6/7] reader-pcsc: fixed handling of detatching events + +- allows re-attatching a reader to an existing reader object by +resetting the SC_READER_REMOVED flag +- readers that are flagged with SC_READER_REMOVED are not used for +SCardGetStatusChange to avoid SCARD_E_UNKNOWN_READER + +fixes https://github.com/OpenSC/OpenSC/issues/1903 +--- + src/libopensc/reader-pcsc.c | 48 ++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 66b426e436..14e3b4e0ec 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -181,6 +181,9 @@ static int pcsc_to_opensc_error(LONG rv) + return SC_ERROR_READER_LOCKED; + case SCARD_E_NO_READERS_AVAILABLE: + return SC_ERROR_NO_READERS_FOUND; ++ case SCARD_E_UNKNOWN_READER: ++ return SC_ERROR_READER_DETACHED; ++ + case SCARD_E_NO_SERVICE: + /* If the service is (auto)started, there could be readers later */ + return SC_ERROR_NO_READERS_FOUND; +@@ -1467,8 +1470,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + for (reader_name = reader_buf; *reader_name != '\x0'; + reader_name += strlen(reader_name) + 1) { +- if (!strcmp(reader->name, reader_name)) ++ if (!strcmp(reader->name, reader_name)) { ++ if (reader->flags & SC_READER_REMOVED) { ++ reader->flags &= ~SC_READER_REMOVED; ++ refresh_attributes(reader); ++ } + break; ++ } + } + + if (*reader_name != '\x0') { +@@ -1546,7 +1554,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + LONG rv; + SCARD_READERSTATE *rgReaderStates; + size_t i; +- unsigned int num_watch; ++ unsigned int num_watch, count; + int r = SC_ERROR_INTERNAL; + DWORD dwtimeout; + +@@ -1565,22 +1573,30 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + /* Find out the current status */ +- num_watch = sc_ctx_get_reader_count(ctx); +- sc_log(ctx, "Trying to watch %d readers", num_watch); +- for (i = 0; i < num_watch; i++) { +- rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name; +- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; +- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; ++ num_watch = 0; ++ count = sc_ctx_get_reader_count(ctx); ++ for (i = 0; i < count; i++) { ++ sc_reader_t *reader = sc_ctx_get_reader(ctx, i); ++ if (reader->flags & SC_READER_REMOVED) ++ continue; ++ rgReaderStates[num_watch].szReader = reader->name; ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; ++ num_watch++; + } +-#ifndef __APPLE__ +- /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ ++ sc_log(ctx, "Trying to watch %d reader%s", num_watch, num_watch == 1 ? "" : "s"); + if (event_mask & SC_EVENT_READER_ATTACHED) { +- rgReaderStates[i].szReader = "\\\\?PnP?\\Notification"; +- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; +- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; ++#ifdef __APPLE__ ++ /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ ++ sc_log(ctx, "PnP notification not supported"); ++#else ++ rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; + num_watch++; +- } ++ sc_log(ctx, "Trying to detect new readers"); + #endif ++ } + } + else { + rgReaderStates = (SCARD_READERSTATE *)(*reader_states); +@@ -1606,14 +1622,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + goto out; + } + +-#ifdef __APPLE__ + if (num_watch == 0) { +- sc_log(ctx, "No readers available, PnP notification not supported"); ++ sc_log(ctx, "No readers available to be watched"); + *event_reader = NULL; + r = SC_ERROR_NO_READERS_FOUND; + goto out; + } +-#endif + + rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, 0, rgReaderStates, num_watch); + if (rv != SCARD_S_SUCCESS) { + +From 2901a2d040ec13b70c9cd212f7cbf9ad4ef8c602 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 13 Jan 2020 17:25:38 +0100 +Subject: [PATCH] opensc-notify: handle reader insertion/removal events + +- If readers are attatched, the new reader is probed for a card to check +if a notification needs to be sent +- removal of readers are not notified to the user, we assume that PC/SC +sends the correct card removal event +- The list of readers to be monitored is adjusted once a reader (dis)appears +- On macOS, without PnP notification, we always check for new/removed +readers with SCardListReaders +- fixes interrupt handling in opensc-notify on Unix + +fixes https://github.com/OpenSC/OpenSC/issues/1874 +--- + src/libopensc/errors.c | 4 +- + src/libopensc/internal-winscard.h | 1 + + src/libopensc/opensc.h | 33 +++-- + src/libopensc/reader-pcsc.c | 205 +++++++++++++++++++++--------- + src/tools/opensc-notify.c | 125 ++++++++++-------- + src/ui/strings.c | 10 +- + 6 files changed, 248 insertions(+), 130 deletions(-) + +diff --git a/src/libopensc/errors.c b/src/libopensc/errors.c +index 5b58b7ea6c..03cb79dd1f 100644 +--- a/src/libopensc/errors.c ++++ b/src/libopensc/errors.c +@@ -45,8 +45,8 @@ const char *sc_strerror(int error) + "Message too long (keypad)", + "Timeout while waiting for event from card reader", + "Unresponsive card (correctly inserted?)", +- "Reader detached (hotplug device?)", +- "Reader reattached (hotplug device?)", ++ "Reader detached", ++ "Reader reattached", + "Reader in use by another application" + }; + const int rdr_base = -SC_ERROR_READER; +diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h +index edc315ca2f..6b2a21c569 100644 +--- a/src/libopensc/internal-winscard.h ++++ b/src/libopensc/internal-winscard.h +@@ -100,6 +100,7 @@ typedef unsigned __int8 uint8_t; + #define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */ + #define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */ + #define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */ ++#define SCARD_E_SERVICE_STOPPED 0x8010001E /**< The smart card resource manager has shut down. */ + #define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */ + #define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */ + #define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */ +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index 10bea0a013..9e764665b2 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -213,10 +213,10 @@ extern "C" { + /* Event masks for sc_wait_for_event() */ + #define SC_EVENT_CARD_INSERTED 0x0001 + #define SC_EVENT_CARD_REMOVED 0x0002 +-#define SC_EVENT_CARD_EVENTS SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED ++#define SC_EVENT_CARD_EVENTS (SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED) + #define SC_EVENT_READER_ATTACHED 0x0004 + #define SC_EVENT_READER_DETACHED 0x0008 +-#define SC_EVENT_READER_EVENTS SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED ++#define SC_EVENT_READER_EVENTS (SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED) + + #define MAX_FILE_SIZE 65535 + +@@ -1024,18 +1024,25 @@ int sc_disconnect_card(struct sc_card *card); + int sc_detect_card_presence(sc_reader_t *reader); + + /** +- * Waits for an event on readers. Note: only the event is detected, +- * there is no update of any card or other info. +- * NOTE: Only PC/SC backend implements this. +- * @param ctx pointer to a Context structure +- * @param event_mask The types of events to wait for; this should +- * be ORed from one of the following +- * SC_EVENT_CARD_REMOVED +- * SC_EVENT_CARD_INSERTED +- * SC_EVENT_READER_ATTACHED +- * @param event_reader (OUT) the reader on which the event was detected, or NULL if new reader ++ * Waits for an event on readers. ++ * ++ * In case of a reader event (attached/detached), the list of reader is ++ * adjusted accordingly. This means that a subsequent call to ++ * `sc_ctx_detect_readers()` is not needed. ++ * ++ * @note Only PC/SC backend implements this. An infinite timeout on macOS does ++ * not detect reader events (use a limited timeout instead if needed). ++ * ++ * @param ctx (IN) pointer to a Context structure ++ * @param event_mask (IN) The types of events to wait for; this should ++ * be ORed from one of the following: ++ * - SC_EVENT_CARD_REMOVED ++ * - SC_EVENT_CARD_INSERTED ++ * - SC_EVENT_READER_ATTACHED ++ * - SC_EVENT_READER_DETACHED ++ * @param event_reader (OUT) the reader on which the event was detected + * @param event (OUT) the events that occurred. This is also ORed +- * from the SC_EVENT_CARD_* constants listed above. ++ * from the constants listed above. + * @param timeout Amount of millisecs to wait; -1 means forever + * @retval < 0 if an error occurred + * @retval = 0 if a an event happened +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 14e3b4e0ec..34dc821bfa 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -127,6 +127,9 @@ struct pcsc_global_private_data { + SCardTransmit_t SCardTransmit; + SCardListReaders_t SCardListReaders; + SCardGetAttrib_t SCardGetAttrib; ++ ++ sc_reader_t *attached_reader; ++ sc_reader_t *removed_reader; + }; + + struct pcsc_private_data { +@@ -185,6 +188,7 @@ static int pcsc_to_opensc_error(LONG rv) + return SC_ERROR_READER_DETACHED; + + case SCARD_E_NO_SERVICE: ++ case SCARD_E_SERVICE_STOPPED: + /* If the service is (auto)started, there could be readers later */ + return SC_ERROR_NO_READERS_FOUND; + case SCARD_E_NO_SMARTCARD: +@@ -358,7 +362,7 @@ static int refresh_attributes(sc_reader_t *reader) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + +- if (priv->reader_state.szReader == NULL) { ++ if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) { + priv->reader_state.szReader = reader->name; + priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; + priv->reader_state.dwEventState = SCARD_STATE_UNAWARE; +@@ -382,12 +386,11 @@ static int refresh_attributes(sc_reader_t *reader) + } + + /* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */ +- if ( ++ if (rv == (LONG)SCARD_E_UNKNOWN_READER + #ifdef SCARD_E_NO_READERS_AVAILABLE +- (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || ++ || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif +- (rv == (LONG)SCARD_E_UNKNOWN_READER) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { +- ++ || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + if (old_flags & SC_READER_CARD_PRESENT) { + reader->flags |= SC_READER_CARD_CHANGED; + } +@@ -1143,7 +1146,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) + return; + + rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len); +- if (rv != (LONG)SCARD_S_SUCCESS) { ++ if (rv != SCARD_S_SUCCESS) { + PCSC_TRACE(reader, "SCardControl failed", rv); + return; + } +@@ -1382,6 +1385,8 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + + sc_log(ctx, "Probing PC/SC readers"); ++ gpriv->attached_reader = NULL; ++ gpriv->removed_reader = NULL; + + do { + if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) { +@@ -1399,12 +1404,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) + * All readers have disappeared, so mark them as + * such so we don't keep polling them over and over. + */ +- if ( ++ if (rv == (LONG)SCARD_E_NO_SERVICE + #ifdef SCARD_E_NO_READERS_AVAILABLE +- (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || ++ || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif +- (rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { +- ++ || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + +@@ -1414,6 +1418,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + + reader->flags |= SC_READER_REMOVED; ++ gpriv->removed_reader = reader; + } + } + +@@ -1473,6 +1478,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + if (!strcmp(reader->name, reader_name)) { + if (reader->flags & SC_READER_REMOVED) { + reader->flags &= ~SC_READER_REMOVED; ++ gpriv->attached_reader = reader; + refresh_attributes(reader); + } + break; +@@ -1487,8 +1493,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) + (reader_buf + reader_buf_size) - next_reader_name); + reader_buf_size -= (next_reader_name - reader_name); + } else { +- /* existing reader not found */ +- reader->flags |= SC_READER_REMOVED; ++ if (!(reader->flags & SC_READER_REMOVED)) { ++ /* existing reader not found */ ++ reader->flags |= SC_READER_REMOVED; ++ gpriv->removed_reader = reader; ++ } + } + } + +@@ -1503,6 +1512,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + _sc_delete_reader(ctx, reader); + continue; + } ++ gpriv->attached_reader = reader; + + /* check for pinpad support early, to allow opensc-tool -l display accurate information */ + priv = reader->drv_data; +@@ -1555,7 +1565,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + SCARD_READERSTATE *rgReaderStates; + size_t i; + unsigned int num_watch, count; +- int r = SC_ERROR_INTERNAL; ++ int r = SC_ERROR_INTERNAL, detect_readers = 0, detected_hotplug = 0; + DWORD dwtimeout; + + LOG_FUNC_CALLED(ctx); +@@ -1579,8 +1589,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + if (reader->flags & SC_READER_REMOVED) + continue; ++ struct pcsc_private_data *priv = reader->drv_data; + rgReaderStates[num_watch].szReader = reader->name; +- rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ if (priv->reader_state.szReader == NULL) { ++ rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; ++ } else { ++ rgReaderStates[num_watch].dwCurrentState = priv->reader_state.dwEventState; ++ } + rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; + num_watch++; + } +@@ -1589,6 +1604,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + #ifdef __APPLE__ + /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ + sc_log(ctx, "PnP notification not supported"); ++ /* Always check on new readers as if a hotplug ++ * event was detected. This overwrites a ++ * SC_ERROR_EVENT_TIMEOUT if a new reader is ++ * detected with SC_SUCCESS. */ ++ detect_readers = 1; ++ detected_hotplug = 1; + #else + rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; + rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; +@@ -1622,9 +1643,11 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + goto out; + } + ++ *event_reader = NULL; ++ *event = 0; ++ + if (num_watch == 0) { + sc_log(ctx, "No readers available to be watched"); +- *event_reader = NULL; + r = SC_ERROR_NO_READERS_FOUND; + goto out; + } +@@ -1646,7 +1669,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + + /* Scan the current state of all readers to see if they + * match any of the events we're polling for */ +- *event = 0; + for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) { + DWORD state, prev_state; + sc_log(ctx, "'%s' before=0x%08X now=0x%08X", +@@ -1657,51 +1679,72 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + state = rsp->dwEventState; + rsp->dwCurrentState = rsp->dwEventState; + if (state & SCARD_STATE_CHANGED) { +- + /* check for hotplug events */ +- if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) { ++ if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) { + sc_log(ctx, "detected hotplug event"); +- *event |= SC_EVENT_READER_ATTACHED; +- *event_reader = NULL; +- } ++ /* Windows sends hotplug event on both, attaching and ++ * detaching a reader. pcscd only sends it in case of ++ * attaching a reader. We'll detect later in which case we ++ * are. */ ++ detect_readers = 1; ++ detected_hotplug = 1; ++ ++ /* Windows wants us to manually reset the changed state */ ++ rsp->dwEventState &= ~SCARD_STATE_CHANGED; ++ ++ /* By default, ignore a hotplug event as if a timout ++ * occurred, since it may be an unrequested removal or ++ * false alarm. Just continue to loop and check at the end ++ * of this function whether we need to return the attached ++ * reader or not. */ ++ r = SC_ERROR_EVENT_TIMEOUT; ++ } else { ++ sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); ++ if (reader) { ++ /* copy the state so we know what to watch out for */ ++ struct pcsc_private_data *priv = reader->drv_data; ++ priv->reader_state.dwEventState = state; ++ priv->reader_state.dwCurrentState = prev_state; ++ } + +- if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { +- sc_log(ctx, "card inserted event"); +- *event |= SC_EVENT_CARD_INSERTED; +- } ++ if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { ++ sc_log(ctx, "card inserted event"); ++ *event |= SC_EVENT_CARD_INSERTED; ++ } + +- if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { +- sc_log(ctx, "card removed event"); +- *event |= SC_EVENT_CARD_REMOVED; +- } ++ if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { ++ sc_log(ctx, "card removed event"); ++ *event |= SC_EVENT_CARD_REMOVED; ++ } + +- if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { +- sc_log(ctx, "reader detached event"); +- *event |= SC_EVENT_READER_DETACHED; +- } ++ if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { ++ sc_log(ctx, "reader detached event"); ++ *event |= SC_EVENT_READER_DETACHED; ++ detect_readers = 1; ++ } + +- if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { +- sc_log(ctx, "reader re-attached event"); +- *event |= SC_EVENT_READER_ATTACHED; +- } ++ if ((state & SCARD_STATE_IGNORE) && !(prev_state & SCARD_STATE_IGNORE)) { ++ sc_log(ctx, "reader detached event"); ++ *event |= SC_EVENT_READER_DETACHED; ++ detect_readers = 1; ++ } + +- if (*event & event_mask) { +- sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); +- *event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); +- r = SC_SUCCESS; +- goto out; +- } ++ if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { ++ sc_log(ctx, "reader re-attached event"); ++ *event |= SC_EVENT_READER_ATTACHED; ++ detect_readers = 1; ++ } + ++ if (*event & event_mask) { ++ sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); ++ *event_reader = reader; ++ r = SC_SUCCESS; ++ goto out; ++ } else { ++ *event = 0; ++ } ++ } + } +- +- /* No match - copy the state so pcscd knows +- * what to watch out for */ +- /* rsp->dwCurrentState = rsp->dwEventState; */ +- } +- +- if (timeout == 0) { +- r = SC_ERROR_EVENT_TIMEOUT; +- goto out; + } + + /* Set the timeout if caller wants to time out */ +@@ -1713,13 +1756,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + + rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch); + +- if (rv == (LONG) SCARD_E_CANCELLED) { ++ if (rv == (LONG)SCARD_E_CANCELLED) { + /* C_Finalize was called, events don't matter */ + r = SC_ERROR_EVENT_TIMEOUT; + goto out; + } + +- if (rv == (LONG) SCARD_E_TIMEOUT) { ++ if (rv == (LONG)SCARD_E_TIMEOUT) { + r = SC_ERROR_EVENT_TIMEOUT; + goto out; + } +@@ -1731,12 +1774,54 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + } + } + out: +- if (!reader_states) { +- free(rgReaderStates); ++ /* in case of an error re-detect all readers */ ++ if (r < 0 && r != SC_ERROR_EVENT_TIMEOUT) ++ detect_readers = 1; ++ ++ if (detect_readers) { ++ pcsc_detect_readers(ctx); + } +- else if (*reader_states == NULL) { +- sc_log(ctx, "return allocated 'reader states'"); +- *reader_states = rgReaderStates; ++ ++ if (detected_hotplug) { ++ if (gpriv->attached_reader) { ++ if (event_reader && event && !*event) { ++ /* no other event has been detected, yet */ ++ *event_reader = gpriv->attached_reader; ++ *event = SC_EVENT_READER_ATTACHED; ++ r = SC_SUCCESS; ++ } ++ gpriv->attached_reader = NULL; ++ } else if (gpriv->removed_reader) { ++ /* Normally, we only check the hotplug event for attached readers. ++ * However, Windows also notifies on removal. Check, if the latter ++ * was requested by the caller. */ ++ if (event_mask & SC_EVENT_READER_DETACHED ++ && event_reader && event && !*event) { ++ /* no other event has been detected, yet */ ++ *event_reader = gpriv->removed_reader; ++ *event = SC_EVENT_READER_DETACHED; ++ r = SC_SUCCESS; ++ } ++ gpriv->removed_reader = NULL; ++ } else { ++ /* false alarm, there was no reader attached or removed, ++ * avoid re-initialize the reader states by resetting detect_readers */ ++ detect_readers = 0; ++ } ++ } ++ ++ if (detect_readers) { ++ free(rgReaderStates); ++ if (reader_states && *reader_states) ++ *reader_states = NULL; ++ } else { ++ if (!reader_states) { ++ free(rgReaderStates); ++ } ++ else if (*reader_states == NULL) { ++ sc_log(ctx, "return allocated reader states"); ++ *reader_states = rgReaderStates; ++ } + } + + LOG_FUNC_RETURN(ctx, r); +@@ -2449,6 +2534,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + } + + sc_log(ctx, "Probing PC/SC reader"); ++ gpriv->attached_reader = NULL; + + gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle; + card_handle = *(SCARDHANDLE *)pcsc_card_handle; +@@ -2467,6 +2553,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + } else { + _sc_delete_reader(ctx, reader); + } ++ gpriv->attached_reader = reader; + } + + out: +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index afc24353a8..87d66c6721 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -49,26 +49,21 @@ void Sleep(unsigned int Milliseconds) + } + #endif + +-void stop_daemon() +-{ +-#ifdef PCSCLITE_GOOD +- sc_cancel(ctx); +-#endif +- run_daemon = 0; +-} +- + void notify_daemon() + { + int r; +- const unsigned int event_mask = SC_EVENT_CARD_EVENTS; ++ const unsigned int event_mask = SC_EVENT_CARD_EVENTS|SC_EVENT_READER_EVENTS; + unsigned int event; + struct sc_reader *event_reader = NULL; +- size_t error_count = 0; ++ void *reader_states = NULL; ++#ifndef __APPLE__ + /* timeout adjusted to the maximum response time for WM_CLOSE in case + * canceling doesn't work */ + const int timeout = 20000; +- struct sc_atr old_atr; +- void *reader_states = NULL; ++#else ++ /* lower timeout, because Apple doesn't support hotplug events */ ++ const int timeout = 2000; ++#endif + + r = sc_establish_context(&ctx, "opensc-notify"); + if (r < 0 || !ctx) { +@@ -76,50 +71,51 @@ void notify_daemon() + return; + } + +- while (run_daemon && error_count < 1000) { ++ while (run_daemon) { ++ + r = sc_wait_for_event(ctx, event_mask, + &event_reader, &event, timeout, &reader_states); + if (r < 0) { + if (r == SC_ERROR_NO_READERS_FOUND) { +- /* No readers available, PnP notification not supported */ +- Sleep(200); +- } else { +- error_count++; ++ Sleep(timeout); ++ continue; + } +- continue; + } + +- error_count = 0; +- +- if (event & SC_EVENT_CARD_REMOVED) { +- sc_notify_id(ctx, &old_atr, NULL, NOTIFY_CARD_REMOVED); +- } +- if (event & SC_EVENT_CARD_INSERTED) { +- if (event_reader) { +- /* FIXME `pcsc_wait_for_event` has all the information that's +- * requested again with `pcsc_detect_card_presence`, but it +- * doesn't use the ATR, for example, to refresh the reader's +- * attributes. To get the ATR we need to call +- * sc_detect_card_presence. Eventually this should be fixed. */ +- sc_detect_card_presence(event_reader); +- memcpy(old_atr.value, event_reader->atr.value, +- event_reader->atr.len); +- old_atr.len = event_reader->atr.len; +- } else { +- old_atr.len = 0; ++ if (event_reader) { ++ if (event & SC_EVENT_CARD_REMOVED ++ || (event & SC_EVENT_READER_DETACHED ++ && event_reader->flags & SC_READER_CARD_PRESENT)) { ++ /* sc_notify_id uses only the reader's name for displaying on ++ * removal, so use a dummy card here to get that information ++ * into the notification */ ++ struct sc_pkcs15_card p15card; ++ sc_card_t card; ++ memset(&card, 0, sizeof card); ++ card.reader = event_reader; ++ memset(&p15card, 0, sizeof p15card); ++ p15card.card = &card; ++ sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_REMOVED); ++ } else if (event & SC_EVENT_CARD_INSERTED ++ || (event & SC_EVENT_READER_ATTACHED ++ && event_reader->flags & SC_READER_CARD_PRESENT)) { ++ /* sc_notify_id prevers the reader's name for displaying on ++ * insertion, so use a dummy card here to get that information ++ * into the notification */ ++ struct sc_pkcs15_card p15card; ++ sc_card_t card; ++ memset(&card, 0, sizeof card); ++ card.reader = event_reader; ++ memset(&p15card, 0, sizeof p15card); ++ p15card.card = &card; ++ sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_INSERTED); + } +- sc_notify_id(ctx, old_atr.len ? &old_atr : NULL, NULL, +- NOTIFY_CARD_INSERTED); + } + } + + if (ctx) { +- if (error_count >= 1000) { +- sc_log(ctx, "Too many errors; aborting."); +- } + /* free `reader_states` */ + sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states); +- reader_states = NULL; + sc_release_context(ctx); + ctx = NULL; + } +@@ -132,7 +128,8 @@ void notify_daemon() + LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + if (message == WM_CLOSE || message == WM_QUIT) { +- stop_daemon(); ++ run_daemon = 0; ++ sc_cancel(ctx); + return TRUE; + } + +@@ -182,32 +179,54 @@ WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowC + + #else + +-#ifdef HAVE_SIGACTION ++#if defined(HAVE_SIGACTION) && defined(HAVE_PTHREAD) ++#include ++#include + #include ++#include ++ ++static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { +- stop_daemon(); ++ run_daemon = 0; ++ write(cancellation_fd[1], &sig, sizeof sig); + } + +-void set_sa_handler(void) ++static void *cancellation_proc(void *arg) + { +- struct sigaction new_sig, old_sig; ++ (void)arg; ++ while (run_daemon) { ++ int sig; ++ if (sizeof sig == read(cancellation_fd[0], &sig, sizeof sig)) { ++ break; ++ } ++ } ++ sc_cancel(ctx); ++ return NULL; ++} + +- /* Register signal handlers */ ++void setup_cancellation(void) ++{ ++ pthread_t cancellation_thread; ++ struct sigaction new_sig, old_sig; + new_sig.sa_handler = sig_handler; + sigemptyset(&new_sig.sa_mask); + new_sig.sa_flags = SA_RESTART; +- if ((sigaction(SIGINT, &new_sig, &old_sig) < 0) +- || (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) { +- fprintf(stderr, "Failed to create signal handler: %s", strerror(errno)); ++ ++ if (pipe(cancellation_fd) != 0 ++ || (errno = pthread_create(&cancellation_thread, NULL, cancellation_proc, NULL)) != 0 ++ || sigaction(SIGINT, &new_sig, &old_sig) != 0 ++ || sigaction(SIGTERM, &new_sig, &old_sig) != 0) { ++ fprintf(stderr, "Failed to setup cancellation: %s", strerror(errno)); + } + } + + #else + +-void set_sa_handler(void) ++void setup_cancellation(void) + { + } ++ + #endif + + #include "opensc-notify-cmdline.h" +@@ -244,8 +263,8 @@ main (int argc, char **argv) + + if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter) + || cmdline.daemon_mode_counter) { +- set_sa_handler(); + run_daemon = 1; ++ setup_cancellation(); + notify_daemon(); + } else { + /* give the notification process some time to spawn */ +diff --git a/src/ui/strings.c b/src/ui/strings.c +index ea1d3ba650..90dbc0f964 100644 +--- a/src/ui/strings.c ++++ b/src/ui/strings.c +@@ -34,8 +34,12 @@ static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_a + static char text[3*SC_MAX_ATR_SIZE] = {0}; + const char prefix[] = "ATR: "; + +- if (p15card && p15card->card && p15card->card->name) { ++ if (p15card && p15card->card ++ && p15card->card->name) { + return p15card->card->name; ++ } else if (p15card && p15card->card ++ && p15card->card->reader && p15card->card->reader->name) { ++ return p15card->card->reader->name; + } + + if (!atr) +@@ -192,7 +196,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, + str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden)."; + break; + case NOTIFY_CARD_INSERTED: +- if (p15card) { ++ if (p15card && p15card->card && p15card->card->name) { + str = "Smartcard kann jetzt verwendet werden"; + } else { + str = "Smartcard erkannt"; +@@ -260,7 +264,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, + str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds)."; + break; + case NOTIFY_CARD_INSERTED: +- if (p15card) { ++ if (p15card && p15card->card && p15card->card->name) { + str = "Smart card is ready to use"; + } else { + str = "Smart card detected"; + + +From a87c4c68cdc272a65cff0a77b5e48b6b0d921387 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Fri, 5 Jun 2020 14:57:00 +0200 +Subject: [PATCH 1/3] Unbreak wait for events + +By Jabuk Jelen + +Fixes https://github.com/OpenSC/OpenSC/issues/2021 +--- + src/libopensc/reader-pcsc.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index b3da6fc88b..808b75530b 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1700,12 +1700,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + r = SC_ERROR_EVENT_TIMEOUT; + } else { + sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); +- if (reader) { +- /* copy the state so we know what to watch out for */ +- struct pcsc_private_data *priv = reader->drv_data; +- priv->reader_state.dwEventState = state; +- priv->reader_state.dwCurrentState = prev_state; +- } + + if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { + sc_log(ctx, "card inserted event"); + +From fb84c16ebadcefcb4dcd68780a1cbe9adb2671bc Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Fri, 5 Jun 2020 15:50:31 +0200 +Subject: [PATCH 2/3] pcsc: immediately exit on hotplug events + +fixes delayed notification for removed readers + +closes https://github.com/OpenSC/OpenSC/issues/2021 +--- + src/libopensc/reader-pcsc.c | 4 ++++ + src/ui/notify.c | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 808b75530b..56da7816ef 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1741,6 +1741,10 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + } + } + ++ /* if a reader was detected, we need to create a new list of readers */ ++ if (detected_hotplug) ++ goto out; ++ + /* Set the timeout if caller wants to time out */ + if (timeout == -1) { + dwtimeout = INFINITE; +diff --git a/src/ui/notify.c b/src/ui/notify.c +index 90e7778c10..897ea21ca3 100644 +--- a/src/ui/notify.c ++++ b/src/ui/notify.c +@@ -437,6 +437,7 @@ void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr, + #elif defined(ENABLE_NOTIFY) && defined(ENABLE_GIO2) + + #include ++#include "libopensc/log.h" + + static GApplication *application = NULL; + +@@ -481,6 +482,14 @@ static void notify_gio(struct sc_context *ctx, + } + } + ++ if (ctx) { ++ sc_log(ctx, "%s %s %s %s", ++ title ? title : "", ++ text ? text : "", ++ icon ? icon : "", ++ group ? group : ""); ++ } ++ + g_application_send_notification(application, group, notification); + + if (gicon) { + +From 00f7f3d87ed3d5d981440e5f53e8520d067a9864 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Mon, 8 Jun 2020 17:04:49 +0200 +Subject: [PATCH 3/3] pkcs11: fixed notifying twice in case of an attached + reader + +before 14e396273 sc_wait_for_event() only notified in case of a new +reader, but didn't add it to the internal list of readers. That's why +PKCS#11 needed to bail out early in this case (and the application had +to call C_WaitForSlotEvent a second time to actually get the related +slot). Since sc_wait_for_event() can now handle insertion correctly, we +can now immediately check (and reset) the events on the slots. +--- + src/pkcs11/pkcs11-global.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index 671890309f..6985bc21ea 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -730,13 +730,6 @@ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ + sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); + sc_pkcs11_unlock(); + r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); +- if (events & SC_EVENT_READER_ATTACHED) { +- rv = sc_pkcs11_lock(); +- if (rv != CKR_OK) +- return rv; +- +- goto out; +- } + /* Was C_Finalize called ? */ + if (in_finalize == 1) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + +From 4cfa4f334d6cbf3f730b5d6b0e5c0daeeffd2da6 Mon Sep 17 00:00:00 2001 +From: Zoltan Kelemen +Date: Sun, 12 Jul 2020 22:07:13 +0200 +Subject: [PATCH] Fix for issue #1999: - Reset context to undefined handle + value on error since call may alter output parameter. - Continue to assume + -1 as undefined handle value in all PCSC implementations, to keep this fix + as small and surgical as possible. + +--- + src/libopensc/reader-pcsc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 56da7816ef..6443d2a9c9 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -1424,7 +1424,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + if ((rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { + gpriv->SCardReleaseContext(gpriv->pcsc_ctx); +- gpriv->pcsc_ctx = 0; ++ gpriv->pcsc_ctx = -1; + gpriv->pcsc_wait_ctx = -1; + /* reconnecting below may may restart PC/SC service */ + rv = SCARD_E_INVALID_HANDLE; +@@ -1441,6 +1441,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) + + rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); + if (rv != SCARD_S_SUCCESS) { ++ gpriv->pcsc_ctx = -1; + PCSC_LOG(ctx, "SCardEstablishContext failed", rv); + ret = pcsc_to_opensc_error(rv); + goto out; +@@ -1451,7 +1452,8 @@ static int pcsc_detect_readers(sc_context_t *ctx) + } + } while (rv != SCARD_S_SUCCESS); + +- reader_buf = malloc(sizeof(char) * reader_buf_size); ++ /* The +2 below is to make sure we have zero terminators, in case we get invalid data */ ++ reader_buf = calloc(reader_buf_size+2, sizeof(char)); + if (!reader_buf) { + ret = SC_ERROR_OUT_OF_MEMORY; + goto out; +@@ -1629,6 +1631,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + if (gpriv->pcsc_wait_ctx == (SCARDCONTEXT)-1) { + rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_wait_ctx); + if (rv != SCARD_S_SUCCESS) { ++ gpriv->pcsc_wait_ctx = -1; + PCSC_LOG(ctx, "SCardEstablishContext(wait) failed", rv); + r = pcsc_to_opensc_error(rv); + goto out; + + +From 8c5d4ec47f9c3f48bd5b2d7747030b8ffc39a2c6 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:48 +0000 +Subject: [PATCH 1/4] Fix detect_card_presence return value + +In opensc.h the documentation states that the function +detect_card_presence should return 0 if no card is present, which is +reasonable. This was not the case before since more flags could be set +even if SC_READER_CARD_PRESENT is not. This was probably missed before +since more flags has been added since this function was first written. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 99887852d7..54d8cf30c7 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -476,7 +476,12 @@ static int pcsc_detect_card_presence(sc_reader_t *reader) + rv = refresh_attributes(reader); + if (rv != SC_SUCCESS) + LOG_FUNC_RETURN(reader->ctx, rv); +- LOG_FUNC_RETURN(reader->ctx, reader->flags); ++ ++ // Return 0 if the card is not present ++ if (reader->flags & SC_READER_CARD_PRESENT) ++ LOG_FUNC_RETURN(reader->ctx, reader->flags); ++ else ++ LOG_FUNC_RETURN(reader->ctx, 0); + } + + static int check_forced_protocol(sc_reader_t *reader, DWORD *protocol) + +From ffb5c82ea3724462a5a23e6b2b34bec30af4eb70 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:52 +0000 +Subject: [PATCH 2/4] Handle when reader is detached on macOS + +refresh_attributes returns SC_SUCCESS if we can't detect the reader. The +same should happen if the reader is unknown/detached. + +This was found when detaching reader on macOS. Then we don't get +SCARD_E_UNKNOWN_READER from SCardGetStatusChange. We notice it later +from that the state of the reader is SCARD_STATE_UNKNOWN. This resulted +in C_WaitForSlotEvent not noticing that the reader, and thus the card, +was removed. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 54d8cf30c7..40f994a514 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -415,7 +415,8 @@ static int refresh_attributes(sc_reader_t *reader) + * XXX: We'll hit it again, as no readers are removed currently. + */ + reader->flags &= ~(SC_READER_CARD_PRESENT); +- return SC_ERROR_READER_DETACHED; ++ sc_log(reader->ctx, "Reader unknown: %s", sc_strerror(SC_ERROR_READER_DETACHED)); ++ SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + reader->flags &= ~(SC_READER_CARD_CHANGED|SC_READER_CARD_INUSE|SC_READER_CARD_EXCLUSIVE); + +From 20d11ef10abc3728f7eb21c6452e2b373fc4bbb1 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:56 +0000 +Subject: [PATCH 3/4] Fix incorrect use of SC_READER_CARD_CHANGED + +Looking in opensc.h the flag SC_READER_CARD_CHANGED should be set if the +card was exchanged. In other words if a card is present but it is not +the same card as before. It looks like SC_READER_CARD_CHANGED was +misinterpreted as a flag for when the card was removed and thus that the +status has changed. + +Signed-off-by: Frida Flodin +--- + src/libopensc/reader-pcsc.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 40f994a514..664042a199 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -393,10 +393,7 @@ static int refresh_attributes(sc_reader_t *reader) + || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE + #endif + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { +- if (old_flags & SC_READER_CARD_PRESENT) { +- reader->flags |= SC_READER_CARD_CHANGED; +- } +- ++ reader->flags &= ~(SC_READER_CARD_PRESENT); + SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + +@@ -459,8 +456,6 @@ static int refresh_attributes(sc_reader_t *reader) + } + } else { + reader->flags &= ~SC_READER_CARD_PRESENT; +- if (old_flags & SC_READER_CARD_PRESENT) +- reader->flags |= SC_READER_CARD_CHANGED; + } + sc_log(reader->ctx, "card %s%s", + reader->flags & SC_READER_CARD_PRESENT ? "present" : "absent", + +From 26bbbe7bb6ab3198ffb50f7dfb9757b3b3d471a1 Mon Sep 17 00:00:00 2001 +From: Frida Flodin +Date: Wed, 6 Oct 2021 09:05:59 +0000 +Subject: [PATCH 4/4] Sanity check detect_card_presence return value + +The return value from detect_card_presence should be 0 if no card is +present. Therefore the flag SC_READER_CARD_PRESENT is not allowed to be +0 if detect_card_presence has non-zero return value. + +Signed-off-by: Frida Flodin +--- + src/libopensc/sc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c +index 29f6b86895..40b9646fe2 100644 +--- a/src/libopensc/sc.c ++++ b/src/libopensc/sc.c +@@ -337,6 +337,12 @@ int sc_detect_card_presence(sc_reader_t *reader) + LOG_FUNC_RETURN(reader->ctx, SC_ERROR_NOT_SUPPORTED); + + r = reader->ops->detect_card_presence(reader); ++ ++ // Check that we get sane return value from backend ++ // detect_card_presence should return 0 if no card is present. ++ if (r && !(r & SC_READER_CARD_PRESENT)) ++ LOG_FUNC_RETURN(reader->ctx, SC_ERROR_INTERNAL); ++ + LOG_FUNC_RETURN(reader->ctx, r); + } + +From 62cf2c496eec26b7bc6a2c55bb3b9b88db462962 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 2 Sep 2022 16:19:26 +0200 +Subject: [PATCH] Keep pcsc reader flags when disconnected + +When the reader is removed, the reader->flags are set to +SC_READER_REMOVED. card_detect_all() then frees resources and +sets slot->reader to NULL. During this, sc_card_disconnect() +is called, setting reader->flags to 0. In a subsequent call +to card_detect_all() with the reader still removed, the corresponding +slot is reclaimed, and slot->reader set back to the removed reader, +but slot->events is overwritten, which causes the C_WaitForSlot() +not to recognize event on the slot. +--- + src/libopensc/reader-pcsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 1efd8a0d31..40bfd293d3 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -672,7 +672,7 @@ static int pcsc_disconnect(sc_reader_t * reader) + LONG rv = priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action); + PCSC_TRACE(reader, "SCardDisconnect returned", rv); + } +- reader->flags = 0; ++ reader->flags &= SC_READER_REMOVED; + return SC_SUCCESS; + } + + +From c2e00e9071952b30ed6d58d9b7670eb3d93ea6fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +Date: Fri, 20 May 2022 14:26:44 +0300 +Subject: [PATCH] pkcs11-session: fix C_GetSessionInfo in 'atomic' mode + +The device is always in logged-out mode with PIN cached, so ignore +the logged-in check. + +Since the token is now guaranteed to be logged-in or have sessions +removed, simplify the further checks to match the session state. + +Fixes: 4bd8cda96604 "pkcs11-session: When we notice logout in lower layers..." +--- + src/pkcs11/pkcs11-session.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index 7fb9cb36..e9388183 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -252,7 +252,6 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_RV rv; + struct sc_pkcs11_session *session; + struct sc_pkcs11_slot *slot; +- int logged_out; + + if (pInfo == NULL_PTR) + return CKR_ARGUMENTS_BAD; +@@ -276,16 +275,16 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + pInfo->ulDeviceError = 0; + + slot = session->slot; +- logged_out = (slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT); +- if (logged_out && slot->login_user >= 0) { ++ if (!sc_pkcs11_conf.atomic && slot->login_user >= 0 && ++ slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT) { + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + rv = CKR_SESSION_HANDLE_INVALID; + goto out; + } +- if (slot->login_user == CKU_SO && !logged_out) { ++ if (slot->login_user == CKU_SO) { + pInfo->state = CKS_RW_SO_FUNCTIONS; +- } else if ((slot->login_user == CKU_USER && !logged_out) || (!(slot->token_info.flags & CKF_LOGIN_REQUIRED))) { ++ } else if (slot->login_user == CKU_USER || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { + pInfo->state = (session->flags & CKF_RW_SESSION) + ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; + } else { +-- +2.40.1 + + + +From 12ac33d6e0f01a334c792b341b7ea27f10ba0b98 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Wed, 22 Mar 2023 16:19:07 +0100 +Subject: [PATCH 1/6] Add function for getting current card status in PKCS15 + layer + +By using sc_detect_card_presence() function and observing status flags. +--- + src/pkcs11/framework-pkcs15.c | 29 +++++++++++++++++++++++++++++ + src/pkcs11/sc-pkcs11.h | 1 + + 2 files changed, 30 insertions(+) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 97daefcb47..11ea867023 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1401,6 +1401,35 @@ int slot_get_logged_in_state(struct sc_pkcs11_slot *slot) + return logged_in; + } + ++int slot_get_card_state(struct sc_pkcs11_slot *slot) ++{ ++ struct pkcs15_fw_data *fw_data = NULL; ++ struct sc_pkcs15_card *p15card = NULL; ++ int rv = 0; ++ ++ if (slot->p11card == NULL) { ++ goto out; ++ } ++ ++ fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; ++ if (!fw_data) ++ goto out; ++ p15card = fw_data->p15_card; ++ if (!p15card) ++ goto out; ++ ++ if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) ++ goto out; ++ if (rv & SC_READER_CARD_CHANGED) ++ return SC_READER_CARD_CHANGED; ++ else if (rv & SC_READER_REMOVED) ++ return SC_READER_REMOVED; ++ else if (rv & SC_READER_CARD_PRESENT) ++ return SC_READER_CARD_PRESENT; ++out: ++ return 0; ++} ++ + + struct sc_pkcs15_object * + _get_auth_object_by_name(struct sc_pkcs15_card *p15card, char *name) +diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h +index bc7baa7e74..4a8dac8de6 100644 +--- a/src/pkcs11/sc-pkcs11.h ++++ b/src/pkcs11/sc-pkcs11.h +@@ -413,6 +413,7 @@ CK_RV slot_token_removed(CK_SLOT_ID id); + CK_RV slot_allocate(struct sc_pkcs11_slot **, struct sc_pkcs11_card *); + CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask); + int slot_get_logged_in_state(struct sc_pkcs11_slot *slot); ++int slot_get_card_state(struct sc_pkcs11_slot *slot); + + /* Login tracking functions */ + CK_RV restore_login_state(struct sc_pkcs11_slot *slot); + +From 2dcb0ee396c5283380a76fa1c4518176e832e6c0 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Wed, 22 Mar 2023 16:19:25 +0100 +Subject: [PATCH 2/6] Differentiate between changed and logged out card in + C_GetSessionInfo + +Do not delete all sessions, when the card was logged out during operation. +Instead, check whether the card was changed and by logging out only set +correct flag. +--- + src/pkcs11/pkcs11-session.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index e938818376..d32e7a5789 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -253,6 +253,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_RV rv; + struct sc_pkcs11_session *session; + struct sc_pkcs11_slot *slot; ++ int card_status = 0, logged_out = 0; + + if (pInfo == NULL_PTR) + return CKR_ARGUMENTS_BAD; +@@ -275,16 +276,20 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + pInfo->ulDeviceError = 0; + + slot = session->slot; +- if (!sc_pkcs11_conf.atomic && slot->login_user >= 0 && +- slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT) { ++ card_status = slot_get_card_state(slot); ++ if (card_status != SC_READER_CARD_PRESENT) { ++ /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + rv = CKR_SESSION_HANDLE_INVALID; + goto out; + } +- if (slot->login_user == CKU_SO) { ++ ++ /* Check whether the user is logged in the card */ ++ logged_out = (slot_get_logged_in_state(slot) == SC_PIN_STATE_LOGGED_OUT); ++ if (slot->login_user == CKU_SO && !logged_out) { + pInfo->state = CKS_RW_SO_FUNCTIONS; +- } else if (slot->login_user == CKU_USER || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { ++ } else if ((slot->login_user == CKU_USER && !logged_out) || !(slot->token_info.flags & CKF_LOGIN_REQUIRED)) { + pInfo->state = (session->flags & CKF_RW_SESSION) + ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; + } else { + +From c528c27616881e6cc3afef2da50193603a572c00 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +Date: Fri, 14 Apr 2023 14:52:10 +0200 +Subject: [PATCH 3/6] Return all flags when checking the card presence + +--- + src/pkcs11/framework-pkcs15.c | 7 +------ + src/pkcs11/pkcs11-session.c | 2 +- + 2 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 11ea867023..e35324c805 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1420,12 +1420,7 @@ int slot_get_card_state(struct sc_pkcs11_slot *slot) + + if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) + goto out; +- if (rv & SC_READER_CARD_CHANGED) +- return SC_READER_CARD_CHANGED; +- else if (rv & SC_READER_REMOVED) +- return SC_READER_REMOVED; +- else if (rv & SC_READER_CARD_PRESENT) +- return SC_READER_CARD_PRESENT; ++ return rv; + out: + return 0; + } +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index d32e7a5789..01ce7676c9 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -277,7 +277,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + + slot = session->slot; + card_status = slot_get_card_state(slot); +- if (card_status != SC_READER_CARD_PRESENT) { ++ if (!(card_status & SC_READER_CARD_PRESENT)) { + /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + +From 3d21cba957cc6972a1a672e8a508e1e6b5f5bba1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 9 May 2023 09:52:51 +0200 +Subject: [PATCH 4/6] Remove session when card is changed + +--- + src/pkcs11/pkcs11-session.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c +index 01ce7676c9..68b6c57b8d 100644 +--- a/src/pkcs11/pkcs11-session.c ++++ b/src/pkcs11/pkcs11-session.c +@@ -277,7 +277,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ + + slot = session->slot; + card_status = slot_get_card_state(slot); +- if (!(card_status & SC_READER_CARD_PRESENT)) { ++ if (!(card_status & SC_READER_CARD_PRESENT) || card_status & SC_READER_CARD_CHANGED) { + /* Card was removed or reinserted, invalidate all sessions */ + slot->login_user = -1; + sc_pkcs11_close_all_sessions(session->slot->id); + +From ecd845c2f7190afc46f39ebbae0dda7b55019994 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 9 May 2023 09:53:20 +0200 +Subject: [PATCH 5/6] Fix PCSC handling when reader is removed + +--- + src/libopensc/reader-pcsc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 04d5ac8fdd..8c2f98c9b1 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -364,7 +364,7 @@ static int refresh_attributes(sc_reader_t *reader) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + +- if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) { ++ if (priv->reader_state.szReader == NULL || reader->flags & SC_READER_REMOVED) { + priv->reader_state.szReader = reader->name; + priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; + priv->reader_state.dwEventState = SCARD_STATE_UNAWARE; +@@ -394,6 +394,8 @@ static int refresh_attributes(sc_reader_t *reader) + #endif + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { + reader->flags &= ~(SC_READER_CARD_PRESENT); ++ reader->flags |= SC_READER_REMOVED; ++ priv->gpriv->removed_reader = reader; + SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + +From d04ec3ea3c7cb3b47de28492b4eea5ed1be2cc0c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Thu, 18 May 2023 14:18:04 +0200 +Subject: [PATCH 6/6] Remove unnecessary goto statement + +--- + src/pkcs11/framework-pkcs15.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index e35324c805..9c7ec67fb4 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1408,21 +1408,19 @@ int slot_get_card_state(struct sc_pkcs11_slot *slot) + int rv = 0; + + if (slot->p11card == NULL) { +- goto out; ++ return 0; + } + + fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; + if (!fw_data) +- goto out; ++ return 0; + p15card = fw_data->p15_card; + if (!p15card) +- goto out; ++ return 0; + + if ((rv = sc_detect_card_presence(p15card->card->reader)) <= 0) +- goto out; ++ return 0; + return rv; +-out: +- return 0; + } + + + +From 5e79a2a4abdd523cfff19824718bbb0d8ced7320 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 9 Apr 2020 16:29:44 +0200 +Subject: [PATCH] fixed compiler warning + +--- + src/tools/opensc-notify.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 87d66c67..b1afc62d 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,7 +189,9 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; +- write(cancellation_fd[1], &sig, sizeof sig); ++ if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { ++ fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); ++ } + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 843779fe6e0f345f483f9ce9c9739913502391eb Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 23 Apr 2020 08:45:24 +0200 +Subject: [PATCH] opensc-notify: respect signal safety + +Thanks, Marcin. +https://github.com/OpenSC/OpenSC/commit/5e79a2a4abdd523cfff19824718bbb0d8ced7320#r38486829 +--- + src/tools/opensc-notify.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index b1afc62d..75767aba 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,9 +189,7 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; +- if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { +- fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); +- } ++ (void)write(cancellation_fd[1], &sig, sizeof sig); + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 7936bdef15c71139a6a6159cabaf9e6101565add Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 29 Apr 2020 01:25:33 +0200 +Subject: [PATCH] resolve unused variable warning on newer gcc + +--- + src/tools/opensc-notify.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 75767aba..3b61c498 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -189,7 +189,10 @@ static int cancellation_fd[] = {-1, -1}; + + void sig_handler(int sig) { + run_daemon = 0; ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-variable" + (void)write(cancellation_fd[1], &sig, sizeof sig); ++#pragma GCC diagnostic pop + } + + static void *cancellation_proc(void *arg) +-- +2.40.1 + +From 1202eceeefd5ffab45648d41ed0a3076cac10920 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 29 Apr 2020 15:16:31 +0200 +Subject: [PATCH] fixed wrong error + +--- + src/tools/opensc-notify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c +index 3b61c498..c67212b3 100644 +--- a/src/tools/opensc-notify.c ++++ b/src/tools/opensc-notify.c +@@ -190,7 +190,7 @@ static int cancellation_fd[] = {-1, -1}; + void sig_handler(int sig) { + run_daemon = 0; + #pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wunused-variable" ++#pragma GCC diagnostic ignored "-Wunused-result" + (void)write(cancellation_fd[1], &sig, sizeof sig); + #pragma GCC diagnostic pop + } +-- +2.40.1 + + +From 295f399304644e6b0acde267ac410d0aae4a1aee Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 24 Apr 2020 10:18:03 +0200 +Subject: [PATCH] reader-pcsc: Avoid use after free (CID 355473) + +--- + src/libopensc/reader-pcsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 34dc821bf..b3da6fc88 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -2550,10 +2550,10 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c + priv->pcsc_card = card_handle; + detect_protocol(reader, card_handle); + detect_reader_features(reader, card_handle); ++ gpriv->attached_reader = reader; + } else { + _sc_delete_reader(ctx, reader); + } +- gpriv->attached_reader = reader; + } + + out: +-- +2.41.0 + +From ca01aa7a8edc8280a5ceadebb472c2e3c198d8c2 Mon Sep 17 00:00:00 2001 +From: Peter Popovec +Date: Thu, 20 Jan 2022 12:26:19 +0100 +Subject: [PATCH] Coverity Scan fix, CID 374840: Null pointer dereferences + (REVERSE_INULL) + + modified: src/pkcs11/slot.c +--- + src/pkcs11/slot.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c +index ea8a3ac2a..86cb3b884 100644 +--- a/src/pkcs11/slot.c ++++ b/src/pkcs11/slot.c +@@ -69,15 +69,17 @@ static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) + CK_UTF8CHAR slotDescription[64]; + CK_UTF8CHAR manufacturerID[32]; + ++ if (reader == NULL) ++ return NULL; + strcpy_bp(slotDescription, reader->name, 64); + strcpy_bp(manufacturerID, reader->vendor, 32); + + /* Locate a slot related to the reader */ + for (i = 0; ireader == reader) + return slot; +- if (slot->reader == NULL && reader != NULL ++ if (slot->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 +-- +2.41.0 + diff --git a/SPECS/opensc.spec b/SPECS/opensc.spec index e7a2759..61c4a68 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -3,7 +3,7 @@ Name: opensc Version: 0.20.0 -Release: 4%{?dist} +Release: 6%{?dist} Summary: Smart card library and applications Group: System Environment/Libraries @@ -32,6 +32,28 @@ Patch15: opensc-0.20.0-calloc0.patch # https://github.com/OpenSC/OpenSC/pull/2148 # + configuration change by default Patch16: opensc-0.20.0-file-cache.patch +# https://github.com/OpenSC/OpenSC/pull/1929 +Patch17: opensc-0.20.0-idprime.patch +# https://github.com/OpenSC/OpenSC/pull/2787 +Patch18: opensc-0.20.0-CVE-2023-2977.patch +# 31d8c2dfd14ed01b430def2f46cc718ef4b595fc +# 8f4a6c703b5ae7d4f44cf33c85330171afa917bf +# https://github.com/OpenSC/OpenSC/pull/1970 without the first and last commits +# https://github.com/OpenSC/OpenSC/pull/1923 +# https://github.com/OpenSC/OpenSC/pull/2051 +# https://github.com/OpenSC/OpenSC/pull/2077 +# https://github.com/OpenSC/OpenSC/pull/2418 +# https://github.com/OpenSC/OpenSC/pull/2600 +# c2e00e9071952b30ed6d58d9b7670eb3d93ea6fb +# https://github.com/OpenSC/OpenSC/pull/2740 +## OpenSC notify build issues +# 5e79a2a4abdd523cfff19824718bbb0d8ced7320 +# 843779fe6e0f345f483f9ce9c9739913502391eb +# 7936bdef15c71139a6a6159cabaf9e6101565add +# 1202eceeefd5ffab45648d41ed0a3076cac10920 +# 295f399304644e6b0acde267ac410d0aae4a1aee +# ca01aa7a8edc8280a5ceadebb472c2e3c198d8c2 +Patch19: opensc-0.20.0-reader-removal.patch BuildRequires: pcsc-lite-devel @@ -71,6 +93,9 @@ every software/card that does so, too. %patch14 -p1 -b .padding %patch15 -p1 -b .calloc0 %patch16 -p1 -b .file-cache +%patch17 -p1 -b .idprime +%patch18 -p1 -b .CVE-2023-2977 +%patch19 -p1 -b .reader-removal cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . @@ -229,6 +254,14 @@ fi %changelog +* Tue Jul 11 2023 Jakub Jelen - 0.20.0-6 +- Fix introduced issues tagged by coverity (RHEL-765) + +* Thu Jun 15 2023 Jakub Jelen - 0.20.0-5 +- Avoid potential crash because of missing list terminator (#2196234) +- Fix CVE-2023-2977: potential buffer overrun in pkcs15 cardos_have_verifyrc_package (#2211093) +- Backport upstream changes regarding to reader removal (#2097048) + * Fri Nov 20 2020 Jakub Jelen - 0.20.0-4 - Use file cache by default (#1892810) - Avoid calloc with 0 argument (#1895401)