channels/smartcard: cleanup ConnectA/ConnectW parsing

This commit is contained in:
Marc-André Moreau
2014-04-05 16:06:46 -04:00
parent c40c1c3fab
commit 600218dfb2
7 changed files with 571 additions and 357 deletions

View File

@@ -49,8 +49,8 @@ static void irp_complete(IRP* irp)
int pos;
pos = (int) Stream_GetPosition(irp->output);
Stream_SetPosition(irp->output, 12);
Stream_Write_UINT32(irp->output, irp->IoStatus);
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4);
Stream_Write_UINT32(irp->output, irp->IoStatus); /* IoStatus (4 bytes) */
Stream_SetPosition(irp->output, pos);
rdpdr_send((rdpdrPlugin*) irp->devman->plugin, irp->output);
@@ -62,10 +62,10 @@ static void irp_complete(IRP* irp)
IRP* irp_new(DEVMAN* devman, wStream* s)
{
IRP* irp;
UINT32 DeviceId;
DEVICE* device;
UINT32 DeviceId;
Stream_Read_UINT32(s, DeviceId);
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
device = devman_get_device_by_id(devman, DeviceId);
if (!device)
@@ -74,20 +74,21 @@ IRP* irp_new(DEVMAN* devman, wStream* s)
irp = (IRP*) _aligned_malloc(sizeof(IRP), MEMORY_ALLOCATION_ALIGNMENT);
ZeroMemory(irp, sizeof(IRP));
irp->input = s;
irp->device = device;
irp->devman = devman;
Stream_Read_UINT32(s, irp->FileId);
Stream_Read_UINT32(s, irp->CompletionId);
Stream_Read_UINT32(s, irp->MajorFunction);
Stream_Read_UINT32(s, irp->MinorFunction);
irp->input = s;
Stream_Read_UINT32(s, irp->FileId); /* FileId (4 bytes) */
Stream_Read_UINT32(s, irp->CompletionId); /* CompletionId (4 bytes) */
Stream_Read_UINT32(s, irp->MajorFunction); /* MajorFunction (4 bytes) */
Stream_Read_UINT32(s, irp->MinorFunction); /* MinorFunction (4 bytes) */
irp->output = Stream_New(NULL, 256);
Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE);
Stream_Write_UINT16(irp->output, PAKID_CORE_DEVICE_IOCOMPLETION);
Stream_Write_UINT32(irp->output, DeviceId);
Stream_Write_UINT32(irp->output, irp->CompletionId);
Stream_Seek_UINT32(irp->output); /* IoStatus */
Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE); /* Component (2 bytes) */
Stream_Write_UINT16(irp->output, PAKID_CORE_DEVICE_IOCOMPLETION); /* PacketId (2 bytes) */
Stream_Write_UINT32(irp->output, DeviceId); /* DeviceId (4 bytes) */
Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */
Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */
irp->Complete = irp_complete;
irp->Discard = irp_free;

View File

