summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-09-11 19:42:42 -0700
committerLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-09-11 19:42:42 -0700
commit188ca68adb5c312111527e1cef4f9bab014f88d5 (patch)
treea03bd4b77c290334ca34903f663a94200d0a86a4
parent2d112bac8f4359a513cc603e5f58fc625700a6c6 (diff)
downloadxrdp-proprietary-188ca68adb5c312111527e1cef4f9bab014f88d5.tar.gz
xrdp-proprietary-188ca68adb5c312111527e1cef4f9bab014f88d5.zip
scard: added GetStatusChange() msg
-rw-r--r--sesman/chansrv/smartcard.c724
-rw-r--r--sesman/chansrv/smartcard.h43
-rw-r--r--sesman/chansrv/smartcard_pcsc.c2
-rw-r--r--sesman/chansrv/smartcard_pcsc.h23
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 <string.h>
#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 */