summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv/smartcard_pcsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sesman/chansrv/smartcard_pcsc.c')
-rw-r--r--sesman/chansrv/smartcard_pcsc.c448
1 files changed, 378 insertions, 70 deletions
diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c
index 95c01a04..6063912d 100644
--- a/sesman/chansrv/smartcard_pcsc.c
+++ b/sesman/chansrv/smartcard_pcsc.c
@@ -63,6 +63,7 @@
#define XRDP_PCSC_STATE_GOT_CO (1 << 8) /* control */
#define XRDP_PCSC_STATE_GOT_D (1 << 9) /* disconnect */
#define XRDP_PCSC_STATE_GOT_ST (1 << 10) /* get status */
+#define XRDP_PCSC_STATE_GOT_CANCEL (1 << 11) /* cancel */
#if 0
/* TODO: put this in con */
@@ -74,15 +75,20 @@ extern int g_display_num; /* in chansrv.c */
static int g_uds_client_id = 0; /* auto incremented for each unix domain
socket connection */
+static int g_autoinc = 0; /* general purpose autoinc */
struct pcsc_card /* item for list of open cards in one context */
{
- tui32 card;
+ tui32 app_card; /* application card, always 4 bytes */
+ int card_bytes; /* client card bytes */
+ char card[8]; /* client card */
};
struct pcsc_context
{
- tui32 context;
+ tui32 app_context; /* application context, always 4 byte */
+ int context_bytes; /* client context bytes */
+ char context[8]; /* client context */
struct list *cards; /* these need to be released on close */
};
@@ -94,6 +100,7 @@ struct pcsc_uds_client
struct list *contexts; /* struct pcsc_context */
int pcsc_state;
int pcsc_extra1;
+ struct pcsc_context *connect_context;
};
static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */
@@ -163,6 +170,87 @@ get_uds_client_by_id(int uds_client_id)
}
/*****************************************************************************/
+struct pcsc_context *
+get_pcsc_context_by_app_context(struct pcsc_uds_client *uds_client,
+ int app_context)
+{
+ struct pcsc_context *rv;
+ int index;
+
+ if (uds_client == 0)
+ {
+ return 0;
+ }
+ if (uds_client->contexts == 0)
+ {
+ return 0;
+ }
+ for (index = 0; index < uds_client->contexts->count; index++)
+ {
+ rv = (struct pcsc_context *)
+ list_get_item(uds_client->contexts, index);
+ if (rv->app_context == app_context)
+ {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+struct pcsc_card *
+get_pcsc_card_by_app_card(struct pcsc_uds_client *uds_client,
+ int app_card, struct pcsc_context **acontext)
+{
+ struct pcsc_card *lcard;
+ struct pcsc_context *lcontext;
+ int index;
+ int index1;
+
+ LLOGLN(10, ("get_pcsc_card_by_app_card:"));
+ LLOGLN(10, (" app_card %d", app_card));
+ if (uds_client == 0)
+ {
+ LLOGLN(0, ("get_pcsc_card_by_app_card: error"));
+ return 0;
+ }
+ if (uds_client->contexts == 0)
+ {
+ LLOGLN(0, ("get_pcsc_card_by_app_card: error"));
+ return 0;
+ }
+ for (index = 0; index < uds_client->contexts->count; index++)
+ {
+ lcontext = (struct pcsc_context *)
+ list_get_item(uds_client->contexts, index);
+ if (lcontext != 0)
+ {
+ if (lcontext->cards != 0)
+ {
+ for (index1 = 0; index1 < lcontext->cards->count; index1++)
+ {
+ lcard = (struct pcsc_card *)
+ list_get_item(lcontext->cards, index1);
+ if (lcard != 0)
+ {
+ if (lcard->app_card == app_card)
+ {
+ if (acontext != 0)
+ {
+ *acontext = lcontext;
+ }
+ return lcard;
+ }
+ }
+ }
+ }
+ }
+ }
+ LLOGLN(0, ("get_pcsc_card_by_app_card: error"));
+ return 0;
+}
+
+/*****************************************************************************/
static int
free_uds_client(struct pcsc_uds_client *uds_client)
{
@@ -199,8 +287,9 @@ free_uds_client(struct pcsc_uds_client *uds_client)
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);
+ scard_send_cancel(0, context->context, context->context_bytes);
+ scard_send_release_context(0, context->context,
+ context->context_bytes);
g_free(context);
}
}
@@ -212,8 +301,9 @@ free_uds_client(struct pcsc_uds_client *uds_client)
}
/*****************************************************************************/
-static int
-uds_client_add_context(struct pcsc_uds_client *uds_client, tui32 context)
+static struct pcsc_context *
+uds_client_add_context(struct pcsc_uds_client *uds_client,
+ char *context, int context_bytes)
{
struct pcsc_context *pcscContext;
@@ -223,25 +313,52 @@ uds_client_add_context(struct pcsc_uds_client *uds_client, tui32 context)
if (pcscContext == 0)
{
LLOGLN(0, ("uds_client_add_context: error"));
- return 1;
+ return 0;
}
- pcscContext->context = context;
+ g_autoinc++;
+ pcscContext->app_context = g_autoinc;
+ pcscContext->context_bytes = context_bytes;
+ g_memcpy(pcscContext->context, context, context_bytes);
if (uds_client->contexts == 0)
{
uds_client->contexts = list_create();
if (uds_client->contexts == 0)
{
LLOGLN(0, ("uds_client_add_context: error"));
- return 1;
+ return 0;
}
}
list_add_item(uds_client->contexts, (tintptr) pcscContext);
+ return pcscContext;
+}
+
+/*****************************************************************************/
+static int
+uds_client_remove_context(struct pcsc_uds_client *uds_client,
+ struct pcsc_context *acontext)
+{
+ int index;
+
+ if (uds_client->contexts == 0)
+ {
+ LLOGLN(0, ("uds_client_remove_context: error"));
+ return 1;
+ }
+ index = list_index_of(uds_client->contexts, (tintptr) acontext);
+ if (index < 0)
+ {
+ LLOGLN(0, ("uds_client_remove_context: error"));
+ return 1;
+ }
+ list_remove_item(uds_client->contexts, index);
+ g_free(acontext); // TODO free cards
return 0;
}
/*****************************************************************************/
static int
-uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context)
+uds_client_remove_context1(struct pcsc_uds_client *uds_client,
+ char *context, int context_bytes)
{
int index;
struct pcsc_context *pcscContext;
@@ -258,7 +375,8 @@ uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context)
list_get_item(uds_client->contexts, index);
if (pcscContext != 0)
{
- if (pcscContext->context == context)
+ if ((pcscContext->context_bytes == context_bytes) &&
+ (g_memcmp(pcscContext->context, context, context_bytes) == 0))
{
list_remove_item(uds_client->contexts, index);
g_free(pcscContext);
@@ -271,6 +389,40 @@ uds_client_remove_context(struct pcsc_uds_client *uds_client, tui32 context)
}
/*****************************************************************************/
+static struct pcsc_card *
+context_add_card(struct pcsc_uds_client *uds_client,
+ struct pcsc_context *acontext,
+ char *card, int card_bytes)
+{
+ struct pcsc_card *pcscCard;
+
+ LLOGLN(10, ("context_add_card:"));
+ pcscCard = (struct pcsc_card * )
+ g_malloc(sizeof(struct pcsc_card), 1);
+ if (pcscCard == 0)
+ {
+ LLOGLN(0, ("context_add_card: error"));
+ return 0;
+ }
+ g_autoinc++;
+ pcscCard->app_card = g_autoinc;
+ pcscCard->card_bytes = card_bytes;
+ g_memcpy(pcscCard->card, card, card_bytes);
+ if (acontext->cards == 0)
+ {
+ acontext->cards = list_create();
+ if (acontext->cards == 0)
+ {
+ LLOGLN(0, ("context_add_card: error"));
+ return 0;
+ }
+ }
+ list_add_item(acontext->cards, (tintptr) pcscCard);
+ LLOGLN(10, (" new app_card %d", pcscCard->app_card));
+ return pcscCard;
+}
+
+/*****************************************************************************/
int APP_CC
scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
{
@@ -386,11 +538,13 @@ scard_function_establish_context_return(void *user_data,
{
int bytes;
int uds_client_id;
- tui32 context;
- tui32 context_len;
+ int context_bytes;
+ int app_context;
+ char context[8];
struct stream *out_s;
struct pcsc_uds_client *uds_client;
struct trans *con;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_function_establish_context_return:"));
LLOGLN(10, (" status 0x%8.8x", status));
@@ -411,25 +565,29 @@ scard_function_establish_context_return(void *user_data,
return 1;
}
uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC;
- context = 0;
+ lcontext = 0;
+ app_context = 0;
+ g_memset(context, 0, 8);
if (status == 0)
{
in_uint8s(in_s, 28);
- in_uint32_le(in_s, context_len);
- if (context_len != 4)
+ in_uint32_le(in_s, context_bytes);
+ if (context_bytes > 8)
{
LLOGLN(0, ("scard_function_establish_context_return: opps "
- "context_len %d", context_len));
+ "context_bytes %d", context_bytes));
+ g_hexdump(in_s->p, context_bytes);
return 1;
}
- in_uint32_le(in_s, context);
- uds_client_add_context(uds_client, context);
+ in_uint8a(in_s, context, context_bytes);
+ lcontext = uds_client_add_context(uds_client, context, context_bytes);
+ app_context = lcontext->app_context;
LLOGLN(10, ("scard_function_establish_context_return: "
- "context 0x%8.8x", context));
+ "app_context %d", app_context));
}
out_s = trans_get_out_s(con, 8192);
s_push_layer(out_s, iso_hdr, 8);
- out_uint32_le(out_s, context);
+ out_uint32_le(out_s, app_context);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
bytes = (int) (out_s->end - out_s->data);
@@ -446,21 +604,30 @@ scard_process_release_context(struct trans *con, struct stream *in_s)
{
int hContext;
struct pcsc_uds_client *uds_client;
+ struct pcsc_context *lcontext;
void *user_data;
LLOGLN(10, ("scard_process_release_context:"));
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"));
+ LLOGLN(0, ("scard_process_release_context: opps"));
return 1;
}
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));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_release_context(user_data, hContext);
- uds_client_remove_context(uds_client, hContext);
+ lcontext = get_pcsc_context_by_app_context(uds_client, hContext);
+ if (lcontext == 0)
+ {
+ LLOGLN(0, ("scard_process_release_context: "
+ "get_pcsc_context_by_app_context failed"));
+ return 1;
+ }
+ scard_send_release_context(user_data, lcontext->context,
+ lcontext->context_bytes);
+ uds_client_remove_context(uds_client, lcontext);
return 0;
}
@@ -517,6 +684,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
char *groups;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_list_readers:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -535,7 +703,15 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d",
hContext, cchReaders));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_list_readers(user_data, hContext, groups, cchReaders, 1);
+ lcontext = get_pcsc_context_by_app_context(uds_client, hContext);
+ if (lcontext == 0)
+ {
+ LLOGLN(0, ("scard_process_list_readers: "
+ "get_pcsc_context_by_app_context failed"));
+ return 1;
+ }
+ scard_send_list_readers(user_data, lcontext->context,
+ lcontext->context_bytes, groups, cchReaders, 1);
g_free(groups);
return 0;
}
@@ -635,10 +811,6 @@ scard_function_list_readers_return(void *user_data,
{
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);
@@ -657,6 +829,7 @@ scard_process_connect(struct trans *con, struct stream *in_s)
READER_STATE rs;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_connect:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -675,7 +848,16 @@ scard_process_connect(struct trans *con, struct stream *in_s)
"dwPreferredProtocols 0x%8.8x", rs.reader_name, rs.dwShareMode,
rs.dwPreferredProtocols));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_connect(user_data, hContext, 1, &rs);
+ lcontext = get_pcsc_context_by_app_context(uds_client, hContext);
+ if (lcontext == 0)
+ {
+ LLOGLN(0, ("scard_process_connect: "
+ "get_pcsc_context_by_app_context failed"));
+ return 1;
+ }
+ uds_client->connect_context = lcontext;
+ scard_send_connect(user_data, lcontext->context, lcontext->context_bytes,
+ 1, &rs);
return 0;
}
@@ -692,6 +874,9 @@ scard_function_connect_return(void *user_data,
struct stream *out_s;
struct pcsc_uds_client *uds_client;
struct trans *con;
+ char *card;
+ int card_bytes;
+ struct pcsc_card *lcard;
LLOGLN(10, ("scard_function_connect_return:"));
LLOGLN(10, (" status 0x%8.8x", status));
@@ -717,8 +902,11 @@ scard_function_connect_return(void *user_data,
{
in_uint8s(in_s, 36);
in_uint32_le(in_s, dwActiveProtocol);
- in_uint8s(in_s, 4);
- in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, card_bytes);
+ in_uint8p(in_s, card, card_bytes);
+ lcard = context_add_card(uds_client, uds_client->connect_context,
+ card, card_bytes);
+ hCard = lcard->app_card;
LLOGLN(10, (" hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol));
}
out_s = trans_get_out_s(con, 8192);
@@ -739,11 +927,12 @@ scard_function_connect_return(void *user_data,
int APP_CC
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;
+ struct pcsc_context *lcontext;
+ struct pcsc_card *lcard;
LLOGLN(10, ("scard_process_disconnect:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -755,11 +944,17 @@ scard_process_disconnect(struct trans *con, struct stream *in_s)
uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_D;
in_uint32_le(in_s, hCard);
in_uint32_le(in_s, dwDisposition);
-
- hContext = 1;
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_disconnect(user_data, hContext, hCard, dwDisposition);
-
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
+ if ((lcontext == 0) || (lcard == 0))
+ {
+ LLOGLN(0, ("scard_process_disconnect: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_disconnect(user_data,
+ lcontext->context, lcontext->context_bytes,
+ lcard->card, lcard->card_bytes, dwDisposition);
return 0;
}
@@ -769,8 +964,6 @@ 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;
@@ -795,17 +988,6 @@ scard_function_disconnect_return(void *user_data,
return 1;
}
uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_D;
- dwActiveProtocol = 0;
- hCard = 0;
- if (status == 0)
- {
- in_uint8s(in_s, 36);
- in_uint32_le(in_s, dwActiveProtocol);
- in_uint8s(in_s, 4);
- in_uint32_le(in_s, hCard);
- LLOGLN(10, ("scard_function_connect_return: hCard %d "
- "dwActiveProtocol %d", hCard, dwActiveProtocol));
- }
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 */
@@ -825,6 +1007,8 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s)
int hCard;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_card *lcard;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_begin_transaction:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -837,7 +1021,16 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s)
in_uint32_le(in_s, hCard);
LLOGLN(10, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_begin_transaction(user_data, hCard);
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
+ if ((lcard == 0) || (lcontext == 0))
+ {
+ LLOGLN(0, ("scard_process_begin_transaction: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_begin_transaction(user_data,
+ lcontext->context, lcontext->context_bytes,
+ lcard->card, lcard->card_bytes);
return 0;
}
@@ -892,6 +1085,8 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s)
int dwDisposition;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_card *lcard;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_end_transaction:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -905,7 +1100,17 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s)
in_uint32_le(in_s, dwDisposition);
LLOGLN(10, ("scard_process_end_transaction: hCard 0x%8.8x", hCard));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_end_transaction(user_data, hCard, dwDisposition);
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
+ if ((lcard == 0) || (lcontext == 0))
+ {
+ LLOGLN(0, ("scard_process_end_transaction: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_end_transaction(user_data,
+ lcontext->context, lcontext->context_bytes,
+ lcard->card, lcard->card_bytes,
+ dwDisposition);
return 0;
}
@@ -955,18 +1160,6 @@ scard_function_end_transaction_return(void *user_data,
/*****************************************************************************/
/* returns error */
int APP_CC
-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(void *user_data,
struct stream *in_s,
int len, int status)
@@ -987,6 +1180,8 @@ scard_process_transmit(struct trans *con, struct stream *in_s)
struct xrdp_scard_io_request recv_ior;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_card *lcard;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_transmit:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -1016,7 +1211,16 @@ scard_process_transmit(struct trans *con, struct stream *in_s)
//g_hexdump(in_s->p, send_bytes);
LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_transmit(user_data, hCard, send_data, send_bytes, recv_bytes,
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
+ if ((lcard == 0) || (lcontext == 0))
+ {
+ LLOGLN(0, ("scard_process_transmit: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_transmit(user_data, lcontext->context, lcontext->context_bytes,
+ lcard->card, lcard->card_bytes,
+ send_data, send_bytes, recv_bytes,
&send_ior, &recv_ior);
return 0;
}
@@ -1116,6 +1320,7 @@ scard_process_control(struct trans *con, struct stream *in_s)
char *send_data;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_card *lcard;
LLOGLN(10, ("scard_process_control:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -1134,7 +1339,15 @@ scard_process_control(struct trans *con, struct stream *in_s)
in_uint32_le(in_s, recv_bytes);
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_control(user_data, hCard, send_data, send_bytes, recv_bytes,
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, 0);
+ if (lcard == 0)
+ {
+ LLOGLN(0, ("scard_process_control: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_control(user_data, lcard->card, lcard->card_bytes,
+ send_data, send_bytes, recv_bytes,
control_code);
return 0;
@@ -1205,6 +1418,8 @@ scard_process_status(struct trans *con, struct stream *in_s)
int cbAtrLen;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_card *lcard;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_status:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -1220,7 +1435,16 @@ scard_process_status(struct trans *con, struct stream *in_s)
in_uint32_le(in_s, cbAtrLen);
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_status(user_data, 1, hCard, cchReaderLen, cbAtrLen);
+ lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
+ if ((lcard == 0) || (lcontext == 0))
+ {
+ LLOGLN(0, ("scard_process_status: "
+ "get_pcsc_card_by_app_card failed"));
+ return 1;
+ }
+ scard_send_status(user_data, 1, lcontext->context, lcontext->context_bytes,
+ lcard->card, lcard->card_bytes,
+ cchReaderLen, cbAtrLen);
return 0;
}
@@ -1343,6 +1567,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s)
READER_STATE *rsa;
struct pcsc_uds_client *uds_client;
void *user_data;
+ struct pcsc_context *lcontext;
LLOGLN(10, ("scard_process_get_status_change:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data);
@@ -1383,8 +1608,16 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s)
"%d cReaders %d", hContext, dwTimeout, cReaders));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
- scard_send_get_status_change(user_data, hContext, 1, dwTimeout, cReaders, rsa);
-
+ lcontext = get_pcsc_context_by_app_context(uds_client, hContext);
+ if (lcontext == 0)
+ {
+ LLOGLN(0, ("scard_process_get_status_change: "
+ "get_pcsc_context_by_app_context failed"));
+ return 1;
+ }
+ scard_send_get_status_change(user_data,
+ lcontext->context, lcontext->context_bytes,
+ 1, dwTimeout, cReaders, rsa);
g_free(rsa);
return 0;
@@ -1469,6 +1702,80 @@ scard_function_get_status_change_return(void *user_data,
/*****************************************************************************/
/* returns error */
int APP_CC
+scard_process_cancel(struct trans *con, struct stream *in_s)
+{
+ int hContext;
+ struct pcsc_uds_client *uds_client;
+ void *user_data;
+ struct pcsc_context *lcontext;
+
+ LLOGLN(10, ("scard_process_cancel:"));
+ uds_client = (struct pcsc_uds_client *) (con->callback_data);
+ if (uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CANCEL)
+ {
+ LLOGLN(0, ("scard_process_cancel: opps"));
+ return 1;
+ }
+ uds_client->pcsc_state |= XRDP_PCSC_STATE_GOT_CANCEL;
+ in_uint32_le(in_s, hContext);
+ LLOGLN(10, ("scard_process_cancel: hContext 0x%8.8x", hContext));
+ user_data = (void *) (tintptr) (uds_client->uds_client_id);
+ lcontext = get_pcsc_context_by_app_context(uds_client, hContext);
+ if (lcontext == 0)
+ {
+ LLOGLN(0, ("scard_process_cancel: "
+ "get_pcsc_context_by_app_context failed"));
+ return 1;
+ }
+ scard_send_cancel(user_data, lcontext->context, lcontext->context_bytes);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_cancel_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_cancel_return:"));
+ LLOGLN(10, (" status 0x%8.8x", status));
+ 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_cancel_return: "
+ "get_uds_client_by_id failed"));
+ return 1;
+ }
+ con = uds_client->con;
+ if ((uds_client->pcsc_state & XRDP_PCSC_STATE_GOT_CANCEL) == 0)
+ {
+ LLOGLN(0, ("scard_function_cancel_return: opps"));
+ return 1;
+ }
+ uds_client->pcsc_state &= ~XRDP_PCSC_STATE_GOT_CANCEL;
+ 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 */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x0D); /* SCARD_CANCEL 0x0D */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
scard_function_is_context_valid_return(void *user_data,
struct stream *in_s,
int len, int status)
@@ -1555,7 +1862,8 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command)
break;
case 0x0D: /* SCARD_CANCEL */
- LLOGLN(0, ("scard_process_msg: SCARD_CANCEL"));
+ LLOGLN(10, ("scard_process_msg: SCARD_CANCEL"));
+ rv = scard_process_cancel(con, in_s);
break;
case 0x0E: /* SCARD_CANCEL_TRANSACTION */