From 9ebc67ba029eafe937be7409431d7ec90a98b690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 22 Dec 2014 16:25:59 -0500 Subject: [PATCH] channels/smartcard: cleanup SCardControl --- channels/smartcard/client/smartcard_main.c | 2 - .../smartcard/client/smartcard_operations.c | 7 +- winpr/include/winpr/smartcard.h | 80 ++++++++++--------- winpr/libwinpr/smartcard/smartcard_pcsc.c | 52 ++++++++---- winpr/libwinpr/smartcard/smartcard_pcsc.h | 34 ++++---- 5 files changed, 98 insertions(+), 77 deletions(-) diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index f501d7717..131802aea 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -508,8 +508,6 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) smartcard->log = WLog_Get("com.freerdp.channel.smartcard.client"); - //WLog_SetLogLevel(smartcard->log, WLOG_DEBUG); - smartcard->IrpQueue = MessageQueue_New(NULL); smartcard->rgSCardContextList = ListDictionary_New(TRUE); smartcard->rgOutstandingMessages = ListDictionary_New(TRUE); diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index 6133d5c48..6e923c33c 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -550,7 +550,8 @@ static UINT32 smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE } status = ret.ReturnCode = SCardConnectA(operation->hContext, (char*) call->szReader, call->Common.dwShareMode, - call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); + call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); + smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext); smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard); smartcard_trace_connect_return(smartcard, &ret); @@ -580,6 +581,7 @@ static UINT32 smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_O status = smartcard_unpack_connect_w_call(smartcard, irp->input, call); smartcard_trace_connect_w_call(smartcard, call); operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); + return status; } @@ -597,7 +599,8 @@ static UINT32 smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE } status = ret.ReturnCode = SCardConnectW(operation->hContext, (WCHAR*) call->szReader, call->Common.dwShareMode, - call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); + call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); + smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext); smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard); smartcard_trace_connect_return(smartcard, &ret); diff --git a/winpr/include/winpr/smartcard.h b/winpr/include/winpr/smartcard.h index fa6cbfcd8..482e3b20e 100644 --- a/winpr/include/winpr/smartcard.h +++ b/winpr/include/winpr/smartcard.h @@ -104,53 +104,55 @@ #endif -#define SCARD_ATR_LENGTH 33 +#define SCARD_ATR_LENGTH 33 -#define SCARD_PROTOCOL_UNDEFINED 0x00000000 -#define SCARD_PROTOCOL_T0 0x00000001 -#define SCARD_PROTOCOL_T1 0x00000002 -#define SCARD_PROTOCOL_RAW 0x00010000 +#define SCARD_PROTOCOL_UNDEFINED 0x00000000 +#define SCARD_PROTOCOL_T0 0x00000001 +#define SCARD_PROTOCOL_T1 0x00000002 +#define SCARD_PROTOCOL_RAW 0x00010000 -#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) -#define SCARD_PROTOCOL_DEFAULT 0x80000000 -#define SCARD_PROTOCOL_OPTIMAL 0x00000000 +#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) +#define SCARD_PROTOCOL_DEFAULT 0x80000000 +#define SCARD_PROTOCOL_OPTIMAL 0x00000000 -#define SCARD_POWER_DOWN 0 -#define SCARD_COLD_RESET 1 -#define SCARD_WARM_RESET 2 +#define SCARD_POWER_DOWN 0 +#define SCARD_COLD_RESET 1 +#define SCARD_WARM_RESET 2 -#define SCARD_CTL_CODE(code) CTL_CODE(FILE_DEVICE_SMARTCARD, (code), METHOD_BUFFERED, FILE_ANY_ACCESS) +#define SCARD_CTL_CODE(code) CTL_CODE(FILE_DEVICE_SMARTCARD, (code), METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SMARTCARD_POWER SCARD_CTL_CODE(1) -#define IOCTL_SMARTCARD_GET_ATTRIBUTE SCARD_CTL_CODE(2) -#define IOCTL_SMARTCARD_SET_ATTRIBUTE SCARD_CTL_CODE(3) -#define IOCTL_SMARTCARD_CONFISCATE SCARD_CTL_CODE(4) -#define IOCTL_SMARTCARD_TRANSMIT SCARD_CTL_CODE(5) -#define IOCTL_SMARTCARD_EJECT SCARD_CTL_CODE(6) -#define IOCTL_SMARTCARD_SWALLOW SCARD_CTL_CODE(7) -#define IOCTL_SMARTCARD_IS_PRESENT SCARD_CTL_CODE(10) -#define IOCTL_SMARTCARD_IS_ABSENT SCARD_CTL_CODE(11) -#define IOCTL_SMARTCARD_SET_PROTOCOL SCARD_CTL_CODE(12) -#define IOCTL_SMARTCARD_GET_STATE SCARD_CTL_CODE(14) -#define IOCTL_SMARTCARD_GET_LAST_ERROR SCARD_CTL_CODE(15) -#define IOCTL_SMARTCARD_GET_PERF_CNTR SCARD_CTL_CODE(16) +#define IOCTL_SMARTCARD_POWER SCARD_CTL_CODE(1) +#define IOCTL_SMARTCARD_GET_ATTRIBUTE SCARD_CTL_CODE(2) +#define IOCTL_SMARTCARD_SET_ATTRIBUTE SCARD_CTL_CODE(3) +#define IOCTL_SMARTCARD_CONFISCATE SCARD_CTL_CODE(4) +#define IOCTL_SMARTCARD_TRANSMIT SCARD_CTL_CODE(5) +#define IOCTL_SMARTCARD_EJECT SCARD_CTL_CODE(6) +#define IOCTL_SMARTCARD_SWALLOW SCARD_CTL_CODE(7) +#define IOCTL_SMARTCARD_IS_PRESENT SCARD_CTL_CODE(10) +#define IOCTL_SMARTCARD_IS_ABSENT SCARD_CTL_CODE(11) +#define IOCTL_SMARTCARD_SET_PROTOCOL SCARD_CTL_CODE(12) +#define IOCTL_SMARTCARD_GET_STATE SCARD_CTL_CODE(14) +#define IOCTL_SMARTCARD_GET_LAST_ERROR SCARD_CTL_CODE(15) +#define IOCTL_SMARTCARD_GET_PERF_CNTR SCARD_CTL_CODE(16) -#define MAXIMUM_ATTR_STRING_LENGTH 32 -#define MAXIMUM_SMARTCARD_READERS 10 +#define IOCTL_SMARTCARD_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) -#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) +#define MAXIMUM_ATTR_STRING_LENGTH 32 +#define MAXIMUM_SMARTCARD_READERS 10 -#define SCARD_CLASS_VENDOR_INFO 1 -#define SCARD_CLASS_COMMUNICATIONS 2 -#define SCARD_CLASS_PROTOCOL 3 -#define SCARD_CLASS_POWER_MGMT 4 -#define SCARD_CLASS_SECURITY 5 -#define SCARD_CLASS_MECHANICAL 6 -#define SCARD_CLASS_VENDOR_DEFINED 7 -#define SCARD_CLASS_IFD_PROTOCOL 8 -#define SCARD_CLASS_ICC_STATE 9 -#define SCARD_CLASS_PERF 0x7FFE -#define SCARD_CLASS_SYSTEM 0x7FFF +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) + +#define SCARD_CLASS_VENDOR_INFO 1 +#define SCARD_CLASS_COMMUNICATIONS 2 +#define SCARD_CLASS_PROTOCOL 3 +#define SCARD_CLASS_POWER_MGMT 4 +#define SCARD_CLASS_SECURITY 5 +#define SCARD_CLASS_MECHANICAL 6 +#define SCARD_CLASS_VENDOR_DEFINED 7 +#define SCARD_CLASS_IFD_PROTOCOL 8 +#define SCARD_CLASS_ICC_STATE 9 +#define SCARD_CLASS_PERF 0x7FFE +#define SCARD_CLASS_SYSTEM 0x7FFF #define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) #define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index bc5527962..5b7d0c31b 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -180,9 +180,8 @@ static wListDictionary* g_MemoryBlocks = NULL; char SMARTCARD_PNP_NOTIFICATION_A[] = "\\\\?PnP?\\Notification"; -WCHAR SMARTCARD_PNP_NOTIFICATION_W[] = { '\\','\\','?','P','n','P','?', - '\\','N','o','t','i','f','i','c','a','t','i','o','n','\0' - }; +WCHAR SMARTCARD_PNP_NOTIFICATION_W[] = +{ '\\','\\','?','P','n','P','?','\\','N','o','t','i','f','i','c','a','t','i','o','n','\0' }; const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(PCSC_SCARD_IO_REQUEST) }; const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PCSC_SCARD_IO_REQUEST) }; @@ -745,7 +744,8 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) char* PCSC_GetReaderAliasFromName(char* namePCSC) { - char* nameWinSCard; + char* nameWinSCard = NULL; + nameWinSCard = PCSC_ConvertReaderNameToWinSCard(namePCSC); if (nameWinSCard) @@ -1636,8 +1636,10 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext, pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED; else pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); + status = (LONG) g_PCSC.pfnSCardConnect(hPrivateContext, szReaderPCSC, - pcsc_dwShareMode, pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol); + pcsc_dwShareMode, pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol); + status = PCSC_MapErrorCodeToWinSCard(status); if (status == SCARD_S_SUCCESS) @@ -1663,7 +1665,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, return SCARD_E_INVALID_HANDLE; status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, - dwPreferredProtocols, phCard, pdwActiveProtocol); + dwPreferredProtocols, phCard, pdwActiveProtocol); if (!PCSC_UnlockCardContext(hContext)) return SCARD_E_INVALID_HANDLE; @@ -1685,7 +1687,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, ConvertFromUnicode(CP_UTF8, 0, szReader, -1, &szReaderA, 0, NULL, NULL); status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, - dwPreferredProtocols, phCard, pdwActiveProtocol); + dwPreferredProtocols, phCard, pdwActiveProtocol); free(szReaderA); if (!PCSC_UnlockCardContext(hContext)) @@ -2115,36 +2117,52 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, if (!g_PCSC.pfnSCardControl) return SCARD_E_NO_SERVICE; + /** + * PCSCv2 Part 10: + * http://www.pcscworkgroup.com/specifications/files/pcsc10_v2.02.09.pdf + * + * Smart Card Driver IOCTLs: + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff548988/ + * + * Converting Windows Feature Request IOCTL code to the pcsc-lite control code: + * http://musclecard.996296.n3.nabble.com/Converting-Windows-Feature-Request-IOCTL-code-to-the-pcsc-lite-control-code-td4906.html + */ + IoCtlMethod = METHOD_FROM_CTL_CODE(dwControlCode); IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode); IoCtlAccess = ACCESS_FROM_CTL_CODE(dwControlCode); IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode); - if (dwControlCode == PCSC_CM_IOCTL_GET_FEATURE_REQUEST) + if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST) getFeatureRequest = TRUE; if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD) dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction); pcsc_dwControlCode = (PCSC_DWORD) dwControlCode; + status = (LONG) g_PCSC.pfnSCardControl(hCard, - pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize, - lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned); + pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize, + lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned); + status = PCSC_MapErrorCodeToWinSCard(status); *lpBytesReturned = (DWORD) pcsc_BytesReturned; if (getFeatureRequest) { - UINT32 ioCtlValue; + UINT32 index; + UINT32 count; PCSC_TLV_STRUCTURE* tlv = (PCSC_TLV_STRUCTURE*) lpOutBuffer; - void* lpOutBufferEnd = (void*) &((BYTE*) lpOutBuffer)[*lpBytesReturned]; - for (; ((void*) tlv) < lpOutBufferEnd; tlv++) + if ((*lpBytesReturned % sizeof(PCSC_TLV_STRUCTURE)) != 0) + return SCARD_E_UNEXPECTED; + + count = *lpBytesReturned / sizeof(PCSC_TLV_STRUCTURE); + + for (index = 0; index < count; index++) { - ioCtlValue = _byteswap_ulong(tlv->value); - ioCtlValue -= 0x42000000; /* inverse of PCSC_SCARD_CTL_CODE() */ - ioCtlValue = SCARD_CTL_CODE(ioCtlValue); - tlv->value = _byteswap_ulong(ioCtlValue); + if (tlv[index].length != 4) + return SCARD_E_UNEXPECTED; } } diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.h b/winpr/libwinpr/smartcard/smartcard_pcsc.h index a25dd64be..af3ec9de7 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.h +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.h @@ -53,30 +53,30 @@ typedef PCSC_ULONG *PCSC_PULONG; typedef long PCSC_LONG; #endif -#define PCSC_SCARD_UNKNOWN 0x0001 -#define PCSC_SCARD_ABSENT 0x0002 -#define PCSC_SCARD_PRESENT 0x0004 -#define PCSC_SCARD_SWALLOWED 0x0008 -#define PCSC_SCARD_POWERED 0x0010 -#define PCSC_SCARD_NEGOTIABLE 0x0020 -#define PCSC_SCARD_SPECIFIC 0x0040 +#define PCSC_SCARD_UNKNOWN 0x0001 +#define PCSC_SCARD_ABSENT 0x0002 +#define PCSC_SCARD_PRESENT 0x0004 +#define PCSC_SCARD_SWALLOWED 0x0008 +#define PCSC_SCARD_POWERED 0x0010 +#define PCSC_SCARD_NEGOTIABLE 0x0020 +#define PCSC_SCARD_SPECIFIC 0x0040 -#define PCSC_SCARD_PROTOCOL_RAW 0x00000004 -#define PCSC_SCARD_PROTOCOL_T15 0x00000008 +#define PCSC_SCARD_PROTOCOL_RAW 0x00000004 +#define PCSC_SCARD_PROTOCOL_T15 0x00000008 -#define PCSC_MAX_BUFFER_SIZE 264 -#define PCSC_MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1 << 16) + 3 + 2) +#define PCSC_MAX_BUFFER_SIZE 264 +#define PCSC_MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1 << 16) + 3 + 2) -#define PCSC_MAX_ATR_SIZE 33 +#define PCSC_MAX_ATR_SIZE 33 -#define PCSC_SCARD_AUTOALLOCATE (PCSC_DWORD)(-1) +#define PCSC_SCARD_AUTOALLOCATE (PCSC_DWORD)(-1) -#define PCSC_SCARD_PCI_T0 (&g_PCSC_rgSCardT0Pci) -#define PCSC_SCARD_PCI_T1 (&g_PCSC_rgSCardT1Pci) -#define PCSC_SCARD_PCI_RAW (&g_PCSC_rgSCardRawPci) +#define PCSC_SCARD_PCI_T0 (&g_PCSC_rgSCardT0Pci) +#define PCSC_SCARD_PCI_T1 (&g_PCSC_rgSCardT1Pci) +#define PCSC_SCARD_PCI_RAW (&g_PCSC_rgSCardRawPci) #define PCSC_SCARD_CTL_CODE(code) (0x42000000 + (code)) -#define PCSC_CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) +#define PCSC_CM_IOCTL_GET_FEATURE_REQUEST PCSC_SCARD_CTL_CODE(3400) /** * pcsc-lite defines SCARD_READERSTATE, SCARD_IO_REQUEST as packed