libwinpr-smartcard: improve SCardGetAttrib, fix null SCARDCONTEXT usage in SCardListReaders

This commit is contained in:
Marc-André Moreau
2014-05-03 17:07:30 -04:00
parent 86b018ee21
commit b51da6c6f4
2 changed files with 210 additions and 95 deletions

View File

@@ -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;
}

View File

@@ -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)