static UINT32 smartcard_IsValidContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, Context_Call* call)
{
	UINT32 status;
	Long_Return ret;

	status = ret.ReturnCode = SCardIsValidContext(operation->hContext);

	smartcard_trace_long_return(smartcard, &ret, "IsValidContext");

	return ret.ReturnCode;
}
Beispiel #2
0
/* :Document-method: is_valid
 * call-seq:
 *      is_valid() --> valid_boolean
 * 
 * Checks if the PC/SC context is still valid.
 * A context may become invalid if the resource manager service has been shut down.
 * Wraps _SCardIsValidContext_ in PC/SC.
 * 
 * Returns a boolean value with the obvious meaning.
 */
static VALUE PCSC_Context_is_valid(VALUE self) {
	struct SCardContextEx *context;	
	Data_Get_Struct(self, struct SCardContextEx, context);
	if(context == NULL) return self;

#if defined(RB_SMARTCARD_OSX_TIGER_HACK) || defined(PCSC_SURROGATE_SCARD_IS_VALID_CONTEXT)	
	return Qtrue;
#else
	context->pcsc_error = SCardIsValidContext(context->pcsc_context);
	return (context->pcsc_error == SCARD_S_SUCCESS) ? Qtrue : Qfalse;
#endif
}
static uint32 handle_IsValidContext(IRP* irp)
{
	uint32 rv;
	SCARDCONTEXT hContext;

	stream_seek(irp->input, 0x1C);
	stream_read_uint32(irp->input, hContext);

	rv = SCardIsValidContext(hContext);

	if (rv)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
	else
		DEBUG_SCARD("Success context: 0x%08x", (unsigned) hContext);

	stream_write_uint32(irp->output, rv);

	return rv;
}
Beispiel #4
0
static UINT32 handle_IsValidContext(IRP* irp)
{
	UINT32 status;
	SCARDCONTEXT hContext;

	stream_seek(irp->input, 0x1C);
	stream_read_UINT32(irp->input, hContext);

	status = SCardIsValidContext(hContext);

	if (status)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
	else
		DEBUG_SCARD("Success context: 0x%08x", (unsigned) hContext);

	smartcard_output_alignment(irp, 8);

	return status;
}
Beispiel #5
0
void CReaderMonitor::stop(bool mustWait)
{
	if (m_hMonitorThread) {
		g_pListener = NULL;
		InterlockedIncrement(&g_fExit);
        if (SCARD_S_SUCCESS == SCardIsValidContext(g_hContext))
            SCardCancel(g_hContext);
		if(mustWait)
		{
			if (WaitForSingleObject(m_hMonitorThread, POLL_PERIOD * 4) == WAIT_TIMEOUT)
				TerminateThread(m_hMonitorThread, 0);
			InterlockedDecrement(&g_fExit);
			CloseHandle(m_hMonitorThread);
		}
		else
		{
			TerminateThread(m_hMonitorThread, 0);
			InterlockedDecrement(&g_fExit);
			CloseHandle(m_hMonitorThread);
		}
		
		m_hMonitorThread = NULL;
	}
}
Beispiel #6
0
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
{
	SCARDHANDLE hCard;
	SCARDCONTEXT hContext;
	SCARD_READERSTATE rgReaderStates[1];
	DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
	DWORD dwPref, dwReaders = 0;
	char *pcReader = NULL, *mszReaders;
#ifdef USE_AUTOALLOCATE
	unsigned char *pbAtr = NULL;
#else
	unsigned char pbAtr[MAX_ATR_SIZE];
#endif
	union {
		unsigned char as_char[100];
		DWORD as_DWORD;
		uint32_t as_uint32_t;
	} buf;
	DWORD dwBufLen;
	unsigned char *pbAttr = NULL;
	DWORD pcbAttrLen;
	char *mszGroups;
	DWORD dwGroups = 0;
	long rv;
	DWORD i;
	int p, iReader;
	int iList[16] = {0};
	SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0;	/* use a default value */
	const SCARD_IO_REQUEST *pioSendPci;
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
	DWORD send_length, length;

	(void)argc;
	(void)argv;

	printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");

	printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
	printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);

	printf("Testing SCardEstablishContext\t: ");
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext+1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardListReaderGroups\t: ");
#ifdef USE_AUTOALLOCATE
	dwGroups = SCARD_AUTOALLOCATE;
	rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
#else
	rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaderGroups\t: ");
	mszGroups = calloc(dwGroups, sizeof(char));
	rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
#endif
	test_rv(rv, hContext, PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwGroups; i++)
	{
		++p;
		printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
		while (mszGroups[++i] != 0) ;
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszGroups);
	test_rv(rv, hContext, PANIC);
#else
	free(mszGroups);
#endif

wait_for_card_again:
	mszGroups = NULL;
	printf("Testing SCardListReaders\t: ");
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, DONT_PANIC);
	if (SCARD_E_NO_READERS_AVAILABLE == rv)
	{
		printf("Testing SCardGetStatusChange \n");
		printf("Please insert a working reader\t: ");
		(void)fflush(stdout);
		rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
		rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

		rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
		test_rv(rv, hContext, PANIC);
	}

	printf("Testing SCardListReaders\t: ");
