Now storing established context and using it for messages without
provided context.
This commit is contained in:
parent
0d7df9ab72
commit
4011fafc51
@ -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
|
||||||
@ -108,6 +114,8 @@ struct _SMARTCARD_DEVICE
|
|||||||
|
|
||||||
LIST* CompletionIds;
|
LIST* CompletionIds;
|
||||||
HANDLE CompletionIdsMutex;
|
HANDLE CompletionIdsMutex;
|
||||||
|
|
||||||
|
SCARDCONTEXT hContext;
|
||||||
};
|
};
|
||||||
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
|
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
/* Ensure, that the capacity expected is actually available. */
|
||||||
|
if (Stream_GetRemainingLength(irp->input) < cBytes)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("length violation %d [%d]", cBytes,
|
||||||
|
Stream_GetRemainingLength(irp->input));
|
||||||
|
status = SCARD_F_INTERNAL_ERROR;
|
||||||
|
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 */
|
/* Read RedirScardcontextRef */
|
||||||
status = handle_RedirContextRef(scard, irp, &inlen, &hContext);
|
status = handle_RedirContextRef(scard, irp, &inlen, &hContext);
|
||||||
if (status)
|
if (status)
|
||||||
goto finish;
|
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user