36#define DLSYM_DECLARE(symbol) \
37 typeof(symbol)* symbol
38#define DLSYM_SET_VALUE(symbol) \
39 .symbol = (typeof(symbol)(*))internal_error
42static LONG internal_error(
void)
47#pragma GCC diagnostic push
48#pragma GCC diagnostic ignored "-Wcast-function-type"
52 DLSYM_DECLARE(SCardEstablishContext);
53 DLSYM_DECLARE(SCardReleaseContext);
54 DLSYM_DECLARE(SCardIsValidContext);
55 DLSYM_DECLARE(SCardConnect);
56 DLSYM_DECLARE(SCardReconnect);
57 DLSYM_DECLARE(SCardDisconnect);
58 DLSYM_DECLARE(SCardBeginTransaction);
59 DLSYM_DECLARE(SCardEndTransaction);
60 DLSYM_DECLARE(SCardStatus);
61 DLSYM_DECLARE(SCardGetStatusChange);
62 DLSYM_DECLARE(SCardControl);
63 DLSYM_DECLARE(SCardTransmit);
64 DLSYM_DECLARE(SCardListReaderGroups);
65 DLSYM_DECLARE(SCardListReaders);
66 DLSYM_DECLARE(SCardFreeMemory);
67 DLSYM_DECLARE(SCardCancel);
68 DLSYM_DECLARE(SCardGetAttrib);
69 DLSYM_DECLARE(SCardSetAttrib);
72 DLSYM_SET_VALUE(SCardEstablishContext),
73 DLSYM_SET_VALUE(SCardReleaseContext),
74 DLSYM_SET_VALUE(SCardIsValidContext),
75 DLSYM_SET_VALUE(SCardConnect),
76 DLSYM_SET_VALUE(SCardReconnect),
77 DLSYM_SET_VALUE(SCardDisconnect),
78 DLSYM_SET_VALUE(SCardBeginTransaction),
79 DLSYM_SET_VALUE(SCardEndTransaction),
80 DLSYM_SET_VALUE(SCardStatus),
81 DLSYM_SET_VALUE(SCardGetStatusChange),
82 DLSYM_SET_VALUE(SCardControl),
83 DLSYM_SET_VALUE(SCardTransmit),
84 DLSYM_SET_VALUE(SCardListReaderGroups),
85 DLSYM_SET_VALUE(SCardListReaders),
86 DLSYM_SET_VALUE(SCardFreeMemory),
87 DLSYM_SET_VALUE(SCardCancel),
88 DLSYM_SET_VALUE(SCardGetAttrib),
89 DLSYM_SET_VALUE(SCardSetAttrib)
91#pragma GCC diagnostic pop
93#define LOG log_line("%s:%d", __FILE__, __LINE__)
95static int Log_fd = -1;
96static void *Lib_handle = NULL;
97static pthread_mutex_t Log_fd_mutex = PTHREAD_MUTEX_INITIALIZER;
100static void log_line(
const char *fmt, ...)
105 vfprintf(stderr, fmt, args);
106 fprintf(stderr,
"\n");
110static void log_line(
const char *fmt, ...)
115static void spy_line_direct(
char *line)
124 snprintf(threadid,
sizeof threadid,
"%lX@", (
unsigned long)pthread_self());
125 pthread_mutex_lock(&Log_fd_mutex);
126 r = write(Log_fd, threadid, strlen(threadid));
127 r = write(Log_fd, line, strlen(line));
128 r = write(Log_fd,
"\n", 1);
130 pthread_mutex_unlock(&Log_fd_mutex);
133static void spy_line(
const char *fmt, ...)
146 size = vsnprintf(line,
sizeof line, fmt, args);
148 if ((
size_t)size >=
sizeof line)
150 printf(
"libpcsc-spy: Buffer is too small!\n");
153 snprintf(threadid,
sizeof threadid,
"%lX@", (
unsigned long)pthread_self());
154 pthread_mutex_lock(&Log_fd_mutex);
155 r = write(Log_fd, threadid, strlen(threadid));
156 r = write(Log_fd, line, size);
157 r = write(Log_fd,
"\n", 1);
159 pthread_mutex_unlock(&Log_fd_mutex);
162static void spy_enter(
const char *fname)
164 struct timeval profile_time;
166 gettimeofday(&profile_time, NULL);
167 spy_line(
">|%ld|%ld|%s", profile_time.tv_sec, profile_time.tv_usec, fname);
170static void spy_quit(
const char *fname, LONG rv)
172 struct timeval profile_time;
174 gettimeofday(&profile_time, NULL);
175 spy_line(
"<|%ld|%ld|%s|0x%08lX", profile_time.tv_sec,
176 profile_time.tv_usec, fname, rv);
179#define Enter() spy_enter(__FUNCTION__)
180#define Quit() spy_quit(__FUNCTION__, rv)
182static void spy_long(
long arg)
184 spy_line(
"0x%08lX", arg);
187static void spy_ptr_long(LONG *arg)
190 spy_line(
"0x%08lX", *arg);
195static void spy_ptr_ulong(ULONG *arg)
198 spy_line(
"0x%08lX", *arg);
203static void spy_pvoid(
const void *ptr)
208static void spy_buffer(
const unsigned char *buffer,
size_t length)
217 char log_buffer[length * 3 +1], *p;
221 log_buffer[0] =
'\0';
222 for (i=0; i<length; i++)
224 snprintf(p, 4,
"%02X ", buffer[i]);
229 spy_line_direct(log_buffer);
233static void spy_str(
const char *str)
238static void spy_n_str(
const char *str, ULONG *len,
int autoallocate)
254 unsigned int length = 0;
262 length += strlen(s)+1;
264 }
while(length < *len);
274 for (i=0; i<cReaders; i++)
276 spy_str(rgReaderStates[i].szReader);
277 spy_long(rgReaderStates[i].dwCurrentState);
278 spy_long(rgReaderStates[i].dwEventState);
280 spy_buffer(rgReaderStates[i].rgbAtr, rgReaderStates[i].cbAtr);
282 spy_buffer(NULL, rgReaderStates[i].cbAtr);
286static LONG load_lib(
void)
289#define LIBPCSC "libpcsclite_real.so.1"
298 Lib_handle = dlopen(lib, RTLD_LAZY);
299 if (NULL == Lib_handle)
301 log_line(
"loading \"%s\" failed: %s", lib, dlerror());
305#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)
307 if (SCardEstablishContext == dlsym(Lib_handle,
"SCardEstablishContext"))
309 log_line(
"Symbols dlsym error");
313 get_symbol(SCardEstablishContext);
314 get_symbol(SCardReleaseContext);
315 get_symbol(SCardIsValidContext);
316 get_symbol(SCardConnect);
317 get_symbol(SCardReconnect);
318 get_symbol(SCardDisconnect);
319 get_symbol(SCardBeginTransaction);
320 get_symbol(SCardEndTransaction);
321 get_symbol(SCardStatus);
322 get_symbol(SCardGetStatusChange);
323 get_symbol(SCardControl);
324 get_symbol(SCardTransmit);
325 get_symbol(SCardListReaderGroups);
326 get_symbol(SCardListReaders);
328 if (dlsym(Lib_handle,
"SCardFreeMemory"))
329 get_symbol(SCardFreeMemory);
330 get_symbol(SCardCancel);
331 get_symbol(SCardGetAttrib);
332 get_symbol(SCardSetAttrib);
337static void init(
void)
351 snprintf(log_pipe,
sizeof log_pipe,
"%s/pcsc-spy", home);
352 Log_fd = open(log_pipe, O_WRONLY);
355 log_line(
"open %s failed: %s", log_pipe, strerror(errno));
360PCSC_API LONG SCardEstablishContext(DWORD dwScope,
363 LPSCARDCONTEXT phContext)
366 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
368 pthread_once(&once_control, init);
372 rv = spy.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
374 spy_ptr_long(phContext);
385 rv = spy.SCardReleaseContext(hContext);
396 rv = spy.SCardIsValidContext(hContext);
404 DWORD dwPreferredProtocols,
405 LPSCARDHANDLE phCard,
406 LPDWORD pdwActiveProtocol)
413 spy_long(dwShareMode);
414 spy_long(dwPreferredProtocols);
415 spy_ptr_long(phCard);
416 spy_ptr_ulong(pdwActiveProtocol);
417 rv = spy.SCardConnect(hContext, szReader, dwShareMode,
418 dwPreferredProtocols, phCard, pdwActiveProtocol);
419 spy_ptr_long(phCard);
420 spy_ptr_ulong(pdwActiveProtocol);
427 DWORD dwPreferredProtocols,
428 DWORD dwInitialization,
429 LPDWORD pdwActiveProtocol)
435 spy_long(dwShareMode);
436 spy_long(dwPreferredProtocols);
437 spy_long(dwInitialization);
438 rv = spy.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
439 dwInitialization, pdwActiveProtocol);
440 spy_ptr_ulong(pdwActiveProtocol);
452 spy_long(dwDisposition);
453 rv = spy.SCardDisconnect(hCard, dwDisposition);
458PCSC_API LONG SCardBeginTransaction(
SCARDHANDLE hCard)
464 rv = spy.SCardBeginTransaction(hCard);
469PCSC_API LONG SCardEndTransaction(
SCARDHANDLE hCard,
476 spy_long(dwDisposition);
477 rv = spy.SCardEndTransaction(hCard, dwDisposition);
484 LPDWORD pcchReaderLen,
491 int autoallocate_ReaderName = 0, autoallocate_Atr = 0;
501 spy_ptr_ulong(pcchReaderLen);
502 spy_ptr_ulong(pcbAtrLen);
503 rv = spy.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
504 pdwProtocol, pbAtr, pcbAtrLen);
505 spy_n_str(mszReaderName, pcchReaderLen, autoallocate_ReaderName);
506 spy_ptr_ulong(pdwState);
507 spy_ptr_ulong(pdwProtocol);
508 if (NULL == pcbAtrLen)
514 if (autoallocate_Atr)
515 buffer = *(LPBYTE *)pbAtr;
519 spy_buffer(buffer, *pcbAtrLen);
525PCSC_API LONG SCardGetStatusChange(
SCARDCONTEXT hContext,
536 spy_readerstate(rgReaderStates, cReaders);
537 rv = spy.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
539 spy_readerstate(rgReaderStates, cReaders);
546 LPCVOID pbSendBuffer,
550 LPDWORD lpBytesReturned)
556 spy_long(dwControlCode);
557 spy_buffer(pbSendBuffer, cbSendLength);
558 rv = spy.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
559 pbRecvBuffer, cbRecvLength, lpBytesReturned);
563 spy_buffer(pbRecvBuffer, *lpBytesReturned);
565 spy_buffer(NULL, *lpBytesReturned);
575 LPCBYTE pbSendBuffer,
579 LPDWORD pcbRecvLength)
595 spy_buffer(pbSendBuffer, cbSendLength);
596 rv = spy.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
597 pioRecvPci, pbRecvBuffer, pcbRecvLength);
611 spy_buffer(pbRecvBuffer, *pcbRecvLength);
613 spy_buffer(NULL, *pcbRecvLength);
621PCSC_API LONG SCardListReaderGroups(
SCARDCONTEXT hContext,
626 int autoallocate = 0;
633 spy_ptr_ulong(pcchGroups);
634 rv = spy.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
636 spy_n_str(mszGroups, pcchGroups, autoallocate);
638 spy_n_str(NULL, pcchGroups, 0);
649 int autoallocate = 0;
657 rv = spy.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
659 spy_n_str(mszReaders, pcchReaders, autoallocate);
661 spy_n_str(NULL, pcchReaders, 0);
674 rv = spy.SCardFreeMemory(hContext, pvMem);
685 rv = spy.SCardCancel(hContext);
696 int autoallocate = 0;
704 rv = spy.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
705 if (NULL == pcbAttrLen)
709 spy_buffer(NULL, *pcbAttrLen);
715 buffer = *(LPBYTE *)pbAttr;
719 spy_buffer(buffer, *pcbAttrLen);
735 spy_buffer(pbAttr, cbAttrLen);
736 rv = spy.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
#define SCARD_S_SUCCESS
No error was encountered.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
#define MAX_ATR_SIZE
Maximum ATR size.
LONG SCARDHANDLE
hCard returned by SCardConnect()
Protocol Control Information (PCI)
unsigned long dwProtocol
Protocol identifier.
unsigned long cbPciLength
Protocol Control Inf Length.
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.