pcsc-lite  2.2.3
libredirect.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3  *
4  * Copyright (C) 2024
5  * Ludovic Rousseau <ludovic.rousseau@free.fr>
6  *
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 
11 1. Redistributions of source code must retain the above copyright
12  notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the
15  documentation and/or other materials provided with the distribution.
16 3. The name of the author may not be used to endorse or promote products
17  derived from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
36 #include <dlfcn.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/time.h>
45 #include <pthread.h>
46 
47 #include "misc.h"
48 #include <winscard.h>
49 #include "sys_generic.h"
50 
51 #define DEBUG
52 
53 #define DLSYM_DECLARE(symbol) \
54  typeof(symbol)* symbol
55 #define DLSYM_SET_VALUE(symbol) \
56  .symbol = (typeof(symbol)(*))internal_error
57 
58 /* fake function to just return en error code */
59 static LONG internal_error(void)
60 {
62 }
63 
64 #pragma GCC diagnostic push
65 #pragma GCC diagnostic ignored "-Wcast-function-type"
66 /* contains pointers to real functions */
67 static struct
68 {
69  DLSYM_DECLARE(SCardEstablishContext);
70  DLSYM_DECLARE(SCardReleaseContext);
71  DLSYM_DECLARE(SCardIsValidContext);
72  DLSYM_DECLARE(SCardConnect);
73  DLSYM_DECLARE(SCardReconnect);
74  DLSYM_DECLARE(SCardDisconnect);
75  DLSYM_DECLARE(SCardBeginTransaction);
76  DLSYM_DECLARE(SCardEndTransaction);
77  DLSYM_DECLARE(SCardStatus);
78  DLSYM_DECLARE(SCardGetStatusChange);
79  DLSYM_DECLARE(SCardControl);
80  DLSYM_DECLARE(SCardTransmit);
81  DLSYM_DECLARE(SCardListReaderGroups);
82  DLSYM_DECLARE(SCardListReaders);
83  DLSYM_DECLARE(SCardFreeMemory);
84  DLSYM_DECLARE(SCardCancel);
85  DLSYM_DECLARE(SCardGetAttrib);
86  DLSYM_DECLARE(SCardSetAttrib);
87 } redirect = {
88  /* initialized with the fake internal_error() function */
89  DLSYM_SET_VALUE(SCardEstablishContext),
90  DLSYM_SET_VALUE(SCardReleaseContext),
91  DLSYM_SET_VALUE(SCardIsValidContext),
92  DLSYM_SET_VALUE(SCardConnect),
93  DLSYM_SET_VALUE(SCardReconnect),
94  DLSYM_SET_VALUE(SCardDisconnect),
95  DLSYM_SET_VALUE(SCardBeginTransaction),
96  DLSYM_SET_VALUE(SCardEndTransaction),
97  DLSYM_SET_VALUE(SCardStatus),
98  DLSYM_SET_VALUE(SCardGetStatusChange),
99  DLSYM_SET_VALUE(SCardControl),
100  DLSYM_SET_VALUE(SCardTransmit),
101  DLSYM_SET_VALUE(SCardListReaderGroups),
102  DLSYM_SET_VALUE(SCardListReaders),
103  DLSYM_SET_VALUE(SCardFreeMemory),
104  DLSYM_SET_VALUE(SCardCancel),
105  DLSYM_SET_VALUE(SCardGetAttrib),
106  DLSYM_SET_VALUE(SCardSetAttrib)
107 };
108 #pragma GCC diagnostic pop
109 
110 static void *Lib_handle = NULL;
111 
112 #ifdef DEBUG
113 static void log_line(const char *fmt, ...)
114 {
115  va_list args;
116 
117  va_start(args, fmt);
118  vprintf(fmt, args);
119  printf("\n");
120  va_end(args);
121 }
122 #else
123 static void log_line(const char *fmt, ...)
124 {
125 }
126 #endif
127 
128 static LONG load_lib(void)
129 {
130 #define LIBPCSC "libpcsclite_real.so.1"
131 
132  const char *lib;
133 
134  lib = SYS_GetEnv("LIBPCSCLITE_DELEGATE");
135  if (NULL == lib)
136  lib = LIBPCSC;
137 
138  /* load the real library */
139  Lib_handle = dlopen(lib, RTLD_LAZY);
140  if (NULL == Lib_handle)
141  {
142  log_line("loading \"%s\" failed: %s", lib, dlerror());
143  return SCARD_F_INTERNAL_ERROR;
144  }
145 
146 #define get_symbol(s) do { redirect.s = dlsym(Lib_handle, #s); if (NULL == redirect.s) { log_line("%s", dlerror()); return SCARD_F_INTERNAL_ERROR; } } while (0)
147 
148  if (SCardEstablishContext == dlsym(Lib_handle, "SCardEstablishContext"))
149  {
150  log_line("Symbols dlsym error");
151  return SCARD_F_INTERNAL_ERROR;
152  }
153 
154  get_symbol(SCardEstablishContext);
155  get_symbol(SCardReleaseContext);
156  get_symbol(SCardIsValidContext);
157  get_symbol(SCardConnect);
158  get_symbol(SCardReconnect);
159  get_symbol(SCardDisconnect);
160  get_symbol(SCardBeginTransaction);
161  get_symbol(SCardEndTransaction);
162  get_symbol(SCardStatus);
163  get_symbol(SCardGetStatusChange);
164  get_symbol(SCardControl);
165  get_symbol(SCardTransmit);
166  get_symbol(SCardListReaderGroups);
167  get_symbol(SCardListReaders);
168  get_symbol(SCardFreeMemory);
169  get_symbol(SCardCancel);
170  get_symbol(SCardGetAttrib);
171  get_symbol(SCardSetAttrib);
172 
173  return SCARD_S_SUCCESS;
174 }
175 
176 
177 /* exported functions */
178 PCSC_API LONG SCardEstablishContext(DWORD dwScope,
179  LPCVOID pvReserved1,
180  LPCVOID pvReserved2,
181  LPSCARDCONTEXT phContext)
182 {
183  LONG rv;
184  static int init = 0;
185 
186  if (!init)
187  {
188  init = 1;
189 
190  /* load the real library */
191  rv = load_lib();
192  if (rv != SCARD_S_SUCCESS)
193  return rv;
194  }
195 
196  return redirect.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
197  phContext);
198 }
199 
200 PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
201 {
202  return redirect.SCardReleaseContext(hContext);
203 }
204 
205 PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext)
206 {
207  return redirect.SCardIsValidContext(hContext);
208 }
209 
210 PCSC_API LONG SCardConnect(SCARDCONTEXT hContext,
211  LPCSTR szReader,
212  DWORD dwShareMode,
213  DWORD dwPreferredProtocols,
214  LPSCARDHANDLE phCard,
215  LPDWORD pdwActiveProtocol)
216 {
217  return redirect.SCardConnect(hContext, szReader, dwShareMode,
218  dwPreferredProtocols, phCard, pdwActiveProtocol);
219 }
220 
221 PCSC_API LONG SCardReconnect(SCARDHANDLE hCard,
222  DWORD dwShareMode,
223  DWORD dwPreferredProtocols,
224  DWORD dwInitialization,
225  LPDWORD pdwActiveProtocol)
226 {
227  return redirect.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
228  dwInitialization, pdwActiveProtocol);
229 }
230 
231 PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard,
232  DWORD dwDisposition)
233 {
234  return redirect.SCardDisconnect(hCard, dwDisposition);
235 }
236 
237 PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
238 {
239  return redirect.SCardBeginTransaction(hCard);
240 }
241 
242 PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard,
243  DWORD dwDisposition)
244 {
245  return redirect.SCardEndTransaction(hCard, dwDisposition);
246 }
247 
248 PCSC_API LONG SCardStatus(SCARDHANDLE hCard,
249  LPSTR mszReaderName,
250  LPDWORD pcchReaderLen,
251  LPDWORD pdwState,
252  LPDWORD pdwProtocol,
253  LPBYTE pbAtr,
254  LPDWORD pcbAtrLen)
255 {
256  return redirect.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
257  pdwProtocol, pbAtr, pcbAtrLen);
258 }
259 
260 PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext,
261  DWORD dwTimeout,
262  SCARD_READERSTATE *rgReaderStates,
263  DWORD cReaders)
264 {
265  return redirect.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
266  cReaders);
267 }
268 
269 PCSC_API LONG SCardControl(SCARDHANDLE hCard,
270  DWORD dwControlCode,
271  LPCVOID pbSendBuffer,
272  DWORD cbSendLength,
273  LPVOID pbRecvBuffer,
274  DWORD cbRecvLength,
275  LPDWORD lpBytesReturned)
276 {
277  return redirect.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
278  pbRecvBuffer, cbRecvLength, lpBytesReturned);
279 }
280 
281 PCSC_API LONG SCardTransmit(SCARDHANDLE hCard,
282  const SCARD_IO_REQUEST *pioSendPci,
283  LPCBYTE pbSendBuffer,
284  DWORD cbSendLength,
285  SCARD_IO_REQUEST *pioRecvPci,
286  LPBYTE pbRecvBuffer,
287  LPDWORD pcbRecvLength)
288 {
289  return redirect.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
290  pioRecvPci, pbRecvBuffer, pcbRecvLength);
291 }
292 
293 PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext,
294  LPSTR mszGroups,
295  LPDWORD pcchGroups)
296 {
297  return redirect.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
298 }
299 
300 PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext,
301  LPCSTR mszGroups,
302  LPSTR mszReaders,
303  LPDWORD pcchReaders)
304 {
305  return redirect.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
306 }
307 
308 PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext,
309  LPCVOID pvMem)
310 {
311  return redirect.SCardFreeMemory(hContext, pvMem);
312 }
313 
314 PCSC_API LONG SCardCancel(SCARDCONTEXT hContext)
315 {
316  return redirect.SCardCancel(hContext);
317 }
318 
319 PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard,
320  DWORD dwAttrId,
321  LPBYTE pbAttr,
322  LPDWORD pcbAttrLen)
323 {
324  return redirect.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
325 }
326 
327 PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard,
328  DWORD dwAttrId,
329  LPCBYTE pbAttr,
330  DWORD cbAttrLen)
331 {
332  return redirect.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
333 }
334 
341 
g_rgSCardT0Pci
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
Definition: libredirect.c:336
SCARD_S_SUCCESS
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
SYS_GetEnv
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
Definition: sys_unix.c:168
sys_generic.h
This handles abstract system level calls.
SCARD_READERSTATE
Definition: pcsclite.h:68
g_rgSCardRawPci
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
Definition: libredirect.c:340
SCARDHANDLE
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
SCARD_PROTOCOL_T0
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:242
SCARD_PROTOCOL_T1
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:243
SCARD_PROTOCOL_RAW
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:244
winscard.h
This handles smart card reader communications.
SCARDCONTEXT
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:52
SCARD_IO_REQUEST
Protocol Control Information (PCI)
Definition: pcsclite.h:80
SCARD_F_INTERNAL_ERROR
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:109
g_rgSCardT1Pci
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
Definition: libredirect.c:338