scard: added support for connect call

ulab-next
Laxmikant Rashinkar 11 years ago
parent 47ac4a897a
commit 215956353f

@ -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");
}

@ -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 */

Loading…
Cancel
Save