00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00026 #include "config.h"
00027 #include <time.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stddef.h>
00031 #include <stdlib.h>
00032 #include <unistd.h>
00033 #include <pthread.h>
00034
00035 #include "pcscd.h"
00036 #include "winscard.h"
00037 #include "debuglog.h"
00038 #include "winscard_msg.h"
00039 #include "winscard_svc.h"
00040 #include "sys_generic.h"
00041 #include "utils.h"
00042 #include "readerfactory.h"
00043 #include "eventhandler.h"
00044 #include "simclist.h"
00045
00052 extern char AutoExit;
00053 static int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
00054 static int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
00055
00056 static list_t contextsList;
00057 pthread_mutex_t contextsList_lock;
00059 struct _psContext
00060 {
00061 int32_t hContext;
00062 list_t cardsList;
00063 pthread_mutex_t cardsList_lock;
00064 uint32_t dwClientID;
00065 pthread_t pthThread;
00066 int protocol_major, protocol_minor;
00067 };
00068 typedef struct _psContext SCONTEXT;
00069
00070 static LONG MSGCheckHandleAssociation(SCARDHANDLE, SCONTEXT *);
00071 static LONG MSGAddContext(SCARDCONTEXT, SCONTEXT *);
00072 static LONG MSGRemoveContext(SCARDCONTEXT, SCONTEXT *);
00073 static LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, SCONTEXT *);
00074 static LONG MSGRemoveHandle(SCARDHANDLE, SCONTEXT *);
00075 static LONG MSGCleanupClient(SCONTEXT *);
00076
00077 static void ContextThread(LPVOID pdwIndex);
00078
00079 extern READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00080
00081 static int contextsListhContext_seeker(const void *el, const void *key)
00082 {
00083 const SCONTEXT * currentContext = (SCONTEXT *)el;
00084
00085 if ((el == NULL) || (key == NULL))
00086 {
00087 Log3(PCSC_LOG_CRITICAL, "contextsListhContext_seeker called with NULL pointer: el=%X, key=%X", el, key);
00088 }
00089
00090 if (currentContext->hContext == *(int32_t *)key)
00091 return 1;
00092 return 0;
00093 }
00094
00095 LONG ContextsInitialize(int customMaxThreadCounter, int customMaxThreadCardHandles)
00096 {
00097 int lrv = 0;
00098
00099 if (customMaxThreadCounter != 0)
00100 contextMaxThreadCounter = customMaxThreadCounter;
00101
00102 if (customMaxThreadCardHandles != 0)
00103 contextMaxCardHandles = customMaxThreadCardHandles;
00104
00105 lrv = list_init(&contextsList);
00106 if (lrv < 0)
00107 {
00108 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
00109 return -1;
00110 }
00111 lrv = list_attributes_seeker(& contextsList, contextsListhContext_seeker);
00112 if (lrv < 0)
00113 {
00114 Log2(PCSC_LOG_CRITICAL, "list_attributes_seeker failed with return value: %X", lrv);
00115 return -1;
00116 }
00117
00118 (void)pthread_mutex_init(&contextsList_lock, NULL);
00119
00120 return 1;
00121 }
00122
00123 void ContextsDeinitialize(void)
00124 {
00125 int listSize;
00126 listSize = list_size(&contextsList);
00127 Log2(PCSC_LOG_DEBUG, "remaining threads: %d", listSize);
00128
00129 }
00130
00141 LONG CreateContextThread(uint32_t *pdwClientID)
00142 {
00143 int rv;
00144 int lrv;
00145 int listSize;
00146 SCONTEXT * newContext = NULL;
00147
00148 (void)pthread_mutex_lock(&contextsList_lock);
00149 listSize = list_size(&contextsList);
00150 (void)pthread_mutex_unlock(&contextsList_lock);
00151
00152 if (listSize >= contextMaxThreadCounter)
00153 {
00154 Log2(PCSC_LOG_CRITICAL, "Too many context running: %d", listSize);
00155 goto error;
00156 }
00157
00158
00159 newContext = malloc(sizeof(*newContext));
00160 if (NULL == newContext)
00161 {
00162 Log1(PCSC_LOG_CRITICAL, "Could not allocate new context");
00163 goto error;
00164 }
00165 memset(newContext, 0, sizeof(*newContext));
00166
00167 newContext->dwClientID = *pdwClientID;
00168
00169
00170 lrv = list_init(&(newContext->cardsList));
00171 if (lrv < 0)
00172 {
00173 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
00174 goto error;
00175 }
00176
00177
00178 list_attributes_copy(&(newContext->cardsList), list_meter_int32_t, 1);
00179
00180
00181
00182
00183
00184
00185 lrv = list_attributes_comparator(&(newContext->cardsList), list_comparator_int32_t);
00186 if (lrv != 0)
00187 {
00188 Log2(PCSC_LOG_CRITICAL, "list_attributes_comparator failed with return value: %X", lrv);
00189 list_destroy(&(newContext->cardsList));
00190 goto error;
00191 }
00192
00193 (void)pthread_mutex_init(&newContext->cardsList_lock, NULL);
00194
00195 (void)pthread_mutex_lock(&contextsList_lock);
00196 lrv = list_append(&contextsList, newContext);
00197 (void)pthread_mutex_unlock(&contextsList_lock);
00198 if (lrv < 0)
00199 {
00200 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X", lrv);
00201 list_destroy(&(newContext->cardsList));
00202 goto error;
00203 }
00204
00205 rv = ThreadCreate(&(newContext->pthThread), THREAD_ATTR_DETACHED,
00206 (PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) newContext);
00207 if (rv)
00208 {
00209 int lrv2;
00210
00211 Log2(PCSC_LOG_CRITICAL, "ThreadCreate failed: %s", strerror(rv));
00212 (void)pthread_mutex_lock(&contextsList_lock);
00213 lrv2 = list_delete(&contextsList, newContext);
00214 (void)pthread_mutex_unlock(&contextsList_lock);
00215 if (lrv2 < 0)
00216 Log2(PCSC_LOG_CRITICAL, "list_delete failed with error %X", lrv2);
00217 list_destroy(&(newContext->cardsList));
00218 goto error;
00219 }
00220
00221
00222 if (AutoExit)
00223 alarm(0);
00224
00225 return SCARD_S_SUCCESS;
00226
00227 error:
00228 if (newContext)
00229 free(newContext);
00230 (void)close(*pdwClientID);
00231 return SCARD_E_NO_MEMORY;
00232 }
00233
00234
00235
00236
00237
00238
00247 #ifndef NO_LOG
00248 static const char *CommandsText[] = {
00249 "NULL",
00250 "ESTABLISH_CONTEXT",
00251 "RELEASE_CONTEXT",
00252 "LIST_READERS",
00253 "CONNECT",
00254 "RECONNECT",
00255 "DISCONNECT",
00256 "BEGIN_TRANSACTION",
00257 "END_TRANSACTION",
00258 "TRANSMIT",
00259 "CONTROL",
00260 "STATUS",
00261 "GET_STATUS_CHANGE",
00262 "CANCEL",
00263 "CANCEL_TRANSACTION",
00264 "GET_ATTRIB",
00265 "SET_ATTRIB",
00266 "CMD_VERSION",
00267 "CMD_GET_READERS_STATE",
00268 "CMD_WAIT_READER_STATE_CHANGE",
00269 "CMD_STOP_WAITING_READER_STATE_CHANGE",
00270 "NULL"
00271 };
00272 #endif
00273
00274 #define READ_BODY(v) \
00275 if (header.size != sizeof(v)) { goto wrong_length; } \
00276 ret = MessageReceive(&v, sizeof(v), filedes); \
00277 if (ret < 0) { Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; }
00278
00279 #define WRITE_BODY(v) \
00280 WRITE_BODY_WITH_COMMAND(CommandsText[header.command], v)
00281 #define WRITE_BODY_WITH_COMMAND(command, v) \
00282 Log4(SCARD_S_SUCCESS == v.rv ? PCSC_LOG_DEBUG : PCSC_LOG_ERROR, "%s rv=0x%X for client %d", command, v.rv, filedes); \
00283 ret = MessageSend(&v, sizeof(v), filedes);
00284
00285 static void ContextThread(LPVOID newContext)
00286 {
00287 SCONTEXT * threadContext = (SCONTEXT *) newContext;
00288 int32_t filedes = threadContext->dwClientID;
00289
00290 Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%X",
00291 threadContext->dwClientID, threadContext);
00292
00293 while (1)
00294 {
00295 struct rxHeader header;
00296 int32_t ret = MessageReceive(&header, sizeof(header), filedes);
00297
00298 if (ret < 0)
00299 {
00300
00301 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00302 EHTryToUnregisterClientForEvent(filedes);
00303 goto exit;
00304 }
00305
00306 if ((header.command > CMD_ENUM_FIRST)
00307 && (header.command < CMD_ENUM_LAST))
00308 Log3(PCSC_LOG_DEBUG, "Received command: %s from client %d",
00309 CommandsText[header.command], filedes);
00310
00311 switch (header.command)
00312 {
00313
00314 case CMD_VERSION:
00315 {
00316 struct version_struct veStr;
00317
00318 READ_BODY(veStr)
00319
00320
00321 threadContext->protocol_major = veStr.major;
00322 threadContext->protocol_minor = veStr.minor;
00323
00324 Log3(PCSC_LOG_DEBUG,
00325 "Client is protocol version %d:%d",
00326 veStr.major, veStr.minor);
00327
00328 veStr.rv = SCARD_S_SUCCESS;
00329
00330
00331 if ((veStr.major > PROTOCOL_VERSION_MAJOR)
00332 || (veStr.major == PROTOCOL_VERSION_MAJOR
00333 && veStr.minor > PROTOCOL_VERSION_MINOR))
00334 {
00335 Log3(PCSC_LOG_CRITICAL,
00336 "Client protocol is too new %d:%d",
00337 veStr.major, veStr.minor);
00338 Log3(PCSC_LOG_CRITICAL,
00339 "Server protocol is %d:%d",
00340 PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
00341 veStr.rv = SCARD_E_NO_SERVICE;
00342 }
00343
00344
00345 veStr.major = PROTOCOL_VERSION_MAJOR;
00346 veStr.minor = PROTOCOL_VERSION_MINOR;
00347
00348
00349 WRITE_BODY(veStr)
00350 }
00351 break;
00352
00353 case CMD_GET_READERS_STATE:
00354 {
00355
00356
00357
00358 ret = MessageSend(readerStates, sizeof(readerStates), filedes);
00359 }
00360 break;
00361
00362 case CMD_WAIT_READER_STATE_CHANGE:
00363 {
00364 struct wait_reader_state_change waStr;
00365
00366 READ_BODY(waStr)
00367
00368
00369 EHRegisterClientForEvent(filedes);
00370
00371
00372
00373
00374 }
00375 break;
00376
00377 case CMD_STOP_WAITING_READER_STATE_CHANGE:
00378 {
00379 struct wait_reader_state_change waStr;
00380
00381 READ_BODY(waStr)
00382
00383
00384 waStr.rv = EHUnregisterClientForEvent(filedes);
00385
00386 WRITE_BODY(waStr)
00387 }
00388 break;
00389
00390 case SCARD_ESTABLISH_CONTEXT:
00391 {
00392 struct establish_struct esStr;
00393 SCARDCONTEXT hContext;
00394
00395 READ_BODY(esStr)
00396
00397 hContext = esStr.hContext;
00398 esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0, &hContext);
00399 esStr.hContext = hContext;
00400
00401 if (esStr.rv == SCARD_S_SUCCESS)
00402 esStr.rv =
00403 MSGAddContext(esStr.hContext, threadContext);
00404
00405 WRITE_BODY(esStr)
00406 }
00407 break;
00408
00409 case SCARD_RELEASE_CONTEXT:
00410 {
00411 struct release_struct reStr;
00412
00413 READ_BODY(reStr)
00414
00415 reStr.rv = SCardReleaseContext(reStr.hContext);
00416
00417 if (reStr.rv == SCARD_S_SUCCESS)
00418 reStr.rv =
00419 MSGRemoveContext(reStr.hContext, threadContext);
00420
00421 WRITE_BODY(reStr)
00422 }
00423 break;
00424
00425 case SCARD_CONNECT:
00426 {
00427 struct connect_struct coStr;
00428 SCARDHANDLE hCard;
00429 DWORD dwActiveProtocol;
00430
00431 READ_BODY(coStr)
00432
00433 hCard = coStr.hCard;
00434 dwActiveProtocol = coStr.dwActiveProtocol;
00435
00436 coStr.rv = SCardConnect(coStr.hContext, coStr.szReader,
00437 coStr.dwShareMode, coStr.dwPreferredProtocols,
00438 &hCard, &dwActiveProtocol);
00439
00440 coStr.hCard = hCard;
00441 coStr.dwActiveProtocol = dwActiveProtocol;
00442
00443 if (coStr.rv == SCARD_S_SUCCESS)
00444 coStr.rv =
00445 MSGAddHandle(coStr.hContext, coStr.hCard, threadContext);
00446
00447 WRITE_BODY(coStr)
00448 }
00449 break;
00450
00451 case SCARD_RECONNECT:
00452 {
00453 struct reconnect_struct rcStr;
00454 DWORD dwActiveProtocol;
00455
00456 READ_BODY(rcStr)
00457
00458 if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
00459 goto exit;
00460
00461 rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
00462 rcStr.dwPreferredProtocols,
00463 rcStr.dwInitialization, &dwActiveProtocol);
00464 rcStr.dwActiveProtocol = dwActiveProtocol;
00465
00466 WRITE_BODY(rcStr)
00467 }
00468 break;
00469
00470 case SCARD_DISCONNECT:
00471 {
00472 struct disconnect_struct diStr;
00473
00474 READ_BODY(diStr)
00475
00476 if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
00477 goto exit;
00478
00479 diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);
00480
00481 if (SCARD_S_SUCCESS == diStr.rv)
00482 diStr.rv =
00483 MSGRemoveHandle(diStr.hCard, threadContext);
00484
00485 WRITE_BODY(diStr)
00486 }
00487 break;
00488
00489 case SCARD_BEGIN_TRANSACTION:
00490 {
00491 struct begin_struct beStr;
00492
00493 READ_BODY(beStr)
00494
00495 if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
00496 goto exit;
00497
00498 beStr.rv = SCardBeginTransaction(beStr.hCard);
00499
00500 WRITE_BODY(beStr)
00501 }
00502 break;
00503
00504 case SCARD_END_TRANSACTION:
00505 {
00506 struct end_struct enStr;
00507
00508 READ_BODY(enStr)
00509
00510 if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
00511 goto exit;
00512
00513 enStr.rv = SCardEndTransaction(enStr.hCard, enStr.dwDisposition);
00514
00515 WRITE_BODY(enStr)
00516 }
00517 break;
00518
00519 case SCARD_CANCEL_TRANSACTION:
00520 {
00521 struct cancel_transaction_struct caStr;
00522
00523 READ_BODY(caStr)
00524
00525 if (MSGCheckHandleAssociation(caStr.hCard, threadContext))
00526 goto exit;
00527
00528 caStr.rv = SCardCancelTransaction(caStr.hCard);
00529
00530 WRITE_BODY(caStr)
00531 }
00532 break;
00533
00534 case SCARD_CANCEL:
00535 {
00536 struct cancel_struct caStr;
00537 SCONTEXT * psTargetContext = NULL;
00538 READ_BODY(caStr)
00539
00540
00541 (void)pthread_mutex_lock(&contextsList_lock);
00542 psTargetContext = (SCONTEXT *) list_seek(&contextsList,
00543 &(caStr.hContext));
00544 (void)pthread_mutex_unlock(&contextsList_lock);
00545 if (psTargetContext != NULL)
00546 {
00547 uint32_t fd = psTargetContext->dwClientID;
00548 caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);
00549 }
00550 else
00551 caStr.rv = SCARD_E_INVALID_HANDLE;
00552
00553 WRITE_BODY(caStr)
00554 }
00555 break;
00556
00557 case SCARD_STATUS:
00558 {
00559 struct status_struct stStr;
00560 DWORD cchReaderLen;
00561 DWORD dwState;
00562 DWORD dwProtocol;
00563 DWORD cbAtrLen;
00564
00565 READ_BODY(stStr)
00566
00567 if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
00568 goto exit;
00569
00570 cchReaderLen = stStr.pcchReaderLen;
00571 dwState = stStr.dwState;
00572 dwProtocol = stStr.dwProtocol;
00573 cbAtrLen = stStr.pcbAtrLen;
00574
00575
00576 if ((cchReaderLen > sizeof(stStr.mszReaderNames))
00577 || (cbAtrLen > sizeof(stStr.pbAtr)))
00578 {
00579 stStr.rv = SCARD_E_INSUFFICIENT_BUFFER ;
00580 }
00581 else
00582 {
00583 stStr.rv = SCardStatus(stStr.hCard,
00584 stStr.mszReaderNames, &cchReaderLen, &dwState,
00585 &dwProtocol, stStr.pbAtr, &cbAtrLen);
00586
00587 stStr.pcchReaderLen = cchReaderLen;
00588 stStr.dwState = dwState;
00589 stStr.dwProtocol = dwProtocol;
00590 stStr.pcbAtrLen = cbAtrLen;
00591 }
00592
00593 WRITE_BODY(stStr)
00594 }
00595 break;
00596
00597 case SCARD_TRANSMIT:
00598 {
00599 struct transmit_struct trStr;
00600 unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00601 unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00602 SCARD_IO_REQUEST ioSendPci;
00603 SCARD_IO_REQUEST ioRecvPci;
00604 DWORD cbRecvLength;
00605
00606 READ_BODY(trStr)
00607
00608 if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
00609 goto exit;
00610
00611
00612 if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
00613 || (trStr.cbSendLength > sizeof(pbSendBuffer)))
00614 goto buffer_overflow;
00615
00616
00617 ret = MessageReceive(pbSendBuffer, trStr.cbSendLength, filedes);
00618 if (ret < 0)
00619 {
00620 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00621 goto exit;
00622 }
00623
00624 ioSendPci.dwProtocol = trStr.ioSendPciProtocol;
00625 ioSendPci.cbPciLength = trStr.ioSendPciLength;
00626 ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol;
00627 ioRecvPci.cbPciLength = trStr.ioRecvPciLength;
00628 cbRecvLength = trStr.pcbRecvLength;
00629
00630 trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
00631 pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
00632 pbRecvBuffer, &cbRecvLength);
00633
00634 trStr.ioSendPciProtocol = ioSendPci.dwProtocol;
00635 trStr.ioSendPciLength = ioSendPci.cbPciLength;
00636 trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol;
00637 trStr.ioRecvPciLength = ioRecvPci.cbPciLength;
00638 trStr.pcbRecvLength = cbRecvLength;
00639
00640 WRITE_BODY(trStr)
00641
00642
00643 if (SCARD_S_SUCCESS == trStr.rv)
00644 ret = MessageSend(pbRecvBuffer, cbRecvLength, filedes);
00645 }
00646 break;
00647
00648 case SCARD_CONTROL:
00649 {
00650 struct control_struct ctStr;
00651 unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00652 unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00653 DWORD dwBytesReturned;
00654
00655 READ_BODY(ctStr)
00656
00657 if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
00658 goto exit;
00659
00660
00661 if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
00662 || (ctStr.cbSendLength > sizeof(pbSendBuffer)))
00663 {
00664 goto buffer_overflow;
00665 }
00666
00667
00668 ret = MessageReceive(pbSendBuffer, ctStr.cbSendLength, filedes);
00669 if (ret < 0)
00670 {
00671 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00672 goto exit;
00673 }
00674
00675 dwBytesReturned = ctStr.dwBytesReturned;
00676
00677 ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
00678 pbSendBuffer, ctStr.cbSendLength,
00679 pbRecvBuffer, ctStr.cbRecvLength,
00680 &dwBytesReturned);
00681
00682 ctStr.dwBytesReturned = dwBytesReturned;
00683
00684 WRITE_BODY(ctStr)
00685
00686
00687 if (SCARD_S_SUCCESS == ctStr.rv)
00688 ret = MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
00689 }
00690 break;
00691
00692 case SCARD_GET_ATTRIB:
00693 {
00694 struct getset_struct gsStr;
00695 DWORD cbAttrLen;
00696
00697 READ_BODY(gsStr)
00698
00699 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
00700 goto exit;
00701
00702
00703 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
00704 goto buffer_overflow;
00705
00706 cbAttrLen = gsStr.cbAttrLen;
00707
00708 gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
00709 gsStr.pbAttr, &cbAttrLen);
00710
00711 gsStr.cbAttrLen = cbAttrLen;
00712
00713 WRITE_BODY(gsStr)
00714 }
00715 break;
00716
00717 case SCARD_SET_ATTRIB:
00718 {
00719 struct getset_struct gsStr;
00720
00721 READ_BODY(gsStr)
00722
00723 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
00724 goto exit;
00725
00726
00727 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
00728 goto buffer_overflow;
00729
00730 gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
00731 gsStr.pbAttr, gsStr.cbAttrLen);
00732
00733 WRITE_BODY(gsStr)
00734 }
00735 break;
00736
00737 default:
00738 Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
00739 goto exit;
00740 }
00741
00742
00743 if (-1 == ret)
00744 {
00745
00746 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00747 goto exit;
00748 }
00749 }
00750
00751 buffer_overflow:
00752 Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes);
00753 goto exit;
00754 wrong_length:
00755 Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
00756 exit:
00757 (void)close(filedes);
00758 (void)MSGCleanupClient(threadContext);
00759 (void)pthread_exit((LPVOID) NULL);
00760 }
00761
00762 LONG MSGSignalClient(uint32_t filedes, LONG rv)
00763 {
00764 uint32_t ret;
00765 struct wait_reader_state_change waStr;
00766
00767 Log2(PCSC_LOG_DEBUG, "Signal client: %d", filedes);
00768
00769 waStr.rv = rv;
00770 WRITE_BODY_WITH_COMMAND("SIGNAL", waStr)
00771
00772 return ret;
00773 }
00774
00775 static LONG MSGAddContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
00776 {
00777 threadContext->hContext = hContext;
00778 return SCARD_S_SUCCESS;
00779 }
00780
00781 static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
00782 {
00783 LONG rv;
00784 int lrv;
00785
00786 if (threadContext->hContext != hContext)
00787 return SCARD_E_INVALID_VALUE;
00788
00789 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00790 while (list_size(&(threadContext->cardsList)) != 0)
00791 {
00792 READER_CONTEXT * rContext = NULL;
00793 SCARDHANDLE hCard, hLockId;
00794 void *ptr;
00795
00796
00797
00798
00799 ptr = list_get_at(&(threadContext->cardsList), 0);
00800 if (NULL == ptr)
00801 {
00802 Log1(PCSC_LOG_CRITICAL, "list_get_at failed");
00803 continue;
00804 }
00805 hCard = *(int32_t *)ptr;
00806
00807
00808
00809
00810 rv = RFReaderInfoById(hCard, &rContext);
00811 if (rv != SCARD_S_SUCCESS)
00812 {
00813 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00814 return rv;
00815 }
00816
00817 hLockId = rContext->hLockId;
00818 rContext->hLockId = 0;
00819
00820 if (hCard != hLockId)
00821 {
00822
00823
00824
00825
00826 rv = SCARD_W_REMOVED_CARD;
00827 }
00828 else
00829 {
00830
00831
00832
00833
00834
00835 rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
00836 }
00837
00838 if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
00839 (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
00840 else
00841 (void)SCardDisconnect(hCard, SCARD_RESET_CARD);
00842
00843
00844 lrv = list_delete_at(&(threadContext->cardsList), 0);
00845 if (lrv < 0)
00846 Log2(PCSC_LOG_CRITICAL,
00847 "list_delete_at failed with return value: %X", lrv);
00848 }
00849 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00850 list_destroy(&(threadContext->cardsList));
00851
00852
00853
00854 threadContext->hContext = 0;
00855
00856 return SCARD_S_SUCCESS;
00857 }
00858
00859 static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
00860 SCONTEXT * threadContext)
00861 {
00862 if (threadContext->hContext == hContext)
00863 {
00864
00865
00866
00867 int listLength, lrv;
00868
00869 listLength = list_size(&(threadContext->cardsList));
00870 if (listLength >= contextMaxCardHandles)
00871 {
00872 Log4(PCSC_LOG_DEBUG, "Too many card handles for thread context @%X: %d (max is %d)"
00873 "Restart pcscd with --max-card-handle-per-thread value",
00874 threadContext, listLength, contextMaxCardHandles);
00875 return SCARD_E_NO_MEMORY;
00876 }
00877
00878 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00879 lrv = list_append(&(threadContext->cardsList), &hCard);
00880 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00881 if (lrv < 0)
00882 {
00883 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
00884 lrv);
00885 return SCARD_E_NO_MEMORY;
00886 }
00887 return SCARD_S_SUCCESS;
00888 }
00889
00890 return SCARD_E_INVALID_VALUE;
00891 }
00892
00893 static LONG MSGRemoveHandle(SCARDHANDLE hCard, SCONTEXT * threadContext)
00894 {
00895 int lrv;
00896
00897 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00898 lrv = list_delete(&(threadContext->cardsList), &hCard);
00899 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00900 if (lrv < 0)
00901 {
00902 Log2(PCSC_LOG_CRITICAL, "list_delete failed with error %X", lrv);
00903 return SCARD_E_INVALID_VALUE;
00904 }
00905
00906 return SCARD_S_SUCCESS;
00907 }
00908
00909
00910 static LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, SCONTEXT * threadContext)
00911 {
00912 int list_index = 0;
00913
00914 if (0 == threadContext->hContext)
00915 {
00916
00917
00918 Log1(PCSC_LOG_CRITICAL, "Invalidated handle");
00919 return -1;
00920 }
00921
00922 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00923 list_index = list_locate(&(threadContext->cardsList), &hCard);
00924 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00925 if (list_index >= 0)
00926 return 0;
00927
00928
00929 Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
00930 (void)SYS_Sleep(2);
00931
00932 return -1;
00933 }
00934
00935
00936
00937
00938
00939 static LONG MSGCleanupClient(SCONTEXT * threadContext)
00940 {
00941 int lrv;
00942 int listSize;
00943
00944 if (threadContext->hContext != 0)
00945 {
00946 (void)SCardReleaseContext(threadContext->hContext);
00947 (void)MSGRemoveContext(threadContext->hContext, threadContext);
00948 }
00949
00950 Log3(PCSC_LOG_DEBUG,
00951 "Thread is stopping: dwClientID=%d, threadContext @%X",
00952 threadContext->dwClientID, threadContext);
00953
00954
00955
00956
00957 memset((void*) threadContext, 0, sizeof(SCONTEXT));
00958 Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXT @%X", threadContext);
00959
00960 (void)pthread_mutex_lock(&contextsList_lock);
00961 lrv = list_delete(&contextsList, threadContext);
00962 listSize = list_size(&contextsList);
00963 (void)pthread_mutex_unlock(&contextsList_lock);
00964 if (lrv < 0)
00965 Log2(PCSC_LOG_CRITICAL, "list_delete failed with error %x", lrv);
00966
00967 free(threadContext);
00968
00969
00970 if (AutoExit && (listSize < 1))
00971 {
00972 Log2(PCSC_LOG_DEBUG, "Starting suicide alarm in %d seconds",
00973 TIME_BEFORE_SUICIDE);
00974 alarm(TIME_BEFORE_SUICIDE);
00975 }
00976
00977 return 0;
00978 }