#ifdef USE_AUTOALLOCATE
	dwReaders = SCARD_AUTOALLOCATE;
	rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
#else
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaders\t: ");
	mszReaders = calloc(dwReaders, sizeof(char));
	rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
#endif
	test_rv(rv, hContext, DONT_PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwReaders; i++)
	{
		++p;
		printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
		iList[p] = i;
		while (mszReaders[++i] != 0) ;
	}

	if (p > 1)
		do
		{
			char input[80];
			char *r;

			printf("Enter the reader number\t\t: ");
			r = fgets(input, sizeof(input), stdin);
			if (NULL == r)
				iReader = -1;
			else
				iReader = atoi(input);

			if (iReader > p || iReader <= 0)
				printf("Invalid Value - try again\n");
		}
		while (iReader > p || iReader <= 0);
	else
		iReader = 1;

	rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
	rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

	printf("Waiting for card insertion\t: ");
	(void)fflush(stdout);
	rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
	test_rv(rv, hContext, PANIC);
	if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
	{
		printf("\nA reader has been connected/disconnected\n");
		goto wait_for_card_again;
	}

	printf("Testing SCardConnect\t\t: ");
	rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
		&hCard, &dwPref);
	test_rv(rv, hContext, PANIC);

	switch(dwPref)
	{
		case SCARD_PROTOCOL_T0:
			pioSendPci = SCARD_PCI_T0;
			break;
		case SCARD_PROTOCOL_T1:
			pioSendPci = SCARD_PCI_T1;
			break;
		case SCARD_PROTOCOL_RAW:
			pioSendPci = SCARD_PCI_RAW;
			break;
		default:
			printf("Unknown protocol\n");
			return -1;
	}

	/* APDU select file */
	printf("Select file:");
	send_length = 7;
	memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
	for (i=0; i<send_length; i++)
		printf(" %02X", bSendBuffer[i]);
	printf("\n");
	length = sizeof(bRecvBuffer);

	printf("Testing SCardTransmit\t\t: ");
	rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length,
		&ioRecvPci, bRecvBuffer, &length);
	test_rv(rv, hContext, PANIC);
	printf(" card response:" GREEN);
	for (i=0; i<length; i++)
		printf(" %02X", bRecvBuffer[i]);
	printf("\n" NORMAL);

	printf("Testing SCardControl\t\t: ");
#ifdef PCSC_PRE_120
	{
		char buffer[1024] = "Foobar";
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
	}
#else
	{
		char buffer[1024] = { 0x02 };
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
			sizeof(buffer), &cbRecvLength);
		if (cbRecvLength && (SCARD_S_SUCCESS == rv))
		{
			for (i=0; i<cbRecvLength; i++)
				printf("%c", buffer[i]);
			printf(" ");
		}
	}
#endif
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		printf("SCARD_ATTR_ATR_STRING: " GREEN);
		for (i = 0; i < pcbAttrLen; i++)
			printf("%02X ", pbAttr[i]);
		printf("\n" NORMAL);
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		int valid = 1;	/* valid value by default */
		long value;
		printf("Vendor IFD version\t\t: ");
		if (dwBufLen == sizeof(DWORD))
			value = buf.as_DWORD;
		else
		{
			if (dwBufLen == sizeof(uint32_t))
				value = buf.as_uint32_t;
			else
			{
				printf(RED "Unsupported size\n" NORMAL);
				valid = 0;	/* invalid value */
			}
		}

		if (valid)
		{
			int M = (value & 0xFF000000) >> 24;		/* Major */
			int m = (value & 0x00FF0000) >> 16;		/* Minor */
			int b = (value & 0x0000FFFF);			/* build */
			printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b);
		}
	}
Beispiel #7
0
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
{
	SCARDHANDLE hCard;
	SCARDCONTEXT hContext;
	SCARD_READERSTATE_A rgReaderStates[1];
	DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
	DWORD dwPref, dwReaders = 0;
	char *pcReaders = NULL, *mszReaders;
#ifdef USE_AUTOALLOCATE
	unsigned char *pbAtr = NULL;
#else
	unsigned char pbAtr[MAX_ATR_SIZE];
#endif
	union {
		unsigned char as_char[100];
		DWORD as_DWORD;
		uint32_t as_uint32_t;
	} buf;
	DWORD dwBufLen;
	unsigned char *pbAttr = NULL;
	DWORD pcbAttrLen;
	char *mszGroups;
	DWORD dwGroups = 0;
	long rv;
	DWORD i;
	int p, iReader;
	int iList[16];
	SCARD_IO_REQUEST pioRecvPci;
	SCARD_IO_REQUEST pioSendPci;
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
	DWORD send_length, length;

	(void)argc;
	(void)argv;

	printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");

	printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
	printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);

	printf("Testing SCardEstablishContext\t: ");
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext+1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardListReaderGroups\t: ");
#ifdef USE_AUTOALLOCATE
	dwGroups = SCARD_AUTOALLOCATE;
	rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
