libwinpr-smartcard: dynamically load pcsclite

This commit is contained in:
Marc-André Moreau 2014-04-02 22:08:04 -04:00
parent c1f1ae2f65
commit d5ca2162ad
3 changed files with 369 additions and 14 deletions

View File

@ -23,7 +23,84 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifndef _WIN32
#include <winpr/error.h>
#ifdef _WIN32
#include <winscard.h>
#else
#ifndef SCARD_S_SUCCESS
#define SCARD_S_SUCCESS NO_ERROR
#endif
#define SCARD_F_INTERNAL_ERROR ((DWORD)0x80100001L)
#define SCARD_E_CANCELLED ((DWORD)0x80100002L)
#define SCARD_E_INVALID_HANDLE ((DWORD)0x80100003L)
#define SCARD_E_INVALID_PARAMETER ((DWORD)0x80100004L)
#define SCARD_E_INVALID_TARGET ((DWORD)0x80100005L)
#define SCARD_E_NO_MEMORY ((DWORD)0x80100006L)
#define SCARD_F_WAITED_TOO_LONG ((DWORD)0x80100007L)
#define SCARD_E_INSUFFICIENT_BUFFER ((DWORD)0x80100008L)
#define SCARD_E_UNKNOWN_READER ((DWORD)0x80100009L)
#define SCARD_E_TIMEOUT ((DWORD)0x8010000AL)
#define SCARD_E_SHARING_VIOLATION ((DWORD)0x8010000BL)
#define SCARD_E_NO_SMARTCARD ((DWORD)0x8010000CL)
#define SCARD_E_UNKNOWN_CARD ((DWORD)0x8010000DL)
#define SCARD_E_CANT_DISPOSE ((DWORD)0x8010000EL)
#define SCARD_E_PROTO_MISMATCH ((DWORD)0x8010000FL)
#define SCARD_E_NOT_READY ((DWORD)0x80100010L)
#define SCARD_E_INVALID_VALUE ((DWORD)0x80100011L)
#define SCARD_E_SYSTEM_CANCELLED ((DWORD)0x80100012L)
#define SCARD_F_COMM_ERROR ((DWORD)0x80100013L)
#define SCARD_F_UNKNOWN_ERROR ((DWORD)0x80100014L)
#define SCARD_E_INVALID_ATR ((DWORD)0x80100015L)
#define SCARD_E_NOT_TRANSACTED ((DWORD)0x80100016L)
#define SCARD_E_READER_UNAVAILABLE ((DWORD)0x80100017L)
#define SCARD_P_SHUTDOWN ((DWORD)0x80100018L)
#define SCARD_E_PCI_TOO_SMALL ((DWORD)0x80100019L)
#define SCARD_E_READER_UNSUPPORTED ((DWORD)0x8010001AL)
#define SCARD_E_DUPLICATE_READER ((DWORD)0x8010001BL)
#define SCARD_E_CARD_UNSUPPORTED ((DWORD)0x8010001CL)
#define SCARD_E_NO_SERVICE ((DWORD)0x8010001DL)
#define SCARD_E_SERVICE_STOPPED ((DWORD)0x8010001EL)
#define SCARD_E_UNEXPECTED ((DWORD)0x8010001FL)
#define SCARD_E_ICC_INSTALLATION ((DWORD)0x80100020L)
#define SCARD_E_ICC_CREATEORDER ((DWORD)0x80100021L)
#define SCARD_E_UNSUPPORTED_FEATURE ((DWORD)0x80100022L)
#define SCARD_E_DIR_NOT_FOUND ((DWORD)0x80100023L)
#define SCARD_E_FILE_NOT_FOUND ((DWORD)0x80100024L)
#define SCARD_E_NO_DIR ((DWORD)0x80100025L)
#define SCARD_E_NO_FILE ((DWORD)0x80100026L)
#define SCARD_E_NO_ACCESS ((DWORD)0x80100027L)
#define SCARD_E_WRITE_TOO_MANY ((DWORD)0x80100028L)
#define SCARD_E_BAD_SEEK ((DWORD)0x80100029L)
#define SCARD_E_INVALID_CHV ((DWORD)0x8010002AL)
#define SCARD_E_UNKNOWN_RES_MNG ((DWORD)0x8010002BL)
#define SCARD_E_NO_SUCH_CERTIFICATE ((DWORD)0x8010002CL)
#define SCARD_E_CERTIFICATE_UNAVAILABLE ((DWORD)0x8010002DL)
#define SCARD_E_NO_READERS_AVAILABLE ((DWORD)0x8010002EL)
#define SCARD_E_COMM_DATA_LOST ((DWORD)0x8010002FL)
#define SCARD_E_NO_KEY_CONTAINER ((DWORD)0x80100030L)
#define SCARD_E_SERVER_TOO_BUSY ((DWORD)0x80100031L)
#define SCARD_E_PIN_CACHE_EXPIRED ((DWORD)0x80100032L)
#define SCARD_E_NO_PIN_CACHE ((DWORD)0x80100033L)
#define SCARD_E_READ_ONLY_CARD ((DWORD)0x80100034L)
#define SCARD_W_UNSUPPORTED_CARD ((DWORD)0x80100065L)
#define SCARD_W_UNRESPONSIVE_CARD ((DWORD)0x80100066L)
#define SCARD_W_UNPOWERED_CARD ((DWORD)0x80100067L)
#define SCARD_W_RESET_CARD ((DWORD)0x80100068L)
#define SCARD_W_REMOVED_CARD ((DWORD)0x80100069L)
#define SCARD_W_SECURITY_VIOLATION ((DWORD)0x8010006AL)
#define SCARD_W_WRONG_CHV ((DWORD)0x8010006BL)
#define SCARD_W_CHV_BLOCKED ((DWORD)0x8010006CL)
#define SCARD_W_EOF ((DWORD)0x8010006DL)
#define SCARD_W_CANCELLED_BY_USER ((DWORD)0x8010006EL)
#define SCARD_W_CARD_NOT_AUTHENTICATED ((DWORD)0x8010006FL)
#define SCARD_W_CACHE_ITEM_NOT_FOUND ((DWORD)0x80100070L)
#define SCARD_W_CACHE_ITEM_STALE ((DWORD)0x80100071L)
#define SCARD_W_CACHE_ITEM_TOO_BIG ((DWORD)0x80100072L)
#define SCARD_ATR_LENGTH 33

