示例#1
0
static int pcsc_reset(cardreader_t *cr)
{
    pcsc_data_t* pcsc = cr->extra_data;

    pcsc->status = SCardReconnect(pcsc->hcard,
                                  SCARD_SHARE_SHARED, 
                                  /* SCARD_SHARE_EXCLUSIVE, */
                                  cr->protocol,
                                  SCARD_RESET_CARD,
                                  &(cr->protocol));

#ifdef __APPLE__
    pcsc->status = SCardReconnect(pcsc->hcard,
                                  SCARD_SHARE_SHARED,
                                  /* SCARD_SHARE_EXCLUSIVE, */
                                  cr->protocol,
                                  SCARD_LEAVE_CARD,
                                  &(cr->protocol));
#endif

    if (pcsc->status==SCARD_S_SUCCESS)
    {
        log_printf(LOG_INFO,"Reconnected reader");
        cr->connected=1;
        return 1;
    }

    log_printf(LOG_ERROR,"Failed to reconnect reader: %s (error 0x%08x).",
               pcsc_stringify_error(pcsc->status),
               pcsc->status );
    cr->connected=0;
    return 0;
}
PCSCREADERDRIVERDLL_API unsigned short CCONV HD_PowerOn(HANDLE devNo, short ivCardSeat)
{
//	DWORD ActiveProtocol;

	//
	//The SCardReconnect function reestablishes an existing connection between 
	//the calling application and a smart card. 
	//This function moves a card handle from direct access to general access, 
	//or acknowledges and clears an error condition that is preventing further 
	//access to the card.
	//

	//SCARD_LEAVE_CARD  Don't do anything special on reconnect. 
	//SCARD_RESET_CARD  Reset the card (Warm Reset). 
	//SCARD_UNPOWER_CARD  Power down the card and reset it (Cold Reset). 
	
//	ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , SCARD_PROTOCOL_T0 , SCARD_UNPOWER_CARD , &ActiveProtocol);
	ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , ActiveProtocol , SCARD_UNPOWER_CARD , &ActiveProtocol);
	if (ret != SCARD_S_SUCCESS)
	{
//		GetErrorCode(ret);
		return CER_PCSC_SCardReconnect;
	}

	return EXCUTE_SUC ;
}
示例#3
0
bool PCSCReader::open(
	void)
{
	// No valid context so we should leave ...
	if (0x00 == m_hScardContext)
		return false;

	long retValue = SCARD_S_SUCCESS;
	retValue = SCardReconnect(m_hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY,
							  SCARD_LEAVE_CARD, &m_dwProtocol);
#if !defined(__APPLE__)
	BYTE atr[512];
	DWORD len = sizeof(atr);
	SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, (LPBYTE) &atr, &len);
#else
	unsigned char atr[512];
	uint32_t len = sizeof(atr);
	char szReader[128];
	uint32_t cch = 128;
	uint32_t dwState;
	uint32_t dwProtocol;
	SCardStatus(m_hCard, szReader, &cch, &dwState, &dwProtocol, (unsigned char *)&atr, &len);
#endif
	return true;
}
示例#4
0
static void smartcard_check_status (SCARDCONTEXT hContext,
		const char* pReader,
		SCARDHANDLE hCardHandle, /* Can be 0 on the first call */
		SCARDHANDLE* newCardHandle, /* The handle returned */
		DWORD* pdwState) {
	DWORD shareMode = SCARD_SHARE_SHARED;
	DWORD preferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
	DWORD dwAP;
	LONG result;

	if (hCardHandle == 0) {
		result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP);
		DEBUG_SCARD_STATUS("SCardConnect", result);
		if (SCARD_S_SUCCESS != result) {
			hCardHandle = 0;
		}
	}

	char szReader[200];
	DWORD cch = sizeof(szReader);
	BYTE bAttr[32];
	DWORD cByte = 32;
	size_t countStatusAttempts = 0;

	while (hCardHandle && (countStatusAttempts < 2)) {
		*pdwState = SCARD_UNKNOWN;

		result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte);
		DEBUG_SCARD_STATUS("SCardStatus", result);
		countStatusAttempts++;

		if ((SCARD_W_RESET_CARD == result) && (countStatusAttempts < 2)) {
			result = SCardReconnect(hCardHandle, shareMode, preferredProtocols, SCARD_RESET_CARD, &dwAP);
			DEBUG_SCARD_STATUS("SCardReconnect", result);
			if (SCARD_S_SUCCESS != result) {
				break;
			}
		}
		else {
			break;
		}
	}

	if (SCARD_S_SUCCESS != result) {
		if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) {
			*pdwState = SCARD_ABSENT;
		}
		else {
			*pdwState = SCARD_UNKNOWN;
		}
	}

	if (newCardHandle == NULL) {
		result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD);
		DEBUG_SCARD_STATUS("SCardDisconnect", result);
	}
	else {
		*newCardHandle = hCardHandle;
	}
}
示例#5
0
bool QPCSCReader::reconnect( Reset reset )
{
	if( !d->card )
		return false;
	LONG err = SCardReconnect( d->card, SCARD_SHARE_SHARED,
		SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, reset, &d->proto );
	d->updateState();
	return err == SCARD_S_SUCCESS;
}
void logicalaccess::PCSCConnection::reconnect()
{
    LONG lReturn = SCardReconnect(handle_, share_mode_, protocol_,
                                  SCARD_LEAVE_CARD, &active_protocol_);
    if (lReturn != SCARD_S_SUCCESS)
    {
        THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException,
                                 "Failed to reconnect PCSC connection: " +
                                     PCSCConnection::strerror(lReturn));
    }
}
示例#7
0
static int testScardReconnect(SCARDCONTEXT hCard, DWORD dwShareMode, DWORD dwPreferredProtocols)
{
	int           ret      = 0;
	int           errCount = 0;
    DWORD         dwAP = 0;

    for (int i = 0; i < 2; i++)
    {
        ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_RESET_CARD, &dwAP);
        if (SCARD_S_SUCCESS != ret)
	    {
            printf("ERR: SCardReconnect(RESET) failed: 0x%0x (%d)\n", ret, ret);
		    errCount++;
	    }

        ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_UNPOWER_CARD, &dwAP);
        if (SCARD_S_SUCCESS != ret)
	    {
            printf("ERR: SCardReconnect(UNPOWER) failed: 0x%0x (%d)\n", ret, ret);
		    errCount++;
	    }

        ret = SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, SCARD_LEAVE_CARD, &dwAP);
        if (SCARD_S_SUCCESS != ret)
	    {
            printf("ERR: SCardReconnect(LEAVE) failed: 0x%0x (%d)\n", ret, ret);
		    errCount++;
	    }

        unsigned char recvBuf[2];
        DWORD recvBufLen = (DWORD) sizeof(recvBuf);
        ret = sendAPDU(hCard, "00:A4:04:0C:0C:A0:00:00:01:77:50:4B:43:53:2D:31:35", recvBuf, &recvBufLen);
	    CHECK_PCSC_RET("sendAPDU(Get Card Data)", ret);
    }

    return errCount;
}
示例#8
0
int unlockPCSCSlot(struct p11Slot_t *slot)
{
	DWORD dwActiveProtocol;
	LONG rv;

	FUNC_CALLED();

	rv = SCardReconnect(slot->card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &dwActiveProtocol);

#ifdef DEBUG
	debug("SCardReconnect (%i, %s): %s\n", slot->id, slot->readername, pcsc_error_to_string(rv));
#endif

	if (rv != SCARD_S_SUCCESS)
		FUNC_FAILS(CKR_DEVICE_ERROR, "Could not reconnect to card");

	FUNC_RETURNS(CKR_OK);
}
示例#9
0
文件: jpcsc.c 项目: hideout/c-beam
/*
 * Reconnect to card.
 */