#else
	rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaderGroups\t: ");
	mszGroups = calloc(dwGroups, sizeof(char));
	rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
#endif
	test_rv(rv, hContext, PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwGroups; i++)
	{
		++p;
		printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
		while (mszGroups[++i] != 0) ;
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszGroups);
	test_rv(rv, hContext, PANIC);
#else
	free(mszGroups);
#endif

wait_for_card_again:
	mszGroups = NULL;
	printf("Testing SCardListReaders\t: ");
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, DONT_PANIC);
	if (SCARD_E_NO_READERS_AVAILABLE == rv)
	{
		printf("Testing SCardGetStatusChange \n");
		printf("Please insert a working reader\t: ");
		(void)fflush(stdout);
		rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
		rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

		rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
		test_rv(rv, hContext, PANIC);
	}

	printf("Testing SCardListReaders\t: ");
#ifdef USE_AUTOALLOCATE
	dwReaders = SCARD_AUTOALLOCATE;
	rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
#else
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaders\t: ");
	mszReaders = calloc(dwReaders, sizeof(char));
	rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
#endif
	test_rv(rv, hContext, DONT_PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwReaders; i++)
	{
		++p;
		printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
		iList[p] = i;
		while (mszReaders[++i] != 0) ;
	}

	if (p > 1)
		do
		{
			char input[80];

			printf("Enter the reader number\t\t: ");
			(void)fgets(input, sizeof(input), stdin);
			(void)sscanf(input, "%d", &iReader);

			if (iReader > p || iReader <= 0)
				printf("Invalid Value - try again\n");
		}
		while (iReader > p || iReader <= 0);
	else
		iReader = 1;

	rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
	rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

	printf("Waiting for card insertion\t: ");
	(void)fflush(stdout);
	rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
	test_rv(rv, hContext, PANIC);
	if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
	{
		printf("\nA reader has been connected/disconnected\n");
		goto wait_for_card_again;
	}

	printf("Testing SCardConnect\t\t: ");
	rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
		&hCard, &dwPref);
	test_rv(rv, hContext, PANIC);

	switch(dwPref)
	{
		case SCARD_PROTOCOL_T0:
			pioSendPci = *SCARD_PCI_T0;
			break;
		case SCARD_PROTOCOL_T1:
			pioSendPci = *SCARD_PCI_T1;
			break;
		case SCARD_PROTOCOL_RAW:
			pioSendPci = *SCARD_PCI_RAW;
			break;
		default:
			printf("Unknown protocol\n");
			return -1;
	}

	int bBreak = 0;

	while (1)
	{
		char inputCommand[1024];	
		char inputAPDU[1024];
		int inputAPDULen = sizeof(inputAPDU);
		printf("Enter APDU to send, (e.g. 00:A4:04:00:00)\n");
		printf("Command APDU: ");
		(void)fgets(inputCommand, sizeof(inputCommand), stdin);
		
		int stringlen = strlen(inputCommand);
		if( inputCommand[stringlen-1] == '\n' ) { inputCommand[stringlen-1] = 0; } //remove newline

		int bError = sc_hex_to_bin(inputCommand, inputAPDU, &inputAPDULen);
		//printf("debug - value bError: %i\n",bError);
		if (bError) { printf("Error parsing input\n\n"); continue; }

		send_length = inputAPDULen;
		if (inputAPDULen == 0) { break; }
		printf("debug inputAPDULen: %i\n",inputAPDULen); 
		memcpy(bSendBuffer, inputAPDU, send_length);
		length = sizeof(bRecvBuffer);

		printf("Testing SCardTransmit:\n "); printf("-> ");
		for (i=0; i<send_length; i++) { printf(" %02X", bSendBuffer[i]); }
		printf("\n");
		rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
			&pioRecvPci, bRecvBuffer, &length);
		test_rv(rv, hContext, PANIC);
		printf("<- " GREEN);
		for (i=0; i<length; i++)
			printf(" %02X", bRecvBuffer[i]);
		printf("\n" NORMAL);
	}

	testrun(&hCard, &hContext, &pioSendPci, 0);
	testrun(&hCard, &hContext, &pioSendPci, 1);
	testrun(&hCard, &hContext, &pioSendPci, 2);
	testrun(&hCard, &hContext, &pioSendPci, 3);

	printf("Testing SCardControl\t\t: ");
#ifdef PCSC_PRE_120
	{
		char buffer[1024] = "Foobar";
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
	}
#else
	{
		char buffer[1024] = { 0x02 };
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
			sizeof(buffer), &cbRecvLength);
		if (cbRecvLength && (SCARD_S_SUCCESS == rv))
		{
			for (i=0; i<cbRecvLength; i++)
				printf("%c", buffer[i]);
			printf(" ");
		}
	}
#endif
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		printf("SCARD_ATTR_ATR_STRING: " GREEN);
		for (i = 0; i < pcbAttrLen; i++)
			printf("%02X ", pbAttr[i]);
		printf("\n" NORMAL);
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL,
			buf.as_DWORD);

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		if (dwBufLen == sizeof(uint32_t))
			printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
				buf.as_uint32_t);
		else
			printf(RED "Wrong size" NORMAL);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);

	printf("Testing SCardSetAttrib\t\t: ");
	rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardStatus\t\t: ");

