From 697dcbb24dba5435bde75efc0caa44c2744a9938 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:00:53 +0000 Subject: [PATCH 1/2] Start the drdynvc channel within xrdp_wm The responsibility for starting the drdynvc channel is moved out of libxrdp into the application. This will make it easier to allow the application to check the channel is enabled before starting it. --- libxrdp/libxrdp.c | 17 +++++++++++ libxrdp/libxrdpinc.h | 2 ++ libxrdp/xrdp_channel.c | 69 +++++++++++++++++++++++------------------- libxrdp/xrdp_rdp.c | 1 - xrdp/xrdp_wm.c | 1 + 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index f9009162b..72bcf8457 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -1406,6 +1406,23 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id, return 1; } +/*****************************************************************************/ +int +libxrdp_drdynvc_start(struct xrdp_session *session) +{ + struct xrdp_rdp *rdp; + struct xrdp_sec *sec; + struct xrdp_channel *chan; + + LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_drdynvc_start:"); + + rdp = (struct xrdp_rdp *) (session->rdp); + sec = rdp->sec_layer; + chan = sec->chan_layer; + return xrdp_channel_drdynvc_start(chan); +} + + /*****************************************************************************/ int libxrdp_drdynvc_open(struct xrdp_session *session, const char *name, diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 69de7801a..e026843c3 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -241,6 +241,8 @@ int libxrdp_disable_channel(struct xrdp_session *session, int channel_id, int is_disabled); int +libxrdp_drdynvc_start(struct xrdp_session *session); +int libxrdp_drdynvc_open(struct xrdp_session *session, const char *name, int flags, struct xrdp_drdynvc_procs *procs, int *chan_id); diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index f43804d78..513dd2c8e 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -752,46 +752,53 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self) int xrdp_channel_drdynvc_start(struct xrdp_channel *self) { - int index; - int count; - struct mcs_channel_item *ci; - struct mcs_channel_item *dci; - - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id); + int rv = 0; + LOG_DEVEL(LOG_LEVEL_INFO, + "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", + self->drdynvc_channel_id); if (self->drdynvc_channel_id != -1) { - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started"); - return 0; + LOG_DEVEL(LOG_LEVEL_INFO, + "xrdp_channel_drdynvc_start: already started"); } - dci = NULL; - count = self->mcs_layer->channel_list->count; - for (index = 0; index < count; index++) + else { - ci = (struct mcs_channel_item *) - list_get_item(self->mcs_layer->channel_list, index); - if (ci != NULL) + int index; + int count; + struct mcs_channel_item *ci; + struct mcs_channel_item *dci; + dci = NULL; + count = self->mcs_layer->channel_list->count; + for (index = 0; index < count; index++) { - if (g_strcasecmp(ci->name, "drdynvc") == 0) + ci = (struct mcs_channel_item *) + list_get_item(self->mcs_layer->channel_list, index); + if (ci != NULL) { - dci = ci; + if (g_strcasecmp(ci->name, DRDYNVC_SVC_CHANNEL_NAME) == 0) + { + dci = ci; + break; + } } } + if (dci != NULL) + { + self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1; + LOG_DEVEL(LOG_LEVEL_DEBUG, DRDYNVC_SVC_CHANNEL_NAME + "Initializing Dynamic Virtual Channel with channel id %d", + self->drdynvc_channel_id); + xrdp_channel_drdynvc_send_capability_request(self); + } + else + { + LOG(LOG_LEVEL_WARNING, + "Static channel '%s' not found. " + "Channel not initialized", DRDYNVC_SVC_CHANNEL_NAME); + rv = -1; + } } - if (dci != NULL) - { - self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1; - LOG_DEVEL(LOG_LEVEL_DEBUG, - "Initializing Dynamic Virtual Channel with channel id %d", - self->drdynvc_channel_id); - xrdp_channel_drdynvc_send_capability_request(self); - } - else - { - LOG(LOG_LEVEL_WARNING, - "Dynamic Virtual Channel named 'drdynvc' not found, " - "channel not initialized"); - } - return 0; + return rv; } /*****************************************************************************/ diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 6be1ff6ea..deefd7a1f 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -1323,7 +1323,6 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) self->session->callback(self->session->id, 0x555a, 0, 0, 0, 0); } - xrdp_channel_drdynvc_start(self->sec_layer->chan_layer); } else { diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index fcf59e555..4b1f3bd85 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -2031,6 +2031,7 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2, LOWORD(param3), HIWORD(param3)); case 0x555a: // "yeah, up_and_running" + libxrdp_drdynvc_start(wm->session); xrdp_mm_up_and_running(wm->mm); break; } From 6ff99cc4b5bffdd6c86df7fd943491442e6dc325 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:13:44 +0000 Subject: [PATCH 2/2] Load channel config in xrdp_wm_create() This commit moves the '[Channels]' parsing code for xrdp.ini from xrdp_wm_init() to an earlier location in xrdp_wm_create(). libxrdp can now check that drdynvc is not disabled before starting it, and xrdp_wm can disable GFX if virtual channels are not available. --- libxrdp/xrdp_channel.c | 26 ++++++--- xrdp/xrdp_wm.c | 122 ++++++++++++++++++++++++----------------- 2 files changed, 89 insertions(+), 59 deletions(-) diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 513dd2c8e..c95f6ea7a 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -782,7 +782,19 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self) } } } - if (dci != NULL) + if (dci == NULL) + { + LOG(LOG_LEVEL_WARNING, "Static channel '%s' not found.", + DRDYNVC_SVC_CHANNEL_NAME); + rv = -1; + } + else if (dci->disabled) + { + LOG(LOG_LEVEL_WARNING, "Static channel '%s' is disabled.", + DRDYNVC_SVC_CHANNEL_NAME); + rv = -1; + } + else { self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1; LOG_DEVEL(LOG_LEVEL_DEBUG, DRDYNVC_SVC_CHANNEL_NAME @@ -790,13 +802,11 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self) self->drdynvc_channel_id); xrdp_channel_drdynvc_send_capability_request(self); } - else - { - LOG(LOG_LEVEL_WARNING, - "Static channel '%s' not found. " - "Channel not initialized", DRDYNVC_SVC_CHANNEL_NAME); - rv = -1; - } + } + + if (rv != 0) + { + LOG(LOG_LEVEL_WARNING, "Dynamic channels will not be available"); } return rv; } diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 4b1f3bd85..33c360e4d 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -29,6 +29,54 @@ #include "log.h" #include "string_calls.h" +/*****************************************************************************/ +static void +xrdp_wm_load_channel_config(struct xrdp_wm *self) +{ + struct list *names = list_create(); + names->auto_free = 1; + struct list *values = list_create(); + values->auto_free = 1; + + if (file_by_name_read_section(self->session->xrdp_ini, + "Channels", names, values) == 0) + { + int chan_id; + int chan_count = libxrdp_get_channel_count(self->session); + const char *disabled_str = NULL; + + for (chan_id = 0 ; chan_id < chan_count ; ++chan_id) + { + char chan_name[16]; + if (libxrdp_query_channel(self->session, chan_id, chan_name, + NULL) == 0) + { + int disabled = 1; /* Channels disabled if not found */ + int index; + + for (index = 0; index < names->count; index++) + { + const char *q = (const char *)list_get_item(names, index); + const char *r = (const char *)list_get_item(values, index); + if (g_strcasecmp(q, chan_name) == 0) + { + disabled = !g_text2bool(r); + break; + } + } + disabled_str = (disabled) ? "disabled" : "enabled"; + LOG(LOG_LEVEL_DEBUG, "xrdp_wm_load_channel_config: " + "channel %s channel id %d is %s", + chan_name, chan_id, disabled_str); + + libxrdp_disable_channel(self->session, chan_id, disabled); + } + } + } + list_delete(names); + list_delete(values); +} + /*****************************************************************************/ struct xrdp_wm * xrdp_wm_create(struct xrdp_process *owner, @@ -69,6 +117,23 @@ xrdp_wm_create(struct xrdp_process *owner, /* to store configuration from xrdp.ini */ self->xrdp_config = g_new0(struct xrdp_config, 1); + /* Load the channel config so libxrdp can check whether + drdynvc is enabled or not */ + xrdp_wm_load_channel_config(self); + + // Start drdynvc if available. + if (libxrdp_drdynvc_start(self->session) == 0) + { + // drdynvc is started. callback() will + // be notified when capabilities are received. + } + else if (self->client_info->gfx) + { + LOG(LOG_LEVEL_WARNING, "Disabling GFX as '" + DRDYNVC_SVC_CHANNEL_NAME "' isn't available"); + self->client_info->gfx = 0; + } + return self; } @@ -564,9 +629,7 @@ xrdp_wm_init(struct xrdp_wm *self) { int fd; int index; - struct list *names; - struct list *values; - char *q; + const char *q; const char *r; char param[256]; char default_section_name[256]; @@ -590,48 +653,6 @@ xrdp_wm_init(struct xrdp_wm *self) /* Scale the login screen values */ xrdp_login_wnd_scale_config_values(self); - /* global channels allow */ - names = list_create(); - names->auto_free = 1; - values = list_create(); - values->auto_free = 1; - if (file_by_name_read_section(self->session->xrdp_ini, - "Channels", names, values) == 0) - { - int chan_id; - int chan_count = libxrdp_get_channel_count(self->session); - const char *disabled_str = NULL; - - for (chan_id = 0 ; chan_id < chan_count ; ++chan_id) - { - char chan_name[16]; - if (libxrdp_query_channel(self->session, chan_id, chan_name, - NULL) == 0) - { - int disabled = 1; /* Channels disabled if not found */ - - for (index = 0; index < names->count; index++) - { - q = (char *) list_get_item(names, index); - if (g_strcasecmp(q, chan_name) == 0) - { - r = (const char *) list_get_item(values, index); - disabled = !g_text2bool(r); - break; - } - } - disabled_str = (disabled) ? "disabled" : "enabled"; - LOG(LOG_LEVEL_DEBUG, "xrdp_wm_init: " - "channel %s channel id %d is %s", - chan_name, chan_id, disabled_str); - - libxrdp_disable_channel(self->session, chan_id, disabled); - } - } - } - list_delete(names); - list_delete(values); - xrdp_wm_load_static_colors_plus(self, autorun_name); xrdp_wm_load_static_pointers(self); self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color; @@ -645,9 +666,9 @@ xrdp_wm_init(struct xrdp_wm *self) fd = g_file_open_ro(self->session->xrdp_ini); if (fd != -1) { - names = list_create(); + struct list *names = list_create(); names->auto_free = 1; - values = list_create(); + struct list *values = list_create(); values->auto_free = 1; /* pick up the first section name except for 'globals', 'Logging', 'channels' @@ -656,7 +677,7 @@ xrdp_wm_init(struct xrdp_wm *self) default_section_name[0] = '\0'; for (index = 0; index < names->count; index++) { - q = (char *)list_get_item(names, index); + q = (const char *)list_get_item(names, index); if ((g_strncasecmp("globals", q, 8) != 0) && (g_strncasecmp("Logging", q, 8) != 0) && (g_strncasecmp("LoggingPerLogger", q, 17) != 0) && @@ -714,8 +735,8 @@ xrdp_wm_init(struct xrdp_wm *self) { for (index = 0; index < names->count; index++) { - q = (char *)list_get_item(names, index); - r = (char *)list_get_item(values, index); + q = (const char *)list_get_item(names, index); + r = (const char *)list_get_item(values, index); if (g_strncasecmp("password", q, 255) == 0) { @@ -2031,7 +2052,6 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2, LOWORD(param3), HIWORD(param3)); case 0x555a: // "yeah, up_and_running" - libxrdp_drdynvc_start(wm->session); xrdp_mm_up_and_running(wm->mm); break; }