JNIEXPORT jint JNICALL GEN_FUNCNAME(Card_NativeReconnect)
(JNIEnv *env, jobject _this, jint dwSharedMode, jint dwPreferredProtos, jint dwInit)
{
    SCARDHANDLE card;
    DWORD proto;
    LONG rv;

    card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField);

    rv = SCardReconnect(card, (DWORD) dwSharedMode, (DWORD) dwPreferredProtos,
                        (DWORD) dwInit, &proto);
    if (rv != SCARD_S_SUCCESS) {
        return rv;
    }

    (*env)->SetIntField(env, _this, ProtoField, proto);
    return rv;
}
示例#10
0
static UINT32 smartcard_Reconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, Reconnect_Call* call)
{
	LONG status;
	Reconnect_Return ret;
	IRP* irp = operation->irp;

	status = ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode,
			call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);

	smartcard_trace_reconnect_return(smartcard, &ret);

	status = smartcard_pack_reconnect_return(smartcard, irp->output, &ret);

	if (status != SCARD_S_SUCCESS)
		return status;

	return ret.ReturnCode;
}
示例#11
0
文件: ifd_pcsc.c 项目: javilonas/NCam
static int32_t pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, uint16_t *atr_size)
{
	struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
	LONG rv;
	DWORD dwState, dwAtrLen, dwReaderLen;
	unsigned char pbAtr[ATR_MAX_SIZE];
	char tmp[sizeof(pbAtr) * 3 + 1];

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC initializing card in (%s)", crdr_data->pcsc_name);
	dwAtrLen = sizeof(pbAtr);
	dwReaderLen = 0;

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting card in (%s) with handle %ld", crdr_data->pcsc_name, (long)(crdr_data->hCard));
	rv = SCardReconnect(crdr_data->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,  SCARD_RESET_CARD, &crdr_data->dwActiveProtocol);

	if(rv != SCARD_S_SUCCESS)
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv);
		return ERROR;
	}

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting done on card in (%s)", crdr_data->pcsc_name);
	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 :  1));

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC getting ATR for card in (%s)", crdr_data->pcsc_name);
	rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen);
	if(rv == SCARD_S_SUCCESS)
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 :  1));
		memcpy(atr, pbAtr, dwAtrLen);
		*atr_size = dwAtrLen;

		rdr_log(pcsc_reader, "ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen, tmp, sizeof(tmp)));
		memcpy(pcsc_reader->card_atr, pbAtr, dwAtrLen);
		pcsc_reader->card_atr_length = dwAtrLen;
		return OK;
	}
	else
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv);
	}

	return ERROR;
}
示例#12
0
static uint32 handle_Reconnect(IRP* irp)
{
	LONG rv;
	SCARDCONTEXT hContext;
	SCARDHANDLE hCard;
	DWORD dwShareMode = 0;
	DWORD dwPreferredProtocol = 0;
	DWORD dwInitialization = 0;
	DWORD dwActiveProtocol = 0;

	stream_seek(irp->input, 0x20);
	stream_read_uint32(irp->input, dwShareMode);
	stream_read_uint32(irp->input, dwPreferredProtocol);
	stream_read_uint32(irp->input, dwInitialization);

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

	DEBUG_SCARD("(context: 0x%08x, hcard: 0x%08x, share: 0x%08x, proto: 0x%08x, init: 0x%08x)",
		(unsigned) hContext, (unsigned) hCard,
		(unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization);

	rv = SCardReconnect(hCard, (DWORD) dwShareMode, (DWORD) dwPreferredProtocol,
	    (DWORD) dwInitialization, (LPDWORD) &dwActiveProtocol);

	if (rv != SCARD_S_SUCCESS)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
	else
		DEBUG_SCARD("Success (proto: 0x%08x)", (unsigned) dwActiveProtocol);

	sc_output_alignment(irp, 8);
	stream_write_uint32(irp->output, dwActiveProtocol); /* reversed? */

	return rv;
}
示例#13
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;
}
PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ResetCard( HANDLE devNo, unsigned char	*srATR, short	*srATRLen, short ivCardSeat)
{
//	DWORD ActiveProtocol;
	DWORD dwCardState=0;
	BYTE  AtrBuffer[32];
	DWORD AtrLen ;

//	LPTSTR cardname;
	char cardname[256];
	DWORD dw = 0;
	BYTE buf[32];

//	ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, NULL, &AtrLen);
	ret = SCardStatus((SCARDHANDLE)devNo, cardname, &dw, &dwCardState, &ActiveProtocol, buf, &AtrLen);
	if (ret != SCARD_S_SUCCESS)
	{
//		GetErrorCode(ret);
		return CER_PCSC_SCardStatus;
	}

	switch ( dwCardState )
	{
		case SCARD_ABSENT:
	//		printf("Card absent.\n");
			return CER_NOCARD;

		case SCARD_SWALLOWED:
	//        printf("Card swallowed.\n");

			//
			//The SCardReconnect function reestablishes an existing connection between 
			//the calling application and a smart card. 
			//This function moves a card handle from direct access to general access, 
			//or acknowledges and clears an error condition that is preventing further 
			//access to the card.
			//

			//SCARD_LEAVE_CARD  Don't do anything special on reconnect. 
			//SCARD_RESET_CARD  Reset the card (Warm Reset). 
			//SCARD_UNPOWER_CARD  Power down the card and reset it (Cold Reset).
			ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , ActiveProtocol , SCARD_UNPOWER_CARD , &ActiveProtocol);
			if (ret != SCARD_S_SUCCESS)
			{
				GetErrorCode(ret);
				return CER_PCSC_SCardReconnect;
			}

			break;

		case SCARD_PRESENT:
	//        printf("Card present.\n");
		case SCARD_NEGOTIABLE:
	//        printf("Card reset and waiting PTS negotiation.\n");
		case SCARD_SPECIFIC:
	//        printf("Card has specific communication protocols set.\n");

			//
			//The SCardReconnect function reestablishes an existing connection between 
			//the calling application and a smart card. 
			//This function moves a card handle from direct access to general access, 
			//or acknowledges and clears an error condition that is preventing further 
			//access to the card.
			//

			//SCARD_LEAVE_CARD  Don't do anything special on reconnect. 
			//SCARD_RESET_CARD  Reset the card (Warm Reset). 
			//SCARD_UNPOWER_CARD  Power down the card and reset it (Cold Reset). 

			ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , ActiveProtocol, SCARD_RESET_CARD , &ActiveProtocol);
			if (ret != SCARD_S_SUCCESS)
			{
				//GetErrorCode(ret);
				return CER_PCSC_SCardReconnect;
			}
			break;

		case SCARD_POWERED:
	//        printf("Card has power.\n");

			//
			//The SCardReconnect function reestablishes an existing connection between 
			//the calling application and a smart card. 
			//This function moves a card handle from direct access to general access, 
			//or acknowledges and clears an error condition that is preventing further 
			//access to the card.
			//

			//SCARD_LEAVE_CARD  Don't do anything special on reconnect. 
			//SCARD_RESET_CARD  Reset the card (Warm Reset). 
			//SCARD_UNPOWER_CARD  Power down the card and reset it (Cold Reset). 
