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 LONG rv;
00474
00475 READ_BODY(diStr)
00476
00477 rv = MSGCheckHandleAssociation(diStr.hCard, threadContext);
00478 if (0 == rv)
00479 {
00480 diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);
00481
00482 if (SCARD_S_SUCCESS == diStr.rv)
00483 diStr.rv =
00484 MSGRemoveHandle(diStr.hCard, threadContext);
00485 }
00486
00487 WRITE_BODY(diStr)
00488 }
00489 break;
00490
00491 case SCARD_BEGIN_TRANSACTION:
00492 {
00493 struct begin_struct beStr;
00494 LONG rv;
00495
00496 READ_BODY(beStr)
00497
00498 rv = MSGCheckHandleAssociation(beStr.hCard, threadContext);
00499 if (0 == rv)
00500 beStr.rv = SCardBeginTransaction(beStr.hCard);
00501
00502 WRITE_BODY(beStr)
00503 }
00504 break;
00505
00506 case SCARD_END_TRANSACTION:
00507 {
00508 struct end_struct enStr;
00509 LONG rv;
00510
00511 READ_BODY(enStr)
00512
00513 rv = MSGCheckHandleAssociation(enStr.hCard, threadContext);
00514 if (0 == rv)
00515 enStr.rv =
00516 SCardEndTransaction(enStr.hCard, enStr.dwDisposition);
00517
00518 WRITE_BODY(enStr)
00519 }
00520 break;
00521
00522 case SCARD_CANCEL_TRANSACTION:
00523 {
00524 struct cancel_transaction_struct caStr;
00525 LONG rv;
00526
00527 READ_BODY(caStr)
00528
00529 rv = MSGCheckHandleAssociation(caStr.hCard, threadContext);
00530 if (0 == rv)
00531 caStr.rv = SCardCancelTransaction(caStr.hCard);
00532
00533 WRITE_BODY(caStr)
00534 }
00535 break;
00536
00537 case SCARD_CANCEL:
00538 {
00539 struct cancel_struct caStr;
00540 SCONTEXT * psTargetContext = NULL;
00541 READ_BODY(caStr)
00542
00543
00544 (void)pthread_mutex_lock(&contextsList_lock);
00545 psTargetContext = (SCONTEXT *) list_seek(&contextsList,
00546 &(caStr.hContext));
00547 (void)pthread_mutex_unlock(&contextsList_lock);
00548 if (psTargetContext != NULL)
00549 {
00550 uint32_t fd = psTargetContext->dwClientID;
00551 caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);
00552 }
00553 else
00554 caStr.rv = SCARD_E_INVALID_HANDLE;
00555
00556 WRITE_BODY(caStr)
00557 }
00558 break;
00559
00560 case SCARD_STATUS:
00561 {
00562 struct status_struct stStr;
00563 LONG rv;
00564
00565 READ_BODY(stStr)
00566
00567 rv = MSGCheckHandleAssociation(stStr.hCard, threadContext);
00568 if (0 == rv)
00569 {
00570 DWORD cchReaderLen;
00571 DWORD dwState;
00572 DWORD dwProtocol;
00573 DWORD cbAtrLen;
00574
00575 cchReaderLen = stStr.pcchReaderLen;
00576 dwState = stStr.dwState;
00577 dwProtocol = stStr.dwProtocol;
00578 cbAtrLen = stStr.pcbAtrLen;
00579
00580
00581 if ((cchReaderLen > sizeof(stStr.mszReaderNames))
00582 || (cbAtrLen > sizeof(stStr.pbAtr)))
00583 {
00584 stStr.rv = SCARD_E_INSUFFICIENT_BUFFER ;
00585 }
00586 else
00587 {
00588 stStr.rv = SCardStatus(stStr.hCard,
00589 stStr.mszReaderNames,
00590 &cchReaderLen, &dwState,
00591 &dwProtocol, stStr.pbAtr, &cbAtrLen);
00592
00593 stStr.pcchReaderLen = cchReaderLen;
00594 stStr.dwState = dwState;
00595 stStr.dwProtocol = dwProtocol;
00596 stStr.pcbAtrLen = cbAtrLen;
00597 }
00598 }
00599
00600 WRITE_BODY(stStr)
00601 }
00602 break;
00603
00604 case SCARD_TRANSMIT:
00605 {
00606 struct transmit_struct trStr;
00607 unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00608 unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00609 SCARD_IO_REQUEST ioSendPci;
00610 SCARD_IO_REQUEST ioRecvPci;
00611 DWORD cbRecvLength;
00612
00613 READ_BODY(trStr)
00614
00615 if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
00616 goto exit;
00617
00618
00619 if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
00620 || (trStr.cbSendLength > sizeof(pbSendBuffer)))
00621 goto exit;
00622
00623
00624 ret = MessageReceive(pbSendBuffer, trStr.cbSendLength, filedes);
00625 if (ret < 0)
00626 {
00627 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00628 goto exit;
00629 }
00630
00631 ioSendPci.dwProtocol = trStr.ioSendPciProtocol;
00632 ioSendPci.cbPciLength = trStr.ioSendPciLength;
00633 ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol;
00634 ioRecvPci.cbPciLength = trStr.ioRecvPciLength;
00635 cbRecvLength = trStr.pcbRecvLength;
00636
00637 trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
00638 pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
00639 pbRecvBuffer, &cbRecvLength);
00640
00641 trStr.ioSendPciProtocol = ioSendPci.dwProtocol;
00642 trStr.ioSendPciLength = ioSendPci.cbPciLength;
00643 trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol;
00644 trStr.ioRecvPciLength = ioRecvPci.cbPciLength;
00645 trStr.pcbRecvLength = cbRecvLength;
00646
00647 WRITE_BODY(trStr)
00648
00649
00650 if (SCARD_S_SUCCESS == trStr.rv)
00651 ret = MessageSend(pbRecvBuffer, cbRecvLength, filedes);
00652 }
00653 break;
00654
00655 case SCARD_CONTROL:
00656 {
00657 struct control_struct ctStr;
00658 unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
00659 unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
00660 DWORD dwBytesReturned;
00661
00662 READ_BODY(ctStr)
00663
00664 if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
00665 goto exit;
00666
00667
00668 if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
00669 || (ctStr.cbSendLength > sizeof(pbSendBuffer)))
00670 {
00671 goto exit;
00672 }
00673
00674
00675 ret = MessageReceive(pbSendBuffer, ctStr.cbSendLength, filedes);
00676 if (ret < 0)
00677 {
00678 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00679 goto exit;
00680 }
00681
00682 dwBytesReturned = ctStr.dwBytesReturned;
00683
00684 ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
00685 pbSendBuffer, ctStr.cbSendLength,
00686 pbRecvBuffer, ctStr.cbRecvLength,
00687 &dwBytesReturned);
00688
00689 ctStr.dwBytesReturned = dwBytesReturned;
00690
00691 WRITE_BODY(ctStr)
00692
00693
00694 if (SCARD_S_SUCCESS == ctStr.rv)
00695 ret = MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
00696 }
00697 break;
00698
00699 case SCARD_GET_ATTRIB:
00700 {
00701 struct getset_struct gsStr;
00702 DWORD cbAttrLen;
00703
00704 READ_BODY(gsStr)
00705
00706 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
00707 goto exit;
00708
00709
00710 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
00711 goto buffer_overflow;
00712
00713 cbAttrLen = gsStr.cbAttrLen;
00714
00715 gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
00716 gsStr.pbAttr, &cbAttrLen);
00717
00718 gsStr.cbAttrLen = cbAttrLen;
00719
00720 WRITE_BODY(gsStr)
00721 }
00722 break;
00723
00724 case SCARD_SET_ATTRIB:
00725 {
00726 struct getset_struct gsStr;
00727
00728 READ_BODY(gsStr)
00729
00730 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
00731 goto buffer_overflow;
00732
00733
00734 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
00735 goto buffer_overflow;
00736
00737 gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
00738 gsStr.pbAttr, gsStr.cbAttrLen);
00739
00740 WRITE_BODY(gsStr)
00741 }
00742 break;
00743
00744 default:
00745 Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
00746 goto exit;
00747 }
00748
00749
00750 if (-1 == ret)
00751 {
00752
00753 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
00754 goto exit;
00755 }
00756 }
00757
00758 buffer_overflow:
00759 Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes);
00760 goto exit;
00761 wrong_length:
00762 Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
00763 exit:
00764 (void)close(filedes);
00765 (void)MSGCleanupClient(threadContext);
00766 (void)pthread_exit((LPVOID) NULL);
00767 }
00768
00769 LONG MSGSignalClient(uint32_t filedes, LONG rv)
00770 {
00771 uint32_t ret;
00772 struct wait_reader_state_change waStr;
00773
00774 Log2(PCSC_LOG_DEBUG, "Signal client: %d", filedes);
00775
00776 waStr.rv = rv;
00777 WRITE_BODY_WITH_COMMAND("SIGNAL", waStr)
00778
00779 return ret;
00780 }
00781
00782 static LONG MSGAddContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
00783 {
00784 threadContext->hContext = hContext;
00785 return SCARD_S_SUCCESS;
00786 }
00787
00788 static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
00789 {
00790 LONG rv;
00791 int lrv;
00792
00793 if (threadContext->hContext != hContext)
00794 return SCARD_E_INVALID_VALUE;
00795
00796 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00797 while (list_size(&(threadContext->cardsList)) != 0)
00798 {
00799 READER_CONTEXT * rContext = NULL;
00800 SCARDHANDLE hCard, hLockId;
00801 void *ptr;
00802
00803
00804
00805
00806 ptr = list_get_at(&(threadContext->cardsList), 0);
00807 if (NULL == ptr)
00808 {
00809 Log1(PCSC_LOG_CRITICAL, "list_get_at failed");
00810 continue;
00811 }
00812 hCard = *(int32_t *)ptr;
00813
00814
00815
00816
00817 rv = RFReaderInfoById(hCard, &rContext);
00818 if (rv != SCARD_S_SUCCESS)
00819 {
00820 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00821 return rv;
00822 }
00823
00824 hLockId = rContext->hLockId;
00825 rContext->hLockId = 0;
00826
00827 if (hCard != hLockId)
00828 {
00829
00830
00831
00832
00833 rv = SCARD_W_REMOVED_CARD;
00834 }
00835 else
00836 {
00837
00838
00839
00840
00841
00842 rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
00843 }
00844
00845 if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
00846 (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
00847 else
00848 (void)SCardDisconnect(hCard, SCARD_RESET_CARD);
00849
00850
00851 lrv = list_delete_at(&(threadContext->cardsList), 0);
00852 if (lrv < 0)
00853 Log2(PCSC_LOG_CRITICAL,
00854 "list_delete_at failed with return value: %X", lrv);
00855 }
00856 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00857 list_destroy(&(threadContext->cardsList));
00858
00859
00860
00861 threadContext->hContext = 0;
00862
00863 return SCARD_S_SUCCESS;
00864 }
00865
00866 static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
00867 SCONTEXT * threadContext)
00868 {
00869 if (threadContext->hContext == hContext)
00870 {
00871
00872
00873
00874 int listLength, lrv;
00875
00876 listLength = list_size(&(threadContext->cardsList));
00877 if (listLength >= contextMaxCardHandles)
00878 {
00879 Log4(PCSC_LOG_DEBUG, "Too many card handles for thread context @%X: %d (max is %d)"
00880 "Restart pcscd with --max-card-handle-per-thread value",
00881 threadContext, listLength, contextMaxCardHandles);
00882 return SCARD_E_NO_MEMORY;
00883 }
00884
00885 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00886 lrv = list_append(&(threadContext->cardsList), &hCard);
00887 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00888 if (lrv < 0)
00889 {
00890 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
00891 lrv);
00892 return SCARD_E_NO_MEMORY;
00893 }
00894 return SCARD_S_SUCCESS;
00895 }
00896
00897 return SCARD_E_INVALID_VALUE;
00898 }
00899
00900 static LONG MSGRemoveHandle(SCARDHANDLE hCard, SCONTEXT * threadContext)
00901 {
00902 int lrv;
00903
00904 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00905 lrv = list_delete(&(threadContext->cardsList), &hCard);
00906 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00907 if (lrv < 0)
00908 {
00909 Log2(PCSC_LOG_CRITICAL, "list_delete failed with error %X", lrv);
00910 return SCARD_E_INVALID_VALUE;
00911 }
00912
00913 return SCARD_S_SUCCESS;
00914 }
00915
00916
00917 static LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, SCONTEXT * threadContext)
00918 {
00919 int list_index = 0;
00920 (void)pthread_mutex_lock(&threadContext->cardsList_lock);
00921 list_index = list_locate(&(threadContext->cardsList), &hCard);
00922 (void)pthread_mutex_unlock(&threadContext->cardsList_lock);
00923 if (list_index >= 0)
00924 return 0;
00925
00926
00927 Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
00928 (void)SYS_Sleep(2);
00929
00930 return -1;
00931 }
00932
00933
00934
00935
00936
00937 static LONG MSGCleanupClient(SCONTEXT * threadContext)
00938 {
00939 int lrv;
00940 int listSize;
00941
00942 if (threadContext->hContext != 0)
00943 {
00944 (void)SCardReleaseContext(threadContext->hContext);
00945 (void)MSGRemoveContext(threadContext->hContext, threadContext);
00946 }
00947
00948 Log3(PCSC_LOG_DEBUG,
00949 "Thread is stopping: dwClientID=%d, threadContext @%X",
00950 threadContext->dwClientID, threadContext);
00951
00952
00953
00954
00955 memset((void*) threadContext, 0, sizeof(SCONTEXT));
00956 Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXT @%X", threadContext);
00957
00958 (void)pthread_mutex_lock(&contextsList_lock);
00959 lrv = list_delete(&contextsList, threadContext);
00960 listSize = list_size(&contextsList);
00961 (void)pthread_mutex_unlock(&contextsList_lock);
00962 if (lrv < 0)
00963 Log2(PCSC_LOG_CRITICAL, "list_delete failed with error %x", lrv);
00964
00965 free(threadContext);
00966
00967
00968 if (AutoExit && (listSize < 1))
00969 {
00970 Log2(PCSC_LOG_DEBUG, "Starting suicide alarm in %d seconds",
00971 TIME_BEFORE_SUICIDE);
00972 alarm(TIME_BEFORE_SUICIDE);
00973 }
00974
00975 return 0;
00976 }