2174 lines
76 KiB
Diff
2174 lines
76 KiB
Diff
From 31d8c2dfd14ed01b430def2f46cc718ef4b595fc Mon Sep 17 00:00:00 2001
|
|
From: Frank Morgner <frankmorgner@gmail.com>
|
|
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; i<list_size(&virtual_slots); i++) {
|
|
- slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
|
- slot->flags &= ~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; i<list_size(&virtual_slots); i++) {
|
|
- slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
|
- slot->id = (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 <frankmorgner@gmail.com>
|
|
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 <deengert@gmail.com>
|
|
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; j<list_size(&virtual_slots); j++) {
|
|
+ slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
|
|
+ if (slot->reader == 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; j<list_size(&virtual_slots); j++) {
|
|
+ slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
|
|
+ if (slot->reader == 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 <frankmorgner@gmail.com>
|
|
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; j<list_size(&virtual_slots); j++) {
|
|
- slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
|
|
- if (slot->reader == 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; j<list_size(&virtual_slots); j++) {
|
|
- slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j);
|
|
- if (slot->reader == 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 <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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; 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
|
|
diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c
|
|
index 2fb495d295..bf91b6bc57 100644
|
|
--- a/src/pkcs11/slot.c
|
|
+++ b/src/pkcs11/slot.c
|
|
@@ -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");
|
|
|
|
From 61a2c6aaff0aa3add222f8560a8075637ee9b1fd Mon Sep 17 00:00:00 2001
|
|
From: Frank Morgner <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <errno.h>
|
|
+#include <pthread.h>
|
|
#include <signal.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+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 <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <gio/gio.h>
|
|
+#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 <frankmorgner@gmail.com>
|
|
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 <zoltan.kelemen@saabgroup.com>
|
|
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 <frifl@cendio.se>
|
|
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 <frifl@cendio.se>
|
|
---
|
|
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 <frifl@cendio.se>
|
|
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 <frifl@cendio.se>
|
|
---
|
|
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 <frifl@cendio.se>
|
|
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 <frifl@cendio.se>
|
|
---
|
|
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 <frifl@cendio.se>
|
|
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 <frifl@cendio.se>
|
|
---
|
|
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 <vhanulik@redhat.com>
|
|
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?= <timo.teras@iki.fi>
|
|
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 <xhanulik@fi.muni.cz>
|
|
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 <xhanulik@fi.muni.cz>
|
|
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 <xhanulik@fi.muni.cz>
|
|
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?= <vhanulik@redhat.com>
|
|
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?= <vhanulik@redhat.com>
|
|
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?= <vhanulik@redhat.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <frankmorgner@gmail.com>
|
|
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 <jjelen@redhat.com>
|
|
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 <popovec.peter@gmail.com>
|
|
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; 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
|
|
+ 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
|
|
|