chansrv: work on smartcard
This commit is contained in:
parent
d22b8b5ed0
commit
a9f37229ac
@ -587,53 +587,50 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s)
|
||||
tui16 cap_type;
|
||||
tui16 cap_len;
|
||||
tui32 cap_version;
|
||||
char* holdp;
|
||||
|
||||
xstream_rd_u16_le(s, num_caps);
|
||||
xstream_seek(s, 2); /* padding */
|
||||
|
||||
for (i = 0; i < num_caps; i++)
|
||||
{
|
||||
holdp = s->p;
|
||||
xstream_rd_u16_le(s, cap_type);
|
||||
xstream_rd_u16_le(s, cap_len);
|
||||
xstream_rd_u32_le(s, cap_version);
|
||||
|
||||
/* remove header length and version */
|
||||
cap_len -= 8;
|
||||
|
||||
switch (cap_type)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
log_debug("got CAP_GENERAL_TYPE");
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_PRINTER_TYPE:
|
||||
log_debug("got CAP_PRINTER_TYPE");
|
||||
g_is_printer_redir_supported = 1;
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_PORT_TYPE:
|
||||
log_debug("got CAP_PORT_TYPE");
|
||||
g_is_port_redir_supported = 1;
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
|
||||
case CAP_DRIVE_TYPE:
|
||||
log_debug("got CAP_DRIVE_TYPE");
|
||||
g_is_drive_redir_supported = 1;
|
||||
if (cap_version == 2)
|
||||
{
|
||||
g_drive_redir_version = 2;
|
||||
xstream_seek(s, cap_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAP_SMARTCARD_TYPE:
|
||||
log_debug("got CAP_SMARTCARD_TYPE");
|
||||
g_is_smartcard_redir_supported = 1;
|
||||
scard_init();
|
||||
xstream_seek(s, cap_len);
|
||||
break;
|
||||
}
|
||||
s->p = holdp + cap_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ struct irp
|
||||
|
||||
void (*callback)(struct stream *s, IRP *irp, tui32 DeviceId,
|
||||
tui32 CompletionId, tui32 IoStatus);
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
IRP * APP_CC devredir_irp_new(void);
|
||||
|
@ -137,13 +137,58 @@ extern tui32 g_completion_id;
|
||||
extern int g_rdpdr_chan_id; /* in chansrv.c */
|
||||
|
||||
/* forward declarations specific to this file */
|
||||
static void scard_send_EstablishContext(IRP *irp);
|
||||
static void scard_send_EstablishContext(IRP *irp, int scope);
|
||||
static void scard_send_ListReaders(IRP *irp, int wide);
|
||||
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 tui32 g_device_id = 0;
|
||||
static int g_scard_index = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_send_irp_establish_context(struct trans *con, int scope)
|
||||
{
|
||||
IRP *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;
|
||||
scard_send_EstablishContext(irp, scope);
|
||||
log_debug("leaving");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_send_irp_list_readers(struct trans *con)
|
||||
{
|
||||
IRP *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_ListReaders_Return;
|
||||
irp->user_data = con;
|
||||
scard_send_ListReaders(irp, 1);
|
||||
log_debug("leaving");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** non static functions **
|
||||
******************************************************************************/
|
||||
@ -151,38 +196,24 @@ static void scard_release_resources(void);
|
||||
void APP_CC
|
||||
scard_device_announce(tui32 device_id)
|
||||
{
|
||||
IRP *irp;
|
||||
|
||||
log_debug("entered: device_id=%d", device_id);
|
||||
|
||||
if (!g_smartcards_inited)
|
||||
if (g_smartcards_inited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_memset(&smartcards, 0, sizeof(smartcards));
|
||||
g_smartcards_inited = 1;
|
||||
}
|
||||
|
||||
if ((irp = devredir_irp_new()) == NULL)
|
||||
g_device_id = device_id;
|
||||
g_scard_index = scard_add_new_device(device_id);
|
||||
if (g_scard_index < 0)
|
||||
{
|
||||
log_error("system out of memory");
|
||||
return;
|
||||
log_debug("scard_add_new_device failed with DeviceId=%d", g_device_id);
|
||||
}
|
||||
|
||||
irp->scard_index = scard_add_new_device(device_id);
|
||||
if (irp->scard_index < 0)
|
||||
else
|
||||
{
|
||||
log_debug("NOT adding smartcard with DeviceId=%d to list", device_id);
|
||||
devredir_irp_delete(irp);
|
||||
return;
|
||||
log_debug("added smartcard with DeviceId=%d to list", g_device_id);
|
||||
}
|
||||
|
||||
log_debug("added smartcard with DeviceId=%d to list", device_id);
|
||||
|
||||
irp->CompletionId = g_completion_id++;
|
||||
irp->DeviceId = device_id;
|
||||
irp->callback = scard_handle_EstablishContext_Return;
|
||||
|
||||
scard_send_EstablishContext(irp);
|
||||
log_debug("leaving");
|
||||
//scard_send_establish_context();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -239,13 +270,19 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
|
||||
g_hexdump(sc->Context, sc->Context_len);
|
||||
}
|
||||
|
||||
irp->callback = scard_handle_ListReaders_Return;
|
||||
scard_send_ListReaders(irp, 1);
|
||||
//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");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void APP_CC
|
||||
scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
|
||||
tui32 DeviceId, tui32 CompletionId,
|
||||
@ -272,9 +309,12 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
|
||||
/* get OutputBufferLen */
|
||||
xstream_rd_u32_le(s, len);
|
||||
|
||||
scard_function_get_readers_state_return((struct trans *) (irp->user_data),
|
||||
s, len);
|
||||
|
||||
/* LK_TODO */
|
||||
log_debug("dumping %d bytes", len);
|
||||
g_hexdump(s->p, len);
|
||||
//log_debug("dumping %d bytes", len);
|
||||
//g_hexdump(s->p, len);
|
||||
|
||||
log_debug("leaving");
|
||||
}
|
||||
@ -288,17 +328,20 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
|
||||
*****************************************************************************/
|
||||
|
||||
static void APP_CC
|
||||
scard_send_EstablishContext(IRP *irp)
|
||||
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;
|
||||
}
|
||||
|
||||
xstream_wr_u32_le(s, 0x08); /* len */
|
||||
xstream_wr_u32_le(s, 0); /* unused */
|
||||
xstream_wr_u32_le(s, SCARD_SCOPE_SYSTEM); /* Ioctl specific data */
|
||||
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 */
|
||||
@ -476,7 +519,10 @@ scard_add_new_device(tui32 device_id)
|
||||
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)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "parse.h"
|
||||
#include "irp.h"
|
||||
#include "trans.h"
|
||||
|
||||
/* forward declarations */
|
||||
void scard_device_announce(tui32 device_id);
|
||||
@ -48,4 +49,9 @@ 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);
|
||||
|
||||
#endif /* end #ifndef _SMARTCARD_C */
|
||||
|
@ -20,11 +20,11 @@
|
||||
/*
|
||||
* smartcard redirection support, PCSC daemon standin
|
||||
* this will act like pcsc daemon
|
||||
* pcsc lib and daemon write struct on unix domain socket for communication
|
||||
*/
|
||||
|
||||
#define PCSC_STANDIN 1
|
||||
|
||||
#include "chansrv.h"
|
||||
#include "os_calls.h"
|
||||
#include "smartcard.h"
|
||||
#include "log.h"
|
||||
@ -34,48 +34,37 @@
|
||||
|
||||
#if PCSC_STANDIN
|
||||
|
||||
/* module based logging */
|
||||
#define LOG_ERROR 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
#define LOG_LEVEL LOG_ERROR
|
||||
|
||||
#define log_error(_params...) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ERROR: ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
}
|
||||
|
||||
#define log_always(_params...) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ALWAYS: ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
}
|
||||
|
||||
#define log_info(_params...) \
|
||||
{ \
|
||||
if (LOG_INFO <= LOG_LEVEL) \
|
||||
#define LLOG_LEVEL 11
|
||||
#define LLOGLN(_level, _args) \
|
||||
do \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define log_debug(_params...) \
|
||||
{ \
|
||||
if (LOG_DEBUG <= LOG_LEVEL) \
|
||||
if (_level < LLOG_LEVEL) \
|
||||
{ \
|
||||
g_write("[%10.10u]: PCSC %s: %d : ", \
|
||||
g_time3(), __func__, __LINE__); \
|
||||
g_writeln (_params); \
|
||||
g_write("chansrv:smartcard [%10.10u]: ", g_time3()); \
|
||||
g_writeln _args ; \
|
||||
} \
|
||||
}
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define PCSCLITE_MSG_KEY_LEN 16
|
||||
#define PCSCLITE_MAX_MESSAGE_SIZE 2048
|
||||
/* using pcsc-lite-1.7.4 */
|
||||
|
||||
struct establish_struct
|
||||
{
|
||||
tui32 dwScope;
|
||||
tui32 hContext;
|
||||
tui32 rv;
|
||||
};
|
||||
|
||||
struct release_struct
|
||||
{
|
||||
tui32 hContext;
|
||||
tui32 rv;
|
||||
};
|
||||
|
||||
/** Major version of the current message protocol */
|
||||
#define PROTOCOL_VERSION_MAJOR 4
|
||||
/** Minor version of the current message protocol */
|
||||
#define PROTOCOL_VERSION_MINOR 2
|
||||
|
||||
struct version_struct
|
||||
{
|
||||
@ -83,25 +72,42 @@ struct version_struct
|
||||
tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */
|
||||
tui32 rv;
|
||||
};
|
||||
typedef struct version_struct version_struct;
|
||||
|
||||
struct rxSharedSegment
|
||||
#define SCARD_S_SUCCESS 0x00000000 /**< No error was encountered. */
|
||||
#define SCARD_F_INTERNAL_ERROR 0x80100001 /**< An internal consistency
|
||||
* check failed. */
|
||||
#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout
|
||||
* value has expired. */
|
||||
|
||||
#define MAX_READERNAME 100
|
||||
#define MAX_ATR_SIZE 33
|
||||
|
||||
struct pubReaderStatesList
|
||||
{
|
||||
tui32 mtype; /** one of the \c pcsc_adm_commands */
|
||||
tui32 user_id;
|
||||
tui32 group_id;
|
||||
tui32 command; /** one of the \c pcsc_msg_commands */
|
||||
tui64 date;
|
||||
tui8 key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */
|
||||
union _u
|
||||
{
|
||||
tui8 data[PCSCLITE_MAX_MESSAGE_SIZE];
|
||||
struct version_struct veStr;
|
||||
} u;
|
||||
char readerName[MAX_READERNAME]; /**< reader name */
|
||||
tui32 eventCounter; /**< number of card events */
|
||||
tui32 readerState; /**< SCARD_* bit field */
|
||||
tsi32 readerSharing; /**< PCSCLITE_SHARING_* sharing status */
|
||||
tui8 cardAtr[MAX_ATR_SIZE]; /**< ATR */
|
||||
tui32 cardAtrLength; /**< ATR length */
|
||||
tui32 cardProtocol; /**< SCARD_PROTOCOL_* value */
|
||||
};
|
||||
typedef struct rxSharedSegment sharedSegmentMsg, *psharedSegmentMsg;
|
||||
|
||||
#define RXSHAREDSEGMENT_BYTES 2088
|
||||
#define PCSCLITE_MAX_READERS_CONTEXTS 16
|
||||
|
||||
static struct pubReaderStatesList
|
||||
g_reader_states[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||
|
||||
struct wait_reader_state_change
|
||||
{
|
||||
tui32 timeOut; /**< timeout in ms */
|
||||
tui32 rv;
|
||||
};
|
||||
|
||||
#define XRDP_PCSC_STATE_NONE 0
|
||||
#define XRDP_PCSC_STATE_GOT_RSC 1
|
||||
|
||||
static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
|
||||
|
||||
extern int g_display_num; /* in chansrv.c */
|
||||
|
||||
@ -116,15 +122,15 @@ static struct pcsc_client *g_tail = 0;
|
||||
|
||||
static struct trans *g_lis = 0;
|
||||
static struct trans *g_con = 0; /* todo, remove this */
|
||||
|
||||
static char g_pcsc_directory[256] = "";
|
||||
static char g_pcsclite_ipc_dir[256] = "";
|
||||
static int g_pub_file_fd = 0;
|
||||
static char g_pub_file_name[256] = "";
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
|
||||
{
|
||||
log_debug("scard_pcsc_get_wait_objs");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_get_wait_objs"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_get_wait_objs(g_lis, objs, count);
|
||||
@ -140,8 +146,7 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
|
||||
int APP_CC
|
||||
scard_pcsc_check_wait_objs(void)
|
||||
{
|
||||
log_debug("scard_pcsc_check_wait_objs");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_check_wait_objs"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_check_wait_objs(g_lis);
|
||||
@ -156,34 +161,218 @@ scard_pcsc_check_wait_objs(void)
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_version(psharedSegmentMsg msg)
|
||||
scard_process_establish_context(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
struct establish_struct in_es;
|
||||
|
||||
LLOGLN(0, ("scard_process_establish_context:"));
|
||||
in_uint8a(in_s, &in_es, sizeof(in_es));
|
||||
LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x",
|
||||
in_es.dwScope));
|
||||
scard_send_irp_establish_context(con, in_es.dwScope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_msg(struct stream *s)
|
||||
scard_function_establish_context_return(struct trans *con, int context)
|
||||
{
|
||||
struct establish_struct out_es;
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_function_establish_context_return: context %d",
|
||||
context));
|
||||
out_es.dwScope = 0;
|
||||
out_es.hContext = context;
|
||||
out_es.rv = SCARD_S_SUCCESS;
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
out_uint8a(out_s, &out_es, sizeof(out_es));
|
||||
s_mark_end(out_s);
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_proess_release_context(struct stream *in_s)
|
||||
{
|
||||
struct release_struct in_rs;
|
||||
struct release_struct out_rs;
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_proess_release_context:"));
|
||||
in_uint8a(in_s, &in_rs, sizeof(in_rs));
|
||||
LLOGLN(0, ("scard_proess_release_context: hContext %d", in_rs.hContext));
|
||||
out_rs.hContext = in_rs.hContext;
|
||||
out_rs.rv = SCARD_S_SUCCESS;
|
||||
out_s = trans_get_out_s(g_con, 8192);
|
||||
out_uint8a(out_s, &out_rs, sizeof(out_rs));
|
||||
s_mark_end(out_s);
|
||||
return trans_force_write(g_con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_version(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
struct stream *out_s;
|
||||
struct version_struct in_version;
|
||||
struct version_struct out_version;
|
||||
|
||||
LLOGLN(0, ("scard_process_version:"));
|
||||
in_uint8a(in_s, &in_version, sizeof(in_version));
|
||||
/* todo: check if version is compatible */
|
||||
LLOGLN(0, ("scard_process_version: version major %d minor %d",
|
||||
in_version.major, in_version.minor));
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
out_version.major = PROTOCOL_VERSION_MAJOR;
|
||||
out_version.minor = PROTOCOL_VERSION_MINOR;
|
||||
out_version.rv = SCARD_S_SUCCESS;
|
||||
out_uint8a(out_s, &out_version, sizeof(out_version));
|
||||
s_mark_end(out_s);
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_get_readers_state(struct stream *in_s)
|
||||
{
|
||||
LLOGLN(0, ("scard_process_get_readers_state:"));
|
||||
scard_send_irp_list_readers(g_con);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_function_get_readers_state_return(struct trans *con,
|
||||
struct stream *in_s,
|
||||
int len)
|
||||
{
|
||||
struct stream *out_s;
|
||||
|
||||
g_hexdump(in_s->p, len);
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
out_uint8a(out_s, g_reader_states, sizeof(g_reader_states));
|
||||
s_mark_end(out_s);
|
||||
return trans_force_write(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* callback from chansrv when timeout occurs */
|
||||
void DEFAULT_CC
|
||||
scard_read_state_chage_timeout(void* data)
|
||||
{
|
||||
struct trans *con;
|
||||
struct stream *out_s;
|
||||
struct wait_reader_state_change out_rsc;
|
||||
|
||||
LLOGLN(0, ("scard_read_state_chage_timeout:"));
|
||||
con = (struct trans *) data;
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC)
|
||||
{
|
||||
out_s = trans_get_out_s(con, 8192);
|
||||
out_rsc.timeOut = 0;
|
||||
out_rsc.rv = SCARD_S_SUCCESS;
|
||||
out_uint8a(out_s, &out_rsc, sizeof(out_rsc));
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC;
|
||||
s_mark_end(out_s);
|
||||
trans_force_write(con);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("scard_read_state_chage_timeout: already stopped"));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_read_state_change(struct trans *con, struct stream *in_s)
|
||||
{
|
||||
struct wait_reader_state_change in_rsc;
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_process_read_state_change:"));
|
||||
in_uint8a(in_s, &in_rsc, sizeof(in_rsc));
|
||||
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RSC;
|
||||
LLOGLN(0, ("scard_process_read_state_change: timeout %d rv %d",
|
||||
in_rsc.timeOut, in_rsc.rv));
|
||||
add_timeout(in_rsc.timeOut, scard_read_state_chage_timeout, con);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_stop_read_state_change(struct stream *in_s)
|
||||
{
|
||||
struct wait_reader_state_change in_rsc;
|
||||
struct wait_reader_state_change out_rsc;
|
||||
struct stream *out_s;
|
||||
|
||||
LLOGLN(0, ("scard_process_stop_read_state_change:"));
|
||||
in_uint8a(in_s, &in_rsc, sizeof(in_rsc));
|
||||
LLOGLN(0, ("scard_process_stop_read_state_change: timeout %d rv %d",
|
||||
in_rsc.timeOut, in_rsc.rv));
|
||||
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RSC)
|
||||
{
|
||||
out_s = trans_get_out_s(g_con, 8192);
|
||||
out_rsc.timeOut = in_rsc.timeOut;
|
||||
out_rsc.rv = SCARD_S_SUCCESS;
|
||||
out_uint8a(out_s, &out_rsc, sizeof(out_rsc));
|
||||
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RSC;
|
||||
s_mark_end(out_s);
|
||||
return trans_force_write(g_con);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLOGLN(0, ("scard_process_stop_read_state_change: already stopped"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
scard_process_msg(struct trans *con, struct stream *in_s, int command)
|
||||
{
|
||||
sharedSegmentMsg msg;
|
||||
int rv;
|
||||
|
||||
g_memset(&msg, 0, sizeof(msg));
|
||||
in_uint32_le(s, msg.mtype);
|
||||
in_uint32_le(s, msg.user_id);
|
||||
in_uint32_le(s, msg.group_id);
|
||||
in_uint32_le(s, msg.command);
|
||||
in_uint64_le(s, msg.date);
|
||||
|
||||
log_debug("scard_process_msg: mtype 0x%2.2x command 0x%2.2x",
|
||||
msg.mtype, msg.command);
|
||||
|
||||
LLOGLN(0, ("scard_process_msg: command 0x%4.4x", command));
|
||||
rv = 0;
|
||||
switch (msg.mtype)
|
||||
switch (command)
|
||||
{
|
||||
case 0xF8: /* CMD_VERSION */
|
||||
rv = scard_process_version(&msg);
|
||||
case 0x01: /* SCARD_ESTABLISH_CONTEXT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_ESTABLISH_CONTEXT"));
|
||||
rv = scard_process_establish_context(con, in_s);
|
||||
break;
|
||||
case 0x02: /* SCARD_RELEASE_CONTEXT */
|
||||
LLOGLN(0, ("scard_process_msg: SCARD_RELEASE_CONTEXT"));
|
||||
rv = scard_proess_release_context(in_s);
|
||||
break;
|
||||
case 0x11: /* CMD_VERSION */
|
||||
LLOGLN(0, ("scard_process_msg: CMD_VERSION"));
|
||||
rv = scard_process_version(con, in_s);
|
||||
break;
|
||||
case 0x12: /* CMD_GET_READERS_STATE */
|
||||
LLOGLN(0, ("scard_process_msg: CMD_GET_READERS_STATE"));
|
||||
rv = scard_process_get_readers_state(in_s);
|
||||
break;
|
||||
case 0x13: /* CMD_WAIT_READER_STATE_CHANGE */
|
||||
LLOGLN(0, ("scard_process_msg: CMD_WAIT_READER_STATE_CHANGE"));
|
||||
rv = scard_process_read_state_change(con, in_s);
|
||||
break;
|
||||
case 0x14: /* CMD_STOP_WAITING_READER_STATE_CHANGE */
|
||||
LLOGLN(0, ("scard_process_msg: CMD_STOP_WAITING_READER_STATE_CHANGE"));
|
||||
rv = scard_process_stop_read_state_change(in_s);
|
||||
break;
|
||||
default:
|
||||
LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command));
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
@ -197,22 +386,27 @@ my_pcsc_trans_data_in(struct trans *trans)
|
||||
struct stream *s;
|
||||
int id;
|
||||
int size;
|
||||
int command;
|
||||
int error;
|
||||
|
||||
log_debug("my_pcsc_trans_data_in:");
|
||||
|
||||
LLOGLN(0, ("my_pcsc_trans_data_in:"));
|
||||
if (trans == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (trans != g_con)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s = trans_get_in_s(trans);
|
||||
g_hexdump(s->p, 64);
|
||||
error = scard_process_msg(s);
|
||||
in_uint32_le(s, size);
|
||||
in_uint32_le(s, command);
|
||||
LLOGLN(0, ("my_pcsc_trans_data_in: size %d command %d", size, command));
|
||||
error = trans_force_read(trans, size);
|
||||
if (error == 0)
|
||||
{
|
||||
error = scard_process_msg(g_con, s, command);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -221,7 +415,7 @@ my_pcsc_trans_data_in(struct trans *trans)
|
||||
int DEFAULT_CC
|
||||
my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
|
||||
{
|
||||
log_debug("my_pcsc_trans_conn_in:");
|
||||
LLOGLN(0, ("my_pcsc_trans_conn_in:"));
|
||||
|
||||
if (trans == 0)
|
||||
{
|
||||
@ -240,11 +434,13 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
|
||||
|
||||
g_con = new_trans;
|
||||
g_con->trans_data_in = my_pcsc_trans_data_in;
|
||||
#if 1
|
||||
g_con->header_size = 8;
|
||||
#else
|
||||
g_con->header_size = RXSHAREDSEGMENT_BYTES;
|
||||
|
||||
log_debug("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d",
|
||||
sizeof(sharedSegmentMsg));
|
||||
|
||||
LLOGLN(0, ("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d",
|
||||
sizeof(sharedSegmentMsg)));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -253,36 +449,51 @@ int APP_CC
|
||||
scard_pcsc_init(void)
|
||||
{
|
||||
char port[256];
|
||||
char *home;
|
||||
int disp;
|
||||
int error;
|
||||
int index;
|
||||
|
||||
log_debug("scard_pcsc_init:");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_init:"));
|
||||
g_memset(g_reader_states, 0, sizeof(g_reader_states));
|
||||
if (g_lis == 0)
|
||||
{
|
||||
g_lis = trans_create(TRANS_MODE_UNIX, 8192, 8192);
|
||||
g_lis->is_term = g_is_term;
|
||||
g_snprintf(g_pcsc_directory, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
|
||||
if (g_directory_exist(g_pcsc_directory))
|
||||
g_lis = trans_create(2, 8192, 8192);
|
||||
|
||||
//g_snprintf(g_pcsclite_ipc_dir, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
|
||||
home = g_getenv("HOME");
|
||||
disp = g_display_num;
|
||||
g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp);
|
||||
|
||||
if (g_directory_exist(g_pcsclite_ipc_dir))
|
||||
{
|
||||
if (g_remove_dir(g_pcsc_directory) != 0)
|
||||
if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
|
||||
{
|
||||
log_error("scard_pcsc_init: g_remove_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed"));
|
||||
}
|
||||
}
|
||||
if (g_create_dir(g_pcsc_directory) != 0)
|
||||
if (!g_create_dir(g_pcsclite_ipc_dir))
|
||||
{
|
||||
log_error("scard_pcsc_init: g_create_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_init: g_create_dir failed"));
|
||||
}
|
||||
g_chmod_hex(g_pcsc_directory, 0x1777);
|
||||
g_snprintf(port, 255, "%s/pcscd.comm", g_pcsc_directory);
|
||||
g_chmod_hex(g_pcsclite_ipc_dir, 0x1777);
|
||||
g_snprintf(port, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir);
|
||||
g_lis->trans_conn_in = my_pcsc_trans_conn_in;
|
||||
error = trans_listen(g_lis, port);
|
||||
if (error != 0)
|
||||
{
|
||||
log_error("scard_pcsc_init: trans_listen failed for port %s",
|
||||
port);
|
||||
LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s",
|
||||
port));
|
||||
return 1;
|
||||
}
|
||||
g_snprintf(g_pub_file_name, 255, "%s/pcscd.pub", g_pcsclite_ipc_dir);
|
||||
g_pub_file_fd = g_file_open(g_pub_file_name);
|
||||
index = 0;
|
||||
while (index < 65537)
|
||||
{
|
||||
g_file_write(g_pub_file_fd, "", 1);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -291,17 +502,22 @@ scard_pcsc_init(void)
|
||||
int APP_CC
|
||||
scard_pcsc_deinit(void)
|
||||
{
|
||||
log_debug("scard_pcsc_deinit:");
|
||||
|
||||
LLOGLN(0, ("scard_pcsc_deinit:"));
|
||||
if (g_lis != 0)
|
||||
{
|
||||
trans_delete(g_lis);
|
||||
g_lis = 0;
|
||||
if (g_remove_dir(g_pcsc_directory) != 0)
|
||||
|
||||
g_file_close(g_pub_file_fd);
|
||||
g_pub_file_fd = 0;
|
||||
g_file_delete(g_pub_file_name);
|
||||
g_pub_file_name[0] = 0;
|
||||
|
||||
if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
|
||||
{
|
||||
log_error("scard_pcsc_deinit: g_remove_dir failed");
|
||||
LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed"));
|
||||
}
|
||||
g_pcsc_directory[0] = 0;
|
||||
g_pcsclite_ipc_dir[0] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,4 +33,10 @@ 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_get_readers_state_return(struct trans *con, struct stream *in_s,
|
||||
int len);
|
||||
|
||||
#endif /* end #ifndef _SMARTCARD_PCSC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user