From 188ca68adb5c312111527e1cef4f9bab014f88d5 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Wed, 11 Sep 2013 19:42:42 -0700 Subject: [PATCH] scard: added GetStatusChange() msg --- sesman/chansrv/smartcard.c | 834 +++++++++++++++++++------------- sesman/chansrv/smartcard.h | 41 +- sesman/chansrv/smartcard_pcsc.c | 2 +- sesman/chansrv/smartcard_pcsc.h | 23 +- 4 files changed, 538 insertions(+), 362 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,50 +135,147 @@ 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 ** +******************************************************************************/ -/*****************************************************************************/ +static void scard_handle_EstablishContext_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); + +static void scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus); + + +/****************************************************************************** +** ** +** 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); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_get_wait_objs(tbus *objs, int *count, int *timeout) +{ + return scard_pcsc_get_wait_objs(objs, count, timeout); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_check_wait_objs(void) +{ + return scard_pcsc_check_wait_objs(); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_init(void) +{ + log_debug("init"); + return scard_pcsc_init(); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_deinit(void) +{ + log_debug("deinit"); + return scard_pcsc_deinit(); +} + +/** + * + *****************************************************************************/ int APP_CC scard_send_irp_establish_context(struct trans *con, int scope) { 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_EstablishContext_Return; irp->user_data = con; + + /* send IRP to client */ scard_send_EstablishContext(irp, scope); - log_debug("leaving"); + return 0; } -/*****************************************************************************/ +/** + * + *****************************************************************************/ int APP_CC scard_send_irp_list_readers(struct trans *con) { IRP *irp; + /* setup up IRP */ if ((irp = devredir_irp_new()) == NULL) { log_error("system out of memory"); @@ -184,43 +286,398 @@ scard_send_irp_list_readers(struct trans *con) irp->DeviceId = g_device_id; irp->callback = scard_handle_ListReaders_Return; irp->user_data = con; + + /* send IRP to client */ scard_send_ListReaders(irp, 1); - log_debug("leaving"); + + 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 + *****************************************************************************/ +int APP_CC +scard_send_irp_get_status_change(struct trans *con, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa) +{ + 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_GetStatusChange_Return; + irp->user_data = con; + + /* send IRP to client */ + scard_send_GetStatusChange(irp, wide, timeout, num_readers, rsa); + return 0; } /****************************************************************************** -** non static functions ** +** ** +** static functions local to this file ** +** ** ******************************************************************************/ -void APP_CC -scard_device_announce(tui32 device_id) +/** + * Crate a new stream and insert specified IOCTL + * + * @param irp information about the I/O + * @param ioctl the IOCTL code + * + * @return stream with IOCTL inserted in it, NULL on error + *****************************************************************************/ +static struct stream * APP_CC +scard_make_new_ioctl(IRP *irp, tui32 ioctl) { - log_debug("entered: device_id=%d", device_id); - if (g_smartcards_inited) + /* + * format of device control request + * + * DeviceIoRequest + * u16 RDPDR_CTYP_CORE + * u16 PAKID_CORE_DEVICE_IOREQUEST + * u32 DeviceId + * u32 FileId + * u32 CompletionId + * u32 MajorFunction + * u32 MinorFunction + * + * u32 OutputBufferLength SHOULD be 2048 + * u32 InputBufferLength + * u32 IoControlCode + * 20 bytes padding + * xx bytes InputBuffer (variable) + */ + + struct stream *s; + + xstream_new(s, 1024 * 4); + if (s == NULL) { + log_error("system out of memory"); + return s; + } + + devredir_insert_DeviceIoRequest(s, + irp->DeviceId, + irp->FileId, + irp->CompletionId, + IRP_MJ_DEVICE_CONTROL, + 0); + + xstream_wr_u32_le(s, 2048); /* OutputBufferLength */ + xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */ + xstream_wr_u32_le(s, ioctl); /* Ioctl Code */ + xstream_seek(s, 20); /* padding */ + + /* [MS-RPCE] 2.2.6.1 */ + xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */ + xstream_wr_u32_le(s, 0xcccccccc); /* filler */ + + return s; +} + +/** + * Create a new smart card device entry and insert it into smartcards[] + * + * @param device_id DeviceId of new card + * + * @return index into smartcards[] on success, -1 on failure + *****************************************************************************/ +static int APP_CC +scard_add_new_device(tui32 device_id) +{ + int index; + 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) + { + log_error("system out of memory"); + return -1; + } + + sc->DeviceId = device_id; + smartcards[index] = sc; + + return index; +} + +/** + * Find first unused entry in smartcards + * + * @return index of first unused entry in smartcards or -1 if smartcards + * is full + *****************************************************************************/ +static int APP_CC +scard_get_free_slot(void) +{ + int i; + + for (i = 0; i < MAX_SMARTCARDS; i++) + { + if (smartcards[i] == NULL) + { + log_debug("found free slot at index %d", i); + return i; + } + } + + log_error("too many smart card devices; rejecting this one"); + return -1; +} + +/** + * Release resources prior to shutting down + *****************************************************************************/ +static void APP_CC +scard_release_resources(void) +{ + int i; + + for (i = 0; i < MAX_SMARTCARDS; i++) + { + if (smartcards[i] != NULL) + { + g_free(smartcards[i]); + smartcards[i] = NULL; + } + } +} + +/** + * + *****************************************************************************/ +static void APP_CC +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; } - 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) + + 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); +} + +/** + * + *****************************************************************************/ +static void APP_CC +scard_send_ListReaders(IRP *irp, int wide) +{ + /* see [MS-RDPESC] 2.2.2.4 */ + + SMARTCARD *sc; + struct stream *s; + int bytes; + tui32 ioctl; + + if ((sc = smartcards[irp->scard_index]) == NULL) { - log_debug("scard_add_new_device failed with DeviceId=%d", g_device_id); + log_error("smartcards[%d] is NULL", irp->scard_index); + return; } - else + + 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 + *****************************************************************************/ +static void +scard_send_GetStatusChange(IRP* irp, int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa) +{ + /* 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_debug("added smartcard with DeviceId=%d to list", g_device_id); + log_error("smartcards[%d] is NULL", irp->scard_index); + return; } - //scard_send_establish_context(); + + 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); } /****************************************************************************** -** callbacks into this module ** +** ** +** local callbacks into this module ** +** ** ******************************************************************************/ -void APP_CC +/** + * + *****************************************************************************/ +static void APP_CC scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) @@ -270,6 +727,7 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, g_hexdump(sc->Context, sc->Context_len); } + // LK_TODO delete this //irp->callback = scard_handle_ListReaders_Return; //scard_send_ListReaders(irp, 1); @@ -282,8 +740,10 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, log_debug("leaving"); } -/******************************************************************************/ -void APP_CC +/** + * + *****************************************************************************/ +static void APP_CC scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) @@ -309,311 +769,39 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - scard_function_list_readers_return((struct trans *) (irp->user_data), + scard_function_list_readers_return((struct trans *) irp->user_data, s, len); - - /* LK_TODO */ - //log_debug("dumping %d bytes", len); - //g_hexdump(s->p, len); - log_debug("leaving"); } -/****************************************************************************** -** static functions local to this file ** -******************************************************************************/ - /** * *****************************************************************************/ - -static void APP_CC -scard_send_EstablishContext(IRP *irp, int scope) +static void +scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) { - struct stream *s; - int bytes; + tui32 len; - if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_ESTABLISH_CONTEXT)) == NULL) + log_debug("entered"); + + /* sanity check */ + if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId)) { - log_error("scard_make_new_ioctl failed"); + log_error("DeviceId/CompletionId do not match those in IRP"); 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); -} - -/** - * - *****************************************************************************/ - -static void APP_CC -scard_send_ListReaders(IRP *irp, int wide) -{ - /* see [MS-RDPESC] 2.2.2.4 */ - - SMARTCARD *sc; - struct stream *s; - int bytes; - tui32 ioctl; - - if ((sc = smartcards[irp->scard_index]) == NULL) + if (IoStatus != 0) { - log_error("smartcards[%d] is NULL", irp->scard_index); + log_error("failed to get status change - device not usable"); + /* LK_TODO delete irp and smartcard entry */ return; } - ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W : - SCARD_IOCTL_LIST_READERS_A; + /* get OutputBufferLen */ + xstream_rd_u32_le(s, len); - 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); - - /* - 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 - */ -} - -/** - * Crate a new stream and insert specified IOCTL - * - * @param irp information about the I/O - * @param ioctl the IOCTL code - * - * @return stream with IOCTL inserted in it, NULL on error - *****************************************************************************/ - -static struct stream * APP_CC -scard_make_new_ioctl(IRP *irp, tui32 ioctl) -{ - /* - * format of device control request - * - * DeviceIoRequest - * u16 RDPDR_CTYP_CORE - * u16 PAKID_CORE_DEVICE_IOREQUEST - * u32 DeviceId - * u32 FileId - * u32 CompletionId - * u32 MajorFunction - * u32 MinorFunction - * - * u32 OutputBufferLength SHOULD be 2048 - * u32 InputBufferLength - * u32 IoControlCode - * 20 bytes padding - * xx bytes InputBuffer (variable) - */ - - struct stream *s; - - xstream_new(s, 1024 * 3); - if (s == NULL) - { - log_error("system out of memory"); - return s; - } - - devredir_insert_DeviceIoRequest(s, - irp->DeviceId, - irp->FileId, - irp->CompletionId, - IRP_MJ_DEVICE_CONTROL, - 0); - - xstream_wr_u32_le(s, 2048); /* OutputBufferLength */ - xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */ - xstream_wr_u32_le(s, ioctl); /* Ioctl Code */ - xstream_seek(s, 20); /* padding */ - - /* [MS-RPCE] 2.2.6.1 */ - xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */ - xstream_wr_u32_le(s, 0xcccccccc); /* filler */ - - return s; -} - -/** - * Create a new smart card device entry and insert it into smartcards[] - * - * @param device_id DeviceId of new card - * - * @return index into smartcards[] on success, -1 on failure - *****************************************************************************/ - -static int APP_CC -scard_add_new_device(tui32 device_id) -{ - int index; - 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) - { - log_error("system out of memory"); - return -1; - } - - sc->DeviceId = device_id; - smartcards[index] = sc; - - return index; -} - -/** - * Find first unused entry in smartcards - * - * @return index of first unused entry in smartcards or -1 if smartcards - * is full - *****************************************************************************/ - -static int APP_CC -scard_get_free_slot(void) -{ - int i; - - for (i = 0; i < MAX_SMARTCARDS; i++) - { - if (smartcards[i] == NULL) - { - log_debug("found free slot at index %d", i); - return i; - } - } - - log_error("too many smart card devices; rejecting this one"); - return -1; -} - -/** - * Release resources prior to shutting down - *****************************************************************************/ - -static void APP_CC -scard_release_resources(void) -{ - int i; - - for (i = 0; i < MAX_SMARTCARDS; i++) - { - if (smartcards[i] != NULL) - { - g_free(smartcards[i]); - smartcards[i] = NULL; - } - } -} - -/** - * - *****************************************************************************/ -int APP_CC -scard_get_wait_objs(tbus *objs, int *count, int *timeout) -{ - return scard_pcsc_get_wait_objs(objs, count, timeout); -} - -/** - * - *****************************************************************************/ -int APP_CC -scard_check_wait_objs(void) -{ - return scard_pcsc_check_wait_objs(); -} - -/** - * - *****************************************************************************/ -int APP_CC -scard_init(void) -{ - log_debug("init") - return scard_pcsc_init(); -} - -/** - * - *****************************************************************************/ -int APP_CC -scard_deinit(void) -{ - log_debug("deinit") - return scard_pcsc_deinit(); + 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 */ +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); -/* 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); - +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 */