[Pcsclite-muscle] Fail to detect smartcard from reconnected reader

Thomas Bajer thomas.bajer at physec.de
Fri Jul 21 11:46:33 UTC 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