summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/pcsc/xrdp_pcsc.c75
-rw-r--r--sesman/chansrv/smartcard.c26
-rw-r--r--sesman/chansrv/smartcard.h3
-rw-r--r--sesman/chansrv/smartcard_pcsc.c185
-rw-r--r--sesman/chansrv/smartcard_pcsc.h3
5 files changed, 282 insertions, 10 deletions
diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c
index b93dba12..c10a1627 100644
--- a/sesman/chansrv/pcsc/xrdp_pcsc.c
+++ b/sesman/chansrv/pcsc/xrdp_pcsc.c
@@ -520,6 +520,11 @@ SCardBeginTransaction(SCARDHANDLE hCard)
PCSC_API LONG
SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
LLOGLN(0, ("SCardEndTransaction:"));
if (g_sck == -1)
{
@@ -527,8 +532,31 @@ SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
return SCARD_F_INTERNAL_ERROR;
}
pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hCard);
+ SET_UINT32(msg, 4, dwDisposition);
+ if (send_message(SCARD_BEGIN_TRANSACTION, msg, 8) != 0)
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
pthread_mutex_unlock(&g_mutex);
- return SCARD_S_SUCCESS;
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardEndTransaction: got status 0x%8.8x", status));
+ return status;
}
/*****************************************************************************/
@@ -652,6 +680,9 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
LLOGLN(0, ("SCardControl: error, not connected"));
return SCARD_F_INTERNAL_ERROR;
}
+ LLOGLN(0, ("SCardControl: dwControlCode %d", dwControlCode));
+ LLOGLN(0, ("SCardControl: cbSendLength %d", cbSendLength));
+ LLOGLN(0, ("SCardControl: cbRecvLength %d", cbRecvLength));
pthread_mutex_lock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
return SCARD_S_SUCCESS;
@@ -664,13 +695,55 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
LPDWORD pcbRecvLength)
{
+ char *msg;
+ int bytes;
+ int code;
+ int offset;
+ int status;
+
LLOGLN(0, ("SCardTransmit:"));
if (g_sck == -1)
{
LLOGLN(0, ("SCardTransmit: error, not connected"));
return SCARD_F_INTERNAL_ERROR;
}
+ LLOGLN(0, ("SCardTransmit: cbSendLength %d", cbSendLength));
+
+ msg = (char *) malloc(8192);
+ SET_UINT32(msg, 0, hCard);
+ SET_UINT32(msg, 4, pioSendPci->dwProtocol);
+ SET_UINT32(msg, 8, pioSendPci->cbPciLength);
+ SET_UINT32(msg, 12, cbSendLength);
+ offset = 16;
+ memcpy(msg + 16, pbSendBuffer, cbSendLength);
+ offset += cbSendLength;
+ SET_UINT32(msg, offset, *pcbRecvLength);
+ offset += 4;
pthread_mutex_lock(&g_mutex);
+
+ if (send_message(SCARD_TRANSMIT, msg, offset) != 0)
+ {
+ LLOGLN(0, ("SCardTransmit: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardTransmit: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_TRANSMIT)
+ {
+ LLOGLN(0, ("SCardTransmit: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+
pthread_mutex_unlock(&g_mutex);
return SCARD_S_SUCCESS;
}
diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c
index 9d55807d..2b07b90e 100644
--- a/sesman/chansrv/smartcard.c
+++ b/sesman/chansrv/smartcard.c
@@ -177,7 +177,8 @@ 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);
+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_Disconnect(IRP* irp, tui32 context,
@@ -577,7 +578,8 @@ scard_send_begin_transaction(struct trans *con, tui32 sc_handle)
* @param sc_handle handle to smartcard
*****************************************************************************/
int APP_CC
-scard_send_end_transaction(struct trans *con, tui32 sc_handle)
+scard_send_end_transaction(struct trans *con, tui32 sc_handle,
+ tui32 dwDisposition)
{
IRP *irp;
@@ -595,7 +597,7 @@ scard_send_end_transaction(struct trans *con, tui32 sc_handle)
irp->user_data = con;
/* send IRP to client */
- scard_send_EndTransaction(irp, sc_handle);
+ scard_send_EndTransaction(irp, sc_handle, dwDisposition);
return 0;
}
@@ -1469,12 +1471,12 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle)
* @param sc_handle handle to smartcard
*****************************************************************************/
static void APP_CC
-scard_send_EndTransaction(IRP *irp, tui32 sc_handle)
+scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition)
{
/* see [MS-RDPESC] 3.1.4.32 */
- SMARTCARD* sc;
- struct stream* s;
+ SMARTCARD *sc;
+ struct stream *s;
int bytes;
if ((sc = smartcards[irp->scard_index]) == NULL)
@@ -1501,7 +1503,7 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle)
*/
xstream_seek(s, 24);
- xstream_wr_u32_le(s, SCARD_LEAVE_CARD);
+ xstream_wr_u32_le(s, dwDisposition);
xstream_seek(s, 8);
/* insert handle */
@@ -1790,7 +1792,8 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs)
/**
* Cancel any outstanding calls
*****************************************************************************/
-static int APP_CC scard_send_Cancel(IRP* irp, tui32 context)
+static int APP_CC
+scard_send_Cancel(IRP* irp, tui32 context)
{
/* see [MS-RDPESC] 3.1.4.27 */
@@ -2081,9 +2084,11 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp,
/* get OutputBufferLen */
xstream_rd_u32_le(s, len);
+
con = (struct trans *) (irp->user_data);
scard_function_connect_return(con, s, len);
devredir_irp_delete(irp);
+
log_debug("leaving");
}
@@ -2128,6 +2133,7 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
tui32 IoStatus)
{
tui32 len;
+ struct trans *con;
log_debug("entered");
@@ -2148,6 +2154,10 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
/* get OutputBufferLen */
xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_begin_transaction_return(con, s, len);
+ devredir_irp_delete(irp);
+
log_debug("leaving");
}
diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h
index 600aef04..14c5d6f2 100644
--- a/sesman/chansrv/smartcard.h
+++ b/sesman/chansrv/smartcard.h
@@ -118,7 +118,8 @@ int APP_CC scard_send_reconnect(struct trans *con, tui32 context,
tui32 sc_handle, READER_STATE* rs);
int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle);
-int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle);
+int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle,
+ tui32 dwDisposition);
int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle);
int APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle);
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 */
diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h
index 94effea9..d22f4322 100644
--- a/sesman/chansrv/smartcard_pcsc.h
+++ b/sesman/chansrv/smartcard_pcsc.h
@@ -44,5 +44,8 @@ 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 APP_CC scard_function_begin_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len);
#endif /* end #ifndef _SMARTCARD_PCSC_H */