From c9a2039858e923cc2b7c29ee51de2dfefad9ac2a Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:55:49 +0100 Subject: [PATCH] Move and rename xrdp_load_keyboard_layout() xrdp_load_keyboard_layout() is used exclusively by the xup module to work out the parameters to pass to xorgxrdp for XKB. This function does not need to be called locally from the SEC module. This commit moves the function to xrdp/lang.c and renames it as xrdp_init_xkb_layout(). The module interface is modified so that xup can call this function. Other modules do not need to call it. --- libxrdp/xrdp_sec.c | 241 --------------------------------- mc/mc.h | 5 +- neutrinordp/xrdp-neutrinordp.h | 4 +- vnc/vnc.h | 5 +- xrdp/lang.c | 240 ++++++++++++++++++++++++++++++++ xrdp/xrdp.h | 16 +++ xrdp/xrdp_mm.c | 10 ++ xrdp/xrdp_types.h | 4 +- xup/xup.c | 6 + xup/xup.h | 5 +- 10 files changed, 290 insertions(+), 246 deletions(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index fa7900ea..779e4b96 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -155,246 +155,6 @@ hex_str_to_bin(char *in, char *out, int out_len) } } -/*****************************************************************************/ -static void -xrdp_load_keyboard_layout(struct xrdp_client_info *client_info) -{ - int fd; - int index = 0; - int bytes; - struct list *names = (struct list *)NULL; - struct list *items = (struct list *)NULL; - struct list *values = (struct list *)NULL; - char *item = (char *)NULL; - char *value = (char *)NULL; - char *q = (char *)NULL; - char keyboard_cfg_file[256] = { 0 }; - char rdp_layout[256] = { 0 }; - - const struct xrdp_keyboard_overrides *ko = - &client_info->xrdp_keyboard_overrides; - - LOG(LOG_LEVEL_INFO, "xrdp_load_keyboard_layout: Keyboard information sent" - " by the RDP client, keyboard_type:[0x%02X], keyboard_subtype:[0x%02X]," - " keylayout:[0x%08X]", - client_info->keyboard_type, client_info->keyboard_subtype, - client_info->keylayout); - - if (ko->type != -1) - { - LOG(LOG_LEVEL_INFO, "overrode keyboard_type 0x%02X" - " with 0x%02X", client_info->keyboard_type, ko->type); - client_info->keyboard_type = ko->type; - } - if (ko->subtype != -1) - { - LOG(LOG_LEVEL_INFO, "overrode keyboard_subtype 0x%02X" - " with 0x%02X", client_info->keyboard_subtype, - ko->subtype); - client_info->keyboard_subtype = ko->subtype; - } - if (ko->layout != -1) - { - LOG(LOG_LEVEL_INFO, "overrode keylayout 0x%08X" - " with 0x%08X", client_info->keylayout, ko->layout); - client_info->keylayout = ko->layout; - } - /* infer model/variant */ - /* TODO specify different X11 keyboard models/variants */ - g_memset(client_info->model, 0, sizeof(client_info->model)); - g_memset(client_info->variant, 0, sizeof(client_info->variant)); - g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1); - if (client_info->keyboard_subtype == 3) - { - /* macintosh keyboard */ - bytes = sizeof(client_info->variant); - g_strncpy(client_info->variant, "mac", bytes - 1); - } - else if (client_info->keyboard_subtype == 0) - { - /* default - standard subtype */ - client_info->keyboard_subtype = 1; - } - - g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH); - LOG(LOG_LEVEL_DEBUG, "keyboard_cfg_file %s", keyboard_cfg_file); - - fd = g_file_open_ro(keyboard_cfg_file); - - if (fd >= 0) - { - int section_found = -1; - char section_rdp_layouts[256] = { 0 }; - char section_layouts_map[256] = { 0 }; - - names = list_create(); - names->auto_free = 1; - items = list_create(); - items->auto_free = 1; - values = list_create(); - values->auto_free = 1; - - file_read_sections(fd, names); - for (index = 0; index < names->count; index++) - { - q = (char *)list_get_item(names, index); - if (g_strncasecmp("default", q, 8) != 0) - { - int i; - - file_read_section(fd, q, items, values); - - for (i = 0; i < items->count; i++) - { - item = (char *)list_get_item(items, i); - value = (char *)list_get_item(values, i); - LOG(LOG_LEVEL_DEBUG, "xrdp_load_keyboard_layout: item %s value %s", - item, value); - if (g_strcasecmp(item, "keyboard_type") == 0) - { - int v = g_atoi(value); - if (v == client_info->keyboard_type) - { - section_found = index; - } - } - else if (g_strcasecmp(item, "keyboard_subtype") == 0) - { - int v = g_atoi(value); - if (v != client_info->keyboard_subtype && - section_found == index) - { - section_found = -1; - break; - } - } - else if (g_strcasecmp(item, "rdp_layouts") == 0) - { - if (section_found != -1 && section_found == index) - { - g_strncpy(section_rdp_layouts, value, 255); - } - } - else if (g_strcasecmp(item, "layouts_map") == 0) - { - if (section_found != -1 && section_found == index) - { - g_strncpy(section_layouts_map, value, 255); - } - } - else if (g_strcasecmp(item, "model") == 0) - { - if (section_found != -1 && section_found == index) - { - bytes = sizeof(client_info->model); - g_memset(client_info->model, 0, bytes); - g_strncpy(client_info->model, value, bytes - 1); - } - } - else if (g_strcasecmp(item, "variant") == 0) - { - if (section_found != -1 && section_found == index) - { - bytes = sizeof(client_info->variant); - g_memset(client_info->variant, 0, bytes); - g_strncpy(client_info->variant, value, bytes - 1); - } - } - else if (g_strcasecmp(item, "options") == 0) - { - if (section_found != -1 && section_found == index) - { - bytes = sizeof(client_info->options); - g_memset(client_info->options, 0, bytes); - g_strncpy(client_info->options, value, bytes - 1); - } - } - else - { - /* - * mixing items from different sections will result in - * skipping over current section. - */ - LOG(LOG_LEVEL_DEBUG, "xrdp_load_keyboard_layout: skipping " - "configuration item - %s, continuing to next " - "section", item); - break; - } - } - - list_clear(items); - list_clear(values); - } - } - - if (section_found == -1) - { - g_memset(section_rdp_layouts, 0, sizeof(char) * 256); - g_memset(section_layouts_map, 0, sizeof(char) * 256); - // read default section - file_read_section(fd, "default", items, values); - for (index = 0; index < items->count; index++) - { - item = (char *)list_get_item(items, index); - value = (char *)list_get_item(values, index); - if (g_strcasecmp(item, "rdp_layouts") == 0) - { - g_strncpy(section_rdp_layouts, value, 255); - } - else if (g_strcasecmp(item, "layouts_map") == 0) - { - g_strncpy(section_layouts_map, value, 255); - } - } - list_clear(items); - list_clear(values); - } - - /* load the map */ - file_read_section(fd, section_rdp_layouts, items, values); - for (index = 0; index < items->count; index++) - { - int rdp_layout_id; - item = (char *)list_get_item(items, index); - value = (char *)list_get_item(values, index); - rdp_layout_id = g_htoi(value); - if (rdp_layout_id == client_info->keylayout) - { - g_strncpy(rdp_layout, item, 255); - break; - } - } - list_clear(items); - list_clear(values); - file_read_section(fd, section_layouts_map, items, values); - for (index = 0; index < items->count; index++) - { - item = (char *)list_get_item(items, index); - value = (char *)list_get_item(values, index); - if (g_strcasecmp(item, rdp_layout) == 0) - { - bytes = sizeof(client_info->layout); - g_strncpy(client_info->layout, value, bytes - 1); - break; - } - } - - list_delete(names); - list_delete(items); - list_delete(values); - - LOG(LOG_LEVEL_INFO, "xrdp_load_keyboard_layout: model [%s] variant [%s] " - "layout [%s] options [%s]", client_info->model, - client_info->variant, client_info->layout, client_info->options); - g_file_close(fd); - } - else - { - LOG(LOG_LEVEL_ERROR, "xrdp_load_keyboard_layout: error opening %s", - keyboard_cfg_file); - } -} - /*****************************************************************************/ struct xrdp_sec * xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) @@ -2496,7 +2256,6 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) client_info->keyboard_type, client_info->keyboard_subtype); - xrdp_load_keyboard_layout(client_info); s->p = s->data; return 0; diff --git a/mc/mc.h b/mc/mc.h index 6aaf441d..f15e3f9a 100644 --- a/mc/mc.h +++ b/mc/mc.h @@ -30,6 +30,7 @@ #define CURRENT_MOD_VER 3 struct source_info; +struct xrdp_client_info; /* Defined in xrdp_client_info.h */ struct monitor_info; @@ -98,7 +99,9 @@ struct mod int total_data_len, int flags); int (*server_bell_trigger)(struct mod *v); int (*server_chansrv_in_use)(struct mod *v); - tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server + void (*server_init_xkb_layout)(struct mod *v, + struct xrdp_client_info *client_info); + tintptr server_dumby[100 - 29]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as long */ diff --git a/neutrinordp/xrdp-neutrinordp.h b/neutrinordp/xrdp-neutrinordp.h index d5dc78a2..a616dca3 100644 --- a/neutrinordp/xrdp-neutrinordp.h +++ b/neutrinordp/xrdp-neutrinordp.h @@ -143,6 +143,8 @@ struct mod int total_data_len, int flags); int (*server_bell_trigger)(struct mod *v); int (*server_chansrv_in_use)(struct mod *v); + void (*server_init_xkb_layout)(struct mod *v, + struct xrdp_client_info *client_info); /* off screen bitmaps */ int (*server_create_os_surface)(struct mod *v, int rdpindex, int width, int height); @@ -197,7 +199,7 @@ struct mod int flags, int frame_id); int (*server_session_info)(struct mod *v, const char *data, int data_bytes); - tintptr server_dumby[100 - 47]; /* align, 100 minus the number of server + tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as long */ diff --git a/vnc/vnc.h b/vnc/vnc.h index 85e943f7..a69c2690 100644 --- a/vnc/vnc.h +++ b/vnc/vnc.h @@ -69,6 +69,7 @@ enum vnc_resize_support_status }; struct source_info; +struct xrdp_client_info; /* Defined in vnc_clip.c */ struct vnc_clipboard_data; @@ -151,7 +152,9 @@ struct vnc int total_data_len, int flags); int (*server_bell_trigger)(struct vnc *v); int (*server_chansrv_in_use)(struct vnc *v); - tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server + void (*server_init_xkb_layout)(struct vnc *v, + struct xrdp_client_info *client_info); + tintptr server_dumby[100 - 29]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as long */ diff --git a/xrdp/lang.c b/xrdp/lang.c index 6a3f8acc..e36f688e 100644 --- a/xrdp/lang.c +++ b/xrdp/lang.c @@ -414,3 +414,243 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap) return rv; } + +/*****************************************************************************/ +void +xrdp_init_xkb_layout(struct xrdp_client_info *client_info) +{ + int fd; + int index = 0; + int bytes; + struct list *names = (struct list *)NULL; + struct list *items = (struct list *)NULL; + struct list *values = (struct list *)NULL; + char *item = (char *)NULL; + char *value = (char *)NULL; + char *q = (char *)NULL; + char keyboard_cfg_file[256] = { 0 }; + char rdp_layout[256] = { 0 }; + + const struct xrdp_keyboard_overrides *ko = + &client_info->xrdp_keyboard_overrides; + + LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: Keyboard information sent" + " by the RDP client, keyboard_type:[0x%02X], keyboard_subtype:[0x%02X]," + " keylayout:[0x%08X]", + client_info->keyboard_type, client_info->keyboard_subtype, + client_info->keylayout); + + if (ko->type != -1) + { + LOG(LOG_LEVEL_INFO, "overrode keyboard_type 0x%02X" + " with 0x%02X", client_info->keyboard_type, ko->type); + client_info->keyboard_type = ko->type; + } + if (ko->subtype != -1) + { + LOG(LOG_LEVEL_INFO, "overrode keyboard_subtype 0x%02X" + " with 0x%02X", client_info->keyboard_subtype, + ko->subtype); + client_info->keyboard_subtype = ko->subtype; + } + if (ko->layout != -1) + { + LOG(LOG_LEVEL_INFO, "overrode keylayout 0x%08X" + " with 0x%08X", client_info->keylayout, ko->layout); + client_info->keylayout = ko->layout; + } + /* infer model/variant */ + /* TODO specify different X11 keyboard models/variants */ + g_memset(client_info->model, 0, sizeof(client_info->model)); + g_memset(client_info->variant, 0, sizeof(client_info->variant)); + g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1); + if (client_info->keyboard_subtype == 3) + { + /* macintosh keyboard */ + bytes = sizeof(client_info->variant); + g_strncpy(client_info->variant, "mac", bytes - 1); + } + else if (client_info->keyboard_subtype == 0) + { + /* default - standard subtype */ + client_info->keyboard_subtype = 1; + } + + g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH); + LOG(LOG_LEVEL_DEBUG, "keyboard_cfg_file %s", keyboard_cfg_file); + + fd = g_file_open_ro(keyboard_cfg_file); + + if (fd >= 0) + { + int section_found = -1; + char section_rdp_layouts[256] = { 0 }; + char section_layouts_map[256] = { 0 }; + + names = list_create(); + names->auto_free = 1; + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + + file_read_sections(fd, names); + for (index = 0; index < names->count; index++) + { + q = (char *)list_get_item(names, index); + if (g_strncasecmp("default", q, 8) != 0) + { + int i; + + file_read_section(fd, q, items, values); + + for (i = 0; i < items->count; i++) + { + item = (char *)list_get_item(items, i); + value = (char *)list_get_item(values, i); + LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: item %s value %s", + item, value); + if (g_strcasecmp(item, "keyboard_type") == 0) + { + int v = g_atoi(value); + if (v == client_info->keyboard_type) + { + section_found = index; + } + } + else if (g_strcasecmp(item, "keyboard_subtype") == 0) + { + int v = g_atoi(value); + if (v != client_info->keyboard_subtype && + section_found == index) + { + section_found = -1; + break; + } + } + else if (g_strcasecmp(item, "rdp_layouts") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_rdp_layouts, value, 255); + } + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_layouts_map, value, 255); + } + } + else if (g_strcasecmp(item, "model") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->model); + g_memset(client_info->model, 0, bytes); + g_strncpy(client_info->model, value, bytes - 1); + } + } + else if (g_strcasecmp(item, "variant") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->variant); + g_memset(client_info->variant, 0, bytes); + g_strncpy(client_info->variant, value, bytes - 1); + } + } + else if (g_strcasecmp(item, "options") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->options); + g_memset(client_info->options, 0, bytes); + g_strncpy(client_info->options, value, bytes - 1); + } + } + else + { + /* + * mixing items from different sections will result in + * skipping over current section. + */ + LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: skipping " + "configuration item - %s, continuing to next " + "section", item); + break; + } + } + + list_clear(items); + list_clear(values); + } + } + + if (section_found == -1) + { + g_memset(section_rdp_layouts, 0, sizeof(char) * 256); + g_memset(section_layouts_map, 0, sizeof(char) * 256); + // read default section + file_read_section(fd, "default", items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, "rdp_layouts") == 0) + { + g_strncpy(section_rdp_layouts, value, 255); + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + g_strncpy(section_layouts_map, value, 255); + } + } + list_clear(items); + list_clear(values); + } + + /* load the map */ + file_read_section(fd, section_rdp_layouts, items, values); + for (index = 0; index < items->count; index++) + { + int rdp_layout_id; + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + rdp_layout_id = g_htoi(value); + if (rdp_layout_id == client_info->keylayout) + { + g_strncpy(rdp_layout, item, 255); + break; + } + } + list_clear(items); + list_clear(values); + file_read_section(fd, section_layouts_map, items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, rdp_layout) == 0) + { + bytes = sizeof(client_info->layout); + g_strncpy(client_info->layout, value, bytes - 1); + break; + } + } + + list_delete(names); + list_delete(items); + list_delete(values); + + LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: model [%s] variant [%s] " + "layout [%s] options [%s]", client_info->model, + client_info->variant, client_info->layout, client_info->options); + g_file_close(fd); + } + else + { + LOG(LOG_LEVEL_ERROR, "xrdp_init_xkb_layout: error opening %s", + keyboard_cfg_file); + } +} diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 8ae54b9a..32286f9b 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -447,6 +447,19 @@ get_keymaps(int keylayout, struct xrdp_keymap *keymap); int km_load_file(const char *filename, struct xrdp_keymap *keymap); +/** + * initialise the XKB layout + * + * Not all backends need to use XKB for keyboard mapping. This + * call is used by those modules that do need an XKB mapping. + * + * Other modules and the login screen use other routines in + * lang.c to interpret incoming RDP scancodes + * @param client_info Client info struct to initialise + */ +void +xrdp_init_xkb_layout(struct xrdp_client_info *client_info); + /* xrdp_login_wnd.c */ /** * Gets the DPI of the login (primary) monitor @@ -528,6 +541,9 @@ int server_bell_trigger(struct xrdp_mod *mod); int server_chansrv_in_use(struct xrdp_mod *mod); +void +server_init_xkb_layout(struct xrdp_mod *mod, + struct xrdp_client_info *client_info); int server_fill_rect(struct xrdp_mod *mod, int x, int y, int cx, int cy); int diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 01acc608..4a4ea6cd 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -384,6 +384,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self) self->mod->server_end_update = server_end_update; self->mod->server_bell_trigger = server_bell_trigger; self->mod->server_chansrv_in_use = server_chansrv_in_use; + self->mod->server_init_xkb_layout = server_init_xkb_layout; self->mod->server_fill_rect = server_fill_rect; self->mod->server_screen_blt = server_screen_blt; self->mod->server_paint_rect = server_paint_rect; @@ -3986,6 +3987,15 @@ server_chansrv_in_use(struct xrdp_mod *mod) return wm->mm->use_chansrv; } +/*****************************************************************************/ +/* Init the XKB layout */ +void +server_init_xkb_layout(struct xrdp_mod *mod, + struct xrdp_client_info *client_info) +{ + xrdp_init_xkb_layout(client_info); +} + /*****************************************************************************/ int diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index f49d78e6..8bb8cfaf 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -124,6 +124,8 @@ struct xrdp_mod int total_data_len, int flags); int (*server_bell_trigger)(struct xrdp_mod *v); int (*server_chansrv_in_use)(struct xrdp_mod *v); + void (*server_init_xkb_layout)(struct xrdp_mod *v, + struct xrdp_client_info *client_info); /* off screen bitmaps */ int (*server_create_os_surface)(struct xrdp_mod *v, int rdpindex, int width, int height); @@ -192,7 +194,7 @@ struct xrdp_mod int (*server_egfx_cmd)(struct xrdp_mod *v, char *cmd, int cmd_bytes, char *data, int data_bytes); - tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server + tintptr server_dumby[100 - 51]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as int */ diff --git a/xup/xup.c b/xup/xup.c index 317ddeaf..645eaa52 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -171,6 +171,12 @@ lib_mod_connect(struct mod *mod) return 1; } + // This is a good place to finalise any parameters that need to + // be set. + // + // Load the XKB layout + mod->server_init_xkb_layout(mod, &(mod->client_info)); + make_stream(s); g_sprintf(con_port, "%s", mod->port); diff --git a/xup/xup.h b/xup/xup.h index 3b95124d..05f747e7 100644 --- a/xup/xup.h +++ b/xup/xup.h @@ -34,6 +34,7 @@ #define CURRENT_MOD_VER 4 struct source_info; +struct xrdp_client_info; struct mod { @@ -111,6 +112,8 @@ struct mod int total_data_len, int flags); int (*server_bell_trigger)(struct mod *v); int (*server_chansrv_in_use)(struct mod *v); + void (*server_init_xkb_layout)(struct mod *v, + struct xrdp_client_info *client_info); /* off screen bitmaps */ int (*server_create_os_surface)(struct mod *v, int rdpindex, int width, int height); @@ -176,7 +179,7 @@ struct mod int (*server_egfx_cmd)(struct mod *v, char *cmd, int cmd_bytes, char *data, int data_bytes); - tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server + tintptr server_dumby[100 - 51]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as long */