From a6fea326ae995df1974c3eb0c856d897eb5066cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BB=D0=B5=D0=BD=D0=BA=D0=BE=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B5?= =?UTF-8?q?=D0=B2=D0=B8=D1=87?= Date: Tue, 13 Jun 2023 15:22:03 +0300 Subject: [PATCH 1/4] Replace sesman\chansrv\smartcard from zorgluf:xrdp:pcsc_0.9.14 --- sesman/chansrv/smartcard.c | 47 +- sesman/chansrv/smartcard.h | 15 +- sesman/chansrv/smartcard_pcsc.c | 1440 +++++++++++++++++++------------ 3 files changed, 932 insertions(+), 570 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 9bc657b61f..15b9b54fc8 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; } @@ -799,7 +804,7 @@ scard_send_get_attrib(void *user_data, char *card, int card_bytes, ******************************************************************************/ /** - * Create a new stream and insert specified IOCTL + * Crate a new stream and insert specified IOCTL * * @param irp information about the I/O * @param ioctl the IOCTL code @@ -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 */ @@ -1911,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->cbPciLength > 0 ? 0x0002000c : 0; + 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, 0); // map5 + 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); @@ -1936,12 +1944,13 @@ 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); } - 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..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; @@ -117,7 +123,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 +150,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 +162,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 042e3de5bd..b5f712ca5f 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -41,10 +41,19 @@ #include "trans.h" #include "chansrv.h" #include "list.h" +#include "defines.h" +#include "xrdp_sockets.h" #if PCSC_STANDIN +#define MAX_ATR_SIZE 33 + +//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 */ static int g_autoinc = 0; /* general purpose autoinc */ @@ -56,6 +65,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[MAX_ATR_SIZE]; + tui32 cardAtrLength; + tui32 cardProtocol; +} PCSC_READER_STATE; + struct pcsc_context { tui32 app_context; /* application context, always 4 byte */ @@ -68,15 +88,30 @@ 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; + + PCSC_READER_STATE readerStates[MAX_READERS]; + tui32 current_states[MAX_READERS]; + tui32 event_states[MAX_READERS]; + int numReaders; + int waiting; + int something_changed; + int send_status; + int version; }; 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 struct trans *g_lis = 0; static char g_pcsclite_ipc_file[256] = ""; /*****************************************************************************/ @@ -96,6 +131,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; @@ -136,6 +172,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 +283,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 +311,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 +323,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 +361,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,12 +421,11 @@ 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, - "context_add_card: failed to allocate memory for pcsc_card"); + "context_add_card: failed to allocate memmory for pcsc_card"); return 0; } g_autoinc++; @@ -355,7 +438,7 @@ context_add_card(struct pcsc_uds_client *uds_client, if (acontext->cards == 0) { LOG(LOG_LEVEL_ERROR, "context_add_card: failed to allocate " - "memory for uds_client->contexts->cards"); + "memmory for uds_client->contexts->cards"); return 0; } } @@ -418,6 +501,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 +529,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 +541,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 +554,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,12 +568,15 @@ 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); @@ -497,20 +589,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); - if (out_s == NULL) + else { - return 1; - } - 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); + 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, 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; + } + 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; } /*****************************************************************************/ @@ -535,6 +653,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); @@ -548,8 +667,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; @@ -567,77 +687,95 @@ scard_function_release_context_return(void *user_data, return 1; } con = uds_client->con; - out_s = trans_get_out_s(con, 8192); - if (out_s == NULL) + return_code = 0; + if (status == 0) { - return 1; + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); } - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + out_s = trans_get_out_s(con, 8192); + 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, MAX_ATR_SIZE); + 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 > (MAX_READERS - 1)) + { + 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 < MAX_READERS) { - LOG(LOG_LEVEL_ERROR, "scard_process_list_readers: " - "get_pcsc_context_by_app_context failed"); - 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; } @@ -647,107 +785,83 @@ 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; + + LOG(LOG_LEVEL_ERROR, "!!F uds_client numReaders %d", uds_client->numReaders); + + 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); + LOG(LOG_LEVEL_ERROR, "!!F scard_readers_to_list uds_client numReaders %d", uds_client->numReaders); + scard_readers_to_list(uds_client, in_s->p, llen); + LOG(LOG_LEVEL_ERROR, "!!E scard_readers_to_list uds_client numReaders %d", uds_client->numReaders); + 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); - if (out_s == NULL) - { - return 1; - } - 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; } /*****************************************************************************/ @@ -761,11 +875,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 " @@ -773,15 +887,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; } @@ -793,17 +901,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); @@ -817,42 +932,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); - if (out_s == NULL) - { - return 1; - } - 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 @@ -877,6 +1010,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); @@ -889,8 +1023,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; @@ -908,19 +1043,22 @@ scard_function_disconnect_return(void *user_data, return 1; } con = uds_client->con; - out_s = trans_get_out_s(con, 8192); - if (out_s == NULL) + return_code = 0; + if (status == 0) { - return 1; + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); } - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + out_s = trans_get_out_s(con, 8192); + 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; } /*****************************************************************************/ @@ -946,6 +1084,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); @@ -959,9 +1098,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; @@ -978,21 +1118,32 @@ scard_function_begin_transaction_return(void *user_data, return 1; } con = uds_client->con; - out_s = trans_get_out_s(con, 8192); - if (out_s == NULL) + return_code = 0; + if (status == 0) { - return 1; + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); } - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + out_s = trans_get_out_s(con, 8192); + 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 @@ -1018,6 +1169,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, @@ -1032,9 +1184,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; @@ -1051,20 +1204,23 @@ scard_function_end_transaction_return(void *user_data, return 1; } con = uds_client->con; - - out_s = trans_get_out_s(con, 8192); - if (out_s == NULL) + return_code = 0; + if (status == 0) { - return 1; + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); } - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + + out_s = trans_get_out_s(con, 8192); + 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; } /*****************************************************************************/ @@ -1077,7 +1233,6 @@ scard_function_get_attrib_return(void *user_data, return 0; } -/*****************************************************************************/ struct pcsc_transmit { int uds_client_id; @@ -1093,6 +1248,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; @@ -1104,18 +1261,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, @@ -1129,17 +1290,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; } @@ -1150,10 +1310,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; @@ -1177,94 +1341,104 @@ 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); - if (out_s == NULL) - { - return 1; - } - 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; } /*****************************************************************************/ -/* returns error */ +struct pcsc_control_struct +{ + int hCard; + tui32 dwControlCode; + tui32 cbSendLength; + tui32 cbRecvLength; + tui32 dwBytesReturned; + tui32 rv; +}; + +/*****************************************************************************/ +/* process but return not supported*/ 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; + struct pcsc_control_struct pcscCtl; + char* sentBuffer; + int rv; + struct stream *out_s; 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; + 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; } /*****************************************************************************/ @@ -1274,51 +1448,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); - if (out_s == NULL) - { - return 1; - } - 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; } /*****************************************************************************/ @@ -1333,23 +1463,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)) { @@ -1357,15 +1482,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, MAX_ATR_SIZE, 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 @@ -1397,31 +1536,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[MAX_ATR_SIZE]; + 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); @@ -1434,26 +1571,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 { @@ -1464,105 +1604,156 @@ 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_uint16_le(in_s, reader_name[index]); - } - g_wcstombs(lreader_name, reader_name, 99); + in_uint8a(in_s, reader_name, dwReaderLen); + } - 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); - if (out_s == NULL) + + for (index = 0; index < 16; index++) { - return 1; + if (g_strcmp(reader_name, uds_client->readerStates[index].readerName) == 0) + { + 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; + } } - 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 = 0; + int minor = 0; 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_INFO, "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->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 */ + 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; + int reader_state_bytes; + 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; + 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; +} - 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; +/*****************************************************************************/ +/* returns error */ +static int +scard_process_cmd_wait_reader_state_change(struct trans *con, + struct stream *in_s) +{ + int rv; + 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; + 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); } - scard_send_get_status_change(user_data, - lcontext->context, lcontext->context_bytes, - 1, dwTimeout, cReaders, rsa); - g_free(rsa); + 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; } @@ -1572,72 +1763,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); - if (out_s == NULL) - { - return 1; - } - 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, MAX_ATR_SIZE); + 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, 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 = 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++) + { + 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); + + } + else if (return_code == 0) + { + uds_client->ref_count++; + scard_send_list_readers(uds_client, + context->context, + context->context_bytes, + 0, 8148, 0, 0); } - 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, 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; } /*****************************************************************************/ @@ -1645,6 +1897,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; @@ -1658,10 +1912,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; } @@ -1673,11 +1933,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); @@ -1691,20 +1951,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); - if (out_s == NULL) + return_code = 0; + if (status == 0) { - return 1; + in_uint8s(in_s, 16); + in_uint32_le(in_s, return_code); } - s_push_layer(out_s, iso_hdr, 8); - out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + 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; } /*****************************************************************************/ @@ -1812,6 +2073,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; @@ -1835,14 +2116,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; } @@ -1871,6 +2202,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) { @@ -1878,6 +2210,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) { @@ -1892,7 +2225,7 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) int scard_pcsc_init(void) { - char *home; +char *home; int disp; int error; @@ -1943,22 +2276,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; From 3c340d172f3a60f3b6a91d7f5ff7b2ab6a175566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BB=D0=B5=D0=BD=D0=BA=D0=BE=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B5?= =?UTF-8?q?=D0=B2=D0=B8=D1=87?= Date: Thu, 15 Jun 2023 10:16:20 +0300 Subject: [PATCH 2/4] remove debug comment --- sesman/chansrv/smartcard_pcsc.c | 6 +----- sesman/sesman.ini.in | 2 +- xrdp/xrdp.ini.in | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index b5f712ca5f..2981be0c25 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -753,11 +753,11 @@ scard_readers_to_list(struct pcsc_uds_client *uds_client, uds_client->event_states[reader_index] = 0; } reader_index++; - hold_reader = uds_client->readerStates[reader_index]; if (reader_index > (MAX_READERS - 1)) { return 0; } + hold_reader = uds_client->readerStates[reader_index]; name_index = 0; } else @@ -798,8 +798,6 @@ scard_function_list_readers_return(void *user_data, LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return:"); uds_client = (struct pcsc_uds_client *) user_data; - LOG(LOG_LEVEL_ERROR, "!!F uds_client numReaders %d", uds_client->numReaders); - rv = 0; if (status == 0) { @@ -818,9 +816,7 @@ scard_function_list_readers_return(void *user_data, 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); - LOG(LOG_LEVEL_ERROR, "!!F scard_readers_to_list uds_client numReaders %d", uds_client->numReaders); scard_readers_to_list(uds_client, in_s->p, llen); - LOG(LOG_LEVEL_ERROR, "!!E scard_readers_to_list uds_client numReaders %d", uds_client->numReaders); for (index = 0; index < uds_client->numReaders; index++) { g_strncpy(rsa[index].reader_name, uds_client->readerStates[index].readerName, 127); diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in index 01a1aa5b71..954ddfa09a 100644 --- a/sesman/sesman.ini.in +++ b/sesman/sesman.ini.in @@ -185,7 +185,7 @@ FileUmask=077 ; xrdp-chansrv.${DISPLAY}.log ; ; Note: Log levels can be any of: core, error, warning, info, debug, or trace -LogLevel=INFO +LogLevel=DEBUG EnableSyslog=true #SyslogLevel=INFO #EnableConsole=false diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index 93c23196b2..bf00c9bf51 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -3,7 +3,7 @@ ini_version=1 ; fork a new process for each incoming connection -fork=true +fork=false ; ports to listen on, number alone means listen on all interfaces ; 0.0.0.0 or :: if ipv6 is configured From ea2520cc55fe78c37f2c31ee6ddc1674cb21f334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BB=D0=B5=D0=BD=D0=BA=D0=BE=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B5?= =?UTF-8?q?=D0=B2=D0=B8=D1=87?= Date: Thu, 15 Jun 2023 13:30:02 +0300 Subject: [PATCH 3/4] Add rdp_keyboard_ru to xrdp_keyboard.ini --- xrdp/xrdp_keyboard.ini | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xrdp/xrdp_keyboard.ini b/xrdp/xrdp_keyboard.ini index c3093770ed..5093a02814 100644 --- a/xrdp/xrdp_keyboard.ini +++ b/xrdp/xrdp_keyboard.ini @@ -145,3 +145,16 @@ rdp_layout_gb=gb rdp_layout_latam=latam rdp_layout_be=be rdp_layout_pt=pt + +[rdp_keyboard_ru] +keyboard_type=4 +keyboard_type=7 +keyboard_subtype=1 +model=pc105 +options=grp:alt_shift_toggle +rdp_layouts=default_rdp_layouts +layouts_map=layouts_map_ru + +[layouts_map_ru] +rdp_layout_us=us,ru +rdp_layout_ru=us,ru \ No newline at end of file From c7d467691b30dc8078d39ee6cc1e361f515c560b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BB=D0=B5=D0=BD=D0=BA=D0=BE=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B5?= =?UTF-8?q?=D0=B2=D0=B8=D1=87?= Date: Mon, 19 Jun 2023 12:18:44 +0300 Subject: [PATCH 4/4] Change: MAX_ATR_SIZE 36 --- sesman/chansrv/pcsc/xrdp_pcsc.c | 2 +- sesman/chansrv/smartcard_pcsc.c | 2 +- sesman/sesman.ini.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 220c97c7df..10b60dbf5a 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -41,7 +41,7 @@ typedef SCARDCONTEXT *LPSCARDCONTEXT; typedef LONG SCARDHANDLE; typedef SCARDHANDLE *LPSCARDHANDLE; -#define MAX_ATR_SIZE 33 +#define MAX_ATR_SIZE 36 typedef struct _SCARD_READERSTATE { diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 2981be0c25..42896d2820 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -47,7 +47,7 @@ #if PCSC_STANDIN -#define MAX_ATR_SIZE 33 +#define MAX_ATR_SIZE 36 //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 diff --git a/sesman/sesman.ini.in b/sesman/sesman.ini.in index 954ddfa09a..01a1aa5b71 100644 --- a/sesman/sesman.ini.in +++ b/sesman/sesman.ini.in @@ -185,7 +185,7 @@ FileUmask=077 ; xrdp-chansrv.${DISPLAY}.log ; ; Note: Log levels can be any of: core, error, warning, info, debug, or trace -LogLevel=DEBUG +LogLevel=INFO EnableSyslog=true #SyslogLevel=INFO #EnableConsole=false