Smartcard fixes (bigendian support, locking, bugfixes) from

Paul Winder <Paul.Winder@tadpole.com>


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1420 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Michael Gernoth 2007-10-30 13:09:37 +00:00
parent 27c360df03
commit 5c01b88a5f
2 changed files with 108 additions and 71 deletions

177
scard.c
View File

@ -43,6 +43,16 @@
#define SCARD_AUTOALLOCATE -1
#define OUT_STREAM_SIZE 4096
#ifdef B_ENDIAN
#define swap32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | \
(((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
#define swap16(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
#else
#define swap32(x) (x)
#define swap16(x) (x)
#endif
static pthread_mutex_t **scard_mutex = NULL;
static uint32 curDevice = 0, curId = 0, curBytesOut = 0;
@ -51,7 +61,7 @@ static int nameMapCount = 0;
static pthread_t queueHandler;
static pthread_mutex_t queueAccess;
static pthread_mutex_t queueEmpty;
static pthread_cond_t queueEmpty;
static pthread_mutex_t hcardAccess;
static PMEM_HANDLE threadListHandle = NULL;
@ -138,9 +148,9 @@ scard_enum_devices(uint32 * id, char *optarg)
return 0;
}
if (0 != pthread_mutex_init(&queueEmpty, NULL))
if (0 != pthread_cond_init(&queueEmpty, NULL))
{
error("scard_enum_devices: Can't initialize queue control mutex\n");
error("scard_enum_devices: Can't initialize queue control cv\n");
return 0;
}
@ -610,7 +620,7 @@ TS_SCardEstablishContext(STREAM in, STREAM out)
}
else
{
DEBUG_SCARD(("SCARD: -> Success (context: 0x%08x)\n", (unsigned) hContext));
DEBUG_SCARD(("SCARD: -> Success (context: 0x%08lx)\n", hContext));
}
out_uint32_le(out, 0x00000004);
@ -1053,6 +1063,11 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
{
SERVER_DWORD dataLength;
/* Do endian swaps... */
cur->dwCurrentState = swap32(cur->dwCurrentState);
cur->dwEventState = swap32(cur->dwEventState);
cur->cbAtr = swap32(cur->cbAtr);
/* reset Current state hign bytes; */
*curState = cur->dwCurrentState;
cur->dwCurrentState &= 0x0000FFFF;
@ -1160,6 +1175,11 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
(unsigned) cur->dwEventState));
/* Do endian swaps... */
cur->dwCurrentState = swap32(cur->dwCurrentState);
cur->dwEventState = swap32(cur->dwEventState);
cur->cbAtr = swap32(cur->cbAtr);
out_uint8p(out, (void *) ((unsigned char **) cur + 2),
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
}
@ -1225,6 +1245,8 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
{
cur->cbAtr = swap32(cur->cbAtr);
DEBUG_SCARD(("SCARD: ATR: "));
for (j = 0; j < pAtrMasks->cbAtr; j++)
{
@ -1251,16 +1273,21 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
if (!ResArray)
return SC_returnNoMemoryError(&lcHandle, in, out);
memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
{
/* Do endian swaps... */
rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
rsCur->dwEventState = swap32(rsCur->dwEventState);
rsCur->cbAtr = swap32(rsCur->cbAtr);
inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
DEBUG_SCARD(("SCARD: \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL"));
DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
(unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState,
(unsigned) rsCur->dwEventState));
}
memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
/* FIXME segfault here. */
myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
@ -1309,8 +1336,13 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
out_uint32_le(out, 0x00084dd8);
out_uint32_le(out, readerCount);
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
for (i = 0, rsCur = ResArray; i < readerCount; i++, rsCur++)
{
/* Do endian swaps... */
rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
rsCur->dwEventState = swap32(rsCur->dwEventState);
rsCur->cbAtr = swap32(rsCur->cbAtr);
out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
}
@ -1388,9 +1420,9 @@ copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_RE
size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
dst->dwProtocol = src->dwProtocol;
dst->cbPciLength = src->cbPciLength
- sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST);
dst->dwProtocol = swap32((uint32_t)src->dwProtocol);
dst->cbPciLength = swap32((uint32_t)src->cbPciLength
- sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST));
memcpy(dstBytes, srcBytes, bytesToCopy);
}
@ -1401,8 +1433,8 @@ copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_RE
size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
dst->dwProtocol = src->dwProtocol;
dst->cbPciLength = src->cbPciLength
dst->dwProtocol = swap32(src->dwProtocol);
dst->cbPciLength = src->cbPciLength /* already correct endian */
- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
memcpy(dstBytes, srcBytes, bytesToCopy);
}
@ -1563,7 +1595,7 @@ TS_SCardTransmit(STREAM in, STREAM out)
{
DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength));
#if 0
if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0))
if ((pioRecvPci != NULL) && (mypioRecvPci->cbPciLength > 0))
{
out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
}
@ -1574,10 +1606,10 @@ TS_SCardTransmit(STREAM in, STREAM out)
outBufferStart(out, cbRecvLength); /* start of recvBuf output */
#if 0
if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0))
if ((pioRecvPci) && (mypioRecvPci->cbPciLength > 0))
{
out_uint32_le(out, pioRecvPci->dwProtocol);
int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci);
out_uint32_le(out, mypioRecvPci->dwProtocol);
int len = mypioRecvPci->cbPciLength - sizeof(mypioRecvPci);
outBufferStartWithLimit(out, len, 12);
outBufferFinishWithLimit(out,
(char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
@ -1620,6 +1652,15 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
dwAtrLen = SCARD_MAX_MEM;
#if 1
/*
* Active client sometimes sends a readerlen *just* big enough
* SCardStatus doesn't seem to like this. This is a workaround,
* aka hack!
*/
dwReaderLen = 200;
#endif
readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
if (!readerName)
return SC_returnNoMemoryError(&lcHandle, in, out);
@ -2382,7 +2423,7 @@ SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
if (!queueFirst)
queueFirst = data;
pthread_mutex_unlock(&queueEmpty);
pthread_cond_broadcast(&queueEmpty);
pthread_mutex_unlock(&queueAccess);
}
return data;
@ -2402,19 +2443,22 @@ static PSCThreadData
SC_getNextInQueue()
{
PSCThreadData Result = NULL;
pthread_mutex_lock(&queueAccess);
if (queueFirst != NULL)
while (queueFirst == NULL)
pthread_cond_wait(&queueEmpty, &queueAccess);
Result = queueFirst;
queueFirst = queueFirst->next;
if (!queueFirst)
{
Result = queueFirst;
queueFirst = queueFirst->next;
if (!queueFirst)
{
queueLast = NULL;
pthread_mutex_trylock(&queueEmpty);
}
Result->next = NULL;
queueLast = NULL;
}
Result->next = NULL;
pthread_mutex_unlock(&queueAccess);
return Result;
}
@ -2432,16 +2476,18 @@ SC_deviceControl(PSCThreadData data)
static void *
thread_function(PThreadListElement listElement)
{
if ((listElement != NULL) && (listElement->data != NULL))
pthread_mutex_lock(&listElement->busy);
while (1)
{
while (1)
{
pthread_mutex_lock(&listElement->nodata);
SC_deviceControl(listElement->data);
listElement->data = NULL;
pthread_mutex_unlock(&listElement->busy);
}
while (listElement->data == NULL)
pthread_cond_wait(&listElement->nodata,
&listElement->busy);
SC_deviceControl(listElement->data);
listElement->data = NULL;
}
pthread_mutex_unlock(&listElement->busy);
pthread_exit(NULL);
return NULL;
}
@ -2450,21 +2496,23 @@ static void
SC_handleRequest(PSCThreadData data)
{
int Result = 0;
PThreadListElement cur = threadList, last = threadList;
PThreadListElement cur;
while (cur)
{
if (0 == pthread_mutex_trylock(&cur->busy))
{
for (cur = threadList; cur != NULL; cur = cur->next) {
if (cur->data == NULL) {
pthread_mutex_lock(&cur->busy);
/* double check with lock held.... */
if (cur->data != NULL) {
pthread_mutex_unlock(&cur->busy);
continue;
}
/* Wake up thread */
cur->data = data;
pthread_mutex_unlock(&cur->nodata);
pthread_cond_broadcast(&cur->nodata);
pthread_mutex_unlock(&cur->busy);
return;
}
else
{
last = cur;
cur = cur->next;
}
}
cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
@ -2473,12 +2521,9 @@ SC_handleRequest(PSCThreadData data)
threadCount++;
cur->next = NULL;
pthread_mutex_init(&cur->busy, NULL);
pthread_mutex_init(&cur->nodata, NULL);
pthread_mutex_trylock(&cur->busy);
pthread_cond_init(&cur->nodata, NULL);
cur->data = data;
pthread_mutex_unlock(&cur->nodata);
Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
if (0 != Result)
@ -2488,10 +2533,8 @@ SC_handleRequest(PSCThreadData data)
SC_destroyThreadData(data);
data = NULL;
}
else if (last)
last->next = cur;
else
threadList = cur;
cur->next = threadList;
threadList = cur;
}
static void *
@ -2501,26 +2544,20 @@ queue_handler_function(void *data)
while (1)
{
cur_data = SC_getNextInQueue();
if (cur_data != NULL)
switch (cur_data->request)
{
switch (cur_data->request)
{
case SC_ESTABLISH_CONTEXT:
case SC_RELEASE_CONTEXT:
{
SC_deviceControl(cur_data);
break;
}
default:
{
SC_handleRequest(cur_data);
break;
}
}
cur_data = NULL;
case SC_ESTABLISH_CONTEXT:
case SC_RELEASE_CONTEXT:
{
SC_deviceControl(cur_data);
break;
}
default:
{
SC_handleRequest(cur_data);
break;
}
}
else
pthread_mutex_lock(&queueEmpty);
}
return NULL;
}

View File

@ -168,7 +168,7 @@ typedef struct _TThreadListElement
{
pthread_t thread;
pthread_mutex_t busy;
pthread_mutex_t nodata;
pthread_cond_t nodata;
PSCThreadData data;
struct _TThreadListElement *next;
} TThreadListElement, *PThreadListElement;