#ifdef USE_AUTOALLOCATE
	dwReaderLen = SCARD_AUTOALLOCATE;
	dwAtrLen = SCARD_AUTOALLOCATE;
	rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt,
		(LPBYTE)&pbAtr, &dwAtrLen);
#else
	dwReaderLen = 100;
	pcReaders   = malloc(sizeof(char) * 100);
	dwAtrLen    = MAX_ATR_SIZE;

	rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
		pbAtr, &dwAtrLen);
#endif
	test_rv(rv, hContext, PANIC);

	printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders);
	printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
	printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
	printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
		dwAtrLen);
	printf("Current Reader ATR Value\t: " GREEN);

	for (i = 0; i < dwAtrLen; i++)
	{
		printf("%02X ", pbAtr[i]);
	}
	printf(NORMAL "\n");

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pcReaders);
	test_rv(rv, hContext, PANIC);
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAtr);
	test_rv(rv, hContext, PANIC);
#else
	if (pcReaders)
		free(pcReaders);
#endif

	if (rv != SCARD_S_SUCCESS)
	{
		(void)SCardDisconnect(hCard, SCARD_RESET_CARD);
		(void)SCardReleaseContext(hContext);
	}

	printf("Press enter: ");
	(void)getchar();
	printf("Testing SCardReconnect\t\t: ");
	rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
		SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardDisconnect\t\t: ");
	rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
	test_rv(rv, hContext, PANIC);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszReaders);
	test_rv(rv, hContext, PANIC);
#else
	free(mszReaders);
