From 8bddeae9bc9cdf6a42675dc16479a51d1cae0dd3 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 28 Nov 2017 16:39:00 -0800 Subject: [PATCH 01/11] set PCSCLITE_CSOCK_NAME env var --- sesman/env.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sesman/env.c b/sesman/env.c index 6cb711c0b6..cbbb4c8480 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -145,6 +145,8 @@ env_set_user(const char *username, char **passwd_file, int display, g_setenv("XRDP_SESSION", "1", 1); /* XRDP_SOCKET_PATH should be set even here, chansrv uses this */ g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); + g_sprintf(text, "%s/pcsc_socket_%d", XRDP_SOCKET_PATH, display); + g_setenv("PCSCLITE_CSOCK_NAME", text, 1); /* pulse sink socket */ g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_OUT_BASE_STR, display); g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); From 9bddcbd0edac720da30843361cbeef03bebaf350 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 5 Dec 2017 18:30:51 -0800 Subject: [PATCH 02/11] charsrv changes to pcsc --- sesman/chansrv/smartcard.c | 41 +- sesman/chansrv/smartcard.h | 9 +- sesman/chansrv/smartcard_pcsc.c | 1386 +++++++++++++++++++------------ sesman/chansrv/smartcard_pcsc.h | 24 +- 4 files changed, 899 insertions(+), 561 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 69e639e908..26178a4c12 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -137,7 +137,7 @@ static void scard_send_IsContextValid(IRP *irp, static void scard_send_ListReaders(IRP *irp, char *context, int context_bytes, char *groups, int cchReaders, - int wide); + int wide, int mszReadersIsNULL); static void scard_send_GetStatusChange(IRP *irp, char *context, int context_bytes, int wide, @@ -161,7 +161,8 @@ static void scard_send_EndTransaction(IRP *irp, static void scard_send_Status(IRP *irp, int wide, char *context, int context_bytes, char *card, int card_bytes, - int cchReaderLen, int cbAtrLen); + int cchReaderLen, int cbAtrLen, + int reader_name_is_null); static void scard_send_Disconnect(IRP *irp, char *context, int context_bytes, char *card, int card_bytes, @@ -172,7 +173,8 @@ static int scard_send_Transmit(IRP *irp, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, - struct xrdp_scard_io_request *recv_ior); + struct xrdp_scard_io_request *recv_ior, + int recv_ior_is_null, int recv_is_null); static int scard_send_Control(IRP *irp, char *context, int context_bytes, char *card, int card_bytes, char *send_data, int send_bytes, @@ -414,7 +416,8 @@ scard_send_is_valid_context(void *user_data, char *context, int context_bytes) *****************************************************************************/ int scard_send_list_readers(void *user_data, char *context, int context_bytes, - char *groups, int cchReaders, int wide) + char *groups, int cchReaders, int wide, + int mszReadersIsNULL) { IRP *irp; @@ -432,7 +435,7 @@ scard_send_list_readers(void *user_data, char *context, int context_bytes, /* send IRP to client */ scard_send_ListReaders(irp, context, context_bytes, groups, - cchReaders, wide); + cchReaders, wide, mszReadersIsNULL); return 0; } @@ -614,7 +617,7 @@ scard_send_end_transaction(void *user_data, char *context, int context_bytes, int scard_send_status(void *user_data, int wide, char *context, int context_bytes, char *card, int card_bytes, - int cchReaderLen, int cbAtrLen) + int cchReaderLen, int cbAtrLen, int reader_name_is_null) { IRP *irp; @@ -633,7 +636,7 @@ scard_send_status(void *user_data, int wide, char *context, int context_bytes, /* send IRP to client */ scard_send_Status(irp, wide, context, context_bytes, card, card_bytes, - cchReaderLen, cbAtrLen); + cchReaderLen, cbAtrLen, reader_name_is_null); return 0; } @@ -679,7 +682,8 @@ 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) + struct xrdp_scard_io_request *recv_ior, + int recv_ior_is_null, int recv_is_null) { IRP *irp; @@ -699,7 +703,8 @@ scard_send_transmit(void *user_data, char *context, int context_bytes, /* send IRP to client */ scard_send_Transmit(irp, context, context_bytes, card, card_bytes, send_data, send_bytes, - recv_bytes, send_ior, recv_ior); + recv_bytes, send_ior, recv_ior, + recv_ior_is_null, recv_is_null); return 0; } @@ -1083,7 +1088,8 @@ scard_send_IsContextValid(IRP *irp, char *context, int context_bytes) *****************************************************************************/ static void scard_send_ListReaders(IRP *irp, char *context, int context_bytes, - char *groups, int cchReaders, int wide) + char *groups, int cchReaders, int wide, + int mszReadersIsNULL) { /* see [MS-RDPESC] 2.2.2.4 */ @@ -1133,7 +1139,7 @@ scard_send_ListReaders(IRP *irp, char *context, int context_bytes, out_uint32_le(s, 0x00020000); out_uint32_le(s, bytes_groups); out_uint32_le(s, val); - out_uint32_le(s, 0x00000000); + out_uint32_le(s, mszReadersIsNULL); out_uint32_le(s, cchReaders); /* insert context */ @@ -1643,7 +1649,7 @@ scard_send_EndTransaction(IRP *irp, char *context, int context_bytes, static void scard_send_Status(IRP *irp, int wide, char *context, int context_bytes, char *card, int card_bytes, - int cchReaderLen, int cbAtrLen) + int cchReaderLen, int cbAtrLen, int reader_name_is_null) { /* see [MS-RDPESC] 2.2.2.18 */ @@ -1686,7 +1692,7 @@ scard_send_Status(IRP *irp, int wide, char *context, int context_bytes, out_uint32_le(s, 0x00020000); out_uint32_le(s, card_bytes); out_uint32_le(s, 0x00020004); - out_uint32_le(s, 0x00000001); + out_uint32_le(s, reader_name_is_null); out_uint32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ out_uint32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ @@ -1797,7 +1803,8 @@ 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) + struct xrdp_scard_io_request *recv_ior, + int recv_ior_is_null, int recv_is_null) { /* see [MS-RDPESC] 2.2.2.19 */ @@ -1914,10 +1921,10 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, val = send_bytes > 0 ? 0x00020008 : 0; out_uint32_le(s, val); /* map3 */ - val = recv_ior->cbPciLength > 0 ? 0x0002000c : 0; + val = recv_ior_is_null ? 0 : 0x00020008; out_uint32_le(s, val); /* map 4 */ - out_uint32_le(s, 0); // map5 + out_uint32_le(s, recv_is_null); // map5 out_uint32_le(s, recv_bytes); /* map0 */ @@ -1941,7 +1948,7 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, align_s(s, 4); } - if (recv_ior->cbPciLength > 0) + if (recv_ior_is_null == 0) { /* map4 */ out_uint32_le(s, recv_ior->dwProtocol); diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index ae4d141b7a..ef154e744a 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -117,7 +117,8 @@ int scard_send_is_valid_context(void *user_data, char *context, int context_bytes); int scard_send_list_readers(void *user_data, char *context, int context_bytes, - char *groups, int cchReaders, int wide); + char *groups, int cchReaders, int wide, + int mszReadersIsNULL); int scard_send_get_status_change(void *user_data, char *context, int context_bytes, @@ -143,7 +144,8 @@ int scard_send_end_transaction(void *user_data, int scard_send_status(void *user_data, int wide, char *context, int context_bytes, char *card, int card_bytes, - int cchReaderLen, int cbAtrLen); + int cchReaderLen, int cbAtrLen, + int reader_name_is_null); int scard_send_disconnect(void *user_data, char *context, int context_bytes, char *card, int card_bytes, @@ -154,7 +156,8 @@ int scard_send_transmit(void *user_data, 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); + struct xrdp_scard_io_request *recv_ior, + int recv_ior_is_null, int recv_is_null); int scard_send_control(void *user_data, char *context, int context_bytes, diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 7eb20712c8..9ef6519fa9 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -41,6 +41,7 @@ #include "trans.h" #include "chansrv.h" #include "list.h" +#include "defines.h" #if PCSC_STANDIN @@ -56,6 +57,17 @@ struct pcsc_card /* item for list of open cards in one context */ char card[16]; /* client card */ }; +typedef struct pubReaderStatesList +{ + char readerName[128]; + tui32 eventCounter; + tui32 readerState; + tui32 readerSharing; + tui8 cardAtr[36]; + tui32 cardAtrLength; + tui32 cardProtocol; +} PCSC_READER_STATE; + struct pcsc_context { tui32 app_context; /* application context, always 4 byte */ @@ -68,15 +80,29 @@ struct pcsc_context struct pcsc_uds_client { int uds_client_id; /* unique id represents each app */ + int ref_count; struct trans *con; /* the connection to the app */ struct list *contexts; /* list of struct pcsc_context */ - struct pcsc_context *connect_context; + + struct pcsc_context *connect_context; /* TODO remove this */ + + int state; + int pad1; + + /* should be 2944 bytes */ + /* 128 + 4 + 4 + 4 + 36 + 4 + 4 = 186, 186 * 16 = 2944 */ + PCSC_READER_STATE readerStates[16]; + tui32 current_states[16]; + tui32 event_states[16]; + int numReaders; + int waiting; + int something_changed; + int send_status; }; static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */ static struct trans *g_lis = 0; -static char g_pcsclite_ipc_dir[256] = ""; static char g_pcsclite_ipc_file[256] = ""; /*****************************************************************************/ @@ -136,6 +162,21 @@ get_uds_client_by_id(int uds_client_id) return 0; } +/*****************************************************************************/ +struct pcsc_context * +get_first_pcsc_context(struct pcsc_uds_client *uds_client) +{ + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts == 0) + { + return 0; + } + return (struct pcsc_context *) list_get_item(uds_client->contexts, 0); +} + /*****************************************************************************/ struct pcsc_context * get_pcsc_context_by_app_context(struct pcsc_uds_client *uds_client, @@ -232,6 +273,11 @@ free_uds_client(struct pcsc_uds_client *uds_client) { return 0; } + if (uds_client->ref_count > 0) + { + return 0; + } + LOG_DEVEL(LOG_LEVEL_DEBUG, "free_uds_client: freeing"); if (uds_client->contexts != 0) { for (i = 0; i < uds_client->contexts->count; i++) @@ -255,7 +301,6 @@ free_uds_client(struct pcsc_uds_client *uds_client) list_delete(context->cards); } LOG_DEVEL(LOG_LEVEL_DEBUG, " left over context %p", context->context); - scard_send_cancel(0, context->context, context->context_bytes); scard_send_release_context(0, context->context, context->context_bytes); g_free(context); @@ -268,6 +313,36 @@ free_uds_client(struct pcsc_uds_client *uds_client) return 0; } +/*****************************************************************************/ +static int +cancel_uds_client(struct pcsc_uds_client *uds_client) +{ + int i; + struct pcsc_context *context; + void *user_data; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "cancel_uds_client:"); + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts != 0) + { + for (i = 0; i < uds_client->contexts->count; i++) + { + context = (struct pcsc_context *) + list_get_item(uds_client->contexts, i); + if (context != 0) + { + user_data = (void *) (tintptr) (uds_client->uds_client_id); + uds_client->ref_count++; + scard_send_cancel(user_data, context->context, context->context_bytes); + } + } + } + return 0; +} + /*****************************************************************************/ static struct pcsc_context * uds_client_add_context(struct pcsc_uds_client *uds_client, @@ -276,8 +351,7 @@ uds_client_add_context(struct pcsc_uds_client *uds_client, struct pcsc_context *pcscContext; LOG_DEVEL(LOG_LEVEL_DEBUG, "uds_client_add_context:"); - pcscContext = (struct pcsc_context *) - g_malloc(sizeof(struct pcsc_context), 1); + pcscContext = g_new0(struct pcsc_context, 1); if (pcscContext == 0) { LOG(LOG_LEVEL_ERROR, @@ -337,8 +411,7 @@ context_add_card(struct pcsc_uds_client *uds_client, struct pcsc_card *pcscCard; LOG_DEVEL(LOG_LEVEL_DEBUG, "context_add_card: card_bytes %d", card_bytes); - pcscCard = (struct pcsc_card *) - g_malloc(sizeof(struct pcsc_card), 1); + pcscCard = g_new0(struct pcsc_card, 1); if (pcscCard == 0) { LOG(LOG_LEVEL_ERROR, @@ -418,6 +491,9 @@ scard_pcsc_check_wait_objs(void) { if (trans_check_wait_objs(uds_client->con) != 0) { + LOG(LOG_LEVEL_ERROR, "scard_pcsc_check_wait_objs: calling free_uds_client"); + cancel_uds_client(uds_client); + uds_client->ref_count--; free_uds_client(uds_client); list_remove_item(g_uds_clients, index); continue; @@ -443,6 +519,7 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) in_uint32_le(in_s, dwScope); LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_establish_context: dwScope 0x%8.8x", dwScope); user_data = (void *) (tintptr) (uds_client->uds_client_id); + uds_client->ref_count++; scard_send_establish_context(user_data, dwScope); return 0; } @@ -454,10 +531,11 @@ scard_function_establish_context_return(void *user_data, struct stream *in_s, int len, int status) { - int bytes; + int rv; int uds_client_id; int context_bytes; int app_context; + int return_code; char context[16]; struct stream *out_s; struct pcsc_uds_client *uds_client; @@ -466,6 +544,7 @@ scard_function_establish_context_return(void *user_data, LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_establish_context_return:"); LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status); + rv = 0; uds_client_id = (int) (tintptr) user_data; uds_client = (struct pcsc_uds_client *) get_uds_client_by_id(uds_client_id); @@ -479,17 +558,33 @@ scard_function_establish_context_return(void *user_data, con = uds_client->con; lcontext = 0; app_context = 0; + return_code = 0; g_memset(context, 0, 16); if (status == 0) { - in_uint8s(in_s, 28); + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + in_uint8s(in_s, 8); in_uint32_le(in_s, context_bytes); - if (context_bytes > 16) + if (return_code != 0 || context_bytes < 4 || context_bytes > 16) { - LOG(LOG_LEVEL_ERROR, "scard_function_establish_context_return: opps " - "context_bytes %d", context_bytes); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "", in_s->p, context_bytes); - return 1; + LOG(LOG_LEVEL_ERROR, "scard_function_establish_context_return: error " + "return_code 0x%8.8x context_bytes %d", + return_code, context_bytes); + if (uds_client->state == 1) + { + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 4); + out_uint32_le(out_s, 3); + out_uint32_le(out_s, 0x80100001); /* result */ + s_mark_end(out_s); + rv = trans_write_copy(uds_client->con); + uds_client->state = 0; + } + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } in_uint8a(in_s, context, context_bytes); lcontext = uds_client_add_context(uds_client, context, context_bytes); @@ -497,16 +592,46 @@ scard_function_establish_context_return(void *user_data, LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_establish_context_return: " "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, 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); - s_pop_layer(out_s, iso_hdr); - out_uint32_le(out_s, bytes - 8); - out_uint32_le(out_s, 0x01); /* SCARD_ESTABLISH_CONTEXT 0x01 */ - return trans_force_write(con); + else + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_establish_context_return: error " + "status %d", status); + if (uds_client->state == 1) + { + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 4); + out_uint32_le(out_s, 3); + out_uint32_le(out_s, 0x80100001); /* result */ + s_mark_end(out_s); + rv = trans_write_copy(uds_client->con); + uds_client->state = 0; + } + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; + } + if (uds_client->state == 1) + { + uds_client->ref_count++; + scard_send_list_readers(uds_client, + lcontext->context, + lcontext->context_bytes, + 0, 8148, 0, 0); + } + else if (uds_client->state == 0) + { + out_s = trans_get_out_s(con, 8192); + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* dwScope */ + out_uint32_le(out_s, app_context); /* hContext */ + out_uint32_le(out_s, return_code); /* rv */ + s_mark_end(out_s); + rv = trans_write_copy(con); + } + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -531,6 +656,7 @@ scard_process_release_context(struct trans *con, struct stream *in_s) "get_pcsc_context_by_app_context failed"); return 1; } + uds_client->ref_count++; scard_send_release_context(user_data, lcontext->context, lcontext->context_bytes); uds_client_remove_context(uds_client, lcontext); @@ -544,8 +670,9 @@ scard_function_release_context_return(void *user_data, struct stream *in_s, int len, int status) { - int bytes; + int rv; int uds_client_id; + int return_code; struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; @@ -563,74 +690,95 @@ scard_function_release_context_return(void *user_data, return 1; } con = uds_client->con; + return_code = 0; + if (status == 0) + { + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + } 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 */ + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hContext */ + out_uint32_le(out_s, return_code); /* rv */ 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, 0x02); /* SCARD_RELEASE_CONTEXT 0x02 */ - return trans_force_write(con); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } -/*****************************************************************************/ -struct pcsc_list_readers -{ - int uds_client_id; - int cchReaders; -}; - /*****************************************************************************/ /* returns error */ int scard_process_list_readers(struct trans *con, struct stream *in_s) { - int hContext; - unsigned int bytes_groups; - int cchReaders; - /* - * At the time of writing, the groups strings which can be sent - * over this interface are all small:- - * - * "SCard$AllReaders", "SCard$DefaultReaders", "SCard$LocalReaders" and - * "SCard$SystemReaders" - * - * We'll allow a bit extra in case the interface changes - */ - char groups[256]; - struct pcsc_uds_client *uds_client; - struct pcsc_context *lcontext; - struct pcsc_list_readers *pcscListReaders; + return 0; +} - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_list_readers:"); - uds_client = (struct pcsc_uds_client *) (con->callback_data); - in_uint32_le(in_s, hContext); - in_uint32_le(in_s, bytes_groups); - if (bytes_groups > (sizeof(groups) - 1)) - { - LOG(LOG_LEVEL_ERROR, "scard_process_list_readers: Unreasonable string length %u", - bytes_groups); - return 1; +/*****************************************************************************/ +static int +scard_readers_to_list(struct pcsc_uds_client *uds_client, + const char *names, int names_bytes) +{ + int reader_index; + int name_index; + int names_index; + char ch; + PCSC_READER_STATE hold_reader; + + reader_index = 0; + name_index = 0; + names_index = 0; + hold_reader = uds_client->readerStates[reader_index]; + while (names_index < names_bytes) + { + ch = names[names_index]; + if (ch == 0) + { + if (name_index < 1) + { + break; + } + uds_client->readerStates[reader_index].readerName[name_index] = 0; + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_readers_to_list: name [%s]", uds_client->readerStates[reader_index].readerName); + /* clear if name changes */ + if (g_strcmp(hold_reader.readerName, uds_client->readerStates[reader_index].readerName) != 0) + { + uds_client->something_changed = 1; + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_readers_to_list: name changed, clearing"); + uds_client->readerStates[reader_index].eventCounter = 0; + uds_client->readerStates[reader_index].readerState = 0; + uds_client->readerStates[reader_index].readerSharing = 0; + g_memset(uds_client->readerStates[reader_index].cardAtr, 0, 36); + uds_client->readerStates[reader_index].cardAtrLength = 0; + uds_client->readerStates[reader_index].cardProtocol = 0; + uds_client->current_states[reader_index] = 0; + uds_client->event_states[reader_index] = 0; + } + reader_index++; + hold_reader = uds_client->readerStates[reader_index]; + if (reader_index > 15) + { + return 0; + } + name_index = 0; + } + else + { + uds_client->readerStates[reader_index].readerName[name_index] = ch; + name_index++; + } + names_index++; } - in_uint8a(in_s, groups, bytes_groups); - groups[bytes_groups] = '\0'; - in_uint32_le(in_s, cchReaders); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_list_readers: hContext 0x%8.8x cchReaders %d", - hContext, cchReaders); - lcontext = get_pcsc_context_by_app_context(uds_client, hContext); - if (lcontext == 0) + uds_client->numReaders = reader_index; + /* clear the rest */ + while (reader_index < 16) { - LOG(LOG_LEVEL_ERROR, "scard_process_list_readers: " - "get_pcsc_context_by_app_context failed"); - g_free(groups); - return 1; + g_memset(uds_client->readerStates + reader_index, 0, sizeof(PCSC_READER_STATE)); + uds_client->current_states[reader_index] = 0; + uds_client->event_states[reader_index] = 0; + reader_index++; } - pcscListReaders = g_new0(struct pcsc_list_readers, 1); - pcscListReaders->uds_client_id = uds_client->uds_client_id; - pcscListReaders->cchReaders = cchReaders; - scard_send_list_readers(pcscListReaders, lcontext->context, - lcontext->context_bytes, groups, cchReaders, 1); return 0; } @@ -640,103 +788,78 @@ scard_function_list_readers_return(void *user_data, struct stream *in_s, int len, int status) { - struct stream *out_s; - int chr; - int readers; - int rn_index; - int index; - int bytes; - int cchReaders; - int llen; - int uds_client_id; - twchar reader_name[100]; - char lreader_name[16][100]; + int return_code; + int llen; + int rv; + int cardAtrLength; struct pcsc_uds_client *uds_client; - struct trans *con; - struct pcsc_list_readers *pcscListReaders; + struct pcsc_context *context; + + int index; + READER_STATE *rsa; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return:"); - LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status); - pcscListReaders = (struct pcsc_list_readers *) user_data; - if (pcscListReaders == 0) - { - LOG(LOG_LEVEL_ERROR, "scard_function_list_readers_return: " - "pcscListReaders is nil"); - 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) - { - LOG(LOG_LEVEL_ERROR, "scard_function_list_readers_return: " - "get_uds_client_by_id failed, could not find id %d", - uds_client_id); - return 1; - } - con = uds_client->con; - g_memset(reader_name, 0, sizeof(reader_name)); - g_memset(lreader_name, 0, sizeof(lreader_name)); - rn_index = 0; - readers = 0; - llen = 0; + uds_client = (struct pcsc_uds_client *) user_data; + rv = 0; if (status == 0) { - in_uint8s(in_s, 28); - in_uint32_le(in_s, len); - llen = len; - if (cchReaders > 0) + context = get_first_pcsc_context(uds_client); + if (context != 0) { - while (len > 0) + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return: return_code 0x%8.8x", return_code); + + rsa = g_new0(READER_STATE, 32); + in_uint8s(in_s, 4); + in_uint32_le(in_s, llen); /* pointer use as boolean */ + if ((llen != 0) && (return_code == 0)) { - in_uint16_le(in_s, chr); - len -= 2; - if (chr == 0) - { - if (reader_name[0] != 0) - { - g_wcstombs(lreader_name[readers], reader_name, 99); - g_memset(reader_name, 0, sizeof(reader_name)); - readers++; - } - reader_name[0] = 0; - rn_index = 0; - } - else + in_uint32_le(in_s, llen); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return: llen %d", llen); + //g_hexdump(in_s->p, llen); + scard_readers_to_list(uds_client, in_s->p, llen); + for (index = 0; index < uds_client->numReaders; index++) { - reader_name[rn_index] = chr; - rn_index++; + g_strncpy(rsa[index].reader_name, uds_client->readerStates[index].readerName, 127); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return: reader for scard_send_get_status_change [%s]", + uds_client->readerStates[index].readerName); + rsa[index].current_state = uds_client->event_states[index] & ~2; + rsa[index].event_state = uds_client->event_states[index]; + cardAtrLength = MIN(33, uds_client->readerStates[index].cardAtrLength); + cardAtrLength = MAX(0, cardAtrLength); + g_memcpy(rsa[index].atr, uds_client->readerStates[index].cardAtr, cardAtrLength); + rsa[index].atr_len = cardAtrLength; } } - } - if (rn_index > 0) - { - if (reader_name[0] != 0) + else { - g_wcstombs(lreader_name[readers], reader_name, 99); - g_memset(reader_name, 0, sizeof(reader_name)); - readers++; + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return: llen zero"); + uds_client->numReaders = 0; + g_memset(uds_client->readerStates, 0, sizeof(uds_client->readerStates)); + g_memset(uds_client->current_states, 0, sizeof(uds_client->current_states)); + g_memset(uds_client->event_states, 0, sizeof(uds_client->event_states)); } + /* add plug and play notifier */ + g_strncpy(rsa[uds_client->numReaders].reader_name, "\\\\?PnP?\\Notification", 127); + rsa[uds_client->numReaders].current_state = uds_client->numReaders << 16; + rsa[uds_client->numReaders].event_state = 0; + uds_client->ref_count++; + scard_send_get_status_change(uds_client, + context->context, + context->context_bytes, + 0, 10, uds_client->numReaders + 1, rsa); + g_free(rsa); + } + else + { + LOG(LOG_LEVEL_ERROR, "scard_function_list_readers_return: error, no context"); + rv = 1; } } - - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, llen); - out_uint32_le(out_s, readers); - for (index = 0; index < readers; index++) - { - out_uint8a(out_s, lreader_name[index], 100); - } - 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, 0x03); /* SCARD_LIST_READERS 0x03 */ - return trans_force_write(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -750,11 +873,11 @@ scard_process_connect(struct trans *con, struct stream *in_s) void *user_data; struct pcsc_context *lcontext; - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_connect:"); - uds_client = (struct pcsc_uds_client *) (con->callback_data); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_establish_context:"); g_memset(&rs, 0, sizeof(rs)); + uds_client = (struct pcsc_uds_client *) (con->callback_data); in_uint32_le(in_s, hContext); - in_uint8a(in_s, rs.reader_name, 100); + in_uint8a(in_s, rs.reader_name, 128); in_uint32_le(in_s, rs.dwShareMode); in_uint32_le(in_s, rs.dwPreferredProtocols); LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_connect: rs.reader_name %s dwShareMode 0x%8.8x " @@ -762,15 +885,9 @@ scard_process_connect(struct trans *con, struct stream *in_s) rs.dwPreferredProtocols); user_data = (void *) (tintptr) (uds_client->uds_client_id); lcontext = get_pcsc_context_by_app_context(uds_client, hContext); - if (lcontext == 0) - { - LOG(LOG_LEVEL_ERROR, "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); + uds_client->ref_count++; + scard_send_connect(user_data, lcontext->context, lcontext->context_bytes, 0, &rs); return 0; } @@ -782,17 +899,24 @@ scard_function_connect_return(void *user_data, { int dwActiveProtocol; int hCard; - int bytes; int uds_client_id; struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; char *card; - int card_bytes; + char dcard[16] = "unknown"; + int return_code; struct pcsc_card *lcard; + int rv; + int hcontext_bytes; + int hcontext_present; + int hcard_bytes; + int hcard_present; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_connect_return:"); LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status); + rv = 0; + card = dcard; uds_client_id = (int) (tintptr) user_data; uds_client = (struct pcsc_uds_client *) get_uds_client_by_id(uds_client_id); @@ -806,38 +930,60 @@ scard_function_connect_return(void *user_data, con = uds_client->con; dwActiveProtocol = 0; hCard = 0; + return_code = 0; if (status == 0) { - in_uint8s(in_s, 36); + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + in_uint32_le(in_s, hcontext_bytes); + in_uint32_le(in_s, hcontext_present); + in_uint32_le(in_s, hcard_bytes); + in_uint32_le(in_s, hcard_present); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_connect_return: hcontext_bytes %d hcard_bytes %d", + hcontext_bytes, hcard_bytes); in_uint32_le(in_s, dwActiveProtocol); - if (len > 40) + LOG_DEVEL(LOG_LEVEL_DEBUG, "dwActiveProtocol %d", dwActiveProtocol); + if (hcontext_bytes > 0 && hcontext_present) { - 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; - LOG_DEVEL(LOG_LEVEL_DEBUG, " hCard %d dwActiveProtocol %d", hCard, - dwActiveProtocol); + in_uint32_le(in_s, hcontext_bytes); + in_uint8s(in_s, hcontext_bytes); } - else + if (hcard_bytes > 0 && hcard_present) { - status = 0x8010000F; /* SCARD_E_PROTO_MISMATCH */ + in_uint32_le(in_s, hcard_bytes); + in_uint8p(in_s, card, hcard_bytes); } + lcard = context_add_card(uds_client, uds_client->connect_context, + card, hcard_bytes); + hCard = lcard->app_card; + LOG_DEVEL(LOG_LEVEL_DEBUG, " hCard %d dwActiveProtocol %d", hCard, + dwActiveProtocol); } out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hContext */ + out_uint8s(out_s, 128); /* szReader */ + out_uint32_le(out_s, 0); /* dwShareMode */ + out_uint32_le(out_s, 0); /* dwPreferredProtocols */ out_uint32_le(out_s, hCard); out_uint32_le(out_s, dwActiveProtocol); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, return_code); /* rv */ 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); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } +#if 0 +struct disconnect_struct +{ + int32_t hCard; + uint32_t dwDisposition; + uint32_t rv; +}; +#endif + /*****************************************************************************/ /* returns error */ int @@ -862,6 +1008,7 @@ scard_process_disconnect(struct trans *con, struct stream *in_s) "get_pcsc_card_by_app_card failed"); return 1; } + uds_client->ref_count++; scard_send_disconnect(user_data, lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes, dwDisposition); @@ -874,8 +1021,9 @@ scard_function_disconnect_return(void *user_data, struct stream *in_s, int len, int status) { - int bytes; + int rv; int uds_client_id; + int return_code; struct stream *out_s; struct pcsc_uds_client *uds_client; struct trans *con; @@ -893,15 +1041,22 @@ scard_function_disconnect_return(void *user_data, return 1; } con = uds_client->con; + return_code = 0; + if (status == 0) + { + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + } 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 */ + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, 0); /* dwDisposition */ + out_uint32_le(out_s, return_code); /* rv */ 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, 0x06); /* SCARD_DISCONNECT 0x06 */ - return trans_force_write(con); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -927,6 +1082,7 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s) "get_pcsc_card_by_app_card failed"); return 1; } + uds_client->ref_count++; scard_send_begin_transaction(user_data, lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes); @@ -940,9 +1096,10 @@ scard_function_begin_transaction_return(void *user_data, struct stream *in_s, int len, int status) { + int rv; struct stream *out_s; - int bytes; int uds_client_id; + int return_code; struct pcsc_uds_client *uds_client; struct trans *con; @@ -959,17 +1116,32 @@ scard_function_begin_transaction_return(void *user_data, return 1; } con = uds_client->con; + return_code = 0; + if (status == 0) + { + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + } 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 */ + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, return_code); /* rv */ 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); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } +#if 0 +struct end_struct +{ + int32_t hCard; + uint32_t dwDisposition; + uint32_t rv; +}; +#endif + /*****************************************************************************/ /* returns error */ int @@ -995,6 +1167,7 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) "get_pcsc_card_by_app_card failed"); return 1; } + uds_client->ref_count++; scard_send_end_transaction(user_data, lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes, @@ -1009,9 +1182,10 @@ scard_function_end_transaction_return(void *user_data, struct stream *in_s, int len, int status) { + int rv; struct stream *out_s; - int bytes; int uds_client_id; + int return_code; struct pcsc_uds_client *uds_client; struct trans *con; @@ -1028,16 +1202,23 @@ scard_function_end_transaction_return(void *user_data, return 1; } con = uds_client->con; + return_code = 0; + if (status == 0) + { + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + } 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 */ + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, 0); /* dwDisposition */ + out_uint32_le(out_s, return_code); /* rv */ 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); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -1050,7 +1231,6 @@ scard_function_get_attrib_return(void *user_data, return 0; } -/*****************************************************************************/ struct pcsc_transmit { int uds_client_id; @@ -1066,6 +1246,8 @@ scard_process_transmit(struct trans *con, struct stream *in_s) int hCard; int recv_bytes; int send_bytes; + int recv_ior_is_null; + int recv_is_null; char *send_data; struct xrdp_scard_io_request send_ior; struct xrdp_scard_io_request recv_ior; @@ -1077,18 +1259,22 @@ scard_process_transmit(struct trans *con, struct stream *in_s) LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_transmit:"); uds_client = (struct pcsc_uds_client *) (con->callback_data); LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_transmit:"); + + recv_ior_is_null = 0; + recv_is_null = 0; + g_memset(&send_ior, 0, sizeof(send_ior)); + g_memset(&recv_ior, 0, sizeof(recv_ior)); in_uint32_le(in_s, hCard); in_uint32_le(in_s, send_ior.dwProtocol); in_uint32_le(in_s, send_ior.cbPciLength); - in_uint32_le(in_s, send_ior.extra_bytes); - in_uint8p(in_s, send_ior.extra_data, send_ior.extra_bytes); in_uint32_le(in_s, send_bytes); - in_uint8p(in_s, send_data, send_bytes); in_uint32_le(in_s, recv_ior.dwProtocol); in_uint32_le(in_s, recv_ior.cbPciLength); - in_uint32_le(in_s, recv_ior.extra_bytes); - in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes); in_uint32_le(in_s, recv_bytes); + in_uint8s(in_s, 4); /* rv */ + in_uint8p(in_s, send_data, send_bytes); + send_ior.cbPciLength = 8; + recv_ior.cbPciLength = 8; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_transmit: send dwProtocol %d cbPciLength %d " "recv dwProtocol %d cbPciLength %d send_bytes %d ", send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol, @@ -1102,17 +1288,16 @@ scard_process_transmit(struct trans *con, struct stream *in_s) return 1; } - pcscTransmit = (struct pcsc_transmit *) - g_malloc(sizeof(struct pcsc_transmit), 1); + pcscTransmit = g_new0(struct pcsc_transmit, 1); pcscTransmit->uds_client_id = uds_client->uds_client_id; pcscTransmit->recv_ior = recv_ior; pcscTransmit->cbRecvLength = recv_bytes; - + uds_client->ref_count++; scard_send_transmit(pcscTransmit, lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes, send_data, send_bytes, recv_bytes, - &send_ior, &recv_ior); + &send_ior, &recv_ior, recv_ior_is_null, recv_is_null); return 0; } @@ -1123,10 +1308,14 @@ scard_function_transmit_return(void *user_data, struct stream *in_s, int len, int status) { + int rv; struct stream *out_s; - int bytes; - int val; + int return_code; int cbRecvLength; + int recv_ior_present; + int recv_present; + int recv_ior_extra_present; + int pad; char *recvBuf; struct xrdp_scard_io_request recv_ior; struct pcsc_uds_client *uds_client; @@ -1150,49 +1339,62 @@ scard_function_transmit_return(void *user_data, con = uds_client->con; cbRecvLength = 0; recvBuf = 0; + return_code = 0; if (status == 0) { - in_uint8s(in_s, 20); - in_uint32_le(in_s, val); - if (val != 0) + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + in_uint32_le(in_s, recv_ior_present); + in_uint32_le(in_s, cbRecvLength); + in_uint32_le(in_s, recv_present); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_transmit_return: recv_ior_present %d recv_present %d", + recv_ior_present, recv_present); + if (recv_ior_present != 0) { /* pioRecvPci */ - in_uint8s(in_s, 8); in_uint32_le(in_s, recv_ior.dwProtocol); in_uint32_le(in_s, recv_ior.cbPciLength); recv_ior.cbPciLength += 8; - in_uint32_le(in_s, recv_ior.extra_bytes); - if (recv_ior.extra_bytes > 0) + in_uint32_le(in_s, recv_ior_extra_present); + if (recv_ior_extra_present != 0) { - in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes); + in_uint32_le(in_s, recv_ior.extra_bytes); + if (recv_ior.extra_bytes > 0) + { + in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes); + } + pad = (4 - recv_ior.extra_bytes) & 3; + in_uint8s(in_s, pad); } } - - in_uint8s(in_s, 4); - in_uint32_le(in_s, val); - if (val != 0) + if (recv_present != 0) { - in_uint32_le(in_s, cbRecvLength); - in_uint8p(in_s, recvBuf, cbRecvLength); + if (s_check_rem(in_s, 4 + cbRecvLength)) + { + in_uint32_le(in_s, cbRecvLength); + in_uint8p(in_s, recvBuf, cbRecvLength); + pad = (4 - cbRecvLength) & 3; + in_uint8s(in_s, pad); + } } - } LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_transmit_return: cbRecvLength %d", cbRecvLength); - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); + + out_s = trans_get_out_s(con, 8192 + cbRecvLength); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, 0); /* send_ior.dwProtocol */ + out_uint32_le(out_s, 0); /* send_ior.cbPciLength */ + out_uint32_le(out_s, 0); /* send_bytes */ out_uint32_le(out_s, recv_ior.dwProtocol); out_uint32_le(out_s, recv_ior.cbPciLength); - out_uint32_le(out_s, recv_ior.extra_bytes); - out_uint8a(out_s, recv_ior.extra_data, recv_ior.extra_bytes); out_uint32_le(out_s, cbRecvLength); - out_uint8a(out_s, recvBuf, cbRecvLength); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + out_uint32_le(out_s, return_code); /* rv */ + out_uint8p(out_s, recvBuf, cbRecvLength); 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, 0x09); /* SCARD_TRANSMIT 0x09 */ - return trans_force_write(con); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -1200,39 +1402,6 @@ scard_function_transmit_return(void *user_data, int scard_process_control(struct trans *con, struct stream *in_s) { - int hCard; - int send_bytes; - int recv_bytes; - int control_code; - char *send_data; - struct pcsc_uds_client *uds_client; - void *user_data; - struct pcsc_context *lcontext; - struct pcsc_card *lcard; - - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_control:"); - uds_client = (struct pcsc_uds_client *) (con->callback_data); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_control:"); - - in_uint32_le(in_s, hCard); - in_uint32_le(in_s, control_code); - in_uint32_le(in_s, send_bytes); - in_uint8p(in_s, send_data, send_bytes); - 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, &lcontext); - if ((lcard == 0) || (lcontext == 0)) - { - LOG(LOG_LEVEL_ERROR, "scard_process_control: " - "get_pcsc_card_by_app_card failed"); - return 1; - } - scard_send_control(user_data, lcontext->context, lcontext->context_bytes, - lcard->card, lcard->card_bytes, - send_data, send_bytes, recv_bytes, - control_code); - return 0; } @@ -1243,47 +1412,7 @@ scard_function_control_return(void *user_data, struct stream *in_s, int len, int status) { - struct stream *out_s; - int bytes; - int cbRecvLength; - char *recvBuf; - int uds_client_id; - struct pcsc_uds_client *uds_client; - struct trans *con; - - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_control_return:"); - LOG_DEVEL(LOG_LEVEL_DEBUG, " 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) - { - LOG(LOG_LEVEL_ERROR, "scard_function_control_return: " - "get_uds_client_by_id failed to find uds_client_id %d", - uds_client_id); - return 1; - } - con = uds_client->con; - cbRecvLength = 0; - recvBuf = 0; - if (status == 0) - { - in_uint8s(in_s, 28); - in_uint32_le(in_s, cbRecvLength); - in_uint8p(in_s, recvBuf, cbRecvLength); - } - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_control_return: cbRecvLength %d", cbRecvLength); - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, cbRecvLength); - out_uint8a(out_s, recvBuf, cbRecvLength); - 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, 0x0A); /* SCARD_CONTROL 0x0A */ - return trans_force_write(con); + return 0; } /*****************************************************************************/ @@ -1298,23 +1427,18 @@ struct pcsc_status int scard_process_status(struct trans *con, struct stream *in_s) { + int rv; int hCard; - int cchReaderLen; - int cbAtrLen; struct pcsc_uds_client *uds_client; struct pcsc_card *lcard; struct pcsc_context *lcontext; struct pcsc_status *pcscStatus; + struct stream *out_s; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_status:"); + rv = 0; uds_client = (struct pcsc_uds_client *) (con->callback_data); - in_uint32_le(in_s, hCard); - in_uint32_le(in_s, cchReaderLen); - in_uint32_le(in_s, cbAtrLen); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_status: hCard 0x%8.8x cchReaderLen %d " - "cbAtrLen %d", hCard, cchReaderLen, cbAtrLen); - lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); if ((lcard == 0) || (lcontext == 0)) { @@ -1322,15 +1446,29 @@ scard_process_status(struct trans *con, struct stream *in_s) "get_pcsc_card_by_app_card failed"); return 1; } - pcscStatus = (struct pcsc_status *) g_malloc(sizeof(struct pcsc_status), 1); - pcscStatus->uds_client_id = uds_client->uds_client_id; - pcscStatus->cchReaderLen = cchReaderLen; - scard_send_status(pcscStatus, 1, - lcontext->context, lcontext->context_bytes, - lcard->card, lcard->card_bytes, - cchReaderLen, cbAtrLen); - - return 0; + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_status: send_status %d", uds_client->send_status); + if (uds_client->send_status) + { + uds_client->send_status = 0; + pcscStatus = g_new0(struct pcsc_status, 1); + pcscStatus->uds_client_id = uds_client->uds_client_id; + pcscStatus->cchReaderLen = 128; + uds_client->ref_count++; + scard_send_status(pcscStatus, 0, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + 128, 36, 0); + } + else + { + out_s = con->out_s; + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, 0); /* rv */ + s_mark_end(out_s); + rv = trans_write_copy(con); + } + return rv; } #define MS_SCARD_UNKNOWN 0 @@ -1362,31 +1500,29 @@ scard_function_status_return(void *user_data, struct stream *in_s, int len, int status) { - struct stream *out_s; + int index; - int bytes; int dwReaderLen; int dwState; int dwProtocol; int dwAtrLen; - char attr[32]; - twchar reader_name[100]; - char lreader_name[100]; + int return_code; + char attr[36]; + char reader_name[128]; + int rv; + struct stream *out_s; + struct pcsc_status *pcscStatus; int uds_client_id; struct pcsc_uds_client *uds_client; struct trans *con; - struct pcsc_status *pcscStatus; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_status_return:"); - LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status); - pcscStatus = (struct pcsc_status *) user_data; if (pcscStatus == 0) { LOG(LOG_LEVEL_ERROR, "scard_function_status_return: pcscStatus is nil"); return 1; } - uds_client_id = pcscStatus->uds_client_id; uds_client = (struct pcsc_uds_client *) get_uds_client_by_id(uds_client_id); @@ -1399,26 +1535,29 @@ scard_function_status_return(void *user_data, return 1; } g_free(pcscStatus); - con = uds_client->con; + dwReaderLen = 0; dwState = 0; dwProtocol = 0; dwAtrLen = 0; - lreader_name[0] = 0; + reader_name[0] = 0; + return_code = 0; + if (status == 0) { - in_uint8s(in_s, 20); + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); in_uint32_le(in_s, dwReaderLen); in_uint8s(in_s, 4); in_uint32_le(in_s, dwState); - dwState = g_ms2pc[dwState % 6]; + dwState = g_ms2pc[dwState % 7]; in_uint32_le(in_s, dwProtocol); in_uint8a(in_s, attr, 32); in_uint32_le(in_s, dwAtrLen); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_status_return: return_code 0x%8.8x", return_code); if (dwReaderLen > 0) { - in_uint32_le(in_s, dwReaderLen); - dwReaderLen /= 2; + in_uint8s(in_s, 4); } else { @@ -1429,101 +1568,141 @@ scard_function_status_return(void *user_data, LOG(LOG_LEVEL_ERROR, "scard_function_status_return: dwReaderLen < 1"); dwReaderLen = 1; } - if (dwReaderLen > 99) + if (dwReaderLen > 127) { - LOG_DEVEL(LOG_LEVEL_WARNING, "scard_function_status_return: dwReaderLen too big " - "0x%8.8x", dwReaderLen); - dwReaderLen = 99; + LOG(LOG_LEVEL_ERROR, "scard_function_status_return: dwReaderLen too big " + "0x%8.8x", dwReaderLen); + dwReaderLen = 127; } + g_memset(reader_name, 0, sizeof(reader_name)); - g_memset(lreader_name, 0, sizeof(lreader_name)); - for (index = 0; index < dwReaderLen - 1; index++) + in_uint8a(in_s, reader_name, dwReaderLen); + + } + + for (index = 0; index < 16; index++) + { + if (g_strcmp(reader_name, uds_client->readerStates[index].readerName) == 0) { - in_uint16_le(in_s, reader_name[index]); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_status_return: found read [%s]", reader_name); + LOG_DEVEL(LOG_LEVEL_DEBUG, " updateing cardAtrLength from %d to %d", uds_client->readerStates[index].cardAtrLength, dwAtrLen); + uds_client->readerStates[index].cardAtrLength = dwAtrLen; + g_memcpy(uds_client->readerStates[index].cardAtr, attr, dwAtrLen); + LOG_DEVEL(LOG_LEVEL_DEBUG, " updateing cardProtocol from %d to %d", uds_client->readerStates[index].cardProtocol, dwProtocol); + uds_client->readerStates[index].cardProtocol = dwProtocol; + LOG_DEVEL(LOG_LEVEL_DEBUG, " updateing dwState from %d to %d", uds_client->readerStates[index].readerState, dwState); + uds_client->readerStates[index].readerState = dwState; } - g_wcstombs(lreader_name, reader_name, 99); } - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_status_return: dwAtrLen %d dwReaderLen %d " - "dwProtocol %d dwState %d name %s", - dwAtrLen, dwReaderLen, dwProtocol, dwState, lreader_name); - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); - dwReaderLen = g_strlen(lreader_name); - out_uint32_le(out_s, dwReaderLen); - out_uint8a(out_s, lreader_name, dwReaderLen); - out_uint32_le(out_s, dwState); - out_uint32_le(out_s, dwProtocol); - out_uint32_le(out_s, dwAtrLen); - out_uint8a(out_s, attr, dwAtrLen); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + + con = uds_client->con; + rv = 0; + out_s = con->out_s; + init_stream(out_s, 0); + out_uint32_le(out_s, 0); /* hCard */ + out_uint32_le(out_s, return_code); /* rv */ 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, 0x0B); /* SCARD_STATUS 0x0B */ - return trans_force_write(con); + rv = trans_write_copy(con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ /* returns error */ -int -scard_process_get_status_change(struct trans *con, struct stream *in_s) +static int +scard_process_cmd_version(struct trans *con, struct stream *in_s) { - int index; - int hContext; - int dwTimeout; - int cReaders; - READER_STATE *rsa; + int rv; + int major; + int minor; struct pcsc_uds_client *uds_client; void *user_data; - struct pcsc_context *lcontext; - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change:"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_version:"); + rv = 0; + in_uint32_le(in_s, major); + in_uint32_le(in_s, minor); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_version: major %d minor %d", major, minor); uds_client = (struct pcsc_uds_client *) (con->callback_data); - in_uint32_le(in_s, hContext); - in_uint32_le(in_s, dwTimeout); - in_uint32_le(in_s, cReaders); - if ((cReaders < 0) || (cReaders > 16)) - { - LOG(LOG_LEVEL_ERROR, "scard_process_get_status_change: bad cReaders %d", cReaders); - return 1; - } - rsa = (READER_STATE *) g_malloc(sizeof(READER_STATE) * cReaders, 1); + uds_client->state = 1; + uds_client = (struct pcsc_uds_client *) (con->callback_data); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + uds_client->ref_count++; + scard_send_establish_context(user_data, 0); /* SCARD_SCOPE_USER */ + return rv; +} - for (index = 0; index < cReaders; index++) - { - in_uint8a(in_s, rsa[index].reader_name, 100); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change: reader_name %s", - rsa[index].reader_name); - in_uint32_le(in_s, rsa[index].current_state); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change: current_state %d", - rsa[index].current_state); - in_uint32_le(in_s, rsa[index].event_state); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change: event_state %d", - rsa[index].event_state); - in_uint32_le(in_s, rsa[index].atr_len); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change: atr_len %d", - rsa[index].atr_len); - in_uint8a(in_s, rsa[index].atr, 36); - } +/*****************************************************************************/ +/* returns error */ +static int +scard_process_cmd_get_readers_state(struct trans *con, struct stream *in_s) +{ + int rv; + struct stream *out_s; + struct pcsc_uds_client *uds_client; - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_get_status_change: hContext 0x%8.8x dwTimeout " - "%d cReaders %d", hContext, dwTimeout, cReaders); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_get_readers_state:"); + rv = 0; + uds_client = (struct pcsc_uds_client *) (con->callback_data); + out_s = con->out_s; + init_stream(out_s, sizeof(uds_client->readerStates)); + out_uint8a(out_s, uds_client->readerStates, sizeof(uds_client->readerStates)); + s_mark_end(out_s); + rv = trans_write_copy(con); + return rv; +} - user_data = (void *) (tintptr) (uds_client->uds_client_id); - lcontext = get_pcsc_context_by_app_context(uds_client, hContext); - if (lcontext == 0) - { - LOG(LOG_LEVEL_ERROR, "scard_process_get_status_change: " - "get_pcsc_context_by_app_context failed"); - g_free(rsa); - return 1; - } - scard_send_get_status_change(user_data, - lcontext->context, lcontext->context_bytes, - 1, dwTimeout, cReaders, rsa); - g_free(rsa); +/*****************************************************************************/ +/* returns error */ +static int +scard_process_cmd_wait_reader_state_change(struct trans *con, + struct stream *in_s) +{ + int rv; + //struct stream *out_s; + int timeOut; + struct pcsc_uds_client *uds_client; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change:"); + in_uint32_le(in_s, timeOut); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change: timeOut %d", + timeOut); + //out_s = con->out_s; + uds_client = (struct pcsc_uds_client *) (con->callback_data); + uds_client->waiting = 1; + rv = 0; + return rv; +} + +/*****************************************************************************/ +/* returns error */ +static int +scard_process_cmd_stop_waiting_reader_state_change(struct trans *con, + struct stream *in_s) +{ + int rv; + struct stream *out_s; + struct pcsc_uds_client *uds_client; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_stop_waiting_reader_state_change:"); + out_s = con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 0); /* timeOut */ + out_uint32_le(out_s, 0); /* rv */ + s_mark_end(out_s); + rv = trans_write_copy(con); + uds_client = (struct pcsc_uds_client *) (con->callback_data); + uds_client->waiting = 0; + uds_client->something_changed = 0; + return rv; +} +/*****************************************************************************/ +/* returns error */ +int +scard_process_get_status_change(struct trans *con, struct stream *in_s) +{ return 0; } @@ -1533,68 +1712,133 @@ scard_function_get_status_change_return(void *user_data, struct stream *in_s, int len, int status) { - int bytes; - int index; + int rv; + int return_code; int cReaders; - tui32 current_state; - tui32 event_state; - tui32 atr_len; /* number of bytes in atr[] */ - tui8 atr[36]; - struct stream *out_s; - int uds_client_id; + int index; + int current_state; + int event_state; + int cardAtrLength; struct pcsc_uds_client *uds_client; - struct trans *con; + struct stream *out_s; + + READER_STATE *rsa; + struct pcsc_context *context; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_get_status_change_return:"); - LOG_DEVEL(LOG_LEVEL_DEBUG, " 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) - { - LOG(LOG_LEVEL_ERROR, "scard_function_get_status_change_return: " - "get_uds_client_by_id failed to find uds_client_id %d", - uds_client_id); - return 1; - } - con = uds_client->con; + rv = 0; + cReaders = 0; + return_code = 0; + uds_client = (struct pcsc_uds_client *) user_data; - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); - if (status != 0) - { - out_uint32_le(out_s, 0); /* cReaders */ - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ - } - else + if (status == 0) { - in_uint8s(in_s, 28); + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + in_uint8s(in_s, 8); in_uint32_le(in_s, cReaders); LOG_DEVEL(LOG_LEVEL_DEBUG, " cReaders %d", cReaders); - out_uint32_le(out_s, cReaders); + if (return_code != 0) + { + cReaders = 0; + } if (cReaders > 0) { for (index = 0; index < cReaders; index++) { - in_uint32_le(in_s, current_state); - out_uint32_le(out_s, current_state); - in_uint32_le(in_s, event_state); - out_uint32_le(out_s, event_state); - in_uint32_le(in_s, atr_len); - out_uint32_le(out_s, atr_len); - in_uint8a(in_s, atr, 36); - out_uint8a(out_s, atr, 36); + in_uint32_le(in_s, current_state); /* current state */ + in_uint32_le(in_s, event_state); /* event state */ + LOG_DEVEL(LOG_LEVEL_DEBUG, " index %d current_state 0x%8.8x event_state 0x%8.8x", index, current_state, event_state); + uds_client->current_states[index] = current_state; + uds_client->event_states[index] = event_state; + if (event_state & 0x0002) /* SCARD_STATE_CHANGED */ + { + if (event_state & 0x0020) /* SCARD_STATE_PRESENT */ + { + uds_client->readerStates[index].readerState = 0x0004; /* SCARD_PRESENT */ + } + else + { + uds_client->readerStates[index].readerState = 0x0002; /* SCARD_ABSENT */ + } + uds_client->something_changed = 1; + uds_client->send_status = 1; + } + in_uint32_le(in_s, uds_client->readerStates[index].cardAtrLength); + in_uint8a(in_s, uds_client->readerStates[index].cardAtr, 36); + uds_client->readerStates[index].eventCounter = (event_state >> 16) & 0xFFFF; + } + } + + context = get_first_pcsc_context(uds_client); + + if (uds_client->state == 1) + { + /* send version back */ + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 4); + out_uint32_le(out_s, 3); + out_uint32_le(out_s, 0); /* result */ + s_mark_end(out_s); + rv = trans_write_copy(uds_client->con); + uds_client->state = 0; + return_code = 0x8010000A; + } + + if (return_code == 0x8010000A) /* SCARD_E_TIMEOUT */ + { + rsa = g_new(READER_STATE, uds_client->numReaders + 1); + for (index = 0; index < uds_client->numReaders; index++) + { + g_strncpy(rsa[index].reader_name, uds_client->readerStates[index].readerName, 127); + rsa[index].current_state = uds_client->event_states[index] & ~2; + rsa[index].event_state = uds_client->event_states[index]; + cardAtrLength = MIN(33, uds_client->readerStates[index].cardAtrLength); + cardAtrLength = MAX(0, cardAtrLength); + g_memcpy(rsa[index].atr, uds_client->readerStates[index].cardAtr, cardAtrLength); + rsa[index].atr_len = cardAtrLength; } + /* add plug and play notifier */ + g_strncpy(rsa[index].reader_name, "\\\\?PnP?\\Notification", 127); + rsa[index].current_state = index << 16; + uds_client->ref_count++; + scard_send_get_status_change(uds_client, + context->context, + context->context_bytes, + 0, 0xFFFFFFFF, index + 1, rsa); + g_free(rsa); + } - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + else if (return_code == 0) + { + uds_client->ref_count++; + scard_send_list_readers(uds_client, + context->context, + context->context_bytes, + 0, 8148, 0, 0); + } + } - 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, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */ - return trans_force_write(con); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_get_status_change_return: something changed %d waiting %d cReaders %d return_code 0x%8.8x", + uds_client->something_changed, uds_client->waiting, cReaders, return_code); + + if (cReaders == 0 && uds_client->waiting && uds_client->something_changed) + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_get_status_change_return: something changed"); + uds_client->waiting = 0; + uds_client->something_changed = 0; + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 0); /* timeOut */ + out_uint32_le(out_s, 0); /* rv */ + s_mark_end(out_s); + rv = trans_write_copy(uds_client->con); + } + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -1602,6 +1846,8 @@ scard_function_get_status_change_return(void *user_data, int scard_process_cancel(struct trans *con, struct stream *in_s) { + int rv; + struct stream *out_s; int hContext; struct pcsc_uds_client *uds_client; void *user_data; @@ -1615,10 +1861,16 @@ scard_process_cancel(struct trans *con, struct stream *in_s) lcontext = get_pcsc_context_by_app_context(uds_client, hContext); if (lcontext == 0) { - LOG(LOG_LEVEL_ERROR, "scard_process_cancel: " - "get_pcsc_context_by_app_context failed"); - return 1; + LOG(LOG_LEVEL_ERROR, "scard_process_cancel: get_pcsc_context_by_app_context failed"); + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 0); /* hContext */ + out_uint32_le(out_s, 0); /* rv */ + s_mark_end(out_s); + rv = trans_write_copy(uds_client->con); + return rv; } + uds_client->ref_count++; scard_send_cancel(user_data, lcontext->context, lcontext->context_bytes); return 0; } @@ -1630,11 +1882,11 @@ scard_function_cancel_return(void *user_data, struct stream *in_s, int len, int status) { - int bytes; + int rv; int uds_client_id; + int return_code; struct stream *out_s; struct pcsc_uds_client *uds_client; - struct trans *con; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_cancel_return:"); LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status); @@ -1648,16 +1900,21 @@ scard_function_cancel_return(void *user_data, uds_client_id); return 1; } - con = uds_client->con; - 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 */ + return_code = 0; + if (status == 0) + { + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); + } + out_s = uds_client->con->out_s; + init_stream(out_s, 8192); + out_uint32_le(out_s, 0); /* hContext */ + out_uint32_le(out_s, return_code); /* rv */ 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); + rv = trans_write_copy(uds_client->con); + uds_client->ref_count--; + free_uds_client(uds_client); + return rv; } /*****************************************************************************/ @@ -1765,6 +2022,26 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_msg: SCARD_SET_ATTRIB"); break; + case 0x11: /* CMD_VERSION */ + LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_msg: CMD_VERSION"); + rv = scard_process_cmd_version(con, in_s); + break; + + case 0x12: /* CMD_GET_READERS_STATE */ + LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_msg: CMD_GET_READERS_STATE"); + rv = scard_process_cmd_get_readers_state(con, in_s); + break; + + case 0x13: /* CMD_WAIT_READER_STATE_CHANGE */ + LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_msg: CMD_WAIT_READER_STATE_CHANGE"); + rv = scard_process_cmd_wait_reader_state_change(con, in_s); + break; + + case 0x14: /* CMD_STOP_WAITING_READER_STATE_CHANGE */ + LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_msg: CMD_STOP_WAITING_READER_STATE_CHANGE"); + rv = scard_process_cmd_stop_waiting_reader_state_change(con, in_s); + break; + default: LOG_DEVEL(LOG_LEVEL_WARNING, "scard_process_msg: unknown mtype 0x%4.4x", command); rv = 1; @@ -1788,14 +2065,64 @@ my_pcsc_trans_data_in(struct trans *trans) { return 0; } + error = 0; s = trans_get_in_s(trans); - in_uint32_le(s, size); - in_uint32_le(s, command); - LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: size %d command %d", size, command); - error = trans_force_read(trans, size); - if (error == 0) - { - error = scard_process_msg(trans, s, command); + switch (trans->extra_flags) + { + case 0: + s->p = s->data; + in_uint32_le(s, size); + in_uint32_le(s, command); + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: size %d command %d", size, command); + trans->extra_flags = command; + if (size > 0) + { + trans->header_size = 8 + size; + break; + } + /* fallthrough */ + default: + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: got payload"); + s->p = s->data; + in_uint8s(s, 4); /* size */ + in_uint32_le(s, command); + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: default command %d", command); + error = scard_process_msg(trans, s, command); + init_stream(s, 0); + trans->header_size = 8; + trans->extra_flags = 0; + break; + case 9: /* transmit */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: special transmit"); + s->p = s->data; + in_uint8s(s, 12 + 8); + in_uint32_le(s, size); + s->p = s->data; + if (size < 1) + { + in_uint8s(s, 4); /* size */ + in_uint32_le(s, command); + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: 9 command %d", command); + error = scard_process_msg(trans, s, command); + init_stream(s, 0); + trans->header_size = 8; + trans->extra_flags = 0; + break; + } + trans->header_size += size; + trans->extra_flags = 999; + break; + case 999: /* transmit */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: special transmit 999"); + s->p = s->data; + in_uint8s(s, 4); /* size */ + in_uint32_le(s, command); + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_data_in: 999 command %d", command); + error = scard_process_msg(trans, s, command); + init_stream(s, 0); + trans->header_size = 8; + trans->extra_flags = 0; + break; } return error; } @@ -1824,6 +2151,7 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) return 1; } + LOG_DEVEL(LOG_LEVEL_DEBUG, "my_pcsc_trans_conn_in: got connection"); uds_client = create_uds_client(new_trans); if (uds_client == 0) { @@ -1831,6 +2159,7 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) } uds_client->con->trans_data_in = my_pcsc_trans_data_in; uds_client->con->header_size = 8; + uds_client->con->no_stream_init_on_data_in = 1; if (g_uds_clients == 0) { @@ -1845,7 +2174,7 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) int scard_pcsc_init(void) { - char *home; + const char *csock_name; int disp; int error; @@ -1853,29 +2182,17 @@ scard_pcsc_init(void) if (g_lis == 0) { g_lis = trans_create(2, 8192, 8192); - home = g_getenv("HOME"); - disp = g_display_num; - g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp); - - if (g_directory_exist(g_pcsclite_ipc_dir)) + csock_name = g_getenv("XRDP_PCSCLITE_CSOCK_NAME"); + if (csock_name != 0) { - if (!g_remove_dir(g_pcsclite_ipc_dir)) - { - LOG_DEVEL(LOG_LEVEL_WARNING, "scard_pcsc_init: g_remove_dir failed"); - } + g_snprintf(g_pcsclite_ipc_file, 255, "%s", csock_name); } - if (!g_directory_exist(g_pcsclite_ipc_dir)) + else { - if (!g_create_dir(g_pcsclite_ipc_dir)) - { - if (!g_directory_exist(g_pcsclite_ipc_dir)) - { - LOG_DEVEL(LOG_LEVEL_WARNING, "scard_pcsc_init: g_create_dir failed"); - } - } + disp = g_display_num; + g_snprintf(g_pcsclite_ipc_file, 255, "/tmp/.xrdp/pcscd%d.com", disp); } - g_chmod_hex(g_pcsclite_ipc_dir, 0x1777); - g_snprintf(g_pcsclite_ipc_file, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_pcsc_init: trans_listen on port %s", g_pcsclite_ipc_file); g_lis->trans_conn_in = my_pcsc_trans_conn_in; error = trans_listen(g_lis, g_pcsclite_ipc_file); if (error != 0) @@ -1892,22 +2209,33 @@ scard_pcsc_init(void) int scard_pcsc_deinit(void) { + int index; + struct pcsc_uds_client *uds_client; + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_pcsc_deinit:"); + if (g_uds_clients != 0) + { + for (index = g_uds_clients->count - 1; index >= 0; index--) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + uds_client->ref_count = 0; + free_uds_client(uds_client); + list_remove_item(g_uds_clients, index); + } + } + if (g_lis != 0) { trans_delete(g_lis); g_lis = 0; } - if (g_pcsclite_ipc_dir[0] != 0) + if (g_pcsclite_ipc_file[0] != 0) { g_file_delete(g_pcsclite_ipc_file); - if (!g_remove_dir(g_pcsclite_ipc_dir)) - { - LOG_DEVEL(LOG_LEVEL_WARNING, "scard_pcsc_deinit: g_remove_dir failed"); - } - g_pcsclite_ipc_dir[0] = 0; + g_pcsclite_ipc_file[0] = 0; } return 0; diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 0588ec01e3..0f0a5deada 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -29,11 +29,11 @@ int scard_pcsc_check_wait_objs(void); int scard_pcsc_init(void); int scard_pcsc_deinit(void); int scard_function_establish_context_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_release_context_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_list_readers_return(void *user_data, struct stream *in_s, int len, int status); @@ -47,8 +47,8 @@ int scard_function_control_return(void *user_data, int len, int status); int scard_function_get_status_change_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_connect_return(void *user_data, struct stream *in_s, @@ -59,16 +59,16 @@ int scard_function_status_return(void *user_data, int len, int status); int scard_function_begin_transaction_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_end_transaction_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_is_context_valid_return(void *user_data, - struct stream *in_s, - int len, int status); + struct stream *in_s, + int len, int status); int scard_function_reconnect_return(void *user_data, struct stream *in_s, From 23191b26f4a399ccc7d781c5b41c6d48f209ead9 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 6 Dec 2017 12:56:09 -0800 Subject: [PATCH 03/11] pcsc: use socket define, fix warnings --- common/xrdp_sockets.h | 2 ++ sesman/chansrv/smartcard_pcsc.c | 11 +++++++---- sesman/env.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/common/xrdp_sockets.h b/common/xrdp_sockets.h index 1a625ef734..90a9df2320 100644 --- a/common/xrdp_sockets.h +++ b/common/xrdp_sockets.h @@ -28,6 +28,7 @@ #define CHANSRV_API_BASE_STR "xrdpapi_%d" #define XRDP_X11RDP_BASE_STR "xrdp_display_%d" #define XRDP_DISCONNECT_BASE_STR "xrdp_disconnect_display_%d" +#define XRDP_PCSC_BASE_STR "xrdp_pcsc_socket_%d" /* fullpath of sockets */ #define XRDP_CHANSRV_STR XRDP_SOCKET_PATH "/" XRDP_CHANSRV_BASE_STR @@ -36,5 +37,6 @@ #define CHANSRV_API_STR XRDP_SOCKET_PATH "/" CHANSRV_API_BASE_STR #define XRDP_X11RDP_STR XRDP_SOCKET_PATH "/" XRDP_X11RDP_BASE_STR #define XRDP_DISCONNECT_STR XRDP_SOCKET_PATH "/" XRDP_DISCONNECT_BASE_STR +#define XRDP_PCSC_STR XRDP_SOCKET_PATH "/" XRDP_PCSC_BASE_STR #endif diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 9ef6519fa9..a7a0c216f5 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -42,6 +42,7 @@ #include "chansrv.h" #include "list.h" #include "defines.h" +#include "xrdp_sockets.h" #if PCSC_STANDIN @@ -1639,6 +1640,7 @@ static int scard_process_cmd_get_readers_state(struct trans *con, struct stream *in_s) { int rv; + int reader_state_bytes; struct stream *out_s; struct pcsc_uds_client *uds_client; @@ -1646,8 +1648,9 @@ scard_process_cmd_get_readers_state(struct trans *con, struct stream *in_s) rv = 0; uds_client = (struct pcsc_uds_client *) (con->callback_data); out_s = con->out_s; - init_stream(out_s, sizeof(uds_client->readerStates)); - out_uint8a(out_s, uds_client->readerStates, sizeof(uds_client->readerStates)); + reader_state_bytes = sizeof(uds_client->readerStates); + init_stream(out_s, reader_state_bytes); + out_uint8a(out_s, uds_client->readerStates, reader_state_bytes); s_mark_end(out_s); rv = trans_write_copy(con); return rv; @@ -1786,7 +1789,7 @@ scard_function_get_status_change_return(void *user_data, return_code = 0x8010000A; } - if (return_code == 0x8010000A) /* SCARD_E_TIMEOUT */ + if (return_code == (int) 0x8010000A) /* SCARD_E_TIMEOUT */ { rsa = g_new(READER_STATE, uds_client->numReaders + 1); for (index = 0; index < uds_client->numReaders; index++) @@ -2190,7 +2193,7 @@ scard_pcsc_init(void) else { disp = g_display_num; - g_snprintf(g_pcsclite_ipc_file, 255, "/tmp/.xrdp/pcscd%d.com", disp); + g_snprintf(g_pcsclite_ipc_file, 255, XRDP_PCSC_STR, disp); } LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_pcsc_init: trans_listen on port %s", g_pcsclite_ipc_file); g_lis->trans_conn_in = my_pcsc_trans_conn_in; diff --git a/sesman/env.c b/sesman/env.c index cbbb4c8480..f9c7d0dca4 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -145,7 +145,7 @@ env_set_user(const char *username, char **passwd_file, int display, g_setenv("XRDP_SESSION", "1", 1); /* XRDP_SOCKET_PATH should be set even here, chansrv uses this */ g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); - g_sprintf(text, "%s/pcsc_socket_%d", XRDP_SOCKET_PATH, display); + g_sprintf(text, XRDP_PCSC_STR, display); g_setenv("PCSCLITE_CSOCK_NAME", text, 1); /* pulse sink socket */ g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_OUT_BASE_STR, display); From 684917a69b9a30ba8c082ca5ee353bef071379ef Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 6 Dec 2017 17:10:01 -0800 Subject: [PATCH 04/11] pcsc: fixes, cleanup --- sesman/chansrv/smartcard_pcsc.c | 1 + sesman/session.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index a7a0c216f5..df99f5f71d 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -123,6 +123,7 @@ create_uds_client(struct trans *con) { return 0; } + uds_client->ref_count = 1; g_autoinc++; uds_client->uds_client_id = g_autoinc; uds_client->con = con; diff --git a/sesman/session.c b/sesman/session.c index c26e62de60..24a6a7bf8a 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -1340,6 +1340,18 @@ cleanup_sockets(int display) } } + g_snprintf(file, 255, XRDP_PCSC_STR, display); + if (g_file_exist(file)) + { + log_message(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); + if (g_file_delete(file) == 0) + { + log_message(LOG_LEVEL_DEBUG, + "cleanup_sockets: failed to delete %s", file); + error++; + } + } + return error; } From 19768b6567aa83af33f71bf68f9ad0142cb8da64 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 6 Dec 2017 17:25:22 -0800 Subject: [PATCH 05/11] check for pcsc socket in x_server_running_check_ports --- sesman/session.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sesman/session.c b/sesman/session.c index 24a6a7bf8a..cef40c341a 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -242,6 +242,13 @@ x_server_running_check_ports(int display) x_running = g_file_exist(text); } + if (!x_running) + { + LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text); + g_sprintf(text, XRDP_PCSC_STR, display); + x_running = g_file_exist(text); + } + if (x_running) { LOG(LOG_LEVEL_INFO, "Found X server running at %s", text); From 995cd02713bf1bb47d6f0e3bf45460963ba29dc5 Mon Sep 17 00:00:00 2001 From: zorgluf Date: Mon, 21 Dec 2020 15:11:56 +0100 Subject: [PATCH 06/11] Fix issues with recent version of pcsc (1.8.8) --- sesman/chansrv/smartcard_pcsc.c | 64 +++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index df99f5f71d..40e4cae6c4 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -47,6 +47,9 @@ #if PCSC_STANDIN +#define MAX_ATR_SIZE 33 +#define MAX_READERS 32 + extern int g_display_num; /* in chansrv.c */ static int g_autoinc = 0; /* general purpose autoinc */ @@ -64,7 +67,7 @@ typedef struct pubReaderStatesList tui32 eventCounter; tui32 readerState; tui32 readerSharing; - tui8 cardAtr[36]; + tui8 cardAtr[MAX_ATR_SIZE]; tui32 cardAtrLength; tui32 cardProtocol; } PCSC_READER_STATE; @@ -90,11 +93,9 @@ struct pcsc_uds_client int state; int pad1; - /* should be 2944 bytes */ - /* 128 + 4 + 4 + 4 + 36 + 4 + 4 = 186, 186 * 16 = 2944 */ - PCSC_READER_STATE readerStates[16]; - tui32 current_states[16]; - tui32 event_states[16]; + PCSC_READER_STATE readerStates[MAX_READERS]; + tui32 current_states[MAX_READERS]; + tui32 event_states[MAX_READERS]; int numReaders; int waiting; int something_changed; @@ -751,7 +752,7 @@ scard_readers_to_list(struct pcsc_uds_client *uds_client, uds_client->readerStates[reader_index].eventCounter = 0; uds_client->readerStates[reader_index].readerState = 0; uds_client->readerStates[reader_index].readerSharing = 0; - g_memset(uds_client->readerStates[reader_index].cardAtr, 0, 36); + g_memset(uds_client->readerStates[reader_index].cardAtr, 0, MAX_ATR_SIZE); uds_client->readerStates[reader_index].cardAtrLength = 0; uds_client->readerStates[reader_index].cardProtocol = 0; uds_client->current_states[reader_index] = 0; @@ -759,7 +760,7 @@ scard_readers_to_list(struct pcsc_uds_client *uds_client, } reader_index++; hold_reader = uds_client->readerStates[reader_index]; - if (reader_index > 15) + if (reader_index > (MAX_READERS - 1)) { return 0; } @@ -774,7 +775,7 @@ scard_readers_to_list(struct pcsc_uds_client *uds_client, } uds_client->numReaders = reader_index; /* clear the rest */ - while (reader_index < 16) + while (reader_index < MAX_READERS) { g_memset(uds_client->readerStates + reader_index, 0, sizeof(PCSC_READER_STATE)); uds_client->current_states[reader_index] = 0; @@ -1400,11 +1401,46 @@ scard_function_transmit_return(void *user_data, } /*****************************************************************************/ -/* returns error */ +struct pcsc_control_struct +{ + int hCard; + tui32 dwControlCode; + tui32 cbSendLength; + tui32 cbRecvLength; + tui32 dwBytesReturned; + tui32 rv; +}; + +#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F +/*****************************************************************************/ +/* process but return not supported*/ int scard_process_control(struct trans *con, struct stream *in_s) { - return 0; + struct pcsc_control_struct pcscCtl; + char* sentBuffer; + int rv; + struct stream *out_s; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_control:"); + rv = 0; + in_uint8a(in_s, &pcscCtl, sizeof(pcscCtl)); + sentBuffer = g_new0(char, pcscCtl.cbSendLength); + in_uint8a(in_s, sentBuffer, pcscCtl.cbSendLength); + + pcscCtl.cbRecvLength = pcscCtl.cbSendLength; + pcscCtl.dwBytesReturned = 0; + pcscCtl.rv = SCARD_E_UNSUPPORTED_FEATURE; + + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_control: return SCARD_E_UNSUPPORTED_FEATURE"); + out_s = con->out_s; + init_stream(out_s, 0); + out_uint8a(out_s, &pcscCtl, sizeof(pcscCtl)); + s_mark_end(out_s); + rv = trans_write_copy(con); + + g_free(sentBuffer); + return rv; } /*****************************************************************************/ @@ -1459,7 +1495,7 @@ scard_process_status(struct trans *con, struct stream *in_s) scard_send_status(pcscStatus, 0, lcontext->context, lcontext->context_bytes, lcard->card, lcard->card_bytes, - 128, 36, 0); + 128, MAX_ATR_SIZE, 0); } else { @@ -1509,7 +1545,7 @@ scard_function_status_return(void *user_data, int dwProtocol; int dwAtrLen; int return_code; - char attr[36]; + char attr[MAX_ATR_SIZE]; char reader_name[128]; int rv; struct stream *out_s; @@ -1769,7 +1805,7 @@ scard_function_get_status_change_return(void *user_data, uds_client->send_status = 1; } in_uint32_le(in_s, uds_client->readerStates[index].cardAtrLength); - in_uint8a(in_s, uds_client->readerStates[index].cardAtr, 36); + in_uint8a(in_s, uds_client->readerStates[index].cardAtr, MAX_ATR_SIZE); uds_client->readerStates[index].eventCounter = (event_state >> 16) & 0xFFFF; } } From 55754bd1356b36787f3d0ab9902928eeb380d0d0 Mon Sep 17 00:00:00 2001 From: zorgluf Date: Mon, 22 Mar 2021 18:03:32 +0100 Subject: [PATCH 07/11] add comments based on aquesnel review --- sesman/chansrv/smartcard.c | 6 ++++-- sesman/env.c | 1 + sesman/session.c | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 26178a4c12..15b9b54fc8 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -1918,14 +1918,15 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, out_uint32_le(s, send_bytes); - val = send_bytes > 0 ? 0x00020008 : 0; + val = send_bytes > 0 ? 0x00020008 : 0; /* 0x00020008 : pointer to data after Transmit_Call struct : 0x00020000 + offset * 4 : map3 */ out_uint32_le(s, val); /* map3 */ - val = recv_ior_is_null ? 0 : 0x00020008; + val = recv_ior_is_null ? 0 : 0x00020008; /* 0x00020008 : pointer to data after Transmit_Call struct : 0x00020000 + offset * 4 : map4 */ out_uint32_le(s, val); /* map 4 */ out_uint32_le(s, recv_is_null); // map5 out_uint32_le(s, recv_bytes); + /* end of Transmit_Call struct */ /* map0 */ out_uint32_le(s, context_bytes); @@ -1943,6 +1944,7 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes, if (send_bytes > 0) { + /* map3 */ out_uint32_le(s, send_bytes); out_uint8a(s, send_data, send_bytes); align_s(s, 4); diff --git a/sesman/env.c b/sesman/env.c index f9c7d0dca4..e11322c88a 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -145,6 +145,7 @@ env_set_user(const char *username, char **passwd_file, int display, g_setenv("XRDP_SESSION", "1", 1); /* XRDP_SOCKET_PATH should be set even here, chansrv uses this */ g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); + /* env varibale used by PCSC to get remote smartcard reader socket */ g_sprintf(text, XRDP_PCSC_STR, display); g_setenv("PCSCLITE_CSOCK_NAME", text, 1); /* pulse sink socket */ diff --git a/sesman/session.c b/sesman/session.c index cef40c341a..298851723d 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -1350,10 +1350,10 @@ cleanup_sockets(int display) g_snprintf(file, 255, XRDP_PCSC_STR, display); if (g_file_exist(file)) { - log_message(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); + LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); if (g_file_delete(file) == 0) { - log_message(LOG_LEVEL_DEBUG, + LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: failed to delete %s", file); error++; } From 3622691440f688316330c3006cef7924ab248dd7 Mon Sep 17 00:00:00 2001 From: zorgluf Date: Fri, 28 May 2021 10:30:28 +0200 Subject: [PATCH 08/11] Add some comments to smartcard code --- sesman/chansrv/smartcard.h | 6 ++++++ sesman/chansrv/smartcard_pcsc.c | 36 ++++++++++----------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index ef154e744a..56991a08d8 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -48,6 +48,12 @@ #define SCARD_RESET_CARD 0x00000001 /* reset smart card */ #define SCARD_UNPOWER_CARD 0x00000002 /* turn off and reset card */ +/* see [MS-RDPESC] 2.2.5 protocol return code */ +#define SCARD_S_SUCCESS 0x00000000 +#define SCARD_F_INTERNAL_ERROR 0x80100001 +#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F +#define SCARD_E_TIMEOUT 0x8010000A + struct xrdp_scard_io_request { tui32 dwProtocol; diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 40e4cae6c4..6ebd1408d8 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -571,23 +571,10 @@ scard_function_establish_context_return(void *user_data, in_uint32_le(in_s, context_bytes); if (return_code != 0 || context_bytes < 4 || context_bytes > 16) { - LOG(LOG_LEVEL_ERROR, "scard_function_establish_context_return: error " - "return_code 0x%8.8x context_bytes %d", - return_code, context_bytes); - if (uds_client->state == 1) - { - out_s = uds_client->con->out_s; - init_stream(out_s, 8192); - out_uint32_le(out_s, 4); - out_uint32_le(out_s, 3); - out_uint32_le(out_s, 0x80100001); /* result */ - s_mark_end(out_s); - rv = trans_write_copy(uds_client->con); - uds_client->state = 0; - } - uds_client->ref_count--; - free_uds_client(uds_client); - return rv; + LOG(LOG_LEVEL_ERROR, "scard_function_establish_context_return: opps " + "context_bytes %d", context_bytes); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "", in_s->p, context_bytes); + return 1; } in_uint8a(in_s, context, context_bytes); lcontext = uds_client_add_context(uds_client, context, context_bytes); @@ -603,9 +590,9 @@ scard_function_establish_context_return(void *user_data, { out_s = uds_client->con->out_s; init_stream(out_s, 8192); - out_uint32_le(out_s, 4); - out_uint32_le(out_s, 3); - out_uint32_le(out_s, 0x80100001); /* result */ + out_uint32_le(out_s, SCARD_PROTOCOL_RAW); /*header - protocol */ + out_uint32_le(out_s, 3); /*header - size */ + out_uint32_le(out_s, SCARD_F_INTERNAL_ERROR); /* result SCARD_F_INTERNAL_ERROR */ s_mark_end(out_s); rv = trans_write_copy(uds_client->con); uds_client->state = 0; @@ -1411,7 +1398,6 @@ struct pcsc_control_struct tui32 rv; }; -#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F /*****************************************************************************/ /* process but return not supported*/ int @@ -1817,16 +1803,16 @@ scard_function_get_status_change_return(void *user_data, /* send version back */ out_s = uds_client->con->out_s; init_stream(out_s, 8192); - out_uint32_le(out_s, 4); - out_uint32_le(out_s, 3); + out_uint32_le(out_s, SCARD_PROTOCOL_RAW); + out_uint32_le(out_s, 3); /* header - size */ out_uint32_le(out_s, 0); /* result */ s_mark_end(out_s); rv = trans_write_copy(uds_client->con); uds_client->state = 0; - return_code = 0x8010000A; + return_code = SCARD_E_TIMEOUT; } - if (return_code == (int) 0x8010000A) /* SCARD_E_TIMEOUT */ + if (return_code == (int) SCARD_E_TIMEOUT) /* SCARD_E_TIMEOUT */ { rsa = g_new(READER_STATE, uds_client->numReaders + 1); for (index = 0; index < uds_client->numReaders; index++) From 49503d212268665eb5223633cbe17713eace4c62 Mon Sep 17 00:00:00 2001 From: zorgluf Date: Mon, 19 Jul 2021 14:22:42 +0200 Subject: [PATCH 09/11] Smartcard fix for pcsclite 1.8.23+ --- sesman/chansrv/smartcard_pcsc.c | 35 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 6ebd1408d8..f294530d66 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -100,6 +100,7 @@ struct pcsc_uds_client int waiting; int something_changed; int send_status; + int version; }; static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */ @@ -1638,8 +1639,8 @@ static int scard_process_cmd_version(struct trans *con, struct stream *in_s) { int rv; - int major; - int minor; + int major = 0; + int minor = 0; struct pcsc_uds_client *uds_client; void *user_data; @@ -1647,10 +1648,10 @@ scard_process_cmd_version(struct trans *con, struct stream *in_s) rv = 0; in_uint32_le(in_s, major); in_uint32_le(in_s, minor); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_version: major %d minor %d", major, minor); + LOG_DEVEL(LOG_LEVEL_INFO, "scard_process_version: major %d minor %d", major, minor); uds_client = (struct pcsc_uds_client *) (con->callback_data); uds_client->state = 1; - uds_client = (struct pcsc_uds_client *) (con->callback_data); + uds_client->version = major * 1000 + minor; user_data = (void *) (tintptr) (uds_client->uds_client_id); uds_client->ref_count++; scard_send_establish_context(user_data, 0); /* SCARD_SCOPE_USER */ @@ -1686,18 +1687,30 @@ scard_process_cmd_wait_reader_state_change(struct trans *con, struct stream *in_s) { int rv; - //struct stream *out_s; - int timeOut; + int timeOut __attribute__((unused)); + int reader_state_bytes; + struct stream *out_s; struct pcsc_uds_client *uds_client; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change:"); - in_uint32_le(in_s, timeOut); - LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change: timeOut %d", - timeOut); - //out_s = con->out_s; uds_client = (struct pcsc_uds_client *) (con->callback_data); uds_client->waiting = 1; - rv = 0; + if (uds_client->version > 4002) { + //In these versions, return reader states immediately + out_s = con->out_s; + reader_state_bytes = sizeof(uds_client->readerStates); + init_stream(out_s, reader_state_bytes); + out_uint8a(out_s, uds_client->readerStates, reader_state_bytes); + s_mark_end(out_s); + rv = trans_write_copy(con); + } else { + in_uint32_le(in_s, timeOut); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change: timeOut %d", + timeOut); + in_uint32_le(in_s, rv); + LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change: rv %d", rv); + } + return rv; } From 9a94ebb7698c3faf270e2b3e5cd67af93db58023 Mon Sep 17 00:00:00 2001 From: zorgluf Date: Mon, 26 Jul 2021 14:44:59 +0200 Subject: [PATCH 10/11] moved attribute(unused) to UNUSED_VAR macro --- sesman/chansrv/smartcard_pcsc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index f294530d66..ab86211b04 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -1687,11 +1687,12 @@ scard_process_cmd_wait_reader_state_change(struct trans *con, struct stream *in_s) { int rv; - int timeOut __attribute__((unused)); + int timeOut; int reader_state_bytes; struct stream *out_s; struct pcsc_uds_client *uds_client; + UNUSED_VAR(timeOut); //remove when timeOut variable used outside debug mode LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_process_cmd_wait_reader_state_change:"); uds_client = (struct pcsc_uds_client *) (con->callback_data); uds_client->waiting = 1; From d6ad58db1b511c83b54febf8379cabe26b0c5c6d Mon Sep 17 00:00:00 2001 From: zorgluf Date: Mon, 2 Aug 2021 15:44:18 +0200 Subject: [PATCH 11/11] Revert MAX_READERS value to 16, matching default PCSCLITE_MAX_READERS_CONTEXTS --- sesman/chansrv/smartcard_pcsc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index ab86211b04..b71f082801 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -48,7 +48,11 @@ #define MAX_ATR_SIZE 33 -#define MAX_READERS 32 + +//The MAX_READERS value is generaly 16, but on some RHEL release, ti might be 32 or 64. See the PCSCLITE_MAX_READERS_CONTEXTS of the libpcsclite source package and adjust MAX_READERS value accordingly. +#define MAX_READERS 16 +//#define MAX_READERS 32 +//#define MAX_READERS 64 extern int g_display_num; /* in chansrv.c */