76static int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
77static int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
97static void MSGCleanupClient(
SCONTEXT *);
99static void * ContextThread(LPVOID
pdwIndex);
103static int contextsListhContext_seeker(
const void *
el,
const void *key)
109 Log3(PCSC_LOG_CRITICAL,
"called with NULL pointer: el=%p, key=%p",
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);
149void 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);
212 Log1(PCSC_LOG_CRITICAL,
"Could not allocate new context");
223 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
lrv);
228 list_attributes_copy(&
newContext->cardsList, list_meter_int32_t, 1);
236 list_comparator_int32_t);
239 Log2(PCSC_LOG_CRITICAL,
240 "list_attributes_comparator failed with return value: %d",
lrv);
250 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
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);
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); \
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",
393 Log3(PCSC_LOG_DEBUG,
"Client is protocol version %d:%d",
402 Log1(PCSC_LOG_CRITICAL,
403 "Communication protocol mismatch!");
404 Log3(PCSC_LOG_ERROR,
"Client protocol is %d:%d",
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;
495 reStr.rv = SCardReleaseContext(
reStr.hContext);
508 DWORD dwActiveProtocol;
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);
529 coStr.dwShareMode,
coStr.dwPreferredProtocols,
530 &hCard, &dwActiveProtocol);
534 coStr.dwActiveProtocol = dwActiveProtocol;
561 rcStr.dwPreferredProtocols,
rcStr.dwInitialization,
563 rcStr.dwActiveProtocol = dwActiveProtocol;
596 beStr.rv = SCardBeginTransaction(
beStr.hCard);
612 enStr.dwDisposition);
693 Log2(PCSC_LOG_DEBUG,
"Client die: %d",
filedes);
707 if (cbRecvLength >
trStr.pcbRecvLength)
717 trStr.pcbRecvLength = cbRecvLength;
732 DWORD dwBytesReturned;
749 Log2(PCSC_LOG_DEBUG,
"Client die: %d",
filedes);
753 dwBytesReturned =
ctStr.dwBytesReturned;
760 if (dwBytesReturned >
ctStr.cbRecvLength)
766 ctStr.dwBytesReturned = dwBytesReturned;
790 cbAttrLen =
gsStr.cbAttrLen;
793 gsStr.pbAttr, &cbAttrLen);
795 gsStr.cbAttrLen = 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);
855 Log2(PCSC_LOG_DEBUG,
"Signal client: %d",
filedes);
858 WRITE_BODY_WITH_COMMAND(
"SIGNAL",
waStr);
867 Log2(PCSC_LOG_DEBUG,
"Send reader states: %d",
filedes);
888 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
908 Log1(PCSC_LOG_CRITICAL,
"list_get_at failed");
918 rv = RFReaderInfoById(hCard, &
rContext);
967 Log2(PCSC_LOG_CRITICAL,
968 "list_delete_at failed with return value: %d",
lrv);
990 Log1(PCSC_LOG_ERROR,
"Invalidated handle");
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",
1019 Log2(PCSC_LOG_CRITICAL,
1020 "list_append failed with return value: %d",
lrv);
1043 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %d",
lrv);
1051static LONG MSGCheckHandleAssociation(
SCARDHANDLE hCard,
1060 Log1(PCSC_LOG_CRITICAL,
"Invalidated handle");
1071 Log1(PCSC_LOG_ERROR,
"Client failed to authenticate");
1096 Log3(PCSC_LOG_DEBUG,
1097 "Thread is stopping: dwClientID=%d, threadContext @%p",
1104 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXT @%p",
threadContext);
1111 Log2(PCSC_LOG_CRITICAL,
"list_delete failed with error %x",
lrv);
1118 Log2(PCSC_LOG_DEBUG,
"Starting suicide alarm in %d seconds",
1119 TIME_BEFORE_SUICIDE);
1120 alarm(TIME_BEFORE_SUICIDE);
LONG EHTryToUnregisterClientForEvent(int32_t filedes)
Try to unregister a client If no client is found then do not log an error.
LONG EHUnregisterClientForEvent(int32_t filedes)
Unregister a client and log an error if the client is not found.
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
#define SCARD_W_SECURITY_VIOLATION
Access was denied because of a security violation.
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
#define SCARD_E_SERVICE_STOPPED
The Smart card resource manager has shut down.
#define SCARD_E_CANCELLED
The action was cancelled by an SCardCancel request.
#define SCARD_S_SUCCESS
No error was encountered.
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
This keeps a list of defines for pcsc-lite.
@ POWER_STATE_POWERED
powered
#define SCARD_RESET_CARD
Reset on close.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
#define SCARD_LEAVE_CARD
Do nothing on close.
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
LONG SCARDHANDLE
hCard returned by SCardConnect()
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
This keeps track of a list of currently available reader structures.
Protocol Control Information (PCI)
pthread_mutex_t cardsList_lock
lock for the above list
pthread_t pthThread
Event polling thread's ID.
uint32_t dwClientID
Connection ID used to reference the Client.
contained in SCARD_BEGIN_TRANSACTION Messages.
contained in SCARD_CANCEL Messages.
contained in SCARD_CONNECT Messages.
contained in SCARD_CONTROL Messages.
contained in SCARD_DISCONNECT Messages.
contained in SCARD_END_TRANSACTION Messages.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
contained in SCARD_GET_ATTRIB and Messages.
Define an exported public reader state structure so each application gets instant notification of cha...
contained in SCARD_RECONNECT Messages.
Information contained in SCARD_RELEASE_CONTEXT Messages.
contained in SCARD_STATUS Messages.
contained in SCARD_TRANSMIT Messages.
Information transmitted in CMD_VERSION Messages.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
uint32_t timeOut
timeout in ms
This handles abstract system level calls.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
This handles smart card reader communications.
INTERNAL LONG MessageSend(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Sends a menssage from client to server or vice-versa.
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the response from the server or vice-versa.
This defines some structures and #defines to be used over the transport layer.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
@ SCARD_DISCONNECT
used by SCardDisconnect()
@ SCARD_SET_ATTRIB
used by SCardSetAttrib()
@ SCARD_RELEASE_CONTEXT
used by SCardReleaseContext()
@ CMD_STOP_WAITING_READER_STATE_CHANGE
stop waiting for a reader state change
@ CMD_GET_READERS_STATE
get the readers state
@ SCARD_CONTROL
used by SCardControl()
@ CMD_VERSION
get the client/server protocol version
@ CMD_WAIT_READER_STATE_CHANGE
wait for a reader state change
@ SCARD_RECONNECT
used by SCardReconnect()
@ SCARD_STATUS
used by SCardStatus()
@ SCARD_GET_ATTRIB
used by SCardGetAttrib()
@ SCARD_BEGIN_TRANSACTION
used by SCardBeginTransaction()
@ SCARD_TRANSMIT
used by SCardTransmit()
@ SCARD_END_TRANSACTION
used by SCardEndTransaction()
@ SCARD_CANCEL
used by SCardCancel()
@ SCARD_CONNECT
used by SCardConnect()
@ SCARD_ESTABLISH_CONTEXT
used by SCardEstablishContext()
bool AutoExit
Represents an Application Context on the Server side.
LONG CreateContextThread(uint32_t *pdwClientID)
Creates threads to handle messages received from Clients.
static const char * CommandsText[]
Handles messages received from Clients.
static list_t contextsList
Context tracking list.
pthread_mutex_t contextsList_lock
lock for the above list
This demarshalls functions over the message queue and keeps track of clients and their handles.