From b51da6c6f4c07cae66a502febf4315499ff5c8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 3 May 2014 17:07:30 -0400 Subject: [PATCH] libwinpr-smartcard: improve SCardGetAttrib, fix null SCARDCONTEXT usage in SCardListReaders --- channels/smartcard/client/smartcard_pack.c | 26 +- winpr/libwinpr/smartcard/smartcard_pcsc.c | 279 ++++++++++++++------- 2 files changed, 210 insertions(+), 95 deletions(-) diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index 6cbfb98b0..322333c95 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -155,7 +155,7 @@ SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartca { SCARDCONTEXT hContext = 0; - if (context->cbContext != sizeof(ULONG_PTR)) + if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0)) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT does not match native size: Actual: %d, Expected: %d", @@ -165,6 +165,8 @@ SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartca if (context->cbContext) CopyMemory(&hContext, &(context->pbContext), context->cbContext); + else + ZeroMemory(&hContext, sizeof(ULONG_PTR)); return hContext; } @@ -216,21 +218,28 @@ UINT32 smartcard_unpack_redir_scard_context(SMARTCARD_DEVICE* smartcard, wStream Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */ - if ((Stream_GetRemainingLength(s) < context->cbContext) || (!context->cbContext)) + if (Stream_GetRemainingLength(s) < context->cbContext) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d", (int) Stream_GetRemainingLength(s), context->cbContext); return STATUS_BUFFER_TOO_SMALL; } - if ((context->cbContext != 4) && (context->cbContext != 8)) + if ((context->cbContext != 0) && (context->cbContext != 4) && (context->cbContext != 8)) { - WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT length is not 4 or 8: %d\n", context->cbContext); + WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %d\n", context->cbContext); return STATUS_INVALID_PARAMETER; } Stream_Read_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */ + if (((context->cbContext == 0) && pbContextNdrPtr) || ((context->cbContext != 0) && !pbContextNdrPtr)) + { + WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT cbContext (%d) pbContextNdrPtr (%d) inconsistency", + (int) context->cbContext, (int) pbContextNdrPtr); + return STATUS_INVALID_PARAMETER; + } + if (context->cbContext > Stream_GetRemainingLength(s)) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too long: Actual: %d, Expected: %d", @@ -257,6 +266,9 @@ UINT32 smartcard_unpack_redir_scard_context_ref(SMARTCARD_DEVICE* smartcard, wSt { UINT32 length; + if (context->cbContext == 0) + return SCARD_S_SUCCESS; + if (Stream_GetRemainingLength(s) < 4) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d\n", @@ -273,13 +285,13 @@ UINT32 smartcard_unpack_redir_scard_context_ref(SMARTCARD_DEVICE* smartcard, wSt return STATUS_INVALID_PARAMETER; } - if ((context->cbContext != 4) && (context->cbContext != 8)) + if ((context->cbContext != 0) && (context->cbContext != 4) && (context->cbContext != 8)) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT length is not 4 or 8: %d\n", context->cbContext); return STATUS_INVALID_PARAMETER; } - if ((Stream_GetRemainingLength(s) < context->cbContext) || (!context->cbContext)) + if (Stream_GetRemainingLength(s) < context->cbContext) { WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d\n", (int) Stream_GetRemainingLength(s), context->cbContext); @@ -288,6 +300,8 @@ UINT32 smartcard_unpack_redir_scard_context_ref(SMARTCARD_DEVICE* smartcard, wSt if (context->cbContext) Stream_Read(s, &(context->pbContext), context->cbContext); + else + ZeroMemory(&(context->pbContext), sizeof(context->pbContext)); return SCARD_S_SUCCESS; } diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 472570b4a..0f9eb100e 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -495,6 +495,18 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) return nameWinSCard; } +char* PCSC_GetReaderAliasFromName(char* namePCSC) +{ + char* nameWinSCard; + + nameWinSCard = PCSC_ConvertReaderNameToWinSCard(namePCSC); + + if (nameWinSCard) + PCSC_AddReaderNameAlias(namePCSC, nameWinSCard); + + return nameWinSCard; +} + char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders) { int length; @@ -516,12 +528,10 @@ char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders) while ((p - names) < cchReaders) { - nameWinSCard = PCSC_ConvertReaderNameToWinSCard(p); + nameWinSCard = PCSC_GetReaderAliasFromName(p); if (nameWinSCard) { - PCSC_AddReaderNameAlias(p, nameWinSCard); - length = strlen(nameWinSCard); CopyMemory(q, nameWinSCard, length); free(nameWinSCard); @@ -667,7 +677,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, status = (LONG) g_PCSC.pfnSCardEstablishContext(pcsc_dwScope, pvReserved1, pvReserved2, phContext); status = PCSC_MapErrorCodeToWinSCard(status); - if (!status) + if (status == SCARD_S_SUCCESS) PCSC_EstablishCardContext(*phContext); return status; @@ -824,11 +834,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) { + BOOL nullCardContext = FALSE; LONG status = SCARD_S_SUCCESS; + LPSTR* pMszReaders = (LPSTR*) mszReaders; if (!g_PCSC.pfnSCardListReaders) return SCARD_E_NO_SERVICE; + if (!hContext) + { + status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + + if (status != SCARD_S_SUCCESS) + return status; + + nullCardContext = TRUE; + } + if (!PCSC_LockCardContext(hContext)) return SCARD_E_INVALID_HANDLE; @@ -837,6 +859,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, if (!PCSC_UnlockCardContext(hContext)) return SCARD_E_INVALID_HANDLE; + if (nullCardContext) + { + status = PCSC_SCardReleaseContext(hContext); + } + return status; } @@ -847,10 +874,21 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPSTR mszReadersA = NULL; LPSTR* pMszReadersA = &mszReadersA; LONG status = SCARD_S_SUCCESS; + BOOL nullCardContext = FALSE; if (!g_PCSC.pfnSCardListReaders) return SCARD_E_NO_SERVICE; + if (!hContext) + { + status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + + if (status != SCARD_S_SUCCESS) + return status; + + nullCardContext = TRUE; + } + if (!PCSC_LockCardContext(hContext)) return SCARD_E_INVALID_HANDLE; @@ -874,6 +912,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, if (!PCSC_UnlockCardContext(hContext)) return SCARD_E_INVALID_HANDLE; + if (nullCardContext) + { + status = PCSC_SCardReleaseContext(hContext); + } + return status; } @@ -1052,13 +1095,19 @@ WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMe { LONG status = SCARD_S_SUCCESS; - if (!PCSC_LockCardContext(hContext)) - return SCARD_E_INVALID_HANDLE; + if (hContext) + { + if (!PCSC_LockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; + } status = PCSC_SCardFreeMemory_Internal(hContext, pvMem); - if (!PCSC_UnlockCardContext(hContext)) - return SCARD_E_INVALID_HANDLE; + if (hContext) + { + if (!PCSC_UnlockCardContext(hContext)) + return SCARD_E_INVALID_HANDLE; + } return status; } @@ -1842,6 +1891,129 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dw return status; } +WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +{ + int length = 0; + char* namePCSC; + char* nameWinSCard; + char* pbAttrA = NULL; + WCHAR* pbAttrW = NULL; + SCARDCONTEXT hContext; + char* friendlyNameA = NULL; + WCHAR* friendlyNameW = NULL; + LONG status = SCARD_S_SUCCESS; + LPBYTE* pPbAttr = (LPBYTE*) pbAttr; + + hContext = PCSC_GetCardContextFromHandle(hCard); + + if (!hContext) + return SCARD_E_INVALID_HANDLE; + + *pcbAttrLen = SCARD_AUTOALLOCATE; + + status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, + (LPBYTE) &pbAttrA, pcbAttrLen); + + if (status != SCARD_S_SUCCESS) + { + pbAttrA = NULL; + *pcbAttrLen = SCARD_AUTOALLOCATE; + + status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, + (LPBYTE) &pbAttrW, pcbAttrLen); + + if (status != SCARD_S_SUCCESS) + return status; + + length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, + *pcbAttrLen, (char**) &pbAttrA, 0, NULL, NULL); + + namePCSC = pbAttrA; + PCSC_SCardFreeMemory_Internal(hContext, pbAttrW); + } + else + { + namePCSC = _strdup(pbAttrA); + + if (!namePCSC) + return SCARD_E_NO_MEMORY; + + PCSC_SCardFreeMemory_Internal(hContext, pbAttrA); + } + + length = strlen(namePCSC); + nameWinSCard = PCSC_GetReaderAliasFromName(namePCSC); + + if (nameWinSCard) + { + length = strlen(nameWinSCard); + friendlyNameA = _strdup(nameWinSCard); + + if (!friendlyNameA) + return SCARD_E_NO_MEMORY; + } + else + { + friendlyNameA = namePCSC; + } + + if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) + { + length = ConvertToUnicode(CP_UTF8, 0, (char*) friendlyNameA, -1, &friendlyNameW, 0); + + free(friendlyNameA); + + if (!friendlyNameW) + return SCARD_E_NO_MEMORY; + + if (*pcbAttrLen == SCARD_AUTOALLOCATE) + { + *pPbAttr = (BYTE*) friendlyNameW; + *pcbAttrLen = length * 2; + PCSC_AddMemoryBlock(hContext, *pPbAttr); + } + else + { + if (((length + 1) * 2) > *pcbAttrLen) + { + free(friendlyNameW); + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + CopyMemory(pbAttr, (BYTE*) friendlyNameW, ((length + 1) * 2)); + *pcbAttrLen = length * 2; + free(friendlyNameW); + } + } + } + else + { + if (*pcbAttrLen == SCARD_AUTOALLOCATE) + { + *pPbAttr = (BYTE*) friendlyNameA; + *pcbAttrLen = length; + PCSC_AddMemoryBlock(hContext, *pPbAttr); + } + else + { + if ((length + 1) > *pcbAttrLen) + { + free(friendlyNameA); + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + CopyMemory(pbAttr, (BYTE*) friendlyNameA, length + 1); + *pcbAttrLen = length; + free(friendlyNameA); + } + } + } + + return status; +} + WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) { DWORD cbAttrLen; @@ -1865,6 +2037,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L hContext = PCSC_GetCardContextFromHandle(hCard); + if (!hContext) + return SCARD_E_INVALID_HANDLE; + + if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) || (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)) + { + return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen); + } + status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen); if (status == SCARD_S_SUCCESS) @@ -1884,86 +2064,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L } else { - if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) - { - WCHAR* pbAttrW = NULL; - - *pcbAttrLen = SCARD_AUTOALLOCATE; - - status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, - (LPBYTE) &pbAttrW, pcbAttrLen); - - if (status == SCARD_S_SUCCESS) - { - int length; - char* pbAttrA = NULL; - - length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, - *pcbAttrLen, (char**) &pbAttrA, 0, NULL, NULL); - - PCSC_SCardFreeMemory_Internal(hContext, pbAttrW); - - if (pcbAttrLenAlloc) - { - PCSC_AddMemoryBlock(hContext, pbAttrA); - *pPbAttr = (BYTE*) pbAttrA; - *pcbAttrLen = length; - } - else - { - if (length > cbAttrLen) - { - free(pbAttrA); - return SCARD_E_INSUFFICIENT_BUFFER; - } - else - { - CopyMemory(pbAttr, (BYTE*) pbAttrA, length); - *pcbAttrLen = length; - } - } - } - } - else if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) - { - char* pbAttrA = NULL; - - *pcbAttrLen = SCARD_AUTOALLOCATE; - - status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, - (LPBYTE) &pbAttrA, pcbAttrLen); - - if (status == SCARD_S_SUCCESS) - { - int length; - WCHAR* pbAttrW = NULL; - - length = ConvertToUnicode(CP_UTF8, 0, (char*) pbAttr, *pcbAttrLen, &pbAttrW, 0); - - PCSC_SCardFreeMemory_Internal(hContext, pbAttrA); - - if (pcbAttrLenAlloc) - { - PCSC_AddMemoryBlock(hContext, pbAttrW); - *pPbAttr = (BYTE*) pbAttrW; - *pcbAttrLen = length; - } - else - { - if (length > cbAttrLen) - { - free(pbAttrW); - return SCARD_E_INSUFFICIENT_BUFFER; - } - else - { - CopyMemory(pbAttr, (BYTE*) pbAttrW, length); - *pcbAttrLen = length; - } - } - } - } - else if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE) + if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE) { PCSC_DWORD dwState = 0; PCSC_DWORD cbAtrLen = 0; @@ -1979,7 +2080,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L if (cbAttrLen < 4) return SCARD_E_INSUFFICIENT_BUFFER; - *pdwProtocol = dwProtocol; + *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(dwProtocol); } } else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)