pcsc-lite  2.5.0
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  vfprintf(stderr, fmt, args);
119  fprintf(stderr, "\n");
120  va_end(args);
121 }
122 #else
123 static void log_line(const char *fmt, ...)
124 {
125 }
126 #endif
127 
128 static void 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;
144  }
145 
146 #define get_symbol(s) do { redirect.s = dlsym(Lib_handle, #s); if (NULL == redirect.s) { log_line("%s", dlerror()); return; } } while (0)
147 
148  if (SCardEstablishContext == dlsym(Lib_handle, "SCardEstablishContext"))
149  {
150  log_line("Symbols dlsym error");
151  return;
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 
174 /* exported functions */
175 PCSC_API LONG SCardEstablishContext(DWORD dwScope,
176  LPCVOID pvReserved1,
177  LPCVOID pvReserved2,
178  LPSCARDCONTEXT phContext)
179 {
180  static pthread_once_t once_control = PTHREAD_ONCE_INIT;
181 
182  pthread_once(&once_control, load_lib);
183 
184  return redirect.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
185  phContext);
186 }
187 
188 PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
189 {
190  return redirect.SCardReleaseContext(hContext);
191 }
192 
193 PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext)
194 {
195  return redirect.SCardIsValidContext(hContext);
196 }
197 
198 PCSC_API LONG SCardConnect(SCARDCONTEXT hContext,
199  LPCSTR szReader,
200  DWORD dwShareMode,
201  DWORD dwPreferredProtocols,
202  LPSCARDHANDLE phCard,
203  LPDWORD pdwActiveProtocol)
204 {
205  return redirect.SCardConnect(hContext, szReader, dwShareMode,
206  dwPreferredProtocols, phCard, pdwActiveProtocol);
207 }
208 
209 PCSC_API LONG SCardReconnect(SCARDHANDLE hCard,
210  DWORD dwShareMode,
211  DWORD dwPreferredProtocols,
212  DWORD dwInitialization,
213  LPDWORD pdwActiveProtocol)
214 {
215  return redirect.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
216  dwInitialization, pdwActiveProtocol);
217 }
218 
219 PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard,
220  DWORD dwDisposition)
221 {
222  return redirect.SCardDisconnect(hCard, dwDisposition);
223 }
224 
225 PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
226 {
227  return redirect.SCardBeginTransaction(hCard);
228 }
229 
230 PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard,
231  DWORD dwDisposition)
232 {
233  return redirect.SCardEndTransaction(hCard, dwDisposition);
234 }
235 
236 PCSC_API LONG SCardStatus(SCARDHANDLE hCard,
237  LPSTR mszReaderName,
238  LPDWORD pcchReaderLen,
239  LPDWORD pdwState,
240  LPDWORD pdwProtocol,
241  LPBYTE pbAtr,
242  LPDWORD pcbAtrLen)
243 {
244  return redirect.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
245  pdwProtocol, pbAtr, pcbAtrLen);
246 }
247 
248 PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext,
249  DWORD dwTimeout,
250  SCARD_READERSTATE *rgReaderStates,
251  DWORD cReaders)
252 {
253  return redirect.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
254  cReaders);
255 }
256 
257 PCSC_API LONG SCardControl(SCARDHANDLE hCard,
258  DWORD dwControlCode,
259  LPCVOID pbSendBuffer,
260  DWORD cbSendLength,
261  LPVOID pbRecvBuffer,
262  DWORD cbRecvLength,
263  LPDWORD lpBytesReturned)
264 {
265  return redirect.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
266  pbRecvBuffer, cbRecvLength, lpBytesReturned);
267 }
268 
269 PCSC_API LONG SCardTransmit(SCARDHANDLE hCard,
270  const SCARD_IO_REQUEST *pioSendPci,
271  LPCBYTE pbSendBuffer,
272  DWORD cbSendLength,
273  SCARD_IO_REQUEST *pioRecvPci,
274  LPBYTE pbRecvBuffer,
275  LPDWORD pcbRecvLength)
276 {
277  return redirect.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
278  pioRecvPci, pbRecvBuffer, pcbRecvLength);
279 }
280 
281 PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext,
282  LPSTR mszGroups,
283  LPDWORD pcchGroups)
284 {
285  return redirect.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
286 }
287 
288 PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext,
289  LPCSTR mszGroups,
290  LPSTR mszReaders,
291  LPDWORD pcchReaders)
292 {
293  return redirect.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
294 }
295 
296 PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext,
297  LPCVOID pvMem)
298 {
299  return redirect.SCardFreeMemory(hContext, pvMem);
300 }
301 
302 PCSC_API LONG SCardCancel(SCARDCONTEXT hContext)
303 {
304  return redirect.SCardCancel(hContext);
305 }
306 
307 PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard,
308  DWORD dwAttrId,
309  LPBYTE pbAttr,
310  LPDWORD pcbAttrLen)
311 {
312  return redirect.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
313 }
314 
315 PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard,
316  DWORD dwAttrId,
317  LPCBYTE pbAttr,
318  DWORD cbAttrLen)
319 {
320  return redirect.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
321 }
322 
This handles abstract system level calls.
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
Definition: sys_unix.c:168
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:52
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
Protocol Control Information (PCI)
Definition: pcsclite.h:79
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:109
This handles smart card reader communications.