chansrv: smartcard, fix for SCardControl, SCardTransmit

ulab-next
Jay Sorg 11 years ago
parent 2aa92fd6a8
commit 9f8d369747

@ -461,9 +461,9 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
int offset; int offset;
LLOGLN(10, ("SCardConnect:")); LLOGLN(10, ("SCardConnect:"));
LLOGLN(10, ("SCardConnect: hContext %p szReader %s dwShareMode %d " LLOGLN(10, ("SCardConnect: hContext 0x%8.8x szReader %s dwShareMode %d "
"dwPreferredProtocols %d", "dwPreferredProtocols %d",
(void*)hContext, szReader, dwShareMode, dwPreferredProtocols)); hContext, szReader, dwShareMode, dwPreferredProtocols));
if (g_sck == -1) if (g_sck == -1)
{ {
LLOGLN(0, ("SCardConnect: error, not connected")); LLOGLN(0, ("SCardConnect: error, not connected"));
@ -505,8 +505,9 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
*phCard = GET_UINT32(msg, 0); *phCard = GET_UINT32(msg, 0);
*pdwActiveProtocol = GET_UINT32(msg, 4); *pdwActiveProtocol = GET_UINT32(msg, 4);
status = GET_UINT32(msg, 8); status = GET_UINT32(msg, 8);
LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard %d", LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard 0x%8.8x "
status, *phCard)); "dwActiveProtocol %d",
status, *phCard, *pdwActiveProtocol));
return status; return status;
} }
@ -534,7 +535,7 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
int bytes; int bytes;
int status; int status;
LLOGLN(10, ("SCardDisconnect: hCard %d dwDisposition %d", LLOGLN(10, ("SCardDisconnect: hCard 0x%8.8x dwDisposition %d",
hCard, dwDisposition)); hCard, dwDisposition));
if (g_sck == -1) if (g_sck == -1)
{ {
@ -574,7 +575,7 @@ SCardBeginTransaction(SCARDHANDLE hCard)
int bytes; int bytes;
int status; int status;
LLOGLN(10, ("SCardBeginTransaction: hCard %d", hCard)); LLOGLN(10, ("SCardBeginTransaction: hCard 0x%8.8x", hCard));
if (hCard == 0) if (hCard == 0)
{ {
LLOGLN(0, ("SCardBeginTransaction: error, bad hCard")); LLOGLN(0, ("SCardBeginTransaction: error, bad hCard"));
@ -967,6 +968,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
int offset; int offset;
int status; int status;
int extra_len; int extra_len;
int got_recv_pci;
LLOGLN(10, ("SCardTransmit:")); LLOGLN(10, ("SCardTransmit:"));
if (g_sck == -1) if (g_sck == -1)
@ -1002,8 +1004,10 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
offset += 4; offset += 4;
memcpy(msg + offset, pbSendBuffer, cbSendLength); memcpy(msg + offset, pbSendBuffer, cbSendLength);
offset += cbSendLength; offset += cbSendLength;
if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) // TODO figure out why recv pci does not work
if (1 || (pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8))
{ {
got_recv_pci = 0;
SET_UINT32(msg, offset, 0); /* dwProtocol */ SET_UINT32(msg, offset, 0); /* dwProtocol */
offset += 4; offset += 4;
SET_UINT32(msg, offset, 0); /* cbPciLength */ SET_UINT32(msg, offset, 0); /* cbPciLength */
@ -1013,6 +1017,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
} }
else else
{ {
got_recv_pci = 1;
SET_UINT32(msg, offset, pioRecvPci->dwProtocol); SET_UINT32(msg, offset, pioRecvPci->dwProtocol);
offset += 4; offset += 4;
SET_UINT32(msg, offset, pioRecvPci->cbPciLength); SET_UINT32(msg, offset, pioRecvPci->cbPciLength);
@ -1046,7 +1051,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
offset = 0; offset = 0;
if (pioRecvPci == 0) if (got_recv_pci == 0)
{ {
offset += 8; offset += 8;
extra_len = GET_UINT32(msg, offset); extra_len = GET_UINT32(msg, offset);

@ -207,7 +207,8 @@ static int APP_CC scard_send_Transmit(IRP *irp,
int recv_bytes, int recv_bytes,
struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *send_ior,
struct xrdp_scard_io_request *recv_ior); struct xrdp_scard_io_request *recv_ior);
static int APP_CC scard_send_Control(IRP* irp, char *card, int card_bytes, static int APP_CC scard_send_Control(IRP* irp, char *context, int context_bytes,
char *card, int card_bytes,
char *send_data, int send_bytes, char *send_data, int send_bytes,
int recv_bytes, int control_code); int recv_bytes, int control_code);
static int APP_CC scard_send_Cancel(IRP *irp, char *context, int context_bytes); static int APP_CC scard_send_Cancel(IRP *irp, char *context, int context_bytes);
@ -737,7 +738,8 @@ scard_send_transmit(void *user_data, char *context, int context_bytes,
* Communicate directly with the smart card reader * Communicate directly with the smart card reader
*****************************************************************************/ *****************************************************************************/
int APP_CC int APP_CC
scard_send_control(void *user_data, char *card, int card_bytes, scard_send_control(void *user_data, char* context, int context_bytes,
char *card, int card_bytes,
char *send_data, int send_bytes, char *send_data, int send_bytes,
int recv_bytes, int control_code) int recv_bytes, int control_code)
{ {
@ -757,8 +759,10 @@ scard_send_control(void *user_data, char *card, int card_bytes,
irp->user_data = user_data; irp->user_data = user_data;
/* send IRP to client */ /* send IRP to client */
scard_send_Control(irp, card, card_bytes, send_data, scard_send_Control(irp, context, context_bytes,
send_bytes, recv_bytes, control_code); card, card_bytes,
send_data, send_bytes,
recv_bytes, control_code);
return 0; return 0;
} }
@ -1981,7 +1985,7 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes,
{ {
/* map4 */ /* map4 */
out_uint32_le(s, recv_ior->dwProtocol); out_uint32_le(s, recv_ior->dwProtocol);
out_uint32_le(s, recv_ior->cbPciLength); out_uint32_le(s, recv_ior->cbPciLength - 8);
val = recv_ior->extra_bytes > 0 ? 1 : 0; val = recv_ior->extra_bytes > 0 ? 1 : 0;
out_uint32_le(s, val); /* map6*/ out_uint32_le(s, val); /* map6*/
if (val) if (val)
@ -2022,7 +2026,8 @@ scard_send_Transmit(IRP *irp, char *context, int context_bytes,
* Communicate directly with the smart card reader * Communicate directly with the smart card reader
*****************************************************************************/ *****************************************************************************/
static int APP_CC static int APP_CC
scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data, scard_send_Control(IRP *irp, char *context, int context_bytes,
char *card, int card_bytes, char *send_data,
int send_bytes, int recv_bytes, int control_code) int send_bytes, int recv_bytes, int control_code)
{ {
/* see [MS-RDPESC] 2.2.2.19 */ /* see [MS-RDPESC] 2.2.2.19 */
@ -2046,9 +2051,9 @@ scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data,
s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00000000);
out_uint32_le(s, 0x00000004); out_uint32_le(s, context_bytes);
out_uint32_le(s, 0x00020000); /* map0 */ out_uint32_le(s, 0x00020000); /* map0 */
out_uint32_le(s, 0x00000004); out_uint32_le(s, card_bytes);
out_uint32_le(s, 0x00020004); /* map1 */ out_uint32_le(s, 0x00020004); /* map1 */
out_uint32_le(s, control_code); out_uint32_le(s, control_code);
out_uint32_le(s, send_bytes); out_uint32_le(s, send_bytes);
@ -2056,8 +2061,8 @@ scard_send_Control(IRP *irp, char *card, int card_bytes, char *send_data,
out_uint32_le(s, val); /* map2 */ out_uint32_le(s, val); /* map2 */
out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00000000);
out_uint32_le(s, recv_bytes); out_uint32_le(s, recv_bytes);
out_uint32_le(s, 4); out_uint32_le(s, context_bytes);
out_uint32_le(s, 0); /* context ? */ out_uint8a(s, context, context_bytes);
out_uint32_le(s, card_bytes); out_uint32_le(s, card_bytes);
out_uint8a(s, card, card_bytes); out_uint8a(s, card, card_bytes);
if (send_bytes > 0) if (send_bytes > 0)

@ -156,7 +156,9 @@ int APP_CC scard_send_transmit(void *user_data,
struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *send_ior,
struct xrdp_scard_io_request *recv_ior); struct xrdp_scard_io_request *recv_ior);
int APP_CC scard_send_control(void *user_data, char *card, int card_bytes, int APP_CC scard_send_control(void *user_data,
char *context, int context_bytes,
char *card, int card_bytes,
char *send_data, int send_bytes, char *send_data, int send_bytes,
int recv_bytes, int control_code); int recv_bytes, int control_code);

@ -53,14 +53,12 @@
extern int g_display_num; /* in chansrv.c */ 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 */ static int g_autoinc = 0; /* general purpose autoinc */
struct pcsc_card /* item for list of open cards in one context */ struct pcsc_card /* item for list of open cards in one context */
{ {
tui32 app_card; /* application card, always 4 bytes */ tui32 app_card; /* application card, always 4 bytes */
int card_bytes; /* client card bytes */ int card_bytes; /* client card bytes */
char card[16]; /* client card */ char card[16]; /* client card */
}; };
@ -68,16 +66,16 @@ struct pcsc_context
{ {
tui32 app_context; /* application context, always 4 byte */ tui32 app_context; /* application context, always 4 byte */
int context_bytes; /* client context bytes */ int context_bytes; /* client context bytes */
char context[16]; /* client context */ char context[16]; /* client context */
struct list *cards; /* these need to be released on close */ struct list *cards; /* these need to be released on close */
}; };
/*****************************************************************************/ /*****************************************************************************/
struct pcsc_uds_client struct pcsc_uds_client
{ {
int uds_client_id; /* from g_uds_client_id */ int uds_client_id; /* unique id represents each app */
struct trans *con; struct trans *con; /* the connection to the app */
struct list *contexts; /* struct pcsc_context */ struct list *contexts; /* list of struct pcsc_context */
struct pcsc_context *connect_context; struct pcsc_context *connect_context;
}; };
@ -104,8 +102,8 @@ create_uds_client(struct trans *con)
{ {
return 0; return 0;
} }
g_uds_client_id++; g_autoinc++;
uds_client->uds_client_id = g_uds_client_id; uds_client->uds_client_id = g_autoinc;
uds_client->con = con; uds_client->con = con;
con->callback_data = uds_client; con->callback_data = uds_client;
return uds_client; return uds_client;
@ -283,7 +281,7 @@ uds_client_add_context(struct pcsc_uds_client *uds_client,
struct pcsc_context *pcscContext; struct pcsc_context *pcscContext;
LLOGLN(10, ("uds_client_add_context:")); LLOGLN(10, ("uds_client_add_context:"));
pcscContext = (struct pcsc_context * ) pcscContext = (struct pcsc_context *)
g_malloc(sizeof(struct pcsc_context), 1); g_malloc(sizeof(struct pcsc_context), 1);
if (pcscContext == 0) if (pcscContext == 0)
{ {
@ -457,7 +455,7 @@ scard_function_establish_context_return(void *user_data,
int uds_client_id; int uds_client_id;
int context_bytes; int context_bytes;
int app_context; int app_context;
char context[8]; char context[16];
struct stream *out_s; struct stream *out_s;
struct pcsc_uds_client *uds_client; struct pcsc_uds_client *uds_client;
struct trans *con; struct trans *con;
@ -477,12 +475,12 @@ scard_function_establish_context_return(void *user_data,
con = uds_client->con; con = uds_client->con;
lcontext = 0; lcontext = 0;
app_context = 0; app_context = 0;
g_memset(context, 0, 8); g_memset(context, 0, 16);
if (status == 0) if (status == 0)
{ {
in_uint8s(in_s, 28); in_uint8s(in_s, 28);
in_uint32_le(in_s, context_bytes); in_uint32_le(in_s, context_bytes);
if (context_bytes > 8) if (context_bytes > 16)
{ {
LLOGLN(0, ("scard_function_establish_context_return: opps " LLOGLN(0, ("scard_function_establish_context_return: opps "
"context_bytes %d", context_bytes)); "context_bytes %d", context_bytes));
@ -647,6 +645,8 @@ scard_function_list_readers_return(void *user_data,
return 1; return 1;
} }
uds_client_id = pcscListReaders->uds_client_id; uds_client_id = pcscListReaders->uds_client_id;
cchReaders = pcscListReaders->cchReaders;
g_free(pcscListReaders);
uds_client = (struct pcsc_uds_client *) uds_client = (struct pcsc_uds_client *)
get_uds_client_by_id(uds_client_id); get_uds_client_by_id(uds_client_id);
if (uds_client == 0) if (uds_client == 0)
@ -654,14 +654,9 @@ scard_function_list_readers_return(void *user_data,
LLOGLN(0, ("scard_function_list_readers_return: " LLOGLN(0, ("scard_function_list_readers_return: "
"get_uds_client_by_id failed, could not find id %d", "get_uds_client_by_id failed, could not find id %d",
uds_client_id)); uds_client_id));
g_free(pcscListReaders);
return 1; return 1;
} }
con = uds_client->con; con = uds_client->con;
cchReaders = pcscListReaders->cchReaders;
g_free(pcscListReaders);
g_memset(reader_name, 0, sizeof(reader_name)); g_memset(reader_name, 0, sizeof(reader_name));
g_memset(lreader_name, 0, sizeof(lreader_name)); g_memset(lreader_name, 0, sizeof(lreader_name));
rn_index = 0; rn_index = 0;
@ -1031,6 +1026,14 @@ scard_function_get_attrib_return(void *user_data,
return 0; return 0;
} }
/*****************************************************************************/
struct pcsc_transmit
{
int uds_client_id;
struct xrdp_scard_io_request recv_ior;
int cbRecvLength;
};
/*****************************************************************************/ /*****************************************************************************/
/* returns error */ /* returns error */
int APP_CC int APP_CC
@ -1043,9 +1046,9 @@ scard_process_transmit(struct trans *con, struct stream *in_s)
struct xrdp_scard_io_request send_ior; struct xrdp_scard_io_request send_ior;
struct xrdp_scard_io_request recv_ior; struct xrdp_scard_io_request recv_ior;
struct pcsc_uds_client *uds_client; struct pcsc_uds_client *uds_client;
void *user_data;
struct pcsc_card *lcard; struct pcsc_card *lcard;
struct pcsc_context *lcontext; struct pcsc_context *lcontext;
struct pcsc_transmit *pcscTransmit;
LLOGLN(10, ("scard_process_transmit:")); LLOGLN(10, ("scard_process_transmit:"));
uds_client = (struct pcsc_uds_client *) (con->callback_data); uds_client = (struct pcsc_uds_client *) (con->callback_data);
@ -1066,9 +1069,7 @@ scard_process_transmit(struct trans *con, struct stream *in_s)
"recv dwProtocol %d cbPciLength %d send_bytes %d ", "recv dwProtocol %d cbPciLength %d send_bytes %d ",
send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol, send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol,
recv_ior.cbPciLength, send_bytes)); recv_ior.cbPciLength, send_bytes));
//g_hexdump(in_s->p, send_bytes);
LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes)); LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes));
user_data = (void *) (tintptr) (uds_client->uds_client_id);
lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
if ((lcard == 0) || (lcontext == 0)) if ((lcard == 0) || (lcontext == 0))
{ {
@ -1076,7 +1077,15 @@ scard_process_transmit(struct trans *con, struct stream *in_s)
"get_pcsc_card_by_app_card failed")); "get_pcsc_card_by_app_card failed"));
return 1; return 1;
} }
scard_send_transmit(user_data, lcontext->context, lcontext->context_bytes,
pcscTransmit = (struct pcsc_transmit *)
g_malloc(sizeof(struct pcsc_transmit), 1);
pcscTransmit->uds_client_id = uds_client->uds_client_id;
pcscTransmit->recv_ior = recv_ior;
pcscTransmit->cbRecvLength = recv_bytes;
scard_send_transmit(pcscTransmit,
lcontext->context, lcontext->context_bytes,
lcard->card, lcard->card_bytes, lcard->card, lcard->card_bytes,
send_data, send_bytes, recv_bytes, send_data, send_bytes, recv_bytes,
&send_ior, &recv_ior); &send_ior, &recv_ior);
@ -1094,17 +1103,20 @@ scard_function_transmit_return(void *user_data,
int bytes; int bytes;
int val; int val;
int cbRecvLength; int cbRecvLength;
int uds_client_id;
struct xrdp_scard_io_request recv_ior;
char *recvBuf; char *recvBuf;
struct xrdp_scard_io_request recv_ior;
struct pcsc_uds_client *uds_client; struct pcsc_uds_client *uds_client;
struct trans *con; struct trans *con;
struct pcsc_transmit *pcscTransmit;
LLOGLN(10, ("scard_function_transmit_return:")); LLOGLN(10, ("scard_function_transmit_return:"));
LLOGLN(10, (" status 0x%8.8x", status)); LLOGLN(10, (" status 0x%8.8x", status));
uds_client_id = (int) (tintptr) user_data; pcscTransmit = (struct pcsc_transmit *) user_data;
recv_ior = pcscTransmit->recv_ior;
uds_client = (struct pcsc_uds_client *) uds_client = (struct pcsc_uds_client *)
get_uds_client_by_id(uds_client_id); get_uds_client_by_id(pcscTransmit->uds_client_id);
g_free(pcscTransmit);
if (uds_client == 0) if (uds_client == 0)
{ {
LLOGLN(0, ("scard_function_transmit_return: " LLOGLN(0, ("scard_function_transmit_return: "
@ -1112,7 +1124,6 @@ scard_function_transmit_return(void *user_data,
return 1; return 1;
} }
con = uds_client->con; con = uds_client->con;
g_memset(&recv_ior, 0, sizeof(recv_ior));
cbRecvLength = 0; cbRecvLength = 0;
recvBuf = 0; recvBuf = 0;
if (status == 0) if (status == 0)
@ -1172,6 +1183,7 @@ scard_process_control(struct trans *con, struct stream *in_s)
char *send_data; char *send_data;
struct pcsc_uds_client *uds_client; struct pcsc_uds_client *uds_client;
void *user_data; void *user_data;
struct pcsc_context *lcontext;
struct pcsc_card *lcard; struct pcsc_card *lcard;
LLOGLN(10, ("scard_process_control:")); LLOGLN(10, ("scard_process_control:"));
@ -1185,14 +1197,15 @@ scard_process_control(struct trans *con, struct stream *in_s)
in_uint32_le(in_s, recv_bytes); in_uint32_le(in_s, recv_bytes);
user_data = (void *) (tintptr) (uds_client->uds_client_id); user_data = (void *) (tintptr) (uds_client->uds_client_id);
lcard = get_pcsc_card_by_app_card(uds_client, hCard, 0); lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext);
if (lcard == 0) if ((lcard == 0) || (lcontext == 0))
{ {
LLOGLN(0, ("scard_process_control: " LLOGLN(0, ("scard_process_control: "
"get_pcsc_card_by_app_card failed")); "get_pcsc_card_by_app_card failed"));
return 1; return 1;
} }
scard_send_control(user_data, lcard->card, lcard->card_bytes, scard_send_control(user_data, lcontext->context, lcontext->context_bytes,
lcard->card, lcard->card_bytes,
send_data, send_bytes, recv_bytes, send_data, send_bytes, recv_bytes,
control_code); control_code);

Loading…
Cancel
Save