chansrv: work on smartcard

ulab-next
Jay Sorg 11 years ago
parent a31234539a
commit a695886f81

@ -520,6 +520,11 @@ SCardBeginTransaction(SCARDHANDLE hCard)
PCSC_API LONG PCSC_API LONG
SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{ {
char msg[256];
int code;
int bytes;
int status;
LLOGLN(0, ("SCardEndTransaction:")); LLOGLN(0, ("SCardEndTransaction:"));
if (g_sck == -1) if (g_sck == -1)
{ {
@ -527,8 +532,31 @@ SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
pthread_mutex_lock(&g_mutex); pthread_mutex_lock(&g_mutex);
SET_UINT32(msg, 0, hCard);
SET_UINT32(msg, 4, dwDisposition);
if (send_message(SCARD_BEGIN_TRANSACTION, msg, 8) != 0)
{
LLOGLN(0, ("SCardEndTransaction: error, send_message"));
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256;
if (get_message(&code, msg, &bytes) != 0)
{
LLOGLN(0, ("SCardEndTransaction: error, get_message"));
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
{
LLOGLN(0, ("SCardEndTransaction: error, bad code"));
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
pthread_mutex_unlock(&g_mutex); pthread_mutex_unlock(&g_mutex);
return SCARD_S_SUCCESS; status = GET_UINT32(msg, 0);
LLOGLN(10, ("SCardEndTransaction: got status 0x%8.8x", status));
return status;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -652,6 +680,9 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
LLOGLN(0, ("SCardControl: error, not connected")); LLOGLN(0, ("SCardControl: error, not connected"));
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
LLOGLN(0, ("SCardControl: dwControlCode %d", dwControlCode));
LLOGLN(0, ("SCardControl: cbSendLength %d", cbSendLength));
LLOGLN(0, ("SCardControl: cbRecvLength %d", cbRecvLength));
pthread_mutex_lock(&g_mutex); pthread_mutex_lock(&g_mutex);
pthread_mutex_unlock(&g_mutex); pthread_mutex_unlock(&g_mutex);
return SCARD_S_SUCCESS; return SCARD_S_SUCCESS;
@ -664,13 +695,55 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
LPDWORD pcbRecvLength) LPDWORD pcbRecvLength)
{ {
char *msg;
int bytes;
int code;
int offset;
int status;
LLOGLN(0, ("SCardTransmit:")); LLOGLN(0, ("SCardTransmit:"));
if (g_sck == -1) if (g_sck == -1)
{ {
LLOGLN(0, ("SCardTransmit: error, not connected")); LLOGLN(0, ("SCardTransmit: error, not connected"));
return SCARD_F_INTERNAL_ERROR; return SCARD_F_INTERNAL_ERROR;
} }
LLOGLN(0, ("SCardTransmit: cbSendLength %d", cbSendLength));
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 += cbSendLength;
SET_UINT32(msg, offset, *pcbRecvLength);
offset += 4;
pthread_mutex_lock(&g_mutex); pthread_mutex_lock(&g_mutex);
if (send_message(SCARD_TRANSMIT, msg, offset) != 0)
{
LLOGLN(0, ("SCardTransmit: 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, ("SCardTransmit: error, get_message"));
free(msg);
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_TRANSMIT)
{
LLOGLN(0, ("SCardTransmit: error, bad code"));
free(msg);
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
pthread_mutex_unlock(&g_mutex); pthread_mutex_unlock(&g_mutex);
return SCARD_S_SUCCESS; return SCARD_S_SUCCESS;
} }

@ -177,7 +177,8 @@ static void APP_CC scard_send_Reconnect(IRP* irp, tui32 context,
tui32 sc_handle, READER_STATE* rs); tui32 sc_handle, READER_STATE* rs);
static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle); static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle);
static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle); static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle,
tui32 dwDisposition);
static void APP_CC scard_send_Status(IRP* irp, int wide, 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, static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context,
@ -577,7 +578,8 @@ scard_send_begin_transaction(struct trans *con, tui32 sc_handle)
* @param sc_handle handle to smartcard * @param sc_handle handle to smartcard
*****************************************************************************/ *****************************************************************************/
int APP_CC int APP_CC
scard_send_end_transaction(struct trans *con, tui32 sc_handle) scard_send_end_transaction(struct trans *con, tui32 sc_handle,
tui32 dwDisposition)
{ {
IRP *irp; IRP *irp;
@ -595,7 +597,7 @@ scard_send_end_transaction(struct trans *con, tui32 sc_handle)
irp->user_data = con; irp->user_data = con;
/* send IRP to client */ /* send IRP to client */
scard_send_EndTransaction(irp, sc_handle); scard_send_EndTransaction(irp, sc_handle, dwDisposition);
return 0; return 0;
} }
@ -1469,12 +1471,12 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle)
* @param sc_handle handle to smartcard * @param sc_handle handle to smartcard
*****************************************************************************/ *****************************************************************************/
static void APP_CC static void APP_CC
scard_send_EndTransaction(IRP *irp, tui32 sc_handle) scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition)
{ {
/* see [MS-RDPESC] 3.1.4.32 */ /* see [MS-RDPESC] 3.1.4.32 */
SMARTCARD* sc; SMARTCARD *sc;
struct stream* s; struct stream *s;
int bytes; int bytes;
if ((sc = smartcards[irp->scard_index]) == NULL) if ((sc = smartcards[irp->scard_index]) == NULL)
@ -1501,7 +1503,7 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle)
*/ */
xstream_seek(s, 24); xstream_seek(s, 24);
xstream_wr_u32_le(s, SCARD_LEAVE_CARD); xstream_wr_u32_le(s, dwDisposition);
xstream_seek(s, 8); xstream_seek(s, 8);
/* insert handle */ /* insert handle */
@ -1790,7 +1792,8 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs)
/** /**
* Cancel any outstanding calls * Cancel any outstanding calls
*****************************************************************************/ *****************************************************************************/
static int APP_CC scard_send_Cancel(IRP* irp, tui32 context) static int APP_CC
scard_send_Cancel(IRP* irp, tui32 context)
{ {
/* see [MS-RDPESC] 3.1.4.27 */ /* see [MS-RDPESC] 3.1.4.27 */
@ -2081,9 +2084,11 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp,
/* get OutputBufferLen */ /* get OutputBufferLen */
xstream_rd_u32_le(s, len); xstream_rd_u32_le(s, len);
con = (struct trans *) (irp->user_data); con = (struct trans *) (irp->user_data);
scard_function_connect_return(con, s, len); scard_function_connect_return(con, s, len);
devredir_irp_delete(irp); devredir_irp_delete(irp);
log_debug("leaving"); log_debug("leaving");
} }
@ -2128,6 +2133,7 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
tui32 IoStatus) tui32 IoStatus)
{ {
tui32 len; tui32 len;
struct trans *con;
log_debug("entered"); log_debug("entered");
@ -2148,6 +2154,10 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
/* get OutputBufferLen */ /* get OutputBufferLen */
xstream_rd_u32_le(s, len); xstream_rd_u32_le(s, len);
con = (struct trans *) (irp->user_data);
scard_function_begin_transaction_return(con, s, len);
devredir_irp_delete(irp);
log_debug("leaving"); log_debug("leaving");
} }

