38#define p_SCardEstablishContext(fct) LONG(fct)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
40#define p_SCardReleaseContext(fct) LONG(fct)(SCARDCONTEXT hContext)
42#define p_SCardIsValidContext(fct) LONG(fct) (SCARDCONTEXT hContext)
44#define p_SCardConnect(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
46#define p_SCardReconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
48#define p_SCardDisconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
50#define p_SCardBeginTransaction(fct) LONG(fct) (SCARDHANDLE hCard)
52#define p_SCardEndTransaction(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
54#define p_SCardStatus(fct) LONG(fct) (SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
56#define p_SCardGetStatusChange(fct) LONG(fct) (SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
58#define p_SCardControl(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
60#define p_SCardTransmit(fct) LONG(fct) (SCARDHANDLE hCard, const SCARD_IO_REQUEST * pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST * pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
62#define p_SCardListReaderGroups(fct) LONG(fct) (SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
64#define p_SCardListReaders(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
66#define p_SCardFreeMemory(fct) LONG(fct) (SCARDCONTEXT hContext, LPCVOID pvMem)
68#define p_SCardCancel(fct) LONG(fct) (SCARDCONTEXT hContext)
70#define p_SCardGetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
72#define p_SCardSetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
75static LONG internal_error(
void)
80#pragma GCC diagnostic push
81#pragma GCC diagnostic ignored "-Wcast-function-type"
85 p_SCardEstablishContext(*SCardEstablishContext);
86 p_SCardReleaseContext(*SCardReleaseContext);
87 p_SCardIsValidContext(*SCardIsValidContext);
88 p_SCardConnect(*SCardConnect);
89 p_SCardReconnect(*SCardReconnect);
90 p_SCardDisconnect(*SCardDisconnect);
91 p_SCardBeginTransaction(*SCardBeginTransaction);
92 p_SCardEndTransaction(*SCardEndTransaction);
93 p_SCardStatus(*SCardStatus);
94 p_SCardGetStatusChange(*SCardGetStatusChange);
95 p_SCardControl(*SCardControl);
96 p_SCardTransmit(*SCardTransmit);
97 p_SCardListReaderGroups(*SCardListReaderGroups);
98 p_SCardListReaders(*SCardListReaders);
99 p_SCardFreeMemory(*SCardFreeMemory);
100 p_SCardCancel(*SCardCancel);
101 p_SCardGetAttrib(*SCardGetAttrib);
102 p_SCardSetAttrib(*SCardSetAttrib);
105 .SCardEstablishContext = (p_SCardEstablishContext(*))internal_error,
106 .SCardReleaseContext = (p_SCardReleaseContext(*))internal_error,
107 .SCardIsValidContext = (p_SCardIsValidContext(*))internal_error,
108 .SCardConnect = (p_SCardConnect(*))internal_error,
109 .SCardReconnect = (p_SCardReconnect(*))internal_error,
110 .SCardDisconnect = (p_SCardDisconnect(*))internal_error,
111 .SCardBeginTransaction = (p_SCardBeginTransaction(*))internal_error,
112 .SCardEndTransaction = (p_SCardEndTransaction(*))internal_error,
113 .SCardStatus = (p_SCardStatus(*))internal_error,
114 .SCardGetStatusChange = (p_SCardGetStatusChange(*))internal_error,
115 .SCardControl = (p_SCardControl(*))internal_error,
116 .SCardTransmit = (p_SCardTransmit(*))internal_error,
117 .SCardListReaderGroups = (p_SCardListReaderGroups(*))internal_error,
118 .SCardListReaders = (p_SCardListReaders(*))internal_error,
119 .SCardFreeMemory = (p_SCardFreeMemory(*))internal_error,
120 .SCardCancel = (p_SCardCancel(*))internal_error,
121 .SCardGetAttrib = (p_SCardGetAttrib(*))internal_error,
122 .SCardSetAttrib = (p_SCardSetAttrib(*))internal_error,
124#pragma GCC diagnostic pop
126#define LOG log_line("%s:%d", __FILE__, __LINE__)
128static int Log_fd = -1;
129static void *Lib_handle = NULL;
130static pthread_mutex_t Log_fd_mutex = PTHREAD_MUTEX_INITIALIZER;
133static void log_line(
const char *fmt, ...)
143static void log_line(
const char *fmt, ...)
148static void spy_line_direct(
char *line)
157 snprintf(threadid,
sizeof threadid,
"%lX@", pthread_self());
158 pthread_mutex_lock(&Log_fd_mutex);
159 r = write(Log_fd, threadid, strlen(threadid));
160 r = write(Log_fd, line, strlen(line));
161 r = write(Log_fd,
"\n", 1);
163 pthread_mutex_unlock(&Log_fd_mutex);
166static void spy_line(
const char *fmt, ...)
179 size = vsnprintf(line,
sizeof line, fmt, args);
181 if ((
size_t)size >=
sizeof line)
183 printf(
"libpcsc-spy: Buffer is too small!\n");
186 snprintf(threadid,
sizeof threadid,
"%lX@", pthread_self());
187 pthread_mutex_lock(&Log_fd_mutex);
188 r = write(Log_fd, threadid, strlen(threadid));
189 r = write(Log_fd, line, size);
190 r = write(Log_fd,
"\n", 1);
192 pthread_mutex_unlock(&Log_fd_mutex);
195static void spy_enter(
const char *fname)
197 struct timeval profile_time;
199 gettimeofday(&profile_time, NULL);
200 spy_line(
">|%ld|%ld|%s", profile_time.tv_sec, profile_time.tv_usec, fname);
203static void spy_quit(
const char *fname, LONG rv)
205 struct timeval profile_time;
207 gettimeofday(&profile_time, NULL);
208 spy_line(
"<|%ld|%ld|%s|%s|0x%08lX", profile_time.tv_sec,
212#define Enter() spy_enter(__FUNCTION__)
213#define Quit() spy_quit(__FUNCTION__, rv)
215static void spy_long(
long arg)
217 spy_line(
"0x%08lX", arg);
220static void spy_ptr_long(LONG *arg)
223 spy_line(
"0x%08lX", *arg);
228static void spy_ptr_ulong(ULONG *arg)
231 spy_line(
"0x%08lX", *arg);
236static void spy_pvoid(
const void *ptr)
241static void spy_buffer(
const unsigned char *buffer,
size_t length)
250 char log_buffer[length * 3 +1], *p;
254 log_buffer[0] =
'\0';
255 for (i=0; i<length; i++)
257 snprintf(p, 4,
"%02X ", buffer[i]);
262 spy_line_direct(log_buffer);
266static void spy_str(
const char *str)
271static void spy_n_str(
const char *str, ULONG *len,
int autoallocate)
287 unsigned int length = 0;
295 length += strlen(s)+1;
297 }
while(length < *len);
307 for (i=0; i<cReaders; i++)
309 spy_str(rgReaderStates[i].szReader);
310 spy_long(rgReaderStates[i].dwCurrentState);
311 spy_long(rgReaderStates[i].dwEventState);
313 spy_buffer(rgReaderStates[i].rgbAtr, rgReaderStates[i].cbAtr);
315 spy_buffer(NULL, rgReaderStates[i].cbAtr);
319static LONG load_lib(
void)
322#define LIBPCSC "libpcsclite_real.so.1"
331 Lib_handle = dlopen(lib, RTLD_LAZY);
332 if (NULL == Lib_handle)
334 log_line(
"loading \"%s\" failed: %s", lib, dlerror());
338#define get_symbol(s) do { spy.s = dlsym(Lib_handle, #s); if (NULL == spy.s) { log_line("%s", dlerror()); return SCARD_F_INTERNAL_ERROR; } } while (0)
340 if (SCardEstablishContext == dlsym(Lib_handle,
"SCardEstablishContext"))
342 log_line(
"Symbols dlsym error");
346 get_symbol(SCardEstablishContext);
347 get_symbol(SCardReleaseContext);
348 get_symbol(SCardIsValidContext);
349 get_symbol(SCardConnect);
350 get_symbol(SCardReconnect);
351 get_symbol(SCardDisconnect);
352 get_symbol(SCardBeginTransaction);
353 get_symbol(SCardEndTransaction);
354 get_symbol(SCardStatus);
355 get_symbol(SCardGetStatusChange);
356 get_symbol(SCardControl);
357 get_symbol(SCardTransmit);
358 get_symbol(SCardListReaderGroups);
359 get_symbol(SCardListReaders);
361 if (dlsym(Lib_handle,
"SCardFreeMemory"))
362 get_symbol(SCardFreeMemory);
363 get_symbol(SCardCancel);
364 get_symbol(SCardGetAttrib);
365 get_symbol(SCardSetAttrib);
372PCSC_API p_SCardEstablishContext(SCardEstablishContext)
394 snprintf(log_pipe,
sizeof log_pipe,
"%s/pcsc-spy", home);
395 Log_fd = open(log_pipe, O_WRONLY);
398 log_line(
"open %s failed: %s", log_pipe, strerror(errno));
404 rv = spy.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
406 spy_ptr_long(phContext);
411PCSC_API p_SCardReleaseContext(SCardReleaseContext)
417 rv = spy.SCardReleaseContext(hContext);
422PCSC_API p_SCardIsValidContext(SCardIsValidContext)
428 rv = spy.SCardIsValidContext(hContext);
433PCSC_API p_SCardConnect(SCardConnect)
440 spy_long(dwShareMode);
441 spy_long(dwPreferredProtocols);
442 spy_ptr_long(phCard);
443 spy_ptr_ulong(pdwActiveProtocol);
444 rv = spy.SCardConnect(hContext, szReader, dwShareMode,
445 dwPreferredProtocols, phCard, pdwActiveProtocol);
446 spy_ptr_long(phCard);
447 spy_ptr_ulong(pdwActiveProtocol);
452PCSC_API p_SCardReconnect(SCardReconnect)
458 spy_long(dwShareMode);
459 spy_long(dwPreferredProtocols);
460 spy_long(dwInitialization);
461 rv = spy.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
462 dwInitialization, pdwActiveProtocol);
463 spy_ptr_ulong(pdwActiveProtocol);
468PCSC_API p_SCardDisconnect(SCardDisconnect)
474 spy_long(dwDisposition);
475 rv = spy.SCardDisconnect(hCard, dwDisposition);
480PCSC_API p_SCardBeginTransaction(SCardBeginTransaction)
486 rv = spy.SCardBeginTransaction(hCard);
491PCSC_API p_SCardEndTransaction(SCardEndTransaction)
497 spy_long(dwDisposition);
498 rv = spy.SCardEndTransaction(hCard, dwDisposition);
503PCSC_API p_SCardStatus(SCardStatus)
506 int autoallocate_ReaderName = 0, autoallocate_Atr = 0;
516 spy_ptr_ulong(pcchReaderLen);
517 spy_ptr_ulong(pcbAtrLen);
518 rv = spy.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
519 pdwProtocol, pbAtr, pcbAtrLen);
520 spy_n_str(mszReaderName, pcchReaderLen, autoallocate_ReaderName);
521 spy_ptr_ulong(pdwState);
522 spy_ptr_ulong(pdwProtocol);
523 if (NULL == pcbAtrLen)
529 if (autoallocate_Atr)
530 buffer = *(LPBYTE *)pbAtr;
534 spy_buffer(buffer, *pcbAtrLen);
540PCSC_API p_SCardGetStatusChange(SCardGetStatusChange)
548 spy_readerstate(rgReaderStates, cReaders);
549 rv = spy.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
551 spy_readerstate(rgReaderStates, cReaders);
556PCSC_API p_SCardControl(SCardControl)
562 spy_long(dwControlCode);
563 spy_buffer(pbSendBuffer, cbSendLength);
564 rv = spy.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
565 pbRecvBuffer, cbRecvLength, lpBytesReturned);
567 spy_buffer(pbRecvBuffer, *lpBytesReturned);
574PCSC_API p_SCardTransmit(SCardTransmit)
582 spy_long(pioSendPci->dwProtocol);
583 spy_long(pioSendPci->cbPciLength);
590 spy_buffer(pbSendBuffer, cbSendLength);
591 rv = spy.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
592 pioRecvPci, pbRecvBuffer, pcbRecvLength);
595 spy_long(pioRecvPci->dwProtocol);
596 spy_long(pioRecvPci->cbPciLength);
604 spy_buffer(pbRecvBuffer, *pcbRecvLength);
611PCSC_API p_SCardListReaderGroups(SCardListReaderGroups)
614 int autoallocate = 0;
621 spy_ptr_ulong(pcchGroups);
622 rv = spy.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
624 spy_n_str(mszGroups, pcchGroups, autoallocate);
626 spy_n_str(NULL, pcchGroups, 0);
631PCSC_API p_SCardListReaders(SCardListReaders)
634 int autoallocate = 0;
642 rv = spy.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
644 spy_n_str(mszReaders, pcchReaders, autoallocate);
646 spy_n_str(NULL, pcchReaders, 0);
651PCSC_API p_SCardFreeMemory(SCardFreeMemory)
658 rv = spy.SCardFreeMemory(hContext, pvMem);
663PCSC_API p_SCardCancel(SCardCancel)
669 rv = spy.SCardCancel(hContext);
674PCSC_API p_SCardGetAttrib(SCardGetAttrib)
677 int autoallocate = 0;
685 rv = spy.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
686 if (NULL == pcbAttrLen)
693 buffer = *(LPBYTE *)pbAttr;
697 spy_buffer(buffer, *pcbAttrLen);
703PCSC_API p_SCardSetAttrib(SCardSetAttrib)
710 spy_buffer(pbAttr, cbAttrLen);
711 rv = spy.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
PCSC_API const char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
#define SCARD_S_SUCCESS
No error was encountered.
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
#define MAX_ATR_SIZE
Maximum ATR size.
This handles abstract system level calls.
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
This handles smart card reader communications.