From 38eba8aac149bdc0d876a451e4716d01a70b9e7c Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Dec 2013 00:07:24 -0800 Subject: [PATCH] chansrv: work on smartcard, mstsc and 64 bit client --- sesman/chansrv/pcsc/xrdp_pcsc.c | 109 ++++++-- sesman/chansrv/smartcard.c | 323 +++++++++++++---------- sesman/chansrv/smartcard.h | 54 ++-- sesman/chansrv/smartcard_pcsc.c | 448 +++++++++++++++++++++++++++----- 4 files changed, 690 insertions(+), 244 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index eed4787e..b9ede3fa 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -57,6 +57,7 @@ PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 }; PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_RAW, 8 }; #define LLOG_LEVEL 5 +//#define LLOG_LEVEL 11 #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) @@ -482,7 +483,8 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, *phCard = GET_UINT32(msg, 0); *pdwActiveProtocol = GET_UINT32(msg, 4); status = GET_UINT32(msg, 8); - LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status)); + LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard %d", + status, *phCard)); return status; } @@ -510,7 +512,8 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) int bytes; int status; - LLOGLN(10, ("SCardDisconnect:")); + LLOGLN(10, ("SCardDisconnect: hCard %d dwDisposition %d", + hCard, dwDisposition)); if (g_sck == -1) { LLOGLN(0, ("SCardDisconnect: error, not connected")); @@ -549,7 +552,12 @@ SCardBeginTransaction(SCARDHANDLE hCard) int bytes; int status; - LLOGLN(10, ("SCardBeginTransaction:")); + LLOGLN(10, ("SCardBeginTransaction: hCard %d", hCard)); + if (hCard == 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, bad hCard")); + return SCARD_F_INTERNAL_ERROR; + } if (g_sck == -1) { LLOGLN(0, ("SCardBeginTransaction: error, not connected")); @@ -632,6 +640,11 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, int to_copy; LLOGLN(10, ("SCardStatus:")); + if (hCard == 0) + { + LLOGLN(0, ("SCardStatus: error, bad hCard")); + return SCARD_F_INTERNAL_ERROR; + } if (g_sck == -1) { LLOGLN(0, ("SCardStatus: error, not connected")); @@ -734,11 +747,13 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, offset = 12; for (index = 0; index < cReaders; index++) { + rgReaderStates[index].dwCurrentState &= ~2; + rgReaderStates[index].dwEventState &= ~2; rname = rgReaderStates[index].szReader; if (strcmp(rname, "\\\\?PnP?\\Notification") == 0) { - LLOGLN(10, (" found \\\\?PnP?\\Notification")); - dwCurrentState = 0x00010000; + LLOGLN(10, (" \\\\?PnP?\\Notification present")); + dwCurrentState = 0; dwEventState = 0; cbAtr = 0; memset(atr, 0, 36); @@ -794,21 +809,46 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders)); for (index = 0; index < cReaders; index++) { - LLOGLN(10, (" out szReader %s", rgReaderStates[index].szReader)); - dwCurrentState = GET_UINT32(msg, offset); - rgReaderStates[index].dwCurrentState = dwCurrentState; - offset += 4; - LLOGLN(10, (" out dwCurrentState 0x%8.8x", dwCurrentState)); - dwEventState = GET_UINT32(msg, offset); - rgReaderStates[index].dwEventState = dwEventState; - offset += 4; - LLOGLN(10, (" out dwEventState 0x%8.8x", dwEventState)); - cbAtr = GET_UINT32(msg, offset); - rgReaderStates[index].cbAtr = cbAtr; - offset += 4; - LLOGLN(10, (" out cbAtr %d", cbAtr)); - memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); - offset += 36; + rname = rgReaderStates[index].szReader; +#if 1 + if (strcmp(rname, "\\\\?PnP?\\Notification") == 0) + { + LLOGLN(10, (" out szReader %s", rgReaderStates[index].szReader)); + dwCurrentState = GET_UINT32(msg, offset); + rgReaderStates[index].dwCurrentState = dwCurrentState; + offset += 4; + LLOGLN(10, (" out dwCurrentState 0x%8.8x", dwCurrentState)); + // disable PnP for now + dwEventState = 4; // GET_UINT32(msg, offset); + rgReaderStates[index].dwEventState = dwEventState; + offset += 4; + LLOGLN(10, (" out dwEventState 0x%8.8x", dwEventState)); + cbAtr = GET_UINT32(msg, offset); + rgReaderStates[index].cbAtr = cbAtr; + offset += 4; + LLOGLN(10, (" out cbAtr %d", cbAtr)); + memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); + offset += 36; + } + else +#endif + { + LLOGLN(10, (" out szReader %s", rgReaderStates[index].szReader)); + dwCurrentState = GET_UINT32(msg, offset); + rgReaderStates[index].dwCurrentState = dwCurrentState; + offset += 4; + LLOGLN(10, (" out dwCurrentState 0x%8.8x", dwCurrentState)); + dwEventState = GET_UINT32(msg, offset); + rgReaderStates[index].dwEventState = dwEventState; + offset += 4; + LLOGLN(10, (" out dwEventState 0x%8.8x", dwEventState)); + cbAtr = GET_UINT32(msg, offset); + rgReaderStates[index].cbAtr = cbAtr; + offset += 4; + LLOGLN(10, (" out cbAtr %d", cbAtr)); + memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); + offset += 36; + } } status = GET_UINT32(msg, offset); offset += 4; @@ -1147,13 +1187,38 @@ SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) PCSC_API LONG SCardCancel(SCARDCONTEXT hContext) { - LLOGLN(0, ("SCardCancel:")); + char msg[256]; + int code; + int bytes; + int status; + + LLOGLN(10, ("SCardCancel:")); if (g_sck == -1) { LLOGLN(0, ("SCardCancel: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - return SCARD_S_SUCCESS; + SET_UINT32(msg, 0, hContext); + if (send_message(SCARD_CANCEL, msg, 4) != 0) + { + LLOGLN(0, ("SCardCancel: error, send_message")); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + code = SCARD_CANCEL; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardCancel: error, get_message")); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4)) + { + LLOGLN(0, ("SCardCancel: error, bad code")); + return SCARD_F_INTERNAL_ERROR; + } + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardCancel: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index edd97803..7fba494a 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -166,35 +166,54 @@ static int APP_CC scard_get_free_slot(void); static void APP_CC scard_release_resources(void); #endif static void APP_CC scard_send_EstablishContext(IRP *irp, int scope); -static void APP_CC scard_send_ReleaseContext(IRP *irp, tui32 context); -static void APP_CC scard_send_IsContextValid(IRP* irp, tui32 context); -static void APP_CC scard_send_ListReaders(IRP *irp, tui32 context, +static void APP_CC scard_send_ReleaseContext(IRP *irp, + char *context, int context_bytes); +static void APP_CC scard_send_IsContextValid(IRP* irp, + char *context, int context_bytes); +static void APP_CC scard_send_ListReaders(IRP *irp, + char *context, int context_bytes, char *groups, int cchReaders, int wide); -static void APP_CC scard_send_GetStatusChange(IRP *irp, tui32 context, int wide, +static void APP_CC scard_send_GetStatusChange(IRP *irp, + char *context, int context_bytes, + int wide, tui32 timeout, tui32 num_readers, READER_STATE *rsa); -static void APP_CC scard_send_Connect(IRP *irp, tui32 context, int wide, +static void APP_CC scard_send_Connect(IRP *irp, + char *context, int context_bytes, + int wide, READER_STATE *rs); -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_Reconnect(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, + READER_STATE *rs); +static void APP_CC scard_send_BeginTransaction(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes); +static void APP_CC scard_send_EndTransaction(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition); -static void APP_CC scard_send_Status(IRP *irp, int wide, tui32 sc_handle, +static void APP_CC scard_send_Status(IRP *irp, int wide, + char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen); -static void APP_CC scard_send_Disconnect(IRP *irp, tui32 context, - tui32 sc_handle, int dwDisposition); -static int APP_CC scard_send_Transmit(IRP *irp, tui32 sc_handle, +static void APP_CC scard_send_Disconnect(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, + int dwDisposition); +static int APP_CC scard_send_Transmit(IRP *irp, + char *context, int context_byte, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior); -static int APP_CC scard_send_Control(IRP* irp, tui32 sc_handle, +static int APP_CC scard_send_Control(IRP* irp, char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code); -static int APP_CC scard_send_Cancel(IRP *irp, tui32 context); -static int APP_CC scard_send_GetAttrib(IRP *irp, tui32 sc_handle, +static int APP_CC scard_send_Cancel(IRP *irp, char *context, int context_bytes); +static int APP_CC scard_send_GetAttrib(IRP *irp, char *card, int card_bytes, READER_STATE *rs); /****************************************************************************** @@ -364,7 +383,8 @@ scard_send_establish_context(void *user_data, int scope) * Release a previously established Smart Card context *****************************************************************************/ int APP_CC -scard_send_release_context(void *user_data, tui32 context) +scard_send_release_context(void *user_data, + char *context, int context_bytes) { IRP *irp; @@ -382,7 +402,7 @@ scard_send_release_context(void *user_data, tui32 context) irp->user_data = user_data; /* send IRP to client */ - scard_send_ReleaseContext(irp, context); + scard_send_ReleaseContext(irp, context, context_bytes); return 0; } @@ -391,7 +411,7 @@ scard_send_release_context(void *user_data, tui32 context) * Checks if a previously established context is still valid *****************************************************************************/ int APP_CC -scard_send_is_valid_context(void *user_data, tui32 context) +scard_send_is_valid_context(void *user_data, char *context, int context_bytes) { IRP *irp; @@ -409,7 +429,7 @@ scard_send_is_valid_context(void *user_data, tui32 context) irp->user_data = user_data; /* send IRP to client */ - scard_send_IsContextValid(irp, context); + scard_send_IsContextValid(irp, context, context_bytes); return 0; } @@ -418,8 +438,8 @@ scard_send_is_valid_context(void *user_data, tui32 context) * *****************************************************************************/ int APP_CC -scard_send_list_readers(void *user_data, tui32 context, char *groups, - int cchReaders, int wide) +scard_send_list_readers(void *user_data, char *context, int context_bytes, + char *groups, int cchReaders, int wide) { IRP *irp; @@ -436,7 +456,8 @@ scard_send_list_readers(void *user_data, tui32 context, char *groups, irp->user_data = user_data; /* send IRP to client */ - scard_send_ListReaders(irp, context, groups, cchReaders, wide); + scard_send_ListReaders(irp, context, context_bytes, groups, + cchReaders, wide); return 0; } @@ -451,8 +472,8 @@ scard_send_list_readers(void *user_data, tui32 context, char *groups, * @param rsa array of READER_STATEs *****************************************************************************/ int APP_CC -scard_send_get_status_change(void *user_data, tui32 context, int wide, - tui32 timeout, tui32 num_readers, +scard_send_get_status_change(void *user_data, char *context, int context_bytes, + int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa) { IRP *irp; @@ -471,7 +492,8 @@ scard_send_get_status_change(void *user_data, tui32 context, int wide, irp->user_data = user_data; /* send IRP to client */ - scard_send_GetStatusChange(irp, context, wide, timeout, num_readers, rsa); + scard_send_GetStatusChange(irp, context, context_bytes, wide, timeout, + num_readers, rsa); return 0; } @@ -483,8 +505,8 @@ scard_send_get_status_change(void *user_data, tui32 context, int wide, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_connect(void *user_data, tui32 context, int wide, - READER_STATE* rs) +scard_send_connect(void *user_data, char *context, int context_bytes, + int wide, READER_STATE* rs) { IRP *irp; @@ -502,7 +524,7 @@ scard_send_connect(void *user_data, tui32 context, int wide, irp->user_data = user_data; /* send IRP to client */ - scard_send_Connect(irp, context, wide, rs); + scard_send_Connect(irp, context, context_bytes, wide, rs); return 0; } @@ -519,8 +541,8 @@ scard_send_connect(void *user_data, tui32 context, int wide, * rs.init_type *****************************************************************************/ int APP_CC -scard_send_reconnect(void *user_data, tui32 context, tui32 sc_handle, - READER_STATE* rs) +scard_send_reconnect(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, READER_STATE* rs) { IRP *irp; @@ -538,7 +560,7 @@ scard_send_reconnect(void *user_data, tui32 context, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_Reconnect(irp, context, sc_handle, rs); + scard_send_Reconnect(irp, context, context_bytes, card, card_bytes, rs); return 0; } @@ -550,7 +572,8 @@ scard_send_reconnect(void *user_data, tui32 context, tui32 sc_handle, * @param con connection to client *****************************************************************************/ int APP_CC -scard_send_begin_transaction(void *user_data, tui32 sc_handle) +scard_send_begin_transaction(void *user_data, char *context, int context_bytes, + char *card, int card_bytes) { IRP *irp; @@ -568,7 +591,7 @@ scard_send_begin_transaction(void *user_data, tui32 sc_handle) irp->user_data = user_data; /* send IRP to client */ - scard_send_BeginTransaction(irp, sc_handle); + scard_send_BeginTransaction(irp, context, context_bytes, card, card_bytes); return 0; } @@ -581,7 +604,8 @@ scard_send_begin_transaction(void *user_data, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ int APP_CC -scard_send_end_transaction(void *user_data, tui32 sc_handle, +scard_send_end_transaction(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition) { IRP *irp; @@ -600,7 +624,8 @@ scard_send_end_transaction(void *user_data, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_EndTransaction(irp, sc_handle, dwDisposition); + scard_send_EndTransaction(irp, context, context_bytes, + card, card_bytes, dwDisposition); return 0; } @@ -612,7 +637,8 @@ scard_send_end_transaction(void *user_data, tui32 sc_handle, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_status(void *user_data, int wide, tui32 sc_handle, +scard_send_status(void *user_data, int wide, char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen) { IRP *irp; @@ -631,7 +657,8 @@ scard_send_status(void *user_data, int wide, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_Status(irp, wide, sc_handle, cchReaderLen, cbAtrLen); + scard_send_Status(irp, wide, context, context_bytes, card, card_bytes, + cchReaderLen, cbAtrLen); return 0; } @@ -643,8 +670,8 @@ scard_send_status(void *user_data, int wide, tui32 sc_handle, * @param sc_handle handle to smartcard *****************************************************************************/ int APP_CC -scard_send_disconnect(void *user_data, tui32 context, tui32 sc_handle, - int dwDisposition) +scard_send_disconnect(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, int dwDisposition) { IRP *irp; @@ -662,7 +689,8 @@ scard_send_disconnect(void *user_data, tui32 context, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_Disconnect(irp, context, sc_handle, dwDisposition); + scard_send_Disconnect(irp, context, context_bytes, + card, card_bytes, dwDisposition); return 0; } @@ -672,7 +700,8 @@ scard_send_disconnect(void *user_data, tui32 context, tui32 sc_handle, * associated with a valid context. *****************************************************************************/ int APP_CC -scard_send_transmit(void *user_data, tui32 sc_handle, +scard_send_transmit(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior) @@ -693,8 +722,9 @@ scard_send_transmit(void *user_data, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_Transmit(irp, sc_handle, send_data, send_bytes, recv_bytes, - send_ior, recv_ior); + scard_send_Transmit(irp, context, context_bytes, card, card_bytes, + send_data, send_bytes, + recv_bytes, send_ior, recv_ior); return 0; } @@ -703,7 +733,7 @@ scard_send_transmit(void *user_data, tui32 sc_handle, * Communicate directly with the smart card reader *****************************************************************************/ int APP_CC -scard_send_control(void *user_data, tui32 sc_handle, +scard_send_control(void *user_data, char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { @@ -723,7 +753,7 @@ scard_send_control(void *user_data, tui32 sc_handle, irp->user_data = user_data; /* send IRP to client */ - scard_send_Control(irp, sc_handle, send_data, + scard_send_Control(irp, card, card_bytes, send_data, send_bytes, recv_bytes, control_code); return 0; @@ -733,7 +763,7 @@ scard_send_control(void *user_data, tui32 sc_handle, * Cancel any outstanding calls *****************************************************************************/ int APP_CC -scard_send_cancel(void *user_data, tui32 context) +scard_send_cancel(void *user_data, char *context, int context_bytes) { IRP *irp; @@ -751,7 +781,7 @@ scard_send_cancel(void *user_data, tui32 context) irp->user_data = user_data; /* send IRP to client */ - scard_send_Cancel(irp, context); + scard_send_Cancel(irp, context, context_bytes); return 0; } @@ -760,7 +790,8 @@ scard_send_cancel(void *user_data, tui32 context) * Get reader attributes *****************************************************************************/ int APP_CC -scard_send_get_attrib(void *user_data, tui32 sc_handle, READER_STATE* rs) +scard_send_get_attrib(void *user_data, char *card, int card_bytes, + READER_STATE* rs) { IRP *irp; @@ -778,7 +809,7 @@ scard_send_get_attrib(void *user_data, tui32 sc_handle, READER_STATE* rs) irp->user_data = user_data; /* send IRP to client */ - scard_send_GetAttrib(irp, sc_handle, rs); + scard_send_GetAttrib(irp, card, card_bytes, rs); return 0; } @@ -966,7 +997,7 @@ scard_send_EstablishContext(IRP *irp, int scope) * Release a previously established Smart Card context *****************************************************************************/ static void APP_CC -scard_send_ReleaseContext(IRP *irp, tui32 context) +scard_send_ReleaseContext(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.2 */ @@ -988,10 +1019,10 @@ scard_send_ReleaseContext(IRP *irp, tui32 context) s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); s_mark_end(s); @@ -1017,7 +1048,7 @@ scard_send_ReleaseContext(IRP *irp, tui32 context) * Checks if a previously established context is still valid *****************************************************************************/ static void APP_CC -scard_send_IsContextValid(IRP *irp, tui32 context) +scard_send_IsContextValid(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.3 */ @@ -1049,14 +1080,19 @@ scard_send_IsContextValid(IRP *irp, tui32 context) * u32 4 bytes context */ - xstream_wr_u32_le(s, 16); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); s_mark_end(s); + 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; @@ -1074,8 +1110,8 @@ scard_send_IsContextValid(IRP *irp, tui32 context) * *****************************************************************************/ static void APP_CC -scard_send_ListReaders(IRP *irp, tui32 context, char *groups, - int cchReaders, int wide) +scard_send_ListReaders(IRP *irp, char *context, int context_bytes, + char *groups, int cchReaders, int wide) { /* see [MS-RDPESC] 2.2.2.4 */ @@ -1121,7 +1157,7 @@ scard_send_ListReaders(IRP *irp, tui32 context, char *groups, s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); out_uint32_le(s, bytes_groups); out_uint32_le(s, val); @@ -1129,8 +1165,8 @@ scard_send_ListReaders(IRP *irp, tui32 context, char *groups, out_uint32_le(s, cchReaders); /* insert context */ - out_uint32_le(s, 4); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); if (bytes_groups > 0) { @@ -1206,7 +1242,8 @@ align_s(struct stream *s, int bytes) * @param rsa array of READER_STATEs *****************************************************************************/ static void APP_CC -scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, +scard_send_GetStatusChange(IRP* irp, char *context, int context_bytes, + int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa) { /* see [MS-RDPESC] 2.2.2.11 for ASCII */ @@ -1239,7 +1276,7 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); out_uint32_le(s, timeout); @@ -1247,8 +1284,8 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, out_uint32_le(s, 0x00020004); /* ? */ /* insert context */ - out_uint32_le(s, 4); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); out_uint32_le(s, num_readers); @@ -1336,7 +1373,8 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, * @param rs reader state *****************************************************************************/ static void APP_CC -scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) +scard_send_Connect(IRP* irp, char *context, int context_bytes, + int wide, READER_STATE* rs) { /* see [MS-RDPESC] 2.2.2.13 for ASCII */ /* see [MS-RDPESC] 2.2.2.14 for Wide char */ @@ -1367,7 +1405,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020004); out_uint32_le(s, rs->dwShareMode); out_uint32_le(s, rs->dwPreferredProtocols); @@ -1396,8 +1434,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) align_s(s, 4); /* insert context */ - out_uint32_le(s, 4); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); out_uint32_le(s, 0); s_mark_end(s); @@ -1432,7 +1470,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) * rs.init_type *****************************************************************************/ static void APP_CC -scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs) +scard_send_Reconnect(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.15 */ /* see [MS-RDPESC] 3.1.4.36 */ @@ -1470,14 +1509,15 @@ scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs) * u32 4 bytes handle */ - xstream_seek(s, 24); - xstream_wr_u32_le(s, rs->dwShareMode); - xstream_wr_u32_le(s, rs->dwPreferredProtocols); - xstream_wr_u32_le(s, rs->init_type); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + xstream_seek(s, 24); /* TODO */ + + out_uint32_le(s, rs->dwShareMode); + out_uint32_le(s, rs->dwPreferredProtocols); + out_uint32_le(s, rs->init_type); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); s_mark_end(s); @@ -1501,7 +1541,8 @@ scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs) * @param con connection to client *****************************************************************************/ static void APP_CC -scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) +scard_send_BeginTransaction(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes) { /* see [MS-RDPESC] 4.9 */ @@ -1523,17 +1564,20 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); - out_uint32_le(s, 0x00000002); - /* insert handle */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + out_uint32_le(s, 0x00000000); s_mark_end(s); @@ -1564,7 +1608,9 @@ 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, tui32 dwDisposition) +scard_send_EndTransaction(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, + tui32 dwDisposition) { /* see [MS-RDPESC] 3.1.4.32 */ @@ -1586,17 +1632,20 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); out_uint32_le(s, dwDisposition); - out_uint32_le(s, 0x00000004); - out_uint32_le(s, 0x00000009); - /* insert handle */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + out_uint32_le(s, 0); s_mark_end(s); @@ -1626,7 +1675,8 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) * @param wide TRUE if unicode string *****************************************************************************/ static void APP_CC -scard_send_Status(IRP *irp, int wide, tui32 sc_handle, +scard_send_Status(IRP *irp, int wide, char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen) { /* see [MS-RDPESC] 2.2.2.18 */ @@ -1666,18 +1716,22 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, */ s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); out_uint32_le(s, 0x00000001); out_uint32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ out_uint32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ - out_uint32_le(s, 0x00000004); - out_uint32_le(s, 0x00000007); - /* insert sc_handle */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + out_uint32_le(s, 0); s_mark_end(s); @@ -1709,8 +1763,8 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, * @param sc_handle handle to smartcard *****************************************************************************/ static void APP_CC -scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, - int dwDisposition) +scard_send_Disconnect(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, int dwDisposition) { /* see [MS-RDPESC] 3.1.4.30 */ @@ -1732,19 +1786,19 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); out_uint32_le(s, dwDisposition); /* insert context */ - out_uint32_le(s, 4); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - /* insert handle */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); out_uint32_le(s, 0x00000000); @@ -1773,7 +1827,8 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, * associated with a valid context. *****************************************************************************/ static int APP_CC -scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, +scard_send_Transmit(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior) @@ -1876,10 +1931,10 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 4); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); /* map0 */ - out_uint32_le(s, 4); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); /* map1 */ out_uint32_le(s, send_ior->dwProtocol); @@ -1900,12 +1955,12 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, out_uint32_le(s, recv_bytes); /* map0 */ - out_uint32_le(s, 4); - out_uint32_le(s, 5); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); /* map1 */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); if (send_ior->extra_bytes > 0) { @@ -1965,7 +2020,7 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data, * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP *irp, tui32 sc_handle, char *send_data, +scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ @@ -2001,8 +2056,8 @@ scard_send_Control(IRP *irp, tui32 sc_handle, char *send_data, out_uint32_le(s, recv_bytes); out_uint32_le(s, 4); out_uint32_le(s, 0); /* context ? */ - out_uint32_le(s, 4); - out_uint32_le(s, sc_handle); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); if (send_bytes > 0) { out_uint32_le(s, send_bytes); @@ -2040,7 +2095,7 @@ scard_send_Control(IRP *irp, tui32 sc_handle, char *send_data, * Cancel any outstanding calls *****************************************************************************/ static int APP_CC -scard_send_Cancel(IRP *irp, tui32 context) +scard_send_Cancel(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.27 */ @@ -2062,10 +2117,10 @@ scard_send_Cancel(IRP *irp, tui32 context) s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ out_uint32_le(s, 0x00000000); - out_uint32_le(s, 0x00000004); + out_uint32_le(s, context_bytes); out_uint32_le(s, 0x00020000); - out_uint32_le(s, 4); - out_uint32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); s_mark_end(s); @@ -2092,7 +2147,7 @@ scard_send_Cancel(IRP *irp, tui32 context) * Get reader attributes *****************************************************************************/ static int APP_CC -scard_send_GetAttrib(IRP *irp, tui32 sc_handle, READER_STATE *rs) +scard_send_GetAttrib(IRP *irp, char *card, int card_bytes, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.21 */ @@ -2128,13 +2183,13 @@ scard_send_GetAttrib(IRP *irp, tui32 sc_handle, READER_STATE *rs) * u32 4 bytes handle */ - xstream_seek(s, 24); - xstream_wr_u32_le(s, rs->dwAttribId); - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, rs->dwAttrLen); + xstream_seek(s, 24); /* TODO */ + out_uint32_le(s, rs->dwAttribId); + out_uint32_le(s, 0); + out_uint32_le(s, rs->dwAttrLen); xstream_seek(s, 8); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); s_mark_end(s); diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 437bbdbf..5004f498 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -111,41 +111,59 @@ int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); int APP_CC scard_send_establish_context(void *user_data, int scope); -int APP_CC scard_send_release_context(void *user_data, tui32 context); -int APP_CC scard_send_is_valid_context(void *user_data, tui32 context); -int APP_CC scard_send_list_readers(void *user_data, tui32 context, +int APP_CC scard_send_release_context(void *user_data, + char *context, int context_bytes); +int APP_CC scard_send_is_valid_context(void *user_data, + char *context, int context_bytes); +int APP_CC scard_send_list_readers(void *user_data, + char *context, int context_bytes, char *groups, int cchReaders, int wide); -int APP_CC scard_send_get_status_change(void *user_data, tui32 context, +int APP_CC scard_send_get_status_change(void *user_data, + char *context, int context_bytes, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); -int APP_CC scard_send_connect(void *user_data, tui32 context, int wide, +int APP_CC scard_send_connect(void *user_data, + char *context, int context_bytes, int wide, READER_STATE* rs); -int APP_CC scard_send_reconnect(void *user_data, tui32 context, - tui32 sc_handle, READER_STATE* rs); - -int APP_CC scard_send_begin_transaction(void *user_data, tui32 sc_handle); -int APP_CC scard_send_end_transaction(void *user_data, tui32 sc_handle, +int APP_CC scard_send_reconnect(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, + READER_STATE* rs); + +int APP_CC scard_send_begin_transaction(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes); +int APP_CC scard_send_end_transaction(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition); -int APP_CC scard_send_status(void *user_data, int wide, tui32 sc_handle, +int APP_CC scard_send_status(void *user_data, int wide, + char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen); -int APP_CC scard_send_disconnect(void *user_data, tui32 context, - tui32 sc_handle, int dwDisposition); - -int APP_CC scard_send_transmit(void *user_data, tui32 sc_handle, +int APP_CC scard_send_disconnect(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, + int dwDisposition); + +int APP_CC scard_send_transmit(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior); -int APP_CC scard_send_control(void *user_data, tui32 sc_handle, +int APP_CC scard_send_control(void *user_data, char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code); -int APP_CC scard_send_cancel(void *user_data, tui32 context); +int APP_CC scard_send_cancel(void *user_data, + char *context, int context_bytes); -int APP_CC scard_send_get_attrib(void *user_data, tui32 sc_handle, +int APP_CC scard_send_get_attrib(void *user_data, char *card, int card_bytes, READER_STATE* rs); /* diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 95c01a04..6063912d 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -63,6 +63,7 @@ #define XRDP_PCSC_STATE_GOT_CO (1 << 8) /* control */ #define XRDP_PCSC_STATE_GOT_D (1 << 9) /* disconnect */ #define XRDP_PCSC_STATE_GOT_ST (1 << 10) /* get status */ +#define XRDP_PCSC_STATE_GOT_CANCEL (1 << 11) /* cancel */ #if 0 /* TODO: put this in con */ @@ -74,15 +75,20 @@ extern int g_display_num; /* in chansrv.c */ static int g_uds_client_id = 0; /* auto incremented for each unix domain socket connection */ +static int g_autoinc = 0; /* general purpose autoinc */ struct pcsc_card /* item for list of open cards in one context */ { - tui32 card; + tui32 app_card; /* application card, always 4 bytes */ + int card_bytes; /* client card bytes */ + char card[8]; /* client card */ }; struct pcsc_context { - tui32 context; + tui32 app_context; /* application context, always 4 byte */ + int context_bytes; /* client context bytes */ + char context[8]; /* client context */ struct list *cards; /* these need to be released on close */ }; @@ -94,6 +100,7 @@ struct pcsc_uds_client struct list *contexts; /* struct pcsc_context */ int pcsc_state; int pcsc_extra1; + struct pcsc_context *connect_context; }; static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */ @@ -162,6 +169,87 @@ get_uds_client_by_id(int uds_client_id) return 0; } +/*****************************************************************************/ +struct pcsc_context * +get_pcsc_context_by_app_context(struct pcsc_uds_client *uds_client, + int app_context) +{ + struct pcsc_context *rv; + int index; + + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts == 0) + { + return 0; + } + for (index = 0; index < uds_client->contexts->count; index++) + { + rv = (struct pcsc_context *) + list_get_item(uds_client->contexts, index); + if (rv->app_context == app_context) + { + return rv; + } + } + return 0; +} + +/*****************************************************************************/ +struct pcsc_card * +get_pcsc_card_by_app_card(struct pcsc_uds_client *uds_client, + int app_card, struct pcsc_context **acontext) +{ + struct pcsc_card *lcard; + struct pcsc_context *lcontext; + int index; + int index1; + + LLOGLN(10, ("get_pcsc_card_by_app_card:")); + LLOGLN(10, (" app_card %d", app_card)); + if (uds_client == 0) + { + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; + } + if (uds_client->contexts == 0) + { + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; + } + for (index = 0; index < uds_client->contexts->count; index++) + { + lcontext = (struct pcsc_context *) + list_get_item(uds_client->contexts, index); + if (lcontext != 0) + { + if (lcontext->cards != 0) + { + for (index1 = 0; index1 < lcontext->cards->count; index1++) + { + lcard = (struct pcsc_card *) + list_get_item(lcontext->cards, index1); + if (lcard != 0) + { + if (lcard->app_card == app_card) + { + if (acontext != 0) + { + *acontext = lcontext; + } + return lcard; + } + } + } + } + } + } + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; +} + /*****************************************************************************/ static int free_uds_client(struct pcsc_uds_client *uds_client) @@ -199,8 +287,9 @@ free_uds_client(struct pcsc_uds_client *uds_client) list_delete(context->cards); } LLOGLN(10, (" left over context 0x%8.8x", context->context)); - scard_send_cancel(0, context->context); - scard_send_release_context(0, context->context); + scard_send_cancel(0, context->context, context->context_bytes); + scard_send_release_context(0, context->context, + context->context_bytes); g_free(context); } } @@ -212,8 +301,9 @@ free_uds_client(struct pcsc_uds_client *uds_client) } /*****************************************************************************/ -static int -uds_client_add_context(struct pcsc_uds_client *uds_client, tui32 context) +static struct pcsc_context * +uds_client_add_context(struct pcsc_uds_client *uds_client, + char *context, int context_bytes) { struct pcsc_context *pcscContext; @@ -223,25 +313,52 @@ uds_client_add_context(struct pcsc_uds_client *uds_client, tui32 context) if (pcscContext == 0) { LLOGLN(0, ("uds_client_add_context: error")); - return 1; + return 0; } - pcscContext->context = context; + g_autoinc++; + pcscContext->app_context = g_autoinc; + pcscContext->context_bytes = context_bytes; + g_memcpy(pcscContext->context, context, context_bytes); if (uds_client->contexts == 0) { uds_client->contexts = list_create(); if (uds_client->contexts == 0) { LLOGLN(0, ("uds_client_add_context: error")); - return 1; + return 0; } } list_add_item(uds_client->contexts, (tintptr) pcscContext); + return pcscContext; +} + +/*****************************************************************************/ +static int +uds_client_remove_context(struct pcsc_uds_client *uds_client, + struct pcsc_context *acontext) +{ + int index; + + if (uds_client->contexts == 0) + { + LLOGLN(0, ("uds_client_remove_context: error")); + return 1; + } + index = list_index_of(uds_client->contexts, (tintptr) acontext); + if (index < 0) + { + LLOGLN(0, ("uds_client_remove_context: error")); + return 1; + } + list_remove_item(uds_client->contexts, index); + g_free(acontext); // TODO free cards return 0; } /*****************************************************************************/ static int -uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context) +uds_client_remove_context1(struct pcsc_uds_client *uds_client, + char *context, int context_bytes) { int index; struct pcsc_context *pcscContext; @@ -258,7 +375,8 @@ uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context) list_get_item(uds_client->contexts, index); if (pcscContext != 0) { - if (pcscContext->context == context) + if ((pcscContext->context_bytes == context_bytes) && + (g_memcmp(pcscContext->context, context, context_bytes) == 0)) { list_remove_item(uds_client->contexts, index); g_free(pcscContext); @@ -270,6 +388,40 @@ uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context) return 1; } +/*****************************************************************************/ +static struct pcsc_card * +context_add_card(struct pcsc_uds_client *uds_client, + struct pcsc_context *acontext, + char *card, int card_bytes) +{ + struct pcsc_card *pcscCard; + + LLOGLN(10, ("context_add_card:")); + pcscCard = (struct pcsc_card * ) + g_malloc(sizeof(struct pcsc_card), 1); + if (pcscCard == 0) + { + LLOGLN(0, ("context_add_card: error")); + return 0; + } + g_autoinc++; + pcscCard->app_card = g_autoinc; + pcscCard->card_bytes = card_bytes; + g_memcpy(pcscCard->card, card, card_bytes); + if (acontext->cards == 0) + { + acontext->cards = list_create(); + if (acontext->cards == 0) + { + LLOGLN(0, ("context_add_card: error")); + return 0; + } + } + list_add_item(acontext->cards, (tintptr) pcscCard); + LLOGLN(10, (" new app_card %d", pcscCard->app_card)); + return pcscCard; +} + /*****************************************************************************/ int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) @@ -386,11 +538,13 @@ scard_function_establish_context_return(void *user_data, { int bytes; int uds_client_id; - tui32 context; - tui32 context_len; + int context_bytes; + int app_context; + char context[8]; struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_function_establish_context_return:")); LLOGLN(10, (" status 0x%8.8x", status)); @@ -411,25 +565,29 @@ scard_function_establish_context_return(void *user_data, return 1; } uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; - context = 0; + lcontext = 0; + app_context = 0; + g_memset(context, 0, 8); if (status == 0) { in_uint8s(in_s, 28); - in_uint32_le(in_s, context_len); - if (context_len != 4) + in_uint32_le(in_s, context_bytes); + if (context_bytes > 8) { LLOGLN(0, ("scard_function_establish_context_return: opps " - "context_len %d", context_len)); + "context_bytes %d", context_bytes)); + g_hexdump(in_s->p, context_bytes); return 1; } - in_uint32_le(in_s, context); - uds_client_add_context(uds_client, context); + in_uint8a(in_s, context, context_bytes); + lcontext = uds_client_add_context(uds_client, context, context_bytes); + app_context = lcontext->app_context; LLOGLN(10, ("scard_function_establish_context_return: " - "context 0x%8.8x", context)); + "app_context %d", app_context)); } out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, context); + out_uint32_le(out_s, app_context); out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); @@ -446,21 +604,30 @@ scard_process_release_context(struct trans *con, struct stream *in_s) { int hContext; struct pcsc_uds_client *uds_client; + struct pcsc_context *lcontext; void *user_data; LLOGLN(10, ("scard_process_release_context:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_RC) { - LLOGLN(0, ("scard_process_establish_context: opps")); + LLOGLN(0, ("scard_process_release_context: opps")); return 1; } uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_RC; in_uint32_le(in_s, hContext); LLOGLN(10, ("scard_process_release_context: hContext 0x%8.8x", hContext)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_release_context(user_data, hContext); - uds_client_remove_context(uds_client, hContext); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_release_context: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_release_context(user_data, lcontext->context, + lcontext->context_bytes); + uds_client_remove_context(uds_client, lcontext); return 0; } @@ -517,6 +684,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) char *groups; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_list_readers:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -535,7 +703,15 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d", hContext, cchReaders)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_list_readers(user_data, hContext, groups, cchReaders, 1); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_list_readers: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_list_readers(user_data, lcontext->context, + lcontext->context_bytes, groups, cchReaders, 1); g_free(groups); return 0; } @@ -635,10 +811,6 @@ scard_function_list_readers_return(void *user_data, { out_uint8a(out_s, lreader_name[index], 100); } - //if (readers == 0) - //{ - // status = 0x8010002E; /* SCARD_E_NO_READERS_AVAILABLE */ - //} out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); @@ -657,6 +829,7 @@ scard_process_connect(struct trans *con, struct stream *in_s) READER_STATE rs; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_connect:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -675,7 +848,16 @@ scard_process_connect(struct trans *con, struct stream *in_s) "dwPreferredProtocols 0x%8.8x", rs.reader_name, rs.dwShareMode, rs.dwPreferredProtocols)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_connect(user_data, hContext, 1, &rs); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_connect: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + uds_client->connect_context = lcontext; + scard_send_connect(user_data, lcontext->context, lcontext->context_bytes, + 1, &rs); return 0; } @@ -692,6 +874,9 @@ scard_function_connect_return(void *user_data, struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; + char *card; + int card_bytes; + struct pcsc_card *lcard; LLOGLN(10, ("scard_function_connect_return:")); LLOGLN(10, (" status 0x%8.8x", status)); @@ -717,8 +902,11 @@ scard_function_connect_return(void *user_data, { in_uint8s(in_s, 36); in_uint32_le(in_s, dwActiveProtocol); - in_uint8s(in_s, 4); - in_uint32_le(in_s, hCard); + in_uint32_le(in_s, card_bytes); + in_uint8p(in_s, card, card_bytes); + lcard = context_add_card(uds_client, uds_client->connect_context, + card, card_bytes); + hCard = lcard->app_card; LLOGLN(10, (" hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol)); } out_s = trans_get_out_s(con, 8192); @@ -739,11 +927,12 @@ scard_function_connect_return(void *user_data, int APP_CC scard_process_disconnect(struct trans *con, struct stream *in_s) { - int hContext; int hCard; int dwDisposition; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_context *lcontext; + struct pcsc_card *lcard; LLOGLN(10, ("scard_process_disconnect:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -755,11 +944,17 @@ scard_process_disconnect(struct trans *con, struct stream *in_s) uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_D; in_uint32_le(in_s, hCard); in_uint32_le(in_s, dwDisposition); - - hContext = 1; user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_disconnect(user_data, hContext, hCard, dwDisposition); - + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcontext == 0) || (lcard == 0)) + { + LLOGLN(0, ("scard_process_disconnect: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_disconnect(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, dwDisposition); return 0; } @@ -769,8 +964,6 @@ scard_function_disconnect_return(void *user_data, struct stream *in_s, int len, int status) { - int dwActiveProtocol; - int hCard; int bytes; int uds_client_id; struct stream *out_s; @@ -795,17 +988,6 @@ scard_function_disconnect_return(void *user_data, return 1; } uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_D; - dwActiveProtocol = 0; - hCard = 0; - if (status == 0) - { - in_uint8s(in_s, 36); - in_uint32_le(in_s, dwActiveProtocol); - in_uint8s(in_s, 4); - in_uint32_le(in_s, hCard); - LLOGLN(10, ("scard_function_connect_return: hCard %d " - "dwActiveProtocol %d", hCard, dwActiveProtocol)); - } out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ @@ -825,6 +1007,8 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s) int hCard; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_begin_transaction:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -837,7 +1021,16 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s) in_uint32_le(in_s, hCard); LLOGLN(10, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_begin_transaction(user_data, hCard); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_begin_transaction: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_begin_transaction(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes); return 0; } @@ -892,6 +1085,8 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) int dwDisposition; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_end_transaction:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -905,7 +1100,17 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) in_uint32_le(in_s, dwDisposition); LLOGLN(10, ("scard_process_end_transaction: hCard 0x%8.8x", hCard)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_end_transaction(user_data, hCard, dwDisposition); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_end_transaction: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_end_transaction(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + dwDisposition); return 0; } @@ -952,18 +1157,6 @@ scard_function_end_transaction_return(void *user_data, return trans_force_write(con); } -/*****************************************************************************/ -/* returns error */ -int APP_CC -scard_function_cancel_return(void *user_data, - struct stream *in_s, - int len, int status) -{ - LLOGLN(10, ("scard_function_cancel_return:")); - //g_hexdump(in_s->p, len); - return 0; -} - /*****************************************************************************/ /* returns error */ int APP_CC @@ -987,6 +1180,8 @@ scard_process_transmit(struct trans *con, struct stream *in_s) struct xrdp_scard_io_request recv_ior; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_transmit:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -1016,7 +1211,16 @@ scard_process_transmit(struct trans *con, struct stream *in_s) //g_hexdump(in_s->p, send_bytes); LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_transmit(user_data, hCard, send_data, send_bytes, recv_bytes, + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_transmit: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_transmit(user_data, lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + send_data, send_bytes, recv_bytes, &send_ior, &recv_ior); return 0; } @@ -1116,6 +1320,7 @@ scard_process_control(struct trans *con, struct stream *in_s) char *send_data; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_card *lcard; LLOGLN(10, ("scard_process_control:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -1134,7 +1339,15 @@ scard_process_control(struct trans *con, struct stream *in_s) in_uint32_le(in_s, recv_bytes); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_control(user_data, hCard, send_data, send_bytes, recv_bytes, + lcard = get_pcsc_card_by_app_card(uds_client, hCard, 0); + if (lcard == 0) + { + LLOGLN(0, ("scard_process_control: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_control(user_data, lcard->card, lcard->card_bytes, + send_data, send_bytes, recv_bytes, control_code); return 0; @@ -1205,6 +1418,8 @@ scard_process_status(struct trans *con, struct stream *in_s) int cbAtrLen; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_status:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -1220,7 +1435,16 @@ scard_process_status(struct trans *con, struct stream *in_s) in_uint32_le(in_s, cbAtrLen); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_status(user_data, 1, hCard, cchReaderLen, cbAtrLen); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_status: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_status(user_data, 1, lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + cchReaderLen, cbAtrLen); return 0; } @@ -1343,6 +1567,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) READER_STATE *rsa; struct pcsc_uds_client *uds_client; void *user_data; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_get_status_change:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -1383,8 +1608,16 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) "%d cReaders %d", hContext, dwTimeout, cReaders)); user_data = (void *) (tintptr) (uds_client->uds_client_id); - scard_send_get_status_change(user_data, hContext, 1, dwTimeout, cReaders, rsa); - + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_get_status_change: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_get_status_change(user_data, + lcontext->context, lcontext->context_bytes, + 1, dwTimeout, cReaders, rsa); g_free(rsa); return 0; @@ -1466,6 +1699,80 @@ scard_function_get_status_change_return(void *user_data, return trans_force_write(con); } +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_cancel(struct trans *con, struct stream *in_s) +{ + int hContext; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; + + LLOGLN(10, ("scard_process_cancel:")); + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CANCEL) + { + LLOGLN(0, ("scard_process_cancel: opps")); + return 1; + } + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_CANCEL; + in_uint32_le(in_s, hContext); + LLOGLN(10, ("scard_process_cancel: hContext 0x%8.8x", hContext)); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_cancel: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_cancel(user_data, lcontext->context, lcontext->context_bytes); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_function_cancel_return(void *user_data, + struct stream *in_s, + int len, int status) +{ + int bytes; + int uds_client_id; + struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; + + LLOGLN(10, ("scard_function_cancel_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_cancel_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CANCEL) == 0) + { + LLOGLN(0, ("scard_function_cancel_return: opps")); + return 1; + } + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_CANCEL; + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + 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); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x0D); /* SCARD_CANCEL 0x0D */ + return trans_force_write(con); +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -1555,7 +1862,8 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x0D: /* SCARD_CANCEL */ - LLOGLN(0, ("scard_process_msg: SCARD_CANCEL")); + LLOGLN(10, ("scard_process_msg: SCARD_CANCEL")); + rv = scard_process_cancel(con, in_s); break; case 0x0E: /* SCARD_CANCEL_TRANSACTION */