[Pcsclite-muscle] Fail to detect smartcard from reconnected reader
Thomas Bajer
thomas.bajer
Fri Jul 21 04:46:33 PDT 2017
Hello,
I would like to report an error, which occurs, when using PCSC-lite for
smartcard detection in C. It causes the smartcard to remain undetected,
when the reader is disconnected. The current workaround is to restart
the PCSC deamon at the beginning.
In my application the removal of the reader is unavoidable, since I am
using a USB token, which acts as a combination of a reader and a smartcard.
Please have a look at the attached minimal example code. The program
checks, whether a reader an a card are available, then connects to the
smartcard. Afterwards, the smartcard is diconnected and the program
waits until the smartcard is no longer physically connected. This
process is being looped until the programm is aborted.
The code was linked with the newest stable release, 1.8.22-1.
The code is compiled and linked on a FreeBSD system running FreeBSD 10.3
(AMD64), the executable is then copied to a pfsense Box which also runs
FreeBSD 10.3 with the same pcscd version.
It would be great if a developer could look at this and commit a fix for
this message.
Below is the exampleReconnect.c example and the build command. Feel free
to play around with it and to make use of the defines at the beginning
of the code
Regards,
Thomas Bajer
/*
* exampleReconnect.c
*
* Created on: 20.07.2017
* Author: T. Bajer
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//#include <usb.h>
#include <errno.h>
#include <stdint.h>
#ifdef __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#else
#include <winscard.h>
#endif
/*
############################################################################################
* #### BUILD COMMAND:
####
* #### gcc -o example exampleReconnect.c -I/usr/local/include/PCSC
-lpcsclite -lusb -Wall ####
*
############################################################################################
*/
/* Uncomment me for more details */
//#define SC_DEBUG
/* Uncomment me to make it work */
//#define HOTFIX
/*
* Prototypes
*/
int connectToSmartcard( SCARDCONTEXT *hContext,
SCARDHANDLE *hCard,
LPTSTR *mszReaders);
void disconnectSmartcard( SCARDCONTEXT *hContext,
SCARDHANDLE *hCard,
LPTSTR *mszReaders);
void waitForSmartcardConnect();
void waitForSmartcardDisconnect();
/*
* MAIN function
*/
int main(int argc, char **argv)
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
LPTSTR mszReaders;
printf("Smartcard detection started.\n");
for(;;)
{
printf("Waiting for smartcard connect...\n");
#ifdef HOTFIX
system("service pcscd restart");
#endif
waitForSmartcardConnect();
printf("Smartcard found.\n");
printf("Connecting to smartcard...\n");
if(connectToSmartcard(&hContext, &hCard, &mszReaders) == 0)
{
printf("Connecting successful!\n");
/*
* Do SC stuff here
*/
printf("Disconnecting...\n");
disconnectSmartcard(&hContext, &hCard, &mszReaders);
printf("Disconnected!\n");
}
else
{
printf("CONNECT FAILED!\n");
}
printf("Waiting for smartcard disconnect...\n");
waitForSmartcardDisconnect();
printf("Smartcard lost!\n");
}
return 0;
}
/*
* Implementations
*/
int connectToSmartcard( SCARDCONTEXT *hContext,
SCARDHANDLE *hCard,
LPTSTR *mszReaders)
{
LONG rv = 0;
DWORD dwReaders, dwActiveProtocol ;
// Init context
printf("Establish context\n");
rv = SCardEstablishContext( SCARD_SCOPE_SYSTEM,
NULL,
NULL, hContext);
if (SCARD_S_SUCCESS != rv)
{
return -1;
}
// Get available smartcard readers
#ifdef SCARD_AUTOALLOCATE
dwReaders = SCARD_AUTOALLOCATE;
printf("List readers\n");
rv = SCardListReaders( *hContext,
NULL,
(LPTSTR)mszReaders,
&dwReaders);
if (SCARD_S_SUCCESS != rv)
{
SCardReleaseContext(*hContext);
return -1;
}
#else
printf("List readers\n");
rv = SCardListReaders( *hContext,
NULL,
NULL,
&dwReaders);
if (SCARD_S_SUCCESS != rv)
{
SCardReleaseContext(*hContext);
return -1;
}
printf("Allocate readers\n");
mszReaders = calloc(dwReaders, sizeof(char));
rv = SCardListReaders( *hContext,
NULL,
*mszReaders,
&dwReaders );
if(SCARD_S_SUCCESS != rv)
{
SCardFreeMemory( *hContext, mszReaders );
SCardReleaseContext( *hContext );
return -1;
}
#endif
printf( "Connect to card\n" );
// Connect to smartcard
rv = SCardConnect( *hContext,
*mszReaders,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
hCard,
&dwActiveProtocol );
if (SCARD_S_SUCCESS != rv)
{
SCardFreeMemory( *hContext, *mszReaders );
SCardReleaseContext( *hContext );
return -1;
}
printf( "Smartcard connected!\n" );
return 0;
}
void disconnectSmartcard( SCARDCONTEXT *hContext,
SCARDHANDLE *hCard,
LPTSTR *mszReaders)
{
printf("Disconnect card...\n");
SCardDisconnect( *hCard, SCARD_LEAVE_CARD );
printf("Free reader...\n");
#ifdef SCARD_AUTOALLOCATE
SCardFreeMemory( *hContext, *mszReaders );
#else
free( *mszReaders );
#endif
printf( "Release context...\n" );
SCardReleaseContext( *hContext );
}
int checkSmartcard( SCARDCONTEXT *hContext,
SCARDHANDLE *hCard,
LPTSTR *mszReaders)
{
LONG rv = 0;
DWORD dwReaders, dwActiveProtocol;
// Init context
#ifdef SC_DEBUG
printf("Establishing SC context...\n");
#endif
rv = SCardEstablishContext( SCARD_SCOPE_SYSTEM,
NULL,
NULL,
hContext);
if (SCARD_S_SUCCESS != rv)
{
#ifdef SC_DEBUG
printf("ERROR: Establishing SC context!\n");
#endif
}
// Get available smartcard readers
#ifdef SCARD_AUTOALLOCATE
if (SCARD_S_SUCCESS == rv)
{
dwReaders = SCARD_AUTOALLOCATE;
#ifdef SC_DEBUG
printf("Listing SC readers...\n");
#endif
rv = SCardListReaders( *hContext,
NULL,
(LPTSTR)mszReaders,
&dwReaders );
if (SCARD_S_SUCCESS != rv)
{
#ifdef SC_DEBUG
printf("ERROR: Listing SC readers!\n");
#endif
/* Max: this has to be given by value, not by pointer! (even if it
doesn't make sense..) */
SCardReleaseContext(*hContext);
}
}
#else
if (SCARD_S_SUCCESS == rv)
{
#ifdef SC_DEBUG
printf("Listing SC readers...\n");
#endif
rv = SCardListReaders( *hContext,
NULL,
NULL,
&dwReaders);
if (SCARD_S_SUCCESS != rv)
{
#ifdef SC_DEBUG
printf("ERROR: Listing SC readers!\n");
#endif
SCardReleaseContext( *hContext );
}
}
if (SCARD_S_SUCCESS == rv)
{
#ifdef SC_DEBUG
printf( "Listing SC readers...\n" );
#endif
mszReaders = calloc( dwReaders, sizeof(char) );
rv = SCardListReaders( *hContext,
NULL,
*mszReaders,
&dwReaders );
if(SCARD_S_SUCCESS != rv)
{
#ifdef SC_DEBUG
printf( "ERROR: Listing SC readers!\n" );
#endif
SCardFreeMemory( *hContext, *mszReaders );
SCardReleaseContext( *hContext );
}
}
#endif
if (SCARD_S_SUCCESS == rv)
{
#ifdef SC_DEBUG
printf( "Connecting to SC...\n" );
#endif
rv = SCardConnect( *hContext,
*mszReaders,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
hCard,
&dwActiveProtocol);
if (SCARD_S_SUCCESS != rv)
{
#ifdef SC_DEBUG
printf("ERROR: Connecting to SC!\n");
#endif
}
}
SCardFreeMemory(*hContext, *mszReaders);
SCardReleaseContext(*hContext);
fflush(stdout);
return rv;
}
void waitForSmartcardConnect()
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
LPTSTR mszReaders;
while(checkSmartcard(&hContext, &hCard, &mszReaders) != 0)
{
sleep(1);
}
}
void waitForSmartcardDisconnect()
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
LPTSTR mszReaders;
while(checkSmartcard(&hContext, &hCard, &mszReaders) == 0)
{
sleep(1);
}
}
More information about the pcsclite-muscle
mailing list