From b69c144c7dc1cbd2d6bed5ac905f5a896719a6fb Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Fri, 18 Oct 2013 20:56:28 -0700 Subject: [PATCH] chansrv: work on smartcard --- sesman/chansrv/pcsc/xrdp_pcsc.c | 170 +++++++++++++++++++++++++--- sesman/chansrv/smartcard.c | 144 ++++++++++++++++++------ sesman/chansrv/smartcard.h | 18 ++- sesman/chansrv/smartcard_pcsc.c | 192 +++++++++++++++++++++++++++----- sesman/chansrv/smartcard_pcsc.h | 8 ++ 5 files changed, 456 insertions(+), 76 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index c10a1627..65be347c 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -393,12 +393,13 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, int offset; LLOGLN(0, ("SCardConnect:")); + LLOGLN(0, ("SCardConnect: hContext %p szReader %s dwShareMode %d dwPreferredProtocols %d", + hContext, szReader, dwShareMode, dwPreferredProtocols)); if (g_sck == -1) { LLOGLN(0, ("SCardConnect: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - pthread_mutex_lock(&g_mutex); offset = 0; SET_UINT32(msg, offset, hContext); offset += 4; @@ -409,12 +410,13 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, return SCARD_F_INTERNAL_ERROR; } memcpy(msg + offset, szReader, bytes); - memset(msg + bytes, 0, 100 - bytes); + memset(msg + offset + bytes, 0, 100 - bytes); offset += 100; SET_UINT32(msg, offset, dwShareMode); offset += 4; SET_UINT32(msg, offset, dwPreferredProtocols); offset += 4; + pthread_mutex_lock(&g_mutex); if (send_message(SCARD_CONNECT, msg, offset) != 0) { LLOGLN(0, ("SCardConnect: error, send_message")); @@ -463,6 +465,11 @@ SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) { + char msg[256]; + int code; + int bytes; + int status; + LLOGLN(0, ("SCardDisconnect:")); if (g_sck == -1) { @@ -470,8 +477,31 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + SET_UINT32(msg, 0, hCard); + SET_UINT32(msg, 4, dwDisposition); + if (send_message(SCARD_DISCONNECT, msg, 8) != 0) + { + LLOGLN(0, ("SCardDisconnect: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardDisconnect: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_DISCONNECT) || (bytes != 4)) + { + LLOGLN(0, ("SCardDisconnect: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardDisconnect: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ @@ -534,7 +564,7 @@ SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) pthread_mutex_lock(&g_mutex); SET_UINT32(msg, 0, hCard); SET_UINT32(msg, 4, dwDisposition); - if (send_message(SCARD_BEGIN_TRANSACTION, msg, 8) != 0) + if (send_message(SCARD_END_TRANSACTION, msg, 8) != 0) { LLOGLN(0, ("SCardEndTransaction: error, send_message")); pthread_mutex_unlock(&g_mutex); @@ -547,7 +577,7 @@ SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4)) + if ((code != SCARD_END_TRANSACTION) || (bytes != 4)) { LLOGLN(0, ("SCardEndTransaction: error, bad code")); pthread_mutex_unlock(&g_mutex); @@ -674,6 +704,12 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned) { + char *msg; + int bytes; + int code; + int offset; + int status = 0; + LLOGLN(0, ("SCardControl:")); if (g_sck == -1) { @@ -683,9 +719,50 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, LLOGLN(0, ("SCardControl: dwControlCode %d", dwControlCode)); LLOGLN(0, ("SCardControl: cbSendLength %d", cbSendLength)); LLOGLN(0, ("SCardControl: cbRecvLength %d", cbRecvLength)); + msg = (char *) malloc(8192); + offset = 0; + SET_UINT32(msg, offset, hCard); + offset += 4; + SET_UINT32(msg, offset, dwControlCode); + offset += 4; + SET_UINT32(msg, offset, cbSendLength); + offset += 4; + memcpy(msg + offset, pbSendBuffer, cbSendLength); + offset += cbSendLength; + SET_UINT32(msg, offset, cbRecvLength); + offset += 4; pthread_mutex_lock(&g_mutex); + if (send_message(SCARD_CONTROL, msg, offset) != 0) + { + LLOGLN(0, ("SCardControl: error, send_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 8192; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardControl: error, get_message")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if (code != SCARD_CONTROL) + { + LLOGLN(0, ("SCardControl: error, bad code")); + free(msg); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + offset = 0; + *lpBytesReturned = GET_UINT32(msg, offset); + offset += 4; + memcpy(pbRecvBuffer, msg + offset, *lpBytesReturned); + offset += *lpBytesReturned; + status = GET_UINT32(msg, offset); + free(msg); + return status; } /*****************************************************************************/ @@ -700,6 +777,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, int code; int offset; int status; + int extra_len; LLOGLN(0, ("SCardTransmit:")); if (g_sck == -1) @@ -708,19 +786,55 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, return SCARD_F_INTERNAL_ERROR; } LLOGLN(0, ("SCardTransmit: cbSendLength %d", cbSendLength)); - + LLOGLN(0, ("SCardTransmit: pioRecvPci %p", pioRecvPci)); + if (pioRecvPci != 0) + { + LLOGLN(0, ("SCardTransmit: pioRecvPci->dwProtocol %d", + (int)pioRecvPci->dwProtocol)); + LLOGLN(0, ("SCardTransmit: pioRecvPci->cbPciLength %d", + (int)pioRecvPci->cbPciLength)); + } msg = (char *) malloc(8192); - SET_UINT32(msg, 0, hCard); - SET_UINT32(msg, 4, pioSendPci->dwProtocol); - SET_UINT32(msg, 8, pioSendPci->cbPciLength); - SET_UINT32(msg, 12, cbSendLength); - offset = 16; - memcpy(msg + 16, pbSendBuffer, cbSendLength); + offset = 0; + SET_UINT32(msg, offset, hCard); + offset += 4; + SET_UINT32(msg, offset, pioSendPci->dwProtocol); + offset += 4; + SET_UINT32(msg, offset, pioSendPci->cbPciLength); + offset += 4; + extra_len = pioSendPci->cbPciLength - 8; + SET_UINT32(msg, offset, extra_len); + offset += 4; + memcpy(msg + offset, pioSendPci + 1, extra_len); + offset += extra_len; + SET_UINT32(msg, offset, cbSendLength); + offset += 4; + memcpy(msg + offset, pbSendBuffer, cbSendLength); offset += cbSendLength; + if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) + { + SET_UINT32(msg, offset, 0); /* dwProtocol */ + offset += 4; + SET_UINT32(msg, offset, 0); /* cbPciLength */ + offset += 4; + SET_UINT32(msg, offset, 0); /* extra_len */ + offset += 4; + } + else + { + SET_UINT32(msg, offset, pioRecvPci->dwProtocol); + offset += 4; + SET_UINT32(msg, offset, pioRecvPci->cbPciLength); + offset += 4; + extra_len = pioRecvPci->cbPciLength - 8; + SET_UINT32(msg, offset, extra_len); + offset += 4; + memcpy(msg + offset, pioRecvPci + 1, extra_len); + offset += extra_len; + } SET_UINT32(msg, offset, *pcbRecvLength); offset += 4; pthread_mutex_lock(&g_mutex); - if (send_message(SCARD_TRANSMIT, msg, offset) != 0) { LLOGLN(0, ("SCardTransmit: error, send_message")); @@ -743,9 +857,33 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } - pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + offset = 0; + if (pioRecvPci == 0) + { + offset += 8; + extra_len = GET_UINT32(msg, offset); + offset += 4; + offset += extra_len; + } + else + { + pioRecvPci->dwProtocol = GET_UINT32(msg, offset); + offset += 4; + pioRecvPci->cbPciLength = GET_UINT32(msg, offset); + offset += 4; + extra_len = GET_UINT32(msg, offset); + offset += 4; + offset += extra_len; + } + *pcbRecvLength = GET_UINT32(msg, offset); + offset += 4; + LLOGLN(0, ("SCardTransmit: cbRecvLength %d", *pcbRecvLength)); + memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength); + offset += *pcbRecvLength; + status = GET_UINT32(msg, offset); + free(msg); + return status; } /*****************************************************************************/ diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 2b07b90e..e22c5eb5 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -182,13 +182,17 @@ static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle, static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle); static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context, - tui32 sc_handle); + tui32 sc_handle, int dwDisposition); static int APP_CC scard_send_Transmit(IRP* irp, tui32 sc_handle, - READER_STATE* rs); + char *send_data, int send_bytes, + int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior); static int APP_CC scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, - READER_STATE* rs); + char *send_data, int send_bytes, + int recv_bytes, int control_code); static int APP_CC scard_send_Cancel(IRP* irp, tui32 context); @@ -639,7 +643,8 @@ scard_send_status(struct trans *con, int wide, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ int APP_CC -scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) +scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle, + int dwDisposition) { IRP *irp; @@ -657,7 +662,7 @@ scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) irp->user_data = con; /* send IRP to client */ - scard_send_Disconnect(irp, context, sc_handle); + scard_send_Disconnect(irp, context, sc_handle, dwDisposition); return 0; } @@ -667,7 +672,10 @@ scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) * associated with a valid context. *****************************************************************************/ int APP_CC -scard_send_transmit(struct trans *con, tui32 sc_handle, READER_STATE* rs) +scard_send_transmit(struct trans *con, tui32 sc_handle, + char *send_data, int send_bytes, int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior) { IRP *irp; @@ -685,7 +693,8 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, READER_STATE* rs) irp->user_data = con; /* send IRP to client */ - scard_send_Transmit(irp, sc_handle, rs); + scard_send_Transmit(irp, sc_handle, send_data, send_bytes, recv_bytes, + send_ior, recv_ior); return 0; } @@ -695,7 +704,8 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, READER_STATE* rs) *****************************************************************************/ int APP_CC scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, - READER_STATE* rs) + char *send_data, int send_bytes, + int recv_bytes, int control_code) { IRP *irp; @@ -713,7 +723,8 @@ scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, irp->user_data = con; /* send IRP to client */ - scard_send_Control(irp, context, sc_handle, rs); + scard_send_Control(irp, context, sc_handle, send_data, + send_bytes, recv_bytes, control_code); return 0; } @@ -1594,7 +1605,8 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ static void APP_CC -scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle) +scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, + int dwDisposition) { /* see [MS-RDPESC] 3.1.4.30 */ @@ -1627,7 +1639,7 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle) */ xstream_seek(s, 24); - xstream_wr_u32_le(s, SCARD_RESET_CARD); + xstream_wr_u32_le(s, dwDisposition); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1653,13 +1665,17 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle) * associated with a valid context. *****************************************************************************/ static int APP_CC -scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) +scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, + int send_bytes, int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior) { /* see [MS-RDPESC] 2.2.2.19 */ SMARTCARD* sc; struct stream* s; int bytes; + int val; if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -1670,6 +1686,12 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_TRANSMIT)) == NULL) return; + log_debug("send_bytes %d recv_bytes %d send dwProtocol %d cbPciLength %d " + "extra_bytes %d recv dwProtocol %d cbPciLength %d", send_bytes, + recv_bytes, send_ior->dwProtocol, send_ior->cbPciLength, + send_ior->extra_bytes, recv_ior->dwProtocol, recv_ior->cbPciLength, + recv_ior->extra_bytes); + /* * command format * @@ -1695,21 +1717,48 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) */ xstream_seek(s, 12); - xstream_wr_u32_le(s, rs->map0); + xstream_wr_u32_le(s, 0); // map0 xstream_seek(s, 4); - xstream_wr_u32_le(s, rs->map1); - xstream_wr_u32_le(s, rs->dwProtocol); - xstream_wr_u32_le(s, rs->cbPciLength); - xstream_wr_u32_le(s, rs->map2); - xstream_wr_u32_le(s, rs->cbSendLength); - xstream_wr_u32_le(s, rs->map3); - xstream_wr_u32_le(s, rs->map4); - xstream_wr_u32_le(s, rs->map5); - xstream_wr_u32_le(s, rs->map6); - xstream_wr_u32_le(s, rs->cbRecvLength); + xstream_wr_u32_le(s, 0); // map1 + xstream_wr_u32_le(s, send_ior->dwProtocol); + xstream_wr_u32_le(s, send_ior->cbPciLength); + val = send_ior->extra_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map2 + xstream_wr_u32_le(s, send_bytes); + val = send_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map3 + val = recv_ior->cbPciLength > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map 4 + xstream_wr_u32_le(s, 0); // map5 + xstream_wr_u32_le(s, recv_bytes); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); + if (send_ior->extra_bytes > 0) + { + xstream_wr_u32_le(s, send_ior->extra_bytes); + out_uint8a(s, send_ior->extra_data, send_ior->extra_bytes); + } + + if (send_bytes > 0) + { + xstream_wr_u32_le(s, send_bytes); + out_uint8a(s, send_data, send_bytes); + } + + if (recv_ior->cbPciLength > 0) + { + xstream_wr_u32_le(s, recv_ior->dwProtocol); + xstream_wr_u32_le(s, recv_ior->cbPciLength); + val = recv_ior->extra_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); + if (val) + { + xstream_wr_u32_le(s, recv_ior->extra_bytes); + out_uint8a(s, recv_ior->extra_data, recv_ior->extra_bytes); + } + } + /* get stream len */ bytes = xstream_len(s); @@ -1725,13 +1774,15 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) +scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, + int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ SMARTCARD* sc; struct stream* s; int bytes; + int val; if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -1765,19 +1816,30 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) */ xstream_seek(s, 12); - xstream_wr_u32_le(s, rs->map0); - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, rs->map1); - xstream_wr_u32_le(s, rs->dwControlCode); - xstream_wr_u32_le(s, rs->cbRecvLength); - xstream_wr_u32_le(s, rs->map2); + xstream_wr_u32_le(s, 0); // map0 + xstream_seek(s, 4); + xstream_wr_u32_le(s, 0); // map1 + + xstream_wr_u32_le(s, control_code); + + xstream_wr_u32_le(s, send_bytes); + + val = send_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map2 + xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, rs->cbOutBufferSize); + xstream_wr_u32_le(s, recv_bytes); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, context); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); + if (send_bytes > 0) + { + xstream_wr_u32_le(s, send_bytes); + out_uint8a(s, send_data, send_bytes); + } + /* get stream len */ bytes = xstream_len(s); @@ -2170,6 +2232,7 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2190,6 +2253,10 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + con = (struct trans *) (irp->user_data); + scard_function_end_transaction_return(con, s, len); + devredir_irp_delete(irp); + log_debug("leaving"); } @@ -2234,6 +2301,7 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2254,6 +2322,10 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + con = (struct trans *) (irp->user_data); + scard_function_disconnect_return(con, s, len); + devredir_irp_delete(irp); + log_debug("leaving"); } @@ -2265,6 +2337,7 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2285,6 +2358,10 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + con = (struct trans *) (irp->user_data); + scard_function_transmit_return(con, s, len); + devredir_irp_delete(irp); + log_debug("leaving"); } @@ -2296,6 +2373,7 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId,tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2316,6 +2394,10 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + con = (struct trans *) (irp->user_data); + scard_function_control_return(con, s, len); + devredir_irp_delete(irp); + log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 14c5d6f2..432cc80b 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -48,6 +48,14 @@ #define SCARD_RESET_CARD 0x00000001 /* reset smart card */ #define SCARD_UNPOWER_CARD 0x00000002 /* turn off and reset card */ +struct xrdp_scard_io_request +{ + tui32 dwProtocol; + tui32 cbPciLength; + int extra_bytes; + char *extra_data; +}; + typedef struct reader_state { char reader_name[128]; @@ -121,13 +129,17 @@ int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle, tui32 dwDisposition); int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle); -int APP_CC scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle); +int APP_CC scard_send_disconnect(struct trans *con, tui32 context, + tui32 sc_handle, int dwDisposition); int APP_CC scard_send_transmit(struct trans *con, tui32 sc_handle, - READER_STATE* rs); + char *send_data, int send_bytes, int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior); int APP_CC scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, - READER_STATE* rs); + char *send_data, int send_bytes, + int recv_bytes, int control_code); int APP_CC scard_send_cancel(struct trans *con, tui32 context); diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index b010eee7..02cdf312 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -60,6 +60,7 @@ #define XRDP_PCSC_STATE_GOT_ET (1 << 6) /* end transaction */ #define XRDP_PCSC_STATE_GOT_TR (1 << 7) /* transmit */ #define XRDP_PCSC_STATE_GOT_CO (1 << 8) /* control */ +#define XRDP_PCSC_STATE_GOT_D (1 << 9) /* disconnect */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -329,7 +330,6 @@ int APP_CC scard_process_connect(struct trans *con, struct stream *in_s) { int hContext; - char szReader[100]; READER_STATE rs; LLOGLN(0, ("scard_process_connect:")); @@ -341,11 +341,11 @@ scard_process_connect(struct trans *con, struct stream *in_s) g_memset(&rs, 0, sizeof(rs)); g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_C; in_uint32_le(in_s, hContext); - in_uint8a(in_s, szReader, 100); + in_uint8a(in_s, rs.reader_name, 100); in_uint32_le(in_s, rs.dwShareMode); in_uint32_le(in_s, rs.dwPreferredProtocols); - LLOGLN(0, ("scard_process_connect: dwShareMode 0x%8.8x " - "dwPreferredProtocols 0x%8.8x", rs.dwShareMode, + LLOGLN(0, ("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); return 0; @@ -371,8 +371,9 @@ scard_function_connect_return(struct trans *con, g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C; in_uint8s(in_s, 36); in_uint32_le(in_s, dwActiveProtocol); - in_uint8s(in_s, 36); + in_uint8s(in_s, 4); in_uint32_le(in_s, hCard); + LLOGLN(0, ("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, hCard); @@ -386,6 +387,66 @@ scard_function_connect_return(struct trans *con, return trans_force_write(con); } +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_disconnect(struct trans *con, struct stream *in_s) +{ + int hContext; + int hCard; + int dwDisposition; + + LLOGLN(0, ("scard_process_disconnect:")); + if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) + { + LLOGLN(0, ("scard_process_disconnect: opps")); + return 1; + } + g_xrdp_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); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +scard_function_disconnect_return(struct trans *con, + struct stream *in_s, + int len) +{ + int dwActiveProtocol; + int hCard; + int bytes; + struct stream *out_s; + + g_hexdump(in_s->p, len); + if ((g_xrdp_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; + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + in_uint8s(in_s, 4); + in_uint32_le(in_s, hCard); + LLOGLN(0, ("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, 0); /* 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, 0x06); /* SCARD_DISCONNECT 0x06 */ + return trans_force_write(con); +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -492,7 +553,11 @@ int APP_CC scard_process_transmit(struct trans *con, struct stream *in_s) { int hCard; - READER_STATE rs; + int recv_bytes; + int send_bytes; + char *send_data; + struct xrdp_scard_io_request send_ior; + struct xrdp_scard_io_request recv_ior; LLOGLN(0, ("scard_process_transmit:")); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) @@ -502,21 +567,26 @@ scard_process_transmit(struct trans *con, struct stream *in_s) } g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_TR; LLOGLN(0, ("scard_process_transmit:")); - - // todo - g_memset(&rs, 0, sizeof(rs)); - in_uint32_le(in_s, hCard); - in_uint32_le(in_s, rs.dwProtocol); - in_uint32_le(in_s, rs.cbPciLength); - in_uint32_le(in_s, rs.cbSendLength); - LLOGLN(0, ("scard_process_transmit: dwProtocol %d cbPciLength %d " - "cbSendLength %d", rs.dwProtocol, rs.cbPciLength, rs.cbSendLength)); - g_hexdump(in_s->p, rs.cbSendLength); - in_uint8s(in_s, rs.cbSendLength); - in_uint32_le(in_s, rs.cbRecvLength); - LLOGLN(0, ("scard_process_transmit: cbRecvLength %d", rs.cbRecvLength)); - + in_uint32_le(in_s, send_ior.dwProtocol); + in_uint32_le(in_s, send_ior.cbPciLength); + in_uint32_le(in_s, send_ior.extra_bytes); + in_uint8p(in_s, send_ior.extra_data, send_ior.extra_bytes); + in_uint32_le(in_s, send_bytes); + in_uint8p(in_s, send_data, send_bytes); + in_uint32_le(in_s, recv_ior.dwProtocol); + in_uint32_le(in_s, recv_ior.cbPciLength); + in_uint32_le(in_s, recv_ior.extra_bytes); + in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes); + in_uint32_le(in_s, recv_bytes); + LLOGLN(0, ("scard_process_transmit: send dwProtocol %d cbPciLength %d " + "recv dwProtocol %d cbPciLength %d send_bytes %d ", + send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol, + recv_ior.cbPciLength, send_bytes)); + g_hexdump(in_s->p, send_bytes); + LLOGLN(0, ("scard_process_transmit: recv_bytes %d", recv_bytes)); + scard_send_transmit(con, hCard, send_data, send_bytes, recv_bytes, + &send_ior, &recv_ior); return 0; } @@ -529,7 +599,13 @@ scard_function_transmit_return(struct trans *con, { struct stream *out_s; int bytes; + int val; + int got_recv_pci; + int cbRecvLength; + struct xrdp_scard_io_request recv_ior; + char *recvBuf; + LLOGLN(0, ("scard_function_transmit_return:")); g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0) { @@ -538,9 +614,41 @@ scard_function_transmit_return(struct trans *con, } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR; - // todo - - return 0; + in_uint8s(in_s, 20); + in_uint32_le(in_s, val); + g_memset(&recv_ior, 0, sizeof(recv_ior)); + got_recv_pci = 0; + if (val != 0) + { + /* pioRecvPci */ + got_recv_pci = 1; + LLOGLN(0, ("scard_function_transmit_return: pioRecvPci not zero!")); + } + in_uint8s(in_s, 4); + in_uint32_le(in_s, val); + cbRecvLength = 0; + recvBuf = 0; + if (val != 0) + { + in_uint32_le(in_s, cbRecvLength); + in_uint8p(in_s, recvBuf, cbRecvLength); + } + LLOGLN(0, ("scard_function_transmit_return: cbRecvLength %d", cbRecvLength)); + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, recv_ior.dwProtocol); + out_uint32_le(out_s, recv_ior.cbPciLength); + out_uint32_le(out_s, recv_ior.extra_bytes); + out_uint8a(out_s, recv_ior.extra_data, recv_ior.extra_bytes); + out_uint32_le(out_s, cbRecvLength); + out_uint8a(out_s, recvBuf, cbRecvLength); + out_uint32_le(out_s, 0); /* 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, 0x09); /* SCARD_TRANSMIT 0x09 */ + return trans_force_write(con); } /*****************************************************************************/ @@ -548,6 +656,13 @@ scard_function_transmit_return(struct trans *con, int APP_CC scard_process_control(struct trans *con, struct stream *in_s) { + tui32 context; + int hCard; + int send_bytes; + int recv_bytes; + int control_code; + char *send_data; + LLOGLN(0, ("scard_process_control:")); if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) { @@ -557,7 +672,16 @@ scard_process_control(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_CO; LLOGLN(0, ("scard_process_control:")); - // todo + in_uint32_le(in_s, hCard); + in_uint32_le(in_s, control_code); + in_uint32_le(in_s, send_bytes); + in_uint8p(in_s, send_data, send_bytes); + in_uint32_le(in_s, recv_bytes); + + context = 1; + + scard_send_control(con, context, hCard, send_data, send_bytes, recv_bytes, + control_code); return 0; } @@ -571,6 +695,8 @@ scard_function_control_return(struct trans *con, { struct stream *out_s; int bytes; + int cbRecvLength; + char *recvBuf; g_hexdump(in_s->p, len); if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0) @@ -580,9 +706,22 @@ scard_function_control_return(struct trans *con, } g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO; - // todo + in_uint8s(in_s, 28); + in_uint32_le(in_s, cbRecvLength); + in_uint8p(in_s, recvBuf, cbRecvLength); - return 0; + LLOGLN(0, ("scard_function_control_return: cbRecvLength %d", cbRecvLength)); + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, cbRecvLength); + out_uint8a(out_s, recvBuf, cbRecvLength); + out_uint32_le(out_s, 0); /* 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, 0x0A); /* SCARD_CONTROL 0x0A */ + return trans_force_write(con); } /*****************************************************************************/ @@ -729,6 +868,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x06: /* SCARD_DISCONNECT */ LLOGLN(0, ("scard_process_msg: SCARD_DISCONNECT")); + rv = scard_process_disconnect(con, in_s); break; case 0x07: /* SCARD_BEGIN_TRANSACTION */ diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index d22f4322..d5447cff 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -38,6 +38,14 @@ int APP_CC scard_function_list_readers_return(struct trans *con, struct stream *in_s, int len); +int APP_CC scard_function_transmit_return(struct trans *con, + struct stream *in_s, + int len); + +int APP_CC scard_function_control_return(struct trans *con, + struct stream *in_s, + int len); + int APP_CC scard_function_get_status_change_return(struct trans *con, struct stream *in_s, int len);