diff options
author | Jay Sorg <jay.sorg@gmail.com> | 2013-12-21 19:16:08 -0800 |
---|---|---|
committer | Jay Sorg <jay.sorg@gmail.com> | 2013-12-21 19:16:08 -0800 |
commit | 1483c7591121036b29ad5243fc2e2419992331ac (patch) | |
tree | 7102a5c5dddda2cd0e5d7ffe1c4dd80f8edeb8c4 /sesman/chansrv/smartcard_pcsc.c | |
parent | 6eab2ed11b634342b48dd75bd3866f35d6479a0f (diff) | |
download | xrdp-proprietary-1483c7591121036b29ad5243fc2e2419992331ac.tar.gz xrdp-proprietary-1483c7591121036b29ad5243fc2e2419992331ac.zip |
chansrv: work on smartcard stability, handle multi threaded calls, app crashes, etc
Diffstat (limited to 'sesman/chansrv/smartcard_pcsc.c')
-rw-r--r-- | sesman/chansrv/smartcard_pcsc.c | 632 |
1 files changed, 525 insertions, 107 deletions
diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index ebf52c82..95c01a04 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -35,6 +35,7 @@ #include "devredir.h" #include "trans.h" #include "chansrv.h" +#include "list.h" #if PCSC_STANDIN @@ -63,42 +64,242 @@ #define XRDP_PCSC_STATE_GOT_D (1 << 9) /* disconnect */ #define XRDP_PCSC_STATE_GOT_ST (1 << 10) /* get status */ +#if 0 /* TODO: put this in con */ -static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; +static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; /* 0 */ static int g_xrdp_pcsc_extra1; +#endif extern int g_display_num; /* in chansrv.c */ +static int g_uds_client_id = 0; /* auto incremented for each unix domain + socket connection */ + +struct pcsc_card /* item for list of open cards in one context */ +{ + tui32 card; +}; + +struct pcsc_context +{ + tui32 context; + struct list *cards; /* these need to be released on close */ +}; + /*****************************************************************************/ -struct pcsc_client +struct pcsc_uds_client { + int uds_client_id; /* from g_uds_client_id */ struct trans *con; + struct list *contexts; /* struct pcsc_context */ + int pcsc_state; + int pcsc_extra1; }; -#if 0 -static struct pcsc_client *g_head = 0; -static struct pcsc_client *g_tail = 0; -#endif +static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */ static struct trans *g_lis = 0; +#if 0 static struct trans *g_con = 0; /* todo, remove this */ +#endif static char g_pcsclite_ipc_dir[256] = ""; static char g_pcsclite_ipc_file[256] = ""; -static int g_pub_file_fd = 0; + +/*****************************************************************************/ +/* got a new unix domain socket connection */ +static struct pcsc_uds_client * +create_uds_client(struct trans *con) +{ + struct pcsc_uds_client *uds_client; + + LLOGLN(10, ("create_uds_client:")); + if (con == 0) + { + return 0; + } + uds_client = g_malloc(sizeof(struct pcsc_uds_client), 1); + if (uds_client == 0) + { + return 0; + } + g_uds_client_id++; + uds_client->uds_client_id = g_uds_client_id; + uds_client->con = con; + con->callback_data = uds_client; + return uds_client; +} + +/*****************************************************************************/ +static struct pcsc_uds_client * +get_uds_client_by_id(int uds_client_id) +{ + struct pcsc_uds_client *uds_client; + int index; + + LLOGLN(10, ("get_uds_client_by_id:")); + if (uds_client_id == 0) + { + LLOGLN(10, ("get_uds_client_by_id: uds_client_id zero")); + return 0; + } + if (g_uds_clients == 0) + { + LLOGLN(10, ("get_uds_client_by_id: g_uds_clients is nil")); + return 0; + } + LLOGLN(10, (" count %d", g_uds_clients->count)); + for (index = 0; index < g_uds_clients->count; index++) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client->uds_client_id == uds_client_id) + { + return uds_client; + } + } + LLOGLN(10, ("get_uds_client_by_id: can't find uds_client_id %d", + uds_client_id)); + return 0; +} + +/*****************************************************************************/ +static int +free_uds_client(struct pcsc_uds_client *uds_client) +{ + int i; + int j; + struct pcsc_context *context; + struct pcsc_card *card; + + LLOGLN(10, ("free_uds_client:")); + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts != 0) + { + for (i = 0; i < uds_client->contexts->count; i++) + { + context = (struct pcsc_context *) + list_get_item(uds_client->contexts, i); + if (context != 0) + { + if (context->cards != 0) + { + for (j = 0; j < context->cards->count; j++) + { + card = (struct pcsc_card *) + list_get_item(context->cards, j); + if (card != 0) + { + /* TODO: send free card to client */ + g_free(card); + } + } + list_delete(context->cards); + } + LLOGLN(10, (" left over context 0x%8.8x", context->context)); + scard_send_cancel(0, context->context); + scard_send_release_context(0, context->context); + g_free(context); + } + } + list_delete(uds_client->contexts); + } + trans_delete(uds_client->con); + g_free(uds_client); + return 0; +} + +/*****************************************************************************/ +static int +uds_client_add_context(struct pcsc_uds_client *uds_client, tui32 context) +{ + struct pcsc_context *pcscContext; + + LLOGLN(10, ("uds_client_add_context:")); + pcscContext = (struct pcsc_context * ) + g_malloc(sizeof(struct pcsc_context), 1); + if (pcscContext == 0) + { + LLOGLN(0, ("uds_client_add_context: error")); + return 1; + } + pcscContext->context = context; + if (uds_client->contexts == 0) + { + uds_client->contexts = list_create(); + if (uds_client->contexts == 0) + { + LLOGLN(0, ("uds_client_add_context: error")); + return 1; + } + } + list_add_item(uds_client->contexts, (tintptr) pcscContext); + return 0; +} + +/*****************************************************************************/ +static int +uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context) +{ + int index; + struct pcsc_context *pcscContext; + + LLOGLN(10, ("uds_client_remove_context:")); + if (uds_client->contexts == 0) + { + LLOGLN(0, ("uds_client_remove_context: error")); + return 1; + } + for (index = 0; index < uds_client->contexts->count; index++) + { + pcscContext = (struct pcsc_context *) + list_get_item(uds_client->contexts, index); + if (pcscContext != 0) + { + if (pcscContext->context == context) + { + list_remove_item(uds_client->contexts, index); + g_free(pcscContext); + return 0; + } + } + } + LLOGLN(10, ("uds_client_remove_context: not found")); + return 1; +} /*****************************************************************************/ int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) { - LLOGLN(10, ("scard_pcsc_get_wait_objs")); + struct pcsc_uds_client *uds_client; + int index; + + LLOGLN(10, ("scard_pcsc_get_wait_objs:")); if (g_lis != 0) { trans_get_wait_objs(g_lis, objs, count); } +#if 0 if (g_con != 0) { trans_get_wait_objs(g_con, objs, count); } +#endif + if (g_uds_clients != 0) + { + for (index = 0; index < g_uds_clients->count; index++) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client != 0) + { + trans_get_wait_objs(uds_client->con, objs, count); + } + } + } return 0; } @@ -106,6 +307,9 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC scard_pcsc_check_wait_objs(void) { + struct pcsc_uds_client *uds_client; + int index; + LLOGLN(10, ("scard_pcsc_check_wait_objs:")); if (g_lis != 0) { @@ -114,6 +318,7 @@ scard_pcsc_check_wait_objs(void) LLOGLN(0, ("scard_pcsc_check_wait_objs: g_lis trans_check_wait_objs error")); } } +#if 0 if (g_con != 0) { if (trans_check_wait_objs(g_con) != 0) @@ -125,6 +330,26 @@ scard_pcsc_check_wait_objs(void) g_xrdp_pcsc_state = 0; } } +#endif + if (g_uds_clients != 0) + { + index = 0; + while (index < g_uds_clients->count) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client != 0) + { + if (trans_check_wait_objs(uds_client->con) != 0) + { + free_uds_client(uds_client); + list_remove_item(g_uds_clients, index); + continue; + } + } + index++; + } + } return 0; } @@ -134,42 +359,58 @@ int APP_CC scard_process_establish_context(struct trans *con, struct stream *in_s) { int dwScope; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_establish_context:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_EC) { LLOGLN(0, ("scard_process_establish_context: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_EC; in_uint32_le(in_s, dwScope); LLOGLN(10, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope)); - scard_send_establish_context(con, dwScope); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_establish_context(user_data, dwScope); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_establish_context_return(struct trans *con, +scard_function_establish_context_return(void *user_data, struct stream *in_s, int len, int status) { int bytes; + int uds_client_id; tui32 context; tui32 context_len; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_establish_context_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_establish_context_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) { LLOGLN(0, ("scard_function_establish_context_return: opps " - "g_xrdp_pcsc_state 0x%8.8x, g_xrdp_pcsc_state")); + "uds_client->pcsc_state 0x%8.8x", uds_client->pcsc_state)); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC; context = 0; if (status == 0) { @@ -182,8 +423,9 @@ scard_function_establish_context_return(struct trans *con, return 1; } in_uint32_le(in_s, context); - LLOGLN(10, ("scard_function_establish_context_return: context 0x%8.8x", - context)); + uds_client_add_context(uds_client, context); + LLOGLN(10, ("scard_function_establish_context_return: " + "context 0x%8.8x", context)); } out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); @@ -203,38 +445,56 @@ int APP_CC scard_process_release_context(struct trans *con, struct stream *in_s) { int hContext; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_release_context:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_RC) { LLOGLN(0, ("scard_process_establish_context: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_RC; in_uint32_le(in_s, hContext); LLOGLN(10, ("scard_process_release_context: hContext 0x%8.8x", hContext)); - scard_send_release_context(con, hContext); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_release_context(user_data, hContext); + uds_client_remove_context(uds_client, hContext); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_release_context_return(struct trans *con, +scard_function_release_context_return(void *user_data, struct stream *in_s, int len, int status) { int bytes; + int uds_client_id; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_release_context_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_release_context_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0) { LLOGLN(0, ("scard_function_release_context_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC; out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ @@ -255,30 +515,34 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) int bytes_groups; int cchReaders; char *groups; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_list_readers:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_LR) { LLOGLN(0, ("scard_process_list_readers: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_LR; in_uint32_le(in_s, hContext); in_uint32_le(in_s, bytes_groups); groups = (char *) g_malloc(bytes_groups + 1, 1); in_uint8a(in_s, groups, bytes_groups); in_uint32_le(in_s, cchReaders); - g_xrdp_pcsc_extra1 = cchReaders; + uds_client->pcsc_extra1 = cchReaders; LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d", hContext, cchReaders)); - scard_send_list_readers(con, hContext, groups, cchReaders, 1); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_list_readers(user_data, hContext, groups, cchReaders, 1); g_free(groups); return 0; } /*****************************************************************************/ int APP_CC -scard_function_list_readers_return(struct trans *con, +scard_function_list_readers_return(void *user_data, struct stream *in_s, int len, int status) { @@ -290,20 +554,33 @@ scard_function_list_readers_return(struct trans *con, int bytes; int cchReaders; int llen; + int uds_client_id; twchar reader_name[100]; char lreader_name[16][100]; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_list_readers_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_list_readers_return: " + "get_uds_client_by_id failed, could not find id %d", + uds_client_id)); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0) { LLOGLN(0, ("scard_function_list_readers_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; - cchReaders = g_xrdp_pcsc_extra1; + cchReaders = uds_client->pcsc_extra1; g_memset(reader_name, 0, sizeof(reader_name)); g_memset(lreader_name, 0, sizeof(lreader_name)); @@ -358,6 +635,10 @@ scard_function_list_readers_return(struct trans *con, { out_uint8a(out_s, lreader_name[index], 100); } + //if (readers == 0) + //{ + // status = 0x8010002E; /* SCARD_E_NO_READERS_AVAILABLE */ + //} out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); @@ -374,15 +655,18 @@ scard_process_connect(struct trans *con, struct stream *in_s) { int hContext; READER_STATE rs; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_connect:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_C) { LLOGLN(0, ("scard_process_connect: opps")); return 1; } g_memset(&rs, 0, sizeof(rs)); - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_C; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_C; in_uint32_le(in_s, hContext); in_uint8a(in_s, rs.reader_name, 100); in_uint32_le(in_s, rs.dwShareMode); @@ -390,30 +674,43 @@ scard_process_connect(struct trans *con, struct stream *in_s) LLOGLN(10, ("scard_process_connect: rs.reader_name %s dwShareMode 0x%8.8x " "dwPreferredProtocols 0x%8.8x", rs.reader_name, rs.dwShareMode, rs.dwPreferredProtocols)); - scard_send_connect(con, hContext, 1, &rs); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_connect(user_data, hContext, 1, &rs); return 0; } /*****************************************************************************/ int APP_CC -scard_function_connect_return(struct trans *con, +scard_function_connect_return(void *user_data, struct stream *in_s, int len, int status) { int dwActiveProtocol; int hCard; int bytes; + int uds_client_id; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_connect_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_connect_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) { LLOGLN(0, ("scard_function_connect_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; dwActiveProtocol = 0; hCard = 0; if (status == 0) @@ -445,44 +742,59 @@ scard_process_disconnect(struct trans *con, struct stream *in_s) int hContext; int hCard; int dwDisposition; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_disconnect:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_D) { LLOGLN(0, ("scard_process_disconnect: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_D; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_D; in_uint32_le(in_s, hCard); in_uint32_le(in_s, dwDisposition); hContext = 1; - - scard_send_disconnect(con, hContext, hCard, dwDisposition); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_disconnect(user_data, hContext, hCard, dwDisposition); return 0; } /*****************************************************************************/ int APP_CC -scard_function_disconnect_return(struct trans *con, +scard_function_disconnect_return(void *user_data, struct stream *in_s, int len, int status) { int dwActiveProtocol; int hCard; int bytes; + int uds_client_id; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_disconnect_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_disconnect_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_D) == 0) { LLOGLN(0, ("scard_function_connect_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_D; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_D; dwActiveProtocol = 0; hCard = 0; if (status == 0) @@ -511,39 +823,55 @@ int APP_CC scard_process_begin_transaction(struct trans *con, struct stream *in_s) { int hCard; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_begin_transaction:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_BT) { LLOGLN(0, ("scard_process_begin_transaction: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_BT; in_uint32_le(in_s, hCard); LLOGLN(10, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); - scard_send_begin_transaction(con, hCard); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_begin_transaction(user_data, hCard); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_begin_transaction_return(struct trans *con, +scard_function_begin_transaction_return(void *user_data, struct stream *in_s, int len, int status) { struct stream *out_s; int bytes; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_begin_transaction_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_begin_transaction_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0) { LLOGLN(0, ("scard_function_begin_transaction_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_BT; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_BT; out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ @@ -562,40 +890,56 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) { int hCard; int dwDisposition; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_end_transaction:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_ET) { LLOGLN(0, ("scard_process_end_transaction: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_ET; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_ET; in_uint32_le(in_s, hCard); in_uint32_le(in_s, dwDisposition); LLOGLN(10, ("scard_process_end_transaction: hCard 0x%8.8x", hCard)); - scard_send_end_transaction(con, hCard, dwDisposition); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_end_transaction(user_data, hCard, dwDisposition); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_end_transaction_return(struct trans *con, +scard_function_end_transaction_return(void *user_data, struct stream *in_s, int len, int status) { struct stream *out_s; int bytes; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_end_transaction_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_end_transaction_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0) { LLOGLN(0, ("scard_function_end_transaction_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ET; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_ET; out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); @@ -611,17 +955,19 @@ scard_function_end_transaction_return(struct trans *con, /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_cancel_return(struct trans *con, +scard_function_cancel_return(void *user_data, struct stream *in_s, int len, int status) { + LLOGLN(10, ("scard_function_cancel_return:")); + //g_hexdump(in_s->p, len); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_get_attrib_return(struct trans *con, +scard_function_get_attrib_return(void *user_data, struct stream *in_s, int len, int status) { @@ -639,14 +985,17 @@ scard_process_transmit(struct trans *con, struct stream *in_s) char *send_data; struct xrdp_scard_io_request send_ior; struct xrdp_scard_io_request recv_ior; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_transmit:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_TR) { LLOGLN(0, ("scard_process_transmit: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_TR; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_TR; LLOGLN(10, ("scard_process_transmit:")); in_uint32_le(in_s, hCard); in_uint32_le(in_s, send_ior.dwProtocol); @@ -666,7 +1015,8 @@ scard_process_transmit(struct trans *con, struct stream *in_s) recv_ior.cbPciLength, send_bytes)); //g_hexdump(in_s->p, send_bytes); LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes)); - scard_send_transmit(con, hCard, send_data, send_bytes, recv_bytes, + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_transmit(user_data, hCard, send_data, send_bytes, recv_bytes, &send_ior, &recv_ior); return 0; } @@ -674,7 +1024,7 @@ scard_process_transmit(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_transmit_return(struct trans *con, +scard_function_transmit_return(void *user_data, struct stream *in_s, int len, int status) { @@ -682,18 +1032,30 @@ scard_function_transmit_return(struct trans *con, int bytes; int val; int cbRecvLength; + int uds_client_id; struct xrdp_scard_io_request recv_ior; char *recvBuf; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_transmit_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_transmit_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0) { LLOGLN(0, ("scard_function_transmit_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR; g_memset(&recv_ior, 0, sizeof(recv_ior)); cbRecvLength = 0; recvBuf = 0; @@ -752,14 +1114,17 @@ scard_process_control(struct trans *con, struct stream *in_s) int recv_bytes; int control_code; char *send_data; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_control:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CO) { LLOGLN(0, ("scard_process_control: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_CO; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_CO; LLOGLN(10, ("scard_process_control:")); in_uint32_le(in_s, hCard); @@ -768,7 +1133,8 @@ scard_process_control(struct trans *con, struct stream *in_s) in_uint8p(in_s, send_data, send_bytes); in_uint32_le(in_s, recv_bytes); - scard_send_control(con, hCard, send_data, send_bytes, recv_bytes, + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_control(user_data, hCard, send_data, send_bytes, recv_bytes, control_code); return 0; @@ -777,7 +1143,7 @@ scard_process_control(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_control_return(struct trans *con, +scard_function_control_return(void *user_data, struct stream *in_s, int len, int status) { @@ -785,16 +1151,28 @@ scard_function_control_return(struct trans *con, int bytes; int cbRecvLength; char *recvBuf; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_control_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_control_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0) { LLOGLN(0, ("scard_function_control_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO; cbRecvLength = 0; recvBuf = 0; if (status == 0) @@ -825,20 +1203,24 @@ scard_process_status(struct trans *con, struct stream *in_s) int hCard; int cchReaderLen; int cbAtrLen; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_status:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_ST) { LLOGLN(0, ("scard_process_status: opps")); return 1; } - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_ST; + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_ST; in_uint32_le(in_s, hCard); in_uint32_le(in_s, cchReaderLen); in_uint32_le(in_s, cbAtrLen); - scard_send_status(con, 1, hCard, cchReaderLen, cbAtrLen); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_status(user_data, 1, hCard, cchReaderLen, cbAtrLen); return 0; } @@ -867,7 +1249,7 @@ static int g_ms2pc[] = { PC_SCARD_UNKNOWN, PC_SCARD_ABSENT, /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_status_return(struct trans *con, +scard_function_status_return(void *user_data, struct stream *in_s, int len, int status) { @@ -881,16 +1263,28 @@ scard_function_status_return(struct trans *con, char attr[32]; twchar reader_name[100]; char lreader_name[100]; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_status_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_status_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_ST) == 0) { LLOGLN(0, ("scard_function_status_return: opps")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ST; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_ST; dwReaderLen = 0; dwState = 0; dwProtocol = 0; @@ -947,13 +1341,17 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) int dwTimeout; int cReaders; READER_STATE *rsa; + struct pcsc_uds_client *uds_client; + void *user_data; LLOGLN(10, ("scard_process_get_status_change:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_GSC) { LLOGLN(0, ("scard_process_get_status_change: opps")); return 1; } + uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_GSC; in_uint32_le(in_s, hContext); in_uint32_le(in_s, dwTimeout); in_uint32_le(in_s, cReaders); @@ -984,9 +1382,8 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) LLOGLN(10, ("scard_process_get_status_change: hContext 0x%8.8x dwTimeout " "%d cReaders %d", hContext, dwTimeout, cReaders)); - g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC; - - scard_send_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_get_status_change(user_data, hContext, 1, dwTimeout, cReaders, rsa); g_free(rsa); @@ -995,7 +1392,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) /*****************************************************************************/ int APP_CC -scard_function_get_status_change_return(struct trans *con, +scard_function_get_status_change_return(void *user_data, struct stream *in_s, int len, int status) { @@ -1007,17 +1404,29 @@ scard_function_get_status_change_return(struct trans *con, tui32 atr_len; /* number of bytes in atr[] */ tui8 atr[36]; struct stream *out_s; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_get_status_change_return:")); LLOGLN(10, (" status 0x%8.8x", status)); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0) + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_get_status_change_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0) { LLOGLN(0, ("scard_function_get_status_change_return: opps " - "g_xrdp_pcsc_state 0x%8.8x", g_xrdp_pcsc_state)); + "g_xrdp_pcsc_state 0x%8.8x", uds_client->pcsc_state)); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC; + uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC; out_s = trans_get_out_s(con, 8192); s_push_layer(out_s, iso_hdr, 8); @@ -1060,7 +1469,7 @@ scard_function_get_status_change_return(struct trans *con, /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_is_context_valid_return(struct trans *con, +scard_function_is_context_valid_return(void *user_data, struct stream *in_s, int len, int status) { @@ -1069,7 +1478,7 @@ scard_function_is_context_valid_return(struct trans *con, /*****************************************************************************/ /* returns error */ -int APP_CC scard_function_reconnect_return(struct trans *con, +int APP_CC scard_function_reconnect_return(void *user_data, struct stream *in_s, int len, int status) { @@ -1184,10 +1593,6 @@ my_pcsc_trans_data_in(struct trans *trans) { return 0; } - if (trans != g_con) - { - return 1; - } s = trans_get_in_s(trans); in_uint32_le(s, size); in_uint32_le(s, command); @@ -1195,7 +1600,7 @@ my_pcsc_trans_data_in(struct trans *trans) error = trans_force_read(trans, size); if (error == 0) { - error = scard_process_msg(g_con, s, command); + error = scard_process_msg(trans, s, command); } return error; } @@ -1205,6 +1610,8 @@ my_pcsc_trans_data_in(struct trans *trans) int DEFAULT_CC my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) { + struct pcsc_uds_client *uds_client; + LLOGLN(10, ("my_pcsc_trans_conn_in:")); if (trans == 0) @@ -1222,9 +1629,26 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) return 1; } + uds_client = create_uds_client(new_trans); + if (uds_client == 0) + { + return 1; + } + uds_client->con->trans_data_in = my_pcsc_trans_data_in; + uds_client->con->header_size = 8; + + if (g_uds_clients == 0) + { + g_uds_clients = list_create(); + } + list_add_item(g_uds_clients, (tbus)uds_client); + +#if 0 g_con = new_trans; g_con->trans_data_in = my_pcsc_trans_data_in; g_con->header_size = 8; +#endif + return 0; } @@ -1287,12 +1711,6 @@ scard_pcsc_deinit(void) g_lis = 0; } - if (g_pub_file_fd != 0) - { - g_file_close(g_pub_file_fd); - g_pub_file_fd = 0; - } - if (g_pcsclite_ipc_dir[0] != 0) { g_file_delete(g_pcsclite_ipc_file); |