@ -118,7 +118,8 @@ int APP_CC scard_send_reconnect(struct trans *con, tui32 context,
tui32 sc_handle, READER_STATE* rs); tui32 sc_handle, READER_STATE* rs);
int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle); 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); 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_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);

@ -57,6 +57,9 @@
#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ #define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */
#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */ #define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */
#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */ #define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */
#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 */
/* TODO: put this in con */ /* 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;
@ -403,6 +406,185 @@ scard_process_begin_transaction(struct trans *con, struct stream *in_s)
return 0; return 0;
} }
/*****************************************************************************/
/* returns error */
int APP_CC
scard_function_begin_transaction_return(struct trans *con,
struct stream *in_s,
int len)
{
struct stream *out_s;
int bytes;
g_hexdump(in_s->p, len);
if ((g_xrdp_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;
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, 0x07); /* SCARD_BEGIN_TRANSACTION 0x07 */
return trans_force_write(con);
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_process_end_transaction(struct trans *con, struct stream *in_s)
{
int hCard;
int dwDisposition;
LLOGLN(0, ("scard_process_end_transaction:"));
if (g_xrdp_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;
in_uint32_le(in_s, hCard);
in_uint32_le(in_s, dwDisposition);
LLOGLN(0, ("scard_process_end_transaction: hCard 0x%8.8x", hCard));
scard_send_end_transaction(con, hCard, dwDisposition);
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_function_end_transaction_return(struct trans *con,
struct stream *in_s,
int len)
{
struct stream *out_s;
int bytes;
g_hexdump(in_s->p, len);
if ((g_xrdp_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;
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, 0x08); /* SCARD_END_TRANSACTION 0x08 */
return trans_force_write(con);
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_process_transmit(struct trans *con, struct stream *in_s)
{
int hCard;
READER_STATE rs;
LLOGLN(0, ("scard_process_transmit:"));
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR)
{
LLOGLN(0, ("scard_process_transmit: opps"));
return 1;
}
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));
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_function_transmit_return(struct trans *con,
struct stream *in_s,
int len)
{
struct stream *out_s;
int bytes;
g_hexdump(in_s->p, len);
if ((g_xrdp_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;
// todo
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_process_control(struct trans *con, struct stream *in_s)
{
LLOGLN(0, ("scard_process_control:"));
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO)
{
LLOGLN(0, ("scard_process_control: opps"));
return 1;
}
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_CO;
LLOGLN(0, ("scard_process_control:"));
// todo
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
scard_function_control_return(struct trans *con,
struct stream *in_s,
int len)
{
struct stream *out_s;
int bytes;
g_hexdump(in_s->p, len);
if ((g_xrdp_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;
// todo
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
/* returns error */ /* returns error */
int APP_CC int APP_CC
@ -556,14 +738,17 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command)
case 0x08: /* SCARD_END_TRANSACTION */ case 0x08: /* SCARD_END_TRANSACTION */
LLOGLN(0, ("scard_process_msg: SCARD_END_TRANSACTION")); LLOGLN(0, ("scard_process_msg: SCARD_END_TRANSACTION"));
rv = scard_process_end_transaction(con, in_s);
break; break;
case 0x09: /* SCARD_TRANSMIT */ case 0x09: /* SCARD_TRANSMIT */
LLOGLN(0, ("scard_process_msg: SCARD_TRANSMIT")); LLOGLN(0, ("scard_process_msg: SCARD_TRANSMIT"));
rv = scard_process_transmit(con, in_s);
break; break;
case 0x0A: /* SCARD_CONTROL */ case 0x0A: /* SCARD_CONTROL */
LLOGLN(0, ("scard_process_msg: SCARD_CONTROL")); LLOGLN(0, ("scard_process_msg: SCARD_CONTROL"));
rv = scard_process_control(con, in_s);
break; break;
case 0x0B: /* SCARD_STATUS */ case 0x0B: /* SCARD_STATUS */

@ -44,5 +44,8 @@ int APP_CC scard_function_get_status_change_return(struct trans *con,
int APP_CC scard_function_connect_return(struct trans *con, int APP_CC scard_function_connect_return(struct trans *con,
struct stream *in_s, struct stream *in_s,
int len); int len);
int APP_CC scard_function_begin_transaction_return(struct trans *con,
struct stream *in_s,
int len);
#endif /* end #ifndef _SMARTCARD_PCSC_H */ #endif /* end #ifndef _SMARTCARD_PCSC_H */

Loading…
Cancel
Save