View File

@ -22,6 +22,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/library.h>
#include <winpr/smartcard.h>
#ifndef _WIN32
@ -31,61 +32,191 @@
/**
* libpcsclite.so.1:
*
* SCardBeginTransaction
* SCardCancel
* SCardConnect
* SCardControl
* SCardDisconnect
* SCardEndTransaction
* SCardEstablishContext
* SCardFreeMemory
* SCardGetAttrib
* SCardGetStatusChange
* SCardReleaseContext
* SCardIsValidContext
* SCardConnect
* SCardReconnect
* SCardDisconnect
* SCardBeginTransaction
* SCardEndTransaction
* SCardStatus
* SCardGetStatusChange
* SCardControl
* SCardTransmit
* SCardListReaderGroups
* SCardListReaders
* SCardReconnect
* SCardReleaseContext
* SCardFreeMemory
* SCardCancel
* SCardGetAttrib
* SCardSetAttrib
* SCardStatus
* SCardTransmit
*/
struct _PCSCLiteFunctionTable
{
LONG (* pfnSCardEstablishContext)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
LONG (* pfnSCardReleaseContext)(SCARDCONTEXT hContext);
LONG (* pfnSCardIsValidContext)(SCARDCONTEXT hContext);
LONG (* pfnSCardConnect)(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);
LONG (* pfnSCardReconnect)(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols,
DWORD dwInitialization, LPDWORD pdwActiveProtocol);
LONG (* pfnSCardDisconnect)(SCARDHANDLE hCard, DWORD dwDisposition);
LONG (* pfnSCardBeginTransaction)(SCARDHANDLE hCard);
LONG (* pfnSCardEndTransaction)(SCARDHANDLE hCard, DWORD dwDisposition);
LONG (* pfnSCardStatus)(SCARDHANDLE hCard,
LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen);
LONG (* pfnSCardGetStatusChange)(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders);
LONG (* pfnSCardControl)(SCARDHANDLE hCard,
DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength,
LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned);
LONG (* pfnSCardTransmit)(SCARDHANDLE hCard,
const SCARD_IO_REQUEST* pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
SCARD_IO_REQUEST* pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
LONG (* pfnSCardListReaderGroups)(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups);
LONG (* pfnSCardListReaders)(SCARDCONTEXT hContext,
LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders);
LONG (* pfnSCardFreeMemory)(SCARDCONTEXT hContext, LPCVOID pvMem);
LONG (* pfnSCardCancel)(SCARDCONTEXT hContext);
LONG (* pfnSCardGetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen);
LONG (* pfnSCardSetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen);
};
typedef struct _PCSCLiteFunctionTable PCSCLiteFunctionTable;
static BOOL g_Initialized = FALSE;
static HMODULE g_PCSCLiteModule = NULL;
static PCSCLiteFunctionTable* g_PCSCLite = NULL;
void InitializePCSCLite(void)
{
if (g_PCSCLite)
return;
g_PCSCLiteModule = LoadLibraryA("libpcsclite.so.1");
if (!g_PCSCLiteModule)
return;
g_PCSCLite = calloc(1, sizeof(PCSCLiteFunctionTable));
if (!g_PCSCLite)
return;
g_PCSCLite->pfnSCardEstablishContext = GetProcAddress(g_PCSCLiteModule, "SCardEstablishContext");
g_PCSCLite->pfnSCardReleaseContext = GetProcAddress(g_PCSCLiteModule, "SCardReleaseContext");
g_PCSCLite->pfnSCardIsValidContext = GetProcAddress(g_PCSCLiteModule, "SCardIsValidContext");
g_PCSCLite->pfnSCardConnect = GetProcAddress(g_PCSCLiteModule, "SCardConnect");
g_PCSCLite->pfnSCardReconnect = GetProcAddress(g_PCSCLiteModule, "SCardReconnect");
g_PCSCLite->pfnSCardDisconnect = GetProcAddress(g_PCSCLiteModule, "SCardDisconnect");
g_PCSCLite->pfnSCardBeginTransaction = GetProcAddress(g_PCSCLiteModule, "SCardBeginTransaction");
g_PCSCLite->pfnSCardEndTransaction = GetProcAddress(g_PCSCLiteModule, "SCardEndTransaction");
g_PCSCLite->pfnSCardStatus = GetProcAddress(g_PCSCLiteModule, "SCardStatus");
g_PCSCLite->pfnSCardGetStatusChange = GetProcAddress(g_PCSCLiteModule, "SCardGetStatusChange");
g_PCSCLite->pfnSCardControl = GetProcAddress(g_PCSCLiteModule, "SCardControl");
g_PCSCLite->pfnSCardTransmit = GetProcAddress(g_PCSCLiteModule, "SCardTransmit");
g_PCSCLite->pfnSCardListReaderGroups = GetProcAddress(g_PCSCLiteModule, "SCardListReaderGroups");
g_PCSCLite->pfnSCardListReaders = GetProcAddress(g_PCSCLiteModule, "SCardListReaders");
g_PCSCLite->pfnSCardFreeMemory = GetProcAddress(g_PCSCLiteModule, "SCardFreeMemory");
g_PCSCLite->pfnSCardCancel = GetProcAddress(g_PCSCLiteModule, "SCardCancel");
g_PCSCLite->pfnSCardGetAttrib = GetProcAddress(g_PCSCLiteModule, "SCardGetAttrib");
g_PCSCLite->pfnSCardSetAttrib = GetProcAddress(g_PCSCLiteModule, "SCardSetAttrib");
}
void InitializeSCardStubs(void)
{
if (g_Initialized)
return;
g_Initialized = TRUE;
InitializePCSCLite();
}
/**
* Standard Windows Smart Card API
*/
WINSCARDAPI LONG WINAPI SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardEstablishContext)
{
return g_PCSCLite->pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardReleaseContext(SCARDCONTEXT hContext)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardReleaseContext)
{
return g_PCSCLite->pfnSCardReleaseContext(hContext);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardIsValidContext(SCARDCONTEXT hContext)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardIsValidContext)
{
return g_PCSCLite->pfnSCardIsValidContext(hContext);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardListReaderGroupsA(SCARDCONTEXT hContext,
LPSTR mszGroups, LPDWORD pcchGroups)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardListReaderGroups)
{
return g_PCSCLite->pfnSCardListReaderGroups(hContext, mszGroups, pcchGroups);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardListReaderGroupsW(SCARDCONTEXT hContext,
LPWSTR mszGroups, LPDWORD pcchGroups)
{
InitializeSCardStubs();
return 0;
}
WINSCARDAPI LONG WINAPI SCardListReadersA(SCARDCONTEXT hContext,
LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardListReaders)
{
return g_PCSCLite->pfnSCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardListReadersW(SCARDCONTEXT hContext,
LPCWSTR mszGroups, LPWSTR mszReaders, LPDWORD pcchReaders)
{
InitializeSCardStubs();
return 0;
}
@ -229,6 +360,13 @@ WINSCARDAPI LONG WINAPI SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCa
WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardFreeMemory)
{
return g_PCSCLite->pfnSCardFreeMemory(hContext, pvMem);
}
return 0;
}
@ -258,6 +396,7 @@ WINSCARDAPI LONG WINAPI SCardLocateCardsByATRA(SCARDCONTEXT hContext,
{
return 0;
}
WINSCARDAPI LONG WINAPI SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
@ -267,11 +406,21 @@ WINSCARDAPI LONG WINAPI SCardLocateCardsByATRW(SCARDCONTEXT hContext,
WINSCARDAPI LONG WINAPI SCardGetStatusChangeA(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardGetStatusChange)
{
return g_PCSCLite->pfnSCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardGetStatusChangeW(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
InitializeSCardStubs();
return 0;
}
@ -279,38 +428,80 @@ WINSCARDAPI LONG WINAPI SCardConnectA(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardConnect)
{
return g_PCSCLite->pfnSCardConnect(hContext, szReader,
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardConnectW(SCARDCONTEXT hContext,
LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
InitializeSCardStubs();
return 0;
}
WINSCARDAPI LONG WINAPI SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardReconnect)
{
return g_PCSCLite->pfnSCardReconnect(hCard, dwShareMode,
dwPreferredProtocols, dwInitialization, pdwActiveProtocol);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardDisconnect)
{
return g_PCSCLite->pfnSCardDisconnect(hCard, dwDisposition);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardBeginTransaction(SCARDHANDLE hCard)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardBeginTransaction)
{
return g_PCSCLite->pfnSCardBeginTransaction(hCard);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardEndTransaction)
{
return g_PCSCLite->pfnSCardEndTransaction(hCard, dwDisposition);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardCancelTransaction(SCARDHANDLE hCard)
{
InitializeSCardStubs();
return 0;
}
@ -324,12 +515,23 @@ WINSCARDAPI LONG WINAPI SCardStatusA(SCARDHANDLE hCard,
LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardStatus)
{
return g_PCSCLite->pfnSCardStatus(hCard, mszReaderNames, pcchReaderLen,
pdwState, pdwProtocol, pbAtr, pcbAtrLen);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardStatusW(SCARDHANDLE hCard,
LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
InitializeSCardStubs();
return 0;
}
@ -337,6 +539,14 @@ WINSCARDAPI LONG WINAPI SCardTransmit(SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardTransmit)
{
return g_PCSCLite->pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer,
cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
}
return 0;
}
@ -349,16 +559,39 @@ WINSCARDAPI LONG WINAPI SCardControl(SCARDHANDLE hCard,
DWORD dwControlCode, LPCVOID lpInBuffer, DWORD cbInBufferSize,
LPVOID lpOutBuffer, DWORD cbOutBufferSize, LPDWORD lpBytesReturned)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardControl)
{
return g_PCSCLite->pfnSCardControl(hCard,
dwControlCode, lpInBuffer, cbInBufferSize,
lpOutBuffer, cbOutBufferSize, lpBytesReturned);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardGetAttrib)
{
return g_PCSCLite->pfnSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardSetAttrib)
{
return g_PCSCLite->pfnSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
}
return 0;
}

View File

@ -4,6 +4,51 @@
int TestSmartCardListReaders(int argc, char* argv[])
{
LONG lStatus;
LPTSTR pReader;
SCARDCONTEXT hSC;
LPTSTR pmszReaders = NULL;
DWORD cch = SCARD_AUTOALLOCATE;
lStatus = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSC);
if (lStatus != SCARD_S_SUCCESS)
{
printf("SCardEstablishContext failure: 0x%04X\n", (int) lStatus);
return -1;
}
lStatus = SCardListReaders(hSC, NULL, (LPTSTR) &pmszReaders, &cch);
if (lStatus != SCARD_S_SUCCESS)
{
if (lStatus == SCARD_E_NO_READERS_AVAILABLE)
{
printf("SCARD_E_NO_READERS_AVAILABLE\n");
}
else
{
return -1;
}
}
else
{
pReader = pmszReaders;
while (*pReader)
{
printf("Reader: %s\n", pReader);
pReader = pReader + strlen((CHAR*) pReader) + 1;
}
lStatus = SCardFreeMemory(hSC, pmszReaders);
if (lStatus != SCARD_S_SUCCESS)
printf("Failed SCardFreeMemory\n");
}
SCardReleaseContext(hSC);
return 0;
}