mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
libwinpr-smartcard: improve SCardGetAttrib, fix null SCARDCONTEXT usage in SCardListReaders
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user