diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 502d3096..b28df62c 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -1139,7 +1139,7 @@ SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, PCSC_API char * pcsc_stringify_error(const long code) { - LLOGLN(10, ("pcsc_stringify_error: %d", (int)code)); + LLOGLN(10, ("pcsc_stringify_error: 0x%8.8x", (int)code)); switch (code) { case SCARD_S_SUCCESS: diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 29406d62..d7b1719c 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -831,9 +831,9 @@ scard_make_new_ioctl(IRP *irp, tui32 ioctl) 0); xstream_wr_u32_le(s, 2048); /* OutputBufferLength */ - xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */ + s_push_layer(s, iso_hdr, 4); /* InputBufferLength - insert later */ xstream_wr_u32_le(s, ioctl); /* Ioctl Code */ - xstream_seek(s, 20); /* padding */ + out_uint8s(s, 20); /* padding */ /* [MS-RPCE] 2.2.6.1 */ xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */ @@ -967,7 +967,10 @@ scard_send_ReleaseContext(IRP* irp, tui32 context) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RELEASE_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1019,7 +1022,10 @@ scard_send_IsContextValid(IRP* irp, tui32 context) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_IS_VALID_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1073,10 +1079,20 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) SCARD_IOCTL_LIST_READERS_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } xstream_wr_u32_le(s, 72); /* number of bytes to follow */ - xstream_seek(s, 28); /* freerdp does not use this */ + + 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, 0x00000000); + out_uint32_le(s, 0xFFFFFFFF); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1110,6 +1126,10 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); + + //g_writeln("scard_send_ListReaders:"); + //g_hexdump(s->data, bytes); + xstream_free(s); /* @@ -1190,27 +1210,34 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, SCARD_IOCTL_GET_STATUS_CHANGE_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } - xstream_seek(s, 16); /* unused */ - xstream_wr_u32_le(s, timeout); - xstream_wr_u32_le(s, num_readers); - xstream_wr_u32_le(s, 0); /* unused */ + s_push_layer(s, mcs_hdr, 4); /* set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00000004); + out_uint32_le(s, 0x00020000); + + out_uint32_le(s, timeout); + out_uint32_le(s, num_readers); + out_uint32_le(s, 0x00020004); /* ? */ /* 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, 0); /* unused */ + out_uint32_le(s, num_readers); /* ? */ /* insert card reader state */ for (i = 0; i < num_readers; i++) { rs = &rsa[i]; - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, rs->current_state); - xstream_wr_u32_le(s, rs->event_state); - xstream_wr_u32_le(s, rs->atr_len); + out_uint32_le(s, 0x00020008); /* ? */ + out_uint32_le(s, rs->current_state); + out_uint32_le(s, rs->event_state); + out_uint32_le(s, rs->atr_len); xstream_copyin(s, rs->atr, 33); out_uint8s(s, 3); } @@ -1222,13 +1249,14 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { rs = &rsa[i]; num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, num_chars); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0); + out_uint32_le(s, num_chars + 2); 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); align_s(s, 4); } } @@ -1239,25 +1267,38 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { rs = &rsa[i]; num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, num_chars); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0); + out_uint32_le(s, num_chars + 2); 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); align_s(s, 4); } } - /* 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); + + //g_writeln("scard_send_GetStatusChange:"); + //g_hexdump(s->data, bytes); + xstream_free(s); } @@ -1292,7 +1333,10 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) SCARD_IOCTL_CONNECT_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1377,7 +1421,10 @@ scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RECONNECT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1438,7 +1485,10 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_BEGIN_TRANSACTION)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1492,7 +1542,10 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_END_TRANSACTION)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1618,7 +1671,10 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_DISCONNECT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -2091,16 +2147,10 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) - { - log_error("failed to list readers"); - /* LK_TODO delete irp and smartcard entry */ - return; - } /* get OutputBufferLen */ xstream_rd_u32_le(s, len); con = (struct trans *) (irp->user_data); - scard_function_list_readers_return(con, s, len); + scard_function_list_readers_return(con, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2123,16 +2173,10 @@ scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) - { - log_error("failed to get status change"); - /* 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_status_change_return(con, s, len); + scard_function_get_status_change_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 29f60c8d..731b4718 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -155,6 +155,9 @@ scard_function_establish_context_return(struct trans *con, 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) @@ -248,7 +251,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int chr; @@ -273,39 +276,39 @@ scard_function_list_readers_return(struct trans *con, in_uint8s(in_s, 28); len -= 28; in_uint32_le(in_s, len); - //g_writeln("len %d", len); rn_index = 0; readers = 0; - while (len > 0) + if (status == 0) { - in_uint16_le(in_s, chr); - len -= 2; - if (chr == 0) + while (len > 0) + { + in_uint16_le(in_s, chr); + len -= 2; + if (chr == 0) + { + 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++; + } + } + if (rn_index > 0) { if (reader_name[0] != 0) { g_wcstombs(lreader_name[readers], reader_name, 99); - //g_writeln("1 %s", lreader_name[readers]); g_memset(reader_name, 0, sizeof(reader_name)); readers++; } - reader_name[0] = 0; - rn_index = 0; - } - else - { - reader_name[rn_index] = chr; - rn_index++; - } - } - if (rn_index > 0) - { - if (reader_name[0] != 0) - { - g_wcstombs(lreader_name[readers], reader_name, 99); - //g_writeln("2 %s", lreader_name[readers]); - g_memset(reader_name, 0, sizeof(reader_name)); - readers++; } } @@ -314,10 +317,9 @@ scard_function_list_readers_return(struct trans *con, out_uint32_le(out_s, readers); for (index = 0; index < readers; index++) { - //g_writeln("3 - %s", lreader_name[index]); out_uint8a(out_s, lreader_name[index], 100); } - 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); @@ -913,7 +915,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, - int len) + int len, int status) { int bytes; int index; @@ -925,6 +927,7 @@ scard_function_get_status_change_return(struct trans *con, struct stream *out_s; LLOGLN(10, ("scard_function_get_status_change_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); //g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0) { @@ -932,33 +935,43 @@ scard_function_get_status_change_return(struct trans *con, return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC; - in_uint8s(in_s, 28); - in_uint32_le(in_s, cReaders); - if (cReaders > 0) + + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + if (status != 0) + { + out_uint32_le(out_s, 0); /* cReaders */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + } + else { - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); + in_uint8s(in_s, 28); + in_uint32_le(in_s, cReaders); + LLOGLN(10, (" cReaders %d", cReaders)); out_uint32_le(out_s, cReaders); - for (index = 0; index < cReaders; index++) + if (cReaders > 0) { - in_uint32_le(in_s, current_state); - out_uint32_le(out_s, current_state); - in_uint32_le(in_s, event_state); - out_uint32_le(out_s, event_state); - in_uint32_le(in_s, atr_len); - out_uint32_le(out_s, atr_len); - in_uint8a(in_s, atr, 36); - out_uint8a(out_s, atr, 36); + for (index = 0; index < cReaders; index++) + { + in_uint32_le(in_s, current_state); + out_uint32_le(out_s, current_state); + in_uint32_le(in_s, event_state); + out_uint32_le(out_s, event_state); + in_uint32_le(in_s, atr_len); + out_uint32_le(out_s, atr_len); + in_uint8a(in_s, atr, 36); + out_uint8a(out_s, atr, 36); + } } - out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ - s_mark_end(out_s); - bytes = (int) (out_s->end - out_s->data); - s_pop_layer(out_s, iso_hdr); - out_uint32_le(out_s, bytes - 8); - out_uint32_le(out_s, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */ - return trans_force_write(con); + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ } - return 0; + + s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */ + return trans_force_write(con); } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index bd5b9090..456d0701 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -36,7 +36,7 @@ int APP_CC scard_function_release_context_return(struct trans *con, int len); int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_transmit_return(struct trans *con, struct stream *in_s, @@ -48,7 +48,7 @@ int APP_CC scard_function_control_return(struct trans *con, int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, - int len); + int len, int status); int APP_CC scard_function_connect_return(struct trans *con, struct stream *in_s,