summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv/smartcard_pcsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sesman/chansrv/smartcard_pcsc.c')
-rw-r--r--sesman/chansrv/smartcard_pcsc.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c
index 62b3b722..b010eee7 100644
--- a/sesman/chansrv/smartcard_pcsc.c
+++ b/sesman/chansrv/smartcard_pcsc.c
@@ -57,6 +57,9 @@
#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */
#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */
#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */
+#define XRDP_PCSC_STATE_GOT_ET (1 << 6) /* end transaction */
+#define XRDP_PCSC_STATE_GOT_TR (1 << 7) /* transmit */
+#define XRDP_PCSC_STATE_GOT_CO (1 << 8) /* control */
/* TODO: put this in con */
static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
@@ -406,6 +409,185 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s)
/*****************************************************************************/
/* returns error */
int APP_CC
+scard_function_begin_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0)
+ {
+ LLOGLN(0, ("scard_function_begin_transaction_return: opps"));
+ 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 */
+ 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, 0x07); /* SCARD_BEGIN_TRANSACTION 0x07 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_end_transaction(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+ int dwDisposition;
+
+ LLOGLN(0, ("scard_process_end_transaction:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET)
+ {
+ LLOGLN(0, ("scard_process_end_transaction: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_ET;
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, dwDisposition);
+ LLOGLN(0, ("scard_process_end_transaction: hCard 0x%8.8x", hCard));
+ scard_send_end_transaction(con, hCard, dwDisposition);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_end_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0)
+ {
+ LLOGLN(0, ("scard_function_end_transaction_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ET;
+
+ 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 */
+ 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, 0x08); /* SCARD_END_TRANSACTION 0x08 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_transmit(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+ READER_STATE rs;
+
+ LLOGLN(0, ("scard_process_transmit:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR)
+ {
+ LLOGLN(0, ("scard_process_transmit: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_TR;
+ LLOGLN(0, ("scard_process_transmit:"));
+
+ // todo
+ g_memset(&rs, 0, sizeof(rs));
+
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, rs.dwProtocol);
+ in_uint32_le(in_s, rs.cbPciLength);
+ in_uint32_le(in_s, rs.cbSendLength);
+ LLOGLN(0, ("scard_process_transmit: dwProtocol %d cbPciLength %d "
+ "cbSendLength %d", rs.dwProtocol, rs.cbPciLength, rs.cbSendLength));
+ g_hexdump(in_s->p, rs.cbSendLength);
+ in_uint8s(in_s, rs.cbSendLength);
+ in_uint32_le(in_s, rs.cbRecvLength);
+ LLOGLN(0, ("scard_process_transmit: cbRecvLength %d", rs.cbRecvLength));
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_transmit_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0)
+ {
+ LLOGLN(0, ("scard_function_transmit_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR;
+
+ // todo
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_control(struct trans *con, struct stream *in_s)
+{
+ LLOGLN(0, ("scard_process_control:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO)
+ {
+ LLOGLN(0, ("scard_process_control: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_CO;
+ LLOGLN(0, ("scard_process_control:"));
+
+ // todo
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_control_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0)
+ {
+ LLOGLN(0, ("scard_function_control_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO;
+
+ // todo
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
scard_process_get_status_change(struct trans *con, struct stream *in_s)
{
int index;
@@ -556,14 +738,17 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command)
case 0x08: /* SCARD_END_TRANSACTION */
LLOGLN(0, ("scard_process_msg: SCARD_END_TRANSACTION"));
+ rv = scard_process_end_transaction(con, in_s);
break;
case 0x09: /* SCARD_TRANSMIT */
LLOGLN(0, ("scard_process_msg: SCARD_TRANSMIT"));
+ rv = scard_process_transmit(con, in_s);
break;
case 0x0A: /* SCARD_CONTROL */
LLOGLN(0, ("scard_process_msg: SCARD_CONTROL"));
+ rv = scard_process_control(con, in_s);
break;
case 0x0B: /* SCARD_STATUS */