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