#endif

	printf("Testing SCardReleaseContext\t: ");
	rv = SCardReleaseContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("\n");
	printf("PC/SC Test Completed Successfully !\n");

	return 0;
}
Beispiel #8
0
static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
	int index;
	int keyCount;
	ULONG_PTR* pKeys;
	SCARDCONTEXT hContext;
	SMARTCARD_CONTEXT* pContext;

	/**
	 * On protocol termination, the following actions are performed:
	 * For each context in rgSCardContextList, SCardCancel is called causing all SCardGetStatusChange calls to be processed.
	 * After that, SCardReleaseContext is called on each context and the context MUST be removed from rgSCardContextList.
	 */

	/**
	 * Call SCardCancel on existing contexts, unblocking all outstanding SCardGetStatusChange calls.
	 */

	if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
	{
		pKeys = NULL;
		keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys);

		for (index = 0; index < keyCount; index++)
		{
			pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);

			if (!pContext)
				continue;

			hContext = pContext->hContext;

			if (SCardIsValidContext(hContext) == SCARD_S_SUCCESS)
			{
				SCardCancel(hContext);
			}
		}

		free(pKeys);
	}

	/**
	 * Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList.
	 */

	if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
	{
		pKeys = NULL;
		keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys);

		for (index = 0; index < keyCount; index++)
		{
			pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]);

			if (!pContext)
				continue;

			hContext = pContext->hContext;

			if (SCardIsValidContext(hContext) == SCARD_S_SUCCESS)
			{
				SCardReleaseContext(hContext);

				if (MessageQueue_PostQuit(pContext->IrpQueue, 0) && (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
					WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());

				CloseHandle(pContext->thread);
				MessageQueue_Free(pContext->IrpQueue);	
				free(pContext);
			}
		}

		free(pKeys);
	}
}
PCSC::PCSC( std::string& a_stInputReaderName, u2& a_u2PortNumber, std::string& a_stURI, u4& a_NameSpaceHivecode, u2& a_TypeHivecode, u4& a_Index ) {

    Log::begin( "PCSC::PCSC" );

    m_bDoTransact = true;

    std::string stIdentifiedReaderName = "";

    LPTSTR pReaderList = NULL;

    if( a_stInputReaderName.empty( ) ) {

        a_stInputReaderName = "selfdiscover";
    }

    m_hContextPCSC = 0;

    m_hCardPCSC = 0;

    LONG lReturn = SCardEstablishContext( 0, NULL, NULL, &m_hContextPCSC );

    if( SCARD_S_SUCCESS != lReturn )
    {
        std::string msg = "";
        Log::toString( msg, "SCardEstablishContext <%#02x>", lReturn );
        Log::error( "PCSC::PCSC", msg.c_str( ) );

        throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
    }

    // self-discovery mechanism
#ifdef WIN32
    if (_stricmp("selfdiscover", a_stInputReaderName.c_str()) == 0) {
#else
    if (strncasecmp("selfdiscover", a_stInputReaderName.c_str(),a_stInputReaderName.length()) == 0) {
#endif
        // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength
        // would signal the SCardListReaders to determine the size of reader string
        // This is not available in Linux so we call the SCardListReaders twice. First
        // to get the length and then the reader names.
#ifdef WIN32
        DWORD readerListCharLength = SCARD_AUTOALLOCATE;
        lReturn = SCardListReaders( m_hContextPCSC, NULL, (LPTSTR)&pReaderList, &readerListCharLength);

#else
        DWORD readerListCharLength = 0;

        lReturn = SCardListReaders(m_hContextPCSC,NULL,NULL,&readerListCharLength);
        if(lReturn != SCARD_S_SUCCESS)
            throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);

        pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength);
        lReturn = SCardListReaders(m_hContextPCSC, NULL,pReaderList, &readerListCharLength);
#endif


        if(lReturn != SCARD_S_SUCCESS) {

            std::string msg = "";
            Log::toString( msg, "SCardListReaders <%#02x>", lReturn );
            Log::error( "PCSC::PCSC", msg.c_str( ) );
            throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);

        } else {

            u4 count = 0;
            u1 foundReader = FALSE;
            SCARDHANDLE finalCardHandle = 0;

            try {

                lpTCharPtr pReader = pReaderList;

                while ('\0' != *pReader ) {

                    size_t readerNameLen = strlen((const char*)pReader);
                    SCARD_READERSTATE readerStates[1];
                    readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
                    readerStates[0].szReader = pReader;

                    if ( SCardGetStatusChange( m_hContextPCSC, 0, readerStates, 1) == SCARD_S_SUCCESS) {

                        if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) {

                            // we found a card in this reader
                            stIdentifiedReaderName = pReader;

                            DWORD activeProtocol;

                            lReturn = SCardConnect( m_hContextPCSC, (LPTSTR)stIdentifiedReaderName.c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &m_hCardPCSC, &activeProtocol);

                            if (lReturn == SCARD_S_SUCCESS) {

                                // try to identify if we're dealing with a .NetCard
                                u1 answerData[258];
                                DWORD answerLen = 258;

                                Log::log( "PCSC::PCSC SCardTransmit..." );
                                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen);
                                Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn );

                                if (lReturn == SCARD_S_SUCCESS)
                                {
                                    u1 rethrowException = FALSE;
                                    try {
                                        if (answerData[answerLen - 2] == 0x61)
                                        {
                                            if (answerData[answerLen - 1] > 10)
                                            {
                                                u1Array invokeAPDU(0);
                                                invokeAPDU += (u1)0xD8;
                                                invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT;
                                                invokeAPDU += (u1)0x6F;
                                                invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD;
                                                invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
                                                invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT;
                                                std::string* cmServicem_stURI = new std::string(CARDMANAGER_SERVICE_NAME);
                                                invokeAPDU.Append(cmServicem_stURI);
                                                delete cmServicem_stURI;
                                                invokeAPDU += (u4)a_NameSpaceHivecode;
                                                invokeAPDU += (u2)a_TypeHivecode;
                                                invokeAPDU.Append(&a_stURI);

                                                // construct call
                                                if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) {
                                                    u1Array apdu(5);
                                                    apdu.GetBuffer()[0] = 0x80;
                                                    apdu.GetBuffer()[1] = 0xC2;
                                                    apdu.GetBuffer()[2] = 0x00;
                                                    apdu.GetBuffer()[3] = 0x00;
                                                    apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
                                                    apdu += invokeAPDU;

                                                    u1Array answer(0);

                                                    Log::log( "PCSC::PCSC - ExchangeData..." );
                                                    exchangeData(apdu, answer);
                                                    Log::log( "PCSC::PCSC - ExchangeData ok" );

                                                    Log::log( "PCSC::PCSC - CheckForException..." );
                                                    u4 protocolOffset = m_MarshallerUtil.CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
                                                    Log::log( "PCSC::PCSC - CheckForException ok" );

                                                    u4 discoveredPortNumber = m_MarshallerUtil.ComReadU4At(answer, protocolOffset);
                                                    if ((a_u2PortNumber == 0) || (discoveredPortNumber == a_u2PortNumber))
                                                    {
                                                        a_u2PortNumber = (u2)discoveredPortNumber;

                                                        if (foundReader == TRUE)
                                                        {
                                                            if (a_Index == 0)
                                                            {
                                                                // this is the second reader/card/app that matches - we error at this point
                                                                rethrowException = TRUE;
                                                                std::string errorMessage( "At least 2 cards posses \"");
                                                                errorMessage += a_stURI.c_str( );
                                                                errorMessage += "\" service\r\nRemove conflicting cards from your system";
                                                                Log::error( "PCSC::PCSC", errorMessage.c_str( ) );

                                                                throw RemotingException(errorMessage);
                                                            }
                                                        }

                                                        foundReader = TRUE;
                                                        finalCardHandle = m_hCardPCSC;

                                                        // Advance to the next value.
                                                        count++;

                                                        if (count == a_Index)
                                                        {
                                                            // we enumerate one by one the valid readers - so stop here
                                                            break;
                                                        }

                                                        pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
                                                        continue;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    catch (...)
                                    {
                                        if (rethrowException == TRUE)
                                        {
                                            throw;
                                        }
                                        else
                                        {
                                            // swallow exception
                                        }
                                    }

                                    SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD);
                                    m_hCardPCSC = 0;
                                }
                                // this is not a .NetCard, or the service was not found - let's try another reader/card
                                else
                                {
                                    Log::error( "PCSC::PCSC", "SCardTransmit failed" );
                                }
                            }
                            else
                            {
                                Log::error( "PCSC::PCSC", "SCardConnect failed" );
                            }
                        }
                        else
                        {
                            Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" );
                        }
                    }
                    else
                    {
                        Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" );
                    }

                    // Advance to the next value.
                    pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
                }
            } catch (...) {

                stIdentifiedReaderName = "";

#ifdef WIN32
                /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList);
                /*if(lReturn != SCARD_S_SUCCESS) {
                throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
                }*/
#else
                if( pReaderList ) {

                    free(pReaderList);
                }
#endif
                throw;
            }

            // have we found anything ?
            if( !foundReader) {

                stIdentifiedReaderName = "";

#ifdef WIN32
                /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList);
                //if(lReturn != SCARD_S_SUCCESS) {
                //    throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
                //}
