53 static int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
54 static int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
74 static LONG MSGCleanupClient(
SCONTEXT *);
76 static void ContextThread(LPVOID pdwIndex);
80 static int contextsListhContext_seeker(
const void *el,
const void *key)
84 if ((el == NULL) || (key == NULL))
86 Log3(PCSC_LOG_CRITICAL,
"called with NULL pointer: el=%p, key=%p",
91 if (currentContext->hContext == *(int32_t *)key)
96 LONG ContextsInitialize(
int customMaxThreadCounter,
97 int customMaxThreadCardHandles)
101 if (customMaxThreadCounter != 0)
102 contextMaxThreadCounter = customMaxThreadCounter;
104 if (customMaxThreadCardHandles != 0)
105 contextMaxCardHandles = customMaxThreadCardHandles;
107 lrv = list_init(&contextsList);
110 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
113 lrv = list_attributes_seeker(& contextsList, contextsListhContext_seeker);
116 Log2(PCSC_LOG_CRITICAL,
117 "list_attributes_seeker failed with return value: %d", lrv);
126 void ContextsDeinitialize(
void)
129 listSize = list_size(&contextsList);
130 Log2(PCSC_LOG_DEBUG,
"remaining threads: %d", listSize);
152 listSize = list_size(&contextsList);
155 if (listSize >= contextMaxThreadCounter)
157 Log2(PCSC_LOG_CRITICAL,
"Too many context running: %d", listSize);
162 newContext = malloc(
sizeof(*newContext));
163 if (NULL == newContext)
165 Log1(PCSC_LOG_CRITICAL,
"Could not allocate new context");
168 memset(newContext, 0,
sizeof(*newContext));
173 lrv = list_init(&(newContext->cardsList));
176 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
181 list_attributes_copy(&(newContext->cardsList), list_meter_int32_t, 1);
188 lrv = list_attributes_comparator(&(newContext->cardsList),
189 list_comparator_int32_t);
192 Log2(PCSC_LOG_CRITICAL,
193 "list_attributes_comparator failed with return value: %d", lrv);
194 list_destroy(&(newContext->cardsList));
201 lrv = list_append(&contextsList, newContext);
205 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
207 list_destroy(&(newContext->cardsList));
211 rv = ThreadCreate(&(newContext->
pthThread), THREAD_ATTR_DETACHED,
212 (PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) newContext);
217 Log2(PCSC_LOG_CRITICAL,
"ThreadCreate failed: %s", strerror(rv));
219 lrv2 = list_delete(&contextsList, newContext);
222 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv2);
223 list_destroy(&(newContext->cardsList));
236 (void)close(*pdwClientID);
269 "CANCEL_TRANSACTION",
273 "CMD_GET_READERS_STATE",
274 "CMD_WAIT_READER_STATE_CHANGE",
275 "CMD_STOP_WAITING_READER_STATE_CHANGE",
280 #define READ_BODY(v) \
281 if (header.size != sizeof(v)) { goto wrong_length; } \
282 ret = MessageReceive(&v, sizeof(v), filedes); \
283 if (ret != SCARD_S_SUCCESS) { Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; }
285 #define WRITE_BODY(v) \
286 WRITE_BODY_WITH_COMMAND(CommandsText[header.command], v)
287 #define WRITE_BODY_WITH_COMMAND(command, v) \
288 Log4(PCSC_LOG_DEBUG, "%s rv=0x%X for client %d", command, v.rv, filedes); \
289 ret = MessageSend(&v, sizeof(v), filedes);
291 static void ContextThread(LPVOID newContext)
296 Log3(PCSC_LOG_DEBUG,
"Thread is started: dwClientID=%d, threadContext @%p",
307 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
312 if ((header.command > CMD_ENUM_FIRST)
313 && (header.command < CMD_ENUM_LAST))
314 Log3(PCSC_LOG_DEBUG,
"Received command: %s from client %d",
315 CommandsText[header.command], filedes);
317 switch (header.command)
326 Log3(PCSC_LOG_DEBUG, "Client is protocol version %d:%d",
335 Log3(PCSC_LOG_CRITICAL,
"Client protocol is %d:%d",
336 veStr.major, veStr.minor);
337 Log3(PCSC_LOG_CRITICAL,
"Server protocol is %d:%d",
357 RFWaitForReaderInit();
361 ret =
MessageSend(readerStates,
sizeof(readerStates), filedes);
372 EHRegisterClientForEvent(filedes);
400 hContext = esStr.hContext;
403 esStr.hContext = hContext;
406 esStr.rv = MSGAddContext(esStr.hContext, threadContext);
421 reStr.rv = MSGRemoveContext(reStr.hContext, threadContext);
431 DWORD dwActiveProtocol;
436 dwActiveProtocol = coStr.dwActiveProtocol;
439 coStr.dwShareMode, coStr.dwPreferredProtocols,
440 &hCard, &dwActiveProtocol);
443 coStr.dwActiveProtocol = dwActiveProtocol;
446 coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
456 DWORD dwActiveProtocol;
460 if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
464 rcStr.dwPreferredProtocols, rcStr.dwInitialization,
466 rcStr.dwActiveProtocol = dwActiveProtocol;
478 if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
484 diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext);
496 if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
511 if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
515 enStr.dwDisposition);
529 psTargetContext = (
SCONTEXT *) list_seek(&contextsList,
532 if (psTargetContext != NULL)
534 uint32_t fd = psTargetContext->dwClientID;
550 if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
554 stStr.rv =
SCardStatus(stStr.hCard, NULL, NULL, NULL,
572 if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
576 if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
577 || (trStr.cbSendLength > sizeof(pbSendBuffer)))
578 goto buffer_overflow;
584 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
588 ioSendPci.
dwProtocol = trStr.ioSendPciProtocol;
590 ioRecvPci.
dwProtocol = trStr.ioRecvPciProtocol;
592 cbRecvLength = trStr.pcbRecvLength;
595 pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
596 pbRecvBuffer, &cbRecvLength);
598 trStr.ioSendPciProtocol = ioSendPci.
dwProtocol;
600 trStr.ioRecvPciProtocol = ioRecvPci.
dwProtocol;
602 trStr.pcbRecvLength = cbRecvLength;
608 ret =
MessageSend(pbRecvBuffer, cbRecvLength, filedes);
617 DWORD dwBytesReturned;
621 if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
625 if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
626 || (ctStr.cbSendLength > sizeof(pbSendBuffer)))
628 goto buffer_overflow;
635 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
639 dwBytesReturned = ctStr.dwBytesReturned;
641 ctStr.rv =
SCardControl(ctStr.hCard, ctStr.dwControlCode,
642 pbSendBuffer, ctStr.cbSendLength,
643 pbRecvBuffer, ctStr.cbRecvLength,
646 ctStr.dwBytesReturned = dwBytesReturned;
652 ret =
MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
663 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
667 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
668 goto buffer_overflow;
670 cbAttrLen = gsStr.cbAttrLen;
673 gsStr.pbAttr, &cbAttrLen);
675 gsStr.cbAttrLen = cbAttrLen;
687 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
691 if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
692 goto buffer_overflow;
695 gsStr.pbAttr, gsStr.cbAttrLen);
702 Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
710 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
716 Log2(PCSC_LOG_DEBUG,
"Buffer overflow detected: %d", filedes);
719 Log2(PCSC_LOG_DEBUG,
"Wrong length: %d", filedes);
721 (void)close(filedes);
722 (void)MSGCleanupClient(threadContext);
723 (void)pthread_exit((LPVOID) NULL);
726 LONG MSGSignalClient(uint32_t filedes, LONG rv)
731 Log2(PCSC_LOG_DEBUG,
"Signal client: %d", filedes);
734 WRITE_BODY_WITH_COMMAND(
"SIGNAL", waStr)
741 threadContext->hContext = hContext;
750 if (threadContext->hContext != hContext)
754 while (list_size(&(threadContext->cardsList)) != 0)
763 ptr = list_get_at(&(threadContext->cardsList), 0);
766 Log1(PCSC_LOG_CRITICAL,
"list_get_at failed");
769 hCard = *(int32_t *)ptr;
774 rv = RFReaderInfoById(hCard, &rContext);
784 if (hCard != hLockId)
799 rv =
SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
808 lrv = list_delete_at(&(threadContext->cardsList), 0);
810 Log2(PCSC_LOG_CRITICAL,
811 "list_delete_at failed with return value: %d", lrv);
814 list_destroy(&(threadContext->cardsList));
818 threadContext->hContext = 0;
826 if (threadContext->hContext == hContext)
833 listLength = list_size(&(threadContext->cardsList));
834 if (listLength >= contextMaxCardHandles)
837 "Too many card handles for thread context @%p: %d (max is %d)"
838 "Restart pcscd with --max-card-handle-per-thread value",
839 threadContext, listLength, contextMaxCardHandles);
844 lrv = list_append(&(threadContext->cardsList), &hCard);
848 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
863 lrv = list_delete(&(threadContext->cardsList), &hCard);
867 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv);
875 static LONG MSGCheckHandleAssociation(
SCARDHANDLE hCard,
880 if (0 == threadContext->hContext)
884 Log1(PCSC_LOG_CRITICAL,
"Invalidated handle");
889 list_index = list_locate(&(threadContext->cardsList), &hCard);
895 Log1(PCSC_LOG_ERROR,
"Client failed to authenticate");
905 static LONG MSGCleanupClient(
SCONTEXT * threadContext)
910 if (threadContext->hContext != 0)
913 (void)MSGRemoveContext(threadContext->hContext, threadContext);
917 "Thread is stopping: dwClientID=%d, threadContext @%p",
923 memset((
void*) threadContext, 0,
sizeof(
SCONTEXT));
924 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXT @%p", threadContext);
927 lrv = list_delete(&contextsList, threadContext);
928 listSize = list_size(&contextsList);
931 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %x", lrv);
938 Log2(PCSC_LOG_DEBUG,
"Starting suicide alarm in %d seconds",
939 TIME_BEFORE_SUICIDE);
940 alarm(TIME_BEFORE_SUICIDE);