diff --git a/common/os_calls.c b/common/os_calls.c index 80b2d235..1d3a71b1 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -2265,6 +2265,27 @@ g_strncmp(const char *c1, const char *c2, int len) return strncmp(c1, c2, len); } +/*****************************************************************************/ +/* compare up to delim */ +int APP_CC +g_strncmp_d(const char *s1, const char *s2, const char delim, int n) +{ + char c1; + char c2; + + while (n > 0) + { + c1 = *s1++; + c2 = *s2++; + if ((c1 == 0) || (c1 != c2) || (c1 == delim) || (c2 == delim)) + { + return c1 - c2; + } + n--; + } + return c1 - c2; +} + /*****************************************************************************/ int APP_CC g_strcasecmp(const char *c1, const char *c2) @@ -2906,9 +2927,13 @@ void APP_CC g_clearenv(void) { #if defined(_WIN32) +#else +#if defined(BSD) + environ[0] = 0; #else environ = 0; #endif +#endif } /*****************************************************************************/ diff --git a/common/os_calls.h b/common/os_calls.h index 3afde05c..1805a6a1 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -115,6 +115,7 @@ char* APP_CC g_strdup(const char* in); char* APP_CC g_strndup(const char* in, const unsigned int maxlen); int APP_CC g_strcmp(const char* c1, const char* c2); int APP_CC g_strncmp(const char* c1, const char* c2, int len); +int APP_CC g_strncmp_d(const char* c1, const char* c2, const char delim, int len); int APP_CC g_strcasecmp(const char* c1, const char* c2); int APP_CC g_strncasecmp(const char* c1, const char* c2, int len); int APP_CC g_atoi(const char* str); diff --git a/common/trans.h b/common/trans.h index 33b57aac..4a8b249c 100644 --- a/common/trans.h +++ b/common/trans.h @@ -36,29 +36,30 @@ struct trans; /* forward declaration */ -typedef int (*ttrans_data_in)(struct trans* self); -typedef int (*ttrans_conn_in)(struct trans* self, struct trans* new_self); -typedef int (*tis_term)(void); +typedef int (DEFAULT_CC *ttrans_data_in)(struct trans* self); +typedef int (DEFAULT_CC *ttrans_conn_in)(struct trans* self, + struct trans* new_self); +typedef int (DEFAULT_CC *tis_term)(void); struct trans { - tbus sck; /* socket handle */ - int mode; /* 1 tcp, 2 unix socket */ - int status; - int type1; /* 1 listener 2 server 3 client */ - ttrans_data_in trans_data_in; - ttrans_conn_in trans_conn_in; - void* callback_data; - int header_size; - struct stream* in_s; - struct stream* out_s; - char* listen_filename; - tis_term is_term; /* used to test for exit */ - struct stream* wait_s; - char addr[256]; - char port[256]; - int no_stream_init_on_data_in; - int extra_flags; /* user defined */ + tbus sck; /* socket handle */ + int mode; /* 1 tcp, 2 unix socket */ + int status; + int type1; /* 1 listener 2 server 3 client */ + ttrans_data_in trans_data_in; + ttrans_conn_in trans_conn_in; + void* callback_data; + int header_size; + struct stream* in_s; + struct stream* out_s; + char* listen_filename; + tis_term is_term; /* used to test for exit */ + struct stream* wait_s; + char addr[256]; + char port[256]; + int no_stream_init_on_data_in; + int extra_flags; /* user defined */ }; struct trans* APP_CC diff --git a/docs/man/sesman.ini.5 b/docs/man/sesman.ini.5 index 84beafb4..a1ba3a50 100644 --- a/docs/man/sesman.ini.5 +++ b/docs/man/sesman.ini.5 @@ -116,6 +116,31 @@ Sets the time(in seconds) limit before a disconnected session is killed. If set to \fI0\fR, automatic killing is disabled. .br +.TP +\fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR +Session allocation policy. By Default, a new session is created +for the combination when using Xrdp, and +for the combination when using Xvnc. +This behaviour can be changed by setting session policy to: +.br + +.br +\fBUBD\fR - session per +.br +\fBUBI\fR - session per +.br +\fBUBC\fR - session per +.br +\fBUBDI\fR - session per +.br +\fBUBDC\fR - session per +.br + +.br +Note that the criteria can not be turned off +and will always be checkt when for Xvnc connections. +.br + .SH "SECURITY" The following parameters can be used in the \fB[Sessions]\fR section: diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 2eb78ea0..3ec00b6e 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -39,6 +39,8 @@ //#define USE_SYNC_FLAG +static char g_fuse_mount_name[256] = "xrdp_client"; + /* FUSE mount point */ char g_fuse_root_path[256] = ""; char g_fuse_clipboard_path[256] = ""; /* for clipboard use */ @@ -369,6 +371,37 @@ int clipboard_request_file_data(int stream_id, int lindex, int offset, static void xfuse_mark_as_stale(int pinode); static void xfuse_delete_stale_entries(int pinode); +/*****************************************************************************/ +int APP_CC +load_fuse_config(void) +{ + int index; + char cfg_file[256]; + struct list *items; + struct list *values; + char *item; + char *value; + + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); + file_by_name_read_section(cfg_file, "Chansrv", 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, "FuseMountName") == 0) + { + g_strncpy(g_fuse_mount_name, value, 255); + } + } + list_delete(items); + list_delete(values); + return 0; +} + /***************************************************************************** ** ** ** public functions - can be called from any code path ** @@ -381,7 +414,8 @@ static void xfuse_delete_stale_entries(int pinode); * @return 0 on success, -1 on failure *****************************************************************************/ -int xfuse_init() +int APP_CC +xfuse_init(void) { struct fuse_args args = FUSE_ARGS_INIT(0, NULL); @@ -398,8 +432,10 @@ int xfuse_init() return -1; } - /* define FUSE mount point to ~/xrdp_client */ - g_snprintf(g_fuse_root_path, 255, "%s/xrdp_client", g_getenv("HOME")); + load_fuse_config(); + + /* define FUSE mount point to ~/xrdp_client, ~/thinclient_drives */ + g_snprintf(g_fuse_root_path, 255, "%s/%s", g_getenv("HOME"), g_fuse_mount_name); g_snprintf(g_fuse_clipboard_path, 255, "%s/.clipboard", g_fuse_root_path); /* if FUSE mount point does not exist, create it */ @@ -460,7 +496,8 @@ int xfuse_init() * @return 0 on success, -1 on failure *****************************************************************************/ -int xfuse_deinit() +int APP_CC +xfuse_deinit(void) { xfuse_deinit_xrdp_fs(); fifo_deinit(&g_fifo_opendir); @@ -1987,7 +2024,7 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, return; } - di = (struct dir_info *) fi->fh; + di = (struct dir_info *) (tintptr) (fi->fh); if (di == NULL) { /* something seriously wrong somewhere! */ diff --git a/sesman/chansrv/pulse/module-xrdp-sink.c b/sesman/chansrv/pulse/module-xrdp-sink.c index d56a4883..d072c0d4 100644 --- a/sesman/chansrv/pulse/module-xrdp-sink.c +++ b/sesman/chansrv/pulse/module-xrdp-sink.c @@ -58,6 +58,15 @@ #include #include +/* defined in pulse/version.h */ +#if PA_PROTOCOL_VERSION > 28 +/* these used to be defined in pulsecore/macro.h */ +typedef bool pa_bool_t; +#define FALSE ((pa_bool_t) 0) +#define TRUE (!FALSE) +#else +#endif + #include "module-xrdp-sink-symdef.h" PA_MODULE_AUTHOR("Jay Sorg"); diff --git a/sesman/chansrv/pulse/module-xrdp-source.c b/sesman/chansrv/pulse/module-xrdp-source.c index 2d7ec4fa..95465c65 100644 --- a/sesman/chansrv/pulse/module-xrdp-source.c +++ b/sesman/chansrv/pulse/module-xrdp-source.c @@ -45,6 +45,15 @@ #include #include +/* defined in pulse/version.h */ +#if PA_PROTOCOL_VERSION > 28 +/* these used to be defined in pulsecore/macro.h */ +typedef bool pa_bool_t; +#define FALSE ((pa_bool_t) 0) +#define TRUE (!FALSE) +#else +#endif + #include "module-xrdp-source-symdef.h" PA_MODULE_AUTHOR("Laxmikant Rashinkar"); @@ -329,8 +338,7 @@ int pa__init(pa_module *m) { pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); - //pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Input")); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "xrdp Input")); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "xrdp source")); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY); diff --git a/sesman/config.c b/sesman/config.c index 897164af..8fa6e86a 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -337,6 +337,7 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, se->max_idle_time = 0; se->max_disc_time = 0; se->kill_disconnected = 0; + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; file_read_section(file, SESMAN_CFG_SESSIONS, param_n, param_v); @@ -368,15 +369,49 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, { se->max_disc_time = g_atoi((char *)list_get_item(param_v, i)); } + + if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_POLICY_S)) + { + char *value = (char *)list_get_item(param_v, i); + if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_DFLT_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBD_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBD; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBC; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDC; + } + else /* silently ignore typos */ + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + } } - /* printing security config */ + /* printing session config */ g_printf("session configuration:\r\n"); g_printf("\tMaxSessions: %i\r\n", se->max_sessions); g_printf("\tX11DisplayOffset: %i\r\n", se->x11_display_offset); g_printf("\tKillDisconnected: %i\r\n", se->kill_disconnected); g_printf("\tIdleTimeLimit: %i\r\n", se->max_idle_time); g_printf("\tDisconnectedTimeLimit: %i\r\n", se->max_idle_time); + g_printf("\tPolicy: %i\r\n", se->policy); return 0; } @@ -413,7 +448,7 @@ config_read_rdp_params(int file, struct config_sesman *cs, struct list *param_n, /******************************************************************************/ int DEFAULT_CC -config_read_xorg_params(int file, struct config_sesman *cs, +config_read_xorg_params(int file, struct config_sesman *cs, struct list *param_n, struct list *param_v) { int i; @@ -427,7 +462,7 @@ config_read_xorg_params(int file, struct config_sesman *cs, for (i = 0; i < param_n->count; i++) { - list_add_item(cs->xorg_params, + list_add_item(cs->xorg_params, (long) g_strdup((char *) list_get_item(param_v, i))); } @@ -436,7 +471,7 @@ config_read_xorg_params(int file, struct config_sesman *cs, for (i = 0; i < cs->xorg_params->count; i++) { - g_printf("\tParameter %02d %s\r\n", + g_printf("\tParameter %02d %s\r\n", i, (char *) list_get_item(cs->xorg_params, i)); } diff --git a/sesman/config.h b/sesman/config.h index a9679e9a..31ac7256 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -65,6 +65,29 @@ #define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit" #define SESMAN_CFG_SESS_DISC_LIMIT "DisconnectedTimeLimit" +#define SESMAN_CFG_SESS_POLICY_S "Policy" +#define SESMAN_CFG_SESS_POLICY_DFLT_S "Default" +#define SESMAN_CFG_SESS_POLICY_UBD_S "UBD" +#define SESMAN_CFG_SESS_POLICY_UBI_S "UBI" +#define SESMAN_CFG_SESS_POLICY_UBC_S "UBC" +#define SESMAN_CFG_SESS_POLICY_UBDI_S "UBDI" +#define SESMAN_CFG_SESS_POLICY_UBDC_S "UBDC" + +enum SESMAN_CFG_SESS_POLICY_BITS { + SESMAN_CFG_SESS_POLICY_D = 0x01, + SESMAN_CFG_SESS_POLICY_I = 0x02, + SESMAN_CFG_SESS_POLICY_C = 0x04 +}; + +enum SESMAN_CFG_SESS_POLICY { + SESMAN_CFG_SESS_POLICY_DFLT = 0, + SESMAN_CFG_SESS_POLICY_UBD = SESMAN_CFG_SESS_POLICY_D, + SESMAN_CFG_SESS_POLICY_UBI = SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBC = SESMAN_CFG_SESS_POLICY_C, + SESMAN_CFG_SESS_POLICY_UBDI = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBDC = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_C +}; + /** * * @struct config_security @@ -135,6 +158,11 @@ struct config_sessions * @brief enables automatic killing of disconnected session */ int kill_disconnected; + /** + * @var policy + * @brief session allocation policy + */ + enum SESMAN_CFG_SESS_POLICY policy; }; /** diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index 9e7d9083..ce528d46 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -74,7 +74,7 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) else if (data) { s_item = session_get_bydata(s->username, s->width, s->height, - s->bpp, s->type); + s->bpp, s->type, s->client_ip); if (s_item != 0) { diff --git a/sesman/sesman.ini b/sesman/sesman.ini index a1875cac..4241bd32 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -15,17 +15,47 @@ TerminalServerAdmins=tsadmins AlwaysGroupCheck = false [Sessions] + +## X11DisplayOffset - x11 display number offset +# Type: integer +# Default: 10 X11DisplayOffset=10 + +## MaxSessions - maximum number of connections to an xrdp server +# Type: integer +# Default: 0 MaxSessions=50 + +## KillDisconnected - kill disconnected sessions +# Type: integer +# Default: 0 # if 1, true, or yes, kill session after 60 seconds KillDisconnected=0 + +## IdleTimeLimit - when to disconnect idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds without mouse or keyboard input before disconnect # not complete yet IdleTimeLimit=0 + +## DisconnectedTimeLimit - when to kill idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds before a disconnected session is killed # min 60 seconds DisconnectedTimeLimit=0 +## Policy - session allocation policy +# Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ] +# Default: Xrdp: and Xvnc: +# "UBD" session per +# "UBI" session per +# "UBC" session per +# "UBDI" session per +# "UBDC" session per +Policy=Default + [Logging] LogFile=xrdp-sesman.log LogLevel=DEBUG @@ -57,3 +87,7 @@ param5=-noreset param6=-ac param7=-nolisten param8=tcp + +[Chansrv] +# drive redirection, defaults to xrdp_client if not set +FuseMountName=thinclient_drives diff --git a/sesman/session.c b/sesman/session.c index 6b50560f..b68ed3f4 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -90,9 +90,10 @@ dumpItemsToString(struct list *self, char *outstr, int len) /******************************************************************************/ struct session_item *DEFAULT_CC -session_get_bydata(char *name, int width, int height, int bpp, int type) +session_get_bydata(char *name, int width, int height, int bpp, int type, char *client_ip) { struct session_chain *tmp; + enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy; /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -104,6 +105,7 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) { case SCP_SESSION_TYPE_XVNC: /* 0 */ type = SESMAN_SESSION_TYPE_XVNC; /* 2 */ + policy |= SESMAN_CFG_SESS_POLICY_D; /* Xvnc cannot resize */ break; case SCP_SESSION_TYPE_XRDP: /* 1 */ type = SESMAN_SESSION_TYPE_XRDP; /* 1 */ @@ -116,14 +118,36 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) return 0; } +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s", + policy, name, width, height, bpp, type, client_ip); +#endif + while (tmp != 0) { +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s", + tmp->item, + tmp->item->name, + tmp->item->width, tmp->item->height, + tmp->item->bpp, tmp->item->type, + tmp->item->client_ip); +#endif + if (type == SESMAN_SESSION_TYPE_XRDP) { /* only name and bpp need to match for X11rdp, it can resize */ if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->bpp == bpp && - tmp->item->type == type) + (!(policy & SESMAN_CFG_SESS_POLICY_D) || + (tmp->item->width == width && tmp->item->height == height)) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -132,10 +156,13 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) } if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->width == width && - tmp->item->height == height && - tmp->item->bpp == bpp && - tmp->item->type == type) + (tmp->item->width == width && tmp->item->height == height) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -577,11 +604,11 @@ session_start_fork(int width, int height, int bpp, char *username, g_snprintf(text, 255, "%d", g_cfg->sess.kill_disconnected); g_setenv("XRDP_SESMAN_KILL_DISCONNECTED", text, 1); - if (type == SESMAN_SESSION_TYPE_XORG) - { + if (type == SESMAN_SESSION_TYPE_XORG) + { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long) g_strdup("/usr/bin/Xorg")); list_add_item(xserver_params, (long) g_strdup(screen)); @@ -599,18 +626,18 @@ session_start_fork(int width, int height, int bpp, char *username, /* some args are passed via env vars */ g_sprintf(geometry, "%d", width); g_setenv("XRDP_START_WIDTH", geometry, 1); - + g_sprintf(geometry, "%d", height); g_setenv("XRDP_START_HEIGHT", geometry, 1); - - /* fire up Xorg */ + + /* fire up Xorg */ g_execvp("/usr/bin/Xorg", pp1); - } + } else if (type == SESMAN_SESSION_TYPE_XVNC) { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("Xvnc")); list_add_item(xserver_params, (long)g_strdup(screen)); @@ -636,7 +663,7 @@ session_start_fork(int width, int height, int bpp, char *username, { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("X11rdp")); list_add_item(xserver_params, (long)g_strdup(screen)); diff --git a/sesman/session.h b/sesman/session.h index 185fa803..05e3b3a9 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -91,9 +91,9 @@ struct session_chain * */ struct session_item* DEFAULT_CC -session_get_bydata(char* name, int width, int height, int bpp, int type); +session_get_bydata(char* name, int width, int height, int bpp, int type, char *client_ip); #ifndef session_find_item - #define session_find_item(a, b, c, d, e) session_get_bydata(a, b, c, d, e); + #define session_find_item(a, b, c, d, e, f) session_get_bydata(a, b, c, d, e, f); #endif /** diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 22e7d644..b27e0fbe 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -55,6 +55,9 @@ use_fastpath=both # configure login screen # +# Login Screen Window Title +#ls_title=My Login Title + # top level window background color in RGB format ls_top_window_bg_color=009cb5 @@ -66,6 +69,7 @@ ls_height=430 ls_bg_color=dedede # logo +# full path to bmp-file or file in shared folder ls_logo_filename= ls_logo_x_pos=55 ls_logo_y_pos=50 diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index bf4fcb12..8b14cb26 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -560,9 +560,19 @@ xrdp_login_wnd_create(struct xrdp_wm *self) self->login_window->notify = xrdp_wm_login_notify; - g_gethostname(buf1, 256); - g_sprintf(buf, "Login to %s", buf1); - set_string(&self->login_window->caption1, buf); + /* if window title not specified, use hostname as default */ + if (globals->ls_title[0] == 0) + { + g_gethostname(buf1, 256); + g_sprintf(buf, "Login to %s", buf1); + set_string(&self->login_window->caption1, buf); + } + else + { + /*self->login_window->caption1 = globals->ls_title[0];*/ + g_sprintf(buf, "%s", globals->ls_title); + set_string(&self->login_window->caption1, buf); + } if (regular) { @@ -827,6 +837,12 @@ load_xrdp_config(struct xrdp_config *config, int bpp) else if (g_strncmp(n, "ls_bg_color", 64) == 0) globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + else if (g_strncmp(n, "ls_title", 255) == 0) + { + g_strncpy(globals->ls_title, v, 255); + globals->ls_title[255] = 0; + } + else if (g_strncmp(n, "ls_logo_filename", 255) == 0) { g_strncpy(globals->ls_logo_filename, v, 255); @@ -917,6 +933,7 @@ load_xrdp_config(struct xrdp_config *config, int bpp) g_writeln("ls_width: %d", globals->ls_width); g_writeln("ls_height: %d", globals->ls_height); g_writeln("ls_bg_color: %x", globals->ls_bg_color); + g_writeln("ls_title: %s", globals->ls_title); g_writeln("ls_logo_filename: %s", globals->ls_logo_filename); g_writeln("ls_logo_x_pos: %d", globals->ls_logo_x_pos); g_writeln("ls_logo_y_pos: %d", globals->ls_logo_y_pos); diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 7e1c81f0..973b64e8 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -595,6 +595,7 @@ struct xrdp_cfg_globals int ls_btn_cancel_y_pos; /* y pos for Cancel button */ int ls_btn_cancel_width; /* width of Cancel button */ int ls_btn_cancel_height; /* height of Cancel button */ + char ls_title[256]; /* loginscreen window title */ }; struct xrdp_cfg_logging