diff --git a/common/parse.h b/common/parse.h index 226e246b..f92e76de 100644 --- a/common/parse.h +++ b/common/parse.h @@ -183,6 +183,31 @@ struct stream } while (0) #endif +/******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define in_uint64_le(s, v) do \ +{ \ + (v) = (tui64) \ + ( \ + (((tui64)(*((unsigned char*)((s)->p + 0)))) << 0) | \ + (((tui64)(*((unsigned char*)((s)->p + 1)))) << 8) | \ + (((tui64)(*((unsigned char*)((s)->p + 2)))) << 16) | \ + (((tui64)(*((unsigned char*)((s)->p + 3)))) << 24) | \ + (((tui64)(*((unsigned char*)((s)->p + 4)))) << 32) | \ + (((tui64)(*((unsigned char*)((s)->p + 5)))) << 40) | \ + (((tui64)(*((unsigned char*)((s)->p + 6)))) << 48) | \ + (((tui64)(*((unsigned char*)((s)->p + 7)))) << 56) \ + ); \ + (s)->p += 8; \ +} while (0) +#else +#define in_uint64_le(s, v) do \ +{ \ + (v) = *((tui64*)((s)->p)); \ + (s)->p += 8; \ +} while (0) +#endif + /******************************************************************************/ #define in_uint32_be(s, v) do \ { \ diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 89753430..7cecdb1e 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -46,6 +46,7 @@ xrdp_chansrv_SOURCES = \ clipboard_file.c \ devredir.c \ smartcard.c \ + smartcard_pcsc.c \ rail.c \ xcommon.c \ drdynvc.c \ diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index f254fa89..57d877df 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -120,13 +120,15 @@ dev_redir_init(void) /* get a random number that will act as a unique clientID */ if ((fd = open("/dev/urandom", O_RDONLY))) { - read(fd, u.buf, 4); + if (read(fd, u.buf, 4) != 4) + { + } close(fd); } else { /* /dev/urandom did not work - use address of struct s */ - tui64 u64 = (tui64) &s; + tui64 u64 = (tui64) (tintptr) &s; u.clientID = (tui32) u64; } @@ -152,6 +154,7 @@ dev_redir_init(void) int APP_CC dev_redir_deinit(void) { + scard_deinit(); return 0; } @@ -282,6 +285,10 @@ done: int APP_CC dev_redir_get_wait_objs(tbus *objs, int *count, int *timeout) { + if (g_is_smartcard_redir_supported) + { + return scard_get_wait_objs(objs, count, timeout); + } return 0; } @@ -289,6 +296,10 @@ dev_redir_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC dev_redir_check_wait_objs(void) { + if (g_is_smartcard_redir_supported) + { + return scard_check_wait_objs(); + } return 0; } @@ -619,6 +630,7 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s) case CAP_SMARTCARD_TYPE: log_debug("got CAP_SMARTCARD_TYPE"); g_is_smartcard_redir_supported = 1; + scard_init(); xstream_seek(s, cap_len); break; } diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index d1052b9c..c370479e 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -26,6 +26,7 @@ #include "log.h" #include "irp.h" #include "devredir.h" +#include "smartcard_pcsc.h" /* * TODO @@ -536,3 +537,37 @@ scard_release_resources(void) /** * *****************************************************************************/ +int APP_CC +scard_get_wait_objs(tbus *objs, int *count, int *timeout) +{ + return scard_pcsc_get_wait_objs(objs, count, timeout); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_check_wait_objs(void) +{ + return scard_pcsc_check_wait_objs(); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_init(void) +{ + log_debug("init") + return scard_pcsc_init(); +} + +/** + * + *****************************************************************************/ +int APP_CC +scard_deinit(void) +{ + log_debug("deinit") + return scard_pcsc_deinit(); +} diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 88f31369..a85b9f5f 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -39,4 +39,13 @@ void scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus); +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); + #endif /* end #ifndef _SMARTCARD_C */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c new file mode 100644 index 00000000..5312ec5f --- /dev/null +++ b/sesman/chansrv/smartcard_pcsc.c @@ -0,0 +1,294 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * smartcard redirection support, PCSC daemon standin + * this will act like pcsc daemon + */ + +#define PCSC_STANDIN 1 + +#include "os_calls.h" +#include "smartcard.h" +#include "log.h" +#include "irp.h" +#include "devredir.h" +#include "trans.h" + +#if PCSC_STANDIN + +#define LLOG_LEVEL 11 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("chansrv:smartcard [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + +#define PCSCLITE_MSG_KEY_LEN 16 +#define PCSCLITE_MAX_MESSAGE_SIZE 2048 + +struct version_struct +{ + tsi32 major; /**< IPC major \ref PROTOCOL_VERSION_MAJOR */ + tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */ + tui32 rv; +}; +typedef struct version_struct version_struct; + +struct rxSharedSegment +{ + tui32 mtype; /** one of the \c pcsc_adm_commands */ + tui32 user_id; + tui32 group_id; + tui32 command; /** one of the \c pcsc_msg_commands */ + tui64 date; + tui8 key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */ + union _u + { + tui8 data[PCSCLITE_MAX_MESSAGE_SIZE]; + struct version_struct veStr; + } u; +}; +typedef struct rxSharedSegment sharedSegmentMsg, *psharedSegmentMsg; + +#define RXSHAREDSEGMENT_BYTES 2088 + +extern int g_display_num; /* in chansrv.c */ + +/*****************************************************************************/ +struct pcsc_client +{ + struct trans *con; +}; + +static struct pcsc_client *g_head = 0; +static struct pcsc_client *g_tail = 0; + +static struct trans *g_lis = 0; +static struct trans *g_con = 0; /* todo, remove this */ + +static char g_pcsc_directory[256] = ""; + +/*****************************************************************************/ +int APP_CC +scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) +{ + LLOGLN(0, ("scard_pcsc_get_wait_objs")); + if (g_lis != 0) + { + trans_get_wait_objs(g_lis, objs, count); + } + if (g_con != 0) + { + trans_get_wait_objs(g_con, objs, count); + } + return 0; +} + +/*****************************************************************************/ +int APP_CC +scard_pcsc_check_wait_objs(void) +{ + LLOGLN(0, ("scard_pcsc_check_wait_objs")); + if (g_lis != 0) + { + trans_check_wait_objs(g_lis); + } + if (g_con != 0) + { + trans_check_wait_objs(g_con); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_version(psharedSegmentMsg msg) +{ + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_msg(struct stream *s) +{ + sharedSegmentMsg msg; + int rv; + + g_memset(&msg, 0, sizeof(msg)); + in_uint32_le(s, msg.mtype); + in_uint32_le(s, msg.user_id); + in_uint32_le(s, msg.group_id); + in_uint32_le(s, msg.command); + in_uint64_le(s, msg.date); + LLOGLN(0, ("scard_process_msg: mtype 0x%2.2x command 0x%2.2x", + msg.mtype, msg.command)); + rv = 0; + switch (msg.mtype) + { + case 0xF8: /* CMD_VERSION */ + rv = scard_process_version(&msg); + break; + } + return rv; +} + +/*****************************************************************************/ +/* returns error */ +int DEFAULT_CC +my_pcsc_trans_data_in(struct trans *trans) +{ + struct stream *s; + int id; + int size; + int error; + + LLOGLN(0, ("my_pcsc_trans_data_in:")); + if (trans == 0) + { + return 0; + } + + if (trans != g_con) + { + return 1; + } + s = trans_get_in_s(trans); + g_hexdump(s->p, 64); + error = scard_process_msg(s); + return error; +} + +/*****************************************************************************/ +/* got a new connection from libpcsclite */ +int DEFAULT_CC +my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) +{ + LLOGLN(0, ("my_pcsc_trans_conn_in:")); + + if (trans == 0) + { + return 1; + } + + if (trans != g_lis) + { + return 1; + } + + if (new_trans == 0) + { + return 1; + } + + g_con = new_trans; + g_con->trans_data_in = my_pcsc_trans_data_in; + g_con->header_size = RXSHAREDSEGMENT_BYTES; + LLOGLN(0, ("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d", + sizeof(sharedSegmentMsg))); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +scard_pcsc_init(void) +{ + char port[256]; + int error; + + LLOGLN(0, ("scard_pcsc_init:")); + if (g_lis == 0) + { + g_lis = trans_create(2, 8192, 8192); + g_snprintf(g_pcsc_directory, 255, "/tmp/.xrdp/pcsc%d", g_display_num); + if (g_directory_exist(g_pcsc_directory)) + { + if (g_remove_dir(g_pcsc_directory) != 0) + { + LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed")); + } + } + if (g_create_dir(g_pcsc_directory) != 0) + { + LLOGLN(0, ("scard_pcsc_init: g_create_dir failed")); + } + g_chmod_hex(g_pcsc_directory, 0x1777); + g_snprintf(port, 255, "%s/pcscd.comm", g_pcsc_directory); + g_lis->trans_conn_in = my_pcsc_trans_conn_in; + error = trans_listen(g_lis, port); + if (error != 0) + { + LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s", + port)); + return 1; + } + } + return 0; +} + +/*****************************************************************************/ +int APP_CC +scard_pcsc_deinit(void) +{ + LLOGLN(0, ("scard_pcsc_deinit:")); + if (g_lis != 0) + { + trans_delete(g_lis); + g_lis = 0; + if (g_remove_dir(g_pcsc_directory) != 0) + { + LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed")); + } + g_pcsc_directory[0] = 0; + } + return 0; +} + +#else + +int APP_CC +scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) +{ + return 0; +} +int APP_CC +scard_pcsc_check_wait_objs(void) +{ + return 0; +} +int APP_CC +scard_pcsc_init(void) +{ + return 0; +} +int APP_CC +scard_pcsc_deinit(void) +{ + return 0; +} + +#endif diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h new file mode 100644 index 00000000..a97a70d3 --- /dev/null +++ b/sesman/chansrv/smartcard_pcsc.h @@ -0,0 +1,36 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * smartcard redirection support, PCSC daemon standin + */ + +#ifndef _SMARTCARD_PCSC_H +#define _SMARTCARD_PCSC_H + +int APP_CC +scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout); +int APP_CC +scard_pcsc_check_wait_objs(void); +int APP_CC +scard_pcsc_init(void); +int APP_CC +scard_pcsc_deinit(void); + +#endif /* end #ifndef _SMARTCARD_PCSC_H */