76 static int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
77 static int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
97 static void MSGCleanupClient(
SCONTEXT *);
99 static void * ContextThread(LPVOID pdwIndex);
103 static int contextsListhContext_seeker(
const void *el,
const void *key)
107 if ((el == NULL) || (key == NULL))
109 Log3(PCSC_LOG_CRITICAL,
"called with NULL pointer: el=%p, key=%p",
114 if (currentContext->hContext == *(int32_t *)key)
119 LONG ContextsInitialize(
int customMaxThreadCounter,
120 int customMaxThreadCardHandles)
124 if (customMaxThreadCounter != 0)
125 contextMaxThreadCounter = customMaxThreadCounter;
127 if (customMaxThreadCardHandles != 0)
128 contextMaxCardHandles = customMaxThreadCardHandles;
133 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
136 lrv = list_attributes_seeker(&
contextsList, contextsListhContext_seeker);
139 Log2(PCSC_LOG_CRITICAL,
140 "list_attributes_seeker failed with return value: %d", lrv);
149 void ContextsDeinitialize(
void)
157 Log2(PCSC_LOG_DEBUG,
"remaining threads: %d", listSize);
162 Log1(PCSC_LOG_ERROR,
"list_iterator_start failed");
168 Log3(PCSC_LOG_DEBUG,
"Cancel dwClientID=%d hContext: %p",
172 Log2(PCSC_LOG_DEBUG,
"Waiting client: %d", elt->
dwClientID);
174 Log2(PCSC_LOG_INFO,
"Client %d terminated", elt->
dwClientID);
202 if (listSize >= contextMaxThreadCounter)
204 Log2(PCSC_LOG_CRITICAL,
"Too many context running: %d", listSize);
209 newContext = malloc(
sizeof(*newContext));
210 if (NULL == newContext)
212 Log1(PCSC_LOG_CRITICAL,
"Could not allocate new context");
215 memset(newContext, 0,
sizeof(*newContext));
220 lrv = list_init(&newContext->cardsList);
223 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
228 list_attributes_copy(&newContext->cardsList, list_meter_int32_t, 1);
235 lrv = list_attributes_comparator(&newContext->cardsList,
236 list_comparator_int32_t);
239 Log2(PCSC_LOG_CRITICAL,
240 "list_attributes_comparator failed with return value: %d", lrv);
241 list_destroy(&newContext->cardsList);
250 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
252 list_destroy(&newContext->cardsList);
256 rv = ThreadCreate(&newContext->
pthThread, THREAD_ATTR_DETACHED,
257 (PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) newContext);
262 Log2(PCSC_LOG_CRITICAL,
"ThreadCreate failed: %s", strerror(rv));
265 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv2);
266 list_destroy(&newContext->cardsList);
283 (void)close(*pdwClientID);
318 "CANCEL_TRANSACTION",
322 "CMD_GET_READERS_STATE",
323 "CMD_WAIT_READER_STATE_CHANGE",
324 "CMD_STOP_WAITING_READER_STATE_CHANGE",
329 #define READ_BODY(v) \
331 if (header.size != sizeof(v)) \
333 ret = MessageReceive(&v, sizeof(v), filedes); \
334 if (ret != SCARD_S_SUCCESS) { \
335 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); \
340 #define WRITE_BODY(v) \
341 WRITE_BODY_WITH_COMMAND(CommandsText[header.command], v)
342 #define WRITE_BODY_WITH_COMMAND(command, v) \
344 LogRv4(PCSC_LOG_DEBUG, v.rv, "%s for client %d", command, filedes); \
345 ret = MessageSend(&v, sizeof(v), filedes); \
348 static void * ContextThread(LPVOID newContext)
353 if (IsClientAuthorized(filedes,
"access_pcsc", NULL) == 0)
355 Log1(PCSC_LOG_CRITICAL,
"Rejected unauthorized PC/SC client");
360 Log1(PCSC_LOG_DEBUG,
"Authorized PC/SC client");
363 Log3(PCSC_LOG_DEBUG,
"Thread is started: dwClientID=%d, threadContext @%p",
374 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
379 if ((header.command > CMD_ENUM_FIRST)
380 && (header.command < CMD_ENUM_LAST))
381 Log3(PCSC_LOG_DEBUG,
"Received command: %s from client %d",
384 switch (header.command)
393 Log3(PCSC_LOG_DEBUG,
"Client is protocol version %d:%d",
394 veStr.major, veStr.minor);
402 Log1(PCSC_LOG_CRITICAL,
403 "Communication protocol mismatch!");
404 Log3(PCSC_LOG_ERROR,
"Client protocol is %d:%d",
405 veStr.major, veStr.minor);
406 Log3(PCSC_LOG_ERROR,
"Server protocol is %d:%d",
426 RFWaitForReaderInit();
440 RFWaitForReaderInit();
444 EHRegisterClientForEvent(filedes);
477 hContext = esStr.hContext;
478 esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0,
480 esStr.hContext = hContext;
483 esStr.rv = MSGAddContext(esStr.hContext, threadContext);
495 reStr.rv = SCardReleaseContext(reStr.hContext);
498 reStr.rv = MSGRemoveContext(reStr.hContext, threadContext);
508 DWORD dwActiveProtocol;
512 coStr.szReader[
sizeof(coStr.szReader)-1] = 0;
514 dwActiveProtocol = coStr.dwActiveProtocol;
516 if (IsClientAuthorized(filedes,
"access_card", coStr.szReader) == 0)
518 Log2(PCSC_LOG_CRITICAL,
"Rejected unauthorized client for '%s'", coStr.szReader);
522 dwActiveProtocol = -1;
526 Log2(PCSC_LOG_DEBUG,
"Authorized client for '%s'", coStr.szReader);
528 coStr.rv = SCardConnect(coStr.hContext, coStr.szReader,
529 coStr.dwShareMode, coStr.dwPreferredProtocols,
530 &hCard, &dwActiveProtocol);
534 coStr.dwActiveProtocol = dwActiveProtocol;
538 coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
557 if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
560 rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
561 rcStr.dwPreferredProtocols, rcStr.dwInitialization,
563 rcStr.dwActiveProtocol = dwActiveProtocol;
575 if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
578 diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);
581 diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext);
593 if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
596 beStr.rv = SCardBeginTransaction(beStr.hCard);
608 if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
611 enStr.rv = SCardEndTransaction(enStr.hCard,
612 enStr.dwDisposition);
634 if (psTargetContext != NULL)
636 uint32_t fd = psTargetContext->dwClientID;
660 if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
664 stStr.rv = SCardStatus(stStr.hCard, NULL, NULL, NULL,
682 if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
686 if (trStr.cbSendLength >
sizeof(pbSendBuffer))
687 goto buffer_overflow;
693 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
697 ioSendPci.
dwProtocol = trStr.ioSendPciProtocol;
699 ioRecvPci.
dwProtocol = trStr.ioRecvPciProtocol;
701 cbRecvLength =
sizeof pbRecvBuffer;
703 trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
704 pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
705 pbRecvBuffer, &cbRecvLength);
707 if (cbRecvLength > trStr.pcbRecvLength)
713 trStr.ioSendPciProtocol = ioSendPci.
dwProtocol;
715 trStr.ioRecvPciProtocol = ioRecvPci.
dwProtocol;
717 trStr.pcbRecvLength = cbRecvLength;
723 ret =
MessageSend(pbRecvBuffer, cbRecvLength, filedes);
732 DWORD dwBytesReturned;
736 if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
740 if (ctStr.cbSendLength >
sizeof(pbSendBuffer))
742 goto buffer_overflow;
749 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
753 dwBytesReturned = ctStr.dwBytesReturned;
755 ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
756 pbSendBuffer, ctStr.cbSendLength,
757 pbRecvBuffer,
sizeof pbRecvBuffer,
760 if (dwBytesReturned > ctStr.cbRecvLength)
766 ctStr.dwBytesReturned = dwBytesReturned;
772 ret =
MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
783 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
787 if (gsStr.cbAttrLen >
sizeof(gsStr.pbAttr))
788 goto buffer_overflow;
790 cbAttrLen = gsStr.cbAttrLen;
792 gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
793 gsStr.pbAttr, &cbAttrLen);
795 gsStr.cbAttrLen = cbAttrLen;
807 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
811 if (gsStr.cbAttrLen >
sizeof(gsStr.pbAttr))
812 goto buffer_overflow;
814 gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
815 gsStr.pbAttr, gsStr.cbAttrLen);
822 Log2(PCSC_LOG_CRITICAL,
"Unknown command: %d", header.command);
830 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
836 Log2(PCSC_LOG_DEBUG,
"Buffer overflow detected: %d", filedes);
839 Log2(PCSC_LOG_DEBUG,
"Wrong length: %d", filedes);
841 (void)close(filedes);
842 MSGCleanupClient(threadContext);
843 (void)pthread_exit((LPVOID) NULL);
846 LONG MSGSignalClient(uint32_t filedes, LONG rv)
855 Log2(PCSC_LOG_DEBUG,
"Signal client: %d", filedes);
858 WRITE_BODY_WITH_COMMAND(
"SIGNAL", waStr);
863 LONG MSGSendReaderStates(uint32_t filedes)
867 Log2(PCSC_LOG_DEBUG,
"Send reader states: %d", filedes);
877 threadContext->hContext = hContext;
886 if (0 == threadContext->hContext)
888 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
892 if (threadContext->hContext != hContext)
896 while (list_size(&threadContext->cardsList) != 0)
905 ptr = list_get_at(&threadContext->cardsList, 0);
908 Log1(PCSC_LOG_CRITICAL,
"list_get_at failed");
911 hCard = *(int32_t *)ptr;
918 rv = RFReaderInfoById(hCard, &rContext);
935 if (hCard != rContext->
hLockId)
954 rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
965 lrv = list_delete_at(&threadContext->cardsList, 0);
967 Log2(PCSC_LOG_CRITICAL,
968 "list_delete_at failed with return value: %d", lrv);
971 UNREF_READER(rContext)
978 threadContext->hContext = 0;
988 if (0 == threadContext->hContext)
990 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
994 if (threadContext->hContext == hContext)
1003 listLength = list_size(&threadContext->cardsList);
1004 if (listLength >= contextMaxCardHandles)
1006 Log4(PCSC_LOG_DEBUG,
1007 "Too many card handles for thread context @%p: %d (max is %d). "
1008 "Restart pcscd with --max-card-handle-per-thread value",
1009 threadContext, listLength, contextMaxCardHandles);
1016 lrv = list_append(&threadContext->cardsList, &hCard);
1019 Log2(PCSC_LOG_CRITICAL,
1020 "list_append failed with return value: %d", lrv);
1039 lrv = list_delete(&threadContext->cardsList, &hCard);
1043 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv);
1051 static LONG MSGCheckHandleAssociation(
SCARDHANDLE hCard,
1056 if (0 == threadContext->hContext)
1060 Log1(PCSC_LOG_CRITICAL,
"Invalidated handle");
1065 list_index = list_locate(&threadContext->cardsList, &hCard);
1067 if (list_index >= 0)
1071 Log1(PCSC_LOG_ERROR,
"Client failed to authenticate");
1081 static void MSGCleanupClient(
SCONTEXT * threadContext)
1086 if (threadContext->hContext != 0)
1088 (void)SCardReleaseContext(threadContext->hContext);
1089 (void)MSGRemoveContext(threadContext->hContext, threadContext);
1093 list_destroy(&threadContext->cardsList);
1096 Log3(PCSC_LOG_DEBUG,
1097 "Thread is stopping: dwClientID=%d, threadContext @%p",
1103 memset((
void*) threadContext, 0,
sizeof(
SCONTEXT));
1104 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXT @%p", threadContext);
1111 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %x", lrv);
1113 free(threadContext);
1118 Log2(PCSC_LOG_DEBUG,
"Starting suicide alarm in %d seconds",
1119 TIME_BEFORE_SUICIDE);
1120 alarm(TIME_BEFORE_SUICIDE);