/*
			ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 , SCARD_RESET_CARD , &ActiveProtocol);
			if (ret != SCARD_S_SUCCESS)
			{
//				GetErrorCode(ret);
				return CER_PCSC_SCardReconnect;
			}
*/			break;

		default:
	//        printf("Unknown or unexpected card state.\n");
			return CER_UNKNOWN;
	}

	AtrLen = 0x20;		//Microsoft Define Atrlen<=0x20;
	ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, (LPBYTE)&AtrBuffer, &AtrLen);
	if (ret != SCARD_S_SUCCESS)
	{
//		GetErrorCode(ret);
		return CER_PCSC_SCardStatus;
	}

		
	*srATRLen = (short)AtrLen;
	memcpy(srATR, AtrBuffer, AtrLen);

	/*if ((memcmp(srATR+4,"\x00\x81",2)!=0)&&(memcmp(srATR+5,"\x00\x81",2)!=0)&&(memcmp(srATR+7,"\x00\x81",2)!=0)&&(memcmp(srATR+4,"\x86\x01",2)!=0)&&(memcmp(srATR+5,"\x86\x01",2)!=0)&&(memcmp(srATR+7,"\x86\x01",2)!=0))
	{
		return CER_NOCARD;
	}
*/
	return EXCUTE_SUC ;	

}
示例#15
0
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
int main(int argc, char *argv[])
{
	LONG rv;
	SCARDCONTEXT hContext;
	DWORD dwReaders;
	LPSTR mszReaders = NULL;
	char *ptr, **readers = NULL;
	int nbReaders;
	SCARDHANDLE hCard;
	DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
	BYTE pbAtr[MAX_ATR_SIZE] = "";
	char pbReader[MAX_READERNAME] = "";
	int reader_nb;
	unsigned int i;
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
	DWORD send_length, length;
	DWORD verify_ioctl = 0;
	DWORD modify_ioctl = 0;
	DWORD pin_properties_ioctl = 0;
	DWORD mct_readerdirect_ioctl = 0;
	DWORD properties_in_tlv_ioctl = 0;
	DWORD ccid_esc_command = 0;
	SCARD_IO_REQUEST pioRecvPci;
	SCARD_IO_REQUEST pioSendPci;
	PCSC_TLV_STRUCTURE *pcsc_tlv;
#if defined(VERIFY_PIN) | defined(MODIFY_PIN)
	int offset;
#endif
#ifdef VERIFY_PIN
	PIN_VERIFY_STRUCTURE *pin_verify;
#endif
#ifdef MODIFY_PIN
	PIN_MODIFY_STRUCTURE *pin_modify;
#endif

	printf("SCardControl sample code\n");
	printf("V 1.4 © 2004-2010, Ludovic Rousseau <*****@*****.**>\n\n");

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

	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	if (rv != SCARD_S_SUCCESS)
	{
		printf("SCardEstablishContext: Cannot Connect to Resource Manager %ulX\n", rv);
		return 1;
	}

	/* Retrieve the available readers list */
	rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
	PCSC_ERROR_EXIT(rv, "SCardListReaders")

	mszReaders = malloc(sizeof(char)*dwReaders);
	if (mszReaders == NULL)
	{
		printf("malloc: not enough memory\n");
		goto end;
	}

	rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
	if (rv != SCARD_S_SUCCESS)
		printf("SCardListReader: %ulX\n", rv);

	/* Extract readers from the null separated string and get the total
	 * number of readers */
	nbReaders = 0;
	ptr = mszReaders;
	while (*ptr != '\0')
	{
		ptr += strlen(ptr)+1;
		nbReaders++;
	}

	if (nbReaders == 0)
	{
		printf("No reader found\n");
		goto end;
	}

	/* allocate the readers table */
	readers = calloc(nbReaders, sizeof(char *));
	if (NULL == readers)
	{
		printf("Not enough memory for readers[]\n");
		goto end;
	}

	/* fill the readers table */
	nbReaders = 0;
	ptr = mszReaders;
	printf("Available readers (use command line argument to select)\n");
	while (*ptr != '\0')
	{
		printf("%d: %s\n", nbReaders, ptr);
		readers[nbReaders] = ptr;
		ptr += strlen(ptr)+1;
		nbReaders++;
	}
	printf("\n");

	if (argc > 1)
	{
		reader_nb = atoi(argv[1]);
		if (reader_nb < 0 || reader_nb >= nbReaders)
		{
			printf("Wrong reader index: %d\n", reader_nb);
			goto end;
		}
	}
	else
		reader_nb = 0;

	/* connect to a reader (even without a card) */
	dwActiveProtocol = -1;
	printf("Using reader: " GREEN "%s\n" NORMAL, readers[reader_nb]);
	rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
		SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
	printf(" Protocol: " GREEN "%uld\n" NORMAL, dwActiveProtocol);
	PCSC_ERROR_EXIT(rv, "SCardConnect")

#ifdef GET_GEMPC_FIRMWARE
	/* get GemPC firmware */
	printf(" Get GemPC Firmware\n");

	/* this is specific to Gemalto readers */
	bSendBuffer[0] = 0x02;
	rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
		1, bRecvBuffer, sizeof(bRecvBuffer), &length);

	printf(" Firmware: " GREEN);
	for (i=0; i<length; i++)
		printf("%02X ", bRecvBuffer[i]);
	printf(NORMAL "\n");

	bRecvBuffer[length] = '\0';
	printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);

	PCSC_ERROR_CONT(rv, "SCardControl")
