mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 19:08:26 -06:00
If an error happens, error message will be read from popen pipe and so libpcsclite.so will not be found. This is the same outcome as when stdout is empty.
402 lines
12 KiB
C++
402 lines
12 KiB
C++
#include "SCardLoader.h"
|
|
#include "PCSCException.h"
|
|
|
|
#ifndef TC_WINDOWS
|
|
#include <dlfcn.h>
|
|
#define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL)
|
|
#define FreeLibrary(x) dlclose(x)
|
|
#define GetProcAddress(x, y) dlsym(x, y)
|
|
typedef void* HMODULE;
|
|
#ifdef TC_MACOSX
|
|
#if !defined(USE_SCARD_CONTROL_112)
|
|
#define SCardControlName "SCardControl132"
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#endif
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#endif
|
|
#define SCardConnectName "SCardConnect"
|
|
#define SCardStatusName "SCardStatus"
|
|
#define SCardGetStatusChangeName "SCardGetStatusChange"
|
|
#define SCardListReaderGroupsName "SCardListReaderGroups"
|
|
#define SCardListReadersName "SCardListReaders"
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#define SCardConnectName "SCardConnectW"
|
|
#define SCardStatusName "SCardStatusW"
|
|
#define SCardGetStatusChangeName "SCardGetStatusChangeW"
|
|
#define SCardListReaderGroupsName "SCardListReaderGroupsW"
|
|
#define SCardListReadersName "SCardListReadersW"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
namespace VeraCrypt
|
|
{
|
|
HMODULE SCardLoader::hScardModule = NULL;
|
|
SCARDCONTEXT SCardLoader::hScardContext = 0;
|
|
SCardEstablishContextPtr SCardLoader::scardEstablishContext = NULL;
|
|
SCardReleaseContextPtr SCardLoader::scardReleaseContext = NULL;
|
|
SCardIsValidContextPtr SCardLoader::scardIsValidContext = NULL;
|
|
#ifndef TC_MACOSX
|
|
SCardFreeMemoryPtr SCardLoader::scardFreeMemory = NULL;
|
|
#endif
|
|
SCardConnectPtr SCardLoader::scardConnect = NULL;
|
|
SCardReconnectPtr SCardLoader::scardReconnect = NULL;
|
|
SCardDisconnectPtr SCardLoader::scardDisconnect = NULL;
|
|
SCardBeginTransactionPtr SCardLoader::scardBeginTransaction = NULL;
|
|
SCardEndTransactionPtr SCardLoader::scardEndTransaction = NULL;
|
|
SCardStatusPtr SCardLoader::scardStatus = NULL;
|
|
SCardGetStatusChangePtr SCardLoader::scardGetStatusChange = NULL;
|
|
SCardControlPtr SCardLoader::scardControl = NULL;
|
|
SCardTransmitPtr SCardLoader::scardTransmit = NULL;
|
|
SCardListReaderGroupsPtr SCardLoader::scardListReaderGroups = NULL;
|
|
SCardListReadersPtr SCardLoader::scardListReaders = NULL;
|
|
SCardCancelPtr SCardLoader::scardCancel = NULL;
|
|
SCardGetAttribPtr SCardLoader::scardGetAttrib = NULL;
|
|
SCardSetAttribPtr SCardLoader::scardSetAttrib = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardT0Pci = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardT1Pci = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardRawPci = NULL;
|
|
bool SCardLoader::bInitialized = false;
|
|
|
|
#ifdef TC_WINDOWS
|
|
wstring SCardLoader::GetSCardPath()
|
|
#else
|
|
string SCardLoader::GetSCardPath()
|
|
#endif
|
|
{
|
|
#ifdef TC_WINDOWS
|
|
wchar_t winscardPath[TC_MAX_PATH];
|
|
if (GetSystemDirectory(winscardPath, TC_MAX_PATH))
|
|
{
|
|
StringCbCat(winscardPath, sizeof(winscardPath), L"\\Winscard.dll");
|
|
}
|
|
else
|
|
StringCbCopy(winscardPath, sizeof(winscardPath), L"C:\\Windows\\System32\\Winscard.dll");
|
|
return winscardPath;
|
|
#elif TC_MACOSX
|
|
return "/System/Library/Frameworks/PCSC.framework/PCSC";
|
|
#else
|
|
string pcscPath = "";
|
|
FILE* pipe =
|
|
#ifdef TC_LINUX
|
|
popen("ldconfig -p 2>&1", "r");
|
|
#else
|
|
popen("ldconfig -r 2>&1", "r"); // FreeBSD
|
|
#endif
|
|
if (pipe)
|
|
{
|
|
char buffer[128];
|
|
while (!feof(pipe))
|
|
{
|
|
if (fgets(buffer, 128, pipe) != NULL)
|
|
{
|
|
string line(buffer);
|
|
if (line.find("libpcsclite.so") != string::npos)
|
|
{
|
|
size_t pos = line.find("=>");
|
|
if (pos != string::npos)
|
|
{
|
|
pcscPath = line.substr(pos + 3);
|
|
pos = pcscPath.find_first_of(" \t\r\n");
|
|
if (pos != string::npos)
|
|
pcscPath = pcscPath.substr(0, pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pclose(pipe);
|
|
}
|
|
|
|
if (pcscPath == "")
|
|
{
|
|
pcscPath = "libpcsclite.so";
|
|
}
|
|
|
|
return pcscPath;
|
|
#endif
|
|
}
|
|
|
|
void SCardLoader::Initialize()
|
|
{
|
|
if (bInitialized)
|
|
return;
|
|
|
|
hScardModule = LoadLibrary(GetSCardPath().c_str());
|
|
if (hScardModule)
|
|
{
|
|
scardEstablishContext = (SCardEstablishContextPtr)GetProcAddress(hScardModule, "SCardEstablishContext");
|
|
scardReleaseContext = (SCardReleaseContextPtr)GetProcAddress(hScardModule, "SCardReleaseContext");
|
|
scardIsValidContext = (SCardIsValidContextPtr)GetProcAddress(hScardModule, "SCardIsValidContext");
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory = (SCardFreeMemoryPtr)GetProcAddress(hScardModule, "SCardFreeMemory");
|
|
#endif
|
|
scardConnect = (SCardConnectPtr)GetProcAddress(hScardModule, SCardConnectName);
|
|
scardReconnect = (SCardReconnectPtr)GetProcAddress(hScardModule, "SCardReconnect");
|
|
scardDisconnect = (SCardDisconnectPtr)GetProcAddress(hScardModule, "SCardDisconnect");
|
|
scardBeginTransaction = (SCardBeginTransactionPtr)GetProcAddress(hScardModule, "SCardBeginTransaction");
|
|
scardEndTransaction = (SCardEndTransactionPtr)GetProcAddress(hScardModule, "SCardEndTransaction");
|
|
scardStatus = (SCardStatusPtr)GetProcAddress(hScardModule, SCardStatusName);
|
|
scardGetStatusChange = (SCardGetStatusChangePtr)GetProcAddress(hScardModule, SCardGetStatusChangeName);
|
|
scardControl = (SCardControlPtr)GetProcAddress(hScardModule, SCardControlName);
|
|
scardTransmit = (SCardTransmitPtr)GetProcAddress(hScardModule, "SCardTransmit");
|
|
scardListReaderGroups = (SCardListReaderGroupsPtr)GetProcAddress(hScardModule, SCardListReaderGroupsName);
|
|
scardListReaders = (SCardListReadersPtr)GetProcAddress(hScardModule, SCardListReadersName);
|
|
scardCancel = (SCardCancelPtr)GetProcAddress(hScardModule, "SCardCancel");
|
|
scardGetAttrib = (SCardGetAttribPtr)GetProcAddress(hScardModule, "SCardGetAttrib");
|
|
scardSetAttrib = (SCardSetAttribPtr)GetProcAddress(hScardModule, "SCardSetAttrib");
|
|
scardT0Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT0Pci");
|
|
scardT1Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT1Pci");
|
|
scardRawPci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardRawPci");
|
|
if (
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory &&
|
|
#endif
|
|
scardEstablishContext && scardReleaseContext && scardIsValidContext && scardConnect && scardReconnect && scardDisconnect &&
|
|
scardBeginTransaction && scardEndTransaction && scardStatus && scardGetStatusChange && scardControl && scardTransmit &&
|
|
scardListReaderGroups && scardListReaders && scardCancel && scardGetAttrib && scardSetAttrib && scardT0Pci && scardT1Pci && scardRawPci)
|
|
{
|
|
if (SCARD_S_SUCCESS == scardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hScardContext))
|
|
{
|
|
bInitialized = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bInitialized)
|
|
{
|
|
Finalize();
|
|
}
|
|
}
|
|
|
|
void SCardLoader::Finalize()
|
|
{
|
|
if (hScardContext)
|
|
{
|
|
scardReleaseContext(hScardContext);
|
|
hScardContext = 0;
|
|
}
|
|
|
|
if (hScardModule)
|
|
{
|
|
FreeLibrary(hScardModule);
|
|
hScardModule = NULL;
|
|
}
|
|
|
|
scardEstablishContext = NULL;
|
|
scardReleaseContext = NULL;
|
|
scardIsValidContext = NULL;
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory = NULL;
|
|
#endif
|
|
scardConnect = NULL;
|
|
scardReconnect = NULL;
|
|
scardDisconnect = NULL;
|
|
scardBeginTransaction = NULL;
|
|
scardEndTransaction = NULL;
|
|
scardStatus = NULL;
|
|
scardGetStatusChange = NULL;
|
|
scardControl = NULL;
|
|
scardTransmit = NULL;
|
|
scardListReaderGroups = NULL;
|
|
scardListReaders = NULL;
|
|
scardCancel = NULL;
|
|
scardGetAttrib = NULL;
|
|
scardSetAttrib = NULL;
|
|
scardT0Pci = NULL;
|
|
scardT1Pci = NULL;
|
|
scardRawPci = NULL;
|
|
|
|
bInitialized = false;
|
|
}
|
|
|
|
SCARDCONTEXT SCardLoader::GetSCardContext()
|
|
{
|
|
return hScardContext;
|
|
}
|
|
|
|
LONG SCardLoader::SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardReleaseContext(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardReleaseContext(hContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardIsValidContext(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardIsValidContext(hContext);
|
|
}
|
|
|
|
#ifndef TC_MACOSX
|
|
LONG SCardLoader::SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardFreeMemory(hContext, pvMem);
|
|
}
|
|
#endif
|
|
|
|
LONG SCardLoader::SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardConnect(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
|
}
|
|
|
|
LONG SCardLoader::SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardReconnect(hCard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol);
|
|
}
|
|
|
|
LONG SCardLoader::SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardDisconnect(hCard, dwDisposition);
|
|
}
|
|
|
|
LONG SCardLoader::SCardBeginTransaction(SCARDHANDLE hCard)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardBeginTransaction(hCard);
|
|
}
|
|
|
|
LONG SCardLoader::SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardEndTransaction(hCard, dwDisposition);
|
|
}
|
|
|
|
LONG SCardLoader::SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardStatus(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
|
|
}
|
|
|
|
LONG SCardLoader::SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
|
|
}
|
|
|
|
LONG SCardLoader::SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
|
|
}
|
|
|
|
LONG SCardLoader::SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
|
|
}
|
|
|
|
LONG SCardLoader::SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardListReaderGroups(hContext, mszGroups, pcchGroups);
|
|
}
|
|
|
|
LONG SCardLoader::SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
|
|
}
|
|
|
|
LONG SCardLoader::SCardCancel(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardCancel(hContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
|
|
}
|
|
|
|
LONG SCardLoader::SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
|
|
}
|
|
} |