pcsc-lite 2.3.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 *
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions
9are met:
10
111. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
132. 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.
163. 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
19THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28THIS 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 */
59static 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 */
67static 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
110static void *Lib_handle = NULL;
111
112#ifdef DEBUG
113static 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
123static void log_line(const char *fmt, ...)
124{
125}
126#endif
127
128static 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 */
175PCSC_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
188PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
189{
190 return redirect.SCardReleaseContext(hContext);
191}
192
193PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext)
194{
195 return redirect.SCardIsValidContext(hContext);
196}
197
198PCSC_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
209PCSC_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
219PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard,
220 DWORD dwDisposition)
221{
222 return redirect.SCardDisconnect(hCard, dwDisposition);
223}
224
225PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
226{
227 return redirect.SCardBeginTransaction(hCard);
228}
229
230PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard,
231 DWORD dwDisposition)
232{
233 return redirect.SCardEndTransaction(hCard, dwDisposition);
234}
235
236PCSC_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
248PCSC_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
257PCSC_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
269PCSC_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
281PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext,
282 LPSTR mszGroups,
283 LPDWORD pcchGroups)
284{
285 return redirect.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
286}
287
288PCSC_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
296PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext,
297 LPCVOID pvMem)
298{
299 return redirect.SCardFreeMemory(hContext, pvMem);
300}
301
302PCSC_API LONG SCardCancel(SCARDCONTEXT hContext)
303{
304 return redirect.SCardCancel(hContext);
305}
306
307PCSC_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
315PCSC_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
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
LONG SCARDHANDLE
hCard returned by SCardConnect()
Protocol Control Information (PCI)
This handles abstract system level calls.
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
Definition sys_unix.c:168
This handles smart card reader communications.