From de9fa3d5fac378ba63cc9e46f8ff08a425953eaf Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 5 Dec 2013 02:22:41 -0800 Subject: [PATCH] chansrv: smartcard, more work on support for MSTSC --- sesman/chansrv/pcsc/xrdp_pcsc.c | 29 ++++- sesman/chansrv/smartcard.c | 209 +++++++++++++++++--------------- sesman/chansrv/smartcard.h | 3 +- sesman/chansrv/smartcard_pcsc.c | 55 ++++++--- 4 files changed, 175 insertions(+), 121 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index b28df62c..e4bb0bfc 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -1004,9 +1004,14 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, int status; int offset; int index; + int bytes_groups; + int val; + int llen; char reader[100]; LLOGLN(10, ("SCardListReaders:")); + LLOGLN(10, ("SCardListReaders: mszGroups %s", mszGroups)); + LLOGLN(10, ("SCardListReaders: *pcchReaders %d", *pcchReaders)); if (g_sck == -1) { LLOGLN(0, ("SCardListReaders: error, not connected")); @@ -1014,8 +1019,22 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, } msg = (char *) malloc(8192); pthread_mutex_lock(&g_mutex); - SET_UINT32(msg, 0, hContext); - if (send_message(SCARD_LIST_READERS, msg, 4) != 0) + offset = 0; + SET_UINT32(msg, offset, hContext); + offset += 4; + bytes_groups = 0; + if (mszGroups != 0) + { + bytes_groups = strlen(mszGroups); + } + SET_UINT32(msg, offset, bytes_groups); + offset += 4; + memcpy(msg + offset, mszGroups, bytes_groups); + offset += bytes_groups; + val = *pcchReaders; + SET_UINT32(msg, offset, val); + offset += 4; + if (send_message(SCARD_LIST_READERS, msg, offset) != 0) { LLOGLN(0, ("SCardListReaders: error, send_message")); free(msg); @@ -1039,6 +1058,8 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, } pthread_mutex_unlock(&g_mutex); offset = 0; + llen = GET_UINT32(msg, offset); + offset += 4; num_readers = GET_UINT32(msg, offset); offset += 4; LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d", @@ -1060,6 +1081,10 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, reader_names_index++; status = GET_UINT32(msg, offset); offset += 4; + if (mszReaders == 0) + { + reader_names_index = llen; + } if (pcchReaders != 0) { *pcchReaders = reader_names_index; diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index c6a36811..7f533a0e 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -167,7 +167,9 @@ static void APP_CC scard_release_resources(void); 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_ListReaders(IRP *irp, tui32 context, + char *groups, int cchReaders, + int wide); static void APP_CC scard_send_GetStatusChange(IRP *irp, tui32 context, int wide, tui32 timeout, tui32 num_readers, READER_STATE *rsa); @@ -415,7 +417,8 @@ scard_send_is_valid_context(struct trans *con, tui32 context) * *****************************************************************************/ int APP_CC -scard_send_list_readers(struct trans *con, tui32 context, int wide) +scard_send_list_readers(struct trans *con, tui32 context, char *groups, + int cchReaders, int wide) { IRP *irp; @@ -432,7 +435,7 @@ scard_send_list_readers(struct trans *con, tui32 context, int wide) irp->user_data = con; /* send IRP to client */ - scard_send_ListReaders(irp, context, wide); + scard_send_ListReaders(irp, context, groups, cchReaders, wide); return 0; } @@ -933,14 +936,18 @@ scard_send_EstablishContext(IRP *irp, int scope) return; } - xstream_wr_u32_le(s, 0x08); /* len */ - xstream_wr_u32_le(s, 0); /* unused */ - 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 */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, scope); + 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); + s_pop_layer(s, iso_hdr); bytes = (int) (s->end - s->p); bytes -= 28; @@ -951,7 +958,7 @@ scard_send_EstablishContext(IRP *irp, int scope) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -978,28 +985,20 @@ scard_send_ReleaseContext(IRP *irp, tui32 context) return; } - /* - * command format - * - * ...... - * 20 bytes padding - * u32 4 bytes len 8, LE, v1 - * u32 4 bytes filler - * 4 bytes len - don't know what this is, zero for now - * 12 bytes unused - * u32 4 bytes context len - * 4 bytes context - */ - - xstream_wr_u32_le(s, 0); - xstream_seek(s, 12); - - /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + 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, context); s_mark_end(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; @@ -1010,7 +1009,7 @@ scard_send_ReleaseContext(IRP *irp, tui32 context) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1067,21 +1066,28 @@ scard_send_IsContextValid(IRP *irp, tui32 context) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** * *****************************************************************************/ static void APP_CC -scard_send_ListReaders(IRP *irp, tui32 context, int wide) +scard_send_ListReaders(IRP *irp, tui32 context, char *groups, + int cchReaders, int wide) { /* see [MS-RDPESC] 2.2.2.4 */ SMARTCARD *sc; struct stream *s; int bytes; + int bytes_groups; + int val; + int index; + int num_chars; tui32 ioctl; + twchar w_groups[100]; + if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -1098,42 +1104,64 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) return; } - xstream_wr_u32_le(s, 72); /* number of bytes to follow */ + num_chars = 0; + bytes_groups = 0; + w_groups[0] = 0; + val = 0; + if (groups != 0) + { + if (groups[0] != 0) + { + num_chars = g_mbstowcs(w_groups, groups, 99); + bytes_groups = wide ? (num_chars + 2) * 2 : num_chars + 2; + val = 0x00020004; + } + } + 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, 0x00000024); - out_uint32_le(s, 0x00020004); + out_uint32_le(s, bytes_groups); + out_uint32_le(s, val); out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0xFFFFFFFF); + out_uint32_le(s, cchReaders); /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, 4); + out_uint32_le(s, context); - xstream_wr_u32_le(s, 36); /* length of mszGroups */ - xstream_wr_u16_le(s, 0x0053); - xstream_wr_u16_le(s, 0x0043); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0024); - xstream_wr_u16_le(s, 0x0041); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x0052); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0073); - - xstream_wr_u32_le(s, 0x00); + if (bytes_groups > 0) + { + if (wide) + { + out_uint32_le(s, bytes_groups); + for (index = 0; index < num_chars; index++) + { + out_uint16_le(s, w_groups[index]); + } + out_uint16_le(s, 0); + out_uint16_le(s, 0); + } + else + { + out_uint32_le(s, bytes_groups); + for (index = 0; index < num_chars; index++) + { + out_uint8(s, w_groups[index]); + } + out_uint16_le(s, 0); + out_uint16_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); + s_pop_layer(s, iso_hdr); bytes = (int) (s->end - s->p); bytes -= 28; @@ -1149,33 +1177,7 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) g_hexdump(s->data, bytes); #endif - xstream_free(s); - - /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... - 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... - 0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... - 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................ - 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. - 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. - 0070 72 00 73 00 00 00 00 00 r.s..... - scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c - */ - - /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................ - 0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................ - 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... - 0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd...... - 0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'.............. - 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. - 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. - 0070 72 00 73 00 00 00 00 00 r.s..... - scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014 - */ + free_stream(s); } /*****************************************************************************/ @@ -1399,6 +1401,11 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) s_mark_end(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; @@ -1409,7 +1416,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1483,7 +1490,7 @@ scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1545,7 +1552,7 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1608,7 +1615,7 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1689,7 +1696,7 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1755,7 +1762,7 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); } /** @@ -1817,10 +1824,10 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, * u32 4 bytes sc_handle */ - g_writeln("send_bytes %d", send_bytes); - g_writeln("recv_bytes %d", recv_bytes); + //g_writeln("send_bytes %d", send_bytes); + //g_writeln("recv_bytes %d", recv_bytes); -#if 1 +#if 0 s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ //out_uint32_be(s, 0x58000000); out_uint32_be(s, 0x00000000); @@ -1859,10 +1866,10 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, 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); + //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); @@ -1943,12 +1950,12 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); -#if 1 +#if 0 g_writeln("scard_send_Transmit:"); g_hexdump(s->data, bytes); #endif - xstream_free(s); + free_stream(s); return 0; } @@ -2021,7 +2028,7 @@ scard_send_Control(IRP *irp, tui32 context, tui32 sc_handle, char *send_data, /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); return 0; } @@ -2077,7 +2084,7 @@ scard_send_Cancel(IRP *irp, tui32 context) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); return 0; } @@ -2141,7 +2148,7 @@ scard_send_GetAttrib(IRP *irp, tui32 sc_handle, READER_STATE *rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + free_stream(s); return 0; } diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 88f4cdf6..24ba2123 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -113,7 +113,8 @@ int APP_CC scard_deinit(void); int APP_CC scard_send_establish_context(struct trans *con, int scope); int APP_CC scard_send_release_context(struct trans *con, tui32 context); int APP_CC scard_send_is_valid_context(struct trans *con, tui32 context); -int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide); +int APP_CC scard_send_list_readers(struct trans *con, tui32 context, + char *groups, int cchReaders, int wide); int APP_CC scard_send_get_status_change(struct trans *con, tui32 context, int wide, tui32 timeout, diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index a98ff194..c6114c2c 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -65,6 +65,7 @@ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; +static int g_xrdp_pcsc_extra1; extern int g_display_num; /* in chansrv.c */ @@ -238,6 +239,9 @@ int APP_CC scard_process_list_readers(struct trans *con, struct stream *in_s) { int hContext; + int bytes_groups; + int cchReaders; + char *groups; LLOGLN(10, ("scard_process_list_readers:")); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) @@ -247,8 +251,15 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) } g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; in_uint32_le(in_s, hContext); - LLOGLN(10, ("scard_process_list_readers: dwScope 0x%8.8x", hContext)); - scard_send_list_readers(con, hContext, 1); + in_uint32_le(in_s, bytes_groups); + groups = (char *) g_malloc(bytes_groups + 1, 1); + in_uint8a(in_s, groups, bytes_groups); + in_uint32_le(in_s, cchReaders); + g_xrdp_pcsc_extra1 = g_xrdp_pcsc_extra1 = cchReaders; + LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d", + hContext, cchReaders)); + scard_send_list_readers(con, hContext, groups, cchReaders, 1); + g_free(groups); return 0; } @@ -264,6 +275,8 @@ scard_function_list_readers_return(struct trans *con, int rn_index; int index; int bytes; + int cchReaders; + int llen; twchar reader_name[100]; char lreader_name[16][100]; @@ -277,33 +290,40 @@ scard_function_list_readers_return(struct trans *con, } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; + cchReaders = g_xrdp_pcsc_extra1; + g_memset(reader_name, 0, sizeof(reader_name)); g_memset(lreader_name, 0, sizeof(lreader_name)); rn_index = 0; readers = 0; + llen = 0; if (status == 0) { in_uint8s(in_s, 28); in_uint32_le(in_s, len); - while (len > 0) + llen = len; + if (cchReaders > 0) { - in_uint16_le(in_s, chr); - len -= 2; - if (chr == 0) + while (len > 0) { - if (reader_name[0] != 0) + in_uint16_le(in_s, chr); + len -= 2; + if (chr == 0) { - g_wcstombs(lreader_name[readers], reader_name, 99); - g_memset(reader_name, 0, sizeof(reader_name)); - readers++; + if (reader_name[0] != 0) + { + g_wcstombs(lreader_name[readers], reader_name, 99); + g_memset(reader_name, 0, sizeof(reader_name)); + readers++; + } + reader_name[0] = 0; + rn_index = 0; + } + else + { + reader_name[rn_index] = chr; + rn_index++; } - reader_name[0] = 0; - rn_index = 0; - } - else - { - reader_name[rn_index] = chr; - rn_index++; } } if (rn_index > 0) @@ -319,6 +339,7 @@ scard_function_list_readers_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, llen); out_uint32_le(out_s, readers); for (index = 0; index < readers; index++) {