#else
                if(pReaderList ) {

                    free(pReaderList);
                }
#endif

                throw RemotingException((lpCharPtr)"Could not find any .NET smart card", SCARD_E_NO_SMARTCARD );
            }

            m_hCardPCSC = finalCardHandle;
        }

        m_stReaderName = stIdentifiedReaderName;

    } else {

        m_stReaderName = a_stInputReaderName;
    }

    Log::end( "PCSC::PCSC" );
}


/*
*/
void PCSC::exchangeData( u1Array &dataIn, u1Array &dataout ) {

    // check validity of handle
    if ( SCARD_S_SUCCESS != SCardIsValidContext( m_hContextPCSC ) ) {

        throw RemotingException( (lpCharPtr)"PCSC: Invalid handle", SCARD_E_INVALID_HANDLE );
    }

    try {

        if( m_bDoTransact ) { 

            beginTransaction( );
        }

        unsigned char ucRetry = 0;

        do {

            ucRetry++;

            unsigned char answerData[ 258 ];
            memset( answerData, 0, sizeof( answerData ) );

            DWORD answerLen = sizeof( answerData );

#ifdef __DEBUG_APDU__
            Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", dataIn.GetBuffer( ), dataIn.GetLength( ) );
            Timer t;
            t.start( );
#endif

            LONG lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen );

            if( SCARD_S_SUCCESS != lReturn ) {

                std::string msg = "";
                Log::toString( msg, "SCardTransmit <%#02x>", lReturn );
                Log::error( "PCSC::ExchangeData", msg.c_str( ) );
            }

            if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) {

                DWORD dwActiveProtocol = SCARD_PROTOCOL_T0;

                lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );

                if( SCARD_S_SUCCESS != lReturn ) {

                    std::string msg = "";
                    Log::toString( msg, "SCardReconnect <%#02x>", lReturn );
                    Log::error( "PCSC::ExchangeData", msg.c_str( ) );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardReconnect error", lReturn );
                }

                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen );

                if( SCARD_S_SUCCESS != lReturn ) {

                    Log::log( "PCSC::ExchangeData - SCardTransmit <%#02x>", lReturn );
                }

            } else if( SCARD_S_SUCCESS != lReturn ) {

                std::string s;
                Log::toString( s, "SCardTransmit failed <%#02x>", lReturn );
                Log::error( "PCSC::ExchangeData", s.c_str( ) );

                throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn );
            }

            if (answerLen < 2) {

                Log::error( "PCSC::ExchangeData", "Incorrect length returned" );

                throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
            }

            if (answerLen > 2) {

                u1Array temp(answerLen - 2);

                temp.SetBuffer(answerData);

                dataout += temp;
            }

            u1 sw1 = answerData[answerLen - 2];

            u1 sw2 = answerData[answerLen - 1];

#ifdef __DEBUG_APDU__
            Log::log( "PCSC::ExchangeData - Status (1) <%02x%02x>", sw1, sw2 );
            Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen );
            t.stop( "PCSC::ExchangeData - Response" );
#endif

            while( (sw1 == 0x61 ) || ( sw1 == 0x9F ) ) {

                memset( answerData, 0, sizeof( answerData ) );

                unsigned char GetResponse[ 5 ];

                memset( GetResponse, 0, sizeof( GetResponse ) );

                if (sw1 == 0x9F) {

                    GetResponse[0] = 0xA0;

                } else {

                    GetResponse[0] = 0x00;
                }

                GetResponse[1] = 0xC0;

                GetResponse[2] = 0x00;

                GetResponse[3] = 0x00;

                GetResponse[4] = sw2;

                answerLen = 258;

#ifdef __DEBUG_APDU__
                Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", GetResponse, sizeof( GetResponse ) );
                t.start( );
#endif

                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen );

                if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) {

                    DWORD dwActiveProtocol = SCARD_PROTOCOL_T0;

                    lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );

                    lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen );

                } else if( SCARD_S_SUCCESS != lReturn ) {

                    std::string s;
                    Log::toString( s, "SCardTransmit failed <%02x>", lReturn );
                    Log::error( "PCSC::ExchangeData", s.c_str( ) );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn );
                }

                if( answerLen < 2 ) {

                    Log::error( "PCSC::ExchangeData", "Incorrect length returned" );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned", SCARD_F_COMM_ERROR );
                }

                if( answerLen > 2 ) {

                    u1Array temp( answerLen - 2 );

                    temp.SetBuffer( answerData );

                    dataout += temp;
                }

                sw1 = answerData[ answerLen - 2 ];

                sw2 = answerData[ answerLen - 1 ];

