From 215956353fa2b122f7b75a9e344138ab61d4b594 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Fri, 13 Sep 2013 10:20:35 -0700 Subject: [PATCH] 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 */