pcsc-lite 2.1.0
libredirect.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 2025
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/* function prototypes */
54
55#define p_SCardEstablishContext(fct) LONG(fct)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
56
57#define p_SCardReleaseContext(fct) LONG(fct)(SCARDCONTEXT hContext)
58
59#define p_SCardIsValidContext(fct) LONG(fct) (SCARDCONTEXT hContext)
60
61#define p_SCardConnect(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
62
63#define p_SCardReconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
64
65#define p_SCardDisconnect(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
66
67#define p_SCardBeginTransaction(fct) LONG(fct) (SCARDHANDLE hCard)
68
69#define p_SCardEndTransaction(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwDisposition)
70
71#define p_SCardStatus(fct) LONG(fct) (SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
72
73#define p_SCardGetStatusChange(fct) LONG(fct) (SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
74
75#define p_SCardControl(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
76
77#define p_SCardTransmit(fct) LONG(fct) (SCARDHANDLE hCard, const SCARD_IO_REQUEST * pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST * pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
78
79#define p_SCardListReaderGroups(fct) LONG(fct) (SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
80
81#define p_SCardListReaders(fct) LONG(fct) (SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
82
83#define p_SCardFreeMemory(fct) LONG(fct) (SCARDCONTEXT hContext, LPCVOID pvMem)
84
85#define p_SCardCancel(fct) LONG(fct) (SCARDCONTEXT hContext)
86
87#define p_SCardGetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
88
89#define p_SCardSetAttrib(fct) LONG(fct) (SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
90
91/* fake function to just return en error code */
92static LONG internal_error(void)
93{
95}
96
97#pragma GCC diagnostic push
98#pragma GCC diagnostic ignored "-Wcast-function-type"
99/* contains pointers to real functions */
100static struct
101{
102 p_SCardEstablishContext(*SCardEstablishContext);
103 p_SCardReleaseContext(*SCardReleaseContext);
104 p_SCardIsValidContext(*SCardIsValidContext);
105 p_SCardConnect(*SCardConnect);
106 p_SCardReconnect(*SCardReconnect);
107 p_SCardDisconnect(*SCardDisconnect);
108 p_SCardBeginTransaction(*SCardBeginTransaction);
109 p_SCardEndTransaction(*SCardEndTransaction);
110 p_SCardStatus(*SCardStatus);
111 p_SCardGetStatusChange(*SCardGetStatusChange);
112 p_SCardControl(*SCardControl);
113 p_SCardTransmit(*SCardTransmit);
114 p_SCardListReaderGroups(*SCardListReaderGroups);
115 p_SCardListReaders(*SCardListReaders);
116 p_SCardFreeMemory(*SCardFreeMemory);
117 p_SCardCancel(*SCardCancel);
118 p_SCardGetAttrib(*SCardGetAttrib);
119 p_SCardSetAttrib(*SCardSetAttrib);
120} redirect = {
121 /* initialized with the fake internal_error() function */
122 .SCardEstablishContext = (p_SCardEstablishContext(*))internal_error,
123 .SCardReleaseContext = (p_SCardReleaseContext(*))internal_error,
124 .SCardIsValidContext = (p_SCardIsValidContext(*))internal_error,
125 .SCardConnect = (p_SCardConnect(*))internal_error,
126 .SCardReconnect = (p_SCardReconnect(*))internal_error,
127 .SCardDisconnect = (p_SCardDisconnect(*))internal_error,
128 .SCardBeginTransaction = (p_SCardBeginTransaction(*))internal_error,
129 .SCardEndTransaction = (p_SCardEndTransaction(*))internal_error,
130 .SCardStatus = (p_SCardStatus(*))internal_error,
131 .SCardGetStatusChange = (p_SCardGetStatusChange(*))internal_error,
132 .SCardControl = (p_SCardControl(*))internal_error,
133 .SCardTransmit = (p_SCardTransmit(*))internal_error,
134 .SCardListReaderGroups = (p_SCardListReaderGroups(*))internal_error,
135 .SCardListReaders = (p_SCardListReaders(*))internal_error,
136 .SCardFreeMemory = (p_SCardFreeMemory(*))internal_error,
137 .SCardCancel = (p_SCardCancel(*))internal_error,
138 .SCardGetAttrib = (p_SCardGetAttrib(*))internal_error,
139 .SCardSetAttrib = (p_SCardSetAttrib(*))internal_error,
140};
141#pragma GCC diagnostic pop
142
143static void *Lib_handle = NULL;
144
145#ifdef DEBUG
146static void log_line(const char *fmt, ...)
147{
148 va_list args;
149
150 va_start(args, fmt);
151 vprintf(fmt, args);
152 printf("\n");
153 va_end(args);
154}
155#else
156static void log_line(const char *fmt, ...)
157{
158}
159#endif
160
161static LONG load_lib(void)
162{
163#define LIBPCSC "libpcsclite_real.so.1"
164
165 const char *lib;
166
167 lib = SYS_GetEnv("LIBPCSCLITE_DELEGATE");
168 if (NULL == lib)
169 lib = LIBPCSC;
170
171 /* load the real library */
172 Lib_handle = dlopen(lib, RTLD_LAZY);
173 if (NULL == Lib_handle)
174 {
175 log_line("loading \"%s\" failed: %s", lib, dlerror());
177 }
178
179#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)
180
181 if (SCardEstablishContext == dlsym(Lib_handle, "SCardEstablishContext"))
182 {
183 log_line("Symbols dlsym error");
185 }
186
187 get_symbol(SCardEstablishContext);
188 get_symbol(SCardReleaseContext);
189 get_symbol(SCardIsValidContext);
190 get_symbol(SCardConnect);
191 get_symbol(SCardReconnect);
192 get_symbol(SCardDisconnect);
193 get_symbol(SCardBeginTransaction);
194 get_symbol(SCardEndTransaction);
195 get_symbol(SCardStatus);
196 get_symbol(SCardGetStatusChange);
197 get_symbol(SCardControl);
198 get_symbol(SCardTransmit);
199 get_symbol(SCardListReaderGroups);
200 get_symbol(SCardListReaders);
201 get_symbol(SCardFreeMemory);
202 get_symbol(SCardCancel);
203 get_symbol(SCardGetAttrib);
204 get_symbol(SCardSetAttrib);
205
206 return SCARD_S_SUCCESS;
207}
208
209
210/* exported functions */
211PCSC_API p_SCardEstablishContext(SCardEstablishContext)
212{
213 LONG rv;
214 static int init = 0;
215
216 if (!init)
217 {
218 init = 1;
219
220 /* load the real library */
221 rv = load_lib();
222 if (rv != SCARD_S_SUCCESS)
223 return rv;
224 }
225
226 return redirect.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
227 phContext);
228 return rv;
229}
230
231PCSC_API p_SCardReleaseContext(SCardReleaseContext)
232{
233 return redirect.SCardReleaseContext(hContext);
234}
235
236PCSC_API p_SCardIsValidContext(SCardIsValidContext)
237{
238 return redirect.SCardIsValidContext(hContext);
239}
240
241PCSC_API p_SCardConnect(SCardConnect)
242{
243 return redirect.SCardConnect(hContext, szReader, dwShareMode,
244 dwPreferredProtocols, phCard, pdwActiveProtocol);
245}
246
247PCSC_API p_SCardReconnect(SCardReconnect)
248{
249 return redirect.SCardReconnect(hCard, dwShareMode, dwPreferredProtocols,
250 dwInitialization, pdwActiveProtocol);
251}
252
253PCSC_API p_SCardDisconnect(SCardDisconnect)
254{
255 return redirect.SCardDisconnect(hCard, dwDisposition);
256}
257
258PCSC_API p_SCardBeginTransaction(SCardBeginTransaction)
259{
260 return redirect.SCardBeginTransaction(hCard);
261}
262
263PCSC_API p_SCardEndTransaction(SCardEndTransaction)
264{
265 return redirect.SCardEndTransaction(hCard, dwDisposition);
266}
267
268PCSC_API p_SCardStatus(SCardStatus)
269{
270 return redirect.SCardStatus(hCard, mszReaderName, pcchReaderLen, pdwState,
271 pdwProtocol, pbAtr, pcbAtrLen);
272}
273
274PCSC_API p_SCardGetStatusChange(SCardGetStatusChange)
275{
276 return redirect.SCardGetStatusChange(hContext, dwTimeout, rgReaderStates,
277 cReaders);
278}
279
280PCSC_API p_SCardControl(SCardControl)
281{
282 return redirect.SCardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength,
283 pbRecvBuffer, cbRecvLength, lpBytesReturned);
284}
285
286PCSC_API p_SCardTransmit(SCardTransmit)
287{
288 return redirect.SCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength,
289 pioRecvPci, pbRecvBuffer, pcbRecvLength);
290}
291
292PCSC_API p_SCardListReaderGroups(SCardListReaderGroups)
293{
294 return redirect.SCardListReaderGroups(hContext, mszGroups, pcchGroups);
295}
296
297PCSC_API p_SCardListReaders(SCardListReaders)
298{
299 return redirect.SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
300}
301
302PCSC_API p_SCardFreeMemory(SCardFreeMemory)
303{
304 return redirect.SCardFreeMemory(hContext, pvMem);
305}
306
307PCSC_API p_SCardCancel(SCardCancel)
308{
309 return redirect.SCardCancel(hContext);
310}
311
312PCSC_API p_SCardGetAttrib(SCardGetAttrib)
313{
314 return redirect.SCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
315}
316
317PCSC_API p_SCardSetAttrib(SCardSetAttrib)
318{
319 return redirect.SCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
320}
321
328
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition pcsclite.h:109
#define SCARD_S_SUCCESS
No error was encountered.
Definition pcsclite.h:107
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition pcsclite.h:243
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition pcsclite.h:242
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition pcsclite.h:244
Protocol Control Information (PCI)
Definition pcsclite.h:80
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.