LudovicRousseau / pcsc-tools

Some tools to be used with smart cards and PC/SC
https://pcsc-tools.apdu.fr/
GNU General Public License v2.0
185 stars 63 forks source link

SCardGetStatusChange for PNP notification return SCARD_E_TIMEOUT #76

Open totti0858 opened 1 year ago

totti0858 commented 1 year ago

For the latest pcsc_scan.c file, I add code at 528 line to check the SCardGetStatusChange return value for the PNP notification, but unfortunately the return value is SCARD_E_TIMEOUT but not SCARD_S_SUCCESS. (my local pcsc-lite version is 1.8.23 and ubuntu Linux)

_rgReaderStates[0].szReader = "\\?PnP?\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;

rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1); printf("SCardGetStatusChange for PNP notification result = %lu\n", rv)_

I think it should be SCARD_S_SUCCESS but not this SCARD_E_TIMEOUT value. Do you know why and do you have the plan to fix this issue?

totti0858 commented 1 year ago

I also compiled the same project under the Windows platform and found that the SCardGetStatusChange for PNP notification returns the right value SCARD_S_SUCCESS as expected after run it under Windows platform.

This difference under different platforms may cause issue under VDI user scenario.

LudovicRousseau commented 1 year ago

I can't reproduce your behavior on Windows. I used this Python program:

#! /usr/bin/env python3

#   SCardGetStatusChange.py : Unitary test for SCardGetStatusChange()
#   Copyright (C) 2023  Ludovic Rousseau
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, see <http://www.gnu.org/licenses/>.

from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *

hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
    raise EstablishContextException(hresult)

reader="\\\\?PnP?\\Notification"
readerstates = {}
readerstates[reader] = (reader, SCARD_STATE_UNAWARE)
hresult, newstates = SCardGetStatusChange(hcontext, 0,
        list(readerstates.values()))
if hresult != SCARD_S_SUCCESS:
    raise BaseSCardException(hresult)

hresult = SCardReleaseContext(hcontext)
print("SCardReleaseContext()", SCardGetErrorMessage(hresult))
if hresult != SCARD_S_SUCCESS:
    raise ReleaseContextException(hresult)

And on Windows I get:

(base) C:\Users\Ludovic\Downloads>python SCardGetStatusChange.py
Traceback (most recent call last):
  File "C:\Users\Ludovic\Downloads\SCardGetStatusChange.py", line 33, in <module>
    raise BaseSCardException(hresult)
smartcard.pcsc.PCSCExceptions.BaseSCardException: scard exception: Le délai d’attente spécifié par l’utilisateur a expiré.  (0x8010000A)

I receive 0x8010000A (SCARD_E_TIMEOUT) and not 0 (SCARD_S_SUCCESS).

In your program I note you use _rgReaderStates[0] and also rgReaderStates[0] (without the _). Maybe the problem is a bug in your code.

totti0858 commented 1 year ago

Just as the way you mentioned how to compile the pcsc_scan.exe for Windows (https://ludovicrousseau.blogspot.com/2017/05/pcscscan-on-windows.html), I had compile it and put the exe into the attachment file.

Please see the attached screen, you can see the log screen shot:

Screen Shot 2023-04-10 at 10 37 22 AM

git-modify.zip you can use the compiled pcsc_scan exe to verify the result.

Why the SCardGetStatusChange has the different result under Linux and Windows platform?

LudovicRousseau commented 1 year ago

Do not send me binary program. Send me the patch you used instead.

On my side I tried with this patch:

--- pcsc_scan.c 2023-02-11 12:33:09.000000000 +0100
+++ pcsc_scan.c 2023-04-10 11:09:24.000000000 +0200
@@ -525,6 +527,7 @@
    rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;

    rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1);
+   printf("rv: %lx\n", rv);
    if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
    {
        if (Options.verbose)

And I confirm the returned value is SCARD_E_TIMEOUT on my Winows 10. I get:

$ ./pcsc_scan.exe
PC/SC device scanner
V 1.6.2 (c) 2001-2022, Ludovic Rousseau <ludovic.rousseau@free.fr>
Press shift key to quit
rv: 8010000a
Using reader plug'n play mechanism
totti0858 commented 1 year ago

It is true that I modify the code as your patch do: adding printf("SCardGetStatusChange for PNP notification result = %lu\n", rv) at line 528.

But when I run the pcsc_scan.exe on my desktop win10 and win11, the result always zero.

would you like to try the binary I provided on your desktop?

LudovicRousseau commented 1 year ago

Send me your source code instead. A binary program is useless for me since I do not know what code is really executed.

totti0858 commented 1 year ago

/home/test/pcsc-tools-master $ diff pcsc_scan.c pcsc_scan.backout 528d527 < printf("SCardGetStatusChange for PNP notification result = %lx\n", rv);

I also attach the zip file that include the modified .c file compiled exe. Please have a try on your windows. git.zip

for sure when execute the pcsc_scan.exe app, I had attached the physical smart card reader& card to the Windows machine.

LudovicRousseau commented 1 year ago

I see the problem. With your program and no smart card reader connected I get:

C:\Users\Ludovic\Documents\git\git>pcsc_scan.exe
PC/SC device scanner
V 1.6.2 (c) 2001-2022, Ludovic Rousseau <ludovic.rousseau@free.fr>
Press shift key to quit
SCardGetStatusChange for PNP notification result = 8010000a
Using reader plug'n play mechanism
Scanning present readers...

I get the expected SCARD_E_TIMEOUT.

But if I connect a reader before running pcsc_scan.exe I get:

C:\Users\Ludovic\Documents\git\git>pcsc_scan.exe
PC/SC device scanner
V 1.6.2 (c) 2001-2022, Ludovic Rousseau <ludovic.rousseau@free.fr>
Press shift key to quit
SCardGetStatusChange for PNP notification result = 0
Using reader plug'n play mechanism
Scanning present readers...
0: Gemplus USB SmartCard Reader 0

Wed Apr 12 14:59:31 2023
 Reader 0: Gemplus USB SmartCard Reader 0
  Event number: 1
  Card state: Card inserted,
  ATR: 3B A7 00 40 18 80 65 A2 08 01 01 52
 Reader 1: \\?PnP?\Notification
  Event number: 1
  Card state:

I get the surprising SCARD_S_SUCCESS.

This is surprising because in the two cases only the special reader \\?PnP?\Notification is used in SCardGetStatusChange(). So the other reader should not have any impact. I consider this a Windows bug, unless this behaviour is documented somewhere.

What do you think?

totti0858 commented 1 year ago

Yes, typical user scenario is that the physical smart card reader are attached before the pcsc_scan.exe executed. I think this is the expected result that return SCARD_S_SUCCESS at this scenario under Windows platform.

Here I want to say the Under Linux platform the pcsc_scan return SCARD_E_TIMEOUT is a bad case. how can we fix this issue?

LudovicRousseau commented 1 year ago

For me it is a bug on Windows. If you think different then please provide technical arguments corresponding to the function documentation.

Why is it important for you to change the behavior of SCardGetStatusChange()?