diff --git a/configure.ac b/configure.ac index 6c9fe41..6ac9432 100644 --- a/configure.ac +++ b/configure.ac @@ -218,6 +218,10 @@ AS_IF([test "x$enable_smartcard" != "xno"], [ exit 1 fi + AC_MSG_CHECKING([for PCSC-lite >= 1.6.0 (PnP/Notifications support)]) + PKG_CHECK_MODULES(PNP_NOTIFICATIONS, libpcsclite >= 1.6.0, [WITH_PNP_NOTIFICATIONS=1], [WITH_PNP_NOTIFICATIONS=0]) + AC_DEFINE(WITH_PNP_NOTIFICATIONS) + AC_MSG_CHECKING([for old version of PCSC]) AC_TRY_LINK([ #include diff --git a/proto.h b/proto.h index ac9242d..ca87d63 100644 --- a/proto.h +++ b/proto.h @@ -360,6 +360,7 @@ void scard_unlock(int lock); int scard_enum_devices(uint32 * id, char *optarg); void scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out); void scard_reset_state(); +void scard_release_all_contexts(void); /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/rdpdr.c b/rdpdr.c index 65c92da..894f4a2 100644 --- a/rdpdr.c +++ b/rdpdr.c @@ -879,6 +879,30 @@ rdpdr_process(STREAM s) g_client_id = 0x815ed39d; /* IP address (use 127.0.0.1) 0x815ed39d */ g_epoch++; +#if WITH_SCARD + /* + * We need to release all SCARD contexts to end all + * current transactions and pending calls + */ + scard_release_all_contexts(); + + /* + * According to [MS-RDPEFS] 3.2.5.1.2: + * + * If this packet appears after a sequence of other packets, + * it is a signal that the server has reconnected to a new session + * and the whole sequence has been reset. The client MUST treat + * this packet as the beginning of a new sequence. + * The client MUST also cancel all outstanding requests and release + * previous references to all devices. + * + * If any problem arises in the future, please, pay attention to the + * "If this packet appears after a sequence of other packets" part + * + */ + +#endif + rdpdr_send_client_announce_reply(); rdpdr_send_client_name_request(); break; diff --git a/scard.c b/scard.c index 6622318..65297c9 100644 --- a/scard.c +++ b/scard.c @@ -4,6 +4,7 @@ Copyright (C) Alexi Volkov 2006 Copyright 2010-2013 Pierre Ossman for Cendio AB Copyright 2011-2017 Henrik Andersson for Cendio AB + Copyright 2015 Rostislav Kondratenko Copyright 2017 Karl Mikaelsson for Cendio AB Copyright 2018 Alexander Zakharov @@ -683,8 +684,6 @@ TS_SCardEstablishContext(STREAM in, STREAM out) MYPCSC_DWORD rv; MYPCSC_SCARDCONTEXT myHContext; SERVER_SCARDCONTEXT hContext; - char *readers = NULL; - DWORD readerCount = 1024; hContext = 0; @@ -705,21 +704,6 @@ TS_SCardEstablishContext(STREAM in, STREAM out) goto bail_out; } - /* This is a workaround where windows application generally - behaves better with polling of smartcard subsystem - availability than were there are no readers available. */ - rv = SCardListReaders(myHContext, NULL, readers, &readerCount); - if (rv != SCARD_S_SUCCESS) - { - logger(SmartCard, Debug, - "TS_SCardEstablishContext(), No readers connected, return no service to client."); - rv = SCARD_E_NO_SERVICE; - SCardReleaseContext(myHContext); - goto bail_out; - } - - - /* add context to list of handle and get server handle */ _scard_handle_list_add(myHContext); hContext = _scard_handle_list_get_server_handle(myHContext); @@ -779,9 +763,6 @@ TS_SCardIsValidContext(STREAM in, STREAM out) MYPCSC_DWORD rv; SERVER_SCARDCONTEXT hContext; MYPCSC_SCARDCONTEXT myHContext; - char *readers; - DWORD readerCount = 1024; - PMEM_HANDLE lcHandle = NULL; in->p += 0x1C; in_uint32_le(in, hContext); @@ -791,13 +772,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out) logger(SmartCard, Debug, "TS_SCardIsValidContext(), context: 0x%08x [0x%lx]", (unsigned) hContext, myHContext); - /* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */ - - readers = SC_xmalloc(&lcHandle, 1024); - if (!readers) - return SC_returnNoMemoryError(&lcHandle, in, out); - - rv = SCardListReaders(myHContext, NULL, readers, &readerCount); + rv = SCardIsValidContext(myHContext); if (rv) { @@ -813,7 +788,6 @@ TS_SCardIsValidContext(STREAM in, STREAM out) } outForceAlignment(out, 8); - SC_xfreeallmemory(&lcHandle); return rv; } @@ -1231,8 +1205,10 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide) inString(&lcHandle, in, (char **) &(cur->szReader), dataLength, wide)); +#if !WITH_PNP_NOTIFICATIONS if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0) cur->dwCurrentState |= SCARD_STATE_IGNORE; +#endif } logger(SmartCard, Debug, @@ -2752,3 +2728,25 @@ scard_reset_state() queueFirst = queueLast = NULL; } + +void scard_release_all_contexts(void) +{ + _scard_handle_list_t *item, *next; + + item = g_scard_handle_list; + + while (item) + { + /* Cancelling ScardGetStatusChange calls */ + SCardCancel(item->handle); + /* releasing context to end all transactions on it */ + SCardReleaseContext(item->handle); + + next = item->next; + xfree(item); + item = next; + } + + g_scard_handle_list = NULL; +} +