#endif

	/* does the reader support PIN verification? */
	rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
		bRecvBuffer, sizeof(bRecvBuffer), &length);
	PCSC_ERROR_EXIT(rv, "SCardControl")

	printf(" TLV (%uld): " GREEN, length);
	for (i=0; i<length; i++)
		printf("%02X ", bRecvBuffer[i]);
	printf(NORMAL "\n");

	PCSC_ERROR_CONT(rv, "SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)")

	if (length % sizeof(PCSC_TLV_STRUCTURE))
	{
		printf("Inconsistent result! Bad TLV values!\n");
		goto end;
	}

	/* get the number of elements instead of the complete size */
	length /= sizeof(PCSC_TLV_STRUCTURE);

	pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
	for (i = 0; i < length; i++)
	{
		switch (pcsc_tlv[i].tag)
		{
			case FEATURE_VERIFY_PIN_DIRECT:
				PRINT_GREEN("Reader supports", "FEATURE_VERIFY_PIN_DIRECT");
				verify_ioctl = ntohl(pcsc_tlv[i].value);
				break;
			case FEATURE_MODIFY_PIN_DIRECT:
				PRINT_GREEN("Reader supports", "FEATURE_MODIFY_PIN_DIRECT");
				modify_ioctl = ntohl(pcsc_tlv[i].value);
				break;
			case FEATURE_IFD_PIN_PROPERTIES:
				PRINT_GREEN("Reader supports", "FEATURE_IFD_PIN_PROPERTIES");
				pin_properties_ioctl = ntohl(pcsc_tlv[i].value);
				break;
			case FEATURE_MCT_READER_DIRECT:
				PRINT_GREEN("Reader supports", "FEATURE_MCT_READER_DIRECT");
				mct_readerdirect_ioctl = ntohl(pcsc_tlv[i].value);
				break;
			case FEATURE_GET_TLV_PROPERTIES:
				PRINT_GREEN("Reader supports", "FEATURE_GET_TLV_PROPERTIES");
				properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value);
				break;
			case FEATURE_CCID_ESC_COMMAND:
				PRINT_GREEN("Reader supports", "FEATURE_CCID_ESC_COMMAND");
				ccid_esc_command = ntohl(pcsc_tlv[i].value);
				break;
			default:
				PRINT_RED_DEC("Can't parse tag", pcsc_tlv[i].tag);
		}
	}
	printf("\n");

	if (properties_in_tlv_ioctl)
	{
		int value;
		int ret;

		rv = SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0,
			bRecvBuffer, sizeof(bRecvBuffer), &length);
		PCSC_ERROR_CONT(rv, "SCardControl(GET_TLV_PROPERTIES)")

		printf("GET_TLV_PROPERTIES (" GREEN "%uld" NORMAL "): " GREEN, length);
		for (i=0; i<length; i++)
			printf("%02X ", bRecvBuffer[i]);
		printf(NORMAL "\n");

		printf("\nDisplay all the properties:\n");
		parse_properties(bRecvBuffer, length);

		printf("\nFind a specific property:\n");
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_buffer(bRecvBuffer, length, PCSCv2_PART10_PROPERTY_wIdVendor, &value);
		if (ret)
			PRINT_RED_DEC(" wIdVendor", ret);
		else
			PRINT_GREEN_HEX4(" wIdVendor", value);

		ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_wIdProduct, &value);
		if (ret)
			PRINT_RED_DEC(" wIdProduct", ret);
		else
			PRINT_GREEN_HEX4(" wIdProduct", value);

		printf("\n");
	}

	if (mct_readerdirect_ioctl)
	{
		char secoder_info[] = { 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };

		rv = SCardControl(hCard, mct_readerdirect_ioctl, secoder_info,
			sizeof(secoder_info), bRecvBuffer, sizeof(bRecvBuffer), &length);
		PCSC_ERROR_CONT(rv, "SCardControl(MCT_READER_DIRECT)")

		printf("MCT_READER_DIRECT (%uld): ", length);
		for (i=0; i<length; i++)
			printf("%02X ", bRecvBuffer[i]);
		printf("\n");
	}

	if (pin_properties_ioctl)
	{
		PIN_PROPERTIES_STRUCTURE *pin_properties;

		rv = SCardControl(hCard, pin_properties_ioctl, NULL, 0,
			bRecvBuffer, sizeof(bRecvBuffer), &length);
		PCSC_ERROR_CONT(rv, "SCardControl(pin_properties_ioctl)")

		printf("PIN PROPERTIES (" GREEN "%uld" NORMAL "): " GREEN, length);
		for (i=0; i<length; i++)
			printf("%02X ", bRecvBuffer[i]);
		printf(NORMAL "\n");

		pin_properties = (PIN_PROPERTIES_STRUCTURE *)bRecvBuffer;
		PRINT_GREEN_HEX4(" wLcdLayout", pin_properties -> wLcdLayout);
		PRINT_GREEN_DEC(" bEntryValidationCondition", pin_properties ->	bEntryValidationCondition);
		PRINT_GREEN_DEC(" bTimeOut2", pin_properties -> bTimeOut2);

		printf("\n");
	}

