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
This commit is contained in:
Henrik Andersson 2014-09-11 11:54:46 +00:00
parent fffb479e0c
commit 761cc053e2
5 changed files with 24 additions and 10 deletions

View File

@ -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* */

View File

@ -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;

View File

@ -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();

15
scard.c
View File

@ -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);
}

View File

@ -154,6 +154,7 @@ typedef struct _TSCThreadData
{
uint32 device;
uint32 id;
uint32 epoch;
RD_NTHANDLE handle;
uint32 request;
STREAM in;