From 188ca68adb5c312111527e1cef4f9bab014f88d5 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Wed, 11 Sep 2013 19:42:42 -0700 Subject: 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(-) (limited to 'sesman/chansrv') 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 */ -- cgit v1.2.1