#ifdef GET_GEMPC_FIRMWARE
	if (ccid_esc_command)
	{
		/* get GemPC firmware */
		printf("Get GemPC Firmware\n");

		/* this is specific to Gemalto readers */
		bSendBuffer[0] = 0x02;
		rv = SCardControl(hCard, ccid_esc_command, bSendBuffer,
			1, bRecvBuffer, sizeof(bRecvBuffer), &length);

		printf(" Firmware: " GREEN);
		for (i=0; i<length; i++)
			printf("%02X ", bRecvBuffer[i]);
		printf(NORMAL "\n");

		bRecvBuffer[length] = '\0';
		printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);

		PCSC_ERROR_CONT(rv, "SCardControl")
	}
#endif

	if (0 == verify_ioctl)
	{
		printf("Reader %s does not support PIN verification\n",
			readers[reader_nb]);
		goto end;
	}

	/* get card status */
	dwAtrLen = sizeof(pbAtr);
	dwReaderLen = sizeof(pbReader);
	rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
		pbAtr, &dwAtrLen);
	printf(" Reader: %s (length %uld bytes)\n", pbReader, dwReaderLen);
	printf(" State: 0x%04ulX\n", dwState);
	printf(" Prot: %uld\n", dwProt);
	printf(" ATR (length %uld bytes):", dwAtrLen);
	for (i=0; i<dwAtrLen; i++)
		printf(" %02X", pbAtr[i]);
	printf("\n");
	PCSC_ERROR_CONT(rv, "SCardStatus")

	if (dwState & SCARD_ABSENT)
	{
		printf("No card inserted\n");
		goto end;
	}

	/* connect to a reader (even without a card) */
	dwActiveProtocol = -1;
	rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
		SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
		&dwActiveProtocol);
	printf(" Protocol: %uld\n", dwActiveProtocol);
	PCSC_ERROR_EXIT(rv, "SCardReconnect")

	switch(dwActiveProtocol)
	{
		case SCARD_PROTOCOL_T0:
			pioSendPci = *SCARD_PCI_T0;
			break;
		case SCARD_PROTOCOL_T1:
			pioSendPci = *SCARD_PCI_T1;
			break;
		default:
			printf("Unknown protocol. No card present?\n");
			return -1;
	}

	/* APDU select applet */
	printf("Select applet: ");
	send_length = 11;
	memcpy(bSendBuffer, "\x00\xA4\x04\x00\x06\xA0\x00\x00\x00\x18\xFF",
		send_length);
	for (i=0; i<send_length; i++)
		printf(" %02X", bSendBuffer[i]);
	printf("\n");
	length = sizeof(bRecvBuffer);
	rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
		&pioRecvPci, bRecvBuffer, &length);
	printf(" card response:");
	for (i=0; i<length; i++)
		printf(" %02X", bRecvBuffer[i]);
	printf("\n");
	PCSC_ERROR_EXIT(rv, "SCardTransmit")
	if ((bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00))
	{
		printf("Error: test applet not found!\n");
		goto end;
	}

