pcsc-lite  2.5.0
readerfactory.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@musclecard.com>
6  * Copyright (C) 2003-2004
7  * Damien Sauveron <damien.sauveron@labri.fr>
8  * Copyright (C) 2002-2024
9  * Ludovic Rousseau <ludovic.rousseau@free.fr>
10  * Copyright (C) 2009
11  * Jean-Luc Giraud <jlgiraud@googlemail.com>
12  *
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16 
17 1. Redistributions of source code must retain the above copyright
18  notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20  notice, this list of conditions and the following disclaimer in the
21  documentation and/or other materials provided with the distribution.
22 3. The name of the author may not be used to endorse or promote products
23  derived from this software without specific prior written permission.
24 
25 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
42 #include "config.h"
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <pthread.h>
52 #include <stdatomic.h>
53 #include <stdbool.h>
54 
55 #include "misc.h"
56 #include "pcscd.h"
57 #include "debuglog.h"
58 #include "readerfactory.h"
59 #include "dyn_generic.h"
60 #include "sys_generic.h"
61 #include "eventhandler.h"
62 #include "readers.h"
63 #include "ifdwrapper.h"
64 #include "hotplug.h"
65 #include "configfile.h"
66 #include "utils.h"
67 
68 #define INITIAL_MAX_READERS_CONTEXTS 2
69 
70 int pcsclite_max_reader_context = -1;
71 READER_CONTEXT ** sReadersContexts;
72 static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
73 #ifdef USE_SERIAL
74 static char *ConfigFile = NULL;
75 static int ConfigFileCRC = 0;
76 #endif
77 static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
78 int16_t ReaderEvents = 1;
79 
80 static LONG removeReader(READER_CONTEXT * sReader);
81 
82 static int RDR_CLIHANDLES_seeker(const void *el, const void *key)
83 {
84  const RDR_CLIHANDLES *rdrCliHandles = el;
85 
86  if ((el == NULL) || (key == NULL))
87  {
88  Log3(PCSC_LOG_CRITICAL,
89  "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p",
90  el, key);
91  return 0;
92  }
93 
94  if (rdrCliHandles->hCard == *(SCARDHANDLE *)key)
95  return 1;
96 
97  return 0;
98 }
99 
100 
101 LONG _RefReader(READER_CONTEXT * sReader)
102 {
103  if (0 == sReader->reference)
105 
106  sReader->reference += 1;
107 
108  return SCARD_S_SUCCESS;
109 }
110 
111 LONG _UnrefReader(READER_CONTEXT * sReader)
112 {
113  if (0 == sReader->reference)
115 
116  sReader->reference -= 1;
117 
118  if (0 == sReader->reference)
119  removeReader(sReader);
120 
121  return SCARD_S_SUCCESS;
122 }
123 
124 LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles)
125 {
126  int i; /* Counter */
127 
128  if (customMaxReaderHandles != 0)
129  maxReaderHandles = customMaxReaderHandles;
130 
131  pcsclite_max_reader_context = INITIAL_MAX_READERS_CONTEXTS;
132  sReadersContexts = calloc(pcsclite_max_reader_context, sizeof(sReadersContexts[0]));
133  if (NULL == sReadersContexts)
135 
136  /* Allocate each reader structure */
137  for (i = 0; i < pcsclite_max_reader_context; i++)
138  {
139  sReadersContexts[i] = malloc(sizeof(READER_CONTEXT));
140  sReadersContexts[i]->vHandle = NULL;
141  atomic_init(&sReadersContexts[i]->hLockId, 0);
142  atomic_init(&sReadersContexts[i]->contexts, 0);
143  atomic_init(&sReadersContexts[i]->reference, 0);
144 
145  /* Zero out each value in the struct */
146  memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
147  memset(sReadersContexts[i]->readerState.cardAtr, 0, MAX_ATR_SIZE);
148  sReadersContexts[i]->readerState.eventCounter = 0;
149  sReadersContexts[i]->readerState.readerState = 0;
150  sReadersContexts[i]->readerState.readerSharing = 0;
151  sReadersContexts[i]->readerState.cardAtrLength = READER_NOT_INITIALIZED;
152  sReadersContexts[i]->readerState.cardProtocol = SCARD_PROTOCOL_UNDEFINED;
153  }
154 
155  /* Create public event structures */
156  return EHInitializeEventStructures();
157 }
158 
159 static LONG RFReAllocateReaderSpace(void)
160 {
161  int new_size = pcsclite_max_reader_context + INITIAL_MAX_READERS_CONTEXTS;
162 
163  Log3(PCSC_LOG_INFO, "from %d to %d", pcsclite_max_reader_context, new_size);
164 
165  sReadersContexts = realloc(sReadersContexts, new_size * sizeof(sReadersContexts[0]));
166 
167  /* Allocate each new reader structure */
168  for (int i = pcsclite_max_reader_context; i < new_size; i++)
169  {
170  sReadersContexts[i] = malloc(sizeof(READER_CONTEXT));
171  sReadersContexts[i]->vHandle = NULL;
172  atomic_init(&sReadersContexts[i]->hLockId, 0);
173  atomic_init(&sReadersContexts[i]->contexts, 0);
174  atomic_init(&sReadersContexts[i]->reference, 0);
175 
176  /* Zero out each value in the struct */
177  memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
178  memset(sReadersContexts[i]->readerState.cardAtr, 0, MAX_ATR_SIZE);
179  sReadersContexts[i]->readerState.eventCounter = 0;
180  sReadersContexts[i]->readerState.readerState = 0;
181  sReadersContexts[i]->readerState.readerSharing = 0;
182  sReadersContexts[i]->readerState.cardAtrLength = READER_NOT_INITIALIZED;
183  sReadersContexts[i]->readerState.cardProtocol = SCARD_PROTOCOL_UNDEFINED;
184  }
185 
186  pcsclite_max_reader_context = new_size;
187 
188  return SCARD_S_SUCCESS;
189 }
190 
191 LONG RFAddReader(const char *readerNameLong, int port, const char *library,
192  const char *device)
193 {
194  DWORD dwContext = 0, dwGetSize;
195  UCHAR ucGetData[1], ucThread[1];
196  LONG rv, parentNode;
197  int i, j;
198  int lrv = 0;
199  char *readerName = NULL;
200 
201  if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
202  return SCARD_E_INVALID_VALUE;
203 
204 #ifdef FILTER_NAMES
205  const char *ro_filter = SYS_GetEnv("PCSCLITE_FILTER_IGNORE_READER_NAMES");
206  if (ro_filter)
207  {
208  char *filter, *next;
209 
210  /* get a RW copy of the env string */
211  filter = alloca(strlen(ro_filter)+1);
212  strcpy(filter, ro_filter);
213 
214  while (filter)
215  {
216  /* ':' is the separator */
217  next = strchr(filter, ':');
218  if (next)
219  {
220  /* NUL terminate the current pattern */
221  *next = '\0';
222  }
223 
224  /* if filter is non empty and found in the reader name */
225  if (*filter && strstr(readerNameLong, filter))
226  {
227  Log3(PCSC_LOG_ERROR,
228  "Reader name \"%s\" contains \"%s\": ignored",
229  readerNameLong, filter);
231  }
232 
233  if (next)
234  /* next pattern */
235  filter = next+1;
236  else
237  /* end */
238  filter = NULL;
239  }
240  }
241 #endif
242 
243  /* allocate memory that is automatically freed */
244  readerName = alloca(strlen(readerNameLong)+1);
245  strcpy(readerName, readerNameLong);
246 
247  /* Reader name too long? also count " 00 00"*/
248  if (strlen(readerName) > MAX_READERNAME - sizeof(" 00 00"))
249  {
250  Log3(PCSC_LOG_ERROR,
251  "Reader name too long: %zd chars instead of max %zd. Truncating!",
252  strlen(readerName), MAX_READERNAME - sizeof(" 00 00"));
253  readerName[MAX_READERNAME - sizeof(" 00 00")] = '\0';
254  }
255 
256  /* Same name, same port, same device - duplicate reader cannot be used */
257  for (i = 0; i < pcsclite_max_reader_context; i++)
258  {
259  if (sReadersContexts[i]->vHandle != 0)
260  {
261  char lpcStripReader[MAX_READERNAME];
262  int tmplen;
263 
264  /* get the reader name without the reader and slot numbers */
265  strncpy(lpcStripReader,
266  sReadersContexts[i]->readerState.readerName,
267  sizeof(lpcStripReader));
268  tmplen = strlen(lpcStripReader);
269  lpcStripReader[tmplen - 6] = 0;
270 
271  if ((strcmp(readerName, lpcStripReader) == 0)
272  && (port == sReadersContexts[i]->port)
273  && (strcmp(device, sReadersContexts[i]->device) == 0))
274  {
275  Log1(PCSC_LOG_ERROR, "Duplicate reader found.");
277  }
278  }
279  }
280 
281  /* We must find an empty slot to put the reader structure */
282  for (i = 0; i < pcsclite_max_reader_context; i++)
283  {
284  if (sReadersContexts[i]->vHandle == 0)
285  {
286  dwContext = i;
287  break;
288  }
289  }
290 
291  if (i == pcsclite_max_reader_context)
292  {
293  /* No more spots left return */
294  RFReAllocateReaderSpace();
295  dwContext = i;
296  }
297 
298  /* Check and set the readername to see if it must be enumerated */
299  parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
300  library, port);
301  if (parentNode < -1)
302  return SCARD_E_NO_MEMORY;
303 
304  sReadersContexts[dwContext]->library = strdup(library);
305  sReadersContexts[dwContext]->device = strdup(device);
306  sReadersContexts[dwContext]->version = 0;
307  sReadersContexts[dwContext]->port = port;
308  sReadersContexts[dwContext]->mMutex = NULL;
309  sReadersContexts[dwContext]->contexts = 0;
310  sReadersContexts[dwContext]->pthThread = 0;
311  sReadersContexts[dwContext]->hLockId = 0;
312  sReadersContexts[dwContext]->LockCount = 0;
313  sReadersContexts[dwContext]->vHandle = NULL;
314  sReadersContexts[dwContext]->pFeeds = NULL;
315  sReadersContexts[dwContext]->pMutex = NULL;
316  sReadersContexts[dwContext]->pthCardEvent = NULL;
317 
318  lrv = list_init(&sReadersContexts[dwContext]->handlesList);
319  if (lrv < 0)
320  {
321  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
322  return SCARD_E_NO_MEMORY;
323  }
324 
325  lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
326  RDR_CLIHANDLES_seeker);
327  if (lrv < 0)
328  {
329  Log2(PCSC_LOG_CRITICAL,
330  "list_attributes_seeker failed with return value: %d", lrv);
331  return SCARD_E_NO_MEMORY;
332  }
333 
334  (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
335  NULL);
336 
337  (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
338  NULL);
339  sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
340 
341  /* reference count */
342  sReadersContexts[dwContext]->reference = 1;
343 
344  /* If a clone to this reader exists take some values from that clone */
345  if (parentNode >= 0 && parentNode < pcsclite_max_reader_context)
346  {
347  sReadersContexts[dwContext]->pFeeds =
348  sReadersContexts[parentNode]->pFeeds;
349  *(sReadersContexts[dwContext])->pFeeds += 1;
350  sReadersContexts[dwContext]->vHandle =
351  sReadersContexts[parentNode]->vHandle;
352  sReadersContexts[dwContext]->mMutex =
353  sReadersContexts[parentNode]->mMutex;
354  sReadersContexts[dwContext]->pMutex =
355  sReadersContexts[parentNode]->pMutex;
356 
357  /* Call on the parent driver to see if it is thread safe */
358  dwGetSize = sizeof(ucThread);
359  rv = IFDGetCapabilities(sReadersContexts[parentNode],
360  TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);
361 
362  if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
363  {
364  Log1(PCSC_LOG_INFO, "Driver is thread safe");
365  sReadersContexts[dwContext]->mMutex = NULL;
366  sReadersContexts[dwContext]->pMutex = NULL;
367  }
368  else
369  *(sReadersContexts[dwContext])->pMutex += 1;
370  }
371 
372  if (sReadersContexts[dwContext]->pFeeds == NULL)
373  {
374  sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int));
375 
376  /* Initialize pFeeds to 1, otherwise multiple
377  cloned readers will cause pcscd to crash when
378  RFUnloadReader unloads the driver library
379  and there are still devices attached using it --mikeg*/
380  *(sReadersContexts[dwContext])->pFeeds = 1;
381  }
382 
383  if (sReadersContexts[dwContext]->mMutex == 0)
384  {
385  sReadersContexts[dwContext]->mMutex =
386  malloc(sizeof(pthread_mutex_t));
387  (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
388  }
389 
390  if (sReadersContexts[dwContext]->pMutex == NULL)
391  {
392  sReadersContexts[dwContext]->pMutex = malloc(sizeof(int));
393  *(sReadersContexts[dwContext])->pMutex = 1;
394  }
395 
396  rv = RFInitializeReader(sReadersContexts[dwContext]);
397  if (rv != SCARD_S_SUCCESS)
398  {
399  int log_level = PCSC_LOG_ERROR;
400  if (SCARD_E_UNKNOWN_READER == rv)
401  log_level = PCSC_LOG_INFO;
402 
403  /* Cannot connect to reader. Exit gracefully */
404  Log2(log_level, "%s init failed.", readerName);
405  (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
406  return rv;
407  }
408 
409  /* asynchronous card movement? */
410  {
411  RESPONSECODE (*fct)(DWORD, int) = NULL;
412 
413  dwGetSize = sizeof(fct);
414 
415  rv = IFDGetCapabilities(sReadersContexts[dwContext],
416  TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
417  if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
418  {
419  Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
420  }
421  else
422  {
423  sReadersContexts[dwContext]->pthCardEvent = fct;
424  Log1(PCSC_LOG_INFO, "Using the reader polling thread");
425  }
426 
427  rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
428  if (rv != SCARD_S_SUCCESS)
429  {
430  Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
431  (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
432  return rv;
433  }
434  }
435 
436  /* we have one more reader */
437  ReaderEvents++;
438  /* wrap? */
439  if (ReaderEvents < 0)
440  ReaderEvents = 1;
441 
442  /* Call on the driver to see if there are multiple slots */
443  dwGetSize = sizeof(ucGetData);
444  rv = IFDGetCapabilities((sReadersContexts[dwContext]),
445  TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData);
446 
447  int nbSlots = ucGetData[0];
448  if (rv != IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
449  /* Reader does not have this defined. Must be a single slot
450  * reader so we can just return SCARD_S_SUCCESS. */
451  return SCARD_S_SUCCESS;
452 
453  if (1 == nbSlots)
454  /* Reader has only one slot */
455  return SCARD_S_SUCCESS;
456 
457  /*
458  * Check the number of slots and create a different
459  * structure for each one accordingly
460  */
461 
462  /* Initialize the rest of the slots */
463  for (j = 1; j < nbSlots; j++)
464  {
465  char *tmpReader = NULL;
466  DWORD dwContextB = 0;
467  RESPONSECODE (*fct)(DWORD, int) = NULL;
468 
469  /* We must find an empty spot to put the reader structure */
470  for (i = 0; i < pcsclite_max_reader_context; i++)
471  {
472  if (sReadersContexts[i]->vHandle == 0)
473  {
474  dwContextB = i;
475  break;
476  }
477  }
478 
479  if (i == pcsclite_max_reader_context)
480  {
481  /* No more slot left return */
482  RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
483  return SCARD_E_NO_MEMORY;
484  }
485 
486  /* Copy the previous reader name and increment the slot number */
487  tmpReader = sReadersContexts[dwContextB]->readerState.readerName;
488  memcpy(tmpReader,
489  sReadersContexts[dwContext]->readerState.readerName,
490  sizeof(sReadersContexts[dwContextB]->readerState.readerName));
491  snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j);
492 
493  sReadersContexts[dwContextB]->library =
494  sReadersContexts[dwContext]->library;
495  sReadersContexts[dwContextB]->device =
496  sReadersContexts[dwContext]->device;
497  sReadersContexts[dwContextB]->version =
498  sReadersContexts[dwContext]->version;
499  sReadersContexts[dwContextB]->port =
500  sReadersContexts[dwContext]->port;
501  sReadersContexts[dwContextB]->vHandle =
502  sReadersContexts[dwContext]->vHandle;
503  sReadersContexts[dwContextB]->mMutex =
504  sReadersContexts[dwContext]->mMutex;
505  sReadersContexts[dwContextB]->pMutex =
506  sReadersContexts[dwContext]->pMutex;
507  sReadersContexts[dwContextB]->slot =
508  sReadersContexts[dwContext]->slot + j;
509  sReadersContexts[dwContextB]->pthCardEvent = NULL;
510 
511  /*
512  * Added by Dave - slots did not have a pFeeds
513  * parameter so it was by luck they were working
514  */
515  sReadersContexts[dwContextB]->pFeeds =
516  sReadersContexts[dwContext]->pFeeds;
517 
518  /* Added by Dave for multiple slots */
519  *(sReadersContexts[dwContextB])->pFeeds += 1;
520 
521  sReadersContexts[dwContextB]->contexts = 0;
522  sReadersContexts[dwContextB]->hLockId = 0;
523  sReadersContexts[dwContextB]->LockCount = 0;
524 
525  lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
526  if (lrv < 0)
527  {
528  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
529  return SCARD_E_NO_MEMORY;
530  }
531 
532  lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
533  RDR_CLIHANDLES_seeker);
534  if (lrv < 0)
535  {
536  Log2(PCSC_LOG_CRITICAL,
537  "list_attributes_seeker failed with return value: %d", lrv);
538  return SCARD_E_NO_MEMORY;
539  }
540 
541  (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
542  (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
543  NULL);
544  sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
545 
546  /* reference count */
547  sReadersContexts[dwContextB]->reference = 1;
548 
549  /* Call on the parent driver to see if the slots are thread safe */
550  dwGetSize = sizeof(ucThread);
551  rv = IFDGetCapabilities((sReadersContexts[dwContext]),
552  TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread);
553 
554  if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
555  {
556  Log1(PCSC_LOG_INFO, "Driver is slot thread safe");
557 
558  sReadersContexts[dwContextB]->library =
559  strdup(sReadersContexts[dwContext]->library);
560  sReadersContexts[dwContextB]->device =
561  strdup(sReadersContexts[dwContext]->device);
562  sReadersContexts[dwContextB]->mMutex =
563  malloc(sizeof(pthread_mutex_t));
564  (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
565  NULL);
566 
567  sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int));
568  *(sReadersContexts[dwContextB])->pMutex = 1;
569  }
570  else
571  *(sReadersContexts[dwContextB])->pMutex += 1;
572 
573  rv = RFInitializeReader(sReadersContexts[dwContextB]);
574  if (rv != SCARD_S_SUCCESS)
575  {
576  /* Cannot connect to slot. Exit gracefully */
577  (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
578  return rv;
579  }
580 
581  /* asynchronous card movement? */
582  dwGetSize = sizeof(fct);
583 
584  rv = IFDGetCapabilities((sReadersContexts[dwContextB]),
585  TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
586  if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
587  {
588  Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
589  }
590  else
591  {
592  sReadersContexts[dwContextB]->pthCardEvent = fct;
593  Log1(PCSC_LOG_INFO, "Using the reader polling thread");
594  }
595 
596  rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
597  if (rv != SCARD_S_SUCCESS)
598  {
599  Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
600  (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
601  return rv;
602  }
603  }
604 
605  return SCARD_S_SUCCESS;
606 }
607 
608 LONG RFRemoveReader(const char *readerName, int port, int flags)
609 {
610  char lpcStripReader[MAX_READERNAME];
611  int i;
612 #ifdef FILTER_NAMES
613  const char *extend;
614 #endif
615  int extend_size = 0;
616 
617  if (readerName == NULL)
618  return SCARD_E_INVALID_VALUE;
619 
620 #ifdef FILTER_NAMES
621  extend = SYS_GetEnv("PCSCLITE_FILTER_EXTEND_READER_NAMES");
622  if (extend)
623  extend_size = strlen(extend);
624 #endif
625 
626  for (i = 0; i < pcsclite_max_reader_context; i++)
627  {
628  if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
629  {
630  strncpy(lpcStripReader,
631  sReadersContexts[i]->readerState.readerName,
632  sizeof(lpcStripReader));
633  lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
634 
635  /* Compare only the significant part of the reader name */
636  if ((strncmp(readerName, lpcStripReader, MAX_READERNAME - sizeof(" 00 00")) == 0)
637  && (port == sReadersContexts[i]->port))
638  {
639  if (flags & REMOVE_READER_FLAG_REMOVED)
640  {
641  UCHAR tagValue[1];
642  DWORD valueLength;
643  LONG ret;
644 
645  /* signal to the driver that the reader has been removed */
646  valueLength = sizeof(tagValue);
647  ret = IFDGetCapabilities(sReadersContexts[i],
648  TAG_IFD_DEVICE_REMOVED, &valueLength, tagValue);
649  if ((IFD_SUCCESS) == ret && (1 == tagValue[0]))
650  {
651  tagValue[0] = 1;
652  IFDSetCapabilities(sReadersContexts[i],
653  TAG_IFD_DEVICE_REMOVED, sizeof tagValue, tagValue);
654  }
655  }
656 
657  /* remove the reader */
658  UNREF_READER(sReadersContexts[i])
659  }
660  }
661  }
662 
663  /* we have one less reader */
664  ReaderEvents++;
665  /* wrap? */
666  if (ReaderEvents < 0)
667  ReaderEvents = 1;
668 
669  return SCARD_S_SUCCESS;
670 }
671 
672 LONG removeReader(READER_CONTEXT * sContext)
673 {
674  /* Try to destroy the thread */
675  if (sContext -> pthThread)
676  EHDestroyEventHandler(sContext);
677 
678  if ((NULL == sContext->pMutex) || (NULL == sContext->pFeeds))
679  {
680  Log1(PCSC_LOG_ERROR,
681  "Trying to remove an already removed driver");
682  return SCARD_E_INVALID_VALUE;
683  }
684 
685  RFUnInitializeReader(sContext);
686 
687  *sContext->pMutex -= 1;
688 
689  /* free shared resources when the last slot is closed */
690  if (0 == *sContext->pMutex)
691  {
692  (void)pthread_mutex_destroy(sContext->mMutex);
693  free(sContext->mMutex);
694  sContext->mMutex = NULL;
695  free(sContext->library);
696  free(sContext->device);
697  free(sContext->pMutex);
698  sContext->pMutex = NULL;
699  }
700 
701  *sContext->pFeeds -= 1;
702 
703  /* Added by Dave to free the pFeeds variable */
704  if (*sContext->pFeeds == 0)
705  {
706  free(sContext->pFeeds);
707  sContext->pFeeds = NULL;
708  }
709 
710  (void)pthread_mutex_destroy(&sContext->powerState_lock);
711  sContext->version = 0;
712  sContext->port = 0;
713  sContext->contexts = 0;
714  sContext->slot = 0;
715  sContext->hLockId = 0;
716  sContext->LockCount = 0;
717  sContext->vHandle = NULL;
718 
719  (void)pthread_mutex_lock(&sContext->handlesList_lock);
720  while (list_size(&sContext->handlesList) != 0)
721  {
722  int lrv;
723  RDR_CLIHANDLES *currentHandle;
724 
725  currentHandle = list_get_at(&sContext->handlesList, 0);
726  lrv = list_delete_at(&sContext->handlesList, 0);
727  if (lrv < 0)
728  Log2(PCSC_LOG_CRITICAL,
729  "list_delete_at failed with return value: %d", lrv);
730 
731  free(currentHandle);
732  }
733  (void)pthread_mutex_unlock(&sContext->handlesList_lock);
734  (void)pthread_mutex_destroy(&sContext->handlesList_lock);
735  list_destroy(&sContext->handlesList);
736 
737  /* signal an event to clients */
739 
740  return SCARD_S_SUCCESS;
741 }
742 
743 LONG RFSetReaderName(READER_CONTEXT * rContext, const char *readerName,
744  const char *libraryName, int port)
745 {
746  LONG parent = -1; /* reader number of the parent of the clone */
747  DWORD valueLength;
748  int currentDigit = -1;
749  int supportedChannels = 0;
750  bool usedDigits[pcsclite_max_reader_context];
751  int i;
752  const char *extend = NULL;
753 
754  /* Clear the list */
755  for (i = 0; i < pcsclite_max_reader_context; i++)
756  usedDigits[i] = false;
757 
758  for (i = 0; i < pcsclite_max_reader_context; i++)
759  {
760  if (sReadersContexts[i]->vHandle != 0)
761  {
762  if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
763  {
764  UCHAR tagValue[1];
765  LONG ret;
766 
767  /* Ask the driver if it supports multiple channels */
768  valueLength = sizeof(tagValue);
769  ret = IFDGetCapabilities(sReadersContexts[i],
771  &valueLength, tagValue);
772 
773  if ((ret == IFD_SUCCESS) && (valueLength == 1) &&
774  (tagValue[0] > 1))
775  {
776  supportedChannels = tagValue[0];
777  Log2(PCSC_LOG_INFO,
778  "Support %d simultaneous readers", tagValue[0]);
779  }
780  else
781  supportedChannels = 1;
782 
783  /* Check to see if it is a hotplug reader and different */
784  if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
785  PCSCLITE_HP_BASE_PORT)
786  && (sReadersContexts[i]->port != port))
787  || (supportedChannels > 1))
788  {
789  const char *reader = sReadersContexts[i]->readerState.readerName;
790 
791  /*
792  * tells the caller who the parent of this
793  * clone is so it can use its shared
794  * resources like mutex/etc.
795  */
796  parent = i;
797 
798  /*
799  * If the same reader already exists and it is
800  * hotplug then we must look for others and
801  * enumerate the readername
802  */
803  currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
804 
805  /* This spot is taken */
806  usedDigits[currentDigit] = true;
807  }
808  }
809  }
810  }
811 
812  /* default value */
813  i = 0;
814 
815  /* Other identical readers exist on the same bus */
816  if (currentDigit != -1)
817  {
818  for (i = 0; i < pcsclite_max_reader_context; i++)
819  {
820  /* get the first free digit */
821  if (usedDigits[i] == false)
822  break;
823  }
824 
825  if (i == pcsclite_max_reader_context)
826  {
827  Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", pcsclite_max_reader_context);
828  return -2;
829  }
830 
831  if (i >= supportedChannels)
832  {
833  Log3(PCSC_LOG_ERROR, "Driver %s does not support more than "
834  "%d reader(s). Maybe the driver should support "
835  "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
836  return -2;
837  }
838  }
839 
840 #ifdef FILTER_NAMES
841  extend = SYS_GetEnv("PCSCLITE_FILTER_EXTEND_READER_NAMES");
842  if (NULL == extend)
843  extend = "";
844 #else
845  extend = "";
846 #endif
847 
848  snprintf(rContext->readerState.readerName,
849  sizeof(rContext->readerState.readerName), "%s%s %02X 00",
850  readerName, extend, i);
851 
852  /* Set the slot in 0xDDDDCCCC */
853  rContext->slot = i << 16;
854 
855  return parent;
856 }
857 
858 LONG RFReaderInfo(const char *readerName, READER_CONTEXT ** sReader)
859 {
860  int i;
861 
862  if (readerName == NULL)
863  return SCARD_E_UNKNOWN_READER;
864 
865  for (i = 0; i < pcsclite_max_reader_context; i++)
866  {
867  if (sReadersContexts[i]->vHandle != 0)
868  {
869  if (strcmp(readerName,
870  sReadersContexts[i]->readerState.readerName) == 0)
871  {
872  /* Increase reference count */
873  REF_READER(sReadersContexts[i])
874 
875  *sReader = sReadersContexts[i];
876  return SCARD_S_SUCCESS;
877  }
878  }
879  }
880 
881  return SCARD_E_UNKNOWN_READER;
882 }
883 
884 LONG RFReaderInfoById(SCARDHANDLE hCard, READER_CONTEXT * * sReader)
885 {
886  int i;
887 
888  for (i = 0; i < pcsclite_max_reader_context; i++)
889  {
890  if (sReadersContexts[i]->vHandle != 0)
891  {
892  RDR_CLIHANDLES * currentHandle;
893  (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
894  currentHandle = list_seek(&sReadersContexts[i]->handlesList,
895  &hCard);
896  (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
897  if (currentHandle != NULL)
898  {
899  /* Increase reference count */
900  REF_READER(sReadersContexts[i])
901 
902  *sReader = sReadersContexts[i];
903  return SCARD_S_SUCCESS;
904  }
905  }
906  }
907 
908  return SCARD_E_INVALID_VALUE;
909 }
910 
911 LONG RFLoadReader(READER_CONTEXT * rContext)
912 {
913  LONG ret = SCARD_S_SUCCESS;
914  if (rContext->vHandle != 0)
915  {
916  Log2(PCSC_LOG_INFO, "Reusing already loaded driver for %s",
917  rContext->library);
918  /* Another reader exists with this library loaded */
919  return SCARD_S_SUCCESS;
920  }
921 
922  rContext->vHandle = DYN_LoadLibrary(rContext->library);
923  if (NULL == rContext->vHandle)
924  ret = SCARD_F_UNKNOWN_ERROR;
925  return ret;
926 }
927 
928 LONG RFBindFunctions(READER_CONTEXT * rContext)
929 {
930  int rv;
931  void *f;
932 
933  rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannelByName", true);
934  if (SCARD_S_SUCCESS == rv)
935  {
936  /* Ifd Handler 3.0 found */
937  rContext->version = IFD_HVERSION_3_0;
938  }
939  else
940  {
941  rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannel", false);
942  if (SCARD_S_SUCCESS == rv)
943  {
944  /* Ifd Handler 2.0 found */
945  rContext->version = IFD_HVERSION_2_0;
946  }
947  else
948  {
949  /* Neither version of the IFD Handler was found - exit */
950  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
951  return SCARD_F_UNKNOWN_ERROR;
952  }
953  }
954 
955  if (rContext->version == IFD_HVERSION_2_0)
956  {
957  /* The following binds version 2.0 of the IFD Handler specs */
958 #define GET_ADDRESS_OPTIONALv2(s, code) \
959 { \
960  void *f1 = NULL; \
961  int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
962  if (SCARD_S_SUCCESS != rvl) \
963  { \
964  code \
965  } \
966  rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
967 }
968 
969 #define GET_ADDRESSv2(s) \
970  GET_ADDRESS_OPTIONALv2(s, \
971  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
972  return(rv); )
973 
974  Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0");
975 
976  GET_ADDRESSv2(CreateChannel)
977  GET_ADDRESSv2(CloseChannel)
978  GET_ADDRESSv2(GetCapabilities)
979  GET_ADDRESSv2(SetCapabilities)
980  GET_ADDRESSv2(PowerICC)
981  GET_ADDRESSv2(TransmitToICC)
982  GET_ADDRESSv2(ICCPresence)
983  GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
984 
985  GET_ADDRESSv2(Control)
986  }
987  else if (rContext->version == IFD_HVERSION_3_0)
988  {
989  /* The following binds version 3.0 of the IFD Handler specs */
990 #define GET_ADDRESS_OPTIONALv3(s, code) \
991 { \
992  void *f1 = NULL; \
993  int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
994  if (SCARD_S_SUCCESS != rvl) \
995  { \
996  code \
997  } \
998  rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
999 }
1000 
1001 #define GET_ADDRESSv3(s) \
1002  GET_ADDRESS_OPTIONALv3(s, \
1003  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
1004  return(rv); )
1005 
1006  Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0");
1007 
1008  GET_ADDRESSv2(CreateChannel)
1009  GET_ADDRESSv2(CloseChannel)
1010  GET_ADDRESSv2(GetCapabilities)
1011  GET_ADDRESSv2(SetCapabilities)
1012  GET_ADDRESSv2(PowerICC)
1013  GET_ADDRESSv2(TransmitToICC)
1014  GET_ADDRESSv2(ICCPresence)
1015  GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
1016 
1017  GET_ADDRESSv3(CreateChannelByName)
1018  GET_ADDRESSv3(Control)
1019  }
1020  else
1021  {
1022  /* Who knows what could have happened for it to get here. */
1023  Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0");
1024  return SCARD_F_UNKNOWN_ERROR;
1025  }
1026 
1027  return SCARD_S_SUCCESS;
1028 }
1029 
1030 LONG RFUnBindFunctions(READER_CONTEXT * rContext)
1031 {
1032  /* Zero out everything */
1033  memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions));
1034 
1035  return SCARD_S_SUCCESS;
1036 }
1037 
1038 LONG RFUnloadReader(READER_CONTEXT * rContext)
1039 {
1040  /* Make sure no one else is using this library */
1041  if (*rContext->pFeeds == 1)
1042  {
1043  Log1(PCSC_LOG_INFO, "Unloading reader driver.");
1044  (void)DYN_CloseLibrary(rContext->vHandle);
1045  rContext->vHandle = NULL;
1046  }
1047 
1048  rContext->vHandle = NULL;
1049 
1050  return SCARD_S_SUCCESS;
1051 }
1052 
1053 LONG RFCheckSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1054 {
1055  if (rContext->hLockId == 0 || rContext->hLockId == hCard)
1056  return SCARD_S_SUCCESS;
1057  else
1059 }
1060 
1061 LONG RFLockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1062 {
1063  LONG rv;
1064 
1065  (void)pthread_mutex_lock(&LockMutex);
1066  rv = RFCheckSharing(hCard, rContext);
1067  if (SCARD_S_SUCCESS == rv)
1068  {
1069  rContext->LockCount += 1;
1070  rContext->hLockId = hCard;
1071  }
1072  (void)pthread_mutex_unlock(&LockMutex);
1073 
1074  return rv;
1075 }
1076 
1077 LONG RFUnlockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1078 {
1079  LONG rv;
1080 
1081  (void)pthread_mutex_lock(&LockMutex);
1082  rv = RFCheckSharing(hCard, rContext);
1083  if (SCARD_S_SUCCESS == rv)
1084  {
1086  {
1087  if (rContext->LockCount > 1)
1088  rContext->LockCount -= 1;
1089  else
1091  }
1092  else
1093  {
1094  if (rContext->LockCount > 0)
1095  {
1096  rContext->LockCount -= 1;
1097  if (0 == rContext->LockCount)
1098  rContext->hLockId = 0;
1099  }
1100  else
1101  /* rContext->LockCount == 0 */
1103  }
1104  }
1105  (void)pthread_mutex_unlock(&LockMutex);
1106 
1107  return rv;
1108 }
1109 
1110 LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1111 {
1112  LONG rv;
1113 
1114  (void)pthread_mutex_lock(&LockMutex);
1115  rv = RFCheckSharing(hCard, rContext);
1116  if (SCARD_S_SUCCESS == rv)
1117  {
1118  rContext->LockCount = 0;
1119  rContext->hLockId = 0;
1120  }
1121  (void)pthread_mutex_unlock(&LockMutex);
1122 
1123  return rv;
1124 }
1125 
1126 LONG RFInitializeReader(READER_CONTEXT * rContext)
1127 {
1128  LONG rv = SCARD_S_SUCCESS;
1129  RESPONSECODE rvd;
1130 
1131  /* Spawn the event handler thread */
1132  Log4(PCSC_LOG_INFO, "Attempting startup of %s using %s on port 0x%X",
1133  rContext->readerState.readerName, rContext->library, rContext->port);
1134 
1135 #ifndef PCSCLITE_STATIC_DRIVER
1136  /* loads the library */
1137  rv = RFLoadReader(rContext);
1138  if (rv != SCARD_S_SUCCESS)
1139  {
1140  Log2(PCSC_LOG_ERROR, "RFLoadReader failed: 0x%lX", rv);
1141  return rv;
1142  }
1143 
1144  /* binds the functions */
1145  rv = RFBindFunctions(rContext);
1146 
1147  if (rv != SCARD_S_SUCCESS)
1148  {
1149  Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: 0x%lX", rv);
1150  (void)RFUnloadReader(rContext);
1151  return rv;
1152  }
1153 #else
1154  /* define a fake vHandle. Can be any value except NULL */
1155  rContext->vHandle = RFInitializeReader;
1156 #endif
1157 
1158  /* tries to open the port */
1159  rvd = IFDOpenIFD(rContext);
1160 
1161  if (rvd != IFD_SUCCESS)
1162  {
1163  int log_level = PCSC_LOG_CRITICAL;
1165 
1166  if (IFD_NO_SUCH_DEVICE == rvd)
1167  {
1168  /* wrong interface on a composite device? */
1169  log_level = PCSC_LOG_INFO;
1171  }
1172 
1173  Log3(log_level, "Open Port 0x%X Failed (%s)",
1174  rContext->port, rContext->device);
1175 
1176  /* IFDOpenIFD() failed */
1177  /* the reader was not started correctly */
1178  rContext->slot = -1;
1179  }
1180 
1181  return rv;
1182 }
1183 
1184 void RFUnInitializeReader(READER_CONTEXT * rContext)
1185 {
1186  Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
1187  rContext->readerState.readerName);
1188 
1189  /* Do not close a reader if IFDOpenIFD() failed in RFInitializeReader() */
1190  if (rContext->slot != -1)
1191  (void)IFDCloseIFD(rContext);
1192 
1193  (void)RFUnBindFunctions(rContext);
1194  (void)RFUnloadReader(rContext);
1195 
1196  /*
1197  * Zero out the public status struct to allow it to be recycled and
1198  * used again
1199  */
1200  memset(rContext->readerState.readerName, 0,
1201  sizeof(rContext->readerState.readerName));
1202  memset(rContext->readerState.cardAtr, 0,
1203  sizeof(rContext->readerState.cardAtr));
1204  rContext->readerState.readerState = 0;
1205  rContext->readerState.eventCounter = 0;
1206  rContext->readerState.readerSharing = 0;
1209 
1210  return;
1211 }
1212 
1213 SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1214 {
1215  SCARDHANDLE randHandle;
1216  LONG ret;
1217 
1218  (void)rContext;
1219 
1220  do
1221  {
1222  READER_CONTEXT *dummy_reader;
1223 
1224  /* Create a random handle with 32 bits check to see if it already is
1225  * used. */
1226  /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be
1227  * generated. The client and server would associate token and hCard
1228  * for authentication. */
1229  randHandle = SYS_RandomInt();
1230 
1231  /* do we already use this hCard somewhere? */
1232  ret = RFReaderInfoById(randHandle, &dummy_reader);
1233  if (SCARD_S_SUCCESS == ret)
1234  UNREF_READER(dummy_reader)
1235  }
1236  while (SCARD_S_SUCCESS == ret);
1237 
1238  /* Once the for loop is completed w/o restart a good handle was
1239  * found and the loop can be exited. */
1240  return randHandle;
1241 }
1242 
1243 LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1244 {
1245  int listLength, lrv;
1246  RDR_CLIHANDLES *newHandle;
1247  LONG rv = SCARD_S_SUCCESS;
1248 
1249  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1250  listLength = list_size(&rContext->handlesList);
1251 
1252  /* Throttle the number of possible handles */
1253  if (listLength >= maxReaderHandles)
1254  {
1255  Log2(PCSC_LOG_CRITICAL,
1256  "Too many handles opened, exceeding configured max (%d)",
1257  maxReaderHandles);
1258  rv = SCARD_E_NO_MEMORY;
1259  goto end;
1260  }
1261 
1262  newHandle = malloc(sizeof(RDR_CLIHANDLES));
1263  if (NULL == newHandle)
1264  {
1265  Log1(PCSC_LOG_CRITICAL, "malloc failed");
1266  rv = SCARD_E_NO_MEMORY;
1267  goto end;
1268  }
1269 
1270  newHandle->hCard = hCard;
1271  atomic_init(&newHandle->dwEventStatus, 0);
1272 
1273  lrv = list_append(&rContext->handlesList, newHandle);
1274  if (lrv < 0)
1275  {
1276  free(newHandle);
1277  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
1278  lrv);
1279  rv = SCARD_E_NO_MEMORY;
1280  }
1281 end:
1282  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1283  return rv;
1284 }
1285 
1286 LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1287 {
1288  RDR_CLIHANDLES *currentHandle;
1289  int lrv;
1290  LONG rv = SCARD_S_SUCCESS;
1291 
1292  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1293  currentHandle = list_seek(&rContext->handlesList, &hCard);
1294  if (NULL == currentHandle)
1295  {
1296  Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%lX", hCard);
1298  goto end;
1299  }
1300 
1301  lrv = list_delete(&rContext->handlesList, currentHandle);
1302  if (lrv < 0)
1303  Log2(PCSC_LOG_CRITICAL,
1304  "list_delete failed with return value: %d", lrv);
1305 
1306  free(currentHandle);
1307 
1308 end:
1309  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1310 
1311  /* Not Found */
1312  return rv;
1313 }
1314 
1315 void RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1316 {
1317  /* Set all the handles for that reader to the event */
1318  int list_index, listSize;
1319  RDR_CLIHANDLES *currentHandle;
1320 
1321  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1322  listSize = list_size(&rContext->handlesList);
1323 
1324  for (list_index = 0; list_index < listSize; list_index++)
1325  {
1326  currentHandle = list_get_at(&rContext->handlesList, list_index);
1327  if (NULL == currentHandle)
1328  {
1329  Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %d",
1330  list_index);
1331  continue;
1332  }
1333 
1334  currentHandle->dwEventStatus = dwEvent;
1335  }
1336  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1337 
1338  if (SCARD_REMOVED == dwEvent)
1339  {
1340  /* unlock the card */
1341  rContext->hLockId = 0;
1342  rContext->LockCount = 0;
1343  }
1344 
1345  return;
1346 }
1347 
1348 LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1349 {
1350  LONG rv;
1351  RDR_CLIHANDLES *currentHandle;
1352  DWORD dwEventStatus;
1353 
1354  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1355  currentHandle = list_seek(&rContext->handlesList, &hCard);
1356  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1357  if (NULL == currentHandle)
1358  {
1359  /* Not Found */
1360  Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard 0x%lX", hCard);
1361  return SCARD_E_INVALID_HANDLE;
1362  }
1363 
1364  dwEventStatus = currentHandle->dwEventStatus;
1365  switch(dwEventStatus)
1366  {
1367  case 0:
1368  rv = SCARD_S_SUCCESS;
1369  break;
1370 
1371  case SCARD_REMOVED:
1372  rv = SCARD_W_REMOVED_CARD;
1373  break;
1374 
1375  case SCARD_RESET:
1376  rv = SCARD_W_RESET_CARD;
1377  break;
1378 
1379  default:
1380  rv = SCARD_E_INVALID_VALUE;
1381  }
1382 
1383  return rv;
1384 }
1385 
1386 LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1387 {
1388  RDR_CLIHANDLES *currentHandle;
1389 
1390  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1391  currentHandle = list_seek(&rContext->handlesList, &hCard);
1392  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1393  if (NULL == currentHandle)
1394  /* Not Found */
1395  return SCARD_E_INVALID_HANDLE;
1396 
1397  currentHandle->dwEventStatus = 0;
1398 
1399  /* hCards should be unique so we
1400  * should be able to return
1401  * as soon as we have a hit */
1402  return SCARD_S_SUCCESS;
1403 }
1404 
1405 LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1406 {
1407  if (rContext->readerState.readerState & SCARD_UNKNOWN)
1409  else
1410  return SCARD_S_SUCCESS;
1411 }
1412 
1413 void RFCleanupReaders(void)
1414 {
1415  int i;
1416 
1417  Log1(PCSC_LOG_INFO, "entering cleaning function");
1418  for (i = 0; i < pcsclite_max_reader_context; i++)
1419  {
1420  if (sReadersContexts[i]->vHandle != 0)
1421  {
1422  LONG rv;
1423  char lpcStripReader[MAX_READERNAME];
1424 
1425  Log2(PCSC_LOG_INFO, "Stopping reader: %s",
1426  sReadersContexts[i]->readerState.readerName);
1427 
1428  strncpy(lpcStripReader,
1429  sReadersContexts[i]->readerState.readerName,
1430  sizeof(lpcStripReader));
1431  /* strip the 6 last char ' 00 00' */
1432  lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
1433 
1434  rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port,
1435  REMOVE_READER_NO_FLAG);
1436 
1437  if (rv != SCARD_S_SUCCESS)
1438  Log2(PCSC_LOG_ERROR, "RFRemoveReader error: %s", rv2text(rv));
1439  }
1440 
1441  free(sReadersContexts[i]);
1442  sReadersContexts[i] = NULL;
1443  }
1444 
1445 #ifdef USE_SERIAL
1446  if (ConfigFile)
1447  {
1448  free(ConfigFile);
1449  ConfigFile = NULL;
1450  }
1451 #endif
1452 }
1453 
1458 #ifdef USE_USB
1459 void RFWaitForReaderInit(void)
1460 {
1461  bool need_to_wait;
1462 
1463  do
1464  {
1465  need_to_wait = false;
1466  for (int i = 0; i < pcsclite_max_reader_context; i++)
1467  {
1468  /* reader is present */
1469  if (sReadersContexts[i] && sReadersContexts[i]->vHandle != NULL)
1470  {
1471  /* but card state is not yet available */
1473  == sReadersContexts[i]->readerState.cardAtrLength)
1474  {
1475  Log2(PCSC_LOG_DEBUG, "Waiting init for reader: %s",
1476  sReadersContexts[i]->readerState.readerName);
1477  need_to_wait = true;
1478  }
1479  }
1480  }
1481 
1482  if (need_to_wait)
1483  SYS_USleep(10*1000); /* 10 ms */
1484  } while (need_to_wait);
1485 }
1486 #endif
1487 
1488 #ifdef USE_SERIAL
1489 int RFStartSerialReaders(const char *readerconf)
1490 {
1491  SerialReader *reader_list = NULL;
1492  int i, rv;
1493 
1494  /* remember the configuration filename for RFReCheckReaderConf() */
1495  ConfigFile = strdup(readerconf);
1496 
1497  rv = DBGetReaderListDir(readerconf, &reader_list);
1498 
1499  /* the list is empty */
1500  if (NULL == reader_list)
1501  return rv;
1502 
1503  for (i=0; reader_list[i].pcFriendlyname; i++)
1504  {
1505  int j;
1506 
1507  (void)RFAddReader(reader_list[i].pcFriendlyname,
1508  reader_list[i].channelId,
1509  reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1510 
1511  /* update the ConfigFileCRC (this false "CRC" is very weak) */
1512  for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1513  ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1514  for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1515  ConfigFileCRC += reader_list[i].pcLibpath[j];
1516  for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1517  ConfigFileCRC += reader_list[i].pcDevicename[j];
1518 
1519  /* free strings allocated by DBGetReaderListDir() */
1520  free(reader_list[i].pcFriendlyname);
1521  free(reader_list[i].pcLibpath);
1522  free(reader_list[i].pcDevicename);
1523  }
1524  free(reader_list);
1525 
1526  return rv;
1527 }
1528 
1529 void RFReCheckReaderConf(void)
1530 {
1531  SerialReader *reader_list = NULL;
1532  int i, crc;
1533 
1534  (void)DBGetReaderListDir(ConfigFile, &reader_list);
1535 
1536  /* the list is empty */
1537  if (NULL == reader_list)
1538  return;
1539 
1540  crc = 0;
1541  for (i=0; reader_list[i].pcFriendlyname; i++)
1542  {
1543  int j;
1544 
1545  /* calculate a local crc */
1546  for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1547  crc += reader_list[i].pcFriendlyname[j];
1548  for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1549  crc += reader_list[i].pcLibpath[j];
1550  for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1551  crc += reader_list[i].pcDevicename[j];
1552  }
1553 
1554  /* cancel if the configuration file has been modified */
1555  if (crc != ConfigFileCRC)
1556  {
1557  Log2(PCSC_LOG_CRITICAL,
1558  "configuration file: %s has been modified. Recheck canceled",
1559  ConfigFile);
1560  return;
1561  }
1562 
1563  for (i=0; reader_list[i].pcFriendlyname; i++)
1564  {
1565  int r;
1566  char present = false;
1567 
1568  Log2(PCSC_LOG_DEBUG, "refresh reader: %s",
1569  reader_list[i].pcFriendlyname);
1570 
1571  /* is the reader already present? */
1572  for (r = 0; r < pcsclite_max_reader_context; r++)
1573  {
1574  if (sReadersContexts[r]->vHandle != 0)
1575  {
1576  char lpcStripReader[MAX_READERNAME];
1577  int tmplen;
1578 
1579  /* get the reader name without the reader and slot numbers */
1580  strncpy(lpcStripReader,
1581  sReadersContexts[r]->readerState.readerName,
1582  sizeof(lpcStripReader));
1583  tmplen = strlen(lpcStripReader);
1584  lpcStripReader[tmplen - 6] = 0;
1585 
1586  if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1587  && (reader_list[i].channelId == sReadersContexts[r]->port))
1588  {
1589  DWORD dwStatus = 0;
1590 
1591  /* the reader was already started */
1592  present = true;
1593 
1594  /* verify the reader is still connected */
1595  if (IFDStatusICC(sReadersContexts[r], &dwStatus)
1596  != SCARD_S_SUCCESS)
1597  {
1598  Log2(PCSC_LOG_INFO, "Reader %s disappeared",
1599  reader_list[i].pcFriendlyname);
1600  (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1601  reader_list[i].channelId, REMOVE_READER_NO_FLAG);
1602  }
1603  }
1604  }
1605  }
1606 
1607  /* the reader was not present */
1608  if (!present)
1609  /* we try to add it */
1610  (void)RFAddReader(reader_list[i].pcFriendlyname,
1611  reader_list[i].channelId, reader_list[i].pcLibpath,
1612  reader_list[i].pcDevicename);
1613 
1614  /* free strings allocated by DBGetReaderListDir() */
1615  free(reader_list[i].pcFriendlyname);
1616  free(reader_list[i].pcLibpath);
1617  free(reader_list[i].pcDevicename);
1618  }
1619  free(reader_list);
1620 }
1621 #endif
1622 
1624 {
1625  (void)pthread_mutex_lock(&rContext->powerState_lock);
1626  int result = rContext->powerState;
1627  (void)pthread_mutex_unlock(&rContext->powerState_lock);
1628  return result;
1629 }
1630 
1631 void RFSetPowerState(READER_CONTEXT * rContext, int value)
1632 {
1633  (void)pthread_mutex_lock(&rContext->powerState_lock);
1634  rContext->powerState = value;
1635  (void)pthread_mutex_unlock(&rContext->powerState_lock);
1636 }
1637 
LONG IFDStatusICC(READER_CONTEXT *rContext, PDWORD pdwStatus)
Provide statistical information about the IFD and ICC including insertions, atr, powering status/etc...
Definition: ifdwrapper.c:337
This abstracts dynamic library loading functions.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:141
#define IFD_NO_SUCH_DEVICE
The IFD_NO_SUCH_DEVICE error must be returned by the driver when it detects the reader is no more pre...
Definition: ifdhandler.h:372
#define TAG_IFD_THREAD_SAFE
driver is thread safe
Definition: ifdhandler.h:324
_Atomic LPVOID vHandle
Dlopen handle.
Definition: readers.h:120
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
int port
Port ID.
Definition: readers.h:122
void EHSignalEventToClients(void)
Sends an asynchronous event to any waiting client.
Definition: eventhandler.c:114
pthread_t pthThread
Event polling thread.
Definition: readers.h:108
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition: readers.h:56
#define SCARD_E_INVALID_TARGET
Registry startup information is missing or invalid.
Definition: pcsclite.h:117
#define SCARD_UNKNOWN
Unknown state.
Definition: pcsclite.h:258
RESPONSECODE(* pthCardEvent)(DWORD, int)
Card Event sync.
Definition: readers.h:109
RESPONSECODE IFDOpenIFD(READER_CONTEXT *rContext)
Open a communication channel to the IFD.
Definition: ifdwrapper.c:105
This handles abstract system level calls.
int slot
Current Reader Slot.
Definition: readers.h:123
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
Definition: sys_unix.c:168
union ReaderContext::@3 psFunctions
driver functions
This wraps the dynamic ifdhandler functions.
int * pMutex
Number of client to mutex.
Definition: readers.h:128
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:151
pthread_mutex_t handlesList_lock
lock for the above list
Definition: readers.h:112
_Atomic int reference
number of users of the structure
Definition: readers.h:131
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:80
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Gets capabilities in the reader.
Definition: ifdwrapper.c:238
char * library
Library Path.
Definition: readers.h:106
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:62
_Atomic SCARDHANDLE hLockId
Lock Id.
Definition: readers.h:124
#define SCARD_F_UNKNOWN_ERROR
An internal error has been detected, but the source is unknown.
Definition: pcsclite.h:147
char * pcLibpath
LIBPATH.
Definition: readerfactory.h:50
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition: pcsclite.h:119
RESPONSECODE IFDCloseIFD(READER_CONTEXT *rContext)
Close a communication channel to the IFD.
Definition: ifdwrapper.c:161
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:153
int * pFeeds
Number of shared client to lib.
Definition: readers.h:127
#define TAG_IFD_SLOTS_NUMBER
number of slots of the reader
Definition: ifdhandler.h:325
int version
IFD Handler version number.
Definition: readers.h:121
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
Definition: pcsclite.h:217
pthread_mutex_t * mMutex
Mutex for this connection.
Definition: readers.h:110
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: readers.h:58
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define TAG_IFD_SLOT_THREAD_SAFE
support access to different slots of the reader
Definition: ifdhandler.h:323
READER_STATE readerState
reader state
Definition: readers.h:133
uint32_t readerState
SCARD_* bit field.
Definition: readers.h:53
_Atomic DWORD dwEventStatus
Recent event that must be sent.
Definition: readerfactory.h:57
_Atomic int LockCount
number of recursive locks
Definition: readers.h:125
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition: pcsclite.h:219
int powerState
auto power off state
Definition: readers.h:129
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition: pcsclite.h:240
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition: pcsclite.h:123
_Atomic uint32_t cardAtrLength
ATR length.
Definition: readers.h:57
#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
driver uses a polling thread with a timeout parameter
Definition: ifdhandler.h:330
#define TAG_IFD_SIMULTANEOUS_ACCESS
number of reader the driver can manage
Definition: ifdhandler.h:326
#define SCARD_E_DUPLICATE_READER
The reader driver did not produce a unique reader name.
Definition: pcsclite.h:161
_Atomic int32_t contexts
Number of open contexts.
Definition: readers.h:126
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:129
char * device
Device Name.
Definition: readers.h:107
This keeps track of a list of currently available reader structures.
#define MAX_ATR_SIZE
Maximum ATR size.
Definition: pcsclite.h:59
char * pcDevicename
DEVICENAME.
Definition: readerfactory.h:49
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:125
char readerName[MAX_READERNAME]
reader name
Definition: readers.h:51
int RFGetPowerState(READER_CONTEXT *rContext)
Wait until all connected readers have a chance to power up a possibly inserted card.
#define TAG_IFD_DEVICE_REMOVED
signals the reader has been removed
Definition: ifdhandler.h:331
This provides a search API for hot pluggble devices.
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
Definition: ifdwrapper.c:207
define structures to represent a reader
pthread_mutex_t powerState_lock
powerState mutex
Definition: readers.h:130
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: readers.h:54
char * pcFriendlyname
FRIENDLYNAME.
Definition: readerfactory.h:48
uint32_t eventCounter
number of card events
Definition: readers.h:52
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:113
int SYS_RandomInt(void)
Generate a pseudo random number.
Definition: sys_unix.c:108
This handles debugging.
#define IFD_SUCCESS
no error
Definition: ifdhandler.h:351
SCARDHANDLE hCard
hCard for this connection
Definition: readerfactory.h:56
#define READER_NOT_INITIALIZED
Special value to indicate that power up has not yet happen This is used to auto start mode to wait un...
Definition: eventhandler.h:67