75 static int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
76 static int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
96 static void MSGCleanupClient(
SCONTEXT *);
98 static void * ContextThread(LPVOID pdwIndex);
102 static int contextsListhContext_seeker(
const void *el,
const void *key)
106 if ((el == NULL) || (key == NULL))
108 Log3(PCSC_LOG_CRITICAL,
"called with NULL pointer: el=%p, key=%p",
113 if (currentContext->hContext == *(int32_t *)key)
118 LONG ContextsInitialize(
int customMaxThreadCounter,
119 int customMaxThreadCardHandles)
123 if (customMaxThreadCounter != 0)
124 contextMaxThreadCounter = customMaxThreadCounter;
126 if (customMaxThreadCardHandles != 0)
127 contextMaxCardHandles = customMaxThreadCardHandles;
132 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
135 lrv = list_attributes_seeker(&
contextsList, contextsListhContext_seeker);
138 Log2(PCSC_LOG_CRITICAL,
139 "list_attributes_seeker failed with return value: %d", lrv);
148 void ContextsDeinitialize(
void)
155 Log2(PCSC_LOG_DEBUG,
"remaining threads: %d", listSize);
182 if (listSize >= contextMaxThreadCounter)
184 Log2(PCSC_LOG_CRITICAL,
"Too many context running: %d", listSize);
189 newContext = malloc(
sizeof(*newContext));
190 if (NULL == newContext)
192 Log1(PCSC_LOG_CRITICAL,
"Could not allocate new context");
195 memset(newContext, 0,
sizeof(*newContext));
200 lrv = list_init(&newContext->cardsList);
203 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
208 list_attributes_copy(&newContext->cardsList, list_meter_int32_t, 1);
215 lrv = list_attributes_comparator(&newContext->cardsList,
216 list_comparator_int32_t);
219 Log2(PCSC_LOG_CRITICAL,
220 "list_attributes_comparator failed with return value: %d", lrv);
221 list_destroy(&newContext->cardsList);
230 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
232 list_destroy(&newContext->cardsList);
236 rv = ThreadCreate(&newContext->
pthThread, THREAD_ATTR_DETACHED,
237 (PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) newContext);
242 Log2(PCSC_LOG_CRITICAL,
"ThreadCreate failed: %s", strerror(rv));
245 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv2);
246 list_destroy(&newContext->cardsList);
263 (void)close(*pdwClientID);
298 "CANCEL_TRANSACTION",
302 "CMD_GET_READERS_STATE",
303 "CMD_WAIT_READER_STATE_CHANGE",
304 "CMD_STOP_WAITING_READER_STATE_CHANGE",
309 #define READ_BODY(v) \
311 if (header.size != sizeof(v)) \
313 ret = MessageReceive(&v, sizeof(v), filedes); \
314 if (ret != SCARD_S_SUCCESS) { \
315 Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); \
320 #define WRITE_BODY(v) \
321 WRITE_BODY_WITH_COMMAND(CommandsText[header.command], v)
322 #define WRITE_BODY_WITH_COMMAND(command, v) \
324 Log4(PCSC_LOG_DEBUG, "%s rv=0x%X for client %d", command, v.rv, filedes); \
325 ret = MessageSend(&v, sizeof(v), filedes); \
328 static void * ContextThread(LPVOID newContext)
333 if (IsClientAuthorized(filedes,
"access_pcsc", NULL) == 0)
335 Log1(PCSC_LOG_CRITICAL,
"Rejected unauthorized PC/SC client");
340 Log1(PCSC_LOG_DEBUG,
"Authorized PC/SC client");
343 Log3(PCSC_LOG_DEBUG,
"Thread is started: dwClientID=%d, threadContext @%p",
354 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
359 if ((header.command > CMD_ENUM_FIRST)
360 && (header.command < CMD_ENUM_LAST))
361 Log3(PCSC_LOG_DEBUG,
"Received command: %s from client %d",
364 switch (header.command)
373 Log3(PCSC_LOG_DEBUG,
"Client is protocol version %d:%d",
374 veStr.major, veStr.minor);
382 Log1(PCSC_LOG_CRITICAL,
383 "Communication protocol mismatch!");
384 Log3(PCSC_LOG_ERROR,
"Client protocol is %d:%d",
385 veStr.major, veStr.minor);
386 Log3(PCSC_LOG_ERROR,
"Server protocol is %d:%d",
406 RFWaitForReaderInit();
420 RFWaitForReaderInit();
424 EHRegisterClientForEvent(filedes);
453 hContext = esStr.hContext;
456 esStr.hContext = hContext;
459 esStr.rv = MSGAddContext(esStr.hContext, threadContext);
474 reStr.rv = MSGRemoveContext(reStr.hContext, threadContext);
484 DWORD dwActiveProtocol;
488 coStr.szReader[
sizeof(coStr.szReader)-1] = 0;
490 dwActiveProtocol = coStr.dwActiveProtocol;
492 if (IsClientAuthorized(filedes,
"access_card", coStr.szReader) == 0)
494 Log2(PCSC_LOG_CRITICAL,
"Rejected unauthorized client for '%s'", coStr.szReader);
499 Log2(PCSC_LOG_DEBUG,
"Authorized client for '%s'", coStr.szReader);
503 coStr.dwShareMode, coStr.dwPreferredProtocols,
504 &hCard, &dwActiveProtocol);
507 coStr.dwActiveProtocol = dwActiveProtocol;
511 coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
526 DWORD dwActiveProtocol;
530 if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
534 rcStr.dwPreferredProtocols, rcStr.dwInitialization,
536 rcStr.dwActiveProtocol = dwActiveProtocol;
548 if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
554 diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext);
566 if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
581 if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
585 enStr.dwDisposition);
607 if (psTargetContext != NULL)
609 uint32_t fd = psTargetContext->dwClientID;
631 if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
635 stStr.rv =
SCardStatus(stStr.hCard, NULL, NULL, NULL,
653 if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
657 if ((trStr.pcbRecvLength >
sizeof(pbRecvBuffer))
658 || (trStr.cbSendLength >
sizeof(pbSendBuffer)))
659 goto buffer_overflow;
665 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
669 ioSendPci.
dwProtocol = trStr.ioSendPciProtocol;
671 ioRecvPci.
dwProtocol = trStr.ioRecvPciProtocol;
673 cbRecvLength =
sizeof pbRecvBuffer;
676 pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
677 pbRecvBuffer, &cbRecvLength);
679 if (cbRecvLength > trStr.pcbRecvLength)
685 trStr.ioSendPciProtocol = ioSendPci.
dwProtocol;
687 trStr.ioRecvPciProtocol = ioRecvPci.
dwProtocol;
689 trStr.pcbRecvLength = cbRecvLength;
695 ret =
MessageSend(pbRecvBuffer, cbRecvLength, filedes);
704 DWORD dwBytesReturned;
708 if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
712 if ((ctStr.cbRecvLength >
sizeof(pbRecvBuffer))
713 || (ctStr.cbSendLength >
sizeof(pbSendBuffer)))
715 goto buffer_overflow;
722 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
726 dwBytesReturned = ctStr.dwBytesReturned;
728 ctStr.rv =
SCardControl(ctStr.hCard, ctStr.dwControlCode,
729 pbSendBuffer, ctStr.cbSendLength,
730 pbRecvBuffer,
sizeof pbRecvBuffer,
733 if (dwBytesReturned > ctStr.cbRecvLength)
739 ctStr.dwBytesReturned = dwBytesReturned;
745 ret =
MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
756 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
760 if (gsStr.cbAttrLen >
sizeof(gsStr.pbAttr))
761 goto buffer_overflow;
763 cbAttrLen = gsStr.cbAttrLen;
766 gsStr.pbAttr, &cbAttrLen);
768 gsStr.cbAttrLen = cbAttrLen;
780 if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
784 if (gsStr.cbAttrLen >
sizeof(gsStr.pbAttr))
785 goto buffer_overflow;
788 gsStr.pbAttr, gsStr.cbAttrLen);
795 Log2(PCSC_LOG_CRITICAL,
"Unknown command: %d", header.command);
803 Log2(PCSC_LOG_DEBUG,
"Client die: %d", filedes);
809 Log2(PCSC_LOG_DEBUG,
"Buffer overflow detected: %d", filedes);
812 Log2(PCSC_LOG_DEBUG,
"Wrong length: %d", filedes);
814 (void)close(filedes);
815 MSGCleanupClient(threadContext);
816 (void)pthread_exit((LPVOID) NULL);
819 LONG MSGSignalClient(uint32_t filedes, LONG rv)
828 Log2(PCSC_LOG_DEBUG,
"Signal client: %d", filedes);
831 WRITE_BODY_WITH_COMMAND(
"SIGNAL", waStr);
836 LONG MSGSendReaderStates(uint32_t filedes)
840 Log2(PCSC_LOG_DEBUG,
"Send reader states: %d", filedes);
850 threadContext->hContext = hContext;
859 if (0 == threadContext->hContext)
861 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
865 if (threadContext->hContext != hContext)
869 while (list_size(&threadContext->cardsList) != 0)
878 ptr = list_get_at(&threadContext->cardsList, 0);
881 Log1(PCSC_LOG_CRITICAL,
"list_get_at failed");
884 hCard = *(int32_t *)ptr;
889 rv = RFReaderInfoById(hCard, &rContext);
903 if (hCard != rContext->
hLockId)
922 rv =
SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
932 lrv = list_delete_at(&threadContext->cardsList, 0);
934 Log2(PCSC_LOG_CRITICAL,
935 "list_delete_at failed with return value: %d", lrv);
937 UNREF_READER(rContext)
943 threadContext->hContext = 0;
953 if (0 == threadContext->hContext)
955 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
959 if (threadContext->hContext == hContext)
968 listLength = list_size(&threadContext->cardsList);
969 if (listLength >= contextMaxCardHandles)
972 "Too many card handles for thread context @%p: %d (max is %d). "
973 "Restart pcscd with --max-card-handle-per-thread value",
974 threadContext, listLength, contextMaxCardHandles);
981 lrv = list_append(&threadContext->cardsList, &hCard);
984 Log2(PCSC_LOG_CRITICAL,
985 "list_append failed with return value: %d", lrv);
1004 lrv = list_delete(&threadContext->cardsList, &hCard);
1008 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d", lrv);
1016 static LONG MSGCheckHandleAssociation(
SCARDHANDLE hCard,
1021 if (0 == threadContext->hContext)
1025 Log1(PCSC_LOG_CRITICAL,
"Invalidated handle");
1030 list_index = list_locate(&threadContext->cardsList, &hCard);
1032 if (list_index >= 0)
1036 Log1(PCSC_LOG_ERROR,
"Client failed to authenticate");
1046 static void MSGCleanupClient(
SCONTEXT * threadContext)
1051 if (threadContext->hContext != 0)
1054 (void)MSGRemoveContext(threadContext->hContext, threadContext);
1058 list_destroy(&threadContext->cardsList);
1061 Log3(PCSC_LOG_DEBUG,
1062 "Thread is stopping: dwClientID=%d, threadContext @%p",
1068 memset((
void*) threadContext, 0,
sizeof(
SCONTEXT));
1069 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXT @%p", threadContext);
1076 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %x", lrv);
1078 free(threadContext);
1083 Log2(PCSC_LOG_DEBUG,
"Starting suicide alarm in %d seconds",
1084 TIME_BEFORE_SUICIDE);
1085 alarm(TIME_BEFORE_SUICIDE);