diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 0af4cfb79..7e49a6c0f 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -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; diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index cf542957c..47777dae5 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -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; diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index 809122ab2..374b6d283 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -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); } diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index 255024cdc..48a29510c 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -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; +} diff --git a/channels/smartcard/client/smartcard_pack.h b/channels/smartcard/client/smartcard_pack.h index 33c261a9c..5c5c8c5a9 100644 --- a/channels/smartcard/client/smartcard_pack.h +++ b/channels/smartcard/client/smartcard_pack.h @@ -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 */ diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index 87e758cda..38c470063 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -34,6 +34,9 @@ #include #include +#define RDPDR_DEVICE_IO_REQUEST_LENGTH 24 +#define RDPDR_DEVICE_IO_RESPONSE_LENGTH 16 + /* RDPDR_HEADER.Component */ enum RDPDR_CTYP { diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index adf5b75d3..b4b69e28c 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -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)