Now storing established context and using it for messages without

provided context.
This commit is contained in:
Armin Novak 2013-09-30 13:29:40 +02:00
parent 0d7df9ab72
commit 4011fafc51
2 changed files with 176 additions and 50 deletions

View File

@ -30,6 +30,12 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#define BOOL PCSC_BOOL
#include <PCSC/pcsclite.h>
#include <PCSC/reader.h>
#include <PCSC/winscard.h>
#undef BOOL
/* /*
* When using Windows Server 2008 R2 as the Terminal Services (TS) * When using Windows Server 2008 R2 as the Terminal Services (TS)
* server, and with a smart card reader connected to the TS client machine * server, and with a smart card reader connected to the TS client machine
@ -106,8 +112,10 @@ struct _SMARTCARD_DEVICE
HANDLE irpEvent; HANDLE irpEvent;
HANDLE stopEvent; HANDLE stopEvent;
LIST* CompletionIds; LIST* CompletionIds;
HANDLE CompletionIdsMutex; HANDLE CompletionIdsMutex;
SCARDCONTEXT hContext;
}; };
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE; typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;

View File

@ -79,6 +79,100 @@
#define WIN_FILE_DEVICE_SMARTCARD 0x00000031 #define WIN_FILE_DEVICE_SMARTCARD 0x00000031
#if defined(DEBUG_SCARD) && (DEBUG_SCARD)
static char *ioctl_to_string(DWORD code)
{
static char res[100];
char *rc;
switch(code)
{
case SCARD_IOCTL_ESTABLISH_CONTEXT:
rc = "SCARD_IOCTL_ESTABLISH_CONTEXT";
break;
case SCARD_IOCTL_IS_VALID_CONTEXT:
rc = "SCARD_IOCTL_IS_VALID_CONTEXT";
break;
case SCARD_IOCTL_RELEASE_CONTEXT:
rc = "SCARD_IOCTL_RELEASE_CONTEXT";
break;
case SCARD_IOCTL_LIST_READERS:
rc = "SCARD_IOCTL_LIST_READERS";
break;
case SCARD_IOCTL_LIST_READERS + 4:
rc = "SCARD_IOCTL_LIST_READERS + 4";
break;
case SCARD_IOCTL_LIST_READER_GROUPS:
rc = "SCARD_IOCTL_LIST_READER_GROUPS";
break;
case SCARD_IOCTL_LIST_READER_GROUPS + 4:
rc = "SCARD_IOCTL_LIST_READER_GROUPS + 4";
break;
case SCARD_IOCTL_GET_STATUS_CHANGE:
rc = "SCARD_IOCTL_GET_STATUS_CHANGE";
break;
case SCARD_IOCTL_GET_STATUS_CHANGE + 4:
rc = "SCARD_IOCTL_GET_STATUS_CHANGE + 4";
break;
case SCARD_IOCTL_CANCEL:
rc = "SCARD_IOCTL_CANCEL";
break;
case SCARD_IOCTL_CONNECT:
rc = "SCARD_IOCTL_CONNECT";
break;
case SCARD_IOCTL_CONNECT + 4:
rc = "SCARD_IOCTL_CONNECT + 4";
break;
case SCARD_IOCTL_RECONNECT:
rc = "SCARD_IOCTL_RECONNECT";
break;
case SCARD_IOCTL_DISCONNECT:
rc = "SCARD_IOCTL_DISCONNECT";
break;
case SCARD_IOCTL_BEGIN_TRANSACTION:
rc = "SCARD_IOCTL_BEGIN_TRANSACTION";
break;
case SCARD_IOCTL_END_TRANSACTION:
rc = "SCARD_IOCTL_END_TRANSACTION";
break;
case SCARD_IOCTL_STATE:
rc = "SCARD_IOCTL_STATE";
break;
case SCARD_IOCTL_STATUS:
rc = "SCARD_IOCTL_STATUS";
break;
case SCARD_IOCTL_STATUS + 4:
rc = "SCARD_IOCTL_STATUS + 4";
break;
case SCARD_IOCTL_TRANSMIT:
rc = "SCARD_IOCTL_TRANSMIT";
break;
case SCARD_IOCTL_CONTROL:
rc = "SCARD_IOCTL_CONTROL";
break;
case SCARD_IOCTL_GETATTRIB:
rc = "SCARD_IOCTL_GETATTRIB";
break;
case SCARD_IOCTL_ACCESS_STARTED_EVENT:
rc = "SCARD_IOCTL_ACCESS_STARTED_EVENT";
break;
case SCARD_IOCTL_LOCATE_CARDS_BY_ATR:
rc = "SCARD_IOCTL_LOCATE_CARDS_BY_ATR";
break;
case SCARD_IOCTL_LOCATE_CARDS_BY_ATR + 4:
rc = "SCARD_IOCTL_LOCATE_CARDS_BY_ATR + 4";
break;
default:
rc = "UNKNOWN";
break;
}
memset(res, 0, sizeof(res));
strncpy(res, rc, strlen(rc));
return res;
}
#endif
static UINT32 handle_CommonTypeHeader(SMARTCARD_DEVICE* scard, IRP* irp, size_t *inlen) static UINT32 handle_CommonTypeHeader(SMARTCARD_DEVICE* scard, IRP* irp, size_t *inlen)
{ {
UINT8 version; UINT8 version;
@ -183,7 +277,6 @@ static UINT32 handle_Context(SMARTCARD_DEVICE* scard, IRP* irp, size_t *inlen)
Stream_GetRemainingLength(irp->input)); Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
Stream_Seek(irp->input, len); Stream_Seek(irp->input, len);
if (len > Stream_GetRemainingLength(irp->input)) if (len > Stream_GetRemainingLength(irp->input))
@ -259,8 +352,8 @@ static UINT32 handle_RedirContextRef(SMARTCARD_DEVICE* scard, IRP* irp,
Stream_Read_UINT32(irp->input, len); Stream_Read_UINT32(irp->input, len);
if (len != 4) if (len != 4)
{ {
DEBUG_WARN("length violation %d [%d]", 4, DEBUG_WARN("length violation %d [%d], expect=%d", len,
Stream_GetRemainingLength(irp->input)); Stream_GetRemainingLength(irp->input), 4);
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
@ -317,7 +410,7 @@ static BOOL check_reader_is_forwarded(SMARTCARD_DEVICE *scard, const char *reade
BOOL rc = TRUE; BOOL rc = TRUE;
char *name = _strdup(readerName); char *name = _strdup(readerName);
char *str, *strpos=NULL, *strstatus=NULL; char *str, *strpos=NULL, *strstatus=NULL;
long pos, status, cpos, ret; long pos, cpos, ret;
assert(scard); assert(scard);
assert(readerName); assert(readerName);
@ -617,7 +710,8 @@ static UINT32 handle_EstablishContext(SMARTCARD_DEVICE* scard, IRP* irp, size_t
Stream_Write_UINT32(irp->output, 4); Stream_Write_UINT32(irp->output, 4);
Stream_Write_UINT32(irp->output, hContext); Stream_Write_UINT32(irp->output, hContext);
/* TODO: store hContext in allowed context list */ /* store hContext in allowed context list */
scard->hContext = hContext;
smartcard_output_alignment(irp, 8); smartcard_output_alignment(irp, 8);
return status; return status;
@ -645,6 +739,7 @@ static UINT32 handle_ReleaseContext(SMARTCARD_DEVICE* scard, IRP* irp, size_t in
return status; return status;
status = SCardReleaseContext(hContext); status = SCardReleaseContext(hContext);
memset(&scard->hContext, 0, sizeof(scard->hContext));
if (status) if (status)
DEBUG_SCARD("%s (0x%08x)", pcsc_stringify_error(status), (unsigned) status); DEBUG_SCARD("%s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
@ -699,6 +794,10 @@ static UINT32 handle_ListReaders(SMARTCARD_DEVICE* scard, IRP* irp,
UINT32 status; UINT32 status;
SCARDCONTEXT hContext; SCARDCONTEXT hContext;
DWORD dwReaders; DWORD dwReaders;
UINT32 cBytes;
INT32 fmszReadersIsNULL;
UINT32 cchReaders;
LPTSTR mszGroups = NULL;
char *readerList = NULL, *walker; char *readerList = NULL, *walker;
int elemLength, dataLength; int elemLength, dataLength;
int pos, poslen1, poslen2, allowed_pos; int pos, poslen1, poslen2, allowed_pos;
@ -715,31 +814,77 @@ static UINT32 handle_ListReaders(SMARTCARD_DEVICE* scard, IRP* irp,
if (status) if (status)
goto finish; goto finish;
/* Ensure, that the capacity expected is actually available. */ if (Stream_GetRemainingLength(irp->input) < 4)
if (Stream_GetRemainingLength(irp->input) < 0x10)
{ {
DEBUG_WARN("length violation %d [%d]", 0x10, DEBUG_WARN("length violation %d [%d]", 4,
Stream_GetRemainingLength(irp->input)); Stream_GetRemainingLength(irp->input));
status = SCARD_F_INTERNAL_ERROR; status = SCARD_F_INTERNAL_ERROR;
goto finish; goto finish;
} }
Stream_Seek(irp->input, 0x10); Stream_Read_UINT32(irp->input, cBytes);
/* Read RedirScardcontextRef */ /* Ensure, that the capacity expected is actually available. */
status = handle_RedirContextRef(scard, irp, &inlen, &hContext); if (Stream_GetRemainingLength(irp->input) < cBytes)
if (status) {
DEBUG_WARN("length violation %d [%d]", cBytes,
Stream_GetRemainingLength(irp->input));
status = SCARD_F_INTERNAL_ERROR;
goto finish; goto finish;
}
if (cBytes)
{
mszGroups = malloc(cBytes);
Stream_Read(irp->input, mszGroups, cBytes);
}
if (Stream_GetRemainingLength(irp->input) < 4)
{
DEBUG_WARN("length violation %d [%d]", 4,
Stream_GetRemainingLength(irp->input));
status = SCARD_F_INTERNAL_ERROR;
goto finish;
}
Stream_Read_UINT32(irp->input, fmszReadersIsNULL);
if (Stream_GetRemainingLength(irp->input) < 4)
{
DEBUG_WARN("length violation %d [%d]", 4,
Stream_GetRemainingLength(irp->input));
status = SCARD_F_INTERNAL_ERROR;
goto finish;
}
Stream_Read_UINT32(irp->input, cchReaders);
/* TODO: This hack is necessary, because after a successful connect
* there is no redirected handle available any more in the packets
* that are sent from some software. */
inlen = Stream_GetRemainingLength(irp->input);
if(12 == inlen)
{
UINT32 tmp;
Stream_Read_UINT32(irp->input, tmp);
/* Read RedirScardcontextRef */
status = handle_RedirContextRef(scard, irp, &inlen, &hContext);
if (status)
goto finish;
}
else
{
DEBUG_WARN("Using stored context, not provided.");
hContext = scard->hContext;
}
/* ignore rest of [MS-RDPESC] 2.2.2.4 ListReaders_Call */ /* ignore rest of [MS-RDPESC] 2.2.2.4 ListReaders_Call */
#ifdef SCARD_AUTOALLOCATE #ifdef SCARD_AUTOALLOCATE
dwReaders = SCARD_AUTOALLOCATE; dwReaders = SCARD_AUTOALLOCATE;
status = SCardListReaders(hContext, NULL, (LPSTR) &readerList, &dwReaders); status = SCardListReaders(hContext, mszGroups, (LPSTR) &readerList, &dwReaders);
#else #else
status = SCardListReaders(hContext, NULL, NULL, &dwReaders); status = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
readerList = malloc(dwReaders); readerList = malloc(dwReaders);
status = SCardListReaders(hContext, NULL, readerList, &dwReaders); status = SCardListReaders(hContext, mszGroups, readerList, &dwReaders);
#endif #endif
if (status != SCARD_S_SUCCESS) if (status != SCARD_S_SUCCESS)
{ {
@ -807,6 +952,9 @@ finish:
#endif #endif
} }
if (mszGroups)
free(mszGroups);
return status; return status;
} }
@ -1546,23 +1694,6 @@ finish:
return status; return status;
} }
static void Stream_Dump(wStream *s)
{
size_t size = Stream_GetRemainingLength(s);
int i;
fprintf(stderr, "-------------------------- Start [%s] [%zd] ------------------------",
__func__, size);
for(i=0; i<size; i++)
{
fprintf(stderr, "%02X", s->pointer[i]);
if (i % 80 == 0)
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
fprintf(stderr, "-------------------------- End [%s] ------------------------", __func__);
}
static UINT32 handle_Transmit(SMARTCARD_DEVICE* scard, IRP* irp, size_t inlen) static UINT32 handle_Transmit(SMARTCARD_DEVICE* scard, IRP* irp, size_t inlen)
{ {
LONG status; LONG status;
@ -1625,18 +1756,6 @@ static UINT32 handle_Transmit(SMARTCARD_DEVICE* scard, IRP* irp, size_t inlen)
if (status) if (status)
goto finish; goto finish;
DEBUG_WARN("dwProtocol=%X, cbPciLength=%d, pioSendPciBufferPtr=%d, cbSendLength=%d, ptrSendBuffer=%d, ptrIoRecvPciBuffer=%d, recvBufferIsNULL=%d, cbRecvLength=%d",
ioSendPci.rq->dwProtocol,
ioSendPci.rq->cbPciLength,
pioSendPciBufferPtr,
cbSendLength,
ptrSendBuffer,
ptrIoRecvPciBuffer,
recvBufferIsNULL,
cbRecvLength);
Stream_Dump(irp->input);
/* Check, if there is data available from the ipSendPci element */ /* Check, if there is data available from the ipSendPci element */
if (pioSendPciBufferPtr) if (pioSendPciBufferPtr)
{ {
@ -2373,7 +2492,9 @@ void smartcard_device_control(SMARTCARD_DEVICE* scard, IRP* irp)
/* body. input_len contains the length of the remaining data /* body. input_len contains the length of the remaining data
* that can be read from the current position of irp->input, * that can be read from the current position of irp->input,
* so pass it on ;) */ * so pass it on ;) */
DEBUG_SCARD("ioctl %08X", ioctl_code); DEBUG_SCARD("ioctl '%s' [%08X], length=%d [%d]",
ioctl_to_string(ioctl_code), ioctl_code, input_len,
Stream_GetRemainingLength(irp->input));
switch (ioctl_code) switch (ioctl_code)
{ {
case SCARD_IOCTL_ESTABLISH_CONTEXT: case SCARD_IOCTL_ESTABLISH_CONTEXT:
@ -2502,9 +2623,6 @@ void smartcard_device_control(SMARTCARD_DEVICE* scard, IRP* irp)
Stream_SetPosition(irp->output, pos); Stream_SetPosition(irp->output, pos);
#ifdef WITH_DEBUG_SCARD
winpr_HexDump(Stream_Buffer(irp->output), Stream_GetPosition(irp->output));
#endif
irp->IoStatus = 0; irp->IoStatus = 0;
irp->Complete(irp); irp->Complete(irp);