From 9f8d3697472ce8dc6353172e9a471568d1aec45e Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 30 Dec 2013 13:41:38 -0800 Subject: [PATCH] chansrv: smartcard, fix for SCardControl, SCardTransmit --- sesman/chansrv/pcsc/xrdp_pcsc.c | 21 +++++---- sesman/chansrv/smartcard.c | 25 ++++++----- sesman/chansrv/smartcard.h | 4 +- sesman/chansrv/smartcard_pcsc.c | 75 +++++++++++++++++++-------------- 4 files changed, 75 insertions(+), 50 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 35c0b7b4..f4aaba14 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -461,9 +461,9 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, int offset; LLOGLN(10, ("SCardConnect:")); - LLOGLN(10, ("SCardConnect: hContext %p szReader %s dwShareMode %d " + LLOGLN(10, ("SCardConnect: hContext 0x%8.8x szReader %s dwShareMode %d " "dwPreferredProtocols %d", - (void*)hContext, szReader, dwShareMode, dwPreferredProtocols)); + hContext, szReader, dwShareMode, dwPreferredProtocols)); if (g_sck == -1) { LLOGLN(0, ("SCardConnect: error, not connected")); @@ -505,8 +505,9 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, *phCard = GET_UINT32(msg, 0); *pdwActiveProtocol = GET_UINT32(msg, 4); status = GET_UINT32(msg, 8); - LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard %d", - status, *phCard)); + LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard 0x%8.8x " + "dwActiveProtocol %d", + status, *phCard, *pdwActiveProtocol)); return status; } @@ -534,7 +535,7 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) int bytes; int status; - LLOGLN(10, ("SCardDisconnect: hCard %d dwDisposition %d", + LLOGLN(10, ("SCardDisconnect: hCard 0x%8.8x dwDisposition %d", hCard, dwDisposition)); if (g_sck == -1) { @@ -574,7 +575,7 @@ SCardBeginTransaction(SCARDHANDLE hCard) int bytes; int status; - LLOGLN(10, ("SCardBeginTransaction: hCard %d", hCard)); + LLOGLN(10, ("SCardBeginTransaction: hCard 0x%8.8x", hCard)); if (hCard == 0) { LLOGLN(0, ("SCardBeginTransaction: error, bad hCard")); @@ -967,6 +968,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, int offset; int status; int extra_len; + int got_recv_pci; LLOGLN(10, ("SCardTransmit:")); if (g_sck == -1) @@ -1002,8 +1004,10 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, offset += 4; memcpy(msg + offset, pbSendBuffer, cbSendLength); offset += cbSendLength; - if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) + // TODO figure out why recv pci does not work + if (1 || (pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) { + got_recv_pci = 0; SET_UINT32(msg, offset, 0); /* dwProtocol */ offset += 4; SET_UINT32(msg, offset, 0); /* cbPciLength */ @@ -1013,6 +1017,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, } else { + got_recv_pci = 1; SET_UINT32(msg, offset, pioRecvPci->dwProtocol); offset += 4; SET_UINT32(msg, offset, pioRecvPci->cbPciLength); @@ -1046,7 +1051,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, return SCARD_F_INTERNAL_ERROR; } offset = 0; - if (pioRecvPci == 0) + if (got_recv_pci == 0) { offset += 8; extra_len = GET_UINT32(msg, offset); diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 42a4ebd5..0d6d5405 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -207,7 +207,8 @@ static int APP_CC scard_send_Transmit(IRP *irp, 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, char *card, int card_bytes, +static int APP_CC scard_send_Control(IRP* irp, char *context, int context_bytes, + 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, char *context, int context_bytes); @@ -737,7 +738,8 @@ scard_send_transmit(void *user_data, char *context, int context_bytes, * Communicate directly with the smart card reader *****************************************************************************/ int APP_CC -scard_send_control(void *user_data, char *card, int card_bytes, +scard_send_control(void *user_data, char* context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { @@ -757,8 +759,10 @@ scard_send_control(void *user_data, char *card, int card_bytes, irp->user_data = user_data; /* send IRP to client */ - scard_send_Control(irp, card, card_bytes, send_data, - send_bytes, recv_bytes, control_code); + scard_send_Control(irp, context, context_bytes, + card, card_bytes, + send_data, send_bytes, + recv_bytes, control_code); return 0; } @@ -1981,7 +1985,7 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, { /* map4 */ out_uint32_le(s, recv_ior->dwProtocol); - out_uint32_le(s, recv_ior->cbPciLength); + out_uint32_le(s, recv_ior->cbPciLength - 8); val = recv_ior->extra_bytes > 0 ? 1 : 0; out_uint32_le(s, val); /* map6*/ if (val) @@ -2022,7 +2026,8 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data, +scard_send_Control(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ @@ -2046,9 +2051,9 @@ scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data, 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); /* map0 */ - out_uint32_le(s, 0x00000004); + out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); /* map1 */ out_uint32_le(s, control_code); out_uint32_le(s, send_bytes); @@ -2056,8 +2061,8 @@ scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data, out_uint32_le(s, val); /* map2 */ out_uint32_le(s, 0x00000000); out_uint32_le(s, recv_bytes); - out_uint32_le(s, 4); - out_uint32_le(s, 0); /* context ? */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); out_uint32_le(s, card_bytes); out_uint8a(s, card, card_bytes); if (send_bytes > 0) diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 5004f498..3ea503a8 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -156,7 +156,9 @@ int APP_CC scard_send_transmit(void *user_data, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior); -int APP_CC scard_send_control(void *user_data, char *card, int card_bytes, +int APP_CC scard_send_control(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code); diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index a7bc14b2..1d1618dc 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -53,14 +53,12 @@ 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 app_card; /* application card, always 4 bytes */ - int card_bytes; /* client card bytes */ + tui32 app_card; /* application card, always 4 bytes */ + int card_bytes; /* client card bytes */ char card[16]; /* client card */ }; @@ -68,16 +66,16 @@ struct pcsc_context { tui32 app_context; /* application context, always 4 byte */ int context_bytes; /* client context bytes */ - char context[16]; /* client context */ + char context[16]; /* client context */ struct list *cards; /* these need to be released on close */ }; /*****************************************************************************/ struct pcsc_uds_client { - int uds_client_id; /* from g_uds_client_id */ - struct trans *con; - struct list *contexts; /* struct pcsc_context */ + int uds_client_id; /* unique id represents each app */ + struct trans *con; /* the connection to the app */ + struct list *contexts; /* list of struct pcsc_context */ struct pcsc_context *connect_context; }; @@ -104,8 +102,8 @@ create_uds_client(struct trans *con) { return 0; } - g_uds_client_id++; - uds_client->uds_client_id = g_uds_client_id; + g_autoinc++; + uds_client->uds_client_id = g_autoinc; uds_client->con = con; con->callback_data = uds_client; return uds_client; @@ -283,7 +281,7 @@ uds_client_add_context(struct pcsc_uds_client *uds_client, struct pcsc_context *pcscContext; LLOGLN(10, ("uds_client_add_context:")); - pcscContext = (struct pcsc_context * ) + pcscContext = (struct pcsc_context *) g_malloc(sizeof(struct pcsc_context), 1); if (pcscContext == 0) { @@ -457,7 +455,7 @@ scard_function_establish_context_return(void *user_data, int uds_client_id; int context_bytes; int app_context; - char context[8]; + char context[16]; struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; @@ -477,12 +475,12 @@ scard_function_establish_context_return(void *user_data, con = uds_client->con; lcontext = 0; app_context = 0; - g_memset(context, 0, 8); + g_memset(context, 0, 16); if (status == 0) { in_uint8s(in_s, 28); in_uint32_le(in_s, context_bytes); - if (context_bytes > 8) + if (context_bytes > 16) { LLOGLN(0, ("scard_function_establish_context_return: opps " "context_bytes %d", context_bytes)); @@ -647,6 +645,8 @@ scard_function_list_readers_return(void *user_data, return 1; } uds_client_id = pcscListReaders->uds_client_id; + cchReaders = pcscListReaders->cchReaders; + g_free(pcscListReaders); uds_client = (struct pcsc_uds_client *) get_uds_client_by_id(uds_client_id); if (uds_client == 0) @@ -654,14 +654,9 @@ scard_function_list_readers_return(void *user_data, LLOGLN(0, ("scard_function_list_readers_return: " "get_uds_client_by_id failed, could not find id %d", uds_client_id)); - g_free(pcscListReaders); return 1; } con = uds_client->con; - - cchReaders = pcscListReaders->cchReaders; - g_free(pcscListReaders); - g_memset(reader_name, 0, sizeof(reader_name)); g_memset(lreader_name, 0, sizeof(lreader_name)); rn_index = 0; @@ -1031,6 +1026,14 @@ scard_function_get_attrib_return(void *user_data, return 0; } +/*****************************************************************************/ +struct pcsc_transmit +{ + int uds_client_id; + struct xrdp_scard_io_request recv_ior; + int cbRecvLength; +}; + /*****************************************************************************/ /* returns error */ int APP_CC @@ -1043,9 +1046,9 @@ scard_process_transmit(struct trans *con, struct stream *in_s) struct xrdp_scard_io_request send_ior; struct xrdp_scard_io_request recv_ior; struct pcsc_uds_client *uds_client; - void *user_data; struct pcsc_card *lcard; struct pcsc_context *lcontext; + struct pcsc_transmit *pcscTransmit; LLOGLN(10, ("scard_process_transmit:")); uds_client = (struct pcsc_uds_client *) (con->callback_data); @@ -1066,9 +1069,7 @@ scard_process_transmit(struct trans *con, struct stream *in_s) "recv dwProtocol %d cbPciLength %d send_bytes %d ", send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol, recv_ior.cbPciLength, send_bytes)); - //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); lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); if ((lcard == 0) || (lcontext == 0)) { @@ -1076,7 +1077,15 @@ scard_process_transmit(struct trans *con, struct stream *in_s) "get_pcsc_card_by_app_card failed")); return 1; } - scard_send_transmit(user_data, lcontext->context, lcontext->context_bytes, + + pcscTransmit = (struct pcsc_transmit *) + g_malloc(sizeof(struct pcsc_transmit), 1); + pcscTransmit->uds_client_id = uds_client->uds_client_id; + pcscTransmit->recv_ior = recv_ior; + pcscTransmit->cbRecvLength = recv_bytes; + + scard_send_transmit(pcscTransmit, + lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes, send_data, send_bytes, recv_bytes, &send_ior, &recv_ior); @@ -1094,17 +1103,20 @@ scard_function_transmit_return(void *user_data, int bytes; int val; int cbRecvLength; - int uds_client_id; - struct xrdp_scard_io_request recv_ior; char *recvBuf; + struct xrdp_scard_io_request recv_ior; struct pcsc_uds_client *uds_client; struct trans *con; + struct pcsc_transmit *pcscTransmit; LLOGLN(10, ("scard_function_transmit_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - uds_client_id = (int) (tintptr) user_data; + pcscTransmit = (struct pcsc_transmit *) user_data; + recv_ior = pcscTransmit->recv_ior; uds_client = (struct pcsc_uds_client *) - get_uds_client_by_id(uds_client_id); + get_uds_client_by_id(pcscTransmit->uds_client_id); + g_free(pcscTransmit); + if (uds_client == 0) { LLOGLN(0, ("scard_function_transmit_return: " @@ -1112,7 +1124,6 @@ scard_function_transmit_return(void *user_data, return 1; } con = uds_client->con; - g_memset(&recv_ior, 0, sizeof(recv_ior)); cbRecvLength = 0; recvBuf = 0; if (status == 0) @@ -1172,6 +1183,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_context *lcontext; struct pcsc_card *lcard; LLOGLN(10, ("scard_process_control:")); @@ -1185,14 +1197,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); - lcard = get_pcsc_card_by_app_card(uds_client, hCard, 0); - if (lcard == 0) + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 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, + scard_send_control(user_data, lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, send_data, send_bytes, recv_bytes, control_code);