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);
339PCSC_API LONG SCardEstablishContext(DWORD dwScope,
342 LPSCARDCONTEXT phContext)
364 snprintf(log_pipe,
sizeof log_pipe,
"%s/pcsc-spy", home);
365 Log_fd = open(log_pipe, O_WRONLY);
368 log_line(
"open %s failed: %s", log_pipe, strerror(errno));
374 rv = spy.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
376 spy_ptr_long(phContext);
387 rv = spy.SCardReleaseContext(hContext);
398 rv = spy.SCardIsValidContext(hContext);
406 DWORD dwPreferredProtocols,
407 LPSCARDHANDLE phCard,
408 LPDWORD pdwActiveProtocol)
415 spy_long(dwShareMode);
416 spy_long(dwPreferredProtocols);
417 spy_ptr_long(phCard);
418 spy_ptr_ulong(pdwActiveProtocol);
419 rv = spy.SCardConnect(hContext, szReader, dwShareMode,
420 dwPreferredProtocols, phCard, pdwActiveProtocol);
421 spy_ptr_long(phCard);
422 spy_ptr_ulong(pdwActiveProtocol);
429 DWORD dwPreferredProtocols,
430 DWORD dwInitialization,
431 LPDWORD pdwActiveProtocol)
437 spy_long(dwShareMode);
438 spy_long(dwPreferredProtocols);
439 spy_long(dwInitialization);
440 rv = spy.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
441 dwInitialization, pdwActiveProtocol);
442 spy_ptr_ulong(pdwActiveProtocol);
454 spy_long(dwDisposition);
455 rv = spy.SCardDisconnect(hCard, dwDisposition);
460PCSC_API LONG SCardBeginTransaction(
SCARDHANDLE hCard)
466 rv = spy.SCardBeginTransaction(hCard);
471PCSC_API LONG SCardEndTransaction(
SCARDHANDLE hCard,
478 spy_long(dwDisposition);
479 rv = spy.SCardEndTransaction(hCard, dwDisposition);
486 LPDWORD pcchReaderLen,
493 int autoallocate_ReaderName = 0, autoallocate_Atr = 0;
503 spy_ptr_ulong(pcchReaderLen);
504 spy_ptr_ulong(pcbAtrLen);
505 rv = spy.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
506 pdwProtocol, pbAtr, pcbAtrLen);
507 spy_n_str(mszReaderName, pcchReaderLen, autoallocate_ReaderName);
508 spy_ptr_ulong(pdwState);
509 spy_ptr_ulong(pdwProtocol);
510 if (NULL == pcbAtrLen)
516 if (autoallocate_Atr)
517 buffer = *(LPBYTE *)pbAtr;
521 spy_buffer(buffer, *pcbAtrLen);
527PCSC_API LONG SCardGetStatusChange(
SCARDCONTEXT hContext,
538 spy_readerstate(rgReaderStates, cReaders);
539 rv = spy.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
541 spy_readerstate(rgReaderStates, cReaders);
548 LPCVOID pbSendBuffer,
552 LPDWORD lpBytesReturned)
558 spy_long(dwControlCode);
559 spy_buffer(pbSendBuffer, cbSendLength);
560 rv = spy.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
561 pbRecvBuffer, cbRecvLength, lpBytesReturned);
565 spy_buffer(pbRecvBuffer, *lpBytesReturned);
567 spy_buffer(NULL, *lpBytesReturned);
577 LPCBYTE pbSendBuffer,
581 LPDWORD pcbRecvLength)
597 spy_buffer(pbSendBuffer, cbSendLength);
598 rv = spy.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
599 pioRecvPci, pbRecvBuffer, pcbRecvLength);
613 spy_buffer(pbRecvBuffer, *pcbRecvLength);
615 spy_buffer(NULL, *pcbRecvLength);
623PCSC_API LONG SCardListReaderGroups(
SCARDCONTEXT hContext,
628 int autoallocate = 0;
635 spy_ptr_ulong(pcchGroups);
636 rv = spy.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
638 spy_n_str(mszGroups, pcchGroups, autoallocate);
640 spy_n_str(NULL, pcchGroups, 0);
651 int autoallocate = 0;
659 rv = spy.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
661 spy_n_str(mszReaders, pcchReaders, autoallocate);
663 spy_n_str(NULL, pcchReaders, 0);
676 rv = spy.SCardFreeMemory(hContext, pvMem);
687 rv = spy.SCardCancel(hContext);
698 int autoallocate = 0;
706 rv = spy.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
707 if (NULL == pcbAttrLen)
711 spy_buffer(NULL, *pcbAttrLen);
717 buffer = *(LPBYTE *)pbAttr;
721 spy_buffer(buffer, *pcbAttrLen);
737 spy_buffer(pbAttr, cbAttrLen);
738 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.