summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
authorJay Sorg <jay.sorg@gmail.com>2013-11-29 21:28:13 -0800
committerJay Sorg <jay.sorg@gmail.com>2013-11-29 21:28:13 -0800
commit3d4fbb883a6843a46b04a2e4c758a9cf4f094fb8 (patch)
treeda571615b0a345cae9a546bbc88de6cb56cc7873 /sesman/chansrv
parent7ca01ac38143e98d64937437ae77bc27b8f6169c (diff)
downloadxrdp-proprietary-3d4fbb883a6843a46b04a2e4c758a9cf4f094fb8.tar.gz
xrdp-proprietary-3d4fbb883a6843a46b04a2e4c758a9cf4f094fb8.zip
chansrv: work on getting MSTSC smartcard working
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/pcsc/xrdp_pcsc.c2
-rw-r--r--sesman/chansrv/smartcard.c124
-rw-r--r--sesman/chansrv/smartcard_pcsc.c111
-rw-r--r--sesman/chansrv/smartcard_pcsc.h4
4 files changed, 149 insertions, 92 deletions
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,