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