@@ -64,6 +64,11 @@ static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
}
}
/**
* Multiple threads and SCardGetStatusChange:
* http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html
*/
static void* smartcard_thread_func(void* arg)
{
IRP* irp;

View File

@@ -132,8 +132,8 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode)
return "SCARD_IOCTL_WRITECACHEW";
case SCARD_IOCTL_GETTRANSMITCOUNT:
return "SCARD_IOCTL_GETTRANSMITCOUNT";
case SCARD_IOCTL_RELEASETARTEDEVENT:
return "SCARD_IOCTL_RELEASETARTEDEVENT";
case SCARD_IOCTL_RELEASESTARTEDEVENT:
return "SCARD_IOCTL_RELEASESTARTEDEVENT";
case SCARD_IOCTL_GETREADERICON:
return "SCARD_IOCTL_GETREADERICON";
case SCARD_IOCTL_GETDEVICETYPEID:
@@ -145,86 +145,7 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode)
return "SCARD_IOCTL_UNKNOWN";
}
static UINT32 handle_CommonTypeHeader(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT8 version;
UINT32 filler;
UINT8 endianness;
UINT16 commonHeaderLength;
if (Stream_GetRemainingLength(irp->input) < 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "CommonTypeHeader is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
/* Process CommonTypeHeader */
Stream_Read_UINT8(irp->input, version); /* Version (1 byte) */
Stream_Read_UINT8(irp->input, endianness); /* Endianness (1 byte) */
Stream_Read_UINT16(irp->input, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
Stream_Read_UINT32(irp->input, filler); /* Filler (4 bytes), should be 0xCCCCCCCC */
if (version != 1)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader Version %d", version);
return SCARD_F_INTERNAL_ERROR;
}
if (endianness != 0x10)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %d", endianness);
return SCARD_F_INTERNAL_ERROR;
}
if (commonHeaderLength != 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %d", commonHeaderLength);
return SCARD_F_INTERNAL_ERROR;
}
if (filler != 0xCCCCCCCC)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08X", filler);
return SCARD_F_INTERNAL_ERROR;
}
return 0;
}
static UINT32 handle_PrivateTypeHeader(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 filler;
UINT32 objectBufferLength;
if (Stream_GetRemainingLength(irp->input) < 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "PrivateTypeHeader is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Read_UINT32(irp->input, objectBufferLength); /* ObjectBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, filler); /* Filler (4 bytes), should be 0x00000000 */
if (objectBufferLength != Stream_GetRemainingLength(irp->input))
{
WLog_Print(smartcard->log, WLOG_WARN, "PrivateTypeHeader ObjectBufferLength mismatch: Actual: %d, Expected: %d",
(int) objectBufferLength, Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
if (filler != 0x00000000)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08X", filler);
return SCARD_F_INTERNAL_ERROR;
}
return 0;
}
static UINT32 handle_Context(SMARTCARD_DEVICE* smartcard, IRP* irp, int *redirect)
static UINT32 handle_Context(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 length;
@@ -237,7 +158,7 @@ static UINT32 handle_Context(SMARTCARD_DEVICE* smartcard, IRP* irp, int *redirec
Stream_Read_UINT32(irp->input, length); /* Length (4 bytes) */
if (Stream_GetRemainingLength(irp->input) < length)
if ((Stream_GetRemainingLength(irp->input) < length) || (!length))
{
WLog_Print(smartcard->log, WLOG_WARN, "Context is too short: Actual: %d, Expected: %d",
(int) Stream_GetRemainingLength(irp->input), length);
@@ -246,12 +167,6 @@ static UINT32 handle_Context(SMARTCARD_DEVICE* smartcard, IRP* irp, int *redirec
Stream_Seek(irp->input, length);
if (!length)
{
WLog_Print(smartcard->log, WLOG_WARN, "Context is null, using stored context");
*redirect |= 0x01;
}
if (length > Stream_GetRemainingLength(irp->input))
{
WLog_Print(smartcard->log, WLOG_WARN, "Context is too long: Actual: %d, Expected: %d",
@@ -262,12 +177,12 @@ static UINT32 handle_Context(SMARTCARD_DEVICE* smartcard, IRP* irp, int *redirec
return 0;
}
static UINT32 handle_CardHandle(SMARTCARD_DEVICE* smartcard, IRP* irp, int* redirect)
static UINT32 handle_CardHandle(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 status;
UINT32 length;
status = handle_Context(smartcard, irp, redirect);
status = handle_Context(smartcard, irp);
if (status)
return status;
@@ -281,7 +196,7 @@ static UINT32 handle_CardHandle(SMARTCARD_DEVICE* smartcard, IRP* irp, int* redi
Stream_Read_UINT32(irp->input, length); /* Length (4 bytes) */
if (Stream_GetRemainingLength(irp->input) < length)
if ((Stream_GetRemainingLength(irp->input) < length) || (!length))
{
WLog_Print(smartcard->log, WLOG_WARN, "CardHandle is too short: Actual: %d, Expected: %d",
(int) Stream_GetRemainingLength(irp->input), length);
@@ -290,28 +205,13 @@ static UINT32 handle_CardHandle(SMARTCARD_DEVICE* smartcard, IRP* irp, int* redi
Stream_Seek(irp->input, length); /* Length (4 bytes) */
if (!length)
{
WLog_Print(smartcard->log, WLOG_WARN, "CardHandle is null, using stored handle");
*redirect |= 0x02;
}
return 0;
}
static UINT32 handle_RedirContextRef(SMARTCARD_DEVICE* smartcard, IRP* irp,
int redirect, SCARDCONTEXT* hContext)
static UINT32 handle_RedirContextRef(SMARTCARD_DEVICE* smartcard, IRP* irp, SCARDCONTEXT* hContext)
{
UINT32 length;
/* No context provided, use stored. */
if (redirect & 0x01)
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirContextRef no context provided, using stored context\n");
*hContext = smartcard->hContext;
return 0;
}
if (Stream_GetRemainingLength(irp->input) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirContextRef is too short: Actual: %d, Expected: %d\n",
@@ -327,7 +227,7 @@ static UINT32 handle_RedirContextRef(SMARTCARD_DEVICE* smartcard, IRP* irp,
return SCARD_F_INTERNAL_ERROR;
}
if (Stream_GetRemainingLength(irp->input) < length)
if ((Stream_GetRemainingLength(irp->input) < length) || (!length))
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirContextRef is too short: Actual: %d, Expected: %d\n",
(int) Stream_GetRemainingLength(irp->input), length);
@@ -342,25 +242,16 @@ static UINT32 handle_RedirContextRef(SMARTCARD_DEVICE* smartcard, IRP* irp,
return 0;
}
static UINT32 handle_RedirHandleRef(SMARTCARD_DEVICE* smartcard, IRP* irp,
int redirect, SCARDCONTEXT* hContext, SCARDHANDLE* hHandle)
static UINT32 handle_RedirHandleRef(SMARTCARD_DEVICE* smartcard, IRP* irp, SCARDCONTEXT* hContext, SCARDHANDLE* hHandle)
{
UINT32 length;
UINT32 status;
status = handle_RedirContextRef(smartcard, irp, redirect, hContext);
status = handle_RedirContextRef(smartcard, irp, hContext);
if (status)
return status;
/* Use stored card handle. */
if (redirect & 0x02)
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirHandleRef no handle provided, using stored handle\n");
*hHandle = smartcard->hCard;
return 0;
}
if (Stream_GetRemainingLength(irp->input) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirHandleRef is too short: Actual: %d, Expected: %d\n",
@@ -376,7 +267,7 @@ static UINT32 handle_RedirHandleRef(SMARTCARD_DEVICE* smartcard, IRP* irp,
return SCARD_F_INTERNAL_ERROR;
}
if (Stream_GetRemainingLength(irp->input) < length)
if ((Stream_GetRemainingLength(irp->input) < length) || (!length))
{
WLog_Print(smartcard->log, WLOG_WARN, "RedirHandleRef is too short: Actual: %d, Expected: %d\n",
(int) Stream_GetRemainingLength(irp->input), length);
@@ -599,35 +490,6 @@ static void smartcard_input_repos(IRP* irp, UINT32 read)
Stream_Seek(irp->input, add);
}
static UINT32 smartcard_input_reader_name(IRP* irp, char** dest, BOOL wide)
{
UINT32 dataLength;
assert(irp);
assert(dest);
if (Stream_GetRemainingLength(irp->input) < 12)
{
DEBUG_WARN("length violation %d [%d]", 12,
Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Seek(irp->input, 8);
Stream_Read_UINT32(irp->input, dataLength);
if (Stream_GetRemainingLength(irp->input) < dataLength)
{
DEBUG_WARN("length violation %d [%d]", dataLength,
Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
smartcard_input_repos(irp, smartcard_input_string(irp, dest, dataLength, wide));
return 0;
}
static UINT32 handle_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 status;
@@ -657,16 +519,15 @@ static UINT32 handle_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_ReleaseContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
UINT32 status;
SCARDCONTEXT hContext = -1;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
return status;
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
return status;
@@ -681,16 +542,15 @@ static UINT32 handle_ReleaseContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_IsValidContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
UINT32 status;
SCARDCONTEXT hContext;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
return status;
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
return status;
@@ -704,7 +564,6 @@ static UINT32 handle_IsValidContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
{
int redirect = 0;
UINT32 status;
SCARDCONTEXT hContext;
DWORD dwReaders;
@@ -713,7 +572,7 @@ static UINT32 handle_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wid
int elemLength, dataLength;
int pos, poslen1, poslen2, allowed_pos;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
goto finish;
@@ -723,7 +582,7 @@ static UINT32 handle_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wid
if (status)
goto finish;
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
goto finish;
@@ -802,14 +661,13 @@ static UINT32 handle_GetStatusChange(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL
{
UINT32 i;
LONG status;
int redirect = 0;
SCARDCONTEXT hContext;
GetStatusChangeA_Call call;
ReaderStateA* readerState = NULL;
LPSCARD_READERSTATEA rgReaderState = NULL;
LPSCARD_READERSTATEA rgReaderStates = NULL;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
goto finish;
@@ -825,10 +683,10 @@ static UINT32 handle_GetStatusChange(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL
Stream_Read_UINT32(irp->input, call.dwTimeOut); /* dwTimeOut (4 bytes) */
Stream_Read_UINT32(irp->input, call.cReaders); /* cReaders (4 bytes) */
Stream_Seek_UINT32(irp->input); /* rgReaderStatesPointer (4 bytes) */
Stream_Seek_UINT32(irp->input); /* rgReaderStatesNdrPtr (4 bytes) */
/* Get context */
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
goto finish;
@@ -965,16 +823,15 @@ finish:
static UINT32 handle_Cancel(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
LONG status;
SCARDCONTEXT hContext;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
return status;
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
return status;
@@ -986,48 +843,18 @@ static UINT32 handle_Cancel(SMARTCARD_DEVICE* smartcard, IRP* irp)
return status;
}
static UINT32 handle_Connect(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
UINT32 handle_ConnectA(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
int redirect = 0;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
ConnectA_Call call;
Connect_Return ret;
call.szReader = NULL;
call.Common.Context.pbContext = (BYTE*) &hContext;
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_Seek_UINT32(irp->input); /* szReaderPointer (4 bytes) */
status = handle_Context(smartcard, irp, &redirect);
if (status)
goto finish;
if (Stream_GetRemainingLength(irp->input) < 8)
{
DEBUG_WARN("Length violation %d [%d]", 8,
Stream_GetRemainingLength(irp->input));
status = SCARD_F_INTERNAL_ERROR;
goto finish;
}
Stream_Read_UINT32(irp->input, call.Common.dwShareMode); /* dwShareMode (4 bytes) */
Stream_Read_UINT32(irp->input, call.Common.dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
status = smartcard_input_reader_name(irp, (char**) &call.szReader, wide);
if (status)
goto finish;
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = smartcard_unpack_connect_a_call(smartcard, irp->input, &call);
if (status)
goto finish;
@@ -1061,16 +888,53 @@ finish:
return status;
}
UINT32 handle_ConnectW(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
ConnectW_Call call;
Connect_Return ret;
call.szReader = NULL;
call.Common.Context.pbContext = (BYTE*) &hContext;
status = smartcard_unpack_connect_w_call(smartcard, irp->input, &call);
if (status)
goto finish;
status = SCardConnectW(hContext, (WCHAR*) call.szReader, (DWORD) call.Common.dwShareMode,
(DWORD) call.Common.dwPreferredProtocols, &hCard, (DWORD*) &ret.dwActiveProtocol);
smartcard->hCard = hCard;
Stream_Write_UINT32(irp->output, 0x00000000);
Stream_Write_UINT32(irp->output, 0x00000000);
Stream_Write_UINT32(irp->output, 0x00000004);
Stream_Write_UINT32(irp->output, 0x016Cff34);
Stream_Write_UINT32(irp->output, ret.dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
Stream_Write_UINT32(irp->output, 0x00000004);
Stream_Write_UINT32(irp->output, hCard);
smartcard_output_alignment(irp, 8);
finish:
if (call.szReader)
free(call.szReader);
return status;
}
static UINT32 handle_Reconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
LONG status;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
Reconnect_Call call;
Reconnect_Return ret;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
return status;
@@ -1086,7 +950,7 @@ static UINT32 handle_Reconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
Stream_Read_UINT32(irp->input, call.dwInitialization); /* dwInitialization (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
return status;
@@ -1109,12 +973,11 @@ static UINT32 handle_Reconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_Disconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
int redirect = 0;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
HCardAndDisposition_Call call;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
return status;
@@ -1128,7 +991,7 @@ static UINT32 handle_Disconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.dwDisposition); /* dwDisposition (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
return status;
@@ -1151,12 +1014,11 @@ static UINT32 handle_Disconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_BeginTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
int redirect = 0;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
HCardAndDisposition_Call call;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
return status;
@@ -1170,7 +1032,7 @@ static UINT32 handle_BeginTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.dwDisposition); /* dwDisposition (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
return status;
@@ -1190,13 +1052,12 @@ static UINT32 handle_BeginTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_EndTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
LONG status;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
HCardAndDisposition_Call call;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
return status;
@@ -1210,7 +1071,7 @@ static UINT32 handle_EndTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.dwDisposition); /* dwDisposition (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
return status;
@@ -1231,7 +1092,6 @@ static UINT32 handle_EndTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
int redirect = 0;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
State_Call call;
@@ -1240,7 +1100,7 @@ static UINT32 handle_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
char* readerName = NULL;
BYTE atr[SCARD_ATR_LENGTH];
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
goto finish;
@@ -1256,7 +1116,7 @@ static UINT32 handle_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
Stream_Read_UINT32(irp->input, call.cbAtrLen); /* cbAtrLen (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
goto finish;
@@ -1303,7 +1163,6 @@ finish:
static DWORD handle_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
{
int redirect = 0;
LONG status;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
@@ -1315,7 +1174,7 @@ static DWORD handle_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
UINT32 dataLength = 0;
int pos, poslen1, poslen2;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
goto finish;
@@ -1332,7 +1191,7 @@ static DWORD handle_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
Stream_Read_UINT32(irp->input, readerLen);
Stream_Read_UINT32(irp->input, atrLen);
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
goto finish;
@@ -1397,7 +1256,6 @@ finish:
static UINT32 handle_Transmit(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
int redirect = 0;
LONG status;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
@@ -1421,7 +1279,7 @@ static UINT32 handle_Transmit(SMARTCARD_DEVICE* smartcard, IRP* irp)
ioSendPci.v = NULL;
ioRecvPci.v = NULL;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
goto finish;
@@ -1447,7 +1305,8 @@ static UINT32 handle_Transmit(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, recvBufferIsNULL);
Stream_Read_UINT32(irp->input, cbRecvLength);
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
goto finish;
@@ -1638,7 +1497,6 @@ static UINT32 handle_Control(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
UINT32 length;
int redirect = 0;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
UINT32 controlFunction;
@@ -1646,7 +1504,7 @@ static UINT32 handle_Control(SMARTCARD_DEVICE* smartcard, IRP* irp)
Control_Return ret;
UINT32 pvInBufferPointer;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
goto finish;
@@ -1666,7 +1524,7 @@ static UINT32 handle_Control(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
Stream_Read_UINT32(irp->input, call.cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
goto finish;
@@ -1745,13 +1603,12 @@ static UINT32 handle_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
LONG status;
DWORD cbAttrLen;
int redirect = 0;
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
GetAttrib_Call call;
GetAttrib_Return ret;
status = handle_CardHandle(smartcard, irp, &redirect);
status = handle_CardHandle(smartcard, irp);
if (status)
return status;
@@ -1767,7 +1624,7 @@ static UINT32 handle_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, call.fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
Stream_Read_UINT32(irp->input, call.cbAttrLen); /* cbAttrLen (4 bytes) */
status = handle_RedirHandleRef(smartcard, irp, redirect, &hContext, &hCard);
status = handle_RedirHandleRef(smartcard, irp, &hContext, &hCard);
if (status)
return status;
@@ -1864,7 +1721,6 @@ static UINT32 handle_AccessStartedEvent(SMARTCARD_DEVICE* smartcard, IRP* irp)
static UINT32 handle_LocateCardsByATR(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
{
int redirect = 0;
LONG status;
UINT32 i, j, k;
SCARDCONTEXT hContext;
@@ -1876,7 +1732,7 @@ static UINT32 handle_LocateCardsByATR(SMARTCARD_DEVICE* smartcard, IRP* irp, BOO
SCARD_ATRMASK* curAtr = NULL;
SCARD_ATRMASK* pAtrMasks = NULL;
status = handle_Context(smartcard, irp, &redirect);
status = handle_Context(smartcard, irp);
if (status)
return status;
@@ -1889,7 +1745,7 @@ static UINT32 handle_LocateCardsByATR(SMARTCARD_DEVICE* smartcard, IRP* irp, BOO
}
Stream_Seek(irp->input, 4);
status = handle_RedirContextRef(smartcard, irp, redirect, &hContext);
status = handle_RedirContextRef(smartcard, irp, &hContext);
if (status)
return status;
@@ -2017,23 +1873,19 @@ finish:
void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 pos;
UINT32 result;
UINT32 status;
UINT32 result_pos;
UINT32 ioControlCode;
UINT32 outputBufferLength;
UINT32 inputBufferLength;
UINT32 ioControlCode;
UINT32 stream_len;
UINT32 irp_result_pos;
UINT32 output_len_pos;
const UINT32 header_lengths = 16;
UINT32 objectBufferLength;
/* Device Control Request */
/* MS-RPCE, Sections 2.2.6.1 and 2.2.6.2. */
if (Stream_GetRemainingLength(irp->input) < 32)
{
DEBUG_WARN("Invalid IRP of length %d received, ignoring.",
Stream_GetRemainingLength(irp->input));
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return;
}
@@ -2042,57 +1894,47 @@ void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
Stream_Read_UINT32(irp->input, ioControlCode); /* IoControlCode (4 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
/* Ensure, that this package is fully available. */
if (Stream_GetRemainingLength(irp->input) < inputBufferLength)
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
{
DEBUG_WARN("Invalid IRP of length %d received, expected %d, ignoring.",
Stream_GetRemainingLength(irp->input), inputBufferLength);
WLog_Print(smartcard->log, WLOG_WARN,
"InputBufferLength mismatch: Actual: %d Expected: %d\n",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
return;
}
WLog_Print(smartcard->log, WLOG_WARN, "ioControlCode: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode), ioControlCode);
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
{
fprintf(stderr, "Input buffer length mismatch: Actual: %d Expected: %d\n",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
return;
}
if (ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT)
{
status = handle_CommonTypeHeader(smartcard, irp);
status = smartcard_unpack_common_type_header(smartcard, irp->input);
if (status)
return;
status = handle_PrivateTypeHeader(smartcard, irp);
status = smartcard_unpack_private_type_header(smartcard, irp->input);
if (status)
return;
}
/* [MS-RDPESC] 3.2.5.1 Sending Outgoing Messages */
/**
* [MS-RDPESC] 3.2.5.1: Sending Outgoing Messages:
* the output buffer length SHOULD be set to 2048
*
* Since it's a SHOULD and not a MUST, we don't care
* about it, but we still reserve at least 2048 bytes.
*/
Stream_EnsureRemainingCapacity(irp->output, 2048);
irp_result_pos = Stream_GetPosition(irp->output);
/* Device Control Response */
Stream_Seek_UINT32(irp->output); /* OutputBufferLength (4 bytes) */
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength (4 bytes) */
Stream_Seek(irp->output, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
Stream_Seek(irp->output, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
/* [MS-RPCE] 2.2.6.1 */
Stream_Write_UINT8(irp->output, 1); /* Version (1 byte) */
Stream_Write_UINT8(irp->output, 0x10); /* Endianness (1 byte) */
Stream_Write_UINT16(irp->output, 8); /* CommonHeaderLength (2 bytes) */
Stream_Write_UINT32(irp->output, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
output_len_pos = Stream_GetPosition(irp->output);
Stream_Seek(irp->output, 4); /* ObjectBufferLength (4 bytes) */
Stream_Write_UINT32(irp->output, 0x0); /* Filler (4 bytes), should be 0x00000000 */
result_pos = Stream_GetPosition(irp->output);
Stream_Seek(irp->output, 4); /* Result (4 bytes) */
Stream_Seek_UINT32(irp->output); /* Result (4 bytes) */
switch (ioControlCode)
{
@@ -2193,11 +2035,11 @@ void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
break;
case SCARD_IOCTL_CONNECTA:
result = handle_Connect(smartcard, irp, 0);
result = handle_ConnectA(smartcard, irp);
break;
case SCARD_IOCTL_CONNECTW:
result = handle_Connect(smartcard, irp, 1);
result = handle_ConnectW(smartcard, irp);
break;
case SCARD_IOCTL_RECONNECT:
@@ -2290,44 +2132,32 @@ void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
default:
result = STATUS_UNSUCCESSFUL;
DEBUG_WARN("scard unknown ioctl 0x%x [%d]\n",
ioControlCode, inputBufferLength);
break;
}
/* look for NTSTATUS errors */
if ((result & 0xC0000000) == 0xC0000000)
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT))
{
DEBUG_WARN("scard processing error 0x%08X", result);
Stream_SetPosition(irp->output, 0);
irp->IoStatus = result;
irp->Complete(irp);
return;
WLog_Print(smartcard->log, WLOG_WARN,
"IRP failure: ioControlCode: %s (0x%08X), status: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode), ioControlCode,
SCardGetErrorString(result), result);
}
/* per Ludovic Rousseau, map different usage of this particular
* error code between pcsc-lite & windows */
if (result == 0x8010001F)
result = 0x80100022;
Stream_SealLength(irp->output);
outputBufferLength = Stream_Length(irp->output) - RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4;
objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
/* handle response packet */
pos = Stream_GetPosition(irp->output);
stream_len = pos - irp_result_pos - 4; /* Value of OutputBufferLength */
Stream_SetPosition(irp->output, irp_result_pos);
Stream_Write_UINT32(irp->output, stream_len);
/* Device Control Response */
Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */
Stream_SetPosition(irp->output, output_len_pos);
/* Remove the effect of the MS-RPCE Common Type Header and Private
* Header (Sections 2.2.6.1 and 2.2.6.2).
*/
Stream_Write_UINT32(irp->output, stream_len - header_lengths);
smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */
smartcard_pack_private_type_header(smartcard, irp->output, objectBufferLength); /* PrivateTypeHeader (8 bytes) */
Stream_SetPosition(irp->output, result_pos);
Stream_Write_UINT32(irp->output, result);
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
Stream_SetPosition(irp->output, pos);
Stream_SetPosition(irp->output, Stream_Length(irp->output));
irp->IoStatus = 0;
irp->Complete(irp);
}

View File

@@ -26,6 +26,103 @@
#include "smartcard_pack.h"
UINT32 smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
{
UINT8 version;
UINT32 filler;
UINT8 endianness;
UINT16 commonHeaderLength;
if (Stream_GetRemainingLength(s) < 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "CommonTypeHeader is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
/* Process CommonTypeHeader */
Stream_Read_UINT8(s, version); /* Version (1 byte) */
Stream_Read_UINT8(s, endianness); /* Endianness (1 byte) */
Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0xCCCCCCCC */
if (version != 1)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader Version %d", version);
return SCARD_F_INTERNAL_ERROR;
}
if (endianness != 0x10)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %d", endianness);
return SCARD_F_INTERNAL_ERROR;
}
if (commonHeaderLength != 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %d", commonHeaderLength);
return SCARD_F_INTERNAL_ERROR;
}
if (filler != 0xCCCCCCCC)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08X", filler);
return SCARD_F_INTERNAL_ERROR;
}
return 0;
}
UINT32 smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
{
Stream_Write_UINT8(s, 1); /* Version (1 byte) */
Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */
Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */
Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
return 0;
}
UINT32 smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
{
UINT32 filler;
UINT32 objectBufferLength;
if (Stream_GetRemainingLength(s) < 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "PrivateTypeHeader is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0x00000000 */
if (filler != 0x00000000)
{
WLog_Print(smartcard->log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08X", filler);
return SCARD_F_INTERNAL_ERROR;
}
if (objectBufferLength != Stream_GetRemainingLength(s))
{
WLog_Print(smartcard->log, WLOG_WARN, "PrivateTypeHeader ObjectBufferLength mismatch: Actual: %d, Expected: %d",
(int) objectBufferLength, Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
return 0;
}
UINT32 smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 objectBufferLength)
{
Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */
return 0;
}
UINT32 smartcard_unpack_establish_context_call(SMARTCARD_DEVICE* smartcard, wStream* s, EstablishContext_Call* call)
{
if (Stream_GetRemainingLength(s) < 4)
@@ -75,3 +172,182 @@ UINT32 smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream*
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_redir_scard_context(SMARTCARD_DEVICE* smartcard, wStream* s, REDIR_SCARDCONTEXT* context)
{
if (Stream_GetRemainingLength(s) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
if ((Stream_GetRemainingLength(s) < context->cbContext) || (!context->cbContext))
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d",
(int) Stream_GetRemainingLength(s), context->cbContext);
return SCARD_F_INTERNAL_ERROR;
}
Stream_Seek_UINT32(s); /* pbContextNdrPtr (4 bytes) */
if (context->cbContext > Stream_GetRemainingLength(s))
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too long: Actual: %d, Expected: %d",
(int) Stream_GetRemainingLength(s), context->cbContext);
return SCARD_F_INTERNAL_ERROR;
}
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_redir_scard_context_ref(SMARTCARD_DEVICE* smartcard, wStream* s, REDIR_SCARDCONTEXT* context)
{
UINT32 length;
ULONG_PTR contextVal;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d\n",
(int) Stream_GetRemainingLength(s), 4);
return SCARD_F_INTERNAL_ERROR;
}
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
if ((length != 4) && (length != 8))
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT length is not 4 or 8: %d\n", length);
return SCARD_F_INTERNAL_ERROR;
}
if ((Stream_GetRemainingLength(s) < length) || (!length))
{
WLog_Print(smartcard->log, WLOG_WARN, "REDIR_SCARDCONTEXT is too short: Actual: %d, Expected: %d\n",
(int) Stream_GetRemainingLength(s), length);
return SCARD_F_INTERNAL_ERROR;
}
if (length > 4)
Stream_Read_UINT64(s, contextVal);
else
Stream_Read_UINT32(s, contextVal);
*((ULONG_PTR*) context->pbContext) = contextVal;
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_connect_common(SMARTCARD_DEVICE* smartcard, wStream* s, Connect_Common* common)
{
UINT32 status;
if (Stream_GetRemainingLength(s) < 8)
{
WLog_Print(smartcard->log, WLOG_WARN, "Connect_Common is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
status = smartcard_unpack_redir_scard_context(smartcard, s, &(common->Context));
if (status)
return status;
Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_read_offset_align(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 alignment)
{
UINT32 pad;
UINT32 offset;
offset = Stream_GetPosition(s);
pad = offset;
offset = (offset + alignment - 1) & ~(alignment - 1);
pad = offset - pad;
Stream_Seek(s, pad);
return pad;
}
UINT32 smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectA_Call* call)
{
UINT32 status;
UINT32 count;
call->szReader = NULL;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "ConnectA_Call is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Seek_UINT32(s); /* szReaderPointer (4 bytes) */
status = smartcard_unpack_connect_common(smartcard, s, &(call->Common));
if (status)
return status;
/* szReader */
Stream_Seek_UINT32(s); /* NdrMaxCount (4 bytes) */
Stream_Seek_UINT32(s); /* NdrOffset (4 bytes) */
Stream_Read_UINT32(s, count); /* NdrActualCount (4 bytes) */
call->szReader = malloc(count + 1);
Stream_Read(s, call->szReader, count);
smartcard_unpack_read_offset_align(smartcard, s, 4);
call->szReader[count] = '\0';
smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.Context));
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectW_Call* call)
{
UINT32 status;
UINT32 count;
call->szReader = NULL;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "ConnectA_Call is too short: %d",
(int) Stream_GetRemainingLength(s));
return SCARD_F_INTERNAL_ERROR;
}
Stream_Seek_UINT32(s); /* szReaderPointer (4 bytes) */
status = smartcard_unpack_connect_common(smartcard, s, &(call->Common));
if (status)
return status;
/* szReader */
Stream_Seek_UINT32(s); /* NdrMaxCount (4 bytes) */
Stream_Seek_UINT32(s); /* NdrOffset (4 bytes) */
Stream_Read_UINT32(s, count); /* NdrActualCount (4 bytes) */
call->szReader = malloc((count + 1) * 2);
Stream_Read(s, call->szReader, (count * 2));
smartcard_unpack_read_offset_align(smartcard, s, 4);
call->szReader[count] = '\0';
smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.Context));
return SCARD_S_SUCCESS;
}

View File

@@ -417,7 +417,20 @@ typedef struct _WriteCacheW_Call
WriteCache_Common Common;
} WriteCacheW_Call;
#define SMARTCARD_COMMON_TYPE_HEADER_LENGTH 8
#define SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH 8
UINT32 smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
UINT32 smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
UINT32 smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
UINT32 smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 objectBufferLength);
UINT32 smartcard_unpack_establish_context_call(SMARTCARD_DEVICE* smartcard, wStream* s, EstablishContext_Call* call);
UINT32 smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s, ListReaders_Call* call);
UINT32 smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectA_Call* call);
UINT32 smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectW_Call* call);
#endif /* FREERDP_CHANNEL_SMARTCARD_CLIENT_PACK_H */

View File

@@ -34,6 +34,9 @@
#include <freerdp/freerdp.h>
#include <freerdp/utils/list.h>
#define RDPDR_DEVICE_IO_REQUEST_LENGTH 24
#define RDPDR_DEVICE_IO_RESPONSE_LENGTH 16
/* RDPDR_HEADER.Component */
enum RDPDR_CTYP
{

View File

@@ -30,6 +30,23 @@
static HMODULE g_PCSCModule = NULL;
static PCSCFunctionTable g_PCSC = { 0 };
LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
{
/**
* pcsc-lite returns SCARD_E_UNEXPECTED when it
* should return SCARD_E_UNSUPPORTED_FEATURE.
*
* Additionally, the pcsc-lite headers incorrectly
* define SCARD_E_UNSUPPORTED_FEATURE to 0x8010001F,
* when the real value should be 0x80100022.
*/
if (errorCode == SCARD_E_UNEXPECTED)
errorCode = SCARD_E_UNSUPPORTED_FEATURE;
return errorCode;
}
/**
* Standard Windows Smart Card API (PCSC)
*/
@@ -37,48 +54,62 @@ static PCSCFunctionTable g_PCSC = { 0 };
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardEstablishContext)
{
return g_PCSC.pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
status = g_PCSC.pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardReleaseContext)
{
return g_PCSC.pfnSCardReleaseContext(hContext);
status = g_PCSC.pfnSCardReleaseContext(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardIsValidContext)
{
return g_PCSC.pfnSCardIsValidContext(hContext);
status = g_PCSC.pfnSCardIsValidContext(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext,
LPSTR mszGroups, LPDWORD pcchGroups)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardListReaderGroups)
{
return g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, pcchGroups);
status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, pcchGroups);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext,
LPWSTR mszGroups, LPDWORD pcchGroups)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardListReaderGroups)
{
mszGroups = NULL;
@@ -86,26 +117,32 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext,
/* FIXME: unicode conversion */
return g_PCSC.pfnSCardListReaderGroups(hContext, (LPSTR) mszGroups, pcchGroups);
status = g_PCSC.pfnSCardListReaderGroups(hContext, (LPSTR) mszGroups, pcchGroups);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext,
LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardListReaders)
{
return g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
LPCWSTR mszGroups, LPWSTR mszReaders, LPDWORD pcchReaders)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardListReaders)
{
mszGroups = NULL;
@@ -115,10 +152,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
/* FIXME: unicode conversion */
return g_PCSC.pfnSCardListReaders(hContext, (LPSTR) mszGroups, (LPSTR) mszReaders, pcchReaders);
status = g_PCSC.pfnSCardListReaders(hContext, (LPSTR) mszGroups, (LPSTR) mszReaders, pcchReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardListCardsA(SCARDCONTEXT hContext,
@@ -273,12 +311,15 @@ WINSCARDAPI LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardFreeMemory)
{
return g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI HANDLE WINAPI PCSC_SCardAccessStartedEvent(void)
@@ -318,17 +359,22 @@ WINSCARDAPI LONG WINAPI PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardGetStatusChange)
{
return g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardGetStatusChange)
{
SCARD_READERSTATEA rgReaderStatesA;
@@ -337,39 +383,48 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext,
ZeroMemory(&rgReaderStatesA, sizeof(SCARD_READERSTATEA));
/* FIXME: unicode conversion */
return g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, &rgReaderStatesA, cReaders);
status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, &rgReaderStatesA, cReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardCancel)
{
return g_PCSC.pfnSCardCancel(hContext);
status = g_PCSC.pfnSCardCancel(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardConnect)
{
return g_PCSC.pfnSCardConnect(hContext, szReader,
status = g_PCSC.pfnSCardConnect(hContext, szReader,
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardConnect)
{
LONG status;
@@ -380,55 +435,68 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
status = g_PCSC.pfnSCardConnect(hContext, szReaderA,
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
free(szReaderA);
return status;
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardReconnect)
{
return g_PCSC.pfnSCardReconnect(hCard, dwShareMode,
status = g_PCSC.pfnSCardReconnect(hCard, dwShareMode,
dwPreferredProtocols, dwInitialization, pdwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardDisconnect)
{
return g_PCSC.pfnSCardDisconnect(hCard, dwDisposition);
status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardBeginTransaction)
{
return g_PCSC.pfnSCardBeginTransaction(hCard);
status = g_PCSC.pfnSCardBeginTransaction(hCard);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardEndTransaction)
{
return g_PCSC.pfnSCardEndTransaction(hCard, dwDisposition);
status = g_PCSC.pfnSCardEndTransaction(hCard, dwDisposition);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
@@ -446,19 +514,24 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard,
LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardStatus)
{
return g_PCSC.pfnSCardStatus(hCard, mszReaderNames, pcchReaderLen,
status = g_PCSC.pfnSCardStatus(hCard, mszReaderNames, pcchReaderLen,
pdwState, pdwProtocol, pbAtr, pcbAtrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardStatus)
{
mszReaderNames = NULL;
@@ -466,24 +539,28 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
/* FIXME: unicode conversion */
return g_PCSC.pfnSCardStatus(hCard, (LPSTR) mszReaderNames, pcchReaderLen,
status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) mszReaderNames, pcchReaderLen,
pdwState, pdwProtocol, pbAtr, pcbAtrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardTransmit)
{
return g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer,
status = g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer,
cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
@@ -495,34 +572,43 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
DWORD dwControlCode, LPCVOID lpInBuffer, DWORD cbInBufferSize,
LPVOID lpOutBuffer, DWORD cbOutBufferSize, LPDWORD lpBytesReturned)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardControl)
{
return g_PCSC.pfnSCardControl(hCard,
status = g_PCSC.pfnSCardControl(hCard,
dwControlCode, lpInBuffer, cbInBufferSize,
lpOutBuffer, cbOutBufferSize, lpBytesReturned);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardGetAttrib)
{
return g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
status = g_PCSC.pfnSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{
LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardSetAttrib)
{
return g_PCSC.pfnSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
status = g_PCSC.pfnSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
}
return 0;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)