From d22b8b5ed0868adf21a6b96a8f119dda5b96c25a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 7 Sep 2013 23:54:36 -0700 Subject: [PATCH 01/32] chansrv: added timeout callback --- sesman/chansrv/chansrv.c | 139 +++++++++++++++++++++++++++++++++++++++ sesman/chansrv/chansrv.h | 5 +- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index d81c488d..c3d1aa79 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -76,6 +76,143 @@ int g_exec_pid = 0; /* this variable gets bumped up once per DVC we create */ tui32 g_dvc_chan_id = 100; +struct timeout_obj +{ + tui32 mstime; + void* data; + void (*callback)(void* data); + struct timeout_obj* next; +}; + +static struct timeout_obj *g_timeout_head = 0; +static struct timeout_obj *g_timeout_tail = 0; + +/*****************************************************************************/ +int APP_CC +add_timeout(int msoffset, void (*callback)(void *data), void *data) +{ + struct timeout_obj *tobj; + tui32 now; + + LOG(10, ("add_timeout:")); + now = g_time3(); + tobj = g_malloc(sizeof(struct timeout_obj), 1); + tobj->mstime = now + msoffset; + tobj->callback = callback; + tobj->data = data; + if (g_timeout_tail == 0) + { + g_timeout_head = tobj; + g_timeout_tail = tobj; + } + else + { + g_timeout_tail->next = tobj; + g_timeout_tail = tobj; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +get_timeout(int *timeout) +{ + struct timeout_obj *tobj; + tui32 now; + int ltimeout; + + LOG(10, ("get_timeout:")); + ltimeout = *timeout; + if (ltimeout < 1) + { + ltimeout = 0; + } + tobj = g_timeout_head; + if (tobj != 0) + { + now = g_time3(); + while (tobj != 0) + { + LOG(10, (" now %u tobj->mstime %u", now, tobj->mstime)); + if (now < tobj->mstime) + { + ltimeout = tobj->mstime - now; + } + tobj = tobj->next; + } + } + if (ltimeout > 0) + { + LOG(10, (" ltimeout %d", ltimeout)); + if (*timeout < 1) + { + *timeout = ltimeout; + } + else + { + if (*timeout > ltimeout) + { + *timeout = ltimeout; + } + } + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +check_timeout(void) +{ + struct timeout_obj *tobj; + struct timeout_obj *last_tobj; + struct timeout_obj *temp_tobj; + int count; + tui32 now; + + LOG(10, ("check_timeout:")); + count = 0; + tobj = g_timeout_head; + if (tobj != 0) + { + last_tobj = 0; + while (tobj != 0) + { + count++; + now = g_time3(); + if (now >= tobj->mstime) + { + tobj->callback(tobj->data); + if (last_tobj == 0) + { + g_timeout_head = tobj->next; + if (g_timeout_head == 0) + { + g_timeout_tail = 0; + } + } + else + { + last_tobj->next = tobj->next; + if (g_timeout_tail == tobj) + { + g_timeout_tail = last_tobj; + } + } + temp_tobj = tobj; + tobj = tobj->next; + g_free(temp_tobj); + } + else + { + last_tobj = tobj; + tobj = tobj->next; + } + } + } + LOG(10, (" count %d", count)); + return 0; +} + /*****************************************************************************/ int DEFAULT_CC g_is_term(void) @@ -925,6 +1062,7 @@ channel_thread_loop(void *in_val) while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + check_timeout(); if (g_is_wait_obj_set(g_term_event)) { LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set")); @@ -1007,6 +1145,7 @@ channel_thread_loop(void *in_val) sound_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout); xfuse_get_wait_objs(objs, &num_objs, &timeout); + get_timeout(&timeout); } /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */ } diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h index 12162dd1..06ecdc07 100644 --- a/sesman/chansrv/chansrv.h +++ b/sesman/chansrv/chansrv.h @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2009-2012 - * Copyright (C) Laxmikant Rashinkar 2009-2012 + * Copyright (C) Jay Sorg 2009-2013 + * Copyright (C) Laxmikant Rashinkar 2009-2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,7 @@ g_is_term(void); int APP_CC send_channel_data(int chan_id, char *data, int size); int APP_CC main_cleanup(void); +int APP_CC add_timeout(int msoffset, void (*callback)(void* data), void* data); int APP_CC find_empty_slot_in_dvc_channels(); struct xrdp_api_data * APP_CC struct_from_dvc_chan_id(tui32 dvc_chan_id); int remove_struct_with_chan_id(tui32 dvc_chan_id); From a9f37229ac997ceefb4ce75da7a97525e8e2e5ed Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sun, 8 Sep 2013 14:22:53 -0700 Subject: [PATCH 02/32] chansrv: work on smartcard --- sesman/chansrv/devredir.c | 13 +- sesman/chansrv/irp.h | 1 + sesman/chansrv/smartcard.c | 108 +++++--- sesman/chansrv/smartcard.h | 6 + sesman/chansrv/smartcard_pcsc.c | 428 ++++++++++++++++++++++++-------- sesman/chansrv/smartcard_pcsc.h | 6 + 6 files changed, 417 insertions(+), 145 deletions(-) diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 418c29e7..22debb11 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -587,53 +587,50 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s) tui16 cap_type; tui16 cap_len; tui32 cap_version; + char* holdp; xstream_rd_u16_le(s, num_caps); xstream_seek(s, 2); /* padding */ for (i = 0; i < num_caps; i++) { + holdp = s->p; xstream_rd_u16_le(s, cap_type); xstream_rd_u16_le(s, cap_len); xstream_rd_u32_le(s, cap_version); - /* remove header length and version */ - cap_len -= 8; - switch (cap_type) { case CAP_GENERAL_TYPE: log_debug("got CAP_GENERAL_TYPE"); - xstream_seek(s, cap_len); break; case CAP_PRINTER_TYPE: log_debug("got CAP_PRINTER_TYPE"); g_is_printer_redir_supported = 1; - xstream_seek(s, cap_len); break; case CAP_PORT_TYPE: log_debug("got CAP_PORT_TYPE"); g_is_port_redir_supported = 1; - xstream_seek(s, cap_len); break; case CAP_DRIVE_TYPE: log_debug("got CAP_DRIVE_TYPE"); g_is_drive_redir_supported = 1; if (cap_version == 2) + { g_drive_redir_version = 2; - xstream_seek(s, cap_len); + } break; case CAP_SMARTCARD_TYPE: log_debug("got CAP_SMARTCARD_TYPE"); g_is_smartcard_redir_supported = 1; scard_init(); - xstream_seek(s, cap_len); break; } + s->p = holdp + cap_len; } } diff --git a/sesman/chansrv/irp.h b/sesman/chansrv/irp.h index e1a65d83..a13ea8e5 100644 --- a/sesman/chansrv/irp.h +++ b/sesman/chansrv/irp.h @@ -52,6 +52,7 @@ struct irp void (*callback)(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); + void *user_data; }; IRP * APP_CC devredir_irp_new(void); diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index c370479e..d422716c 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -137,52 +137,83 @@ extern tui32 g_completion_id; extern int g_rdpdr_chan_id; /* in chansrv.c */ /* forward declarations specific to this file */ -static void scard_send_EstablishContext(IRP *irp); +static void scard_send_EstablishContext(IRP *irp, int scope); static void scard_send_ListReaders(IRP *irp, int wide); static struct stream *scard_make_new_ioctl(IRP *irp, tui32 ioctl); static int scard_add_new_device(tui32 device_id); static int scard_get_free_slot(void); static void scard_release_resources(void); -/****************************************************************************** -** non static functions ** -******************************************************************************/ +static tui32 g_device_id = 0; +static int g_scard_index = 0; -void APP_CC -scard_device_announce(tui32 device_id) +/*****************************************************************************/ +int APP_CC +scard_send_irp_establish_context(struct trans *con, int scope) { IRP *irp; - log_debug("entered: device_id=%d", device_id); - - if (!g_smartcards_inited) + if ((irp = devredir_irp_new()) == NULL) { - g_memset(&smartcards, 0, sizeof(smartcards)); - g_smartcards_inited = 1; + log_error("system out of memory"); + return 1; } + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_EstablishContext_Return; + irp->user_data = con; + scard_send_EstablishContext(irp, scope); + log_debug("leaving"); + return 0; +} + +/*****************************************************************************/ +int APP_CC +scard_send_irp_list_readers(struct trans *con) +{ + IRP *irp; if ((irp = devredir_irp_new()) == NULL) { log_error("system out of memory"); - return; + return 1; } + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_ListReaders_Return; + irp->user_data = con; + scard_send_ListReaders(irp, 1); + log_debug("leaving"); + return 0; +} + +/****************************************************************************** +** non static functions ** +******************************************************************************/ - irp->scard_index = scard_add_new_device(device_id); - if (irp->scard_index < 0) +void APP_CC +scard_device_announce(tui32 device_id) +{ + log_debug("entered: device_id=%d", device_id); + if (g_smartcards_inited) { - log_debug("NOT adding smartcard with DeviceId=%d to list", device_id); - devredir_irp_delete(irp); return; } - - log_debug("added smartcard with DeviceId=%d to list", device_id); - - irp->CompletionId = g_completion_id++; - irp->DeviceId = device_id; - irp->callback = scard_handle_EstablishContext_Return; - - scard_send_EstablishContext(irp); - log_debug("leaving"); + g_memset(&smartcards, 0, sizeof(smartcards)); + g_smartcards_inited = 1; + g_device_id = device_id; + g_scard_index = scard_add_new_device(device_id); + if (g_scard_index < 0) + { + log_debug("scard_add_new_device failed with DeviceId=%d", g_device_id); + } + else + { + log_debug("added smartcard with DeviceId=%d to list", g_device_id); + } + //scard_send_establish_context(); } /****************************************************************************** @@ -239,13 +270,19 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, g_hexdump(sc->Context, sc->Context_len); } - irp->callback = scard_handle_ListReaders_Return; - scard_send_ListReaders(irp, 1); + //irp->callback = scard_handle_ListReaders_Return; + //scard_send_ListReaders(irp, 1); + + scard_function_establish_context_return((struct trans *) (irp->user_data), + ((int*)(sc->Context))[0]); + + devredir_irp_delete(irp); /* LK_TODO need to delete IRP */ log_debug("leaving"); } +/******************************************************************************/ void APP_CC scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, @@ -272,9 +309,12 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + scard_function_get_readers_state_return((struct trans *) (irp->user_data), + s, len); + /* LK_TODO */ - log_debug("dumping %d bytes", len); - g_hexdump(s->p, len); + //log_debug("dumping %d bytes", len); + //g_hexdump(s->p, len); log_debug("leaving"); } @@ -288,17 +328,20 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, *****************************************************************************/ static void APP_CC -scard_send_EstablishContext(IRP *irp) +scard_send_EstablishContext(IRP *irp, int scope) { struct stream *s; int bytes; if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_ESTABLISH_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } xstream_wr_u32_le(s, 0x08); /* len */ xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, SCARD_SCOPE_SYSTEM); /* Ioctl specific data */ + xstream_wr_u32_le(s, scope); /* Ioctl specific data */ xstream_wr_u32_le(s, 0); /* don't know what this is, */ /* but Win7 is sending it */ /* get stream len */ @@ -476,7 +519,10 @@ scard_add_new_device(tui32 device_id) SMARTCARD *sc; if ((index = scard_get_free_slot()) < 0) + { + log_error("scard_get_free_slot failed"); return -1; + } if ((sc = g_malloc(sizeof(SMARTCARD), 1)) == NULL) { diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index a85b9f5f..ecf79a04 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -26,6 +26,7 @@ #include "parse.h" #include "irp.h" +#include "trans.h" /* forward declarations */ void scard_device_announce(tui32 device_id); @@ -48,4 +49,9 @@ scard_init(void); int APP_CC scard_deinit(void); +int APP_CC +scard_send_irp_establish_context(struct trans *con, int scope); +int APP_CC +scard_send_irp_list_readers(struct trans *con); + #endif /* end #ifndef _SMARTCARD_C */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 909c7df3..3eec4793 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -20,11 +20,11 @@ /* * smartcard redirection support, PCSC daemon standin * this will act like pcsc daemon + * pcsc lib and daemon write struct on unix domain socket for communication */ #define PCSC_STANDIN 1 -#include "chansrv.h" #include "os_calls.h" #include "smartcard.h" #include "log.h" @@ -34,48 +34,37 @@ #if PCSC_STANDIN -/* module based logging */ -#define LOG_ERROR 0 -#define LOG_INFO 1 -#define LOG_DEBUG 2 -#define LOG_LEVEL LOG_ERROR - -#define log_error(_params...) \ -{ \ - g_write("[%10.10u]: PCSC %s: %d : ERROR: ", \ - g_time3(), __func__, __LINE__); \ - g_writeln (_params); \ -} - -#define log_always(_params...) \ -{ \ - g_write("[%10.10u]: PCSC %s: %d : ALWAYS: ", \ - g_time3(), __func__, __LINE__); \ - g_writeln (_params); \ -} - -#define log_info(_params...) \ -{ \ - if (LOG_INFO <= LOG_LEVEL) \ - { \ - g_write("[%10.10u]: PCSC %s: %d : ", \ - g_time3(), __func__, __LINE__); \ - g_writeln (_params); \ - } \ -} +#define LLOG_LEVEL 11 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("chansrv:smartcard [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + +/* using pcsc-lite-1.7.4 */ + +struct establish_struct +{ + tui32 dwScope; + tui32 hContext; + tui32 rv; +}; -#define log_debug(_params...) \ -{ \ - if (LOG_DEBUG <= LOG_LEVEL) \ - { \ - g_write("[%10.10u]: PCSC %s: %d : ", \ - g_time3(), __func__, __LINE__); \ - g_writeln (_params); \ - } \ -} +struct release_struct +{ + tui32 hContext; + tui32 rv; +}; -#define PCSCLITE_MSG_KEY_LEN 16 -#define PCSCLITE_MAX_MESSAGE_SIZE 2048 +/** Major version of the current message protocol */ +#define PROTOCOL_VERSION_MAJOR 4 +/** Minor version of the current message protocol */ +#define PROTOCOL_VERSION_MINOR 2 struct version_struct { @@ -83,25 +72,42 @@ struct version_struct tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */ tui32 rv; }; -typedef struct version_struct version_struct; -struct rxSharedSegment +#define SCARD_S_SUCCESS 0x00000000 /**< No error was encountered. */ +#define SCARD_F_INTERNAL_ERROR 0x80100001 /**< An internal consistency + * check failed. */ +#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout + * value has expired. */ + +#define MAX_READERNAME 100 +#define MAX_ATR_SIZE 33 + +struct pubReaderStatesList { - tui32 mtype; /** one of the \c pcsc_adm_commands */ - tui32 user_id; - tui32 group_id; - tui32 command; /** one of the \c pcsc_msg_commands */ - tui64 date; - tui8 key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */ - union _u - { - tui8 data[PCSCLITE_MAX_MESSAGE_SIZE]; - struct version_struct veStr; - } u; + char readerName[MAX_READERNAME]; /**< reader name */ + tui32 eventCounter; /**< number of card events */ + tui32 readerState; /**< SCARD_* bit field */ + tsi32 readerSharing; /**< PCSCLITE_SHARING_* sharing status */ + tui8 cardAtr[MAX_ATR_SIZE]; /**< ATR */ + tui32 cardAtrLength; /**< ATR length */ + tui32 cardProtocol; /**< SCARD_PROTOCOL_* value */ +}; + +#define PCSCLITE_MAX_READERS_CONTEXTS 16 + +static struct pubReaderStatesList + g_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; + +struct wait_reader_state_change +{ + tui32 timeOut; /**< timeout in ms */ + tui32 rv; }; -typedef struct rxSharedSegment sharedSegmentMsg, *psharedSegmentMsg; -#define RXSHAREDSEGMENT_BYTES 2088 +#define XRDP_PCSC_STATE_NONE 0 +#define XRDP_PCSC_STATE_GOT_RSC 1 + +static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; extern int g_display_num; /* in chansrv.c */ @@ -116,15 +122,15 @@ static struct pcsc_client *g_tail = 0; static struct trans *g_lis = 0; static struct trans *g_con = 0; /* todo, remove this */ - -static char g_pcsc_directory[256] = ""; +static char g_pcsclite_ipc_dir[256] = ""; +static int g_pub_file_fd = 0; +static char g_pub_file_name[256] = ""; /*****************************************************************************/ int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) { - log_debug("scard_pcsc_get_wait_objs"); - + LLOGLN(0, ("scard_pcsc_get_wait_objs")); if (g_lis != 0) { trans_get_wait_objs(g_lis, objs, count); @@ -140,8 +146,7 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC scard_pcsc_check_wait_objs(void) { - log_debug("scard_pcsc_check_wait_objs"); - + LLOGLN(0, ("scard_pcsc_check_wait_objs")); if (g_lis != 0) { trans_check_wait_objs(g_lis); @@ -156,34 +161,218 @@ scard_pcsc_check_wait_objs(void) /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_version(psharedSegmentMsg msg) +scard_process_establish_context(struct trans *con, struct stream *in_s) { + struct establish_struct in_es; + + LLOGLN(0, ("scard_process_establish_context:")); + in_uint8a(in_s, &in_es, sizeof(in_es)); + LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", + in_es.dwScope)); + scard_send_irp_establish_context(con, in_es.dwScope); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_msg(struct stream *s) +scard_function_establish_context_return(struct trans *con, int context) { - sharedSegmentMsg msg; - int rv; + struct establish_struct out_es; + struct stream *out_s; + + LLOGLN(0, ("scard_function_establish_context_return: context %d", + context)); + out_es.dwScope = 0; + out_es.hContext = context; + out_es.rv = SCARD_S_SUCCESS; + out_s = trans_get_out_s(con, 8192); + out_uint8a(out_s, &out_es, sizeof(out_es)); + s_mark_end(out_s); + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_proess_release_context(struct stream *in_s) +{ + struct release_struct in_rs; + struct release_struct out_rs; + struct stream *out_s; + + LLOGLN(0, ("scard_proess_release_context:")); + in_uint8a(in_s, &in_rs, sizeof(in_rs)); + LLOGLN(0, ("scard_proess_release_context: hContext %d", in_rs.hContext)); + out_rs.hContext = in_rs.hContext; + out_rs.rv = SCARD_S_SUCCESS; + out_s = trans_get_out_s(g_con, 8192); + out_uint8a(out_s, &out_rs, sizeof(out_rs)); + s_mark_end(out_s); + return trans_force_write(g_con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_version(struct trans *con, struct stream *in_s) +{ + struct stream *out_s; + struct version_struct in_version; + struct version_struct out_version; + + LLOGLN(0, ("scard_process_version:")); + in_uint8a(in_s, &in_version, sizeof(in_version)); + /* todo: check if version is compatible */ + LLOGLN(0, ("scard_process_version: version major %d minor %d", + in_version.major, in_version.minor)); + out_s = trans_get_out_s(con, 8192); + out_version.major = PROTOCOL_VERSION_MAJOR; + out_version.minor = PROTOCOL_VERSION_MINOR; + out_version.rv = SCARD_S_SUCCESS; + out_uint8a(out_s, &out_version, sizeof(out_version)); + s_mark_end(out_s); + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_get_readers_state(struct stream *in_s) +{ + LLOGLN(0, ("scard_process_get_readers_state:")); + scard_send_irp_list_readers(g_con); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_function_get_readers_state_return(struct trans *con, + struct stream *in_s, + int len) +{ + struct stream *out_s; + + g_hexdump(in_s->p, len); + out_s = trans_get_out_s(con, 8192); + out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); + s_mark_end(out_s); + return trans_force_write(con); +} - g_memset(&msg, 0, sizeof(msg)); - in_uint32_le(s, msg.mtype); - in_uint32_le(s, msg.user_id); - in_uint32_le(s, msg.group_id); - in_uint32_le(s, msg.command); - in_uint64_le(s, msg.date); +/*****************************************************************************/ +/* callback from chansrv when timeout occurs */ +void DEFAULT_CC +scard_read_state_chage_timeout(void* data) +{ + struct trans *con; + struct stream *out_s; + struct wait_reader_state_change out_rsc; + + LLOGLN(0, ("scard_read_state_chage_timeout:")); + con = (struct trans *) data; + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) + { + out_s = trans_get_out_s(con, 8192); + out_rsc.timeOut = 0; + out_rsc.rv = SCARD_S_SUCCESS; + out_uint8a(out_s, &out_rsc, sizeof(out_rsc)); + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC; + s_mark_end(out_s); + trans_force_write(con); + } + else + { + LLOGLN(0, ("scard_read_state_chage_timeout: already stopped")); + } +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_read_state_change(struct trans *con, struct stream *in_s) +{ + struct wait_reader_state_change in_rsc; + struct stream *out_s; + + LLOGLN(0, ("scard_process_read_state_change:")); + in_uint8a(in_s, &in_rsc, sizeof(in_rsc)); + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RSC; + LLOGLN(0, ("scard_process_read_state_change: timeout %d rv %d", + in_rsc.timeOut, in_rsc.rv)); + add_timeout(in_rsc.timeOut, scard_read_state_chage_timeout, con); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_stop_read_state_change(struct stream *in_s) +{ + struct wait_reader_state_change in_rsc; + struct wait_reader_state_change out_rsc; + struct stream *out_s; + + LLOGLN(0, ("scard_process_stop_read_state_change:")); + in_uint8a(in_s, &in_rsc, sizeof(in_rsc)); + LLOGLN(0, ("scard_process_stop_read_state_change: timeout %d rv %d", + in_rsc.timeOut, in_rsc.rv)); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) + { + out_s = trans_get_out_s(g_con, 8192); + out_rsc.timeOut = in_rsc.timeOut; + out_rsc.rv = SCARD_S_SUCCESS; + out_uint8a(out_s, &out_rsc, sizeof(out_rsc)); + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC; + s_mark_end(out_s); + return trans_force_write(g_con); + } + else + { + LLOGLN(0, ("scard_process_stop_read_state_change: already stopped")); + } + return 0; +} - log_debug("scard_process_msg: mtype 0x%2.2x command 0x%2.2x", - msg.mtype, msg.command); +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_msg(struct trans *con, struct stream *in_s, int command) +{ + int rv; + LLOGLN(0, ("scard_process_msg: command 0x%4.4x", command)); rv = 0; - switch (msg.mtype) + switch (command) { - case 0xF8: /* CMD_VERSION */ - rv = scard_process_version(&msg); + case 0x01: /* SCARD_ESTABLISH_CONTEXT */ + LLOGLN(0, ("scard_process_msg: SCARD_ESTABLISH_CONTEXT")); + rv = scard_process_establish_context(con, in_s); + break; + case 0x02: /* SCARD_RELEASE_CONTEXT */ + LLOGLN(0, ("scard_process_msg: SCARD_RELEASE_CONTEXT")); + rv = scard_proess_release_context(in_s); + break; + case 0x11: /* CMD_VERSION */ + LLOGLN(0, ("scard_process_msg: CMD_VERSION")); + rv = scard_process_version(con, in_s); + break; + case 0x12: /* CMD_GET_READERS_STATE */ + LLOGLN(0, ("scard_process_msg: CMD_GET_READERS_STATE")); + rv = scard_process_get_readers_state(in_s); + break; + case 0x13: /* CMD_WAIT_READER_STATE_CHANGE */ + LLOGLN(0, ("scard_process_msg: CMD_WAIT_READER_STATE_CHANGE")); + rv = scard_process_read_state_change(con, in_s); + break; + case 0x14: /* CMD_STOP_WAITING_READER_STATE_CHANGE */ + LLOGLN(0, ("scard_process_msg: CMD_STOP_WAITING_READER_STATE_CHANGE")); + rv = scard_process_stop_read_state_change(in_s); + break; + default: + LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command)); + rv = 1; break; } return rv; @@ -197,22 +386,27 @@ my_pcsc_trans_data_in(struct trans *trans) struct stream *s; int id; int size; + int command; int error; - log_debug("my_pcsc_trans_data_in:"); - + LLOGLN(0, ("my_pcsc_trans_data_in:")); if (trans == 0) { return 0; } - if (trans != g_con) { return 1; } s = trans_get_in_s(trans); - g_hexdump(s->p, 64); - error = scard_process_msg(s); + in_uint32_le(s, size); + in_uint32_le(s, command); + LLOGLN(0, ("my_pcsc_trans_data_in: size %d command %d", size, command)); + error = trans_force_read(trans, size); + if (error == 0) + { + error = scard_process_msg(g_con, s, command); + } return error; } @@ -221,7 +415,7 @@ my_pcsc_trans_data_in(struct trans *trans) int DEFAULT_CC my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) { - log_debug("my_pcsc_trans_conn_in:"); + LLOGLN(0, ("my_pcsc_trans_conn_in:")); if (trans == 0) { @@ -240,11 +434,13 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) g_con = new_trans; g_con->trans_data_in = my_pcsc_trans_data_in; +#if 1 + g_con->header_size = 8; +#else g_con->header_size = RXSHAREDSEGMENT_BYTES; - - log_debug("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d", - sizeof(sharedSegmentMsg)); - + LLOGLN(0, ("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d", + sizeof(sharedSegmentMsg))); +#endif return 0; } @@ -253,36 +449,51 @@ int APP_CC scard_pcsc_init(void) { char port[256]; + char *home; + int disp; int error; + int index; - log_debug("scard_pcsc_init:"); - + LLOGLN(0, ("scard_pcsc_init:")); + g_memset(g_reader_states, 0, sizeof(g_reader_states)); if (g_lis == 0) { - g_lis = trans_create(TRANS_MODE_UNIX, 8192, 8192); - g_lis->is_term = g_is_term; - g_snprintf(g_pcsc_directory, 255, "/tmp/.xrdp/pcsc%d", g_display_num); - if (g_directory_exist(g_pcsc_directory)) + g_lis = trans_create(2, 8192, 8192); + + //g_snprintf(g_pcsclite_ipc_dir, 255, "/tmp/.xrdp/pcsc%d", g_display_num); + 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)) { - if (g_remove_dir(g_pcsc_directory) != 0) + if (g_remove_dir(g_pcsclite_ipc_dir) != 0) { - log_error("scard_pcsc_init: g_remove_dir failed"); + LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed")); } } - if (g_create_dir(g_pcsc_directory) != 0) + if (!g_create_dir(g_pcsclite_ipc_dir)) { - log_error("scard_pcsc_init: g_create_dir failed"); + LLOGLN(0, ("scard_pcsc_init: g_create_dir failed")); } - g_chmod_hex(g_pcsc_directory, 0x1777); - g_snprintf(port, 255, "%s/pcscd.comm", g_pcsc_directory); + g_chmod_hex(g_pcsclite_ipc_dir, 0x1777); + g_snprintf(port, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir); g_lis->trans_conn_in = my_pcsc_trans_conn_in; error = trans_listen(g_lis, port); if (error != 0) { - log_error("scard_pcsc_init: trans_listen failed for port %s", - port); + LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s", + port)); return 1; } + g_snprintf(g_pub_file_name, 255, "%s/pcscd.pub", g_pcsclite_ipc_dir); + g_pub_file_fd = g_file_open(g_pub_file_name); + index = 0; + while (index < 65537) + { + g_file_write(g_pub_file_fd, "", 1); + index++; + } } return 0; } @@ -291,17 +502,22 @@ scard_pcsc_init(void) int APP_CC scard_pcsc_deinit(void) { - log_debug("scard_pcsc_deinit:"); - + LLOGLN(0, ("scard_pcsc_deinit:")); if (g_lis != 0) { trans_delete(g_lis); g_lis = 0; - if (g_remove_dir(g_pcsc_directory) != 0) + + g_file_close(g_pub_file_fd); + g_pub_file_fd = 0; + g_file_delete(g_pub_file_name); + g_pub_file_name[0] = 0; + + if (g_remove_dir(g_pcsclite_ipc_dir) != 0) { - log_error("scard_pcsc_deinit: g_remove_dir failed"); + LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed")); } - g_pcsc_directory[0] = 0; + g_pcsclite_ipc_dir[0] = 0; } return 0; } diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index a97a70d3..282128f9 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -33,4 +33,10 @@ scard_pcsc_init(void); int APP_CC scard_pcsc_deinit(void); +int APP_CC +scard_function_establish_context_return(struct trans *con, int context); +int APP_CC +scard_function_get_readers_state_return(struct trans *con, struct stream *in_s, + int len); + #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 2d112bac8f4359a513cc603e5f58fc625700a6c6 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 9 Sep 2013 12:30:58 -0700 Subject: [PATCH 03/32] chansrv: work on smart card --- sesman/chansrv/devredir.c | 4 +- sesman/chansrv/smartcard.c | 56 ++++++++++---------- sesman/chansrv/smartcard_pcsc.c | 90 ++++++++++++++++++++++++++++++--- sesman/chansrv/smartcard_pcsc.h | 5 +- 4 files changed, 116 insertions(+), 39 deletions(-) diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 22debb11..05fd3302 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -68,7 +68,7 @@ #define log_info(_params...) \ { \ - if (LOG_INFO <= LOG_LEVEL) \ + if (LOG_INFO <= LOG_LEVEL) \ { \ g_write("[%10.10u]: DEV_REDIR %s: %d : ", \ g_time3(), __func__, __LINE__); \ @@ -78,7 +78,7 @@ #define log_debug(_params...) \ { \ - if (LOG_DEBUG <= LOG_LEVEL) \ + if (LOG_DEBUG <= LOG_LEVEL) \ { \ g_write("[%10.10u]: DEV_REDIR %s: %d : ", \ g_time3(), __func__, __LINE__); \ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index d422716c..8e3761e6 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -309,8 +309,8 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - scard_function_get_readers_state_return((struct trans *) (irp->user_data), - s, len); + scard_function_list_readers_return((struct trans *) (irp->user_data), + s, len); /* LK_TODO */ //log_debug("dumping %d bytes", len); @@ -389,22 +389,22 @@ scard_send_ListReaders(IRP *irp, int wide) xstream_copyin(s, sc->Context, sc->Context_len); xstream_wr_u32_le(s, 36); /* length of mszGroups */ - xstream_wr_u16_le(s, 0x0053); - xstream_wr_u16_le(s, 0x0043); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0024); - xstream_wr_u16_le(s, 0x0041); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x0052); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0073); + xstream_wr_u16_le(s, 0x0053); /* S */ + xstream_wr_u16_le(s, 0x0043); /* C */ + xstream_wr_u16_le(s, 0x0061); /* a */ + xstream_wr_u16_le(s, 0x0072); /* r */ + xstream_wr_u16_le(s, 0x0064); /* d */ + xstream_wr_u16_le(s, 0x0024); /* $ */ + xstream_wr_u16_le(s, 0x0041); /* A */ + xstream_wr_u16_le(s, 0x006c); /* l */ + xstream_wr_u16_le(s, 0x006c); /* l */ + xstream_wr_u16_le(s, 0x0052); /* R */ + xstream_wr_u16_le(s, 0x0065); /* e */ + xstream_wr_u16_le(s, 0x0061); /* a */ + xstream_wr_u16_le(s, 0x0064); /* d */ + xstream_wr_u16_le(s, 0x0065); /* e */ + xstream_wr_u16_le(s, 0x0072); /* r */ + xstream_wr_u16_le(s, 0x0073); /* s */ xstream_wr_u32_le(s, 0x00); @@ -419,16 +419,16 @@ scard_send_ListReaders(IRP *irp, int wide) xstream_free(s); /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... - 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... - 0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... - 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................ - 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. - 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. - 0070 72 00 73 00 00 00 00 00 r.s..... - scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c + scard_device_control: dumping 120 bytes of data + 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... + 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... + 0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... + 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................ + 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. + 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. + 0070 72 00 73 00 00 00 00 00 r.s..... + scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c */ /* diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 3eec4793..72249f32 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -195,15 +195,15 @@ scard_function_establish_context_return(struct trans *con, int context) /*****************************************************************************/ /* returns error */ int APP_CC -scard_proess_release_context(struct stream *in_s) +scard_process_release_context(struct stream *in_s) { struct release_struct in_rs; struct release_struct out_rs; struct stream *out_s; - LLOGLN(0, ("scard_proess_release_context:")); + LLOGLN(0, ("scard_process_release_context:")); in_uint8a(in_s, &in_rs, sizeof(in_rs)); - LLOGLN(0, ("scard_proess_release_context: hContext %d", in_rs.hContext)); + LLOGLN(0, ("scard_process_release_context: hContext %d", in_rs.hContext)); out_rs.hContext = in_rs.hContext; out_rs.rv = SCARD_S_SUCCESS; out_s = trans_get_out_s(g_con, 8192); @@ -248,13 +248,32 @@ scard_process_get_readers_state(struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_get_readers_state_return(struct trans *con, - struct stream *in_s, - int len) +scard_function_list_readers_return(struct trans *con, + struct stream *in_s, + int len) { struct stream *out_s; g_hexdump(in_s->p, len); + + g_strcpy(g_reader_states[0].readerName, "ACS AET65 00 00"); + g_reader_states[0].readerState = 0x14; + g_reader_states[0].cardProtocol = 3; + + g_reader_states[0].cardAtrLength = 10; + g_reader_states[0].cardAtr[0] = 0x3B; + g_reader_states[0].cardAtr[1] = 0x95; + g_reader_states[0].cardAtr[2] = 0x95; + g_reader_states[0].cardAtr[3] = 0x40; + g_reader_states[0].cardAtr[4] = 0xFF; + g_reader_states[0].cardAtr[5] = 0xD0; + g_reader_states[0].cardAtr[6] = 0x00; + g_reader_states[0].cardAtr[7] = 0x54; + g_reader_states[0].cardAtr[8] = 0x01; + g_reader_states[0].cardAtr[9] = 0x32; + + //g_reader_states[0].eventCounter++; + out_s = trans_get_out_s(con, 8192); out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); s_mark_end(out_s); @@ -352,8 +371,65 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x02: /* SCARD_RELEASE_CONTEXT */ LLOGLN(0, ("scard_process_msg: SCARD_RELEASE_CONTEXT")); - rv = scard_proess_release_context(in_s); + rv = scard_process_release_context(in_s); + break; + + case 0x03: /* SCARD_LIST_READERS */ + LLOGLN(0, ("scard_process_msg: SCARD_LIST_READERS")); + break; + + case 0x04: /* SCARD_CONNECT */ + LLOGLN(0, ("scard_process_msg: SCARD_CONNECT")); + break; + + case 0x05: /* SCARD_RECONNECT */ + LLOGLN(0, ("scard_process_msg: SCARD_RECONNECT")); + break; + + case 0x06: /* SCARD_DISCONNECT */ + LLOGLN(0, ("scard_process_msg: SCARD_DISCONNECT")); + break; + + case 0x07: /* SCARD_BEGIN_TRANSACTION */ + LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION")); + break; + + case 0x08: /* SCARD_END_TRANSACTION */ + LLOGLN(0, ("scard_process_msg: SCARD_END_TRANSACTION")); + break; + + case 0x09: /* SCARD_TRANSMIT */ + LLOGLN(0, ("scard_process_msg: SCARD_TRANSMIT")); break; + + case 0x0A: /* SCARD_CONTROL */ + LLOGLN(0, ("scard_process_msg: SCARD_CONTROL")); + break; + + case 0x0B: /* SCARD_STATUS */ + LLOGLN(0, ("scard_process_msg: SCARD_STATUS")); + break; + + case 0x0C: /* SCARD_GET_STATUS_CHANGE */ + LLOGLN(0, ("scard_process_msg: SCARD_GET_STATUS_CHANGE")); + break; + + case 0x0D: /* SCARD_CANCEL */ + LLOGLN(0, ("scard_process_msg: SCARD_CANCEL")); + break; + + case 0x0E: /* SCARD_CANCEL_TRANSACTION */ + LLOGLN(0, ("scard_process_msg: SCARD_CANCEL_TRANSACTION")); + break; + + case 0x0F: /* SCARD_GET_ATTRIB */ + LLOGLN(0, ("scard_process_msg: SCARD_GET_ATTRIB")); + break; + + case 0x10: /* SCARD_SET_ATTRIB */ + LLOGLN(0, ("scard_process_msg: SCARD_SET_ATTRIB")); + break; + case 0x11: /* CMD_VERSION */ LLOGLN(0, ("scard_process_msg: CMD_VERSION")); rv = scard_process_version(con, in_s); diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 282128f9..bac8638c 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -36,7 +36,8 @@ scard_pcsc_deinit(void); int APP_CC scard_function_establish_context_return(struct trans *con, int context); int APP_CC -scard_function_get_readers_state_return(struct trans *con, struct stream *in_s, - int len); +scard_function_list_readers_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 68224550da3a7008f6c391155a44fbc2b17ecf79 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 9 Sep 2013 15:20:01 -0700 Subject: [PATCH 04/32] common: update a copyright year --- common/arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/arch.h b/common/arch.h index b8780926..6a29b0a9 100644 --- a/common/arch.h +++ b/common/arch.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 3acea314392e78bdfbd2a9d32da03c98f35aad2a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 9 Sep 2013 15:20:49 -0700 Subject: [PATCH 05/32] common: added g_signal_segfault to header --- common/os_calls.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/os_calls.h b/common/os_calls.h index 2dbbe660..443a1840 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -125,6 +125,7 @@ int APP_CC g_get_errno(void); int APP_CC g_execvp(const char* p1, char* args[]); int APP_CC g_execlp3(const char* a1, const char* a2, const char* a3); void APP_CC g_signal_child_stop(void (*func)(int)); +void APP_CC g_signal_segfault(void (*func)(int)); void APP_CC g_signal_hang_up(void (*func)(int)); void APP_CC g_signal_user_interrupt(void (*func)(int)); void APP_CC g_signal_kill(void (*func)(int)); From 4e58a5a3c022f90ce9219e126893b721fee2b90a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 9 Sep 2013 15:43:58 -0700 Subject: [PATCH 06/32] X11rdp: work on off screen bitmap, size limit, use ack for screen delayed drawing --- xorg/X11R7.6/rdp/rdp.h | 2 + xorg/X11R7.6/rdp/rdpCopyArea.c | 10 +- xorg/X11R7.6/rdp/rdpdraw.c | 22 +++-- xorg/X11R7.6/rdp/rdpup.c | 170 +++++++++++++++++++++++++++------ xup/xup.c | 8 +- 5 files changed, 174 insertions(+), 38 deletions(-) diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h index c9afd285..91f50c26 100644 --- a/xorg/X11R7.6/rdp/rdp.h +++ b/xorg/X11R7.6/rdp/rdp.h @@ -471,6 +471,8 @@ int rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv); int rdpup_remove_os_bitmap(int rdpindex); +int +rdpup_update_os_use(int rdpindex); void rdpup_get_screen_image_rect(struct image_data* id); void diff --git a/xorg/X11R7.6/rdp/rdpCopyArea.c b/xorg/X11R7.6/rdp/rdpCopyArea.c index 169ec347..254590ee 100644 --- a/xorg/X11R7.6/rdp/rdpCopyArea.c +++ b/xorg/X11R7.6/rdp/rdpCopyArea.c @@ -429,6 +429,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, pSrcPixmap = (PixmapPtr)pSrc; pSrcPriv = GETPIXPRIV(pSrcPixmap); + LLOGLN(10, ("rdpCopyArea: 3 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch)); + if (xrdp_is_os(pSrcPixmap, pSrcPriv)) { if (pDst->type == DRAWABLE_WINDOW) @@ -468,7 +470,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, } else { - LLOGLN(10, ("rdpCopyArea: 2")); + LLOGLN(10, ("rdpCopyArea: 2 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch)); } } @@ -495,7 +497,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, LLOGLN(10, ("rdpCopyArea: getting dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; - dirty_type = RDI_IMGLL; + dirty_type = RDI_IMGLY; } else { @@ -525,7 +527,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, LLOGLN(10, ("rdpCopyArea: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; - dirty_type = RDI_IMGLL; + dirty_type = RDI_IMGLY; } else { @@ -541,6 +543,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, return rv; } + LLOGLN(10, ("rdpCopyArea: post_process")); + RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c index 6b6c9581..f9dff80a 100644 --- a/xorg/X11R7.6/rdp/rdpdraw.c +++ b/xorg/X11R7.6/rdp/rdpdraw.c @@ -739,13 +739,12 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, width, org_width, depth, g_rdpScreen.depth)); pScreen->CreatePixmap = g_rdpScreen.CreatePixmap; rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint); + pScreen->CreatePixmap = rdpCreatePixmap; priv = GETPIXPRIV(rv); priv->rdpindex = -1; - priv->con_number = g_con_number; priv->kind_width = width; pScreen->ModifyPixmapHeader(rv, org_width, 0, 0, 0, 0, 0); - pScreen->CreatePixmap = rdpCreatePixmap; - if (org_width == 0 && height == 0) + if ((org_width == 0) && (height == 0)) { priv->is_scratch = 1; } @@ -793,14 +792,19 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv) int height; struct image_data id; - if (!XRDP_IS_OS(priv)) + if (XRDP_IS_OS(priv)) + { + /* update time stamp */ + rdpup_update_os_use(priv->rdpindex); + } + else { width = pix->drawable.width; height = pix->drawable.height; if ((pix->usage_hint == 0) && (pix->drawable.depth >= g_rdpScreen.depth) && (width > 0) && (height > 0) && (priv->kind_width > 0) && - (priv->is_scratch == 0)) + (priv->is_scratch == 0) && (priv->use_count >= 0)) { LLOGLN(10, ("%d %d", priv->kind_width, pix->drawable.width)); priv->rdpindex = rdpup_add_os_bitmap(pix, priv); @@ -815,8 +819,12 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv) box.y2 = height; if (g_do_dirty_os) { + LLOGLN(10, ("xrdp_is_os: priv->con_number %d g_con_number %d", + priv->con_number, g_con_number)); + LLOGLN(10, ("xrdp_is_os: priv->use_count %d", priv->use_count)); if (priv->con_number != g_con_number) { + LLOGLN(10, ("xrdp_is_os: queuing invalidating all")); draw_item_remove_all(priv); RegionInit(®1, &box, 0); draw_item_add_img_region(priv, ®1, GXcopy, RDI_IMGLL, 16); @@ -1350,7 +1358,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, rdpPixmapRec *pDirtyPriv; struct image_data id; - LLOGLN(10, ("rdpComposite:")); + LLOGLN(10, ("rdpComposite: op %d width %d height %d", op, width, height)); ps = GetPictureScreen(g_pScreen); ps->Composite = g_rdpScreen.Composite; ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, @@ -1424,6 +1432,8 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, return; } + LLOGLN(10, ("rdpComposite: post_process")); + if (pDst->pCompositeClip != 0) { box.x1 = p->x + xDst; diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c index b8a763a7..0277fc20 100644 --- a/xorg/X11R7.6/rdp/rdpup.c +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -39,6 +39,9 @@ static char *g_shmemptr = 0; static int g_shmem_lineBytes = 0; static RegionPtr g_shm_reg = 0; +static int g_rect_id_ack = 0; +static int g_rect_id = 0; + static int g_listen_sck = 0; static int g_sck = 0; static int g_sck_closed = 0; @@ -82,9 +85,11 @@ struct rdpup_os_bitmap int stamp; }; +#define MAX_OS_BYTES (16 * 1024 * 1024) static struct rdpup_os_bitmap *g_os_bitmaps = 0; static int g_max_os_bitmaps = 0; static int g_os_bitmap_stamp = 0; +static int g_os_bitmap_alloc_size = 0; static int g_pixmap_byte_total = 0; static int g_pixmap_num_used = 0; @@ -217,6 +222,7 @@ rdpup_disconnect(void) } } } + g_os_bitmap_alloc_size = 0; g_max_os_bitmaps = 0; g_free(g_os_bitmaps); @@ -233,6 +239,7 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) int rv; int oldest; int oldest_index; + int this_bytes; if (!g_connected) { @@ -244,6 +251,17 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) return -1; } + this_bytes = pixmap->devKind * pixmap->drawable.height; + if (this_bytes > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpup_add_os_bitmap: error, too big this_bytes %d " + "width %d height %d", this_bytes, + pixmap->drawable.height, pixmap->drawable.height)); + return -1; + } + + oldest = 0x7fffffff; + oldest_index = -1; rv = -1; index = 0; @@ -260,42 +278,77 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) rv = index; break; } - + else + { + if (g_os_bitmaps[index].stamp < oldest) + { + oldest = g_os_bitmaps[index].stamp; + oldest_index = index; + } + } index++; } if (rv == -1) { + if (oldest_index == -1) + { + LLOGLN(0, ("rdpup_add_os_bitmap: error")); + } + else + { + rdpup_remove_os_bitmap(oldest_index); + g_os_bitmaps[index].used = 1; + g_os_bitmaps[index].pixmap = pixmap; + g_os_bitmaps[index].priv = priv; + g_os_bitmaps[index].stamp = g_os_bitmap_stamp; + g_os_bitmap_stamp++; + g_pixmap_num_used++; + rv = oldest_index; + } + } + + if (rv < 0) + { + return rv; + } + + g_os_bitmap_alloc_size += this_bytes; + LLOGLN(10, ("rdpup_add_os_bitmap: this_bytes %d g_os_bitmap_alloc_size %d", + this_bytes, g_os_bitmap_alloc_size)); + while (g_os_bitmap_alloc_size > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpup_add_os_bitmap: must delete g_pixmap_num_used %d", + g_pixmap_num_used)); /* find oldest */ oldest = 0x7fffffff; - oldest_index = 0; + oldest_index = -1; index = 0; - while (index < g_max_os_bitmaps) { - if (g_os_bitmaps[index].stamp < oldest) + if (g_os_bitmaps[index].used && g_os_bitmaps[index].stamp < oldest) { oldest = g_os_bitmaps[index].stamp; oldest_index = index; } - index++; } - - LLOGLN(10, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index)); - /* evict old */ - g_os_bitmaps[oldest_index].priv->status = 0; - g_os_bitmaps[oldest_index].priv->con_number = 0; - /* set new */ - g_os_bitmaps[oldest_index].pixmap = pixmap; - g_os_bitmaps[oldest_index].priv = priv; - g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp; - g_os_bitmap_stamp++; - rv = oldest_index; + if (oldest_index == -1) + { + LLOGLN(0, ("rdpup_add_os_bitmap: error 1")); + break; + } + if (oldest_index == rv) + { + LLOGLN(0, ("rdpup_add_os_bitmap: error 2")); + break; + } + rdpup_remove_os_bitmap(oldest_index); + rdpup_delete_os_surface(oldest_index); } - LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv)); - LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used)); + LLOGLN(10, ("rdpup_add_os_bitmap: g_pixmap_num_used %d " + "g_os_bitmap_stamp 0x%8.8x", g_pixmap_num_used, g_os_bitmap_stamp)); return rv; } @@ -303,8 +356,12 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) int rdpup_remove_os_bitmap(int rdpindex) { + PixmapPtr pixmap; + rdpPixmapPtr priv; + int this_bytes; + LLOGLN(10, ("rdpup_remove_os_bitmap: index %d stamp %d", - rdpindex, g_os_bitmaps[rdpindex].stamp)); + rdpindex, g_os_bitmaps[rdpindex].stamp)); if (g_os_bitmaps == 0) { @@ -318,16 +375,66 @@ rdpup_remove_os_bitmap(int rdpindex) if (g_os_bitmaps[rdpindex].used) { + pixmap = g_os_bitmaps[rdpindex].pixmap; + priv = g_os_bitmaps[rdpindex].priv; + draw_item_remove_all(priv); + this_bytes = pixmap->devKind * pixmap->drawable.height; + g_os_bitmap_alloc_size -= this_bytes; + LLOGLN(10, ("rdpup_remove_os_bitmap: this_bytes %d " + "g_os_bitmap_alloc_size %d", this_bytes, + g_os_bitmap_alloc_size)); g_os_bitmaps[rdpindex].used = 0; g_os_bitmaps[rdpindex].pixmap = 0; g_os_bitmaps[rdpindex].priv = 0; g_pixmap_num_used--; + priv->status = 0; + priv->con_number = 0; + priv->use_count = 0; + } + else + { + LLOGLN(0, ("rdpup_remove_os_bitmap: error")); } LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used)); return 0; } +/*****************************************************************************/ +int +rdpup_update_os_use(int rdpindex) +{ + PixmapPtr pixmap; + rdpPixmapPtr priv; + int this_bytes; + + LLOGLN(10, ("rdpup_update_use: index %d stamp %d", + rdpindex, g_os_bitmaps[rdpindex].stamp)); + + if (g_os_bitmaps == 0) + { + return 1; + } + + if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps)) + { + return 1; + } + + if (g_os_bitmaps[rdpindex].used) + { + g_os_bitmaps[rdpindex].stamp = g_os_bitmap_stamp; + g_os_bitmap_stamp++; + } + else + { + LLOGLN(0, ("rdpup_update_use: error rdpindex %d", rdpindex)); + } + + return 0; +} + + /*****************************************************************************/ /* returns error */ static int @@ -433,7 +540,14 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) if (g_do_dirty_ons) { - rdpup_check_dirty_screen(&g_screenPriv); + if (g_rect_id == g_rect_id_ack) + { + rdpup_check_dirty_screen(&g_screenPriv); + } + else + { + LLOGLN(0, ("rdpDeferredUpdateCallback: skipping")); + } } else { @@ -909,11 +1023,13 @@ rdpup_process_msg(struct stream *s) { LLOGLN(10, ("rdpup_process_msg: got msg 105")); in_uint32_le(s, flags); + in_uint32_le(s, g_rect_id_ack); in_uint32_le(s, x); in_uint32_le(s, y); in_uint32_le(s, cx); in_uint32_le(s, cy); LLOGLN(10, (" %d %d %d %d", x, y, cx ,cy)); + LLOGLN(10, (" rect_id %d rect_id_ack %d", g_rect_id, g_rect_id_ack)); box.x1 = x; box.y1 = y; @@ -926,6 +1042,8 @@ rdpup_process_msg(struct stream *s) RegionUninit(®); } + + else { rdpLog("unknown message type in rdpup_process_msg %d\n", msg_type); @@ -1870,7 +1988,7 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h) d += id->shmem_lineBytes; ly += 1; } - size = 32; + size = 36; rdpup_pre_check(size); out_uint16_le(g_out_s, 60); out_uint16_le(g_out_s, size); @@ -1880,6 +1998,8 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h) out_uint16_le(g_out_s, w); out_uint16_le(g_out_s, h); out_uint32_le(g_out_s, 0); + g_rect_id++; + out_uint32_le(g_out_s, g_rect_id); out_uint32_le(g_out_s, id->shmem_id); out_uint32_le(g_out_s, id->shmem_offset); out_uint16_le(g_out_s, id->width); @@ -2128,10 +2248,6 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv) return 0; } - /* update use time / count */ - g_os_bitmaps[pDirtyPriv->rdpindex].stamp = g_os_bitmap_stamp; - g_os_bitmap_stamp++; - LLOGLN(10, ("rdpup_check_dirty: got dirty")); rdpup_switch_os_surface(pDirtyPriv->rdpindex); rdpup_get_pixmap_image_rect(pDirtyPixmap, &id); @@ -2293,8 +2409,8 @@ rdpup_check_dirty_screen(rdpPixmapRec *pDirtyPriv) for (index = 0; index < count; index++) { box = REGION_RECTS(di->reg)[index]; - LLOGLN(10, (" RDI_IMGLL %d %d %d %d", box.x1, box.y1, - box.x2, box.y2)); + LLOGLN(10, (" RDI_IMGLL x %d y %d w %d h %d", box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1)); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } diff --git a/xup/xup.c b/xup/xup.c index 475e64ed..da29f9f2 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -516,7 +516,8 @@ process_server_set_pointer_ex(struct mod *mod, struct stream *s) /******************************************************************************/ /* return error */ static int APP_CC -send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy) +send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy, + int frame_id) { int len; struct stream *s; @@ -526,6 +527,7 @@ send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy) s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 105); out_uint32_le(s, flags); + out_uint32_le(s, frame_id); out_uint32_le(s, x); out_uint32_le(s, y); out_uint32_le(s, cx); @@ -568,6 +570,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) int flags; int shmem_id; int shmem_offset; + int frame_id; char *bmpdata; char cur_data[32 * (32 * 3)]; char cur_mask[32 * (32 / 8)]; @@ -699,6 +702,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) in_uint16_le(s, cx); in_uint16_le(s, cy); in_uint32_le(s, flags); + in_uint32_le(s, frame_id); in_uint32_le(s, shmem_id); in_uint32_le(s, shmem_offset); in_uint16_le(s, width); @@ -728,7 +732,7 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) { rv = 1; } - send_paint_rect_ack(mod, flags, x, y, cx, cy); + send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); break; default: From 39ed446e1513c52f795d090fc9b1f173c0912d6a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:00:30 -0700 Subject: [PATCH 07/32] VUL: fix some possible buffer overruns --- common/parse.h | 3 ++ common/trans.c | 6 +++- libxrdp/xrdp_iso.c | 18 ++++++++++ libxrdp/xrdp_mcs.c | 89 +++++++++++++++++++++++++++++++++++++++++++++- libxrdp/xrdp_sec.c | 46 +++++++++++++++++++++--- 5 files changed, 156 insertions(+), 6 deletions(-) diff --git a/common/parse.h b/common/parse.h index 3ec37104..69a57ff8 100644 --- a/common/parse.h +++ b/common/parse.h @@ -55,6 +55,9 @@ struct stream /******************************************************************************/ #define s_check_rem(s, n) ((s)->p + (n) <= (s)->end) +/******************************************************************************/ +#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size) + /******************************************************************************/ #define s_check_end(s) ((s)->p == (s)->end) diff --git a/common/trans.c b/common/trans.c index 0b672168..8313b606 100644 --- a/common/trans.c +++ b/common/trans.c @@ -221,8 +221,12 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size) while (size > 0) { + /* make sure stream has room */ + if ((in_s->end + size) > (in_s->data + in_s->size)) + { + return 1; + } rcvd = g_tcp_recv(self->sck, in_s->end, size, 0); - if (rcvd == -1) { if (g_tcp_last_error_would_block(self->sck)) diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index d851c1bb..feba6814 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -72,20 +72,38 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code) in_uint8s(s, 1); in_uint16_be(s, len); + if (len < 4) + { + return 1; + } + if (xrdp_tcp_recv(self->tcp_layer, s, len - 4) != 0) { return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint8s(s, 1); in_uint8(s, *code); if (*code == ISO_PDU_DT) { + if (!s_check_rem(s, 1)) + { + return 1; + } in_uint8s(s, 1); } else { + if (!s_check_rem(s, 5)) + { + return 1; + } in_uint8s(s, 5); } diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 4bf3d025..cdcfeee6 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -132,6 +132,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) return 1; } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, opcode); appid = opcode >> 2; @@ -145,6 +150,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint16_be(s, userid); in_uint16_be(s, chanid); log_message(LOG_LEVEL_DEBUG,"MCS_CJRQ - channel join request received"); @@ -176,6 +186,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) return 1; } + if (!s_check_rem(s, 6)) + { + return 1; + } + in_uint8s(s, 2); in_uint16_be(s, *chan); in_uint8s(s, 1); @@ -183,6 +198,10 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) if (len & 0x80) { + if (!s_check_rem(s, 1)) + { + return 1; + } in_uint8s(s, 1); } @@ -202,10 +221,18 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, if (tag_val > 0xff) { + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_be(s, tag); } else { + if (!s_check_rem(s, 1)) + { + return 1; + } in_uint8(s, tag); } @@ -214,6 +241,11 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, return 1; } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, l); if (l & 0x80) @@ -223,6 +255,10 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, while (l > 0) { + if (!s_check_rem(s, 1)) + { + return 1; + } in_uint8(s, i); *len = (*len << 8) | i; l--; @@ -255,6 +291,11 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s) return 1; } + if (!s_check_rem(s, len)) + { + return 1; + } + in_uint8s(s, len); if (s_check(s)) @@ -276,7 +317,7 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) struct stream *s; make_stream(s); - init_stream(s, 8192); + init_stream(s, 16 * 1024); if (xrdp_iso_recv(self->iso_layer, s) != 0) { @@ -338,6 +379,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + if ((len <= 0) || (len > 16 * 1024)) + { + free_stream(s); + return 1; + } + /* make a copy of client mcs data */ init_stream(self->client_mcs_data, len); out_uint8a(self->client_mcs_data, s->p, len); @@ -372,6 +419,12 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) free_stream(s); return 1; } + + if (!s_check_rem(s, 1)) + { + free_stream(s); + return 1; + } in_uint8(s, opcode); @@ -381,11 +434,22 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) return 1; } + if (!s_check_rem(s, 4)) + { + free_stream(s); + return 1; + } + in_uint8s(s, 2); in_uint8s(s, 2); if (opcode & 2) { + if (!s_check_rem(s, 2)) + { + free_stream(s); + return 1; + } in_uint16_be(s, self->userid); } @@ -416,6 +480,12 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) return 1; } + if (!s_check_rem(s, 1)) + { + free_stream(s); + return 1; + } + in_uint8(s, opcode); if ((opcode >> 2) != MCS_AURQ) @@ -426,6 +496,11 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if (opcode & 2) { + if (!s_check_rem(s, 2)) + { + free_stream(s); + return 1; + } in_uint16_be(s, self->userid); } @@ -491,6 +566,12 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) return 1; } + if (!s_check_rem(s, 1)) + { + free_stream(s); + return 1; + } + in_uint8(s, opcode); if ((opcode >> 2) != MCS_CJRQ) @@ -499,6 +580,12 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) return 1; } + if (!s_check_rem(s, 4)) + { + free_stream(s); + return 1; + } + in_uint8s(s, 4); if (opcode & 2) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 726fcde4..c44ae420 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -836,16 +836,30 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) return 0; } + if (!s_check_rem(s, 4)) + { + return 1; + } + in_uint32_le(s, num_channels); + if (num_channels > 256) + { + return 1; + } + for (index = 0; index < num_channels; index++) { channel_item = (struct mcs_channel_item *) g_malloc(sizeof(struct mcs_channel_item), 1); + if (!s_check_rem(s, 12)) + { + return 1; + } in_uint8a(s, channel_item->name, 8); in_uint32_le(s, channel_item->flags); channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); - list_add_item(self->mcs_layer->channel_list, (long)channel_item); + list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item); DEBUG(("got channel flags %8.8x name %s", channel_item->flags, channel_item->name)); } @@ -864,10 +878,14 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) int tag = 0; int size = 0; - s = &self->client_mcs_data; + s = &(self->client_mcs_data); /* set p to beginning */ s->p = s->data; /* skip header */ + if (!s_check_rem(s, 23)) + { + return 1; + } in_uint8s(s, 23); while (s_check_rem(s, 4)) @@ -999,7 +1017,7 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) /*****************************************************************************/ /* process the mcs client data we received from the mcs layer */ -static void APP_CC +static int APP_CC xrdp_sec_in_mcs_data(struct xrdp_sec *self) { struct stream *s = (struct stream *)NULL; @@ -1011,6 +1029,10 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) s = &(self->client_mcs_data); /* get hostname, its unicode */ s->p = s->data; + if (!s_check_rem(s, 47)) + { + return 1; + } in_uint8s(s, 47); g_memset(client_info->hostname, 0, 32); c = 1; @@ -1018,6 +1040,10 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) while (index < 16 && c != 0) { + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint8(s, c); in_uint8s(s, 1); client_info->hostname[index] = c; @@ -1026,13 +1052,22 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) /* get build */ s->p = s->data; + if (!s_check_rem(s, 43 + 4)) + { + return 1; + } in_uint8s(s, 43); in_uint32_le(s, client_info->build); /* get keylayout */ s->p = s->data; + if (!s_check_rem(s, 39 + 4)) + { + return 1; + } in_uint8s(s, 39); in_uint32_le(s, client_info->keylayout); s->p = s->data; + return 0; } /*****************************************************************************/ @@ -1105,7 +1140,10 @@ xrdp_sec_incoming(struct xrdp_sec *self) (int)(self->server_mcs_data.end - self->server_mcs_data.data)); #endif DEBUG((" out xrdp_sec_incoming")); - xrdp_sec_in_mcs_data(self); + if (xrdp_sec_in_mcs_data(self) != 0) + { + return 1; + } return 0; } From 369b090e38c1000ffd9a931615c3442692b0da18 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:02:35 -0700 Subject: [PATCH 08/32] VUL: fix some possible buffer overruns --- libxrdp/xrdp_mcs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index cdcfeee6..8c8b7ad6 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -385,6 +385,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + if (!s_check_rem(s, len)) + { + free_stream(s); + return 1; + } + /* make a copy of client mcs data */ init_stream(self->client_mcs_data, len); out_uint8a(self->client_mcs_data, s->p, len); From a1ae000589f50b7a16f9aff42cca5ab3aae79a4e Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:03:35 -0700 Subject: [PATCH 09/32] VUL: channels are limited to 31 --- libxrdp/xrdp_sec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index c44ae420..5b87042a 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -843,7 +843,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) in_uint32_le(s, num_channels); - if (num_channels > 256) + if (num_channels > 31) { return 1; } From 31c5a30a9b6bdb6612b8971ba92bee9a8ae08af7 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:05:17 -0700 Subject: [PATCH 10/32] VUL: if xrdp_sec_process_mcs_data_channels fails, xrdp_sec_process_mcs_data should fail --- libxrdp/xrdp_sec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 5b87042a..6d3e8374 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -908,7 +908,10 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) case SEC_TAG_CLI_CRYPT: break; case SEC_TAG_CLI_CHANNELS: - xrdp_sec_process_mcs_data_channels(self, s); + if (xrdp_sec_process_mcs_data_channels(self, s) != 0) + { + return 1; + } break; case SEC_TAG_CLI_4: break; From 06d92b787ad12b693ee174ce8885636c5511b31c Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:09:19 -0700 Subject: [PATCH 11/32] VUL: call libxrdp_disconnect if libxrdp_process_incomming fails --- xrdp/xrdp_process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index 228bf630..4c52eaac 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -203,6 +203,9 @@ xrdp_process_main_loop(struct xrdp_process *self) else { g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed"); + /* this will try to send a disconnect, + maybe should check that connection got far enough */ + libxrdp_disconnect(self->session); } /* Run end in module */ xrdp_process_mod_end(self); From f75b9143e2ea5cf487eb76e42f58f816c88e688a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:18:21 -0700 Subject: [PATCH 12/32] VUL: make sure cache entries are in range --- common/xrdp_constants.h | 3 +++ libxrdp/xrdp_rdp.c | 29 +++++++++++++++++++++++------ xrdp/xrdp.h | 2 +- xrdp/xrdp_cache.c | 17 ++++++++++++++--- xrdp/xrdp_types.h | 3 ++- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index b978d2de..a163df07 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -559,4 +559,7 @@ #define CMDTYPE_FRAME_MARKER 0x0004 #define CMDTYPE_STREAM_SURFACE_BITS 0x0006 +#define XRDP_MAX_BITMAP_CACHE_ID 3 +#define XRDP_MAX_BITMAP_CACHE_IDX 2000 + #endif diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 2d90485f..a940a695 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -915,13 +915,27 @@ static int APP_CC xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s, int len) { + int i; + self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); - in_uint16_le(s, self->client_info.cache1_entries); + /* cache 1 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache1_entries = i; in_uint16_le(s, self->client_info.cache1_size); - in_uint16_le(s, self->client_info.cache2_entries); + /* cache 2 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache2_entries = i; in_uint16_le(s, self->client_info.cache2_size); - in_uint16_le(s, self->client_info.cache3_entries); + /* caceh 3 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache3_entries = i; in_uint16_le(s, self->client_info.cache3_size); DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, self->client_info.cache1_size)); @@ -947,16 +961,19 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s, self->client_info.bitmap_cache_persist_enable = i; in_uint8s(s, 2); /* number of caches in set, 3 */ in_uint32_le(s, i); - i = MIN(i, 2000); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); self->client_info.cache1_entries = i; self->client_info.cache1_size = 256 * Bpp; in_uint32_le(s, i); - i = MIN(i, 2000); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); self->client_info.cache2_entries = i; self->client_info.cache2_size = 1024 * Bpp; in_uint32_le(s, i); i = i & 0x7fffffff; - i = MIN(i, 2000); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); self->client_info.cache3_entries = i; self->client_info.cache3_size = 4096 * Bpp; DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 081adf3c..6adf17f0 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -27,8 +27,8 @@ #include "trans.h" #include "list.h" #include "libxrdpinc.h" -#include "xrdp_types.h" #include "xrdp_constants.h" +#include "xrdp_types.h" #include "defines.h" #include "os_calls.h" #include "ssl_calls.h" diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index f421371d..b5787763 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -33,16 +33,27 @@ xrdp_cache_create(struct xrdp_wm *owner, self->wm = owner; self->session = session; self->use_bitmap_comp = client_info->use_bitmap_comp; - self->cache1_entries = client_info->cache1_entries; + + self->cache1_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX, + client_info->cache1_entries); + self->cache1_entries = MAX(self->cache1_entries, 0); self->cache1_size = client_info->cache1_size; - self->cache2_entries = client_info->cache2_entries; + + self->cache2_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX, + client_info->cache2_entries); + self->cache2_entries = MAX(self->cache2_entries, 0); self->cache2_size = client_info->cache2_size; - self->cache3_entries = client_info->cache3_entries; + + self->cache3_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX, + client_info->cache3_entries); + self->cache3_entries = MAX(self->cache3_entries, 0); self->cache3_size = client_info->cache3_size; + self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable; self->bitmap_cache_version = client_info->bitmap_cache_version; self->pointer_cache_entries = client_info->pointer_cache_entries; self->xrdp_os_del_list = list_create(); + return self; } diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index e7bb7baf..5a43d9a9 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -195,7 +195,8 @@ struct xrdp_cache struct xrdp_palette_item palette_items[6]; /* bitmap */ int bitmap_stamp; - struct xrdp_bitmap_item bitmap_items[3][2000]; + struct xrdp_bitmap_item bitmap_items[XRDP_MAX_BITMAP_CACHE_ID] + [XRDP_MAX_BITMAP_CACHE_IDX]; int use_bitmap_comp; int cache1_entries; int cache1_size; From 445e7d980005503913e77895f5b13097928b3437 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 16:20:11 -0700 Subject: [PATCH 13/32] VUL: check bytes remaining in xrdp_rdp_process_data_input --- libxrdp/xrdp_rdp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index a940a695..0bbd411f 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -1322,12 +1322,20 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s) int param2; int time; + if (!s_check_rem(s, 4)) + { + return 1; + } in_uint16_le(s, num_events); in_uint8s(s, 2); /* pad */ DEBUG(("in xrdp_rdp_process_data_input %d events", num_events)); for (index = 0; index < num_events; index++) { + if (!s_check_rem(s, 12)) + { + return 1; + } in_uint32_le(s, time); in_uint16_le(s, msg_type); in_uint16_le(s, device_flags); From 6848cbbc0483837466e8b2d4b3af147cfc7d2ed7 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 10 Sep 2013 23:17:18 -0700 Subject: [PATCH 14/32] VUL: add some more buffer checks --- libxrdp/xrdp_mcs.c | 26 +++++++++++- libxrdp/xrdp_rdp.c | 91 ++++++++++++++++++++++++++++++++++++------ libxrdp/xrdp_sec.c | 98 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 196 insertions(+), 19 deletions(-) diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 8c8b7ad6..d110c987 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -291,7 +291,7 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s) return 1; } - if (!s_check_rem(s, len)) + if ((len < 0) || !s_check_rem(s, len)) { return 1; } @@ -337,6 +337,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + if ((len < 0) || !s_check_rem(s, len)) + { + free_stream(s); + return 1; + } + in_uint8s(s, len); if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) @@ -345,6 +351,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + if ((len < 0) || !s_check_rem(s, len)) + { + free_stream(s); + return 1; + } + in_uint8s(s, len); if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0) @@ -353,6 +365,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + if ((len < 0) || !s_check_rem(s, len)) + { + free_stream(s); + return 1; + } + in_uint8s(s, len); if (xrdp_mcs_parse_domain_params(self, s) != 0) @@ -379,6 +397,7 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) return 1; } + /* mcs data can not be zero length */ if ((len <= 0) || (len > 16 * 1024)) { free_stream(s); @@ -596,6 +615,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if (opcode & 2) { + if (!s_check_rem(s, 2)) + { + free_stream(s); + return 1; + } in_uint8s(s, 2); } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 0bbd411f..214202f5 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -514,6 +514,11 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) p = &(self->sec_layer->client_mcs_data); p->p = p->data; + if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2)) + { + g_writeln("xrdp_rdp_parse_client_mcs_data: error"); + return 1; + } in_uint8s(p, 31); in_uint16_le(p, self->client_info.width); in_uint16_le(p, self->client_info.height); @@ -524,6 +529,10 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) switch (i) { case 0xca01: + if (!s_check_rem(p, 6 + 1)) + { + return 1; + } in_uint8s(p, 6); in_uint8(p, i); @@ -837,6 +846,11 @@ xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s, { int i; + if (len < 10 + 2) + { + g_writeln("xrdp_process_capset_general: error"); + return 1; + } in_uint8s(s, 10); in_uint16_le(s, i); /* use_compact_packets is pretty much 'use rdp5' */ @@ -858,6 +872,11 @@ xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s, int cap_flags; DEBUG(("order capabilities")); + if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + { + g_writeln("xrdp_process_capset_order: error"); + return 1; + } in_uint8s(s, 20); /* Terminal desc, pad */ in_uint8s(s, 2); /* Cache X granularity */ in_uint8s(s, 2); /* Cache Y granularity */ @@ -917,6 +936,11 @@ xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s, { int i; + if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) + { + g_writeln("xrdp_process_capset_bmpcache: error"); + return 1; + } self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); /* cache 1 */ @@ -955,6 +979,11 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s, int Bpp = 0; int i = 0; + if (len < 2 + 2 + 4 + 4 + 4) + { + g_writeln("xrdp_process_capset_bmpcache2: error"); + return 1; + } self->client_info.bitmap_cache_version |= 2; Bpp = (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); /* cache flags */ @@ -992,6 +1021,11 @@ xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, { int codec_id; + if (len < 1) + { + g_writeln("xrdp_process_capset_cache_v3_codec_id: error"); + return 1; + } in_uint8(s, codec_id); g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d", codec_id); @@ -1009,6 +1043,11 @@ xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s, int colorPointerFlag; int no_new_cursor; + if (len < 2 + 2 + 2) + { + g_writeln("xrdp_process_capset_pointercache: error"); + return 1; + } no_new_cursor = self->client_info.pointer_flags & 2; in_uint16_le(s, colorPointerFlag); self->client_info.pointer_flags = colorPointerFlag; @@ -1045,6 +1084,11 @@ xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s, { int code; + if (len < 4) + { + g_writeln("xrdp_process_capset_brushcache: error"); + return 1; + } in_uint32_le(s, code); self->client_info.brush_cache_code = code; return 0; @@ -1057,12 +1101,11 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, { int i32; - if (len - 4 < 8) + if (len < 4 + 2 + 2) { - g_writeln("xrdp_process_offscreen_bmpcache: bad len"); + g_writeln("xrdp_process_offscreen_bmpcache: error"); return 1; } - in_uint32_le(s, i32); self->client_info.offscreen_support_level = i32; in_uint16_le(s, i32); @@ -1083,12 +1126,11 @@ xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len) { int i32; - if (len - 4 < 4) + if (len < 4) { - g_writeln("xrdp_process_capset_rail: bad len"); + g_writeln("xrdp_process_capset_rail: error"); return 1; } - in_uint32_le(s, i32); self->client_info.rail_support_level = i32; g_writeln("xrdp_process_capset_rail: rail_support_level %d", @@ -1102,12 +1144,11 @@ xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len) { int i32; - if (len - 4 < 7) + if (len < 4 + 1 + 2) { - g_writeln("xrdp_process_capset_window: bad len"); + g_writeln("xrdp_process_capset_window: error"); return 1; } - in_uint32_le(s, i32); self->client_info.wnd_support_level = i32; in_uint8(s, i32); @@ -1134,14 +1175,32 @@ xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len) char *codec_guid; char *next_guid; + if (len < 1) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } in_uint8(s, codec_count); + len--; for (index = 0; index < codec_count; index++) { codec_guid = s->p; + if (len < 16 + 1 + 2) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } in_uint8s(s, 16); in_uint8(s, codec_id); in_uint16_le(s, codec_properties_length); + len -= 16 + 1 + 2; + if (len < codec_properties_length) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } + len -= codec_properties_length; next_guid = s->p + codec_properties_length; if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) @@ -1207,9 +1266,19 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) for (index = 0; index < num_caps; index++) { p = s->p; + if (!s_check_rem(s, 4)) + { + g_writeln("xrdp_rdp_process_confirm_active: error 1"); + return 1; + } in_uint16_le(s, type); in_uint16_le(s, len); - + if ((len < 4) || !s_check_rem(s, len - 4)) + { + g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p); + return 1; + } + len -= 4; switch (type) { case RDP_CAPSET_GENERAL: /* 1 */ @@ -1295,7 +1364,7 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) break; } - s->p = p + len; + s->p = p + len + 4; } DEBUG(("out xrdp_rdp_process_confirm_active")); diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 6d3e8374..fbdc99a4 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -331,12 +331,20 @@ unicode_in(struct stream *s, int uni_len, char *dst, int dst_len) break; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint8(s, dst[dst_index]); in_uint8s(s, 1); dst_index++; src_index += 2; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint8s(s, 2); return 0; } @@ -359,6 +367,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) /* initialize (zero out) local variables */ g_memset(tmpdata, 0, sizeof(char) * 256); + if (!s_check_rem(s, 8)) + { + return 1; + } in_uint8s(s, 4); in_uint32_le(s, flags); DEBUG(("in xrdp_sec_process_logon_info flags $%x", flags)); @@ -398,6 +410,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) } } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_domain); if (len_domain > 511) @@ -406,6 +422,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_user); if (len_user > 511) @@ -414,6 +434,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_password); if (len_password > 511) @@ -422,6 +446,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_program); if (len_program > 511) @@ -430,6 +458,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_directory); if (len_directory > 511) @@ -438,35 +470,75 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } - unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255); + if (unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255) != 0) + { + return 1; + } DEBUG(("domain %s", self->rdp_layer->client_info.domain)); - unicode_in(s, len_user, self->rdp_layer->client_info.username, 255); + if (unicode_in(s, len_user, self->rdp_layer->client_info.username, 255) != 0) + { + return 1; + } DEBUG(("username %s", self->rdp_layer->client_info.username)); if (flags & RDP_LOGON_AUTO) { - unicode_in(s, len_password, self->rdp_layer->client_info.password, 255); + if (unicode_in(s, len_password, self->rdp_layer->client_info.password, 255) != 0) + { + return 1; + } DEBUG(("flag RDP_LOGON_AUTO found")); } else { + if (!s_check_rem(s, len_password + 2)) + { + return 1; + } in_uint8s(s, len_password + 2); if (self->rdp_layer->client_info.require_credentials) + { + g_writeln("xrdp_sec_process_logon_info: credentials on cmd line is mandatory"); return 1; /* credentials on cmd line is mandatory */ + } } - unicode_in(s, len_program, self->rdp_layer->client_info.program, 255); + if (unicode_in(s, len_program, self->rdp_layer->client_info.program, 255) != 0) + { + return 1; + } DEBUG(("program %s", self->rdp_layer->client_info.program)); - unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255); + if (unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255) != 0) + { + return 1; + } DEBUG(("directory %s", self->rdp_layer->client_info.directory)); if (flags & RDP_LOGON_BLOB) { + if (!s_check_rem(s, 4)) + { + return 1; + } in_uint8s(s, 2); /* unknown */ in_uint16_le(s, len_ip); - unicode_in(s, len_ip - 2, tmpdata, 255); + if (unicode_in(s, len_ip - 2, tmpdata, 255) != 0) + { + return 1; + } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_dll); - unicode_in(s, len_dll - 2, tmpdata, 255); + if (unicode_in(s, len_dll - 2, tmpdata, 255) != 0) + { + return 1; + } + if (!s_check_rem(s, 4 + 62 + 22 + 62 + 26 + 4)) + { + return 1; + } in_uint32_le(s, tzone); /* len of timetone */ in_uint8s(s, 62); /* skip */ in_uint8s(s, 22); /* skip misc. */ @@ -676,17 +748,29 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 1; } + if (!s_check_rem(s, 4)) + { + return 1; + } in_uint32_le(s, flags); DEBUG((" in xrdp_sec_recv flags $%x", flags)); if (flags & SEC_ENCRYPT) /* 0x08 */ { + if (!s_check_rem(s, 8)) + { + return 1; + } in_uint8s(s, 8); /* signature */ xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ { + if (!s_check_rem(s, 4 + 64)) + { + return 1; + } in_uint32_le(s, len); in_uint8a(s, self->client_crypt_random, 64); xrdp_sec_rsa_op(self->client_random, self->client_crypt_random, From 188ca68adb5c312111527e1cef4f9bab014f88d5 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Wed, 11 Sep 2013 19:42:42 -0700 Subject: [PATCH 15/32] scard: added GetStatusChange() msg --- sesman/chansrv/smartcard.c | 724 ++++++++++++++++++++------------ sesman/chansrv/smartcard.h | 43 +- sesman/chansrv/smartcard_pcsc.c | 2 +- sesman/chansrv/smartcard_pcsc.h | 23 +- 4 files changed, 484 insertions(+), 308 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 8e3761e6..6140873f 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -21,6 +21,7 @@ * smartcard redirection support */ +#include #include "os_calls.h" #include "smartcard.h" #include "log.h" @@ -60,13 +61,15 @@ #endif #define log_error(_params...) \ +do \ { \ g_write("[%10.10u]: SMART_CARD %s: %d : ERROR: ", \ g_time3(), __func__, __LINE__); \ g_writeln (_params); \ -} +} while (0) #define log_info(_params...) \ +do \ { \ if (LOG_INFO <= LOG_LEVEL) \ { \ @@ -74,9 +77,10 @@ g_time3(), __func__, __LINE__); \ g_writeln (_params); \ } \ -} +} while (0) #define log_debug(_params...) \ +do \ { \ if (LOG_DEBUG <= LOG_LEVEL) \ { \ @@ -84,7 +88,7 @@ g_time3(), __func__, __LINE__); \ g_writeln (_params); \ } \ -} +} while (0) /* [MS-RDPESC] 3.1.4 */ #define SCARD_IOCTL_ESTABLISH_CONTEXT 0x00090014 /* EstablishContext */ @@ -99,7 +103,8 @@ #define SCARD_IOCTL_FORGET_READER 0x00090068 /* IntroduceReader */ #define SCARD_IOCTL_ADD_READER_TO_GROUP 0x00090070 /* AddReaderToGroup */ #define SCARD_IOCTL_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup */ -#define SCARD_IOCTL_GET_STATUS_CHANGE 0x000900A0 /* GetStatusChangeA */ +#define SCARD_IOCTL_GET_STATUS_CHANGE_A 0x000900A0 /* GetStatusChangeA */ +#define SCARD_IOCTL_GET_STATUS_CHANGE_W 0x000900A4 /* GetStatusChangeW */ #define SCARD_IOCTL_CANCEL 0x000900A8 /* Cancel */ #define SCARD_IOCTL_CONNECT 0x000900AC /* ConnectA */ #define SCARD_IOCTL_RECONNECT 0x000900B4 /* Reconnect */ @@ -130,321 +135,204 @@ typedef struct smartcard int Context_len; /* Context len in bytes */ } SMARTCARD; -SMARTCARD *smartcards[MAX_SMARTCARDS]; -int g_smartcards_inited = 0; +/* globals */ +SMARTCARD* smartcards[MAX_SMARTCARDS]; +int g_smartcards_inited = 0; +static tui32 g_device_id = 0; +static int g_scard_index = 0; +/* externs */ extern tui32 g_completion_id; -extern int g_rdpdr_chan_id; /* in chansrv.c */ +extern int g_rdpdr_chan_id; /* in chansrv.c */ -/* forward declarations specific to this file */ -static void scard_send_EstablishContext(IRP *irp, int scope); -static void scard_send_ListReaders(IRP *irp, int wide); + +/****************************************************************************** +** static functions local to this file ** +******************************************************************************/ static struct stream *scard_make_new_ioctl(IRP *irp, tui32 ioctl); static int scard_add_new_device(tui32 device_id); static int scard_get_free_slot(void); static void scard_release_resources(void); +static void scard_send_EstablishContext(IRP* irp, int scope); +static void scard_send_ListReaders(IRP* irp, int wide); +static void scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa); -static tui32 g_device_id = 0; -static int g_scard_index = 0; +/****************************************************************************** +** local callbacks into this module ** +******************************************************************************/ -/*****************************************************************************/ -int APP_CC -scard_send_irp_establish_context(struct trans *con, int scope) -{ - IRP *irp; +static void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); - if ((irp = devredir_irp_new()) == NULL) - { - log_error("system out of memory"); - return 1; - } - irp->scard_index = g_scard_index; - irp->CompletionId = g_completion_id++; - irp->DeviceId = g_device_id; - irp->callback = scard_handle_EstablishContext_Return; - irp->user_data = con; - scard_send_EstablishContext(irp, scope); - log_debug("leaving"); - return 0; -} +static void scard_handle_ListReaders_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); -/*****************************************************************************/ -int APP_CC -scard_send_irp_list_readers(struct trans *con) -{ - IRP *irp; +static void scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); - if ((irp = devredir_irp_new()) == NULL) - { - log_error("system out of memory"); - return 1; - } - irp->scard_index = g_scard_index; - irp->CompletionId = g_completion_id++; - irp->DeviceId = g_device_id; - irp->callback = scard_handle_ListReaders_Return; - irp->user_data = con; - scard_send_ListReaders(irp, 1); - log_debug("leaving"); - return 0; -} /****************************************************************************** -** non static functions ** +** ** +** externally accessible functions, defined in smartcard.h ** +** ** ******************************************************************************/ +/** + *****************************************************************************/ void APP_CC scard_device_announce(tui32 device_id) { log_debug("entered: device_id=%d", device_id); + if (g_smartcards_inited) - { return; - } + g_memset(&smartcards, 0, sizeof(smartcards)); g_smartcards_inited = 1; g_device_id = device_id; g_scard_index = scard_add_new_device(device_id); + if (g_scard_index < 0) - { log_debug("scard_add_new_device failed with DeviceId=%d", g_device_id); - } else - { log_debug("added smartcard with DeviceId=%d to list", g_device_id); - } - //scard_send_establish_context(); } -/****************************************************************************** -** callbacks into this module ** -******************************************************************************/ - -void APP_CC -scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, - tui32 DeviceId, tui32 CompletionId, - tui32 IoStatus) +/** + * + *****************************************************************************/ +int APP_CC +scard_get_wait_objs(tbus *objs, int *count, int *timeout) { - tui32 len; - int tmp; - SMARTCARD *sc; - - log_debug("entered"); - - /* sanity check */ - if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) - { - log_error("DeviceId/CompletionId do not match those in IRP"); - return; - } - - if (IoStatus != 0) - { - log_error("failed to establish context - device not usable"); - /* LK_TODO delete irp and smartcard entry */ - return; - } - - sc = smartcards[irp->scard_index]; - - /* get OutputBufferLen */ - xstream_rd_u32_le(s, len); - - /* LK_TODO */ - g_hexdump(s->p, len); - - xstream_rd_u32_le(s, tmp); /* should be len 8, LE, V1 */ - xstream_rd_u32_le(s, tmp); /* marshalling flag */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, len); /* len of context in bytes */ - sc->Context_len = len; - xstream_copyout(sc->Context, s, len); - - if (LOG_LEVEL == LOG_DEBUG) - { - log_debug("dumping context (%d bytes)", sc->Context_len); - g_hexdump(sc->Context, sc->Context_len); - } - - //irp->callback = scard_handle_ListReaders_Return; - //scard_send_ListReaders(irp, 1); - - scard_function_establish_context_return((struct trans *) (irp->user_data), - ((int*)(sc->Context))[0]); - - devredir_irp_delete(irp); + return scard_pcsc_get_wait_objs(objs, count, timeout); +} - /* LK_TODO need to delete IRP */ - log_debug("leaving"); +/** + * + *****************************************************************************/ +int APP_CC +scard_check_wait_objs(void) +{ + return scard_pcsc_check_wait_objs(); } -/******************************************************************************/ -void APP_CC -scard_handle_ListReaders_Return(struct stream *s, IRP *irp, - tui32 DeviceId, tui32 CompletionId, - tui32 IoStatus) +/** + * + *****************************************************************************/ +int APP_CC +scard_init(void) { - tui32 len; + log_debug("init"); + return scard_pcsc_init(); +} - log_debug("entered"); +/** + * + *****************************************************************************/ +int APP_CC +scard_deinit(void) +{ + log_debug("deinit"); + return scard_pcsc_deinit(); +} - /* sanity check */ - if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) - { - log_error("DeviceId/CompletionId do not match those in IRP"); - return; - } +/** + * + *****************************************************************************/ +int APP_CC +scard_send_irp_establish_context(struct trans *con, int scope) +{ + IRP *irp; - if (IoStatus != 0) + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) { - log_error("failed to list readers - device not usable"); - /* LK_TODO delete irp and smartcard entry */ - return; + log_error("system out of memory"); + return 1; } - /* get OutputBufferLen */ - xstream_rd_u32_le(s, len); - - scard_function_list_readers_return((struct trans *) (irp->user_data), - s, len); + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_EstablishContext_Return; + irp->user_data = con; - /* LK_TODO */ - //log_debug("dumping %d bytes", len); - //g_hexdump(s->p, len); + /* send IRP to client */ + scard_send_EstablishContext(irp, scope); - log_debug("leaving"); + return 0; } -/****************************************************************************** -** static functions local to this file ** -******************************************************************************/ - /** * *****************************************************************************/ - -static void APP_CC -scard_send_EstablishContext(IRP *irp, int scope) +int APP_CC +scard_send_irp_list_readers(struct trans *con) { - struct stream *s; - int bytes; + IRP *irp; - if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_ESTABLISH_CONTEXT)) == NULL) + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) { - log_error("scard_make_new_ioctl failed"); - return; + log_error("system out of memory"); + return 1; } + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_ListReaders_Return; + irp->user_data = con; - xstream_wr_u32_le(s, 0x08); /* len */ - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, scope); /* Ioctl specific data */ - xstream_wr_u32_le(s, 0); /* don't know what this is, */ - /* but Win7 is sending it */ - /* get stream len */ - bytes = xstream_len(s); - - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + /* send IRP to client */ + scard_send_ListReaders(irp, 1); - /* send to client */ - send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + return 0; } /** + * Send get change in status command * + * @param con connection to client + * @param wide TRUE if unicode string + * @param timeout timeout in milliseconds, -1 for infinity + * @param num_readers number of entries in rsa + * @param rsa array of READER_STATEs *****************************************************************************/ - -static void APP_CC -scard_send_ListReaders(IRP *irp, int wide) +int APP_CC +scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa) { - /* see [MS-RDPESC] 2.2.2.4 */ - - SMARTCARD *sc; - struct stream *s; - int bytes; - tui32 ioctl; + IRP *irp; - if ((sc = smartcards[irp->scard_index]) == NULL) + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) { - log_error("smartcards[%d] is NULL", irp->scard_index); - return; + log_error("system out of memory"); + return 1; } - ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W : - SCARD_IOCTL_LIST_READERS_A; - - if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) - return; - - xstream_wr_u32_le(s, 72); /* number of bytes to follow */ - xstream_seek(s, 0x1c); /* freerdp does not use this */ - - /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); - - xstream_wr_u32_le(s, 36); /* length of mszGroups */ - xstream_wr_u16_le(s, 0x0053); /* S */ - xstream_wr_u16_le(s, 0x0043); /* C */ - xstream_wr_u16_le(s, 0x0061); /* a */ - xstream_wr_u16_le(s, 0x0072); /* r */ - xstream_wr_u16_le(s, 0x0064); /* d */ - xstream_wr_u16_le(s, 0x0024); /* $ */ - xstream_wr_u16_le(s, 0x0041); /* A */ - xstream_wr_u16_le(s, 0x006c); /* l */ - xstream_wr_u16_le(s, 0x006c); /* l */ - xstream_wr_u16_le(s, 0x0052); /* R */ - xstream_wr_u16_le(s, 0x0065); /* e */ - xstream_wr_u16_le(s, 0x0061); /* a */ - xstream_wr_u16_le(s, 0x0064); /* d */ - xstream_wr_u16_le(s, 0x0065); /* e */ - xstream_wr_u16_le(s, 0x0072); /* r */ - xstream_wr_u16_le(s, 0x0073); /* s */ - - xstream_wr_u32_le(s, 0x00); - - /* get stream len */ - bytes = xstream_len(s); - - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; - - /* send to client */ - send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_GetStatusChange_Return; + irp->user_data = con; - /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... - 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... - 0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... - 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................ - 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. - 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. - 0070 72 00 73 00 00 00 00 00 r.s..... - scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c - */ + /* send IRP to client */ + scard_send_GetStatusChange(irp, wide, timeout, num_readers, rsa); - /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................ - 0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................ - 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... - 0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd...... - 0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'.............. - 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. - 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. - 0070 72 00 73 00 00 00 00 00 r.s..... - scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014 - */ + return 0; } +/****************************************************************************** +** ** +** static functions local to this file ** +** ** +******************************************************************************/ + /** * Crate a new stream and insert specified IOCTL * @@ -453,7 +341,6 @@ scard_send_ListReaders(IRP *irp, int wide) * * @return stream with IOCTL inserted in it, NULL on error *****************************************************************************/ - static struct stream * APP_CC scard_make_new_ioctl(IRP *irp, tui32 ioctl) { @@ -478,7 +365,7 @@ scard_make_new_ioctl(IRP *irp, tui32 ioctl) struct stream *s; - xstream_new(s, 1024 * 3); + xstream_new(s, 1024 * 4); if (s == NULL) { log_error("system out of memory"); @@ -511,7 +398,6 @@ scard_make_new_ioctl(IRP *irp, tui32 ioctl) * * @return index into smartcards[] on success, -1 on failure *****************************************************************************/ - static int APP_CC scard_add_new_device(tui32 device_id) { @@ -542,7 +428,6 @@ scard_add_new_device(tui32 device_id) * @return index of first unused entry in smartcards or -1 if smartcards * is full *****************************************************************************/ - static int APP_CC scard_get_free_slot(void) { @@ -564,7 +449,6 @@ scard_get_free_slot(void) /** * Release resources prior to shutting down *****************************************************************************/ - static void APP_CC scard_release_resources(void) { @@ -583,37 +467,341 @@ scard_release_resources(void) /** * *****************************************************************************/ -int APP_CC -scard_get_wait_objs(tbus *objs, int *count, int *timeout) +static void APP_CC +scard_send_EstablishContext(IRP *irp, int scope) { - return scard_pcsc_get_wait_objs(objs, count, timeout); + struct stream *s; + int bytes; + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_ESTABLISH_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); + return; + } + + xstream_wr_u32_le(s, 0x08); /* len */ + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, scope); /* Ioctl specific data */ + xstream_wr_u32_le(s, 0); /* don't know what this is, */ + /* but Win7 is sending it */ + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } /** * *****************************************************************************/ -int APP_CC -scard_check_wait_objs(void) +static void APP_CC +scard_send_ListReaders(IRP *irp, int wide) { - return scard_pcsc_check_wait_objs(); + /* see [MS-RDPESC] 2.2.2.4 */ + + SMARTCARD *sc; + struct stream *s; + int bytes; + tui32 ioctl; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W : + SCARD_IOCTL_LIST_READERS_A; + + if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + return; + + xstream_wr_u32_le(s, 72); /* number of bytes to follow */ + xstream_seek(s, 28); /* freerdp does not use this */ + + /* insert context */ + xstream_wr_u32_le(s, sc->Context_len); + xstream_copyin(s, sc->Context, sc->Context_len); + + xstream_wr_u32_le(s, 36); /* length of mszGroups */ + xstream_wr_u16_le(s, 0x0053); + xstream_wr_u16_le(s, 0x0043); + xstream_wr_u16_le(s, 0x0061); + xstream_wr_u16_le(s, 0x0072); + xstream_wr_u16_le(s, 0x0064); + xstream_wr_u16_le(s, 0x0024); + xstream_wr_u16_le(s, 0x0041); + xstream_wr_u16_le(s, 0x006c); + xstream_wr_u16_le(s, 0x006c); + xstream_wr_u16_le(s, 0x0052); + xstream_wr_u16_le(s, 0x0065); + xstream_wr_u16_le(s, 0x0061); + xstream_wr_u16_le(s, 0x0064); + xstream_wr_u16_le(s, 0x0065); + xstream_wr_u16_le(s, 0x0072); + xstream_wr_u16_le(s, 0x0073); + + xstream_wr_u32_le(s, 0x00); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); + + /* + scard_device_control: dumping 120 bytes of data + 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... + 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... + 0030 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... + 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 03 01 ................ + 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. + 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. + 0070 72 00 73 00 00 00 00 00 r.s..... + scard_device_control: output_len=2048 input_len=88 ioctl_code=0x9002c + */ + + /* + scard_device_control: dumping 120 bytes of data + 0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................ + 0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................ + 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H....... + 0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd...... + 0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'.............. + 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$. + 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e. + 0070 72 00 73 00 00 00 00 00 r.s..... + scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014 + */ } /** + * Get change in status * + * @param irp I/O resource pkt + * @param wide TRUE if unicode string + * @param timeout timeout in milliseconds, -1 for infinity + * @param num_readers number of entries in rsa + * @param rsa array of READER_STATEs *****************************************************************************/ -int APP_CC -scard_init(void) +static void +scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa) { - log_debug("init") - return scard_pcsc_init(); + /* see [MS-RDPESC] 2.2.2.11 for ASCII */ + /* see [MS-RDPESC] 2.2.2.12 for Wide char */ + + SMARTCARD* sc; + READER_STATE* rs; + struct stream* s; + tui32 ioctl; + int bytes; + int i; + int len; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + ioctl = (wide > 0) ? SCARD_IOCTL_GET_STATUS_CHANGE_W : + SCARD_IOCTL_GET_STATUS_CHANGE_A; + + if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + return; + + xstream_seek(s, 16); /* unused */ + xstream_wr_u32_le(s, timeout); + xstream_wr_u32_le(s, num_readers); + xstream_wr_u32_le(s, 0); /* unused */ + + /* insert context */ + xstream_wr_u32_le(s, sc->Context_len); + xstream_copyin(s, sc->Context, sc->Context_len); + + xstream_wr_u32_le(s, 0); /* unused */ + + /* insert card reader state */ + for (i = 0; i < num_readers; i++) + { + rs = &rsa[i]; + + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, rs->current_state); + xstream_wr_u32_le(s, rs->event_state); + xstream_wr_u32_le(s, rs->atr_len); + xstream_copyin(s, rs->atr, rs->atr_len); + xstream_wr_u32_le(s, 0); /* unused */ + } + + /* insert card reader names */ + for (i = 0; i < num_readers; i++) + { + rs = &rsa[i]; + len = strlen(rs->reader_name); + + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, len); + xstream_copyin(s, rs->reader_name, len); + xstream_wr_u32_le(s, 0); /* null terminate */ + } + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); } +/****************************************************************************** +** ** +** local callbacks into this module ** +** ** +******************************************************************************/ + /** * *****************************************************************************/ -int APP_CC -scard_deinit(void) +static void APP_CC +scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) { - log_debug("deinit") - return scard_pcsc_deinit(); + tui32 len; + int tmp; + SMARTCARD *sc; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("failed to establish context - device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + sc = smartcards[irp->scard_index]; + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + /* LK_TODO */ + g_hexdump(s->p, len); + + xstream_rd_u32_le(s, tmp); /* should be len 8, LE, V1 */ + xstream_rd_u32_le(s, tmp); /* marshalling flag */ + xstream_rd_u32_le(s, tmp); /* ?? */ + xstream_rd_u32_le(s, tmp); /* ?? */ + xstream_rd_u32_le(s, tmp); /* ?? */ + xstream_rd_u32_le(s, tmp); /* ?? */ + xstream_rd_u32_le(s, tmp); /* ?? */ + xstream_rd_u32_le(s, len); /* len of context in bytes */ + sc->Context_len = len; + xstream_copyout(sc->Context, s, len); + + if (LOG_LEVEL == LOG_DEBUG) + { + log_debug("dumping context (%d bytes)", sc->Context_len); + g_hexdump(sc->Context, sc->Context_len); + } + + // LK_TODO delete this + //irp->callback = scard_handle_ListReaders_Return; + //scard_send_ListReaders(irp, 1); + + scard_function_establish_context_return((struct trans *) (irp->user_data), + ((int*)(sc->Context))[0]); + + devredir_irp_delete(irp); + + /* LK_TODO need to delete IRP */ + log_debug("leaving"); +} + +/** + * + *****************************************************************************/ +static void APP_CC +scard_handle_ListReaders_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("failed to list readers - device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + scard_function_list_readers_return((struct trans *) irp->user_data, + s, len); + log_debug("leaving"); +} + +/** + * + *****************************************************************************/ +static void +scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("failed to get status change - device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index ecf79a04..3d113ce1 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -28,30 +28,23 @@ #include "irp.h" #include "trans.h" -/* forward declarations */ -void scard_device_announce(tui32 device_id); - -/* callbacks into this module */ -void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, - tui32 DeviceId, tui32 CompletionId, - tui32 IoStatus); - -void scard_handle_ListReaders_Return(struct stream *s, IRP *irp, - tui32 DeviceId, tui32 CompletionId, - tui32 IoStatus); - -int APP_CC -scard_get_wait_objs(tbus *objs, int *count, int *timeout); -int APP_CC -scard_check_wait_objs(void); -int APP_CC -scard_init(void); -int APP_CC -scard_deinit(void); - -int APP_CC -scard_send_irp_establish_context(struct trans *con, int scope); -int APP_CC -scard_send_irp_list_readers(struct trans *con); +typedef struct reader_state +{ + char reader_name[128]; + tui32 current_state; + tui32 event_state; + tui32 atr_len; /* number of bytes in atr[] */ + tui8 atr[36]; +} READER_STATE; +void scard_device_announce(tui32 device_id); +int APP_CC scard_get_wait_objs(tbus *objs, int *count, int *timeout); +int APP_CC scard_check_wait_objs(void); +int APP_CC scard_init(void); +int APP_CC scard_deinit(void); +int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); +int APP_CC scard_send_irp_list_readers(struct trans *con); + +int APP_CC scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa); #endif /* end #ifndef _SMARTCARD_C */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 72249f32..5d1be106 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -273,7 +273,7 @@ scard_function_list_readers_return(struct trans *con, g_reader_states[0].cardAtr[9] = 0x32; //g_reader_states[0].eventCounter++; - + out_s = trans_get_out_s(con, 8192); out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); s_mark_end(out_s); diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index bac8638c..1c8c6d7b 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -24,20 +24,15 @@ #ifndef _SMARTCARD_PCSC_H #define _SMARTCARD_PCSC_H -int APP_CC -scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); -int APP_CC -scard_pcsc_check_wait_objs(void); -int APP_CC -scard_pcsc_init(void); -int APP_CC -scard_pcsc_deinit(void); +int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); +int APP_CC scard_pcsc_check_wait_objs(void); +int APP_CC scard_pcsc_init(void); +int APP_CC scard_pcsc_deinit(void); -int APP_CC -scard_function_establish_context_return(struct trans *con, int context); -int APP_CC -scard_function_list_readers_return(struct trans *con, - struct stream *in_s, - int len); +int APP_CC scard_function_establish_context_return(struct trans *con, int context); + +int APP_CC scard_function_list_readers_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 215956353fa2b122f7b75a9e344138ab61d4b594 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Fri, 13 Sep 2013 10:20:35 -0700 Subject: [PATCH 16/32] scard: added support for connect call --- sesman/chansrv/smartcard.c | 140 ++++++++++++++++++++++++++++++++++++- sesman/chansrv/smartcard.h | 34 +++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 6140873f..78a47ba0 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -106,7 +106,8 @@ do \ #define SCARD_IOCTL_GET_STATUS_CHANGE_A 0x000900A0 /* GetStatusChangeA */ #define SCARD_IOCTL_GET_STATUS_CHANGE_W 0x000900A4 /* GetStatusChangeW */ #define SCARD_IOCTL_CANCEL 0x000900A8 /* Cancel */ -#define SCARD_IOCTL_CONNECT 0x000900AC /* ConnectA */ +#define SCARD_IOCTL_CONNECT_A 0x000900AC /* ConnectA */ +#define SCARD_IOCTL_CONNECT_W 0x000900B0 /* ConnectW */ #define SCARD_IOCTL_RECONNECT 0x000900B4 /* Reconnect */ #define SCARD_IOCTL_DISCONNECT 0x000900B8 /* Disconnect */ #define SCARD_IOCTL_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */ @@ -155,9 +156,12 @@ static int scard_get_free_slot(void); static void scard_release_resources(void); static void scard_send_EstablishContext(IRP* irp, int scope); static void scard_send_ListReaders(IRP* irp, int wide); + static void scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); +static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs); + /****************************************************************************** ** local callbacks into this module ** ******************************************************************************/ @@ -174,6 +178,9 @@ static void scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); +static void scard_handle_Connect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); /****************************************************************************** ** ** @@ -327,6 +334,36 @@ scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, return 0; } +/** + * Open a connection to the smart card located in the reader + * + * @param con connection to client + * @param wide TRUE if unicode string + *****************************************************************************/ +int APP_CC +scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_Connect_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_Connect(irp, wide, rs); + + return 0; +} + /****************************************************************************** ** ** ** static functions local to this file ** @@ -668,6 +705,75 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, xstream_free(s); } +/** + * Send connect command + * + * @param irp I/O resource pkt + * @param wide TRUE if unicode string + * @param rs reader state + *****************************************************************************/ +static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) +{ + /* see [MS-RDPESC] 2.2.2.13 for ASCII */ + /* see [MS-RDPESC] 2.2.2.14 for Wide char */ + + SMARTCARD* sc; + struct stream* s; + tui32 ioctl; + int bytes; + int len; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + ioctl = (wide > 0) ? SCARD_IOCTL_CONNECT_A : + SCARD_IOCTL_CONNECT_W; + + if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 20 bytes unused (s->p is currently pointed here) + * u32 4 bytes dwShareMode + * u32 4 bytes dwPreferredProtocol + * xx bytes reader name + * u32 4 bytes context length (len) + * len bytes context + */ + + xstream_seek(s, 20); + xstream_wr_u32_le(s, rs->shared_mode_flag); + xstream_wr_u32_le(s, rs->preferred_protocol); + + /* insert reader name */ + /* LK_TODO need to handle unicode */ + len = strlen(rs->reader_name); + xstream_copyin(s, rs->reader_name, len); + + /* insert context */ + xstream_wr_u32_le(s, sc->Context_len); + xstream_copyin(s, sc->Context, sc->Context_len); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + /****************************************************************************** ** ** ** local callbacks into this module ** @@ -805,3 +911,35 @@ scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, log_debug("leaving"); } + +/** + * + *****************************************************************************/ +static void +scard_handle_Connect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("failed to connect - device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 3d113ce1..8352a01e 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -28,6 +28,21 @@ #include "irp.h" #include "trans.h" +#define SCARD_SHARE_EXCLUSIVE 0x00000001 +#define SCARD_SHARE_SHARED 0x00000002 +#define SCARD_SHARE_DIRECT 0x00000003 + +/* see [MS-RDPESC] 2.2.5 protocol identifier - Table A */ +#define SCARD_PROTOCOL_UNDEFINED 0x00000000 +#define SCARD_PROTOCOL_T0 0x00000001 +#define SCARD_PROTOCOL_T1 0x00000002 +#define SCARD_PROTOCOL_Tx 0x00000003 +#define SCARD_PROTOCOL_RAW 0x00010000 + +/* see [MS-RDPESC] 2.2.5 protocol identifier - Table B */ +#define SCARD_PROTOCOL_DEFAULT 0x80000000 +#define SCARD_PROTOCOL_OPTIMAL 0x00000000 + typedef struct reader_state { char reader_name[128]; @@ -35,6 +50,22 @@ typedef struct reader_state tui32 event_state; tui32 atr_len; /* number of bytes in atr[] */ tui8 atr[36]; + + /* + * share mode flag, can be one of: + * SCARD_SHARE_EXCLUSIVE app not willing to share smartcard with other apps + * SCARD_SHARE_SHARED app willing to share smartcard with other apps + * SCARD_SHARE_DIRECT app demands direct control of smart card, hence + * it is not available to other readers + */ + tui32 shared_mode_flag; + + /* + * This field MUST have a value from Table A which is logically + * OR'ed with a value from Table B. + */ + tui32 preferred_protocol; + } READER_STATE; void scard_device_announce(tui32 device_id); @@ -47,4 +78,7 @@ int APP_CC scard_send_irp_list_readers(struct trans *con); int APP_CC scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); + +int APP_CC scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs); + #endif /* end #ifndef _SMARTCARD_C */ From edf483ecb66eff4cc378ea4c3ebba3410947ebe7 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 14 Sep 2013 12:57:34 -0700 Subject: [PATCH 17/32] chansrv: work on smartcard --- sesman/chansrv/smartcard.c | 48 ++++++--- sesman/chansrv/smartcard_pcsc.c | 184 +++++++++++++++++++++++++++++--- sesman/chansrv/smartcard_pcsc.h | 28 +++-- 3 files changed, 225 insertions(+), 35 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 78a47ba0..a0e15e6e 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -644,6 +644,9 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, int bytes; int i; int len; + int num_chars; + int index; + twchar w_reader_name[100]; if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -672,26 +675,45 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, for (i = 0; i < num_readers; i++) { rs = &rsa[i]; - xstream_wr_u32_le(s, 0); /* unused */ xstream_wr_u32_le(s, rs->current_state); xstream_wr_u32_le(s, rs->event_state); xstream_wr_u32_le(s, rs->atr_len); - xstream_copyin(s, rs->atr, rs->atr_len); - xstream_wr_u32_le(s, 0); /* unused */ + xstream_copyin(s, rs->atr, 33); + out_uint8s(s, 3); } - /* insert card reader names */ - for (i = 0; i < num_readers; i++) + if (wide) { - rs = &rsa[i]; - len = strlen(rs->reader_name); - - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, 0); /* unused */ - xstream_wr_u32_le(s, len); - xstream_copyin(s, rs->reader_name, len); - xstream_wr_u32_le(s, 0); /* null terminate */ + /* insert card reader names */ + for (i = 0; i < num_readers; i++) + { + rs = &rsa[i]; + num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, num_chars); + for (index = 0; index < num_chars; index++) + { + xstream_wr_u16_le(s, w_reader_name[index]); + } + } + } + else + { + /* insert card reader names */ + for (i = 0; i < num_readers; i++) + { + rs = &rsa[i]; + num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, 0); /* unused */ + xstream_wr_u32_le(s, num_chars); + for (index = 0; index < num_chars; index++) + { + xstream_wr_u8(s, w_reader_name[index]); + } + } } /* get stream len */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 5d1be106..7fe75956 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -31,6 +31,7 @@ #include "irp.h" #include "devredir.h" #include "trans.h" +#include "chansrv.h" #if PCSC_STANDIN @@ -40,7 +41,7 @@ { \ if (_level < LLOG_LEVEL) \ { \ - g_write("chansrv:smartcard [%10.10u]: ", g_time3()); \ + g_write("chansrv:smartcard_pcsc [%10.10u]: ", g_time3()); \ g_writeln _args ; \ } \ } \ @@ -95,8 +96,12 @@ struct pubReaderStatesList #define PCSCLITE_MAX_READERS_CONTEXTS 16 +static int g_num_readers = 0; +/* pcsc list */ static struct pubReaderStatesList - g_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; + g_pcsc_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; +/* rdp list */ +static READER_STATE g_xrdp_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; struct wait_reader_state_change { @@ -104,8 +109,11 @@ struct wait_reader_state_change tui32 rv; }; -#define XRDP_PCSC_STATE_NONE 0 -#define XRDP_PCSC_STATE_GOT_RSC 1 +#define XRDP_PCSC_STATE_NONE 0 +#define XRDP_PCSC_STATE_GOT_RSC (1 << 0) /* read state change */ +#define XRDP_PCSC_STATE_GOT_EC (1 << 1) /* establish context */ +#define XRDP_PCSC_STATE_GOT_LR (1 << 2) /* list readers */ +#define XRDP_PCSC_STATE_GOT_RC (1 << 3) /* release context */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -166,6 +174,12 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) struct establish_struct in_es; LLOGLN(0, ("scard_process_establish_context:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) + { + LLOGLN(0, ("scard_process_establish_context: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC; in_uint8a(in_s, &in_es, sizeof(in_es)); LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", in_es.dwScope)); @@ -183,6 +197,12 @@ scard_function_establish_context_return(struct trans *con, int context) LLOGLN(0, ("scard_function_establish_context_return: context %d", context)); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) + { + LLOGLN(0, ("scard_function_establish_context_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; out_es.dwScope = 0; out_es.hContext = context; out_es.rv = SCARD_S_SUCCESS; @@ -204,6 +224,9 @@ scard_process_release_context(struct stream *in_s) LLOGLN(0, ("scard_process_release_context:")); in_uint8a(in_s, &in_rs, sizeof(in_rs)); LLOGLN(0, ("scard_process_release_context: hContext %d", in_rs.hContext)); + + /* TODO: use XRDP_PCSC_STATE_GOT_RC */ + out_rs.hContext = in_rs.hContext; out_rs.rv = SCARD_S_SUCCESS; out_s = trans_get_out_s(g_con, 8192); @@ -238,10 +261,26 @@ scard_process_version(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_get_readers_state(struct stream *in_s) +scard_process_get_readers_state(struct trans *con, struct stream *in_s) { + //struct stream *out_s; + LLOGLN(0, ("scard_process_get_readers_state:")); - scard_send_irp_list_readers(g_con); + + //out_s = trans_get_out_s(con, 8192); + //out_uint8a(out_s, g_pcsc_reader_states, sizeof(g_pcsc_reader_states)); + //s_mark_end(out_s); + //return trans_force_write(con); + + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) + { + LLOGLN(0, ("scard_process_get_readers_state: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; + + scard_send_irp_list_readers(con); + return 0; } @@ -253,9 +292,55 @@ scard_function_list_readers_return(struct trans *con, int len) { struct stream *out_s; + int chr; + int readers; + int rn_index; + char reader_name[100]; g_hexdump(in_s->p, len); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0) + { + LLOGLN(0, ("scard_function_list_readers_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; + + in_uint8s(in_s, 28); + len -= 28; + in_uint32_le(in_s, len); + g_writeln("len %d", len); + rn_index = 0; + readers = 1; + while (len > 0) + { + in_uint16_le(in_s, chr); + len -= 2; + if (chr == 0) + { + if (reader_name[0] != 0) + { + g_writeln("1 %s", reader_name); + readers++; + } + reader_name[0] = 0; + rn_index = 0; + } + else + { + reader_name[rn_index] = chr; + rn_index++; + } + } + if (rn_index > 0) + { + if (reader_name[0] != 0) + { + g_writeln("2 %s", reader_name); + readers++; + } + } +#if 0 g_strcpy(g_reader_states[0].readerName, "ACS AET65 00 00"); g_reader_states[0].readerState = 0x14; g_reader_states[0].cardProtocol = 3; @@ -278,6 +363,8 @@ scard_function_list_readers_return(struct trans *con, out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); s_mark_end(out_s); return trans_force_write(con); +#endif + return 0; } /*****************************************************************************/ @@ -314,20 +401,44 @@ scard_process_read_state_change(struct trans *con, struct stream *in_s) { struct wait_reader_state_change in_rsc; struct stream *out_s; + int index; LLOGLN(0, ("scard_process_read_state_change:")); in_uint8a(in_s, &in_rsc, sizeof(in_rsc)); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) + { + LLOGLN(0, ("scard_process_read_state_change: opps")); + return 0; + } + +#if 0 + for (index = 0; index < 16; index++) + { + //g_memcpy(rd[index].reader_name, g_pcsc_reader_states[index].readerName, 99); + g_strncpy(rd[index].reader_name, "Gemalto PC Twin Reader 00 00", 99); + rd[index].current_state = g_pcsc_reader_states[index].readerState; + rd[index].event_state = g_pcsc_reader_states[index].eventCounter; + rd[index].atr_len = g_pcsc_reader_states[index].cardAtrLength; + g_memcpy(rd[index].atr, g_pcsc_reader_states[index].cardAtr, 33); + } +#endif + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RSC; + scard_send_irp_get_status_change(con, 1, in_rsc.timeOut, g_num_readers, + g_xrdp_reader_states); + LLOGLN(0, ("scard_process_read_state_change: timeout %d rv %d", in_rsc.timeOut, in_rsc.rv)); + add_timeout(in_rsc.timeOut, scard_read_state_chage_timeout, con); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_stop_read_state_change(struct stream *in_s) +scard_process_stop_read_state_change(struct trans *con, struct stream *in_s) { struct wait_reader_state_change in_rsc; struct wait_reader_state_change out_rsc; @@ -339,13 +450,13 @@ scard_process_stop_read_state_change(struct stream *in_s) in_rsc.timeOut, in_rsc.rv)); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) { - out_s = trans_get_out_s(g_con, 8192); + out_s = trans_get_out_s(con, 8192); out_rsc.timeOut = in_rsc.timeOut; out_rsc.rv = SCARD_S_SUCCESS; out_uint8a(out_s, &out_rsc, sizeof(out_rsc)); g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC; s_mark_end(out_s); - return trans_force_write(g_con); + return trans_force_write(con); } else { @@ -354,6 +465,54 @@ scard_process_stop_read_state_change(struct stream *in_s) return 0; } +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_function_get_status_change_return(struct trans *con, + struct stream *in_s, + int len) +{ + struct stream *out_s; + int num_readers; + int index; + int current_state; + int event_state; + int atr_len; + char atr[36]; + + LLOGLN(0, ("scard_function_get_status_change_return:")); + + //g_hexdump(in_s->p, len); + + in_uint8s(in_s, 28); + in_uint32_le(in_s, num_readers); + LLOGLN(0, (" num_reader %d", num_readers)); + + g_num_readers = num_readers; + + for (index = 0; index < num_readers; index++) + { + in_uint32_le(in_s, current_state); + in_uint32_le(in_s, event_state); + in_uint32_le(in_s, atr_len); + in_uint8a(in_s, atr, 36); + LLOGLN(0, (" current_state 0x%8.8x event_state 0x%8.8x " + "atr_len 0x%8.8x", current_state, event_state, atr_len)); + g_xrdp_reader_states[index].current_state = current_state; + g_xrdp_reader_states[index].event_state = event_state; + g_xrdp_reader_states[index].atr_len = atr_len; + g_memcpy(g_xrdp_reader_states[index].atr, atr, 36); + + } + //out_s = trans_get_out_s(con, 8192); + //out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); + //s_mark_end(out_s); + //return trans_force_write(con); + + return 0; + +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -436,7 +595,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x12: /* CMD_GET_READERS_STATE */ LLOGLN(0, ("scard_process_msg: CMD_GET_READERS_STATE")); - rv = scard_process_get_readers_state(in_s); + rv = scard_process_get_readers_state(con, in_s); break; case 0x13: /* CMD_WAIT_READER_STATE_CHANGE */ LLOGLN(0, ("scard_process_msg: CMD_WAIT_READER_STATE_CHANGE")); @@ -444,7 +603,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x14: /* CMD_STOP_WAITING_READER_STATE_CHANGE */ LLOGLN(0, ("scard_process_msg: CMD_STOP_WAITING_READER_STATE_CHANGE")); - rv = scard_process_stop_read_state_change(in_s); + rv = scard_process_stop_read_state_change(con, in_s); break; default: LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command)); @@ -531,7 +690,8 @@ scard_pcsc_init(void) int index; LLOGLN(0, ("scard_pcsc_init:")); - g_memset(g_reader_states, 0, sizeof(g_reader_states)); + g_memset(g_pcsc_reader_states, 0, sizeof(g_pcsc_reader_states)); + g_memset(g_xrdp_reader_states, 0, sizeof(g_xrdp_reader_states)); if (g_lis == 0) { g_lis = trans_create(2, 8192, 8192); diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 1c8c6d7b..ef1ccd68 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -24,15 +24,23 @@ #ifndef _SMARTCARD_PCSC_H #define _SMARTCARD_PCSC_H -int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); -int APP_CC scard_pcsc_check_wait_objs(void); -int APP_CC scard_pcsc_init(void); -int APP_CC scard_pcsc_deinit(void); - -int APP_CC scard_function_establish_context_return(struct trans *con, int context); - -int APP_CC scard_function_list_readers_return(struct trans *con, - struct stream *in_s, - int len); +int APP_CC +scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); +int APP_CC +scard_pcsc_check_wait_objs(void); +int APP_CC +scard_pcsc_init(void); +int APP_CC +scard_pcsc_deinit(void); +int APP_CC +scard_function_establish_context_return(struct trans *con, int context); +int APP_CC +scard_function_list_readers_return(struct trans *con, + struct stream *in_s, + int len); +int APP_CC +scard_function_get_status_change_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 68371ed3618601bac3202a1180a73193eabfcd40 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 14 Sep 2013 12:59:42 -0700 Subject: [PATCH 18/32] chansrv: work on smartcard --- sesman/chansrv/pcsc/Makefile | 12 ++ sesman/chansrv/pcsc/xrdp_pcsc.c | 316 ++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 sesman/chansrv/pcsc/Makefile create mode 100644 sesman/chansrv/pcsc/xrdp_pcsc.c diff --git a/sesman/chansrv/pcsc/Makefile b/sesman/chansrv/pcsc/Makefile new file mode 100644 index 00000000..483151f2 --- /dev/null +++ b/sesman/chansrv/pcsc/Makefile @@ -0,0 +1,12 @@ + +OBJS = xrdp_pcsc.o + +CFLAGS = -Wall -O2 -fPIC + +all: libpcsclite.so + +libpcsclite.so: $(OBJS) + $(CC) $(LDFLAGS) -shared -o libpcsclite.so $(OBJS) + +clean: + rm -f $(OBJS) libpcsclite.so diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c new file mode 100644 index 00000000..f41efbf1 --- /dev/null +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -0,0 +1,316 @@ + +#include +#include +#include +#include +#include + +#define PCSC_API + +typedef unsigned char BYTE; +typedef BYTE *LPBYTE; +typedef unsigned int LONG; +typedef unsigned int DWORD; +typedef DWORD *LPDWORD; +typedef const void *LPCVOID; +typedef const char *LPCSTR; +typedef char *LPSTR; +typedef void *LPVOID; +typedef const BYTE *LPCBYTE; + +typedef LONG SCARDCONTEXT; +typedef SCARDCONTEXT *LPSCARDCONTEXT; + +typedef LONG SCARDHANDLE; +typedef SCARDHANDLE *LPSCARDHANDLE; + +#define MAX_ATR_SIZE 33 + +typedef struct _SCARD_READERSTATE +{ + const char *szReader; + void *pvUserData; + DWORD dwCurrentState; + DWORD dwEventState; + DWORD cbAtr; + unsigned char rgbAtr[MAX_ATR_SIZE]; +} SCARD_READERSTATE, *LPSCARD_READERSTATE; + +typedef struct _SCARD_IO_REQUEST +{ + unsigned long dwProtocol; + unsigned long cbPciLength; +} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; + +#define LLOG_LEVEL 11 +#define LLOGLN(_level, _args) \ + do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) + +#define SCARD_S_SUCCESS 0x00000000 +#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) + +static int g_fd = 0; /* unix domain socket */ + +/*****************************************************************************/ +static int +get_display_num_from_display(char *display_text) +{ + int rv; + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + char host[256]; + char disp[256]; + char scre[256]; + + memset(host, 0, 256); + memset(disp, 0, 256); + memset(scre, 0, 256); + + index = 0; + host_index = 0; + disp_index = 0; + scre_index = 0; + mode = 0; + + while (display_text[index] != 0) + { + if (display_text[index] == ':') + { + mode = 1; + } + else if (display_text[index] == '.') + { + mode = 2; + } + else if (mode == 0) + { + host[host_index] = display_text[index]; + host_index++; + } + else if (mode == 1) + { + disp[disp_index] = display_text[index]; + disp_index++; + } + else if (mode == 2) + { + scre[scre_index] = display_text[index]; + scre_index++; + } + index++; + } + host[host_index] = 0; + disp[disp_index] = 0; + scre[scre_index] = 0; + rv = atoi(disp); + return 0; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, + LPSCARDCONTEXT phContext) +{ + int sck; + int dis; + char *xrdp_session; + char *xrdp_display; + char *home_str; + char text[256]; + + LLOGLN(10, ("SCardEstablishContext:")); + xrdp_session = getenv("XRDP_SESSION"); + if (xrdp_session == NULL) + { + /* XRDP_SESSION must be set */ + return SCARD_F_INTERNAL_ERROR; + } + xrdp_display = getenv("DISPLAY"); + if (xrdp_display == NULL) + { + /* DISPLAY must be set */ + return SCARD_F_INTERNAL_ERROR; + } + home_str = getenv("HOME"); + if (home_str == NULL) + { + /* HOME must be set */ + return SCARD_F_INTERNAL_ERROR; + } + dis = get_display_num_from_display(xrdp_display); + if (dis < 10) + { + /* DISPLAY must be > 9 */ + return SCARD_F_INTERNAL_ERROR; + } + if (g_fd == 0) + { + g_fd = socket(PF_LOCAL, SOCK_STREAM, 0); + snprintf(text, 255, "%s/.pcsc%d", home_str, dis); + } + if (g_fd == 0) + { + return SCARD_F_INTERNAL_ERROR; + } + *phContext = 0; + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardReleaseContext(SCARDCONTEXT hContext) +{ + LLOGLN(10, ("SCardReleaseContext:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardIsValidContext(SCARDCONTEXT hContext) +{ + LLOGLN(10, ("SCardIsValidContext:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, + DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) +{ + LLOGLN(10, ("SCardConnect:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, + DWORD dwPreferredProtocols, DWORD dwInitialization, + LPDWORD pdwActiveProtocol) +{ + LLOGLN(10, ("SCardReconnect:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LLOGLN(10, ("SCardDisconnect:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardBeginTransaction(SCARDHANDLE hCard) +{ + LLOGLN(0, ("SCardBeginTransaction:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LLOGLN(10, ("SCardEndTransaction:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, + LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LLOGLN(10, ("SCardStatus:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, + LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) +{ + LLOGLN(10, ("SCardGetStatusChange:")); + LLOGLN(10, ("SCardGetStatusChange: dwTimeout %d cReaders %d", + dwTimeout, cReaders)); + memset(rgReaderStates, 0, sizeof(SCARD_READERSTATE)); + usleep(60000000); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, + DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, + LPDWORD lpBytesReturned) +{ + LLOGLN(10, ("SCardControl:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, + LPDWORD pcbRecvLength) +{ + LLOGLN(10, ("SCardTransmit:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, + LPDWORD pcchGroups) +{ + LLOGLN(10, ("SCardListReaderGroups:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, + LPDWORD pcchReaders) +{ + LLOGLN(10, ("SCardListReaders:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) +{ + LLOGLN(10, ("SCardFreeMemory:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardCancel(SCARDCONTEXT hContext) +{ + LLOGLN(10, ("SCardCancel:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, + LPDWORD pcbAttrLen) +{ + LLOGLN(10, ("SCardGetAttrib:")); + return SCARD_S_SUCCESS; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, + DWORD cbAttrLen) +{ + LLOGLN(10, ("SCardSetAttrib:")); + return SCARD_S_SUCCESS; +} From a1352b62e34a1849d55188123335db526b51d011 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sun, 15 Sep 2013 13:52:07 -0700 Subject: [PATCH 19/32] scard: added more messages --- sesman/chansrv/smartcard.c | 664 ++++++++++++++++++++++++++++++++++++- sesman/chansrv/smartcard.h | 5 + 2 files changed, 658 insertions(+), 11 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index a0e15e6e..7d5cb39e 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -113,7 +113,8 @@ do \ #define SCARD_IOCTL_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */ #define SCARD_IOCTL_END_TRANSACTION 0x000900C0 /* EndTransaction */ #define SCARD_IOCTL_STATE 0x000900C4 /* State */ -#define SCARD_IOCTL_STATUS 0x000900C8 /* StatusA */ +#define SCARD_IOCTL_STATUS_A 0x000900C8 /* StatusA */ +#define SCARD_IOCTL_STATUS_W 0x000900CC /* StatusW */ #define SCARD_IOCTL_TRANSMIT 0x000900D0 /* Transmit */ #define SCARD_IOCTL_CONTROL 0x000900D4 /* Control */ #define SCARD_IOCTL_GETATTRIB 0x000900D8 /* GetAttrib */ @@ -126,6 +127,12 @@ do \ #define SCARD_SCOPE_TERMINAL 0x00000001 #define SCARD_SCOPE_SYSTEM 0x00000002 +/* disposition - action to take on card */ +#define SCARD_LEAVE_CARD 0x00000000 +#define SCARD_RESET_CARD 0x00000001 +#define SCARD_UNPOWER_CARD 0x00000002 +#define SCARD_EJECT_CARD 0x00000003 + #define MAX_SMARTCARDS 16 /* stores info about a smart card */ @@ -155,12 +162,17 @@ static int scard_add_new_device(tui32 device_id); static int scard_get_free_slot(void); static void scard_release_resources(void); static void scard_send_EstablishContext(IRP* irp, int scope); +static void scard_send_ReleaseContext(IRP* irp); static void scard_send_ListReaders(IRP* irp, int wide); static void scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs); +static void scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); +static void scard_send_EndTransaction(IRP* irp, tui32 sc_handle); +static void scard_send_Status(IRP* irp, int wide, tui32 sc_handle); +static void scard_send_Disconnect(IRP* irp, tui32 sc_handle); /****************************************************************************** ** local callbacks into this module ** @@ -170,6 +182,10 @@ static void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); +static void scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + static void scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); @@ -182,6 +198,22 @@ static void scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); +static void scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + +static void scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + +static void scard_handle_Status_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + +static void scard_handle_Disconnect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + /****************************************************************************** ** ** ** externally accessible functions, defined in smartcard.h ** @@ -274,6 +306,33 @@ scard_send_irp_establish_context(struct trans *con, int scope) return 0; } +/** + * Release a previously established Smart Card context + *****************************************************************************/ +int +APP_CC scard_send_release_context(struct trans *con) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_ReleaseContext_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_ReleaseContext(irp); + + return 0; +} + /** * *****************************************************************************/ @@ -364,6 +423,127 @@ scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs) return 0; } +/** + * Lock smart card reader for exclusive access for specified smart + * card reader handle. + * + * @param con connection to client + *****************************************************************************/ +int +APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_BeginTransaction_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_BeginTransaction(irp, sc_handle); + + return 0; +} + +/** + * Release a smart card reader after being locked by a previously + * successful call to Begin Transaction + * + * @param con connection to client + * @param sc_handle handle to smartcard + *****************************************************************************/ +int +APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_EndTransaction_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_EndTransaction(irp, sc_handle); + + return 0; +} + +/** + * Get the status of a connection for a valid smart card reader handle + * + * @param con connection to client + * @param wide TRUE if unicode string + *****************************************************************************/ +int +APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_Status_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_Status(irp, wide, sc_handle); + + return 0; +} + +/** + * Release a smart card reader handle that was acquired in ConnectA/ConnectW + * + * @param con connection to client + * @param sc_handle handle to smartcard + *****************************************************************************/ +int +APP_CC scard_send_disconnect(struct trans *con, tui32 sc_handle) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_Disconnect_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_Disconnect(irp, sc_handle); + + return 0; +} + /****************************************************************************** ** ** ** static functions local to this file ** @@ -532,6 +712,58 @@ scard_send_EstablishContext(IRP *irp, int scope) xstream_free(s); } +/** + * Release a previously established Smart Card context + *****************************************************************************/ +static void +scard_send_ReleaseContext(IRP* irp) +{ + /* see [MS-RDPESC] 3.1.4.2 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RELEASE_CONTEXT)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 4 bytes len - don't know what this is, zero for now + * 12 bytes unused + * u32 4 bytes context len + * 4 bytes context + */ + + xstream_wr_u32_le(s, 0); + xstream_seek(s, 12); + + /* insert context */ + xstream_wr_u32_le(s, sc->Context_len); + xstream_copyin(s, sc->Context, sc->Context_len); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + /** * *****************************************************************************/ @@ -551,8 +783,8 @@ scard_send_ListReaders(IRP *irp, int wide) return; } - ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W : - SCARD_IOCTL_LIST_READERS_A; + ioctl = (wide) ? SCARD_IOCTL_LIST_READERS_W : + SCARD_IOCTL_LIST_READERS_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) return; @@ -654,8 +886,8 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, return; } - ioctl = (wide > 0) ? SCARD_IOCTL_GET_STATUS_CHANGE_W : - SCARD_IOCTL_GET_STATUS_CHANGE_A; + ioctl = (wide) ? SCARD_IOCTL_GET_STATUS_CHANGE_W : + SCARD_IOCTL_GET_STATUS_CHANGE_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) return; @@ -744,6 +976,9 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) tui32 ioctl; int bytes; int len; + int num_chars; + int index; + twchar w_reader_name[100]; if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -751,8 +986,8 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) return; } - ioctl = (wide > 0) ? SCARD_IOCTL_CONNECT_A : - SCARD_IOCTL_CONNECT_W; + ioctl = (wide) ? SCARD_IOCTL_CONNECT_W : + SCARD_IOCTL_CONNECT_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) return; @@ -764,7 +999,7 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) * 20 bytes padding * u32 4 bytes len 8, LE, v1 * u32 4 bytes filler - * 20 bytes unused (s->p is currently pointed here) + * 20 bytes unused (s->p currently pointed here at unused[0]) * u32 4 bytes dwShareMode * u32 4 bytes dwPreferredProtocol * xx bytes reader name @@ -777,9 +1012,18 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) xstream_wr_u32_le(s, rs->preferred_protocol); /* insert reader name */ - /* LK_TODO need to handle unicode */ - len = strlen(rs->reader_name); - xstream_copyin(s, rs->reader_name, len); + num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, num_chars); + if (wide) + { + for (index = 0; index < num_chars; index++) + xstream_wr_u16_le(s, w_reader_name[index]); + } + else + { + for (index = 0; index < num_chars; index++) + xstream_wr_u8(s, w_reader_name[index]); + } /* insert context */ xstream_wr_u32_le(s, sc->Context_len); @@ -796,6 +1040,244 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) xstream_free(s); } +/** + * Lock smart card reader for exclusive access for specified smart + * card reader handle. + * + * @param con connection to client + *****************************************************************************/ +static void +scard_send_BeginTransaction(IRP* irp, tui32 sc_handle) +{ + /* see [MS-RDPESC] 4.9 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_BEGIN_TRANSACTION)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 36 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes len of sc_handle + * 4 bytes sc_handle + */ + + xstream_seek(s, 36); + + /* insert handle */ + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, sc_handle); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + +/** + * Release a smart card reader after being locked by a previously + * successful call to Begin Transaction + * + * @param con connection to client + * @param sc_handle handle to smartcard + *****************************************************************************/ +static void +scard_send_EndTransaction(IRP* irp, tui32 sc_handle) +{ + /* see [MS-RDPESC] 3.1.4.32 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_END_TRANSACTION)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 24 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes disposition + * 8 unused + * u32 4 bytes length of sc_handle + * 4 bytes sc_handle + */ + + xstream_seek(s, 24); + xstream_wr_u32_le(s, SCARD_LEAVE_CARD); + xstream_seek(s, 8); + + /* insert handle */ + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, sc_handle); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + +/** + * Get the status of a connection for a valid smart card reader handle + * + * @param con connection to client + * @param wide TRUE if unicode string + *****************************************************************************/ +static void +scard_send_Status(IRP* irp, int wide, tui32 sc_handle) +{ + /* see [MS-RDPESC] 2.2.2.18 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + tui32 ioctl; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + ioctl = (wide) ? SCARD_IOCTL_CONNECT_W : + SCARD_IOCTL_CONNECT_A; + + if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 28 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes reader len + * u32 4 bytes ATR len + * 8 bytes unused + * u32 4 bytes len of sc_handle + * 4 bytes sc_handle + * 4 bytes unused + */ + + xstream_seek(s, 28); + xstream_wr_u32_le(s, -1); /* readerLen, see [MS-RDPESC] 4.11 */ + xstream_wr_u32_le(s, 36); /* atrLen, see [MS-RDPESC] 4.11 */ + xstream_seek(s, 8); + + /* insert sc_handle */ + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, sc_handle); + + xstream_wr_u32_le(s, 0); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + +/** + * Release a smart card reader handle that was acquired in ConnectA/ConnectW + * + * @param con connection to client + * @param sc_handle handle to smartcard + *****************************************************************************/ +static void +scard_send_Disconnect(IRP* irp, tui32 sc_handle) +{ + /* see [MS-RDPESC] 3.1.4.30 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_DISCONNECT)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 24 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes disposition + * u32 4 bytes context len + * 4 bytes context + * u32 4 bytes length of sc_handle + * 4 bytes sc_handle + */ + + xstream_seek(s, 24); + xstream_wr_u32_le(s, SCARD_RESET_CARD); + + /* insert context */ + xstream_wr_u32_le(s, sc->Context_len); + xstream_copyin(s, sc->Context, sc->Context_len); + + /* insert handle */ + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, sc_handle); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + /****************************************************************************** ** ** ** local callbacks into this module ** @@ -868,6 +1350,38 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, log_debug("leaving"); } +/** + * + *****************************************************************************/ +static void +scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("ReleaseContext failed, device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + /** * *****************************************************************************/ @@ -965,3 +1479,131 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, log_debug("leaving"); } + +/** + * + *****************************************************************************/ +static void +scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("BeginTransaction failed, device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + +/** + * + *****************************************************************************/ +static void +scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("EndTransaction failed, device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + +/** + * + *****************************************************************************/ +static void +scard_handle_Status_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("StatusCall failed, device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + +/** + * + *****************************************************************************/ +static void +scard_handle_Disconnect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("Disconnect failed, device not usable"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 8352a01e..046bb14a 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -74,11 +74,16 @@ int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); +int APP_CC scard_send_release_context(struct trans *con); int APP_CC scard_send_irp_list_readers(struct trans *con); int APP_CC scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); int APP_CC scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs); +int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); +int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle); +int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle); +int APP_CC scard_send_disconnect(struct trans *con, tui32 sc_handle); #endif /* end #ifndef _SMARTCARD_C */ From 0ef89c02abaaf51cc0875153ef9d7e673889a1c1 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sun, 15 Sep 2013 15:20:16 -0700 Subject: [PATCH 20/32] scard: changed the way we store and pass context --- sesman/chansrv/smartcard.c | 86 ++++++++++++++++----------------- sesman/chansrv/smartcard.h | 13 +++-- sesman/chansrv/smartcard_pcsc.c | 11 +++-- sesman/chansrv/smartcard_pcsc.h | 30 +++++------- 4 files changed, 70 insertions(+), 70 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 7d5cb39e..f694484f 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -139,8 +139,6 @@ do \ typedef struct smartcard { tui32 DeviceId; - char Context[16]; /* opaque context; save as passed to us */ - int Context_len; /* Context len in bytes */ } SMARTCARD; /* globals */ @@ -162,17 +160,20 @@ static int scard_add_new_device(tui32 device_id); static int scard_get_free_slot(void); static void scard_release_resources(void); static void scard_send_EstablishContext(IRP* irp, int scope); -static void scard_send_ReleaseContext(IRP* irp); -static void scard_send_ListReaders(IRP* irp, int wide); +static void scard_send_ReleaseContext(IRP* irp, tui32 context); +static void scard_send_ListReaders(IRP* irp, tui32 context, int wide); -static void scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, - tui32 num_readers, READER_STATE* rsa); +static void scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, + tui32 timeout, tui32 num_readers, + READER_STATE* rsa); + +static void scard_send_Connect(IRP* irp, tui32 context, int wide, + READER_STATE* rs); -static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs); static void scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); static void scard_send_EndTransaction(IRP* irp, tui32 sc_handle); static void scard_send_Status(IRP* irp, int wide, tui32 sc_handle); -static void scard_send_Disconnect(IRP* irp, tui32 sc_handle); +static void scard_send_Disconnect(IRP* irp, tui32 context, tui32 sc_handle); /****************************************************************************** ** local callbacks into this module ** @@ -310,7 +311,7 @@ scard_send_irp_establish_context(struct trans *con, int scope) * Release a previously established Smart Card context *****************************************************************************/ int -APP_CC scard_send_release_context(struct trans *con) +APP_CC scard_send_release_context(struct trans *con, tui32 context) { IRP *irp; @@ -328,7 +329,7 @@ APP_CC scard_send_release_context(struct trans *con) irp->user_data = con; /* send IRP to client */ - scard_send_ReleaseContext(irp); + scard_send_ReleaseContext(irp, context); return 0; } @@ -337,7 +338,7 @@ APP_CC scard_send_release_context(struct trans *con) * *****************************************************************************/ int APP_CC -scard_send_irp_list_readers(struct trans *con) +scard_send_irp_list_readers(struct trans *con, tui32 context, int wide) { IRP *irp; @@ -354,7 +355,7 @@ scard_send_irp_list_readers(struct trans *con) irp->user_data = con; /* send IRP to client */ - scard_send_ListReaders(irp, 1); + scard_send_ListReaders(irp, context, wide); return 0; } @@ -369,8 +370,9 @@ scard_send_irp_list_readers(struct trans *con) * @param rsa array of READER_STATEs *****************************************************************************/ int APP_CC -scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, - tui32 num_readers, READER_STATE* rsa) +scard_send_irp_get_status_change(struct trans *con, tui32 context, int wide, + tui32 timeout, tui32 num_readers, + READER_STATE* rsa) { IRP *irp; @@ -388,7 +390,7 @@ scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, irp->user_data = con; /* send IRP to client */ - scard_send_GetStatusChange(irp, wide, timeout, num_readers, rsa); + scard_send_GetStatusChange(irp, context, wide, timeout, num_readers, rsa); return 0; } @@ -400,7 +402,8 @@ scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs) +scard_send_irp_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs) { IRP *irp; @@ -418,7 +421,7 @@ scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs) irp->user_data = con; /* send IRP to client */ - scard_send_Connect(irp, wide, rs); + scard_send_Connect(irp, context, wide, rs); return 0; } @@ -521,7 +524,7 @@ APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ int -APP_CC scard_send_disconnect(struct trans *con, tui32 sc_handle) +APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) { IRP *irp; @@ -539,7 +542,7 @@ APP_CC scard_send_disconnect(struct trans *con, tui32 sc_handle) irp->user_data = con; /* send IRP to client */ - scard_send_Disconnect(irp, sc_handle); + scard_send_Disconnect(irp, context, sc_handle); return 0; } @@ -716,7 +719,7 @@ scard_send_EstablishContext(IRP *irp, int scope) * Release a previously established Smart Card context *****************************************************************************/ static void -scard_send_ReleaseContext(IRP* irp) +scard_send_ReleaseContext(IRP* irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.2 */ @@ -750,8 +753,8 @@ scard_send_ReleaseContext(IRP* irp) xstream_seek(s, 12); /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); /* get stream len */ bytes = xstream_len(s); @@ -768,7 +771,7 @@ scard_send_ReleaseContext(IRP* irp) * *****************************************************************************/ static void APP_CC -scard_send_ListReaders(IRP *irp, int wide) +scard_send_ListReaders(IRP *irp, tui32 context, int wide) { /* see [MS-RDPESC] 2.2.2.4 */ @@ -793,8 +796,8 @@ scard_send_ListReaders(IRP *irp, int wide) xstream_seek(s, 28); /* freerdp does not use this */ /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); xstream_wr_u32_le(s, 36); /* length of mszGroups */ xstream_wr_u16_le(s, 0x0053); @@ -863,7 +866,7 @@ scard_send_ListReaders(IRP *irp, int wide) * @param rsa array of READER_STATEs *****************************************************************************/ static void -scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, +scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa) { /* see [MS-RDPESC] 2.2.2.11 for ASCII */ @@ -898,8 +901,8 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, xstream_wr_u32_le(s, 0); /* unused */ /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); xstream_wr_u32_le(s, 0); /* unused */ @@ -966,7 +969,8 @@ scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, * @param wide TRUE if unicode string * @param rs reader state *****************************************************************************/ -static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) +static void scard_send_Connect(IRP* irp, tui32 context, int wide, + READER_STATE* rs) { /* see [MS-RDPESC] 2.2.2.13 for ASCII */ /* see [MS-RDPESC] 2.2.2.14 for Wide char */ @@ -1026,8 +1030,8 @@ static void scard_send_Connect(IRP* irp, int wide, READER_STATE* rs) } /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); /* get stream len */ bytes = xstream_len(s); @@ -1224,7 +1228,7 @@ scard_send_Status(IRP* irp, int wide, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ static void -scard_send_Disconnect(IRP* irp, tui32 sc_handle) +scard_send_Disconnect(IRP* irp, tui32 context, tui32 sc_handle) { /* see [MS-RDPESC] 3.1.4.30 */ @@ -1260,8 +1264,8 @@ scard_send_Disconnect(IRP* irp, tui32 sc_handle) xstream_wr_u32_le(s, SCARD_RESET_CARD); /* insert context */ - xstream_wr_u32_le(s, sc->Context_len); - xstream_copyin(s, sc->Context, sc->Context_len); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); /* insert handle */ xstream_wr_u32_le(s, 4); @@ -1292,6 +1296,7 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { + tui32 context; tui32 len; int tmp; SMARTCARD *sc; @@ -1327,22 +1332,17 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, xstream_rd_u32_le(s, tmp); /* ?? */ xstream_rd_u32_le(s, tmp); /* ?? */ xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, len); /* len of context in bytes */ - sc->Context_len = len; - xstream_copyout(sc->Context, s, len); + xstream_rd_u32_le(s, len); /* len of context in bytes, always 4 */ + xstream_rd_u32_le(s, context); if (LOG_LEVEL == LOG_DEBUG) - { - log_debug("dumping context (%d bytes)", sc->Context_len); - g_hexdump(sc->Context, sc->Context_len); - } + log_debug("dumping: )", context); // LK_TODO delete this //irp->callback = scard_handle_ListReaders_Return; - //scard_send_ListReaders(irp, 1); scard_function_establish_context_return((struct trans *) (irp->user_data), - ((int*)(sc->Context))[0]); + context); devredir_irp_delete(irp); diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 046bb14a..1927b2e0 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -74,16 +74,19 @@ int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); -int APP_CC scard_send_release_context(struct trans *con); -int APP_CC scard_send_irp_list_readers(struct trans *con); +int APP_CC scard_send_release_context(struct trans *con, tui32 context); +int APP_CC scard_send_irp_list_readers(struct trans *con, tui32 context, int wide); -int APP_CC scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, +int APP_CC scard_send_irp_get_status_change(struct trans *con, tui32 context, + int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); -int APP_CC scard_send_irp_connect(struct trans *con, int wide, READER_STATE* rs); +int APP_CC scard_send_irp_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs); + int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle); -int APP_CC scard_send_disconnect(struct trans *con, tui32 sc_handle); +int APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle); #endif /* end #ifndef _SMARTCARD_C */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 7fe75956..2f11c517 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -23,6 +23,9 @@ * pcsc lib and daemon write struct on unix domain socket for communication */ +#define JAY_TODO_CONTEXT 0 +#define JAY_TODO_WIDE 1 + #define PCSC_STANDIN 1 #include "os_calls.h" @@ -190,7 +193,7 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_establish_context_return(struct trans *con, int context) +scard_function_establish_context_return(struct trans *con, tui32 context) { struct establish_struct out_es; struct stream *out_s; @@ -279,7 +282,7 @@ scard_process_get_readers_state(struct trans *con, struct stream *in_s) } g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; - scard_send_irp_list_readers(con); + scard_send_irp_list_readers(con, JAY_TODO_CONTEXT, JAY_TODO_WIDE); return 0; } @@ -424,7 +427,7 @@ scard_process_read_state_change(struct trans *con, struct stream *in_s) #endif g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RSC; - scard_send_irp_get_status_change(con, 1, in_rsc.timeOut, g_num_readers, + scard_send_irp_get_status_change(con, JAY_TODO_CONTEXT, 1, in_rsc.timeOut, g_num_readers, g_xrdp_reader_states); LLOGLN(0, ("scard_process_read_state_change: timeout %d rv %d", @@ -502,7 +505,7 @@ scard_function_get_status_change_return(struct trans *con, g_xrdp_reader_states[index].event_state = event_state; g_xrdp_reader_states[index].atr_len = atr_len; g_memcpy(g_xrdp_reader_states[index].atr, atr, 36); - + } //out_s = trans_get_out_s(con, 8192); //out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index ef1ccd68..fd842a80 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -24,23 +24,17 @@ #ifndef _SMARTCARD_PCSC_H #define _SMARTCARD_PCSC_H -int APP_CC -scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); -int APP_CC -scard_pcsc_check_wait_objs(void); -int APP_CC -scard_pcsc_init(void); -int APP_CC -scard_pcsc_deinit(void); -int APP_CC -scard_function_establish_context_return(struct trans *con, int context); -int APP_CC -scard_function_list_readers_return(struct trans *con, - struct stream *in_s, - int len); -int APP_CC -scard_function_get_status_change_return(struct trans *con, - struct stream *in_s, - int len); +int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); +int APP_CC scard_pcsc_check_wait_objs(void); +int APP_CC scard_pcsc_init(void); +int APP_CC scard_pcsc_deinit(void); +int APP_CC scard_function_establish_context_return(struct trans *con, tui32 context); + +int APP_CC scard_function_list_readers_return(struct trans *con, + struct stream *in_s, + int len); + +int APP_CC scard_function_get_status_change_return(struct trans *con, + struct stream *in_s, int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From b206de3314b33b1d3264271dba2daa080898aad5 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 16 Sep 2013 00:10:04 -0700 Subject: [PATCH 21/32] pcsc: work on pcsclite lib --- sesman/chansrv/pcsc/xrdp_pcsc.c | 537 +++++++++++++++++++++++++++++--- 1 file changed, 495 insertions(+), 42 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index f41efbf1..251fdd82 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -2,8 +2,14 @@ #include #include #include +#include +#include +#include +#include #include #include +#include +#include #define PCSC_API @@ -42,18 +48,40 @@ typedef struct _SCARD_IO_REQUEST unsigned long cbPciLength; } SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; -#define LLOG_LEVEL 11 +#define LLOG_LEVEL 5 #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) +#define SCARD_ESTABLISH_CONTEXT 0x01 +#define SCARD_RELEASE_CONTEXT 0x02 +#define SCARD_LIST_READERS 0x03 +#define SCARD_GET_STATUS_CHANGE 0x0C + #define SCARD_S_SUCCESS 0x00000000 #define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) -static int g_fd = 0; /* unix domain socket */ +#define SET_UINT32(_data, _offset, _val) do { \ + (((BYTE*)(_data)) + (_offset))[0] = ((_val) >> 0) & 0xff; \ + (((BYTE*)(_data)) + (_offset))[1] = ((_val) >> 8) & 0xff; \ + (((BYTE*)(_data)) + (_offset))[2] = ((_val) >> 16) & 0xff; \ + (((BYTE*)(_data)) + (_offset))[3] = ((_val) >> 24) & 0xff; } while (0) + +#define GET_UINT32(_data, _offset) \ + ((((BYTE*)(_data)) + (_offset))[0] << 0) | \ + ((((BYTE*)(_data)) + (_offset))[1] << 8) | \ + ((((BYTE*)(_data)) + (_offset))[2] << 16) | \ + ((((BYTE*)(_data)) + (_offset))[3] << 24) + +#define LMIN(_val1, _val2) (_val1) < (_val2) ? (_val1) : (_val2) +#define LMAX(_val1, _val2) (_val1) > (_val2) ? (_val1) : (_val2) + +static int g_sck = -1; /* unix domain socket */ + +static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; /*****************************************************************************/ static int -get_display_num_from_display(char *display_text) +get_display_num_from_display(const char *display_text) { int rv; int index; @@ -105,73 +133,233 @@ get_display_num_from_display(char *display_text) host[host_index] = 0; disp[disp_index] = 0; scre[scre_index] = 0; + LLOGLN(0, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]", + host, disp, scre)); rv = atoi(disp); - return 0; + return rv; } /*****************************************************************************/ -PCSC_API LONG -SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, - LPSCARDCONTEXT phContext) +static int +connect_to_chansrv(void) { - int sck; + int bytes; int dis; + int error; char *xrdp_session; char *xrdp_display; char *home_str; - char text[256]; + struct sockaddr_un saddr; + struct sockaddr *psaddr; - LLOGLN(10, ("SCardEstablishContext:")); xrdp_session = getenv("XRDP_SESSION"); if (xrdp_session == NULL) { /* XRDP_SESSION must be set */ - return SCARD_F_INTERNAL_ERROR; + LLOGLN(0, ("connect_to_chansrv: error, not xrdp session")); + return 1; } xrdp_display = getenv("DISPLAY"); if (xrdp_display == NULL) { /* DISPLAY must be set */ - return SCARD_F_INTERNAL_ERROR; + LLOGLN(0, ("connect_to_chansrv: error, display not set")); + return 1; } home_str = getenv("HOME"); if (home_str == NULL) { /* HOME must be set */ - return SCARD_F_INTERNAL_ERROR; + LLOGLN(0, ("connect_to_chansrv: error, home not set")); + return 1; } dis = get_display_num_from_display(xrdp_display); if (dis < 10) { /* DISPLAY must be > 9 */ + LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis)); + return 1; + } + if (g_sck == -1) + { + g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); + if (g_sck == -1) + { + LLOGLN(0, ("connect_to_chansrv: error, socket failed")); + return 1; + } + memset(&saddr, 0, sizeof(struct sockaddr_un)); + saddr.sun_family = AF_UNIX; + bytes = sizeof(saddr.sun_path); + snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); + saddr.sun_path[bytes - 1] = 0; + LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); + psaddr = (struct sockaddr *) &saddr; + bytes = sizeof(struct sockaddr_un); + error = connect(g_sck, psaddr, bytes); + if (error == 0) + { + } + else + { + perror("connect_to_chansrv"); + close(g_sck); + g_sck = -1; + LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path)); + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +static int +send_message(int code, char *data, int bytes) +{ + char header[8]; + + SET_UINT32(header, 0, bytes); + SET_UINT32(header, 4, code); + if (send(g_sck, header, 8, 0) != 8) + { + return 1; + } + if (send(g_sck, data, bytes, 0) != bytes) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +get_message(int *code, char *data, int *bytes) +{ + char header[8]; + int max_bytes; + + if (recv(g_sck, header, 8, 0) != 8) + { + return 1; + } + max_bytes = *bytes; + *bytes = GET_UINT32(header, 0); + *code = GET_UINT32(header, 4); + if (*bytes > max_bytes) + { + return 1; + } + if (recv(g_sck, data, *bytes, 0) != *bytes) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +PCSC_API LONG +SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, + LPSCARDCONTEXT phContext) +{ + char msg[256]; + DWORD context; + int code; + int bytes; + int status; + + LLOGLN(0, ("SCardEstablishContext:")); + if (g_sck == -1) + { + if (connect_to_chansrv() != 0) + { + LLOGLN(0, ("SCardEstablishContext: error, can not connect " + "to chansrv")); + return SCARD_F_INTERNAL_ERROR; + } + } + pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, dwScope); + if (send_message(SCARD_ESTABLISH_CONTEXT, msg, 4) != 0) + { + LLOGLN(0, ("SCardEstablishContext: error, send_message")); + pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - if (g_fd == 0) + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) { - g_fd = socket(PF_LOCAL, SOCK_STREAM, 0); - snprintf(text, 255, "%s/.pcsc%d", home_str, dis); + LLOGLN(0, ("SCardEstablishContext: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; } - if (g_fd == 0) + if ((code != SCARD_ESTABLISH_CONTEXT) || (bytes != 8)) { + LLOGLN(0, ("SCardEstablishContext: error, bad code")); + pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - *phContext = 0; - return SCARD_S_SUCCESS; + pthread_mutex_unlock(&g_mutex); + context = GET_UINT32(msg, 0); + status = GET_UINT32(msg, 4); + LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", context)); + *phContext = context; + return status; } /*****************************************************************************/ PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext) { - LLOGLN(10, ("SCardReleaseContext:")); - return SCARD_S_SUCCESS; + char msg[256]; + int code; + int bytes; + int status; + + LLOGLN(0, ("SCardReleaseContext:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardReleaseContext: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hContext); + if (send_message(SCARD_RELEASE_CONTEXT, msg, 4) != 0) + { + LLOGLN(0, ("SCardReleaseContext: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardReleaseContext: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4)) + { + LLOGLN(0, ("SCardReleaseContext: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_unlock(&g_mutex); + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext) { - LLOGLN(10, ("SCardIsValidContext:")); + LLOGLN(0, ("SCardIsValidContext:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardIsValidContext: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -181,7 +369,14 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { - LLOGLN(10, ("SCardConnect:")); + LLOGLN(0, ("SCardConnect:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardConnect: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -191,7 +386,14 @@ SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol) { - LLOGLN(10, ("SCardReconnect:")); + LLOGLN(0, ("SCardReconnect:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardReconnect: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -199,7 +401,14 @@ SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) { - LLOGLN(10, ("SCardDisconnect:")); + LLOGLN(0, ("SCardDisconnect:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardDisconnect: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -208,6 +417,13 @@ PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) { LLOGLN(0, ("SCardBeginTransaction:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardBeginTransaction: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -215,7 +431,14 @@ SCardBeginTransaction(SCARDHANDLE hCard) PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) { - LLOGLN(10, ("SCardEndTransaction:")); + LLOGLN(0, ("SCardEndTransaction:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardEndTransaction: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -225,7 +448,14 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { - LLOGLN(10, ("SCardStatus:")); + LLOGLN(0, ("SCardStatus:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardStatus: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -234,12 +464,91 @@ PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) { - LLOGLN(10, ("SCardGetStatusChange:")); - LLOGLN(10, ("SCardGetStatusChange: dwTimeout %d cReaders %d", - dwTimeout, cReaders)); - memset(rgReaderStates, 0, sizeof(SCARD_READERSTATE)); - usleep(60000000); - return SCARD_S_SUCCESS; + char *msg; + int bytes; + int code; + int index; + int offset; + int str_len; + int status; + + LLOGLN(0, ("SCardGetStatusChange:")); + LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders)); + if (g_sck == -1) + { + LLOGLN(0, ("SCardGetStatusChange: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + msg = (char *) malloc(8192); + SET_UINT32(msg, 0, hContext); + SET_UINT32(msg, 4, dwTimeout); + SET_UINT32(msg, 8, cReaders); + offset = 12; + for (index = 0; index < cReaders; index++) + { + str_len = strlen(rgReaderStates[index].szReader); + str_len = LMIN(str_len, 99); + memset(msg + offset, 0, 100); + memcpy(msg + offset, rgReaderStates[index].szReader, str_len); + offset += 100; + LLOGLN(10, (" in dwCurrentState %d", rgReaderStates[index].dwCurrentState)); + SET_UINT32(msg, offset, rgReaderStates[index].dwCurrentState); + offset += 4; + LLOGLN(10, (" in dwEventState %d", rgReaderStates[index].dwEventState)); + SET_UINT32(msg, offset, rgReaderStates[index].dwEventState); + offset += 4; + LLOGLN(10, (" in cbAtr %d", rgReaderStates[index].cbAtr)); + SET_UINT32(msg, offset, rgReaderStates[index].cbAtr); + offset += 4; + memset(msg + offset, 0, 36); + memcpy(msg + offset, rgReaderStates[index].rgbAtr, 33); + offset += 36; + } + pthread_mutex_lock(&g_mutex); + if (send_message(SCARD_GET_STATUS_CHANGE, msg, offset) != 0) + { + LLOGLN(0, ("SCardGetStatusChange: error, send_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 8192; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardGetStatusChange: error, get_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if (code != SCARD_GET_STATUS_CHANGE) + { + LLOGLN(0, ("SCardGetStatusChange: error, bad code")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_unlock(&g_mutex); + cReaders = GET_UINT32(msg, 0); + offset = 4; + LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders)); + for (index = 0; index < cReaders; index++) + { + rgReaderStates[index].dwCurrentState = GET_UINT32(msg, offset); + offset += 4; + LLOGLN(10, (" out dwCurrentState %d", rgReaderStates[index].dwCurrentState)); + rgReaderStates[index].dwEventState = GET_UINT32(msg, offset); + offset += 4; + LLOGLN(10, (" out dwEventState %d", rgReaderStates[index].dwEventState)); + rgReaderStates[index].cbAtr = GET_UINT32(msg, offset); + offset += 4; + LLOGLN(10, (" out cbAtr %d", rgReaderStates[index].cbAtr)); + memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); + offset += 36; + } + status = GET_UINT32(msg, offset); + offset += 4; + free(msg); + return status; } /*****************************************************************************/ @@ -248,7 +557,14 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned) { - LLOGLN(10, ("SCardControl:")); + LLOGLN(0, ("SCardControl:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardControl: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -259,7 +575,14 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) { - LLOGLN(10, ("SCardTransmit:")); + LLOGLN(0, ("SCardTransmit:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardTransmit: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -268,7 +591,14 @@ PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups) { - LLOGLN(10, ("SCardListReaderGroups:")); + LLOGLN(0, ("SCardListReaderGroups:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardListReaderGroups: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -277,15 +607,95 @@ PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) { - LLOGLN(10, ("SCardListReaders:")); - return SCARD_S_SUCCESS; + char* msg; + char* reader_names; + int reader_names_index; + int code; + int bytes; + int num_readers; + int status; + int offset; + int index; + char reader[100]; + + LLOGLN(0, ("SCardListReaders:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardListReaders: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + msg = (char *) malloc(8192); + pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hContext); + if (send_message(SCARD_LIST_READERS, msg, 4) != 0) + { + LLOGLN(0, ("SCardListReaders: error, send_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 8192; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardListReaders: error, get_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if (code != SCARD_LIST_READERS) + { + LLOGLN(0, ("SCardListReaders: error, bad code")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_unlock(&g_mutex); + offset = 0; + num_readers = GET_UINT32(msg, offset); + offset += 4; + LLOGLN(10, ("hi - mszReaders %p pcchReaders %p num_readers %d", mszReaders, pcchReaders, num_readers)); + reader_names = (char *) malloc(8192); + reader_names_index = 0; + for (index = 0; index < num_readers; index++) + { + memcpy(reader, msg + offset, 100); + bytes = strlen(reader); + memcpy(reader_names + reader_names_index, reader, bytes); + reader_names_index += bytes; + reader_names[reader_names_index] = 0; + reader_names_index++; + offset += 100; + LLOGLN(10, ("SCardListReaders: readername %s", reader)); + } + reader_names[reader_names_index] = 0; + reader_names_index++; + status = GET_UINT32(msg, offset); + offset += 4; + if (pcchReaders != 0) + { + *pcchReaders = reader_names_index; + } + if (mszReaders != 0) + { + memcpy(mszReaders, reader_names, reader_names_index); + } + free(msg); + free(reader_names); + return status; } /*****************************************************************************/ PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) { - LLOGLN(10, ("SCardFreeMemory:")); + LLOGLN(0, ("SCardFreeMemory:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardFreeMemory: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -293,7 +703,14 @@ SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) PCSC_API LONG SCardCancel(SCARDCONTEXT hContext) { - LLOGLN(10, ("SCardCancel:")); + LLOGLN(0, ("SCardCancel:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardCancel: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -302,7 +719,14 @@ PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) { - LLOGLN(10, ("SCardGetAttrib:")); + LLOGLN(0, ("SCardGetAttrib:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardGetAttrib: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } @@ -311,6 +735,35 @@ PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen) { - LLOGLN(10, ("SCardSetAttrib:")); + LLOGLN(0, ("SCardSetAttrib:")); + if (g_sck == -1) + { + LLOGLN(0, ("SCardSetAttrib: error, not connected")); + return SCARD_F_INTERNAL_ERROR; + } + pthread_mutex_lock(&g_mutex); + pthread_mutex_unlock(&g_mutex); return SCARD_S_SUCCESS; } + +static char g_error_str[512]; + +/*****************************************************************************/ +char * +pcsc_stringify_error(const long code) +{ + switch (code) + { + case SCARD_S_SUCCESS: + snprintf(g_error_str, 511, "Command successful."); + break; + case SCARD_F_INTERNAL_ERROR: + snprintf(g_error_str, 511, "Internal error."); + break; + default: + snprintf(g_error_str, 511, "error 0x%8.8x", (int)code); + break; + } + g_error_str[511] = 0; + return g_error_str; +} From d926a5becd9814f55025a58fb4bb9263c6a24dbb Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 16 Sep 2013 00:16:21 -0700 Subject: [PATCH 22/32] chansrv: work on smartcard --- sesman/chansrv/smartcard.c | 194 +++++++------ sesman/chansrv/smartcard.h | 2 +- sesman/chansrv/smartcard_pcsc.c | 464 ++++++++++++-------------------- sesman/chansrv/smartcard_pcsc.h | 11 +- 4 files changed, 275 insertions(+), 396 deletions(-) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index f694484f..b97ffca6 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -155,63 +155,64 @@ extern int g_rdpdr_chan_id; /* in chansrv.c */ /****************************************************************************** ** static functions local to this file ** ******************************************************************************/ -static struct stream *scard_make_new_ioctl(IRP *irp, tui32 ioctl); -static int scard_add_new_device(tui32 device_id); -static int scard_get_free_slot(void); -static void scard_release_resources(void); -static void scard_send_EstablishContext(IRP* irp, int scope); -static void scard_send_ReleaseContext(IRP* irp, tui32 context); -static void scard_send_ListReaders(IRP* irp, tui32 context, int wide); - -static void scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, - tui32 timeout, tui32 num_readers, - READER_STATE* rsa); - -static void scard_send_Connect(IRP* irp, tui32 context, int wide, - READER_STATE* rs); - -static void scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); -static void scard_send_EndTransaction(IRP* irp, tui32 sc_handle); -static void scard_send_Status(IRP* irp, int wide, tui32 sc_handle); -static void scard_send_Disconnect(IRP* irp, tui32 context, tui32 sc_handle); +static struct stream * APP_CC scard_make_new_ioctl(IRP *irp, tui32 ioctl); +static int APP_CC scard_add_new_device(tui32 device_id); +static int APP_CC scard_get_free_slot(void); +static void APP_CC scard_release_resources(void); +static void APP_CC scard_send_EstablishContext(IRP* irp, int scope); +static void APP_CC scard_send_ReleaseContext(IRP* irp, tui32 context); +static void APP_CC scard_send_ListReaders(IRP* irp, tui32 context, int wide); + +static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, + tui32 timeout, tui32 num_readers, + READER_STATE* rsa); + +static void APP_CC scard_send_Connect(IRP* irp, tui32 context, int wide, + READER_STATE* rs); + +static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); +static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle); +static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle); +static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context, + tui32 sc_handle); /****************************************************************************** ** local callbacks into this module ** ******************************************************************************/ -static void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_ListReaders_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_Connect_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_Status_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_Status_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); -static void scard_handle_Disconnect_Return(struct stream *s, IRP *irp, +static void APP_CC scard_handle_Disconnect_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); @@ -310,8 +311,8 @@ scard_send_irp_establish_context(struct trans *con, int scope) /** * Release a previously established Smart Card context *****************************************************************************/ -int -APP_CC scard_send_release_context(struct trans *con, tui32 context) +int APP_CC +scard_send_irp_release_context(struct trans *con, tui32 context) { IRP *irp; @@ -432,8 +433,8 @@ scard_send_irp_connect(struct trans *con, tui32 context, int wide, * * @param con connection to client *****************************************************************************/ -int -APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle) +int APP_CC +scard_send_begin_transaction(struct trans *con, tui32 sc_handle) { IRP *irp; @@ -463,8 +464,8 @@ APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle) * @param con connection to client * @param sc_handle handle to smartcard *****************************************************************************/ -int -APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle) +int APP_CC +scard_send_end_transaction(struct trans *con, tui32 sc_handle) { IRP *irp; @@ -493,8 +494,8 @@ APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle) * @param con connection to client * @param wide TRUE if unicode string *****************************************************************************/ -int -APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle) +int APP_CC +scard_send_status(struct trans *con, int wide, tui32 sc_handle) { IRP *irp; @@ -523,8 +524,8 @@ APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle) * @param con connection to client * @param sc_handle handle to smartcard *****************************************************************************/ -int -APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) +int APP_CC +scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) { IRP *irp; @@ -718,7 +719,7 @@ scard_send_EstablishContext(IRP *irp, int scope) /** * Release a previously established Smart Card context *****************************************************************************/ -static void +static void APP_CC scard_send_ReleaseContext(IRP* irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.2 */ @@ -856,6 +857,21 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) */ } +/*****************************************************************************/ +static int +align_s(struct stream *s, int bytes) +{ + int i32; + + i32 = (int) (s->p - s->data); + while ((i32 % bytes) != 0) + { + out_uint8s(s, 1); + i32 = (int) (s->p - s->data); + } + return 0; +} + /** * Get change in status * @@ -865,7 +881,7 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) * @param num_readers number of entries in rsa * @param rsa array of READER_STATEs *****************************************************************************/ -static void +static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa) { @@ -932,6 +948,7 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { xstream_wr_u16_le(s, w_reader_name[index]); } + align_s(s, 4); } } else @@ -948,6 +965,7 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { xstream_wr_u8(s, w_reader_name[index]); } + align_s(s, 4); } } @@ -969,8 +987,8 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, * @param wide TRUE if unicode string * @param rs reader state *****************************************************************************/ -static void scard_send_Connect(IRP* irp, tui32 context, int wide, - READER_STATE* rs) +static void APP_CC +scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) { /* see [MS-RDPESC] 2.2.2.13 for ASCII */ /* see [MS-RDPESC] 2.2.2.14 for Wide char */ @@ -1021,12 +1039,16 @@ static void scard_send_Connect(IRP* irp, tui32 context, int wide, if (wide) { for (index = 0; index < num_chars; index++) + { xstream_wr_u16_le(s, w_reader_name[index]); + } } else { for (index = 0; index < num_chars; index++) + { xstream_wr_u8(s, w_reader_name[index]); + } } /* insert context */ @@ -1050,13 +1072,13 @@ static void scard_send_Connect(IRP* irp, tui32 context, int wide, * * @param con connection to client *****************************************************************************/ -static void -scard_send_BeginTransaction(IRP* irp, tui32 sc_handle) +static void APP_CC +scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) { /* see [MS-RDPESC] 4.9 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1104,8 +1126,8 @@ scard_send_BeginTransaction(IRP* irp, tui32 sc_handle) * @param con connection to client * @param sc_handle handle to smartcard *****************************************************************************/ -static void -scard_send_EndTransaction(IRP* irp, tui32 sc_handle) +static void APP_CC +scard_send_EndTransaction(IRP *irp, tui32 sc_handle) { /* see [MS-RDPESC] 3.1.4.32 */ @@ -1161,13 +1183,13 @@ scard_send_EndTransaction(IRP* irp, tui32 sc_handle) * @param con connection to client * @param wide TRUE if unicode string *****************************************************************************/ -static void -scard_send_Status(IRP* irp, int wide, tui32 sc_handle) +static void APP_CC +scard_send_Status(IRP *irp, int wide, tui32 sc_handle) { /* see [MS-RDPESC] 2.2.2.18 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; tui32 ioctl; @@ -1227,8 +1249,8 @@ scard_send_Status(IRP* irp, int wide, tui32 sc_handle) * @param con connection to client * @param sc_handle handle to smartcard *****************************************************************************/ -static void -scard_send_Disconnect(IRP* irp, tui32 context, tui32 sc_handle) +static void APP_CC +scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle) { /* see [MS-RDPESC] 3.1.4.30 */ @@ -1296,57 +1318,27 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { - tui32 context; - tui32 len; - int tmp; - SMARTCARD *sc; + tui32 len; + struct trans *con; log_debug("entered"); - /* sanity check */ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) { log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) { log_error("failed to establish context - device not usable"); /* LK_TODO delete irp and smartcard entry */ return; } - - sc = smartcards[irp->scard_index]; - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - - /* LK_TODO */ - g_hexdump(s->p, len); - - xstream_rd_u32_le(s, tmp); /* should be len 8, LE, V1 */ - xstream_rd_u32_le(s, tmp); /* marshalling flag */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, tmp); /* ?? */ - xstream_rd_u32_le(s, len); /* len of context in bytes, always 4 */ - xstream_rd_u32_le(s, context); - - if (LOG_LEVEL == LOG_DEBUG) - log_debug("dumping: )", context); - - // LK_TODO delete this - //irp->callback = scard_handle_ListReaders_Return; - - scard_function_establish_context_return((struct trans *) (irp->user_data), - context); - + con = (struct trans *) (irp->user_data); + scard_function_establish_context_return(con, s, len); devredir_irp_delete(irp); - - /* LK_TODO need to delete IRP */ log_debug("leaving"); } @@ -1359,26 +1351,26 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); - /* sanity check */ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) { log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) { log_error("ReleaseContext failed, device not usable"); /* LK_TODO delete irp and smartcard entry */ return; } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_release_context_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -1391,28 +1383,26 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); - /* sanity check */ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) { log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) { log_error("failed to list readers - device not usable"); /* LK_TODO delete irp and smartcard entry */ return; } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - - scard_function_list_readers_return((struct trans *) irp->user_data, - s, len); + con = (struct trans *) (irp->user_data); + scard_function_list_readers_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -1425,26 +1415,26 @@ scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); - /* sanity check */ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) { log_error("DeviceId/CompletionId do not match those in IRP"); return; } - if (IoStatus != 0) { log_error("failed to get status change - device not usable"); /* LK_TODO delete irp and smartcard entry */ return; } - /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_get_status_change_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 1927b2e0..44d4fcbc 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -74,7 +74,7 @@ int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); -int APP_CC scard_send_release_context(struct trans *con, tui32 context); +int APP_CC scard_send_irp_release_context(struct trans *con, tui32 context); int APP_CC scard_send_irp_list_readers(struct trans *con, tui32 context, int wide); int APP_CC scard_send_irp_get_status_change(struct trans *con, tui32 context, diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 2f11c517..ded872cb 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -50,74 +50,13 @@ } \ while (0) -/* using pcsc-lite-1.7.4 */ - -struct establish_struct -{ - tui32 dwScope; - tui32 hContext; - tui32 rv; -}; - -struct release_struct -{ - tui32 hContext; - tui32 rv; -}; - -/** Major version of the current message protocol */ -#define PROTOCOL_VERSION_MAJOR 4 -/** Minor version of the current message protocol */ -#define PROTOCOL_VERSION_MINOR 2 - -struct version_struct -{ - tsi32 major; /**< IPC major \ref PROTOCOL_VERSION_MAJOR */ - tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */ - tui32 rv; -}; - -#define SCARD_S_SUCCESS 0x00000000 /**< No error was encountered. */ -#define SCARD_F_INTERNAL_ERROR 0x80100001 /**< An internal consistency - * check failed. */ -#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout - * value has expired. */ - -#define MAX_READERNAME 100 -#define MAX_ATR_SIZE 33 - -struct pubReaderStatesList -{ - char readerName[MAX_READERNAME]; /**< reader name */ - tui32 eventCounter; /**< number of card events */ - tui32 readerState; /**< SCARD_* bit field */ - tsi32 readerSharing; /**< PCSCLITE_SHARING_* sharing status */ - tui8 cardAtr[MAX_ATR_SIZE]; /**< ATR */ - tui32 cardAtrLength; /**< ATR length */ - tui32 cardProtocol; /**< SCARD_PROTOCOL_* value */ -}; - -#define PCSCLITE_MAX_READERS_CONTEXTS 16 - -static int g_num_readers = 0; -/* pcsc list */ -static struct pubReaderStatesList - g_pcsc_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; -/* rdp list */ -static READER_STATE g_xrdp_reader_states[PCSCLITE_MAX_READERS_CONTEXTS]; - -struct wait_reader_state_change -{ - tui32 timeOut; /**< timeout in ms */ - tui32 rv; -}; - #define XRDP_PCSC_STATE_NONE 0 -#define XRDP_PCSC_STATE_GOT_RSC (1 << 0) /* read state change */ -#define XRDP_PCSC_STATE_GOT_EC (1 << 1) /* establish context */ -#define XRDP_PCSC_STATE_GOT_LR (1 << 2) /* list readers */ -#define XRDP_PCSC_STATE_GOT_RC (1 << 3) /* release context */ +#define XRDP_PCSC_STATE_GOT_EC (1 << 0) /* establish context */ +#define XRDP_PCSC_STATE_GOT_LR (1 << 1) /* list readers */ +#define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ +#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ +/* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; extern int g_display_num; /* in chansrv.c */ @@ -135,7 +74,6 @@ static struct trans *g_lis = 0; static struct trans *g_con = 0; /* todo, remove this */ static char g_pcsclite_ipc_dir[256] = ""; static int g_pub_file_fd = 0; -static char g_pub_file_name[256] = ""; /*****************************************************************************/ int APP_CC @@ -174,7 +112,7 @@ scard_pcsc_check_wait_objs(void) int APP_CC scard_process_establish_context(struct trans *con, struct stream *in_s) { - struct establish_struct in_es; + int dwScope; LLOGLN(0, ("scard_process_establish_context:")); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) @@ -183,112 +121,122 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) return 1; } g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC; - in_uint8a(in_s, &in_es, sizeof(in_es)); - LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", - in_es.dwScope)); - scard_send_irp_establish_context(con, in_es.dwScope); + in_uint32_le(in_s, dwScope); + LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope)); + scard_send_irp_establish_context(con, dwScope); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_establish_context_return(struct trans *con, tui32 context) +scard_function_establish_context_return(struct trans *con, + struct stream *in_s, + int len) { - struct establish_struct out_es; + int bytes; + tui32 context; + tui32 context_len; struct stream *out_s; - LLOGLN(0, ("scard_function_establish_context_return: context %d", - context)); + LLOGLN(0, ("scard_function_establish_context_return:")); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) { LLOGLN(0, ("scard_function_establish_context_return: opps")); return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; - out_es.dwScope = 0; - out_es.hContext = context; - out_es.rv = SCARD_S_SUCCESS; + in_uint8s(in_s, 28); + in_uint32_le(in_s, context_len); + if (context_len != 4) + { + LLOGLN(0, ("scard_function_establish_context_return: opps")); + return 1; + } + in_uint32_le(in_s, context); + LLOGLN(0, ("scard_function_establish_context_return: context 0x%8.8x", context)); out_s = trans_get_out_s(con, 8192); - out_uint8a(out_s, &out_es, sizeof(out_es)); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, context); + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x01); /* SCARD_ESTABLISH_CONTEXT 0x01 */ return trans_force_write(con); } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_release_context(struct stream *in_s) +scard_process_release_context(struct trans *con, struct stream *in_s) { - struct release_struct in_rs; - struct release_struct out_rs; - struct stream *out_s; + int hContext; LLOGLN(0, ("scard_process_release_context:")); - in_uint8a(in_s, &in_rs, sizeof(in_rs)); - LLOGLN(0, ("scard_process_release_context: hContext %d", in_rs.hContext)); - - /* TODO: use XRDP_PCSC_STATE_GOT_RC */ - - out_rs.hContext = in_rs.hContext; - out_rs.rv = SCARD_S_SUCCESS; - out_s = trans_get_out_s(g_con, 8192); - out_uint8a(out_s, &out_rs, sizeof(out_rs)); - s_mark_end(out_s); - return trans_force_write(g_con); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) + { + LLOGLN(0, ("scard_process_establish_context: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC; + in_uint32_le(in_s, hContext); + LLOGLN(0, ("scard_process_release_context: hContext 0x%8.8x", hContext)); + scard_send_irp_release_context(con, hContext); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_version(struct trans *con, struct stream *in_s) +scard_function_release_context_return(struct trans *con, + struct stream *in_s, + int len) { + int bytes; struct stream *out_s; - struct version_struct in_version; - struct version_struct out_version; - - LLOGLN(0, ("scard_process_version:")); - in_uint8a(in_s, &in_version, sizeof(in_version)); - /* todo: check if version is compatible */ - LLOGLN(0, ("scard_process_version: version major %d minor %d", - in_version.major, in_version.minor)); + tui32 context; + + LLOGLN(0, ("scard_function_release_context_return:")); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0) + { + LLOGLN(0, ("scard_function_release_context_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC; out_s = trans_get_out_s(con, 8192); - out_version.major = PROTOCOL_VERSION_MAJOR; - out_version.minor = PROTOCOL_VERSION_MINOR; - out_version.rv = SCARD_S_SUCCESS; - out_uint8a(out_s, &out_version, sizeof(out_version)); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x02); /* SCARD_RELEASE_CONTEXT 0x02 */ return trans_force_write(con); } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_get_readers_state(struct trans *con, struct stream *in_s) +scard_process_list_readers(struct trans *con, struct stream *in_s) { - //struct stream *out_s; - - LLOGLN(0, ("scard_process_get_readers_state:")); - - //out_s = trans_get_out_s(con, 8192); - //out_uint8a(out_s, g_pcsc_reader_states, sizeof(g_pcsc_reader_states)); - //s_mark_end(out_s); - //return trans_force_write(con); + int hContext; + LLOGLN(0, ("scard_process_list_readers:")); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) { - LLOGLN(0, ("scard_process_get_readers_state: opps")); + LLOGLN(0, ("scard_process_list_readers: opps")); return 1; } g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; - - scard_send_irp_list_readers(con, JAY_TODO_CONTEXT, JAY_TODO_WIDE); - + in_uint32_le(in_s, hContext); + LLOGLN(0, ("scard_process_list_readers: dwScope 0x%8.8x", hContext)); + scard_send_irp_list_readers(con, hContext, 1); return 0; } /*****************************************************************************/ -/* returns error */ int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, @@ -298,23 +246,28 @@ scard_function_list_readers_return(struct trans *con, int chr; int readers; int rn_index; - char reader_name[100]; + int index; + int bytes; + twchar reader_name[100]; + char lreader_name[16][100]; + LLOGLN(10, ("scard_function_list_readers_return:")); g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0) { - LLOGLN(0, ("scard_function_list_readers_return: opps")); + LLOGLN(10, ("scard_function_list_readers_return: opps")); return 1; } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; + g_memset(reader_name, 0, sizeof(reader_name)); + g_memset(lreader_name, 0, sizeof(lreader_name)); in_uint8s(in_s, 28); len -= 28; in_uint32_le(in_s, len); g_writeln("len %d", len); rn_index = 0; - readers = 1; + readers = 0; while (len > 0) { in_uint16_le(in_s, chr); @@ -323,7 +276,9 @@ scard_function_list_readers_return(struct trans *con, { if (reader_name[0] != 0) { - g_writeln("1 %s", reader_name); + g_wcstombs(lreader_name[readers], reader_name, 99); + g_writeln("1 %s", lreader_name[readers]); + g_memset(reader_name, 0, sizeof(reader_name)); readers++; } reader_name[0] = 0; @@ -339,181 +294,136 @@ scard_function_list_readers_return(struct trans *con, { if (reader_name[0] != 0) { - g_writeln("2 %s", reader_name); + g_wcstombs(lreader_name[readers], reader_name, 99); + g_writeln("2 %s", lreader_name[readers]); + g_memset(reader_name, 0, sizeof(reader_name)); readers++; } } -#if 0 - g_strcpy(g_reader_states[0].readerName, "ACS AET65 00 00"); - g_reader_states[0].readerState = 0x14; - g_reader_states[0].cardProtocol = 3; - - g_reader_states[0].cardAtrLength = 10; - g_reader_states[0].cardAtr[0] = 0x3B; - g_reader_states[0].cardAtr[1] = 0x95; - g_reader_states[0].cardAtr[2] = 0x95; - g_reader_states[0].cardAtr[3] = 0x40; - g_reader_states[0].cardAtr[4] = 0xFF; - g_reader_states[0].cardAtr[5] = 0xD0; - g_reader_states[0].cardAtr[6] = 0x00; - g_reader_states[0].cardAtr[7] = 0x54; - g_reader_states[0].cardAtr[8] = 0x01; - g_reader_states[0].cardAtr[9] = 0x32; - - //g_reader_states[0].eventCounter++; out_s = trans_get_out_s(con, 8192); - out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); - s_mark_end(out_s); - return trans_force_write(con); -#endif - return 0; -} - -/*****************************************************************************/ -/* callback from chansrv when timeout occurs */ -void DEFAULT_CC -scard_read_state_chage_timeout(void* data) -{ - struct trans *con; - struct stream *out_s; - struct wait_reader_state_change out_rsc; - - LLOGLN(0, ("scard_read_state_chage_timeout:")); - con = (struct trans *) data; - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, readers); + for (index = 0; index < readers; index++) { - out_s = trans_get_out_s(con, 8192); - out_rsc.timeOut = 0; - out_rsc.rv = SCARD_S_SUCCESS; - out_uint8a(out_s, &out_rsc, sizeof(out_rsc)); - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC; - s_mark_end(out_s); - trans_force_write(con); - } - else - { - LLOGLN(0, ("scard_read_state_chage_timeout: already stopped")); + g_writeln("3 - %s", lreader_name[index]); + out_uint8a(out_s, lreader_name[index], 100); } + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x03); /* SCARD_LIST_READERS 0x03 */ + return trans_force_write(con); } /*****************************************************************************/ /* returns error */ int APP_CC -scard_process_read_state_change(struct trans *con, struct stream *in_s) +scard_process_get_status_change(struct trans *con, struct stream *in_s) { - struct wait_reader_state_change in_rsc; - struct stream *out_s; int index; + int hContext; + int dwTimeout; + int cReaders; + READER_STATE *rsa; - LLOGLN(0, ("scard_process_read_state_change:")); - in_uint8a(in_s, &in_rsc, sizeof(in_rsc)); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) + LLOGLN(0, ("scard_process_get_status_change:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) { - LLOGLN(0, ("scard_process_read_state_change: opps")); - return 0; + LLOGLN(0, ("scard_process_get_status_change: opps")); + return 1; } - -#if 0 - for (index = 0; index < 16; index++) + in_uint32_le(in_s, hContext); + in_uint32_le(in_s, dwTimeout); + in_uint32_le(in_s, cReaders); + if ((cReaders < 0) || (cReaders > 16)) { - //g_memcpy(rd[index].reader_name, g_pcsc_reader_states[index].readerName, 99); - g_strncpy(rd[index].reader_name, "Gemalto PC Twin Reader 00 00", 99); - rd[index].current_state = g_pcsc_reader_states[index].readerState; - rd[index].event_state = g_pcsc_reader_states[index].eventCounter; - rd[index].atr_len = g_pcsc_reader_states[index].cardAtrLength; - g_memcpy(rd[index].atr, g_pcsc_reader_states[index].cardAtr, 33); + LLOGLN(0, ("scard_process_get_status_change: bad cReaders %d", cReaders)); + return 1; } -#endif + rsa = (READER_STATE *) g_malloc(sizeof(READER_STATE) * cReaders, 1); - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RSC; - scard_send_irp_get_status_change(con, JAY_TODO_CONTEXT, 1, in_rsc.timeOut, g_num_readers, - g_xrdp_reader_states); + for (index = 0; index < cReaders; index++) + { + in_uint8a(in_s, rsa[index].reader_name, 100); + LLOGLN(10, ("scard_process_get_status_change: reader_name %s", + rsa[index].reader_name)); + in_uint32_le(in_s, rsa[index].current_state); + LLOGLN(10, ("scard_process_get_status_change: current_state %d", + rsa[index].current_state)); + in_uint32_le(in_s, rsa[index].event_state); + LLOGLN(10, ("scard_process_get_status_change: event_state %d", + rsa[index].event_state)); + in_uint32_le(in_s, rsa[index].atr_len); + LLOGLN(10, ("scard_process_get_status_change: atr_len %d", + rsa[index].atr_len)); + in_uint8a(in_s, rsa[index].atr, 36); + } - LLOGLN(0, ("scard_process_read_state_change: timeout %d rv %d", - in_rsc.timeOut, in_rsc.rv)); + LLOGLN(0, ("scard_process_get_status_change: hContext 0x%8.8x dwTimeout " + "%d cReaders %d", hContext, dwTimeout, cReaders)); - add_timeout(in_rsc.timeOut, scard_read_state_chage_timeout, con); + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC; - return 0; -} + scard_send_irp_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); -/*****************************************************************************/ -/* returns error */ -int APP_CC -scard_process_stop_read_state_change(struct trans *con, struct stream *in_s) -{ - struct wait_reader_state_change in_rsc; - struct wait_reader_state_change out_rsc; - struct stream *out_s; + g_free(rsa); - LLOGLN(0, ("scard_process_stop_read_state_change:")); - in_uint8a(in_s, &in_rsc, sizeof(in_rsc)); - LLOGLN(0, ("scard_process_stop_read_state_change: timeout %d rv %d", - in_rsc.timeOut, in_rsc.rv)); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC) - { - out_s = trans_get_out_s(con, 8192); - out_rsc.timeOut = in_rsc.timeOut; - out_rsc.rv = SCARD_S_SUCCESS; - out_uint8a(out_s, &out_rsc, sizeof(out_rsc)); - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC; - s_mark_end(out_s); - return trans_force_write(con); - } - else - { - LLOGLN(0, ("scard_process_stop_read_state_change: already stopped")); - } return 0; } /*****************************************************************************/ -/* returns error */ int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, int len) { - struct stream *out_s; - int num_readers; + int bytes; int index; - int current_state; - int event_state; - int atr_len; - char atr[36]; + int cReaders; + tui32 current_state; + tui32 event_state; + tui32 atr_len; /* number of bytes in atr[] */ + tui8 atr[36]; + struct stream *out_s; LLOGLN(0, ("scard_function_get_status_change_return:")); - - //g_hexdump(in_s->p, len); - + g_hexdump(in_s->p, len); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0) + { + LLOGLN(0, ("scard_function_establish_context_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC; in_uint8s(in_s, 28); - in_uint32_le(in_s, num_readers); - LLOGLN(0, (" num_reader %d", num_readers)); - - g_num_readers = num_readers; - - for (index = 0; index < num_readers; index++) + in_uint32_le(in_s, cReaders); + if (cReaders > 0) { - in_uint32_le(in_s, current_state); - in_uint32_le(in_s, event_state); - in_uint32_le(in_s, atr_len); - in_uint8a(in_s, atr, 36); - LLOGLN(0, (" current_state 0x%8.8x event_state 0x%8.8x " - "atr_len 0x%8.8x", current_state, event_state, atr_len)); - g_xrdp_reader_states[index].current_state = current_state; - g_xrdp_reader_states[index].event_state = event_state; - g_xrdp_reader_states[index].atr_len = atr_len; - g_memcpy(g_xrdp_reader_states[index].atr, atr, 36); - + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, cReaders); + 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); + } + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */ + return trans_force_write(con); } - //out_s = trans_get_out_s(con, 8192); - //out_uint8a(out_s, g_reader_states, sizeof(g_reader_states)); - //s_mark_end(out_s); - //return trans_force_write(con); - return 0; - } /*****************************************************************************/ @@ -533,11 +443,12 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x02: /* SCARD_RELEASE_CONTEXT */ LLOGLN(0, ("scard_process_msg: SCARD_RELEASE_CONTEXT")); - rv = scard_process_release_context(in_s); + rv = scard_process_release_context(con, in_s); break; case 0x03: /* SCARD_LIST_READERS */ LLOGLN(0, ("scard_process_msg: SCARD_LIST_READERS")); + rv = scard_process_list_readers(con, in_s); break; case 0x04: /* SCARD_CONNECT */ @@ -574,6 +485,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x0C: /* SCARD_GET_STATUS_CHANGE */ LLOGLN(0, ("scard_process_msg: SCARD_GET_STATUS_CHANGE")); + rv = scard_process_get_status_change(con, in_s); break; case 0x0D: /* SCARD_CANCEL */ @@ -592,22 +504,6 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) LLOGLN(0, ("scard_process_msg: SCARD_SET_ATTRIB")); break; - case 0x11: /* CMD_VERSION */ - LLOGLN(0, ("scard_process_msg: CMD_VERSION")); - rv = scard_process_version(con, in_s); - break; - case 0x12: /* CMD_GET_READERS_STATE */ - LLOGLN(0, ("scard_process_msg: CMD_GET_READERS_STATE")); - rv = scard_process_get_readers_state(con, in_s); - break; - case 0x13: /* CMD_WAIT_READER_STATE_CHANGE */ - LLOGLN(0, ("scard_process_msg: CMD_WAIT_READER_STATE_CHANGE")); - rv = scard_process_read_state_change(con, in_s); - break; - case 0x14: /* CMD_STOP_WAITING_READER_STATE_CHANGE */ - LLOGLN(0, ("scard_process_msg: CMD_STOP_WAITING_READER_STATE_CHANGE")); - rv = scard_process_stop_read_state_change(con, in_s); - break; default: LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command)); rv = 1; @@ -693,8 +589,6 @@ scard_pcsc_init(void) int index; LLOGLN(0, ("scard_pcsc_init:")); - g_memset(g_pcsc_reader_states, 0, sizeof(g_pcsc_reader_states)); - g_memset(g_xrdp_reader_states, 0, sizeof(g_xrdp_reader_states)); if (g_lis == 0) { g_lis = trans_create(2, 8192, 8192); @@ -725,14 +619,6 @@ scard_pcsc_init(void) port)); return 1; } - g_snprintf(g_pub_file_name, 255, "%s/pcscd.pub", g_pcsclite_ipc_dir); - g_pub_file_fd = g_file_open(g_pub_file_name); - index = 0; - while (index < 65537) - { - g_file_write(g_pub_file_fd, "", 1); - index++; - } } return 0; } @@ -749,8 +635,6 @@ scard_pcsc_deinit(void) g_file_close(g_pub_file_fd); g_pub_file_fd = 0; - g_file_delete(g_pub_file_name); - g_pub_file_name[0] = 0; if (g_remove_dir(g_pcsclite_ipc_dir) != 0) { diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index fd842a80..81bf5046 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -28,13 +28,18 @@ int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); int APP_CC scard_pcsc_check_wait_objs(void); int APP_CC scard_pcsc_init(void); int APP_CC scard_pcsc_deinit(void); -int APP_CC scard_function_establish_context_return(struct trans *con, tui32 context); - +int APP_CC scard_function_establish_context_return(struct trans *con, + struct stream *in_s, + int len); +int APP_CC scard_function_release_context_return(struct trans *con, + struct stream *in_s, + int len); int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, int len); int APP_CC scard_function_get_status_change_return(struct trans *con, - struct stream *in_s, int len); + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */ From 6fcf380eadb550bf0d2aeac1da4b8f7b68b7b0f6 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 16 Sep 2013 11:14:48 -0700 Subject: [PATCH 23/32] added a --enable-tjpeg option for turbo jpeg --- configure.ac | 4 ++ libxrdp/Makefile.am | 7 +++ libxrdp/xrdp_jpeg_compress.c | 82 +++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 11188d36..e8823350 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,10 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg], [Build jpeg module (default: no)]), [jpeg=true], [jpeg=false]) AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue]) +AC_ARG_ENABLE(tjpeg, AS_HELP_STRING([--enable-tjpeg], + [Build turbo jpeg module(assumes /opt/libjpeg-turbo) (default: no)]), + [tjpeg=true], [tjpeg=false]) +AM_CONDITIONAL(XRDP_TJPEG, [test x$tjpeg = xtrue]) AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound], [Build simple pulse audio interface (default: no)]), [simplesound=true], [simplesound=false]) diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index 279113b8..6564da36 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -16,10 +16,17 @@ EXTRA_DEFINES += -DXRDP_NEUTRINORDP EXTRA_LIBS += $(FREERDP_LIBS) endif +if XRDP_TJPEG +EXTRA_DEFINES += -DXRDP_JPEG -DXRDP_TJPEG +EXTRA_INCLUDES += -I/opt/libjpeg-turbo/include +EXTRA_FLAGS += -L/opt/libjpeg-turbo/lib -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib +EXTRA_LIBS += -lturbojpeg +else if XRDP_JPEG EXTRA_DEFINES += -DXRDP_JPEG EXTRA_LIBS += -ljpeg endif +endif if GOT_PREFIX EXTRA_INCLUDES += -I$(prefix)/include diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index 82a816a0..e402f7d0 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -20,7 +20,87 @@ #include "libxrdp.h" -#if defined(XRDP_JPEG) +#if defined(XRDP_TJPEG) + +/* turbo jpeg */ + +#include +#include +#include +#include + +static tjhandle g_tj_han = 0; /* turbojpeg handle */ + +/*****************************************************************************/ +int APP_CC +xrdp_jpeg_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, + int e, int quality) +{ + int error; + int i; + int j; + unsigned int pixel; + unsigned int *src32; + unsigned int *dst32; + unsigned long cdata_bytes; + unsigned char *src_buf; + unsigned char *dst_buf; + char *temp_buf; + + if (bpp != 24) + { + g_writeln("bpp wrong %d", bpp); + return height; + } + if (g_tj_han == 0) + { + g_tj_han = tjInitCompress(); + } + cdata_bytes = byte_limit; + src_buf = (unsigned char *) in_data; + dst_buf = (unsigned char *) (s->p); + temp_buf = 0; + if (e == 0) + { + src_buf = (unsigned char*)in_data; + } + else + { + temp_buf = (char *) g_malloc((width + e) * height * 4, 0); + dst32 = (unsigned int *) temp_buf; + src32 = (unsigned int *) in_data; + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + pixel = *src32; + src32++; + *dst32 = pixel; + dst32++; + } + for (i = 0; i < e; i++) + { + *dst32 = pixel; + dst32++; + } + } + src_buf = (unsigned char *) temp_buf; + } + dst_buf = (unsigned char*)(s->p); + error = tjCompress(g_tj_han, src_buf, width + e, (width + e) * 4, height, + TJPF_XBGR, dst_buf, &cdata_bytes, + TJSAMP_420, quality, 0); + //g_writeln("error %d %d %d %d", error, width, e, height); + s->p += cdata_bytes; + g_free(temp_buf); + return height; +} + +#elif defined(XRDP_JPEG) + +/* libjpeg */ #include #include From d2f0e459f478ea2e9e940da8933acde23dccf2bc Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 16 Sep 2013 11:54:46 -0700 Subject: [PATCH 24/32] X11rdp: use lossy compression in more places --- xorg/X11R7.6/rdp/rdpPolyFillRect.c | 27 ++++++++++++++++++--------- xorg/X11R7.6/rdp/rdpPutImage.c | 2 +- xorg/X11R7.6/rdp/rdpdraw.c | 8 ++++---- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/xorg/X11R7.6/rdp/rdpPolyFillRect.c b/xorg/X11R7.6/rdp/rdpPolyFillRect.c index 1043a5d9..af68e83f 100644 --- a/xorg/X11R7.6/rdp/rdpPolyFillRect.c +++ b/xorg/X11R7.6/rdp/rdpPolyFillRect.c @@ -108,7 +108,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, LLOGLN(10, ("rdpPolyFillRect: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; - dirty_type = RDI_IMGLL; + dirty_type = (FillTiled == pGC->fillStyle) ? + RDI_IMGLY : RDI_IMGLL; } else { @@ -125,7 +126,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, LLOGLN(10, ("rdpPolyFillRect: getting dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; - dirty_type = RDI_FILL; + dirty_type = (FillTiled == pGC->fillStyle) ? + RDI_IMGLY : RDI_IMGLL; } else { @@ -151,7 +153,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, LLOGLN(10, ("rdpPolyFillRect: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; - dirty_type = RDI_IMGLL; + dirty_type = (FillTiled == pGC->fillStyle) ? + RDI_IMGLY : RDI_IMGLL; } else { @@ -192,7 +195,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, } else { - draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, 2); + draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, + dirty_type, 2); } } else if (got_id) @@ -214,7 +218,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) { box = REGION_RECTS(fill_reg)[j]; - rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_fill_rect(box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1); } rdpup_set_opcode(GXcopy); @@ -251,13 +256,15 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ { LLOGLN(10, ("rdpPolyFillRect: 3")); - draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + draw_item_add_fill_region(pDirtyPriv, &clip_reg, + pGC->fgPixel, pGC->alu); } else { LLOGLN(10, ("rdpPolyFillRect: 4")); - draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, 2); + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, + dirty_type, 2); } } else if (got_id) @@ -281,7 +288,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; - rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_fill_rect(box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1); } rdpup_set_opcode(GXcopy); @@ -291,7 +299,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_send_area(&id, box.x1, box.y1, + box.x2 - box.x1, box.y2 - box.y1); } } diff --git a/xorg/X11R7.6/rdp/rdpPutImage.c b/xorg/X11R7.6/rdp/rdpPutImage.c index ffc179d5..050f5f5f 100644 --- a/xorg/X11R7.6/rdp/rdpPutImage.c +++ b/xorg/X11R7.6/rdp/rdpPutImage.c @@ -135,7 +135,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, LLOGLN(10, ("rdpPutImage: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; - dirty_type = RDI_IMGLL; + dirty_type = RDI_IMGLY; } else { diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c index f9dff80a..2bb6ccc4 100644 --- a/xorg/X11R7.6/rdp/rdpdraw.c +++ b/xorg/X11R7.6/rdp/rdpdraw.c @@ -827,7 +827,7 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv) LLOGLN(10, ("xrdp_is_os: queuing invalidating all")); draw_item_remove_all(priv); RegionInit(®1, &box, 0); - draw_item_add_img_region(priv, ®1, GXcopy, RDI_IMGLL, 16); + draw_item_add_img_region(priv, ®1, GXcopy, RDI_IMGLY, 16); RegionUninit(®1); priv->is_dirty = 1; priv->con_number = g_con_number; @@ -1212,7 +1212,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h, if (g_do_dirty_ons) { - draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLL, 16); + draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLY, 16); } else { @@ -1250,7 +1250,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed) if (g_do_dirty_ons) { - draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLL, 16); + draw_item_add_img_region(&g_screenPriv, ®, GXcopy, RDI_IMGLY, 16); } else { @@ -1415,7 +1415,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, LLOGLN(10, ("rdpComposite: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; - dirty_type = RDI_IMGLL; + dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY; } else { From 9263b22cb295ae5eefa3bf25e35873b718966325 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 19 Sep 2013 01:03:20 -0700 Subject: [PATCH 25/32] chansrv: work on smartcard --- sesman/chansrv/pcsc/xrdp_pcsc.c | 107 +++++++++++++++++++++++--------- sesman/chansrv/smartcard.c | 16 ++--- sesman/chansrv/smartcard.h | 19 +++--- sesman/chansrv/smartcard_pcsc.c | 38 ++++++++++-- 4 files changed, 128 insertions(+), 52 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 251fdd82..520c9971 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -55,6 +55,7 @@ typedef struct _SCARD_IO_REQUEST #define SCARD_ESTABLISH_CONTEXT 0x01 #define SCARD_RELEASE_CONTEXT 0x02 #define SCARD_LIST_READERS 0x03 +#define SCARD_CONNECT 0x04 #define SCARD_GET_STATUS_CHANGE 0x0C #define SCARD_S_SUCCESS 0x00000000 @@ -79,6 +80,9 @@ static int g_sck = -1; /* unix domain socket */ static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +/* for pcsc_stringify_error */ +static char g_error_str[512]; + /*****************************************************************************/ static int get_display_num_from_display(const char *display_text) @@ -152,6 +156,11 @@ connect_to_chansrv(void) struct sockaddr_un saddr; struct sockaddr *psaddr; + if (g_sck != -1) + { + /* already connected */ + return 0; + } xrdp_session = getenv("XRDP_SESSION"); if (xrdp_session == NULL) { @@ -180,34 +189,31 @@ connect_to_chansrv(void) LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis)); return 1; } + g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); if (g_sck == -1) { - g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); - if (g_sck == -1) - { - LLOGLN(0, ("connect_to_chansrv: error, socket failed")); - return 1; - } - memset(&saddr, 0, sizeof(struct sockaddr_un)); - saddr.sun_family = AF_UNIX; - bytes = sizeof(saddr.sun_path); - snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); - saddr.sun_path[bytes - 1] = 0; - LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); - psaddr = (struct sockaddr *) &saddr; - bytes = sizeof(struct sockaddr_un); - error = connect(g_sck, psaddr, bytes); - if (error == 0) - { - } - else - { - perror("connect_to_chansrv"); - close(g_sck); - g_sck = -1; - LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path)); - return 1; - } + LLOGLN(0, ("connect_to_chansrv: error, socket failed")); + return 1; + } + memset(&saddr, 0, sizeof(struct sockaddr_un)); + saddr.sun_family = AF_UNIX; + bytes = sizeof(saddr.sun_path); + snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); + saddr.sun_path[bytes - 1] = 0; + LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); + psaddr = (struct sockaddr *) &saddr; + bytes = sizeof(struct sockaddr_un); + error = connect(g_sck, psaddr, bytes); + if (error == 0) + { + } + else + { + perror("connect_to_chansrv"); + close(g_sck); + g_sck = -1; + LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path)); + return 1; } return 0; } @@ -369,6 +375,12 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { + char msg[256]; + int code; + int bytes; + int status; + int offset; + LLOGLN(0, ("SCardConnect:")); if (g_sck == -1) { @@ -376,8 +388,47 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + offset = 0; + SET_UINT32(msg, offset, hContext); + offset += 4; + bytes = strlen(szReader); + if (bytes > 99) + { + LLOGLN(0, ("SCardConnect: error, name too long")); + return SCARD_F_INTERNAL_ERROR; + } + memcpy(msg + offset, szReader, bytes); + memset(msg + bytes, 0, 100 - bytes); + offset += 100; + SET_UINT32(msg, offset, dwShareMode); + offset += 4; + SET_UINT32(msg, offset, dwPreferredProtocols); + offset += 4; + if (send_message(SCARD_CONNECT, msg, offset) != 0) + { + LLOGLN(0, ("SCardConnect: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardConnect: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if (code != SCARD_RELEASE_CONTEXT) + { + LLOGLN(0, ("SCardConnect: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + *phCard = GET_UINT32(msg, 0); + *pdwActiveProtocol = GET_UINT32(msg, 4); + status = GET_UINT32(msg, 8); + LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ @@ -746,8 +797,6 @@ SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, return SCARD_S_SUCCESS; } -static char g_error_str[512]; - /*****************************************************************************/ char * pcsc_stringify_error(const long code) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index b97ffca6..94c08ad4 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -285,7 +285,7 @@ scard_deinit(void) * *****************************************************************************/ int APP_CC -scard_send_irp_establish_context(struct trans *con, int scope) +scard_send_establish_context(struct trans *con, int scope) { IRP *irp; @@ -312,7 +312,7 @@ scard_send_irp_establish_context(struct trans *con, int scope) * Release a previously established Smart Card context *****************************************************************************/ int APP_CC -scard_send_irp_release_context(struct trans *con, tui32 context) +scard_send_release_context(struct trans *con, tui32 context) { IRP *irp; @@ -339,7 +339,7 @@ scard_send_irp_release_context(struct trans *con, tui32 context) * *****************************************************************************/ int APP_CC -scard_send_irp_list_readers(struct trans *con, tui32 context, int wide) +scard_send_list_readers(struct trans *con, tui32 context, int wide) { IRP *irp; @@ -371,9 +371,9 @@ scard_send_irp_list_readers(struct trans *con, tui32 context, int wide) * @param rsa array of READER_STATEs *****************************************************************************/ int APP_CC -scard_send_irp_get_status_change(struct trans *con, tui32 context, int wide, - tui32 timeout, tui32 num_readers, - READER_STATE* rsa) +scard_send_get_status_change(struct trans *con, tui32 context, int wide, + tui32 timeout, tui32 num_readers, + READER_STATE* rsa) { IRP *irp; @@ -403,8 +403,8 @@ scard_send_irp_get_status_change(struct trans *con, tui32 context, int wide, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_irp_connect(struct trans *con, tui32 context, int wide, - READER_STATE* rs) +scard_send_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs) { IRP *irp; diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 44d4fcbc..c763db31 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -73,17 +73,14 @@ int APP_CC scard_get_wait_objs(tbus *objs, int *count, int *timeout); int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); -int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); -int APP_CC scard_send_irp_release_context(struct trans *con, tui32 context); -int APP_CC scard_send_irp_list_readers(struct trans *con, tui32 context, int wide); - -int APP_CC scard_send_irp_get_status_change(struct trans *con, tui32 context, - int wide, tui32 timeout, - tui32 num_readers, READER_STATE* rsa); - -int APP_CC scard_send_irp_connect(struct trans *con, tui32 context, int wide, - READER_STATE* rs); - +int APP_CC scard_send_establish_context(struct trans *con, int scope); +int APP_CC scard_send_release_context(struct trans *con, tui32 context); +int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide); +int APP_CC scard_send_get_status_change(struct trans *con, tui32 context, + int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa); +int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs); int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle); diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index ded872cb..7af1871c 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -55,6 +55,7 @@ #define XRDP_PCSC_STATE_GOT_LR (1 << 1) /* list readers */ #define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ #define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ +#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -123,7 +124,7 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC; in_uint32_le(in_s, dwScope); LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope)); - scard_send_irp_establish_context(con, dwScope); + scard_send_establish_context(con, dwScope); return 0; } @@ -183,7 +184,7 @@ scard_process_release_context(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC; in_uint32_le(in_s, hContext); LLOGLN(0, ("scard_process_release_context: hContext 0x%8.8x", hContext)); - scard_send_irp_release_context(con, hContext); + scard_send_release_context(con, hContext); return 0; } @@ -232,7 +233,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; in_uint32_le(in_s, hContext); LLOGLN(0, ("scard_process_list_readers: dwScope 0x%8.8x", hContext)); - scard_send_irp_list_readers(con, hContext, 1); + scard_send_list_readers(con, hContext, 1); return 0; } @@ -318,6 +319,34 @@ scard_function_list_readers_return(struct trans *con, return trans_force_write(con); } +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_connect(struct trans *con, struct stream *in_s) +{ + int hContext; + char szReader[100]; + READER_STATE rs; + + LLOGLN(0, ("scard_process_connect:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) + { + LLOGLN(0, ("scard_process_connect: opps")); + return 1; + } + g_memset(&rs, 0, sizeof(rs)); + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_C; + in_uint32_le(in_s, hContext); + in_uint8a(in_s, szReader, 100); + in_uint32_le(in_s, rs.shared_mode_flag); + in_uint32_le(in_s, rs.preferred_protocol); + LLOGLN(0, ("scard_process_connect: dwShareMode 0x%8.8x " + "dwPreferredProtocols 0x%8.8x", rs.shared_mode_flag, + rs.preferred_protocol)); + scard_send_connect(con, hContext, 1, &rs); + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -367,7 +396,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC; - scard_send_irp_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); + scard_send_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); g_free(rsa); @@ -453,6 +482,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x04: /* SCARD_CONNECT */ LLOGLN(0, ("scard_process_msg: SCARD_CONNECT")); + rv = scard_process_connect(con, in_s); break; case 0x05: /* SCARD_RECONNECT */ From 2c021f5fab1f0f6f571874431f3d540c6f4add2f Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 19 Sep 2013 10:59:29 -0700 Subject: [PATCH 26/32] don't use a global for turbo jpeg --- libxrdp/libxrdp.h | 7 +++- libxrdp/xrdp_jpeg_compress.c | 73 +++++++++++++++++++++++++++++++----- libxrdp/xrdp_orders.c | 4 +- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index d31edbb4..da3bcc88 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -211,6 +211,7 @@ struct xrdp_orders int order_count; int order_level; /* inc for every call to xrdp_orders_init */ struct xrdp_orders_state orders_state; + void* jpeg_han; }; #define PROTO_RDP_40 1 @@ -431,10 +432,14 @@ xrdp_bitmap_compress(char* in_data, int width, int height, int start_line, struct stream* temp_s, int e); int APP_CC -xrdp_jpeg_compress(char* in_data, int width, int height, +xrdp_jpeg_compress(void *handle, char* in_data, int width, int height, struct stream* s, int bpp, int byte_limit, int start_line, struct stream* temp_s, int e, int quality); +void *APP_CC +xrdp_jpeg_init(void); +int APP_CC +xrdp_jpeg_deinit(void *handle); /* xrdp_channel.c */ struct xrdp_channel* APP_CC diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index e402f7d0..a41bd1cf 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -29,11 +29,9 @@ #include #include -static tjhandle g_tj_han = 0; /* turbojpeg handle */ - /*****************************************************************************/ int APP_CC -xrdp_jpeg_compress(char *in_data, int width, int height, +xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, struct stream *s, int bpp, int byte_limit, int start_line, struct stream *temp_s, int e, int quality) @@ -48,16 +46,19 @@ xrdp_jpeg_compress(char *in_data, int width, int height, unsigned char *src_buf; unsigned char *dst_buf; char *temp_buf; + tjhandle tj_han; if (bpp != 24) { - g_writeln("bpp wrong %d", bpp); + g_writeln("xrdp_jpeg_compress: bpp wrong %d", bpp); return height; } - if (g_tj_han == 0) + if (handle == 0) { - g_tj_han = tjInitCompress(); + g_writeln("xrdp_jpeg_compress: handle is nil"); + return height; } + tj_han = (tjhandle) handle; cdata_bytes = byte_limit; src_buf = (unsigned char *) in_data; dst_buf = (unsigned char *) (s->p); @@ -89,15 +90,39 @@ xrdp_jpeg_compress(char *in_data, int width, int height, src_buf = (unsigned char *) temp_buf; } dst_buf = (unsigned char*)(s->p); - error = tjCompress(g_tj_han, src_buf, width + e, (width + e) * 4, height, + error = tjCompress(tj_han, src_buf, width + e, (width + e) * 4, height, TJPF_XBGR, dst_buf, &cdata_bytes, TJSAMP_420, quality, 0); - //g_writeln("error %d %d %d %d", error, width, e, height); s->p += cdata_bytes; g_free(temp_buf); return height; } +/*****************************************************************************/ +void *APP_CC +xrdp_jpeg_init(void) +{ + tjhandle tj_han; + + tj_han = tjInitCompress(); + return tj_han; +} + +/*****************************************************************************/ +int APP_CC +xrdp_jpeg_deinit(void *handle) +{ + tjhandle tj_han; + + if (handle == 0) + { + return 0; + } + tj_han = (tjhandle) handle; + tjDestroy(tj_han); + return 0; +} + #elif defined(XRDP_JPEG) /* libjpeg */ @@ -285,7 +310,7 @@ jpeg_compress(char *in_data, int width, int height, /*****************************************************************************/ int APP_CC -xrdp_jpeg_compress(char *in_data, int width, int height, +xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, struct stream *s, int bpp, int byte_limit, int start_line, struct stream *temp_s, int e, int quality) @@ -295,11 +320,25 @@ xrdp_jpeg_compress(char *in_data, int width, int height, return height; } +/*****************************************************************************/ +void *APP_CC +xrdp_jpeg_init(void) +{ + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_jpeg_deinit(void *handle) +{ + return 0; +} + #else /*****************************************************************************/ int APP_CC -xrdp_jpeg_compress(char *in_data, int width, int height, +xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, struct stream *s, int bpp, int byte_limit, int start_line, struct stream *temp_s, int e, int quality) @@ -307,4 +346,18 @@ xrdp_jpeg_compress(char *in_data, int width, int height, return height; } +/*****************************************************************************/ +void *APP_CC +xrdp_jpeg_init(void) +{ + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_jpeg_deinit(void *handle) +{ + return 0; +} + #endif diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index f753371d..1d04496e 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -47,6 +47,7 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) init_stream(self->out_s, 16384); self->orders_state.clip_right = 1; /* silly rdp right clip */ self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */ + self->jpeg_han = xrdp_jpeg_init(); return self; } @@ -59,6 +60,7 @@ xrdp_orders_delete(struct xrdp_orders *self) return; } + xrdp_jpeg_deinit(self->jpeg_han); free_stream(self->out_s); g_free(self->orders_state.text_data); g_free(self); @@ -2394,7 +2396,7 @@ xrdp_orders_send_bitmap3(struct xrdp_orders *self, make_stream(temp_s); init_stream(temp_s, 16384); quality = ci->jpeg_prop[0]; - xrdp_jpeg_compress(data, width, height, xr_s, bpp, 16384, + xrdp_jpeg_compress(self->jpeg_han, data, width, height, xr_s, bpp, 16384, height - 1, temp_s, e, quality); s_mark_end(xr_s); bufsize = (int)(xr_s->end - xr_s->data); From cff17f303839a0280a35e10cf99ba144d52240ba Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 19 Sep 2013 12:27:03 -0700 Subject: [PATCH 27/32] xrdp: fix a crash in painter when invalid target is set --- xrdp/xrdp_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 10bea994..51a2de85 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2439,7 +2439,7 @@ server_switch_os_surface(struct xrdp_mod *mod, int rdpindex) bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex); - if (bi != 0) + if ((bi != 0) && (bi->bitmap != 0)) { //g_writeln("server_switch_os_surface: setting target_surface to rdpid %d", id); wm->target_surface = bi->bitmap; From db71bc5d8b7841dee476bee228eadf009cec710f Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Fri, 20 Sep 2013 19:00:14 -0700 Subject: [PATCH 28/32] smartcard: added more messages --- sesman/chansrv/smartcard.c | 255 +++++++++++++++++++++++++++++++++++++ sesman/chansrv/smartcard.h | 28 ++++ 2 files changed, 283 insertions(+) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 94c08ad4..1a81efea 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -32,6 +32,8 @@ /* * TODO * + * o ensure that all wide calls are handled correctly + * * o need to query client for build number and determine whether we should use * SCREDIR_VERSION_XP or SCREDIR_VERSION_LONGHORN * @@ -161,6 +163,7 @@ static int APP_CC scard_get_free_slot(void); static void APP_CC scard_release_resources(void); static void APP_CC scard_send_EstablishContext(IRP* irp, int scope); static void APP_CC scard_send_ReleaseContext(IRP* irp, tui32 context); +static void APP_CC scard_send_IsContextValid(IRP* irp, tui32 context); static void APP_CC scard_send_ListReaders(IRP* irp, tui32 context, int wide); static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, @@ -170,6 +173,9 @@ static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, static void APP_CC scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs); +static void APP_CC scard_send_Reconnect(IRP* irp, tui32 context, + tui32 sc_handle, READER_STATE* rs); + static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle); static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle); @@ -188,6 +194,11 @@ static void APP_CC scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); + +static void APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + static void APP_CC scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); @@ -200,6 +211,10 @@ static void APP_CC scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); +static void APP_CC scard_handle_Reconnect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + static void APP_CC scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); @@ -335,6 +350,33 @@ scard_send_release_context(struct trans *con, tui32 context) return 0; } +/** + * Checks if a previously established context is still valid + *****************************************************************************/ +int APP_CC +scard_send_is_valid_context(struct trans *con, tui32 context) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_IsContextValid_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_IsContextValid(irp, context); + + return 0; +} + /** * *****************************************************************************/ @@ -427,6 +469,42 @@ scard_send_connect(struct trans *con, tui32 context, int wide, return 0; } +/** + * The reconnect method re-establishes a smart card reader handle. On success, + * the handle is valid once again. + * + * @param con connection to client + * @param sc_handle handle to device + * @param rs reader state where following fields are set + * rs.shared_mode_flag + * rs.preferred_protocol + * rs.init_type + *****************************************************************************/ +int APP_CC +scard_send_reconnect(struct trans *con, tui32 context, tui32 sc_handle, + READER_STATE* rs) +{ + IRP *irp; + + /* setup up IRP */ + if ((irp = devredir_irp_new()) == NULL) + { + log_error("system out of memory"); + return 1; + } + + irp->scard_index = g_scard_index; + irp->CompletionId = g_completion_id++; + irp->DeviceId = g_device_id; + irp->callback = scard_handle_Reconnect_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_Reconnect(irp, context, sc_handle, rs); + + return 0; +} + /** * Lock smart card reader for exclusive access for specified smart * card reader handle. @@ -768,6 +846,56 @@ scard_send_ReleaseContext(IRP* irp, tui32 context) xstream_free(s); } +/** + * Checks if a previously established context is still valid + *****************************************************************************/ +static void APP_CC +scard_send_IsContextValid(IRP* irp, tui32 context) +{ + /* see [MS-RDPESC] 3.1.4.3 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_IS_VALID_CONTEXT)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 16 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes context len + * u32 4 bytes context + */ + + xstream_wr_u32_le(s, 16); + + /* insert context */ + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + /** * *****************************************************************************/ @@ -1066,6 +1194,73 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) xstream_free(s); } +/** + * The reconnect method re-establishes a smart card reader handle. On success, + * the handle is valid once again. + * + * @param con connection to client + * @param sc_handle handle to device + * @param rs reader state where following fields are set + * rs.shared_mode_flag + * rs.preferred_protocol + * rs.init_type + *****************************************************************************/ +static void APP_CC +scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) +{ + /* see [MS-RDPESC] 2.2.2.15 */ + /* see [MS-RDPESC] 3.1.4.36 */ + + SMARTCARD* sc; + struct stream* s; + int bytes; + + if ((sc = smartcards[irp->scard_index]) == NULL) + { + log_error("smartcards[%d] is NULL", irp->scard_index); + return; + } + + if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RECONNECT)) == NULL) + return; + + /* + * command format + * + * ...... + * 20 bytes padding + * u32 4 bytes len 8, LE, v1 + * u32 4 bytes filler + * 24 bytes unused (s->p currently pointed here at unused[0]) + * u32 4 bytes dwShareMode + * u32 4 bytes dwPreferredProtocol + * u32 4 bytes dwInitialization + * u32 4 bytes context length + * u32 4 bytes context + * u32 4 bytes handle length + * u32 4 bytes handle + */ + + xstream_seek(s, 24); + xstream_wr_u32_le(s, rs->shared_mode_flag); + xstream_wr_u32_le(s, rs->preferred_protocol); + xstream_wr_u32_le(s, rs->init_type); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, context); + xstream_wr_u32_le(s, 4); + xstream_wr_u32_le(s, sc_handle); + + /* get stream len */ + bytes = xstream_len(s); + + /* InputBufferLength is number of bytes AFTER 20 byte padding */ + *(s->data + 28) = bytes - 56; + + /* send to client */ + send_channel_data(g_rdpdr_chan_id, s->data, bytes); + xstream_free(s); +} + /** * Lock smart card reader for exclusive access for specified smart * card reader handle. @@ -1374,6 +1569,34 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, log_debug("leaving"); } +static void APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("Error checking context validity"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + /** * *****************************************************************************/ @@ -1470,6 +1693,38 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, log_debug("leaving"); } +/** + * + *****************************************************************************/ +static void APP_CC +scard_handle_Reconnect_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) +{ + tui32 len; + + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) + { + log_error("DeviceId/CompletionId do not match those in IRP"); + return; + } + + if (IoStatus != 0) + { + log_error("failed to reconnect"); + /* LK_TODO delete irp and smartcard entry */ + return; + } + + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); + + log_debug("leaving"); +} + /** * *****************************************************************************/ diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index c763db31..a2019535 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -43,6 +43,11 @@ #define SCARD_PROTOCOL_DEFAULT 0x80000000 #define SCARD_PROTOCOL_OPTIMAL 0x00000000 +/* initialization type */ +#define SCARD_LEAVE_CARD 0x00000000 /* do not do anything */ +#define SCARD_RESET_CARD 0x00000001 /* reset smart card */ +#define SCARD_UNPOWER_CARD 0x00000002 /* turn off and reset card */ + typedef struct reader_state { char reader_name[128]; @@ -66,6 +71,12 @@ typedef struct reader_state */ tui32 preferred_protocol; + /* + * initialization type, must be one of the initialization type + * defined above + */ + tui32 init_type; + } READER_STATE; void scard_device_announce(tui32 device_id); @@ -75,15 +86,32 @@ int APP_CC scard_init(void); int APP_CC scard_deinit(void); int APP_CC scard_send_establish_context(struct trans *con, int scope); int APP_CC scard_send_release_context(struct trans *con, tui32 context); +int APP_CC scard_send_is_valid_context(struct trans *con, tui32 context); int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide); + int APP_CC scard_send_get_status_change(struct trans *con, tui32 context, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); + int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide, READER_STATE* rs); + +int APP_CC scard_send_reconnect(struct trans *con, tui32 context, + tui32 sc_handle, READER_STATE* rs); + int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle); int APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle); +/* + SCardReconnect + SCardTransmit + SCardControl + SCardListReaderGroups + not needed: SCardFreeMemory + SCardCancel + SCardGetAttrib + SCardSetAttrib + */ #endif /* end #ifndef _SMARTCARD_C */ From dfd78c722b738e8db4c096393b6ecf0e26435f40 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 12:16:52 -0700 Subject: [PATCH 29/32] chansrv: fix for deadlock --- common/trans.c | 83 ++++++++++++++++++++++++++++++++++++++++ common/trans.h | 3 ++ sesman/chansrv/chansrv.c | 14 ++++++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/common/trans.c b/common/trans.c index 8313b606..408b4a7e 100644 --- a/common/trans.c +++ b/common/trans.c @@ -291,6 +291,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) size = (int)(out_s->end - out_s->data); total = 0; + self->in_write = 1; while (total < size) { sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); @@ -308,6 +309,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* term */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } } @@ -317,6 +319,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } } @@ -324,6 +327,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; + self->in_write = 0; return 1; } else @@ -331,6 +335,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) total = total + sent; } } + self->in_write = 0; return 0; } @@ -342,6 +347,84 @@ trans_force_write(struct trans *self) return trans_force_write_s(self, self->out_s); } +/*****************************************************************************/ +int APP_CC +trans_write_check(struct trans* self, int timeout) +{ + int size; + int total; + int sent; + int error; + tbus robjs[1]; + tbus wobjs[1]; + struct stream *out_s; + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + out_s = self->out_s; + + size = (int)(out_s->end - out_s->data); + total = 0; + + self->in_write = 1; + while (total < size) + { + robjs[0] = self->sck; + wobjs[0] = self->sck; + error = g_obj_wait(robjs, 1, wobjs, 1, timeout); + if (error != 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + + if (!g_tcp_can_send(self->sck, 0)) + { + trans_check_wait_objs(self); + continue; + } + + sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); + + if (sent == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + if (!g_tcp_can_send(self->sck, 10)) + { + /* check for term here */ + } + } + else + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + } + else if (sent == 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + self->in_write = 0; + return 1; + } + else + { + total = total + sent; + } + } + self->in_write = 0; + + return 0; +} + /*****************************************************************************/ int APP_CC trans_connect(struct trans *self, const char *server, const char *port, diff --git a/common/trans.h b/common/trans.h index 4b8e3b42..d9ad6c19 100644 --- a/common/trans.h +++ b/common/trans.h @@ -54,6 +54,7 @@ struct trans struct stream* out_s; char* listen_filename; tis_term is_term; /* used to test for exit */ + int in_write; }; struct trans* APP_CC @@ -73,6 +74,8 @@ trans_force_read(struct trans* self, int size); int APP_CC trans_force_write(struct trans* self); int APP_CC +trans_write_check(struct trans* self, int timeout); +int APP_CC trans_connect(struct trans* self, const char* server, const char* port, int timeout); int APP_CC diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index c3d1aa79..56626c77 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -293,10 +293,20 @@ send_data_from_chan_item(struct chan_item *chan_item) out_uint32_le(s, cod->s->size); out_uint8a(s, cod->s->p, size); s_mark_end(s); - LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- " + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- " "size %d chan_flags 0x%8.8x", size, chan_flags)); g_sent = 1; - error = trans_force_write(g_con_trans); + if (g_con_trans->in_write) + { + g_writeln("chansrv::send_data_from_chan_item: error, " + "write while in_write"); + error = 1; + } + else + { + /* write but check for read if blocked */ + error = trans_write_check(g_con_trans, -1); + } if (error != 0) { From 3b743f64ebf4c857a5784add1da72ba41fcf7025 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 18:08:22 -0700 Subject: [PATCH 30/32] chansrv: deadlock, add trans copy func --- common/trans.c | 171 ++++++++++++++++++++++++--------------- common/trans.h | 4 +- sesman/chansrv/chansrv.c | 29 +++---- 3 files changed, 122 insertions(+), 82 deletions(-) diff --git a/common/trans.c b/common/trans.c index 408b4a7e..ae150940 100644 --- a/common/trans.c +++ b/common/trans.c @@ -90,6 +90,86 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count) return 0; } +/*****************************************************************************/ +int APP_CC +trans_get_wait_objs_rw(struct trans *self, + tbus *robjs, int *rcount, + tbus *wobjs, int *wcount) +{ + if (self == 0) + { + return 1; + } + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + robjs[*rcount] = self->sck; + (*rcount)++; + + if (self->wait_s != 0) + { + wobjs[*wcount] = self->sck; + (*wcount)++; + } + + return 0; +} + +/*****************************************************************************/ +int APP_CC +send_waiting(struct trans *self, int block) +{ + struct stream *temp_s; + int bytes; + int sent; + int timeout; + int cont; + + timeout = block ? 100 : 0; + cont = 1; + while (cont) + { + if (self->wait_s != 0) + { + temp_s = self->wait_s; + if (g_tcp_can_send(self->sck, timeout)) + { + bytes = (int) (temp_s->end - temp_s->p); + sent = g_tcp_send(self->sck, temp_s->p, bytes, 0); + if (sent > 0) + { + temp_s->p += sent; + if (temp_s->p >= temp_s->end) + { + self->wait_s = (struct stream *) (temp_s->next_packet); + free_stream(temp_s); + } + } + else if (sent == 0) + { + return 1; + } + else + { + if (!g_tcp_last_error_would_block(self->sck)) + { + return 1; + } + } + } + } + else + { + break; + } + cont = block; + } + return 0; +} + /*****************************************************************************/ int APP_CC trans_check_wait_objs(struct trans *self) @@ -203,6 +283,12 @@ trans_check_wait_objs(struct trans *self) } } } + if (send_waiting(self, 0) != 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } } return rv; @@ -291,7 +377,12 @@ trans_force_write_s(struct trans *self, struct stream *out_s) size = (int)(out_s->end - out_s->data); total = 0; - self->in_write = 1; + if (send_waiting(self, 1) != 0) + { + self->status = TRANS_STATUS_DOWN; + return 1; + } + while (total < size) { sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); @@ -309,7 +400,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* term */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } } @@ -319,7 +409,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } } @@ -327,7 +416,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) { /* error */ self->status = TRANS_STATUS_DOWN; - self->in_write = 0; return 1; } else @@ -335,7 +423,6 @@ trans_force_write_s(struct trans *self, struct stream *out_s) total = total + sent; } } - self->in_write = 0; return 0; } @@ -349,15 +436,12 @@ trans_force_write(struct trans *self) /*****************************************************************************/ int APP_CC -trans_write_check(struct trans* self, int timeout) +trans_write_copy(struct trans *self) { int size; - int total; - int sent; - int error; - tbus robjs[1]; - tbus wobjs[1]; struct stream *out_s; + struct stream *wait_s; + struct stream *temp_s; if (self->status != TRANS_STATUS_UP) { @@ -365,63 +449,24 @@ trans_write_check(struct trans* self, int timeout) } out_s = self->out_s; - size = (int)(out_s->end - out_s->data); - total = 0; - - self->in_write = 1; - while (total < size) + make_stream(wait_s); + init_stream(wait_s, size); + out_uint8a(wait_s, out_s->data, size); + s_mark_end(wait_s); + if (self->wait_s == 0) { - robjs[0] = self->sck; - wobjs[0] = self->sck; - error = g_obj_wait(robjs, 1, wobjs, 1, timeout); - if (error != 0) - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - - if (!g_tcp_can_send(self->sck, 0)) - { - trans_check_wait_objs(self); - continue; - } - - sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); - - if (sent == -1) - { - if (g_tcp_last_error_would_block(self->sck)) - { - if (!g_tcp_can_send(self->sck, 10)) - { - /* check for term here */ - } - } - else - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - } - else if (sent == 0) - { - /* error */ - self->status = TRANS_STATUS_DOWN; - self->in_write = 0; - return 1; - } - else + self->wait_s = wait_s; + } + else + { + temp_s = self->wait_s; + while (temp_s->next_packet != 0) { - total = total + sent; + temp_s = (struct stream *) (temp_s->next_packet); } + temp_s->next_packet = wait_s; } - self->in_write = 0; - return 0; } diff --git a/common/trans.h b/common/trans.h index d9ad6c19..b7b9c20d 100644 --- a/common/trans.h +++ b/common/trans.h @@ -54,7 +54,7 @@ struct trans struct stream* out_s; char* listen_filename; tis_term is_term; /* used to test for exit */ - int in_write; + struct stream* wait_s; }; struct trans* APP_CC @@ -74,7 +74,7 @@ trans_force_read(struct trans* self, int size); int APP_CC trans_force_write(struct trans* self); int APP_CC -trans_write_check(struct trans* self, int timeout); +trans_write_copy(struct trans* self); int APP_CC trans_connect(struct trans* self, const char* server, const char* port, int timeout); diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 56626c77..86c50960 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -296,18 +296,8 @@ send_data_from_chan_item(struct chan_item *chan_item) LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- " "size %d chan_flags 0x%8.8x", size, chan_flags)); g_sent = 1; - if (g_con_trans->in_write) - { - g_writeln("chansrv::send_data_from_chan_item: error, " - "write while in_write"); - error = 1; - } - else - { - /* write but check for read if blocked */ - error = trans_write_check(g_con_trans, -1); - } + error = trans_write_copy(g_con_trans); if (error != 0) { return 1; @@ -402,7 +392,7 @@ send_init_response_message(void) out_uint32_le(s, 2); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -425,7 +415,7 @@ send_channel_setup_response_message(void) out_uint32_le(s, 4); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -448,7 +438,7 @@ send_channel_data_response_message(void) out_uint32_le(s, 6); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); - return trans_force_write(g_con_trans); + return trans_write_copy(g_con_trans); } /*****************************************************************************/ @@ -647,7 +637,7 @@ process_message_channel_data(struct stream *s) if (chan_flags & 2) /* last */ { s_mark_end(ls); - trans_force_write(g_api_con_trans); + trans_write_copy(g_api_con_trans); } } } @@ -1051,7 +1041,9 @@ THREAD_RV THREAD_CC channel_thread_loop(void *in_val) { tbus objs[32]; + tbus wobjs[32]; int num_objs; + int num_wobjs; int timeout; int error; THREAD_RV rv; @@ -1065,12 +1057,13 @@ channel_thread_loop(void *in_val) { timeout = -1; num_objs = 0; + num_wobjs = 0; objs[num_objs] = g_term_event; num_objs++; trans_get_wait_objs(g_lis_trans, objs, &num_objs); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); - while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) + while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0) { check_timeout(); if (g_is_wait_obj_set(g_term_event)) @@ -1145,10 +1138,12 @@ channel_thread_loop(void *in_val) xfuse_check_wait_objs(); timeout = -1; num_objs = 0; + num_wobjs = 0; objs[num_objs] = g_term_event; num_objs++; trans_get_wait_objs(g_lis_trans, objs, &num_objs); - trans_get_wait_objs(g_con_trans, objs, &num_objs); + trans_get_wait_objs_rw(g_con_trans, objs, &num_objs, + wobjs, &num_wobjs); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); trans_get_wait_objs(g_api_con_trans, objs, &num_objs); xcommon_get_wait_objs(objs, &num_objs, &timeout); From fc31ae1f48bc2162c49daee8b79f66c67c9cf428 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Sep 2013 19:17:50 -0700 Subject: [PATCH 31/32] trans: reset p when adding to trans list --- common/trans.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/trans.c b/common/trans.c index ae150940..5d5c6125 100644 --- a/common/trans.c +++ b/common/trans.c @@ -454,6 +454,7 @@ trans_write_copy(struct trans *self) init_stream(wait_s, size); out_uint8a(wait_s, out_s->data, size); s_mark_end(wait_s); + wait_s->p = wait_s->data; if (self->wait_s == 0) { self->wait_s = wait_s; From 675e1b86c44d6b75032ec4cb40f4ccfb8cd06358 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 24 Sep 2013 11:17:50 -0700 Subject: [PATCH 32/32] chansrv: work on smartcard --- sesman/chansrv/pcsc/xrdp_pcsc.c | 52 ++++++++++++++++++++++++++---- sesman/chansrv/smartcard.c | 8 ++++- sesman/chansrv/smartcard_pcsc.c | 57 +++++++++++++++++++++++++++++++++ sesman/chansrv/smartcard_pcsc.h | 3 ++ 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 520c9971..b93dba12 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -52,11 +52,22 @@ typedef struct _SCARD_IO_REQUEST #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) -#define SCARD_ESTABLISH_CONTEXT 0x01 -#define SCARD_RELEASE_CONTEXT 0x02 -#define SCARD_LIST_READERS 0x03 -#define SCARD_CONNECT 0x04 -#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_ESTABLISH_CONTEXT 0x01 +#define SCARD_RELEASE_CONTEXT 0x02 +#define SCARD_LIST_READERS 0x03 +#define SCARD_CONNECT 0x04 +#define SCARD_RECONNECT 0x05 +#define SCARD_DISCONNECT 0x06 +#define SCARD_BEGIN_TRANSACTION 0x07 +#define SCARD_END_TRANSACTION 0x08 +#define SCARD_TRANSMIT 0x09 +#define SCARD_CONTROL 0x0A +#define SCARD_STATUS 0x0B +#define SCARD_GET_STATUS_CHANGE 0x0C +#define SCARD_CANCEL 0x0D +#define SCARD_CANCEL_TRANSACTION 0x0E +#define SCARD_GET_ATTRIB 0x0F +#define SCARD_SET_ATTRIB 0x10 #define SCARD_S_SUCCESS 0x00000000 #define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) @@ -417,7 +428,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - if (code != SCARD_RELEASE_CONTEXT) + if (code != SCARD_CONNECT) { LLOGLN(0, ("SCardConnect: error, bad code")); pthread_mutex_unlock(&g_mutex); @@ -467,6 +478,11 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) { + char msg[256]; + int code; + int bytes; + int status; + LLOGLN(0, ("SCardBeginTransaction:")); if (g_sck == -1) { @@ -474,8 +490,30 @@ SCardBeginTransaction(SCARDHANDLE hCard) return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hCard); + if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4)) + { + LLOGLN(0, ("SCardBeginTransaction: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 1a81efea..e4d144bd 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -1163,6 +1163,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) /* insert reader name */ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99); + xstream_wr_u32_le(s, 0); + xstream_wr_u32_le(s, 0); xstream_wr_u32_le(s, num_chars); if (wide) { @@ -1178,6 +1180,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) xstream_wr_u8(s, w_reader_name[index]); } } + align_s(s, 4); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1670,6 +1673,7 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -1689,7 +1693,9 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_connect_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 7af1871c..4d496c97 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -56,6 +56,7 @@ #define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ #define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ #define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */ +#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -347,6 +348,61 @@ scard_process_connect(struct trans *con, struct stream *in_s) return 0; } +/*****************************************************************************/ +int APP_CC +scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len) +{ + int dwActiveProtocol; + int hCard; + int bytes; + struct stream *out_s; + + g_hexdump(in_s->p, len); + if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) + { + LLOGLN(0, ("scard_function_connect_return: opps")); + return 1; + } + g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 36); + in_uint32_le(in_s, hCard); + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, hCard); + out_uint32_le(out_s, dwActiveProtocol); + out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */ + s_mark_end(out_s); + bytes = (int) (out_s->end - out_s->data); + s_pop_layer(out_s, iso_hdr); + out_uint32_le(out_s, bytes - 8); + out_uint32_le(out_s, 0x04); /* SCARD_CONNECT 0x04 */ + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_begin_transaction(struct trans *con, struct stream *in_s) +{ + int hCard; + + LLOGLN(0, ("scard_process_begin_transaction:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) + { + LLOGLN(0, ("scard_process_begin_transaction: opps")); + return 1; + } + g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT; + in_uint32_le(in_s, hCard); + LLOGLN(0, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); + scard_send_begin_transaction(con, hCard); + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -495,6 +551,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x07: /* SCARD_BEGIN_TRANSACTION */ LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION")); + rv = scard_process_begin_transaction(con, in_s); break; case 0x08: /* SCARD_END_TRANSACTION */ diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index 81bf5046..94effea9 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -41,5 +41,8 @@ int APP_CC scard_function_list_readers_return(struct trans *con, int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, int len); +int APP_CC scard_function_connect_return(struct trans *con, + struct stream *in_s, + int len); #endif /* end #ifndef _SMARTCARD_PCSC_H */