diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 520c9971..b93dba12 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -52,11 +52,22 @@ typedef struct _SCARD_IO_REQUEST #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) -#define SCARD_ESTABLISH_CONTEXT 0x01 -#define SCARD_RELEASE_CONTEXT 0x02 -#define SCARD_LIST_READERS 0x03 -#define SCARD_CONNECT 0x04 -#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_ESTABLISH_CONTEXT 0x01 +#define SCARD_RELEASE_CONTEXT 0x02 +#define SCARD_LIST_READERS 0x03 +#define SCARD_CONNECT 0x04 +#define SCARD_RECONNECT 0x05 +#define SCARD_DISCONNECT 0x06 +#define SCARD_BEGIN_TRANSACTION 0x07 +#define SCARD_END_TRANSACTION 0x08 +#define SCARD_TRANSMIT 0x09 +#define SCARD_CONTROL 0x0A +#define SCARD_STATUS 0x0B +#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_CANCEL 0x0D +#define SCARD_CANCEL_TRANSACTION 0x0E +#define SCARD_GET_ATTRIB 0x0F +#define SCARD_SET_ATTRIB 0x10 #define SCARD_S_SUCCESS 0x00000000 #define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) @@ -417,7 +428,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - if (code != SCARD_RELEASE_CONTEXT) + if (code != SCARD_CONNECT) { LLOGLN(0, ("SCardConnect: error, bad code")); pthread_mutex_unlock(&g_mutex); @@ -467,6 +478,11 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) { + char msg[256]; + int code; + int bytes; + int status; + LLOGLN(0, ("SCardBeginTransaction:")); if (g_sck == -1) { @@ -474,8 +490,30 @@ SCardBeginTransaction(SCARDHANDLE hCard) return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hCard); + if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4)) + { + LLOGLN(0, ("SCardBeginTransaction: 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, ("SCardBeginTransaction: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 1a81efea..e4d144bd 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -1163,6 +1163,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) /* insert reader name */ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, 0); + xstream_wr_u32_le(s, 0); xstream_wr_u32_le(s, num_chars); if (wide) { @@ -1178,6 +1180,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) xstream_wr_u8(s, w_reader_name[index]); } } + align_s(s, 4); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1670,6 +1673,7 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -1689,7 +1693,9 @@ 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"); } diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 7af1871c..4d496c97 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -56,6 +56,7 @@ #define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ #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 */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -347,6 +348,61 @@ scard_process_connect(struct trans *con, struct stream *in_s) return 0; } +/*****************************************************************************/ +int APP_CC +scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len) +{ + int dwActiveProtocol; + int hCard; + int bytes; + struct stream *out_s; + + g_hexdump(in_s->p, len); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) + { + LLOGLN(0, ("scard_function_connect_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 36); + in_uint32_le(in_s, hCard); + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, hCard); + out_uint32_le(out_s, dwActiveProtocol); + 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, 0x04); /* SCARD_CONNECT 0x04 */ + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_begin_transaction(struct trans *con, struct stream *in_s) +{ + int hCard; + + LLOGLN(0, ("scard_process_begin_transaction:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) + { + LLOGLN(0, ("scard_process_begin_transaction: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT; + in_uint32_le(in_s, hCard); + LLOGLN(0, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); + scard_send_begin_transaction(con, hCard); + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -495,6 +551,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x07: /* SCARD_BEGIN_TRANSACTION */ LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION")); + rv = scard_process_begin_transaction(con, in_s); break; case 0x08: /* SCARD_END_TRANSACTION */ diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 81bf5046..94effea9 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -41,5 +41,8 @@ int APP_CC scard_function_list_readers_return(struct trans *con, int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, int len); +int APP_CC scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */