From 761cc053e219f0c0ccf30fc7f860021c7d187ed9 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Thu, 11 Sep 2014 11:54:46 +0000 Subject: [PATCH] Fixes a bug with Windows Server 2012 r2 and smartcard redirection were the RDPDR channel is shutdown by server. The RDPDR channel is shutdown by server when responses from abdonend iorequests are received on a reinitialized RDPDR channel. This fix adds epochs for RDPDR channel and tags iorequest to specific epoch to handle abdonend iorequest. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/rdesktop/trunk@1836 423420c4-83ab-492f-b58f-81f9feb106b5 --- proto.h | 2 +- rdesktop.c | 12 +++++++----- rdpdr.c | 4 +++- scard.c | 15 ++++++++++++--- scard.h | 1 + 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/proto.h b/proto.h index 1451b19..3bb02a5 100644 --- a/proto.h +++ b/proto.h @@ -352,7 +352,7 @@ unsigned int seamless_send_persistent(RD_BOOL); void scard_lock(int lock); void scard_unlock(int lock); int scard_enum_devices(uint32 * id, char *optarg); -void scardSetInfo(uint32 device, uint32 id, uint32 bytes_out); +void scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out); void scard_reset_state(); /* *INDENT-OFF* */ diff --git a/rdesktop.c b/rdesktop.c index 4e887b4..e2292b8 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -557,8 +557,7 @@ main(int argc, char *argv[]) /* setup default flags for TS_INFO_PACKET */ flags = RDP_INFO_MOUSE | RDP_INFO_DISABLECTRLALTDEL - | RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL - | RDP_INFO_ENABLEWINDOWSKEY; + | RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL | RDP_INFO_ENABLEWINDOWSKEY; prompt_password = False; g_seamless_spawn_cmd[0] = domain[0] = g_password[0] = shell[0] = directory[0] = 0; @@ -790,15 +789,18 @@ main(int argc, char *argv[]) } else if (str_startswith(optarg, "b")) /* broadband */ { - g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER; + g_rdp5_performanceflags = + RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER; } else if (str_startswith(optarg, "l")) /* lan */ { - g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | RDP5_DISABLE_NOTHING; + g_rdp5_performanceflags = + RDP5_NO_CURSOR_SHADOW | RDP5_DISABLE_NOTHING; } else { - g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | strtol(optarg, NULL, 16); + g_rdp5_performanceflags = + RDP5_NO_CURSOR_SHADOW | strtol(optarg, NULL, 16); } break; diff --git a/rdpdr.c b/rdpdr.c index 66ab141..89623ab 100644 --- a/rdpdr.c +++ b/rdpdr.c @@ -68,6 +68,7 @@ extern FILEINFO g_fileinfo[]; extern RD_BOOL g_notify_stamp; static VCHANNEL *rdpdr_channel; +static uint32 g_epoch; /* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */ RD_NTHANDLE g_min_timeout_fd; @@ -695,7 +696,7 @@ rdpdr_process_irp(STREAM s) out.size = sizeof(buffer); #ifdef WITH_SCARD - scardSetInfo(device, id, bytes_out + 0x14); + scardSetInfo(g_epoch, device, id, bytes_out + 0x14); #endif status = fns->device_control(file, request, s, &out); result = buffer_len = out.p - out.data; @@ -823,6 +824,7 @@ rdpdr_process(STREAM s) if server version is < 12 */ if (vmin < 0x000c) g_client_id = 0x815ed39d; /* IP address (use 127.0.0.1) 0x815ed39d */ + g_epoch++; rdpdr_send_client_announce_reply(); rdpdr_send_client_name_request(); diff --git a/scard.c b/scard.c index 948cd70..4fbcf46 100644 --- a/scard.c +++ b/scard.c @@ -63,7 +63,7 @@ static pthread_mutex_t **scard_mutex = NULL; -static uint32 curDevice = 0, curId = 0, curBytesOut = 0; +static uint32 curEpoch = 0, curDevice = 0, curId = 0, curBytesOut = 0; static PSCNameMapRec nameMapList = NULL; static int nameMapCount = 0; @@ -87,11 +87,12 @@ static void *queue_handler_function(void *data); #endif /* MAKE_PROTO */ void -scardSetInfo(uint32 device, uint32 id, uint32 bytes_out) +scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out) { curDevice = device; curId = id; curBytesOut = bytes_out; + curEpoch = epoch; } #ifndef MAKE_PROTO @@ -2456,6 +2457,7 @@ SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out) data->memHandle = lcHandle; data->device = curDevice; data->id = curId; + data->epoch = curEpoch; data->handle = handle; data->request = request; data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE); @@ -2527,7 +2529,14 @@ SC_deviceControl(PSCThreadData data) size_t buffer_len = 0; scard_device_control(data->handle, data->request, data->in, data->out); buffer_len = (size_t) data->out->p - (size_t) data->out->data; - rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len); + + /* if iorequest belongs to another epoch, don't send response + back to server due to it's considered as abdonend. + */ + if (data->epoch == curEpoch) + rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, + buffer_len); + SC_destroyThreadData(data); } diff --git a/scard.h b/scard.h index 4c8cd66..d582122 100644 --- a/scard.h +++ b/scard.h @@ -154,6 +154,7 @@ typedef struct _TSCThreadData { uint32 device; uint32 id; + uint32 epoch; RD_NTHANDLE handle; uint32 request; STREAM in;