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 ; }
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; }
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; } }
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)); } }
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; }
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); }
/* * 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; }
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; }
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; }
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; }
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 ; }
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") }
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); }