#ifdef __DEBUG_APDU__
                Log::log( "PCSC::ExchangeData - Status (2) <%02x%02x>", sw1, sw2 );
                Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen );
                t.stop( "PCSC::ExchangeData - Response" );
#endif
            }

            // The response is not acceptable. We have to retry the data transmission
            if( ( 0x63 == sw1 ) || ( ( 0x69 == sw1 ) && ( 0x99 == sw2 ) ) ) {

                Log::log( "PCSC::ExchangeData - Invalid response. Retry" );

            } else {

                break;
            }

 /*               if( ( 0x90 == sw1 ) && ( 0x00 == sw2 ) ) {

                break;
            }*/

        } while ( 3 > ucRetry );

    } catch (...) {

        if( m_bDoTransact ) { 

            endTransaction( );
        }

        throw;
    }

    if( m_bDoTransact ) { 

        endTransaction( );
    }
}


/* Cleanup the context and card handle
*/
PCSC::~PCSC( ) {

    if( m_hCardPCSC ) {

        SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD );

        m_hCardPCSC = 0;
    }

    if( m_hContextPCSC ) {

        SCardReleaseContext( m_hContextPCSC );

        m_hContextPCSC = 0;
    }
}

MARSHALLER_NS_END
Beispiel #10
0
static void smartcard_init(DEVICE* device)
{
	int index;
	int keyCount;
	ULONG_PTR* pKeys;
	SCARDCONTEXT hContext;
	SMARTCARD_CONTEXT* pContext;
	SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;

	/**
	 * On protocol termination, the following actions are performed:
	 * For each context in rgSCardContextList, SCardCancel is called causing all outstanding messages to be processed.
	 * After there are no more outstanding messages, SCardReleaseContext is called on each context and the context MUST
	 * be removed from rgSCardContextList.
	 */

	/**
	 * Call SCardCancel on existing contexts, unblocking all outstanding IRPs.
	 */

	if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
	{
		pKeys = NULL;
		keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys);

		for (index = 0; index < keyCount; index++)
		{
			pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);

			if (!pContext)
				continue;

			hContext = pContext->hContext;

			if (SCardIsValidContext(hContext))
			{
				SCardCancel(hContext);
			}
		}

		free(pKeys);
	}

	/**
	 * Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList.
	 */

	if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
	{
		pKeys = NULL;
		keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys);

		for (index = 0; index < keyCount; index++)
		{
			pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]);

			if (!pContext)
				continue;

			hContext = pContext->hContext;

			if (SCardIsValidContext(hContext))
			{
				SCardReleaseContext(hContext);
			}
		}

		free(pKeys);
	}
}
Beispiel #11
0
DWORD WINAPI CReaderMonitor::ReaderMonitorProc(void* param)
{
	HRESULT hRes;
	LPTSTR mszNewReaderNames = NULL;

	while (!InterlockedCompareExchange(&g_fExit,0,0)) {

		if (g_hContext == 0) {
			// trying to establish context
			hRes = SCardEstablishContext(g_dwScope, NULL, NULL, &g_hContext);
			if (hRes != SCARD_S_SUCCESS) {
				Sleep(POLL_PERIOD);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
				g_hContext = 0;
			}
		}

		if (g_hContext) {

            if (SCARD_S_SUCCESS == SCardIsValidContext(g_hContext))
            {
			    // rescan reader list...
			    mszNewReaderNames = NULL;
			    DWORD cchReaderNames = 0;
			    do {
				    hRes = SCardListReaders(g_hContext, NULL, NULL, &cchReaderNames);
                if ((hRes == SCARD_S_SUCCESS) && cchReaderNames) {
					    mszNewReaderNames = new TCHAR[cchReaderNames];
					    hRes = SCardListReaders(g_hContext, NULL, mszNewReaderNames, &cchReaderNames);
					    if (hRes != SCARD_S_SUCCESS) {
						    delete[] mszNewReaderNames;
						    mszNewReaderNames = NULL;
					    }
				    }
			    }
			    while (hRes == SCARD_E_INSUFFICIENT_BUFFER);
            }
            else
                hRes = SCARD_E_NO_SERVICE;

			if(InterlockedCompareExchange(&g_fExit,1,1))
				break;

			// check reader listing status
			DWORD cNewReaderStates = 0;
			SCARD_READERSTATE *pNewReaderStates = NULL;
			switch (hRes) {
            case ERROR_INVALID_HANDLE:
			case SCARD_E_INVALID_HANDLE:
			case SCARD_E_NO_SERVICE:
			case SCARD_E_SERVICE_STOPPED:
				SCardReleaseContext(g_hContext);
				g_hContext = 0;
				hRes = SCARD_S_SUCCESS;
				break;
			case SCARD_E_NO_READERS_AVAILABLE:
				hRes = SCARD_S_SUCCESS;
				break;
			case SCARD_S_SUCCESS:
				for (LPCTSTR pReader = mszNewReaderNames; *pReader != 0; pReader += _tcslen(pReader) + 1)
					cNewReaderStates++;
				if (cNewReaderStates)
				{
					pNewReaderStates = new SCARD_READERSTATE[cNewReaderStates];
					memset(pNewReaderStates,0,cNewReaderStates* sizeof(SCARD_READERSTATE));
				}
			default:
				break;
			}

			if(InterlockedCompareExchange(&g_fExit,1,1))
				break;
			
			if (hRes == SCARD_S_SUCCESS) {
				// compare readers
				DWORD j;
				for (j = 0; j < g_cReaderStates; j++)
					g_pReaderStates[j].pvUserData = (LPVOID)1;
				LPCTSTR pReader = mszNewReaderNames;
				DWORD i = 0;
				if (pReader) {
					while (*pReader != 0) {
						pNewReaderStates[i].pvUserData = (LPVOID)1;
						pNewReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
						for (j = 0; j < g_cReaderStates; j++) {
							if (_tcscmp(pReader, g_pReaderStates[j].szReader) == 0) {
								g_pReaderStates[j].pvUserData = NULL;
								pNewReaderStates[i] = g_pReaderStates[j];
								break;
							}
						}

						pNewReaderStates[i].szReader = pReader;
						pReader += _tcslen(pReader) + 1;
						i++;
					}
				}

				// check removed readers
				for (j = 0; j < g_cReaderStates; j++) {
					if (g_pReaderStates[j].pvUserData != NULL) {
						NotifyReaderUnplug(g_pReaderStates[j].szReader);
						if(InterlockedCompareExchange(&g_fExit,1,1))
							goto end_label;
					}
				}

				// update current list
				if (g_pReaderStates)
					delete[] g_pReaderStates;
				if (g_mszReaderNames)
					delete[] g_mszReaderNames;
				g_mszReaderNames = mszNewReaderNames;
				g_pReaderStates = pNewReaderStates;
				g_cReaderStates = cNewReaderStates;
				mszNewReaderNames = NULL;
			}

			// check reader states
			if (g_cReaderStates == 0) {
                if (!g_bReadersListInitialized)
                {
                   SetEvent(g_readersCheckedEvent);
                   g_bReadersListInitialized = true;
                }
				Sleep(POLL_PERIOD);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
			}
			else {
				hRes = SCardGetStatusChange(g_hContext, POLL_PERIOD, g_pReaderStates, g_cReaderStates);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
				if (hRes == SCARD_S_SUCCESS) {
					// check changed readers...
					for (DWORD i = 0; i < g_cReaderStates && !InterlockedCompareExchange(&g_fExit,0,0); i++) {
						if (g_pReaderStates[i].pvUserData != NULL) {
							// new reader
							g_pReaderStates[i].pvUserData = NULL;
							g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED;
                            g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState;
                            if ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0)
							    NotifyReaderPlug(g_pReaderStates[i]);
							if(InterlockedCompareExchange(&g_fExit,1,1))
								goto end_label;
							
						}
						else if (g_pReaderStates[i].dwEventState & SCARD_STATE_CHANGED) {
							// existing reader
							g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED;
							if (    ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0)
                                &&  ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_MUTE) == 0)
                                &&  (   ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT) && (!(g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT)))
                                      ||((!(g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT)) && (g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT))
                                    )
                               )
                            {
								NotifyReaderChange(g_pReaderStates[i]);
                            }
                            g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState & (~(SCARD_STATE_CHANGED | SCARD_STATE_IGNORE));
							if(InterlockedCompareExchange(&g_fExit,1,1))
								goto end_label; 
						}
					}
                }
                else if (hRes != SCARD_E_TIMEOUT)
                {
                    if(InterlockedCompareExchange(&g_fExit,1,1))
                        goto end_label; 

                    // something strange happened. Act as if all readers where disconnected
                    for (DWORD i = 0; i < g_cReaderStates; i++)
                    {
                        NotifyReaderUnplug(g_pReaderStates[i].szReader);
						if(InterlockedCompareExchange(&g_fExit,1,1))
							goto end_label;
                    }

				    if (g_pReaderStates)
					    delete[] g_pReaderStates;
				    if (g_mszReaderNames)
					    delete[] g_mszReaderNames;
				    g_mszReaderNames = NULL;
				    g_pReaderStates = NULL;
				    g_cReaderStates = 0;
				    SCardReleaseContext(g_hContext);
				    g_hContext = 0;
                }
                if (!g_bReadersListInitialized)
                {
                   SetEvent(g_readersCheckedEvent);
                   g_bReadersListInitialized = true;
                }				
			}
		}
	}
end_label:

	ResetGlobals();
	if(mszNewReaderNames)
		delete [] mszNewReaderNames;

	return 0;
}