#ifdef VERIFY_PIN
	/* verify PIN */
	printf(" Secure verify PIN\n");
	pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;

	/* table for bEntryValidationCondition
	 * 0x01: Max size reached
	 * 0x02: Validation key pressed
	 * 0x04: Timeout occured
	 */
	/* PC/SC v2.02.05 Part 10 PIN verification data structure */
	pin_verify -> bTimerOut = 0x00;
	pin_verify -> bTimerOut2 = 0x00;
	pin_verify -> bmFormatString = 0x82;
	pin_verify -> bmPINBlockString = 0x04;
	pin_verify -> bmPINLengthFormat = 0x00;
	pin_verify -> wPINMaxExtraDigit = 0x0408; /* Min Max */
	pin_verify -> bEntryValidationCondition = 0x02;	/* validation key pressed */
	pin_verify -> bNumberMessage = 0x01;
	pin_verify -> wLangId = 0x0904;
	pin_verify -> bMsgIndex = 0x00;
	pin_verify -> bTeoPrologue[0] = 0x00;
	pin_verify -> bTeoPrologue[1] = 0x00;
	pin_verify -> bTeoPrologue[2] = 0x00;
	/* pin_verify -> ulDataLength = 0x00; we don't know the size yet */

	/* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
	offset = 0;
	pin_verify -> abData[offset++] = 0x00;	/* CLA */
	pin_verify -> abData[offset++] = 0x20;	/* INS: VERIFY */
	pin_verify -> abData[offset++] = 0x00;	/* P1 */
	pin_verify -> abData[offset++] = 0x00;	/* P2 */
	pin_verify -> abData[offset++] = 0x08;	/* Lc: 8 data bytes */
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
	pin_verify -> ulDataLength = offset;	/* APDU size */

	length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1;	/* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */

	printf(" command:");
	for (i=0; i<length; i++)
		printf(" %02X", bSendBuffer[i]);
	printf("\n");
	printf("Enter your PIN: ");
	fflush(stdout);
	rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
		length, bRecvBuffer, sizeof(bRecvBuffer), &length);

	{
#ifndef S_SPLINT_S
		fd_set fd;
#endif
		struct timeval timeout;

		FD_ZERO(&fd);
		FD_SET(STDIN_FILENO, &fd);	/* stdin */
		timeout.tv_sec = 0;			/* timeout = 0.1s */
		timeout.tv_usec = 100000;

		/* we only try to read stdin if the pinpad is on a keyboard
		 * we do not read stdin for a SPR 532 for example */
		if (select(1, &fd, NULL, NULL, &timeout) > 0)
		{
			/* read the fake digits */
			char in[40];	/* 4 digits + \n + \0 */
			(void)fgets(in, sizeof(in), stdin);

			printf("keyboard sent: %s", in);
		}
		else
			/* if it is not a keyboard */
			printf("\n");
	}

	printf(" card response:");
	for (i=0; i<length; i++)
		printf(" %02X", bRecvBuffer[i]);
	printf("\n");
	PCSC_ERROR_CONT(rv, "SCardControl")

	/* verify PIN dump */
	printf("\nverify PIN dump: ");
	send_length = 5;
	memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
		send_length);
	for (i=0; i<send_length; i++)
		printf(" %02X", bSendBuffer[i]);
	printf("\n");
	length = sizeof(bRecvBuffer);
	rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
		&pioRecvPci, bRecvBuffer, &length);
	printf(" card response:");
	for (i=0; i<length; i++)
		printf(" %02X", bRecvBuffer[i]);
	printf("\n");
	PCSC_ERROR_EXIT(rv, "SCardTransmit")

	if ((2 == length) && (0x6C == bRecvBuffer[0]))
	{
		printf("\nverify PIN dump: ");
		send_length = 5;
		memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
			send_length);
		bSendBuffer[4] = bRecvBuffer[1];
		for (i=0; i<send_length; i++)
			printf(" %02X", bSendBuffer[i]);
		printf("\n");
		length = sizeof(bRecvBuffer);
		rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
			&pioRecvPci, bRecvBuffer, &length);
		printf(" card response:");
		for (i=0; i<length; i++)
			printf(" %02X", bRecvBuffer[i]);
		printf("\n");
		PCSC_ERROR_EXIT(rv, "SCardTransmit")
	}
