From 9263b22cb295ae5eefa3bf25e35873b718966325 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 19 Sep 2013 01:03:20 -0700 Subject: [PATCH] chansrv: work on smartcard --- sesman/chansrv/pcsc/xrdp_pcsc.c | 107 +++++++++++++++++++++++--------- sesman/chansrv/smartcard.c | 16 ++--- sesman/chansrv/smartcard.h | 19 +++--- sesman/chansrv/smartcard_pcsc.c | 38 ++++++++++-- 4 files changed, 128 insertions(+), 52 deletions(-) diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 251fdd82..520c9971 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -55,6 +55,7 @@ typedef struct _SCARD_IO_REQUEST #define SCARD_ESTABLISH_CONTEXT 0x01 #define SCARD_RELEASE_CONTEXT 0x02 #define SCARD_LIST_READERS 0x03 +#define SCARD_CONNECT 0x04 #define SCARD_GET_STATUS_CHANGE 0x0C #define SCARD_S_SUCCESS 0x00000000 @@ -79,6 +80,9 @@ static int g_sck = -1; /* unix domain socket */ static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +/* for pcsc_stringify_error */ +static char g_error_str[512]; + /*****************************************************************************/ static int get_display_num_from_display(const char *display_text) @@ -152,6 +156,11 @@ connect_to_chansrv(void) struct sockaddr_un saddr; struct sockaddr *psaddr; + if (g_sck != -1) + { + /* already connected */ + return 0; + } xrdp_session = getenv("XRDP_SESSION"); if (xrdp_session == NULL) { @@ -180,34 +189,31 @@ connect_to_chansrv(void) LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis)); return 1; } + g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); if (g_sck == -1) { - g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); - if (g_sck == -1) - { - LLOGLN(0, ("connect_to_chansrv: error, socket failed")); - return 1; - } - memset(&saddr, 0, sizeof(struct sockaddr_un)); - saddr.sun_family = AF_UNIX; - bytes = sizeof(saddr.sun_path); - snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); - saddr.sun_path[bytes - 1] = 0; - LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); - psaddr = (struct sockaddr *) &saddr; - bytes = sizeof(struct sockaddr_un); - error = connect(g_sck, psaddr, bytes); - if (error == 0) - { - } - else - { - perror("connect_to_chansrv"); - close(g_sck); - g_sck = -1; - LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path)); - return 1; - } + LLOGLN(0, ("connect_to_chansrv: error, socket failed")); + return 1; + } + memset(&saddr, 0, sizeof(struct sockaddr_un)); + saddr.sun_family = AF_UNIX; + bytes = sizeof(saddr.sun_path); + snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); + saddr.sun_path[bytes - 1] = 0; + LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); + psaddr = (struct sockaddr *) &saddr; + bytes = sizeof(struct sockaddr_un); + error = connect(g_sck, psaddr, bytes); + if (error == 0) + { + } + else + { + perror("connect_to_chansrv"); + close(g_sck); + g_sck = -1; + LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path)); + return 1; } return 0; } @@ -369,6 +375,12 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { + char msg[256]; + int code; + int bytes; + int status; + int offset; + LLOGLN(0, ("SCardConnect:")); if (g_sck == -1) { @@ -376,8 +388,47 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, return SCARD_F_INTERNAL_ERROR; } pthread_mutex_lock(&g_mutex); + offset = 0; + SET_UINT32(msg, offset, hContext); + offset += 4; + bytes = strlen(szReader); + if (bytes > 99) + { + LLOGLN(0, ("SCardConnect: error, name too long")); + return SCARD_F_INTERNAL_ERROR; + } + memcpy(msg + offset, szReader, bytes); + memset(msg + bytes, 0, 100 - bytes); + offset += 100; + SET_UINT32(msg, offset, dwShareMode); + offset += 4; + SET_UINT32(msg, offset, dwPreferredProtocols); + offset += 4; + if (send_message(SCARD_CONNECT, msg, offset) != 0) + { + LLOGLN(0, ("SCardConnect: error, send_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardConnect: error, get_message")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } + if (code != SCARD_RELEASE_CONTEXT) + { + LLOGLN(0, ("SCardConnect: error, bad code")); + pthread_mutex_unlock(&g_mutex); + return SCARD_F_INTERNAL_ERROR; + } pthread_mutex_unlock(&g_mutex); - return SCARD_S_SUCCESS; + *phCard = GET_UINT32(msg, 0); + *pdwActiveProtocol = GET_UINT32(msg, 4); + status = GET_UINT32(msg, 8); + LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ @@ -746,8 +797,6 @@ SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, return SCARD_S_SUCCESS; } -static char g_error_str[512]; - /*****************************************************************************/ char * pcsc_stringify_error(const long code) diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index b97ffca6..94c08ad4 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -285,7 +285,7 @@ scard_deinit(void) * *****************************************************************************/ int APP_CC -scard_send_irp_establish_context(struct trans *con, int scope) +scard_send_establish_context(struct trans *con, int scope) { IRP *irp; @@ -312,7 +312,7 @@ scard_send_irp_establish_context(struct trans *con, int scope) * Release a previously established Smart Card context *****************************************************************************/ int APP_CC -scard_send_irp_release_context(struct trans *con, tui32 context) +scard_send_release_context(struct trans *con, tui32 context) { IRP *irp; @@ -339,7 +339,7 @@ scard_send_irp_release_context(struct trans *con, tui32 context) * *****************************************************************************/ int APP_CC -scard_send_irp_list_readers(struct trans *con, tui32 context, int wide) +scard_send_list_readers(struct trans *con, tui32 context, int wide) { IRP *irp; @@ -371,9 +371,9 @@ scard_send_irp_list_readers(struct trans *con, tui32 context, int wide) * @param rsa array of READER_STATEs *****************************************************************************/ int APP_CC -scard_send_irp_get_status_change(struct trans *con, tui32 context, int wide, - tui32 timeout, tui32 num_readers, - READER_STATE* rsa) +scard_send_get_status_change(struct trans *con, tui32 context, int wide, + tui32 timeout, tui32 num_readers, + READER_STATE* rsa) { IRP *irp; @@ -403,8 +403,8 @@ scard_send_irp_get_status_change(struct trans *con, tui32 context, int wide, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_irp_connect(struct trans *con, tui32 context, int wide, - READER_STATE* rs) +scard_send_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs) { IRP *irp; diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 44d4fcbc..c763db31 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -73,17 +73,14 @@ int APP_CC scard_get_wait_objs(tbus *objs, int *count, int *timeout); int APP_CC scard_check_wait_objs(void); int APP_CC scard_init(void); int APP_CC scard_deinit(void); -int APP_CC scard_send_irp_establish_context(struct trans *con, int scope); -int APP_CC scard_send_irp_release_context(struct trans *con, tui32 context); -int APP_CC scard_send_irp_list_readers(struct trans *con, tui32 context, int wide); - -int APP_CC scard_send_irp_get_status_change(struct trans *con, tui32 context, - int wide, tui32 timeout, - tui32 num_readers, READER_STATE* rsa); - -int APP_CC scard_send_irp_connect(struct trans *con, tui32 context, int wide, - READER_STATE* rs); - +int APP_CC scard_send_establish_context(struct trans *con, int scope); +int APP_CC scard_send_release_context(struct trans *con, tui32 context); +int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide); +int APP_CC scard_send_get_status_change(struct trans *con, tui32 context, + int wide, tui32 timeout, + tui32 num_readers, READER_STATE* rsa); +int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide, + READER_STATE* rs); 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_status(struct trans *con, int wide, tui32 sc_handle); diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index ded872cb..7af1871c 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -55,6 +55,7 @@ #define XRDP_PCSC_STATE_GOT_LR (1 << 1) /* list readers */ #define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */ #define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */ +#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */ /* TODO: put this in con */ static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; @@ -123,7 +124,7 @@ scard_process_establish_context(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC; in_uint32_le(in_s, dwScope); LLOGLN(0, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope)); - scard_send_irp_establish_context(con, dwScope); + scard_send_establish_context(con, dwScope); return 0; } @@ -183,7 +184,7 @@ scard_process_release_context(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC; in_uint32_le(in_s, hContext); LLOGLN(0, ("scard_process_release_context: hContext 0x%8.8x", hContext)); - scard_send_irp_release_context(con, hContext); + scard_send_release_context(con, hContext); return 0; } @@ -232,7 +233,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; in_uint32_le(in_s, hContext); LLOGLN(0, ("scard_process_list_readers: dwScope 0x%8.8x", hContext)); - scard_send_irp_list_readers(con, hContext, 1); + scard_send_list_readers(con, hContext, 1); return 0; } @@ -318,6 +319,34 @@ scard_function_list_readers_return(struct trans *con, return trans_force_write(con); } +/*****************************************************************************/ +/* returns error */ +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:")); + if (g_xrdp_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; + in_uint32_le(in_s, hContext); + in_uint8a(in_s, szReader, 100); + in_uint32_le(in_s, rs.shared_mode_flag); + in_uint32_le(in_s, rs.preferred_protocol); + LLOGLN(0, ("scard_process_connect: dwShareMode 0x%8.8x " + "dwPreferredProtocols 0x%8.8x", rs.shared_mode_flag, + rs.preferred_protocol)); + scard_send_connect(con, hContext, 1, &rs); + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -367,7 +396,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC; - scard_send_irp_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); + scard_send_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa); g_free(rsa); @@ -453,6 +482,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) case 0x04: /* SCARD_CONNECT */ LLOGLN(0, ("scard_process_msg: SCARD_CONNECT")); + rv = scard_process_connect(con, in_s); break; case 0x05: /* SCARD_RECONNECT */