From f265c14499f258cab934ee114a4c99877a751d23 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 4 Dec 2013 15:40:55 -0800 Subject: [PATCH] chansrv: smartcard, work on getting MSTSC working --- sesman/chansrv/smartcard.c | 746 +++++++++++++++++--------------- sesman/chansrv/smartcard_pcsc.c | 204 +++++---- sesman/chansrv/smartcard_pcsc.h | 26 +- 3 files changed, 524 insertions(+), 452 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 4b2104a6..c6a36811 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -163,25 +164,25 @@ static int APP_CC scard_get_free_slot(void); #if 0 static void APP_CC scard_release_resources(void); #endif -static void APP_CC scard_send_EstablishContext(IRP* irp, int scope); -static void APP_CC scard_send_ReleaseContext(IRP* irp, tui32 context); +static void APP_CC scard_send_EstablishContext(IRP *irp, int scope); +static void APP_CC scard_send_ReleaseContext(IRP *irp, tui32 context); static void APP_CC scard_send_IsContextValid(IRP* irp, tui32 context); -static void APP_CC scard_send_ListReaders(IRP* irp, tui32 context, int wide); -static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, +static void APP_CC scard_send_ListReaders(IRP *irp, tui32 context, int wide); +static void APP_CC scard_send_GetStatusChange(IRP *irp, tui32 context, int wide, tui32 timeout, tui32 num_readers, - READER_STATE* rsa); -static void APP_CC scard_send_Connect(IRP* irp, tui32 context, int wide, - READER_STATE* rs); -static void APP_CC scard_send_Reconnect(IRP* irp, tui32 context, - tui32 sc_handle, READER_STATE* rs); -static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); -static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle, + READER_STATE *rsa); +static void APP_CC scard_send_Connect(IRP *irp, tui32 context, int wide, + READER_STATE *rs); +static void APP_CC scard_send_Reconnect(IRP *irp, tui32 context, + tui32 sc_handle, READER_STATE *rs); +static void APP_CC scard_send_BeginTransaction(IRP *irp, tui32 sc_handle); +static void APP_CC scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition); -static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle, +static void APP_CC scard_send_Status(IRP *irp, int wide, tui32 sc_handle, int cchReaderLen, int cbAtrLen); -static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context, +static void APP_CC scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, int dwDisposition); -static int APP_CC scard_send_Transmit(IRP* irp, tui32 sc_handle, +static int APP_CC scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, @@ -189,9 +190,9 @@ static int APP_CC scard_send_Transmit(IRP* irp, tui32 sc_handle, static int APP_CC scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, int send_bytes, int recv_bytes, int control_code); -static int APP_CC scard_send_Cancel(IRP* irp, tui32 context); -static int APP_CC scard_send_GetAttrib(IRP* irp, tui32 sc_handle, - READER_STATE* rs); +static int APP_CC scard_send_Cancel(IRP *irp, tui32 context); +static int APP_CC scard_send_GetAttrib(IRP *irp, tui32 sc_handle, + READER_STATE *rs); /****************************************************************************** ** local callbacks into this module ** @@ -937,14 +938,19 @@ scard_send_EstablishContext(IRP *irp, int scope) xstream_wr_u32_le(s, scope); /* Ioctl specific data */ xstream_wr_u32_le(s, 0); /* don't know what this is, */ /* but Win7 is sending it */ - /* get stream len */ - bytes = xstream_len(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_mark_end(s); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -952,12 +958,12 @@ scard_send_EstablishContext(IRP *irp, int scope) * Release a previously established Smart Card context *****************************************************************************/ static void APP_CC -scard_send_ReleaseContext(IRP* irp, tui32 context) +scard_send_ReleaseContext(IRP *irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.2 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -992,14 +998,18 @@ scard_send_ReleaseContext(IRP* irp, tui32 context) xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, context); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1007,12 +1017,12 @@ scard_send_ReleaseContext(IRP* irp, tui32 context) * Checks if a previously established context is still valid *****************************************************************************/ static void APP_CC -scard_send_IsContextValid(IRP* irp, tui32 context) +scard_send_IsContextValid(IRP *irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.3 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1045,14 +1055,18 @@ scard_send_IsContextValid(IRP* irp, tui32 context) xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, context); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1118,17 +1132,22 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) xstream_wr_u32_le(s, 0x00); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - //g_writeln("scard_send_ListReaders:"); - //g_hexdump(s->data, bytes); +#if 0 + g_writeln("scard_send_ListReaders:"); + g_hexdump(s->data, bytes); +#endif xstream_free(s); @@ -1215,7 +1234,7 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, return; } - s_push_layer(s, mcs_hdr, 4); /* set later */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00000004); out_uint32_le(s, 0x00020000); @@ -1342,58 +1361,54 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) return; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 20 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes dwShareMode - * u32 4 bytes dwPreferredProtocols - * xx bytes reader name - * u32 4 bytes context length (len) - * len bytes context - */ - - xstream_seek(s, 20); - xstream_wr_u32_le(s, rs->dwShareMode); - xstream_wr_u32_le(s, rs->dwPreferredProtocols); - - /* insert reader name */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, rs->dwShareMode); + out_uint32_le(s, rs->dwPreferredProtocols); num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, num_chars); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0x00000000); + out_uint32_le(s, num_chars + 2); if (wide) { for (index = 0; index < num_chars; index++) { - xstream_wr_u16_le(s, w_reader_name[index]); + out_uint16_le(s, w_reader_name[index]); } + out_uint16_le(s, 0); + out_uint16_le(s, 0); } else { for (index = 0; index < num_chars; index++) { - xstream_wr_u8(s, w_reader_name[index]); + out_uint8(s, w_reader_name[index]); } + out_uint8(s, 0); + out_uint8(s, 0); } align_s(s, 4); /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, 4); + out_uint32_le(s, context); + out_uint32_le(s, 0); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1409,13 +1424,13 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) * rs.init_type *****************************************************************************/ static void APP_CC -scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) +scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.15 */ /* see [MS-RDPESC] 3.1.4.36 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1456,14 +1471,18 @@ scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1494,32 +1513,38 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) return; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 36 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes len of sc_handle - * 4 bytes sc_handle - */ - - xstream_seek(s, 36); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00000002); /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, 4); + out_uint32_le(s, sc_handle); + out_uint32_le(s, 0x00000000); + + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1551,36 +1576,38 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) return; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 24 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes disposition - * 8 unused - * u32 4 bytes length of sc_handle - * 4 bytes sc_handle - */ - - xstream_seek(s, 24); - xstream_wr_u32_le(s, dwDisposition); - xstream_seek(s, 8); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, dwDisposition); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00000009); /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, 4); + out_uint32_le(s, sc_handle); + out_uint32_le(s, 0); + + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1613,42 +1640,55 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, log_error("scard_make_new_ioctl"); return; } - - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 28 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes reader len - * u32 4 bytes ATR len - * 8 bytes unused - * u32 4 bytes len of sc_handle - * 4 bytes sc_handle - * 4 bytes unused - */ - - xstream_seek(s, 28); - xstream_wr_u32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ - xstream_wr_u32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ - xstream_seek(s, 8); - +/* + 30 00 00 00 + 00 00 00 00 + 04 00 00 00 + 00 00 02 00 + 04 00 00 00 + 04 00 02 00 + 01 00 00 00 dwReaderLen + 00 00 00 00 dwAtrLen + 40 00 00 00 + 04 00 00 00 + 07 00 00 00 + 04 00 00 00 + 09 00 00 00 hCard + 00 00 00 00 +*/ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ + out_uint32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ + out_uint32_le(s, 0x00000040); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00000007); /* insert sc_handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, 4); + out_uint32_le(s, sc_handle); + out_uint32_le(s, 0); - xstream_wr_u32_le(s, 0); + s_mark_end(s); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1680,40 +1720,41 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, return; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 24 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes disposition - * u32 4 bytes context len - * 4 bytes context - * u32 4 bytes length of sc_handle - * 4 bytes sc_handle - */ - - xstream_seek(s, 24); - xstream_wr_u32_le(s, dwDisposition); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, dwDisposition); /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, 4); + out_uint32_le(s, context); /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, 4); + out_uint32_le(s, sc_handle); + + out_uint32_le(s, 0x00000000); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } @@ -1722,15 +1763,15 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, * associated with a valid context. *****************************************************************************/ static int APP_CC -scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, +scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior) { /* see [MS-RDPESC] 2.2.2.19 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; int val; @@ -1776,21 +1817,84 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, * u32 4 bytes sc_handle */ - xstream_seek(s, 12); - xstream_wr_u32_le(s, 0); // map0 - xstream_seek(s, 4); - xstream_wr_u32_le(s, 0); // map1 + g_writeln("send_bytes %d", send_bytes); + g_writeln("recv_bytes %d", recv_bytes); + +#if 1 + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + //out_uint32_be(s, 0x58000000); + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x00000200); + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x04000200); + out_uint32_be(s, 0x01000000); + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x00000000); + + //out_uint32_be(s, 0x05000000); + out_uint32_le(s, send_bytes); + + out_uint32_be(s, 0x08000200); + out_uint32_be(s, 0x0c000200); + out_uint32_be(s, 0x00000000); + + //out_uint32_be(s, 0x02010000); + out_uint32_le(s, recv_bytes); + + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x05000000); + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x0b000000); + + //out_uint32_be(s, 0x05000000); + //out_uint32_be(s, 0x00b00704); + //out_uint32_be(s, 0x10000000); + out_uint32_le(s, send_bytes); + out_uint8p(s, send_data, send_bytes); + align_s(s, 4); + + out_uint32_be(s, 0x01000000); + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x00000000); +#else + + g_printf("send cbPciLength %d\n", send_ior->cbPciLength); + g_printf("send extra_bytes %d\n", send_ior->extra_bytes); + g_printf("recv cbPciLength %d\n", recv_ior->cbPciLength); + g_printf("recv extra_bytes %d\n", recv_ior->extra_bytes); + + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + + out_uint32_le(s, 4); + xstream_wr_u32_le(s, 0x00020000); /* map0 */ + + out_uint32_le(s, 4); + xstream_wr_u32_le(s, 0x00020004); /* map1 */ + xstream_wr_u32_le(s, send_ior->dwProtocol); - xstream_wr_u32_le(s, send_ior->cbPciLength); + xstream_wr_u32_le(s, send_ior->cbPciLength - 8); + val = send_ior->extra_bytes > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); // map2 + xstream_wr_u32_le(s, val); /* map2 */ + xstream_wr_u32_le(s, send_bytes); - val = send_bytes > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); // map3 - val = recv_ior->cbPciLength > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); // map 4 + + val = send_bytes > 0 ? 0x00020008 : 0; + xstream_wr_u32_le(s, val); /* map3 */ + + val = recv_ior->cbPciLength > 0 ? 0x0002000c : 0; + xstream_wr_u32_le(s, val); /* map 4 */ + xstream_wr_u32_le(s, 0); // map5 xstream_wr_u32_le(s, recv_bytes); + + /* map0 */ + out_uint32_le(s, 4); + out_uint32_le(s, 5); + + /* map1 */ xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); @@ -1804,29 +1908,46 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, { xstream_wr_u32_le(s, send_bytes); out_uint8a(s, send_data, send_bytes); + align_s(s, 4); } if (recv_ior->cbPciLength > 0) { + /* map4 */ xstream_wr_u32_le(s, recv_ior->dwProtocol); xstream_wr_u32_le(s, recv_ior->cbPciLength); val = recv_ior->extra_bytes > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); + xstream_wr_u32_le(s, val); /* map6*/ if (val) { xstream_wr_u32_le(s, recv_ior->extra_bytes); out_uint8a(s, recv_ior->extra_data, recv_ior->extra_bytes); } } +#endif + + s_mark_end(s); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + +#if 1 + g_writeln("scard_send_Transmit:"); + g_hexdump(s->data, bytes); +#endif + xstream_free(s); return 0; } @@ -1835,13 +1956,13 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, +scard_send_Control(IRP *irp, tui32 context, tui32 sc_handle, char *send_data, int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; int val; @@ -1857,61 +1978,49 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, return 1; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 12 bytes unused (s->p currently pointed here at unused[0]) - * u32 4 bytes map0 - * 4 bytes unused - * u32 4 bytes map1 - * u32 4 bytes dwControlCode - * u32 4 bytes cbRecvLength - * u32 4 bytes map2 - * 4 bytes unused - * u32 4 bytes cbOutBufferSize - * u32 4 bytes context len - * u32 4 bytes context - * u32 4 bytes handle len - * u32 4 bytes handle - */ - - xstream_seek(s, 12); - xstream_wr_u32_le(s, 0); // map0 - xstream_seek(s, 4); - xstream_wr_u32_le(s, 0); // map1 - - xstream_wr_u32_le(s, control_code); - - xstream_wr_u32_le(s, send_bytes); - - val = send_bytes > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); // map2 - - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, recv_bytes); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); - + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); /* map0 */ + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020004); /* map1 */ + out_uint32_le(s, control_code); + out_uint32_le(s, send_bytes); + val = send_bytes > 0 ? 0x00020008 : 0; + out_uint32_le(s, val); /* map2 */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, recv_bytes); + out_uint32_le(s, 4); + out_uint32_le(s, context); + out_uint32_le(s, 4); + out_uint32_le(s, sc_handle); if (send_bytes > 0) { - xstream_wr_u32_le(s, send_bytes); + out_uint32_le(s, send_bytes); out_uint8a(s, send_data, send_bytes); } + else + { + out_uint32_le(s, 0x00000000); + } - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); return 0; } @@ -1920,12 +2029,12 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, * Cancel any outstanding calls *****************************************************************************/ static int APP_CC -scard_send_Cancel(IRP* irp, tui32 context) +scard_send_Cancel(IRP *irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.27 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1956,14 +2065,18 @@ scard_send_Cancel(IRP* irp, tui32 context) xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, context); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); return 0; } @@ -1972,12 +2085,12 @@ scard_send_Cancel(IRP* irp, tui32 context) * Get reader attributes *****************************************************************************/ static int APP_CC -scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) +scard_send_GetAttrib(IRP *irp, tui32 sc_handle, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.21 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -2016,14 +2129,18 @@ scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); return 0; } @@ -2052,16 +2169,10 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) - { - log_error("failed to establish context - device not usable"); - /* LK_TODO delete irp and smartcard entry */ - return; - } /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_establish_context_return(con, s, len); + scard_function_establish_context_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2084,16 +2195,10 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) - { - log_error("ReleaseContext failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_release_context_return(con, s, len); + scard_function_release_context_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2118,17 +2223,10 @@ APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("Error checking context validity"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_is_context_valid_return(con, s, len); + scard_function_is_context_valid_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2205,18 +2303,11 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("failed to connect"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_connect_return(con, s, len); + scard_function_connect_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); @@ -2242,17 +2333,10 @@ scard_handle_Reconnect_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("failed to reconnect"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_reconnect_return(con, s, len); + scard_function_reconnect_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2277,17 +2361,10 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("BeginTransaction failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_begin_transaction_return(con, s, len); + scard_function_begin_transaction_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2312,17 +2389,10 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("EndTransaction failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_end_transaction_return(con, s, len); + scard_function_end_transaction_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2347,17 +2417,10 @@ scard_handle_Status_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("StatusCall failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_status_return(con, s, len); + scard_function_status_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2382,17 +2445,10 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, return; } - if (IoStatus != 0) - { - log_error("Disconnect failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_disconnect_return(con, s, len); + scard_function_disconnect_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2416,17 +2472,10 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, return; } - if (IoStatus != 0) - { - log_error("Transmit failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_transmit_return(con, s, len); + scard_function_transmit_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2450,17 +2499,10 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, return; } - if (IoStatus != 0) - { - log_error("Control failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_control_return(con, s, len); + scard_function_control_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2484,17 +2526,10 @@ scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId, return; } - if (IoStatus != 0) - { - log_error("Cancel_call failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_cancel_return(con, s, len); + scard_function_cancel_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2518,17 +2553,10 @@ scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId, return; } - if (IoStatus != 0) - { - log_error("GetAttrib_call failed"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_get_attrib_return(con, s, len); + scard_function_get_attrib_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 731b4718..a98ff194 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -140,8 +140,8 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) /* returns error */ int APP_CC scard_function_establish_context_return(struct trans *con, - struct stream *in_s, - int len) + struct stream *in_s, + int len, int status) { int bytes; tui32 context; @@ -149,28 +149,32 @@ scard_function_establish_context_return(struct trans *con, struct stream *out_s; LLOGLN(10, ("scard_function_establish_context_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) { LLOGLN(0, ("scard_function_establish_context_return: opps")); return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; - - //g_hexdump(in_s->p, len); - - in_uint8s(in_s, 28); - in_uint32_le(in_s, context_len); - if (context_len != 4) + context = 0; + if (status == 0) { - LLOGLN(0, ("scard_function_establish_context_return: opps")); - return 1; + in_uint8s(in_s, 28); + in_uint32_le(in_s, context_len); + if (context_len != 4) + { + LLOGLN(0, ("scard_function_establish_context_return: opps")); + return 1; + } + in_uint32_le(in_s, context); + LLOGLN(10, ("scard_function_establish_context_return: context 0x%8.8x", + context)); } - in_uint32_le(in_s, context); - LLOGLN(10, ("scard_function_establish_context_return: context 0x%8.8x", context)); out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, context); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -204,12 +208,13 @@ scard_process_release_context(struct trans *con, struct stream *in_s) int APP_CC scard_function_release_context_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { int bytes; struct stream *out_s; LLOGLN(10, ("scard_function_release_context_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0) { LLOGLN(0, ("scard_function_release_context_return: opps")); @@ -218,7 +223,7 @@ scard_function_release_context_return(struct trans *con, g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC; out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -263,6 +268,7 @@ scard_function_list_readers_return(struct trans *con, char lreader_name[16][100]; LLOGLN(10, ("scard_function_list_readers_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0) { @@ -273,13 +279,12 @@ scard_function_list_readers_return(struct trans *con, g_memset(reader_name, 0, sizeof(reader_name)); g_memset(lreader_name, 0, sizeof(lreader_name)); - in_uint8s(in_s, 28); - len -= 28; - in_uint32_le(in_s, len); rn_index = 0; readers = 0; if (status == 0) { + in_uint8s(in_s, 28); + in_uint32_le(in_s, len); while (len > 0) { in_uint16_le(in_s, chr); @@ -359,13 +364,15 @@ scard_process_connect(struct trans *con, struct stream *in_s) int APP_CC scard_function_connect_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { int dwActiveProtocol; int hCard; int bytes; struct stream *out_s; + LLOGLN(10, ("scard_function_connect_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) { @@ -373,16 +380,21 @@ scard_function_connect_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; - in_uint8s(in_s, 36); - in_uint32_le(in_s, dwActiveProtocol); - in_uint8s(in_s, 4); - in_uint32_le(in_s, hCard); - LLOGLN(10, ("scard_function_connect_return: hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol)); + dwActiveProtocol = 0; + hCard = 0; + if (status == 0) + { + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 4); + in_uint32_le(in_s, hCard); + LLOGLN(10, (" hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol)); + } out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, hCard); out_uint32_le(out_s, dwActiveProtocol); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -421,13 +433,15 @@ scard_process_disconnect(struct trans *con, struct stream *in_s) int APP_CC scard_function_disconnect_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { int dwActiveProtocol; int hCard; int bytes; struct stream *out_s; + LLOGLN(10, ("scard_function_disconnect_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) == 0) { @@ -435,14 +449,19 @@ scard_function_disconnect_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_D; - in_uint8s(in_s, 36); - in_uint32_le(in_s, dwActiveProtocol); - in_uint8s(in_s, 4); - in_uint32_le(in_s, hCard); - LLOGLN(10, ("scard_function_connect_return: hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol)); + dwActiveProtocol = 0; + hCard = 0; + if (status == 0) + { + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 4); + in_uint32_le(in_s, hCard); + LLOGLN(10, ("scard_function_connect_return: hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol)); + } out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -476,11 +495,13 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s) int APP_CC scard_function_begin_transaction_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; + LLOGLN(10, ("scard_function_begin_transaction_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0) { @@ -488,10 +509,9 @@ scard_function_begin_transaction_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_BT; - out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -527,11 +547,13 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) int APP_CC scard_function_end_transaction_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; + LLOGLN(10, ("scard_function_end_transaction_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0) { @@ -542,7 +564,7 @@ scard_function_end_transaction_return(struct trans *con, out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -556,7 +578,7 @@ scard_function_end_transaction_return(struct trans *con, int APP_CC scard_function_cancel_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { return 0; } @@ -566,7 +588,7 @@ scard_function_cancel_return(struct trans *con, int APP_CC scard_function_get_attrib_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { return 0; } @@ -619,7 +641,7 @@ scard_process_transmit(struct trans *con, struct stream *in_s) int APP_CC scard_function_transmit_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; @@ -629,6 +651,7 @@ scard_function_transmit_return(struct trans *con, char *recvBuf; LLOGLN(10, ("scard_function_transmit_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0) { @@ -637,22 +660,28 @@ scard_function_transmit_return(struct trans *con, } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR; - in_uint8s(in_s, 20); - in_uint32_le(in_s, val); g_memset(&recv_ior, 0, sizeof(recv_ior)); - if (val != 0) - { - /* pioRecvPci */ - LLOGLN(0, ("scard_function_transmit_return: pioRecvPci not zero!")); - } - in_uint8s(in_s, 4); - in_uint32_le(in_s, val); cbRecvLength = 0; - recvBuf = 0; - if (val != 0) + + if (status == 0) { - in_uint32_le(in_s, cbRecvLength); - in_uint8p(in_s, recvBuf, cbRecvLength); + in_uint8s(in_s, 20); + in_uint32_le(in_s, val); + g_memset(&recv_ior, 0, sizeof(recv_ior)); + if (val != 0) + { + /* pioRecvPci */ + LLOGLN(0, ("scard_function_transmit_return: pioRecvPci not zero!")); + } + in_uint8s(in_s, 4); + in_uint32_le(in_s, val); + cbRecvLength = 0; + recvBuf = 0; + if (val != 0) + { + in_uint32_le(in_s, cbRecvLength); + in_uint8p(in_s, recvBuf, cbRecvLength); + } } LLOGLN(10, ("scard_function_transmit_return: cbRecvLength %d", cbRecvLength)); out_s = trans_get_out_s(con, 8192); @@ -663,7 +692,7 @@ scard_function_transmit_return(struct trans *con, out_uint8a(out_s, recv_ior.extra_data, recv_ior.extra_bytes); out_uint32_le(out_s, cbRecvLength); out_uint8a(out_s, recvBuf, cbRecvLength); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -712,13 +741,15 @@ scard_process_control(struct trans *con, struct stream *in_s) int APP_CC scard_function_control_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; int cbRecvLength; char *recvBuf; + LLOGLN(10, ("scard_function_control_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0) { @@ -726,17 +757,20 @@ scard_function_control_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO; - - in_uint8s(in_s, 28); - in_uint32_le(in_s, cbRecvLength); - in_uint8p(in_s, recvBuf, cbRecvLength); - + cbRecvLength = 0; + recvBuf = 0; + if (status == 0) + { + in_uint8s(in_s, 28); + in_uint32_le(in_s, cbRecvLength); + in_uint8p(in_s, recvBuf, cbRecvLength); + } LLOGLN(10, ("scard_function_control_return: cbRecvLength %d", cbRecvLength)); out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, cbRecvLength); out_uint8a(out_s, recvBuf, cbRecvLength); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -797,7 +831,7 @@ static int g_ms2pc[] = { PC_SCARD_UNKNOWN, PC_SCARD_ABSENT, int APP_CC scard_function_status_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int index; @@ -810,6 +844,8 @@ scard_function_status_return(struct trans *con, twchar reader_name[100]; char lreader_name[100]; + LLOGLN(10, ("scard_function_status_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST) == 0) { @@ -817,23 +853,31 @@ scard_function_status_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ST; - in_uint8s(in_s, 20); - in_uint32_le(in_s, dwReaderLen); - in_uint8s(in_s, 4); - in_uint32_le(in_s, dwState); - dwState = g_ms2pc[dwState % 6]; - in_uint32_le(in_s, dwProtocol); - in_uint8a(in_s, attr, 32); - in_uint32_le(in_s, dwAtrLen); - in_uint32_le(in_s, dwReaderLen); - dwReaderLen /= 2; - g_memset(reader_name, 0, sizeof(reader_name)); - g_memset(lreader_name, 0, sizeof(lreader_name)); - for (index = 0; index < dwReaderLen; index++) + dwReaderLen = 0; + dwState = 0; + dwProtocol = 0; + dwAtrLen = 0; + lreader_name[0] = 0; + if (status == 0) { - in_uint16_le(in_s, reader_name[index]); + in_uint8s(in_s, 20); + in_uint32_le(in_s, dwReaderLen); + in_uint8s(in_s, 4); + in_uint32_le(in_s, dwState); + dwState = g_ms2pc[dwState % 6]; + in_uint32_le(in_s, dwProtocol); + in_uint8a(in_s, attr, 32); + in_uint32_le(in_s, dwAtrLen); + in_uint32_le(in_s, dwReaderLen); + dwReaderLen /= 2; + g_memset(reader_name, 0, sizeof(reader_name)); + g_memset(lreader_name, 0, sizeof(lreader_name)); + for (index = 0; index < dwReaderLen; index++) + { + in_uint16_le(in_s, reader_name[index]); + } + g_wcstombs(lreader_name, reader_name, 99); } - g_wcstombs(lreader_name, reader_name, 99); LLOGLN(10, ("scard_function_status_return: dwAtrLen %d dwReaderLen %d " "dwProtocol %d dwState %d name %s", dwAtrLen, dwReaderLen, dwProtocol, dwState, lreader_name)); @@ -846,7 +890,7 @@ scard_function_status_return(struct trans *con, out_uint32_le(out_s, dwProtocol); out_uint32_le(out_s, dwAtrLen); out_uint8a(out_s, attr, dwAtrLen); - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -979,7 +1023,7 @@ scard_function_get_status_change_return(struct trans *con, int APP_CC scard_function_is_context_valid_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { return 0; } @@ -988,7 +1032,7 @@ scard_function_is_context_valid_return(struct trans *con, /* returns error */ int APP_CC scard_function_reconnect_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { return 0; } diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 456d0701..34c74063 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -30,21 +30,21 @@ int APP_CC scard_pcsc_init(void); int APP_CC scard_pcsc_deinit(void); int APP_CC scard_function_establish_context_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_release_context_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, int len, int status); int APP_CC scard_function_transmit_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_control_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, @@ -52,38 +52,38 @@ int APP_CC scard_function_get_status_change_return(struct trans *con, int APP_CC scard_function_connect_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_status_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_begin_transaction_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_end_transaction_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_is_context_valid_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_reconnect_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_disconnect_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_cancel_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_get_attrib_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); #endif /* end #ifndef _SMARTCARD_PCSC_H */