示例#17
0
static void ContextThread(LPVOID newContext)
{
	SCONTEXT * threadContext = (SCONTEXT *) newContext;
	int32_t filedes = threadContext->dwClientID;

	if (IsClientAuthorized(filedes, "access_pcsc", NULL) == 0)
	{
		Log1(PCSC_LOG_CRITICAL, "Rejected unauthorized PC/SC client");
		goto exit;
	}
	else
	{
		Log1(PCSC_LOG_DEBUG, "Authorized PC/SC client");
	}

	Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%p",
		threadContext->dwClientID, threadContext);

	while (1)
	{
		struct rxHeader header;
		int32_t ret = MessageReceive(&header, sizeof(header), filedes);

		if (ret != SCARD_S_SUCCESS)
		{
			/* Clean up the dead client */
			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
			EHTryToUnregisterClientForEvent(filedes);
			goto exit;
		}

		if ((header.command > CMD_ENUM_FIRST)
			&& (header.command < CMD_ENUM_LAST))
			Log3(PCSC_LOG_DEBUG, "Received command: %s from client %d",
				CommandsText[header.command], filedes);

		switch (header.command)
		{
			/* pcsc-lite client/server protocol version */
			case CMD_VERSION:
			{
				struct version_struct veStr;

				READ_BODY(veStr)

				Log3(PCSC_LOG_DEBUG, "Client is protocol version %d:%d",
					veStr.major, veStr.minor);

				veStr.rv = SCARD_S_SUCCESS;

				/* client and server use different protocol */
				if ((veStr.major != PROTOCOL_VERSION_MAJOR)
					|| (veStr.minor != PROTOCOL_VERSION_MINOR))
				{
					Log3(PCSC_LOG_CRITICAL, "Client protocol is %d:%d",
						veStr.major, veStr.minor);
					Log3(PCSC_LOG_CRITICAL, "Server protocol is %d:%d",
						PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
					veStr.rv = SCARD_E_NO_SERVICE;
				}

				/* set the server protocol version */
				veStr.major = PROTOCOL_VERSION_MAJOR;
				veStr.minor = PROTOCOL_VERSION_MINOR;

				/* send back the response */
				WRITE_BODY(veStr)
			}
			break;

			case CMD_GET_READERS_STATE:
			{
				/* nothing to read */

#ifdef USE_USB
				/* wait until all readers are ready */
				RFWaitForReaderInit();
#endif

				/* dump the readers state */
				ret = MessageSend(readerStates, sizeof(readerStates), filedes);
			}
			break;

			case CMD_WAIT_READER_STATE_CHANGE:
			{
				struct wait_reader_state_change waStr;

				READ_BODY(waStr)

				/* add the client fd to the list */
				EHRegisterClientForEvent(filedes);

				/* We do not send anything here.
				 * Either the client will timeout or the server will
				 * answer if an event occurs */
			}
			break;

			case CMD_STOP_WAITING_READER_STATE_CHANGE:
			{
				struct wait_reader_state_change waStr;

				READ_BODY(waStr)

				/* add the client fd to the list */
				waStr.rv = EHUnregisterClientForEvent(filedes);

				WRITE_BODY(waStr)
			}
			break;

			case SCARD_ESTABLISH_CONTEXT:
			{
				struct establish_struct esStr;
				SCARDCONTEXT hContext;

				READ_BODY(esStr)

				hContext = esStr.hContext;
				esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0,
					&hContext);
				esStr.hContext = hContext;

				if (esStr.rv == SCARD_S_SUCCESS)
					esStr.rv = MSGAddContext(esStr.hContext, threadContext);

				WRITE_BODY(esStr)
			}
			break;

			case SCARD_RELEASE_CONTEXT:
			{
				struct release_struct reStr;

				READ_BODY(reStr)

				reStr.rv = SCardReleaseContext(reStr.hContext);

				if (reStr.rv == SCARD_S_SUCCESS)
					reStr.rv = MSGRemoveContext(reStr.hContext, threadContext);

				WRITE_BODY(reStr)
			}
			break;

			case SCARD_CONNECT:
			{
				struct connect_struct coStr;
				SCARDHANDLE hCard;
				DWORD dwActiveProtocol;

				READ_BODY(coStr)

				coStr.szReader[sizeof(coStr.szReader)-1] = 0;
				hCard = coStr.hCard;
				dwActiveProtocol = coStr.dwActiveProtocol;

				if (IsClientAuthorized(filedes, "access_card", coStr.szReader) == 0)
				{
					Log2(PCSC_LOG_CRITICAL, "Rejected unauthorized client for '%s'", coStr.szReader);
					goto exit;
				}
				else
				{
					Log2(PCSC_LOG_DEBUG, "Authorized client for '%s'", coStr.szReader);
				}

				coStr.rv = SCardConnect(coStr.hContext, coStr.szReader,
					coStr.dwShareMode, coStr.dwPreferredProtocols,
					&hCard, &dwActiveProtocol);

				coStr.hCard = hCard;
				coStr.dwActiveProtocol = dwActiveProtocol;

				if (coStr.rv == SCARD_S_SUCCESS)
					coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
						threadContext);

				WRITE_BODY(coStr)
			}
			break;

			case SCARD_RECONNECT:
			{
				struct reconnect_struct rcStr;
				DWORD dwActiveProtocol;

				READ_BODY(rcStr)

				if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
					goto exit;

				rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
					rcStr.dwPreferredProtocols, rcStr.dwInitialization,
					&dwActiveProtocol);
				rcStr.dwActiveProtocol = dwActiveProtocol;

				WRITE_BODY(rcStr)
			}
			break;

			case SCARD_DISCONNECT:
			{
				struct disconnect_struct diStr;

				READ_BODY(diStr)

				if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
					goto exit;

				diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);

				if (SCARD_S_SUCCESS == diStr.rv)
					diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext);

				WRITE_BODY(diStr)
			}
			break;

			case SCARD_BEGIN_TRANSACTION:
			{
				struct begin_struct beStr;

				READ_BODY(beStr)

				if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
					goto exit;

				beStr.rv = SCardBeginTransaction(beStr.hCard);

				WRITE_BODY(beStr)
			}
			break;

			case SCARD_END_TRANSACTION:
			{
				struct end_struct enStr;

				READ_BODY(enStr)

				if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
					goto exit;

				enStr.rv = SCardEndTransaction(enStr.hCard,
					enStr.dwDisposition);

				WRITE_BODY(enStr)
			}
			break;

			case SCARD_CANCEL:
			{
				struct cancel_struct caStr;
				SCONTEXT * psTargetContext = NULL;
				READ_BODY(caStr)

				/* find the client */
				(void)pthread_mutex_lock(&contextsList_lock);
				psTargetContext = (SCONTEXT *) list_seek(&contextsList,
					&caStr.hContext);
				(void)pthread_mutex_unlock(&contextsList_lock);
				if (psTargetContext != NULL)
				{
					uint32_t fd = psTargetContext->dwClientID;
					caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);

					/* the client should not receive the event
					 * notification now the waiting has been cancelled */
					EHUnregisterClientForEvent(fd);
				}
				else
					caStr.rv = SCARD_E_INVALID_HANDLE;

				WRITE_BODY(caStr)
			}
			break;

			case SCARD_STATUS:
			{
				struct status_struct stStr;

				READ_BODY(stStr)

				if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
					goto exit;

				/* only hCard and return value are used by the client */
				stStr.rv = SCardStatus(stStr.hCard, NULL, NULL, NULL,
					NULL, 0, NULL);

				WRITE_BODY(stStr)
			}
			break;

			case SCARD_TRANSMIT:
			{
				struct transmit_struct trStr;
				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
				SCARD_IO_REQUEST ioSendPci;
				SCARD_IO_REQUEST ioRecvPci;
				DWORD cbRecvLength;

				READ_BODY(trStr)

				if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
					|| (trStr.cbSendLength > sizeof(pbSendBuffer)))
					goto buffer_overflow;

				/* read sent buffer */
				ret = MessageReceive(pbSendBuffer, trStr.cbSendLength, filedes);
				if (ret != SCARD_S_SUCCESS)
				{
					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
					goto exit;
				}

				ioSendPci.dwProtocol = trStr.ioSendPciProtocol;
				ioSendPci.cbPciLength = trStr.ioSendPciLength;
				ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol;
				ioRecvPci.cbPciLength = trStr.ioRecvPciLength;
				cbRecvLength = sizeof pbRecvBuffer;

				trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
					pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
					pbRecvBuffer, &cbRecvLength);

				if (cbRecvLength > trStr.pcbRecvLength)
					/* The client buffer is not large enough.
					 * The pbRecvBuffer buffer will NOT be sent a few
					 * lines bellow. So no buffer overflow is expected. */
					trStr.rv = SCARD_E_INSUFFICIENT_BUFFER;

				trStr.ioSendPciProtocol = ioSendPci.dwProtocol;
				trStr.ioSendPciLength = ioSendPci.cbPciLength;
				trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol;
				trStr.ioRecvPciLength = ioRecvPci.cbPciLength;
				trStr.pcbRecvLength = cbRecvLength;

				WRITE_BODY(trStr)

				/* write received buffer */
				if (SCARD_S_SUCCESS == trStr.rv)
					ret = MessageSend(pbRecvBuffer, cbRecvLength, filedes);
			}
			break;

			case SCARD_CONTROL:
			{
				struct control_struct ctStr;
				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
				DWORD dwBytesReturned;

				READ_BODY(ctStr)

				if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
					|| (ctStr.cbSendLength > sizeof(pbSendBuffer)))
				{
					goto buffer_overflow;
				}

				/* read sent buffer */
				ret = MessageReceive(pbSendBuffer, ctStr.cbSendLength, filedes);
				if (ret != SCARD_S_SUCCESS)
				{
					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
					goto exit;
				}

				dwBytesReturned = ctStr.dwBytesReturned;

				ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
					pbSendBuffer, ctStr.cbSendLength,
					pbRecvBuffer, ctStr.cbRecvLength,
					&dwBytesReturned);

				ctStr.dwBytesReturned = dwBytesReturned;

				WRITE_BODY(ctStr)

				/* write received buffer */
				if (SCARD_S_SUCCESS == ctStr.rv)
					ret = MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
			}
			break;

			case SCARD_GET_ATTRIB:
			{
				struct getset_struct gsStr;
				DWORD cbAttrLen;

				READ_BODY(gsStr)

				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
					goto buffer_overflow;

				cbAttrLen = gsStr.cbAttrLen;

				gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
					gsStr.pbAttr, &cbAttrLen);

				gsStr.cbAttrLen = cbAttrLen;

				WRITE_BODY(gsStr)
			}
			break;

			case SCARD_SET_ATTRIB:
			{
				struct getset_struct gsStr;

				READ_BODY(gsStr)

				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
					goto buffer_overflow;

				gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
					gsStr.pbAttr, gsStr.cbAttrLen);

				WRITE_BODY(gsStr)
			}
			break;

			default:
				Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
				goto exit;
		}

		/* MessageSend() failed */
		if (ret != SCARD_S_SUCCESS)
		{
			/* Clean up the dead client */
			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
			goto exit;
		}
	}

buffer_overflow:
	Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes);
	goto exit;
wrong_length:
	Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
exit:
	(void)close(filedes);
	(void)MSGCleanupClient(threadContext);
	(void)pthread_exit((LPVOID) NULL);
}