diff --git a/common/string_calls.c b/common/string_calls.c index 3a94e732..941a2995 100644 --- a/common/string_calls.c +++ b/common/string_calls.c @@ -162,8 +162,8 @@ g_text2bool(const char *s) } /*****************************************************************************/ -int -g_get_display_num_from_display(const char *display_text) +static int +get_display_num_from_display(const char *display_text) { int rv = -1; const char *p; @@ -191,6 +191,70 @@ g_get_display_num_from_display(const char *display_text) return rv; } +/*****************************************************************************/ +int +g_get_display_string_from_x11_display(int display_num, + char buff[], unsigned int bufflen) +{ + unsigned int res = g_snprintf(buff, bufflen, "X11-%d", display_num); + return (res >= bufflen) ? -1 : 0; +} + + +/*****************************************************************************/ +int +g_get_x11_display_from_display_string(const char *display_str) +{ + int result = -1; + if (display_str != NULL) + { + if (display_str[0] == 'X' && display_str[1] == '1' && + display_str[2] == '1' && display_str[3] == '-' && + isdigit(display_str[4])) + { + result = g_atoi(display_str + 4); + } + } + + return result; +} + +/*****************************************************************************/ +int +g_get_display_string(char buff[], unsigned int bufflen) +{ + const char *str; + const char *p = NULL; + int rv = 0; + + if ((str = g_getenv("WAYLAND_DISPLAY")) != NULL) + { + // Return the unqualified part of the name + p = strrchr(str, '/'); + p = (p != NULL) ? (p + 1) : str; + strlcpy(buff, p, bufflen); + } + else if ((str = g_getenv("DISPLAY")) != NULL) + { + int n = get_display_num_from_display(str); + + if (n >= 0) + { + g_snprintf(buff, bufflen, "X11-%d", n); + } + else + { + rv = g_get_display_string_from_x11_display(n, buff, bufflen); + } + } + else + { + rv = -1; + } + + return rv; +} + /*****************************************************************************/ /* returns length of text */ int diff --git a/common/string_calls.h b/common/string_calls.h index 1b554938..735829af 100644 --- a/common/string_calls.h +++ b/common/string_calls.h @@ -190,14 +190,37 @@ char * g_bytes_to_hexdump(const char *src, int len); /** - * Extracts the display number from an X11 display string + * Converts an X11 display number to a display string * - * @param display_text Display string (i.e. g_getenv("DISPLAY")) - * - * @result <0 if the string could not be parsed, or >=0 for a display number + * @param display_num X11 display unmber + * @param buff Buffer for result + * @param bufflen size of above + * @return != 0 if the result doesn't fit */ int -g_get_display_num_from_display(const char *display_text); +g_get_display_string_from_x11_display(int display_num, + char buff[], unsigned int bufflen); +/** + * Converts a display string to an X11 display number + * + * @param display_str Display string + * @return X11 display number, or -1 if the display string isn't X11 + */ +int +g_get_x11_display_from_display_string(const char *display_str); + +/** + * Extracts the display string from either DISPLAY or WAYLAND_DISPLAY + * + * @param buff Buffer for result + * @param bufflen Length of above buffer + * + * Returned buffer will be (e.g.) "X11-10" for X11 or "wayland-1" for Wayland + * + * @result != 0 if the string could not be found or parsed + */ +int +g_get_display_string(char buff[], unsigned int bufflen); /** * Converts a bitmask into a string for output purposes diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index dfa3c216..8983d922 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -49,6 +49,12 @@ **/ #define MAX_XRDP_INSTANCE_NAMELEN 80 +/** + * Max length of buffer containing a Wayland or X11 display + * name + **/ +#define MAX_DISPLAY_NAME_SIZE 32 + /** * Size of buffer including terminator for a socket description, as * returned by g_sck_get_peer_description() diff --git a/common/xrdp_sockets.h b/common/xrdp_sockets.h index e98b7657..18397612 100644 --- a/common/xrdp_sockets.h +++ b/common/xrdp_sockets.h @@ -45,13 +45,13 @@ #define SCP_LISTEN_PORT_BASE_STR "sesman.socket" /* names of socket files within XRDP_SOCKET_PATH, qualified by - * display number */ -#define XRDP_CHANSRV_BASE_STR "xrdp_chansrv_socket_%d" -#define CHANSRV_PORT_OUT_BASE_STR "xrdp_chansrv_audio_out_socket_%d" -#define CHANSRV_PORT_IN_BASE_STR "xrdp_chansrv_audio_in_socket_%d" -#define CHANSRV_API_BASE_STR "xrdpapi_%d" -#define XRDP_X11RDP_BASE_STR "xrdp_display_%d" -#define XRDP_DISCONNECT_BASE_STR "xrdp_disconnect_display_%d" + * display name */ +#define XRDP_CHANSRV_BASE_STR "xrdp_chansrv_socket_%s" +#define CHANSRV_PORT_OUT_BASE_STR "xrdp_chansrv_audio_out_socket_%s" +#define CHANSRV_PORT_IN_BASE_STR "xrdp_chansrv_audio_in_socket_%s" +#define CHANSRV_API_BASE_STR "xrdpapi_%s" +#define XRDP_X11RDP_BASE_STR "xrdp_display_%s" +#define XRDP_DISCONNECT_BASE_STR "xrdp_disconnect_display_%s" /* fullpath declarations */ #define XRDP_CHANSRV_STR XRDP_SOCKET_PATH "/" XRDP_CHANSRV_BASE_STR diff --git a/docs/man/sesman.ini.5.in b/docs/man/sesman.ini.5.in index 4664bdd7..eda5d01b 100644 --- a/docs/man/sesman.ini.5.in +++ b/docs/man/sesman.ini.5.in @@ -420,8 +420,7 @@ If first character is not a '/', this is relative to $HOME. The following substitutions are made in this string:- %U - Username %u - Numeric UID - %d - Numeric display number (ex 10) - %D - Display environment variable (ex :10.0) + %d - Display identifier (e.g. "X11-10" for X11, or "wayland-1" for Wayland) %% - Percent character .HP 3 1) The directory path permissions MUST be configured correctly by diff --git a/libipm/eicp.c b/libipm/eicp.c index 9d5c378c..e76fd4ca 100644 --- a/libipm/eicp.c +++ b/libipm/eicp.c @@ -273,7 +273,7 @@ eicp_send_logout_request(struct trans *trans) int eicp_send_create_session_request(struct trans *trans, - unsigned int display, + int x11_display, enum scp_session_type type, unsigned short width, unsigned short height, @@ -285,8 +285,8 @@ eicp_send_create_session_request(struct trans *trans, return libipm_msg_out_simple_send( trans, (int)E_EICP_CREATE_SESSION_REQUEST, - "uyqqysss", - display, + "iyqqysss", + x11_display, type, width, height, @@ -300,7 +300,7 @@ eicp_send_create_session_request(struct trans *trans, int eicp_get_create_session_request(struct trans *trans, - unsigned int *display, + int *x11_display, enum scp_session_type *type, unsigned short *width, unsigned short *height, @@ -310,7 +310,7 @@ eicp_get_create_session_request(struct trans *trans, const char **instance_name) { /* Intermediate values */ - uint32_t i_display; + int32_t i_x11_display; uint8_t i_type; uint16_t i_width; uint16_t i_height; @@ -318,8 +318,8 @@ eicp_get_create_session_request(struct trans *trans, int rv = libipm_msg_in_parse( trans, - "uyqqysss", - &i_display, + "iyqqysss", + &i_x11_display, &i_type, &i_width, &i_height, @@ -330,7 +330,7 @@ eicp_get_create_session_request(struct trans *trans, if (rv == 0) { - *display = i_display; + *x11_display = i_x11_display; *type = (enum scp_session_type)i_type; *width = i_width; *height = i_height; @@ -345,12 +345,13 @@ eicp_get_create_session_request(struct trans *trans, int eicp_send_create_session_response(struct trans *trans, enum scp_screate_status status, + const char *display, const struct guid *guid) { struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; return libipm_msg_out_simple_send( trans, (int)E_EICP_CREATE_SESSION_RESPONSE, - "iB", status, &guid_descriptor); + "isB", status, display, &guid_descriptor); } /*****************************************************************************/ @@ -358,6 +359,7 @@ eicp_send_create_session_response(struct trans *trans, int eicp_get_create_session_response(struct trans *trans, enum scp_screate_status *status, + const char **display, struct guid *guid) { /* Intermediate values */ @@ -366,14 +368,19 @@ eicp_get_create_session_response(struct trans *trans, const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; int rv = libipm_msg_in_parse( trans, - "iB", + "isB", &i_status, + display, &guid_descriptor); if (rv == 0) { *status = (enum scp_screate_status)i_status; } + else + { + *display = ""; + } return rv; } diff --git a/libipm/eicp.h b/libipm/eicp.h index 93e88373..d2077d42 100644 --- a/libipm/eicp.h +++ b/libipm/eicp.h @@ -272,7 +272,7 @@ eicp_send_logout_request(struct trans *trans); * Send an E_EICP_CREATE_SESSION_REQUEST (sesman) * * @param trans EICP transport - * @param display X display number to use + * @param x11_display X display number to use, or -1 if not X11 * @param type Session type * @param width Initial session width * @param height Initial session height @@ -293,7 +293,7 @@ eicp_send_logout_request(struct trans *trans); */ int eicp_send_create_session_request(struct trans *trans, - unsigned int display, + int x11_display, enum scp_session_type type, unsigned short width, unsigned short height, @@ -307,7 +307,7 @@ eicp_send_create_session_request(struct trans *trans, * Parse an incoming E_EICP_CREATE_SESSION_REQUEST (sesexec) * * @param trans EICP transport - * @param[out] display X display number to use + * @param[out] x11_display X display number to use * @param[out] type Session type * @param[out] width Initial session width * @param[out] height Initial session height @@ -322,7 +322,7 @@ eicp_send_create_session_request(struct trans *trans, */ int eicp_get_create_session_request(struct trans *trans, - unsigned int *display, + int *x11_display, enum scp_session_type *type, unsigned short *width, unsigned short *height, @@ -340,12 +340,15 @@ eicp_get_create_session_request(struct trans *trans, * * @param trans EICP transport * @param status Status of creation request + * @param display Display name, either (e.g.) "X11-n" (X11) + * or "wayland-n" (Wayland) * @param guid GUID of session * @return != 0 for error */ int eicp_send_create_session_response(struct trans *trans, enum scp_screate_status status, + const char *display, const struct guid *guid); @@ -358,12 +361,15 @@ eicp_send_create_session_response(struct trans *trans, * * @param trans EICP transport * @param[out] status Status of creation request + * @param[out] display Display name, either (e.g.) "X11-n" (X11) + * or "wayland-n" (Wayland) * @param[out] guid GUID of session * @return != 0 for error */ int eicp_get_create_session_response(struct trans *trans, enum scp_screate_status *status, + const char **display, struct guid *guid); #endif /* EICP_H */ diff --git a/libipm/ercp.c b/libipm/ercp.c index b7648fef..6bcdc22c 100644 --- a/libipm/ercp.c +++ b/libipm/ercp.c @@ -147,7 +147,7 @@ ercp_msg_in_reset(struct trans *trans) int ercp_send_session_announce_event(struct trans *trans, - unsigned int display, + const char *display, uid_t uid, enum scp_session_type type, unsigned short start_width, @@ -163,7 +163,7 @@ ercp_send_session_announce_event(struct trans *trans, return libipm_msg_out_simple_send( trans, (int)E_ERCP_SESSION_ANNOUNCE_EVENT, - "uiyqqyBsxs", + "siyqqyBsxs", display, uid, type, @@ -180,7 +180,7 @@ ercp_send_session_announce_event(struct trans *trans, int ercp_get_session_announce_event(struct trans *trans, - unsigned int *display, + const char **display, uid_t *uid, enum scp_session_type *type, unsigned short *start_width, @@ -192,7 +192,6 @@ ercp_get_session_announce_event(struct trans *trans, const char **instance_name) { /* Intermediate values */ - uint32_t i_display; int32_t i_uid; uint8_t i_type; uint16_t i_width; @@ -204,8 +203,8 @@ ercp_get_session_announce_event(struct trans *trans, int rv = libipm_msg_in_parse( trans, - "uiyqqyBsxs", - &i_display, + "siyqqyBsxs", + display, &i_uid, &i_type, &i_width, @@ -218,7 +217,6 @@ ercp_get_session_announce_event(struct trans *trans, if (rv == 0) { - *display = i_display; *uid = (uid_t)i_uid; *type = (enum scp_session_type)i_type; *start_width = i_width; @@ -226,6 +224,10 @@ ercp_get_session_announce_event(struct trans *trans, *bpp = i_bpp; *start_time = (time_t)i_start_time; } + else + { + *display = ""; + } return rv; } diff --git a/libipm/ercp.h b/libipm/ercp.h index 3d6b201e..b96a4266 100644 --- a/libipm/ercp.h +++ b/libipm/ercp.h @@ -177,7 +177,7 @@ ercp_msg_in_reset(struct trans *trans); */ int ercp_send_session_announce_event(struct trans *trans, - unsigned int display, + const char *display, uid_t uid, enum scp_session_type type, unsigned short start_width, @@ -209,7 +209,7 @@ ercp_send_session_announce_event(struct trans *trans, */ int ercp_get_session_announce_event(struct trans *trans, - unsigned int *display, + const char **display, uid_t *uid, enum scp_session_type *type, unsigned short *start_width, diff --git a/libipm/scp.c b/libipm/scp.c index cb96e034..b3fe2f62 100644 --- a/libipm/scp.c +++ b/libipm/scp.c @@ -481,7 +481,7 @@ scp_get_create_session_request(struct trans *trans, int scp_send_create_session_response(struct trans *trans, enum scp_screate_status status, - int display, + const char *display, const struct guid *guid) { struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; @@ -489,7 +489,7 @@ scp_send_create_session_response(struct trans *trans, return libipm_msg_out_simple_send( trans, (int)E_SCP_CREATE_SESSION_RESPONSE, - "iiB", + "isB", status, display, &guid_descriptor); @@ -500,25 +500,27 @@ scp_send_create_session_response(struct trans *trans, int scp_get_create_session_response(struct trans *trans, enum scp_screate_status *status, - int *display, + const char **display, struct guid *guid) { /* Intermediate values */ int32_t i_status; - int32_t i_display; const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; int rv = libipm_msg_in_parse( trans, - "iiB", + "isB", &i_status, - &i_display, + display, &guid_descriptor); if (rv == 0) { *status = (enum scp_screate_status)i_status; - *display = i_display; + } + else + { + *display = ""; } return rv; @@ -747,7 +749,7 @@ scp_send_list_sessions_response( rv = libipm_msg_out_simple_send( trans, (int)E_SCP_LIST_SESSIONS_RESPONSE, - "iiuyqqyxisssxs", + "iisyqqyxisssxs", status, info->sid, info->display, @@ -791,7 +793,7 @@ scp_get_list_sessions_response( if (*status == E_SCP_LS_SESSION_INFO) { int32_t i_sid; - uint32_t i_display; + char *i_display; uint8_t i_type; uint16_t i_width; uint16_t i_height; @@ -806,7 +808,7 @@ scp_get_list_sessions_response( rv = libipm_msg_in_parse( trans, - "iuyqqyxisssxs", + "isyqqyxisssxs", &i_sid, &i_display, &i_type, @@ -826,6 +828,7 @@ scp_get_list_sessions_response( /* Allocate a block of memory large enough for the * structure result, and the strings it contains */ unsigned int len = sizeof(struct scp_session_info) + + g_strlen(i_display) + 1 + g_strlen(i_start_ip_addr) + 1 + g_strlen(i_client_ip) + 1 + g_strlen(i_client_name) + 1 + @@ -848,7 +851,7 @@ scp_get_list_sessions_response( } /* Copy the data over */ p->sid = i_sid; - p->display = i_display; + COPY_STRING(p->display, i_display); p->type = (enum scp_session_type)i_type; p->width = i_width; p->height = i_height; diff --git a/libipm/scp.h b/libipm/scp.h index a9e86b49..2f8e2ac3 100644 --- a/libipm/scp.h +++ b/libipm/scp.h @@ -391,15 +391,17 @@ scp_get_create_session_request(struct trans *trans, * * @param trans SCP transport * @param status Status of creation request - * @param display Should be zero if create session failed. + * @param display Will be "" if create session failed * @param guid Guid for session. Should be all zeros if create session failed * * @return != 0 for error + * + * The display will be either "X11-n" (X11) or (e.g) "wayland-0" (Wayland) */ int scp_send_create_session_response(struct trans *trans, enum scp_screate_status status, - int display, + const char *display, const struct guid *guid); @@ -408,7 +410,7 @@ scp_send_create_session_response(struct trans *trans, * * @param trans SCP transport * @param[out] status Status of creation request - * @param[out] display Should be zero if create session failed. + * @param[out] display Will be "" if create session failed * @param[out] guid Guid for session. Should be all zeros if create session * failed * @@ -417,7 +419,7 @@ scp_send_create_session_response(struct trans *trans, int scp_get_create_session_response(struct trans *trans, enum scp_screate_status *status, - int *display, + const char **display, struct guid *guid); /** diff --git a/libipm/scp_application_types.h b/libipm/scp_application_types.h index c6ad8aaa..28e90d53 100644 --- a/libipm/scp_application_types.h +++ b/libipm/scp_application_types.h @@ -45,13 +45,16 @@ enum scp_session_type "unknown" \ ) +#define SCP_SESSION_TYPE_IS_X11(t) \ + ((t) >= SCP_SESSION_TYPE_XVNC && (t) <= SCP_SESSION_TYPE_XORG) + /** * @brief Information to display about a particular sesman session */ struct scp_session_info { int sid; ///< Session ID - unsigned int display; ///< Display number + char *display; ///< Display name ("X11-n" or "wayland-n") enum scp_session_type type; ///< Session type unsigned short width; ///< Initial session width unsigned short height; ///< Initial session height diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 790ae8fd..dbadfc5f 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -43,6 +43,7 @@ #include "chansrv_fuse.h" #include "chansrv_config.h" #include "xrdp_sockets.h" +#include "xrdp_constants.h" #include "audin.h" #include "channel_defs.h" @@ -68,7 +69,8 @@ static tbus g_thread_done_event = 0; struct config_chansrv *g_cfg = NULL; -int g_display_num = -1; +char g_display_str[MAX_DISPLAY_NAME_SIZE]; + int g_cliprdr_chan_id = -1; /* cliprdr */ int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpdr_chan_id = -1; /* rdpdr */ @@ -1426,7 +1428,8 @@ setup_listen(void) g_lis_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192); g_lis_trans->is_term = g_is_term; - g_snprintf(port, sizeof(port), XRDP_CHANSRV_STR, g_getuid(), g_display_num); + g_snprintf(port, sizeof(port), XRDP_CHANSRV_STR, + g_getuid(), g_display_str); g_lis_trans->trans_conn_in = my_trans_conn_in; error = trans_listen(g_lis_trans, port); @@ -1450,7 +1453,8 @@ setup_api_listen(void) g_api_lis_trans = trans_create(TRANS_MODE_UNIX, 8192 * 4, 8192 * 4); g_api_lis_trans->is_term = g_is_term; - g_snprintf(port, sizeof(port), CHANSRV_API_STR, g_getuid(), g_display_num); + g_snprintf(port, sizeof(port), CHANSRV_API_STR, + g_getuid(), g_display_str); g_api_lis_trans->trans_conn_in = my_api_trans_conn_in; error = trans_listen(g_api_lis_trans, port); @@ -1933,24 +1937,15 @@ main(int argc, char **argv) char text[256]; const char *config_path; char log_path[256]; - const char *display_text; char log_file[256]; enum logReturns error; struct log_config *logconfig; g_init("xrdp-chansrv"); /* os_calls */ g_memset(g_drdynvcs, 0, sizeof(g_drdynvcs)); - display_text = g_getenv("DISPLAY"); - if (display_text == NULL) + if (g_get_display_string(g_display_str, sizeof(g_display_str)) < 0) { - g_writeln("DISPLAY is not set"); - main_cleanup(); - return 1; - } - g_display_num = g_get_display_num_from_display(display_text); - if (g_display_num < 0) - { - g_writeln("Unable to get display from DISPLAY='%s'", display_text); + g_writeln("Unable to get display string"); main_cleanup(); return 1; } @@ -1976,7 +1971,8 @@ main(int argc, char **argv) pid = g_getpid(); /* starting logging subsystem */ - g_snprintf(log_file, 255, "%s/xrdp-chansrv.%d.log", log_path, g_display_num); + g_snprintf(log_file, sizeof(log_file), + "%s/xrdp-chansrv.%s.log", log_path, g_display_str); g_writeln("chansrv::main: using log file [%s]", log_file); if (g_file_exist(log_file)) { @@ -2038,9 +2034,6 @@ main(int argc, char **argv) /* Cater for the X server exiting unexpectedly */ xcommon_set_x_server_fatal_handler(x_server_fatal_handler); - LOG_DEVEL(LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text); - LOG_DEVEL(LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num); - /* Set up RAIL sync objects */ g_snprintf(text, sizeof(text), "xrdp_chansrv_%8.8x_exec", pid); g_exec_event = g_create_wait_obj(text); diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 937a23ea..7df4fdba 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -173,6 +173,7 @@ int xfuse_path_in_xfuse_fs(const char *path) #include "devredir.h" #include "list.h" #include "file.h" +#include "xrdp_constants.h" /* Check for FUSE features we may wish to use * @@ -2989,14 +2990,12 @@ static unsigned int format_user_info(char *dest, unsigned int len, { char uidstr[64]; char username[64]; - char display[64]; - char displaynum[64]; + char display[MAX_DISPLAY_NAME_SIZE]; const struct info_string_tag map[] = { {'u', uidstr}, {'U', username}, - {'d', displaynum}, - {'D', display}, + {'d', display}, INFO_STRING_END_OF_LIST }; @@ -3005,20 +3004,13 @@ static unsigned int format_user_info(char *dest, unsigned int len, if (g_getlogin(username, sizeof(username)) != 0) { /* Fall back to UID */ - g_strncpy(username, uidstr, sizeof(username) - 1); + strlcpy(username, uidstr, sizeof(username)); } - if (getenv("DISPLAY") == NULL) + if (g_get_display_string(display, sizeof(display)) < 0) { /* if environment variable is not set, set it to empty string */ display[0] = '\0'; - displaynum[0] = '\0'; - } - else - { - g_strncpy(display, getenv("DISPLAY"), sizeof(display) - 1); - g_snprintf(displaynum, sizeof(displaynum), "%d", - g_get_display_num_from_display(display)); } return g_format_info_string(dest, len, format, map); diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 46c047c5..57963122 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -15,7 +15,9 @@ #include #include +#include "os_calls.h" #include "string_calls.h" +#include "xrdp_constants.h" #define PCSC_API @@ -164,10 +166,9 @@ static int connect_to_chansrv(void) { int bytes; - int dis; + char disstr[MAX_DISPLAY_NAME_SIZE]; int error; char *xrdp_session; - char *xrdp_display; char *home_str; struct sockaddr_un saddr; struct sockaddr *psaddr; @@ -184,11 +185,10 @@ connect_to_chansrv(void) LLOGLN(0, ("connect_to_chansrv: error, not xrdp session")); return 1; } - xrdp_display = getenv("DISPLAY"); - if (xrdp_display == NULL) + + if (g_get_display_string(disstr, sizeof(disstr)) < 0) { - /* DISPLAY must be set */ - LLOGLN(0, ("connect_to_chansrv: error, display not set")); + LLOGLN(0, ("connect_to_chansrv: error, don't understand DISPLAY")); return 1; } home_str = getenv("HOME"); @@ -198,13 +198,6 @@ connect_to_chansrv(void) LLOGLN(0, ("connect_to_chansrv: error, home not set")); return 1; } - dis = g_get_display_num_from_display(xrdp_display); - if (dis < 0) - { - LLOGLN(0, ("connect_to_chansrv: error, don't understand DISPLAY='%s'", - xrdp_display)); - return 1; - } g_sck = socket(PF_LOCAL, SOCK_STREAM, 0); if (g_sck == -1) { @@ -214,7 +207,7 @@ connect_to_chansrv(void) 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); + snprintf(saddr.sun_path, bytes, "%s/.pcsc%s/pcscd.comm", home_str, disstr); saddr.sun_path[bytes - 1] = 0; LLOGLN(10, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); psaddr = (struct sockaddr *) &saddr; diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c index a9bac1a6..74f6de4f 100644 --- a/sesman/chansrv/rail.c +++ b/sesman/chansrv/rail.c @@ -44,7 +44,7 @@ #include "list.h" extern int g_rail_chan_id; /* in chansrv.c */ -extern int g_display_num; /* in chansrv.c */ +extern char g_display_str[]; /* in chansrv.c */ extern char *g_exec_name; /* in chansrv.c */ extern tbus g_exec_event; /* in chansrv.c */ extern tbus g_exec_mutex; /* in chansrv.c */ diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 8a7b762b..4ac5a2b9 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -52,11 +52,12 @@ #include "chansrv.h" #include "list.h" #include "smartcard_pcsc.h" +#include "xrdp_sockets.h" #if PCSC_STANDIN -extern int g_display_num; /* in chansrv.c */ +extern char g_display_str[]; /* in chansrv.c */ static int g_autoinc = 0; /* general purpose autoinc */ @@ -1982,7 +1983,6 @@ int scard_pcsc_init(void) { char *home; - int disp; int error; LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_pcsc_init:"); @@ -1992,8 +1992,8 @@ scard_pcsc_init(void) // TODO: See #2501. Use needs a way to move PCSCLITE_CSOCK_NAME // to a location not under $HOME. home = g_getenv("HOME"); - disp = g_display_num; - g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp); + g_snprintf(g_pcsclite_ipc_dir, sizeof(g_pcsclite_ipc_dir), + "%s/.pcsc%s", home, g_display_str); if (g_directory_exist(g_pcsclite_ipc_dir)) { @@ -2015,7 +2015,8 @@ scard_pcsc_init(void) /* Only the current user should be able to access the remote * smartcard */ g_chmod_hex(g_pcsclite_ipc_dir, 0x700); - g_snprintf(g_pcsclite_ipc_file, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir); + g_snprintf(g_pcsclite_ipc_file, sizeof(g_pcsclite_ipc_file), + "%s/pcscd.comm", g_pcsclite_ipc_dir); g_lis->trans_conn_in = my_pcsc_trans_conn_in; error = trans_listen(g_lis, g_pcsclite_ipc_file); if (error != 0) diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index a67628b7..4a285b0f 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -63,7 +63,7 @@ static lame_global_flags *g_lame_encoder = 0; #endif extern int g_rdpsnd_chan_id; /* in chansrv.c */ -extern int g_display_num; /* in chansrv.c */ +extern char g_display_str[]; /* in chansrv.c */ extern struct config_chansrv *g_cfg; /* in chansrv.c */ /* audio out: sound_server -> xrdp -> NeutrinoRDP */ @@ -1903,7 +1903,8 @@ sound_start_source_listener(void) g_audio_l_trans_in = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); g_audio_l_trans_in->is_term = g_is_term; - g_snprintf(port, sizeof(port), CHANSRV_PORT_IN_STR, g_getuid(), g_display_num); + g_snprintf(port, sizeof(port), CHANSRV_PORT_IN_STR, g_getuid(), + g_display_str); g_audio_l_trans_in->trans_conn_in = sound_sndsrvr_source_conn_in; if (trans_listen(g_audio_l_trans_in, port) != 0) { @@ -1922,7 +1923,8 @@ sound_start_sink_listener(void) g_audio_l_trans_out = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); g_audio_l_trans_out->is_term = g_is_term; - g_snprintf(port, sizeof(port), CHANSRV_PORT_OUT_STR, g_getuid(), g_display_num); + g_snprintf(port, sizeof(port), CHANSRV_PORT_OUT_STR, g_getuid(), + g_display_str); g_audio_l_trans_out->trans_conn_in = sound_sndsrvr_sink_conn_in; if (trans_listen(g_audio_l_trans_out, port) != 0) { diff --git a/sesman/eicp_process.c b/sesman/eicp_process.c index 959fc33b..f659229a 100644 --- a/sesman/eicp_process.c +++ b/sesman/eicp_process.c @@ -100,12 +100,12 @@ static int process_create_session_response(struct scp_list_item *sli) { struct session_item *s_item; - int display; + const char *display; struct guid guid; enum scp_screate_status status; int rv = eicp_get_create_session_response(sli->sesexec_trans, - &status, &guid); + &status, &display, &guid); if (rv == 0) { // Create an entry on the session list for the new session @@ -130,8 +130,7 @@ process_create_session_response(struct scp_list_item *sli) s_item->sesexec_pid = sli->sesexec_pid; s_item->guid = guid; s_item->uid = sli->uid; - s_item->display = sli->session_display; - display = s_item->display; + strlcpy(s_item->display, display, sizeof(s_item->display)); // We don't use the sesexec process again sli->sesexec_trans = NULL; @@ -140,12 +139,12 @@ process_create_session_response(struct scp_list_item *sli) else { guid_clear(&guid); - display = -1; + display = ""; } rv = scp_send_create_session_response(sli->client_trans, status, display, &guid); sli->create_session_in_progress = 0; - sli->session_display = -1; + sli->session_x11_display = -1; } return rv; diff --git a/sesman/ercp_process.c b/sesman/ercp_process.c index da42f1d7..6f00e2bc 100644 --- a/sesman/ercp_process.c +++ b/sesman/ercp_process.c @@ -44,7 +44,7 @@ process_session_announce_event(struct session_item *si) int rv; const char *start_ip_addr; const char *instance_name; - unsigned int display; + const char *display; rv = ercp_get_session_announce_event(si->sesexec_trans, &display, @@ -57,30 +57,19 @@ process_session_announce_event(struct session_item *si) &start_ip_addr, &si->start_time, &instance_name); - if (rv == 0) - { - // We may already know the display we sent sesexec. If we do, - // check sesexec sent the same value back. - if (si->display >= 0 && display != (unsigned int)si->display) - { - LOG(LOG_LEVEL_ERROR, "Bugcheck: sesman expected display %d, got %u", - si->display, display); - rv = 1; - } - } if (rv == 0) { snprintf(si->start_ip_addr, sizeof(si->start_ip_addr), "%s", start_ip_addr); + strlcpy(si->display, display, sizeof(si->display)); snprintf(si->xrdp_instance_name, sizeof(si->xrdp_instance_name), "%s", instance_name); - si->display = display; si->state = E_SESSION_RUNNING; LOG(LOG_LEVEL_INFO, - "sesman: Session on display :%d is now running", si->display); + "sesman: Session on display %s is now running", si->display); } return rv; @@ -90,7 +79,7 @@ process_session_announce_event(struct session_item *si) static void process_session_finished_event(struct session_item *si) { - LOG(LOG_LEVEL_INFO, "sesman: Session on display :%d has finished.", + LOG(LOG_LEVEL_INFO, "sesman: Session on display %s has finished.", si->display); // Setting the transport down will remove this connection from the list si->sesexec_trans->status = TRANS_STATUS_DOWN; @@ -113,7 +102,7 @@ process_client_connect_event(struct session_item *si) strlcpy(si->client_name, client_name, sizeof(si->client_name)); si->last_connect_disconnect = connect_time; LOG(LOG_LEVEL_INFO, - "sesman: Session on display :%d is connected from client '%s'", + "sesman: Session on display %s is connected from client '%s'", si->display, si->client_name); } @@ -134,7 +123,7 @@ process_client_disconnect_event(struct session_item *si) si->client_name[0] = '\0'; si->last_connect_disconnect = disconnect_time; LOG(LOG_LEVEL_INFO, - "sesman: Session on display :%d has no client connection", + "sesman: Session on display %s has no client connection", si->display); } diff --git a/sesman/scp_list.c b/sesman/scp_list.c index ab278d1b..acf9b621 100644 --- a/sesman/scp_list.c +++ b/sesman/scp_list.c @@ -126,7 +126,7 @@ scp_list_item_new(void) { g_snprintf(result->peername, sizeof(result->peername), "unknown"); result->uid = (uid_t) -1; - result->session_display = -1; + result->session_x11_display = -1; if (!list_add_item(g_scp_list, (tintptr)result)) { g_free(result); @@ -263,7 +263,7 @@ scp_list_check_wait_objs(void) /******************************************************************************/ void -scp_list_get_create_session_displays(struct set_int *alloc_displays) +scp_list_get_create_session_x11_displays(struct set_int *alloc_displays) { int i = 0; for (i = 0; i < g_scp_list->count; ++i) @@ -272,10 +272,12 @@ scp_list_get_create_session_displays(struct set_int *alloc_displays) sli = (struct scp_list_item *)list_get_item(g_scp_list, i); + // Only add X11 displays if (SCP_LIST_ITEM_IN_USE(sli) && - sli->create_session_in_progress) + sli->create_session_in_progress && + sli->session_x11_display >= 0) { - set_int_add(alloc_displays, sli->session_display); + set_int_add(alloc_displays, sli->session_x11_display); } } } diff --git a/sesman/scp_list.h b/sesman/scp_list.h index 32907ccf..fd356a8a 100644 --- a/sesman/scp_list.h +++ b/sesman/scp_list.h @@ -87,8 +87,8 @@ struct scp_list_item char xrdp_instance_name[MAX_XRDP_INSTANCE_NAMELEN]; ///< Instance name associated with session int is_admin; int create_session_in_progress; ///< Already handling a create_session - /// Display allocated for session. This is always valid (>= 0) - unsigned int session_display; + /// X11 display allocated for session (-1 if N/A) + int session_x11_display; }; @@ -158,11 +158,11 @@ int scp_list_check_wait_objs(void); /** - * @brief Get all create-session displays + * @brief Get all create-session X11 displays * - * Adds displays allocated to create-session operations to a set + * Adds X11 displays allocated to create-session operations to a set */ void -scp_list_get_create_session_displays(struct set_int *alloc_displays); +scp_list_get_create_session_x11_displays(struct set_int *alloc_displays); #endif // SCP_LIST_H diff --git a/sesman/scp_process.c b/sesman/scp_process.c index a1f65f05..874fca6f 100644 --- a/sesman/scp_process.c +++ b/sesman/scp_process.c @@ -414,8 +414,8 @@ get_free_display(void) { // Get all the displays either allocated to sessions, or // potentially assigned to sessions on the SCP list - session_list_get_session_displays(alloc_displays); - scp_list_get_create_session_displays(alloc_displays); + session_list_get_session_x11_displays(alloc_displays); + scp_list_get_create_session_x11_displays(alloc_displays); // Find a free display, taking the allocated ones into account result = display_utils_get_free_display(alloc_displays); @@ -442,7 +442,8 @@ process_create_session_request(struct scp_list_item *sli) const char *instance_name; struct guid guid; - int display = -1; + const char *display; + int x11_display = -1; struct session_item *s_item = NULL; int start_sesexec = (sli->sesexec_trans == NULL); int send_client_reply = 1; @@ -476,7 +477,7 @@ process_create_session_request(struct scp_list_item *sli) { // Found an existing session LOG(LOG_LEVEL_INFO, - "A suitable session on display :%d is already active", + "A suitable session on display %s is already active", s_item->display); display = s_item->display; guid = s_item->guid; @@ -489,10 +490,11 @@ process_create_session_request(struct scp_list_item *sli) "The maximum number of sessions has been reached"); status = E_SCP_SCREATE_MAX_REACHED; } - else if ((display = get_free_display()) < 0) + else if (SCP_SESSION_TYPE_IS_X11(type) && + (x11_display = get_free_display()) < 0) { LOG(LOG_LEVEL_ERROR, - "No free display can be found for a new session"); + "No free X11 display can be found for a new session"); status = E_SCP_SCREATE_NO_DISPLAY; } // Create a socket dir for this user @@ -532,7 +534,7 @@ process_create_session_request(struct scp_list_item *sli) int eicp_stat; eicp_stat = eicp_send_create_session_request( sli->sesexec_trans, - display, + x11_display, type, width, height, bpp, shell, directory, instance_name); @@ -551,7 +553,7 @@ process_create_session_request(struct scp_list_item *sli) // We're not sending a reply yet send_client_reply = 0; sli->create_session_in_progress = 1; - sli->session_display = display; // Reserve display + sli->session_x11_display = x11_display; // Reserve display } } } @@ -560,7 +562,7 @@ process_create_session_request(struct scp_list_item *sli) { if (status != E_SCP_SCREATE_OK) { - display = -1; + display = ""; guid_clear(&guid); } rv = scp_send_create_session_response(sli->client_trans, diff --git a/sesman/sesexec/eicp_server.c b/sesman/sesexec/eicp_server.c index b9fa6384..03f589f4 100644 --- a/sesman/sesexec/eicp_server.c +++ b/sesman/sesexec/eicp_server.c @@ -148,13 +148,14 @@ handle_create_session_request(struct trans *self) int status; status = eicp_get_create_session_request( - self, &sp.display, + self, &sp.x11_display, &sp.type, &sp.width, &sp.height, &sp.bpp, &sp.shell, &sp.directory, &sp.instance_name); if (status == 0) { enum scp_screate_status scp_status = E_SCP_SCREATE_OK; + const char *display = ""; // Must be logged in to start a session if (g_login_info == NULL) @@ -166,10 +167,15 @@ handle_create_session_request(struct trans *self) // Try to create the session sp.guid = guid_new(); scp_status = session_start(g_login_info, &sp, &g_session_data); + if (scp_status == E_SCP_SCREATE_OK) + { + display = session_get_display(g_session_data); + } } // Return the creation status to sesman. - status = eicp_send_create_session_response(self, scp_status, &sp.guid); + status = eicp_send_create_session_response(self, scp_status, display, + &sp.guid); if (status == 0 && scp_status == E_SCP_SCREATE_OK) { // Further comms to sesman is sent over the ERCP protocol @@ -178,7 +184,7 @@ handle_create_session_request(struct trans *self) // Announce the session to sesman if ((status = ercp_send_session_announce_event( self, - sp.display, + display, g_login_info->uid, sp.type, sp.width, diff --git a/sesman/sesexec/env.c b/sesman/sesexec/env.c index 747ae5ad..96f4f00b 100644 --- a/sesman/sesexec/env.c +++ b/sesman/sesexec/env.c @@ -36,95 +36,24 @@ #include "log.h" #include "os_calls.h" #include "sesexec.h" -#include "ssl_calls.h" -#include "string_calls.h" #include "xrdp_sockets.h" /******************************************************************************/ int -env_check_password_file(const char *filename, const char *passwd) -{ - char encryptedPasswd[16]; - char key[24]; - char passwd_hash[20]; - char passwd_hash_text[40]; - int fd; - int passwd_bytes; - void *des; - void *sha1; - - if (filename == NULL) - { - LOG(LOG_LEVEL_WARNING, "Cannot write VNC password hash to NULL file"); - return 1; - } - - /* - * If we're in FIPS mode, do not write the GUID to disk after it's - * been encrypted with an insecure algorithm. - */ - if (g_fips_mode_enabled()) - { - LOG(LOG_LEVEL_ERROR, "Can't create VNC password file in FIPS mode"); - return 1; - } - /* create password hash from password */ - passwd_bytes = (passwd == NULL) ? 0 : strlen(passwd); - sha1 = ssl_sha1_info_create(); - ssl_sha1_clear(sha1); - ssl_sha1_transform(sha1, "xrdp_vnc", 8); - ssl_sha1_transform(sha1, passwd, passwd_bytes); - ssl_sha1_transform(sha1, passwd, passwd_bytes); - ssl_sha1_complete(sha1, passwd_hash); - ssl_sha1_info_delete(sha1); - g_snprintf(passwd_hash_text, sizeof(passwd_hash_text), - "%2.2x%2.2x%2.2x%2.2x", - (tui8)passwd_hash[0], (tui8)passwd_hash[1], - (tui8)passwd_hash[2], (tui8)passwd_hash[3]); - passwd = passwd_hash_text; - - /* create file from password */ - g_memset(encryptedPasswd, 0, sizeof(encryptedPasswd)); - g_strncpy(encryptedPasswd, passwd, 8); - g_memset(key, 0, sizeof(key)); - g_mirror_memcpy(key, g_fixedkey, 8); - des = ssl_des3_encrypt_info_create(key, 0); - ssl_des3_encrypt(des, 8, encryptedPasswd, encryptedPasswd); - ssl_des3_info_delete(des); - fd = g_file_open_ex(filename, 0, 1, 1, 1); - if (fd == -1) - { - LOG(LOG_LEVEL_WARNING, - "Cannot write VNC password hash to file %s: %s", - filename, g_get_strerror()); - return 1; - } - g_file_write(fd, encryptedPasswd, 8); - g_file_close(fd); - return 0; -} - -/******************************************************************************/ -/* its the responsibility of the caller to free passwd_file */ -int -env_set_user(int uid, char **passwd_file, int display, +env_set_user(int uid, const struct list *env_names, const struct list *env_values) { int error; int pw_gid; int index; - int len; char *name; char *value; - char *pw_username; - char *pw_shell; - char *pw_dir; + char *pw_username = NULL; + char *pw_shell = NULL; + char *pw_dir = NULL; + char *display = NULL; + int is_x11 = 0; char text[256]; - char hostname[256]; - - pw_username = 0; - pw_shell = 0; - pw_dir = 0; error = g_getuser_info_by_uid(uid, &pw_username, &pw_gid, &pw_shell, &pw_dir, 0); @@ -162,27 +91,15 @@ env_set_user(int uid, char **passwd_file, int display, g_setenv_log("UID", text, 1); g_setenv_log("HOME", pw_dir, 1); g_set_current_dir(pw_dir); - g_snprintf(text, sizeof(text), ":%d.0", display); - g_setenv_log("DISPLAY", text, 1); // Use our PID as the XRDP_SESSION value g_snprintf(text, sizeof(text), "%d", g_pid); g_setenv_log("XRDP_SESSION", text, 1); - /* XRDP_SOCKET_PATH should be set here. It's used by + /* XRDP_SOCKET_PATH is used by * xorgxrdp and the pulseaudio plugin */ g_snprintf(text, sizeof(text), XRDP_SOCKET_PATH, uid); g_setenv_log("XRDP_SOCKET_PATH", text, 1); - /* pulse sink socket */ - g_snprintf(text, sizeof(text), CHANSRV_PORT_OUT_BASE_STR, display); - g_setenv_log("XRDP_PULSE_SINK_SOCKET", text, 1); - /* pulse source socket */ - g_snprintf(text, sizeof(text), CHANSRV_PORT_IN_BASE_STR, display); - g_setenv_log("XRDP_PULSE_SOURCE_SOCKET", text, 1); - if (g_cfg->sec.xauth_in_sysdir) - { - g_snprintf(text, sizeof(text), XRDP_SOCKET_PATH "/Xauthority", - uid); - g_setenv_log("XAUTHORITY", text, 1); - } + + // Set the passed-in variables. This may include a DISPLAY if ((env_names != 0) && (env_values != 0) && (env_names->count == env_values->count)) { @@ -191,80 +108,42 @@ env_set_user(int uid, char **passwd_file, int display, name = (char *) list_get_item(env_names, index), value = (char *) list_get_item(env_values, index), g_setenv_log(name, value, 1); + + // Look for a DISPLAY. WAYLAND_DISPLAY overrides + // DISPLAY + if (strcmp(name, "WAYLAND_DISPLAY") == 0) + { + display = value; + is_x11 = 0; + } + else if (display == NULL && strcmp(name, "DISPLAY") == 0) + { + display = value; + is_x11 = 1; + } } } - g_gethostname(hostname, 255); - hostname[255] = 0; - if (passwd_file != 0) + + // Set things dependent on the DISPLAY + if (display != NULL) { - if (0 == g_cfg->auth_file_path) + /* pulse sink socket */ + g_snprintf(text, sizeof(text), CHANSRV_PORT_OUT_BASE_STR, + display); + g_setenv_log("XRDP_PULSE_SINK_SOCKET", text, 1); + /* pulse source socket */ + g_snprintf(text, sizeof(text), CHANSRV_PORT_IN_BASE_STR, + display); + g_setenv_log("XRDP_PULSE_SOURCE_SOCKET", text, 1); + + // Only set Xauthority for X11 + if (is_x11 && g_cfg->sec.xauth_in_sysdir) { - /* if no auth_file_path is set, then we go for - $HOME/.vnc/sesman_passwd-USERNAME@HOSTNAME:DISPLAY */ - if (!g_directory_exist(".vnc")) - { - if (g_mkdir(".vnc") < 0) - { - LOG(LOG_LEVEL_ERROR, - "Error creating .vnc directory: %s", - g_get_strerror()); - } - } - - len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, pw_username, hostname, display); - ++len; // Allow for terminator - - *passwd_file = (char *) g_malloc(len, 1); - if (*passwd_file != NULL) - { - /* Try legacy names first, remove if found */ - g_snprintf(*passwd_file, len, - "%s/.vnc/sesman_%s_passwd:%d", - pw_dir, pw_username, display); - if (g_file_exist(*passwd_file)) - { - LOG(LOG_LEVEL_WARNING, "Removing old " - "password file %s", *passwd_file); - g_file_delete(*passwd_file); - } - g_snprintf(*passwd_file, len, - "%s/.vnc/sesman_%s_passwd", - pw_dir, pw_username); - if (g_file_exist(*passwd_file)) - { - LOG(LOG_LEVEL_WARNING, "Removing insecure " - "password file %s", *passwd_file); - g_file_delete(*passwd_file); - } - g_snprintf(*passwd_file, len, - "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, pw_username, hostname, display); - } - } - else - { - /* we use auth_file_path as requested */ - len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); - - ++len; // Allow for terminator - *passwd_file = (char *) g_malloc(len, 1); - if (*passwd_file != NULL) - { - g_snprintf(*passwd_file, len, - g_cfg->auth_file_path, pw_username); - } - } - - if (*passwd_file != NULL) - { - LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", *passwd_file); + g_snprintf(text, sizeof(text), + XRDP_SOCKET_PATH "/Xauthority", uid); + g_setenv_log("XAUTHORITY", text, 1); } } - - g_free(pw_username); - g_free(pw_dir); - g_free(pw_shell); } } else @@ -273,5 +152,9 @@ env_set_user(int uid, char **passwd_file, int display, "error getting user info for uid %d", uid); } + g_free(pw_username); + g_free(pw_dir); + g_free(pw_shell); + return error; } diff --git a/sesman/sesexec/env.h b/sesman/sesexec/env.h index 615285bb..521d46c2 100644 --- a/sesman/sesexec/env.h +++ b/sesman/sesexec/env.h @@ -44,13 +44,13 @@ env_check_password_file(const char *filename, const char *password); * * @brief Sets user environment ($PATH, $HOME, $UID, and others) * @param uid user ID - * @param passwd_file VNC password file - * @param display The session display + * @param env_names List of session environment variables to set + * @param env_values List of session environment values to set * @return 0 on success, g_getuser_info() error codes on error * */ int -env_set_user(int uid, char **passwd_file, int display, +env_set_user(int uid, const struct list *env_names, const struct list *env_values); #endif diff --git a/sesman/sesexec/sesexec_discover.c b/sesman/sesexec/sesexec_discover.c index 27b35733..b182c340 100644 --- a/sesman/sesexec/sesexec_discover.c +++ b/sesman/sesexec/sesexec_discover.c @@ -92,7 +92,7 @@ discover_trans_conn_in(struct trans *trans, struct trans *new_trans) { (void)ercp_send_session_announce_event( new_trans, - sp->display, + session_get_display(g_session_data), g_login_info->uid, sp->type, sp->width, @@ -143,9 +143,9 @@ sesexec_discover_enable(void) { char discover_port[XRDP_SOCKETS_MAXPATH]; - snprintf(discover_port, sizeof(discover_port), "%s.r/%u", + snprintf(discover_port, sizeof(discover_port), "%s.r/%s", g_cfg->listen_port, - session_get_parameters(g_session_data)->display); + session_get_display(g_session_data)); g_discover_trans->is_term = sesexec_is_term; g_discover_trans->trans_conn_in = discover_trans_conn_in; if ((rv = trans_listen(g_discover_trans, discover_port)) != 0) diff --git a/sesman/sesexec/session.c b/sesman/sesexec/session.c index 899faac4..ebf0250d 100644 --- a/sesman/sesexec/session.c +++ b/sesman/sesexec/session.c @@ -49,6 +49,7 @@ #include "os_calls.h" #include "sesexec.h" #include "sessionrecord.h" +#include "ssl_calls.h" #include "string_calls.h" #include "trans.h" #include "xauth.h" @@ -62,6 +63,7 @@ struct session_data pid_t chansrv; ///< PID of chansrv time_t start_time; unsigned int connect_count; + char display[MAX_DISPLAY_NAME_SIZE]; // Set by session_start() struct session_parameters params; // Flexible array member used to store strings in params and ip_addr; #ifdef __cplusplus @@ -189,7 +191,7 @@ dumpItemsToString(struct list *self, char *outstr, int len) /******************************************************************************/ static void start_chansrv(const struct login_info *login_info, - const struct session_parameters *s, + const struct session_data *sd, void *closure /* unused */) { struct list *chansrv_params = list_create(); @@ -211,7 +213,7 @@ start_chansrv(const struct login_info *login_info, } else { - env_set_user(login_info->uid, 0, s->display, + env_set_user(login_info->uid, g_cfg->env_names, g_cfg->env_values); @@ -228,36 +230,35 @@ start_chansrv(const struct login_info *login_info, /******************************************************************************/ static void start_window_manager(const struct login_info *login_info, - const struct session_parameters *s, + const struct session_data *sd, void *closure /* unused */) { char text[256]; + const struct session_parameters *sp = &sd->params; env_set_user(login_info->uid, - 0, - s->display, g_cfg->env_names, g_cfg->env_values); auth_set_env(login_info->auth_info); LOG_DEVEL_LEAKING_FDS("window manager", 3, -1); - if (s->directory[0] != '\0') + if (sp->directory[0] != '\0') { if (g_cfg->sec.allow_alternate_shell) { - g_set_current_dir(s->directory); + g_set_current_dir(sp->directory); } else { LOG(LOG_LEVEL_WARNING, "Directory change to %s requested, but not " "allowed by AllowAlternateShell config value.", - s->directory); + sp->directory); } } - if (s->shell[0] != '\0') + if (sp->shell[0] != '\0') { if (g_cfg->sec.allow_alternate_shell) { @@ -269,27 +270,28 @@ start_window_manager(const struct login_info *login_info, LOG(LOG_LEVEL_INFO, "Setting variable '%s' to the specified shell of '%s'", g_cfg->sec.pass_shell_as_env, - s->shell); - g_setenv_log(g_cfg->sec.pass_shell_as_env, s->shell, 1); + sp->shell); + g_setenv_log(g_cfg->sec.pass_shell_as_env, sp->shell, 1); } else { // Try to execute the shell directly (if permitted) - if (g_strchr(s->shell, ' ') != 0 || g_strchr(s->shell, '\t') != 0) + if (g_strchr(sp->shell, ' ') != 0 || + g_strchr(sp->shell, '\t') != 0) { LOG(LOG_LEVEL_INFO, "Using user requested window manager on " - "display %u with embedded arguments using a shell: %s", - s->display, s->shell); - const char *argv[] = {"sh", "-c", s->shell, NULL}; + "display %s with embedded arguments using a shell: %s", + sd->display, sp->shell); + const char *argv[] = {"sh", "-c", sp->shell, NULL}; g_execvp("/bin/sh", (char **)argv); } else { LOG(LOG_LEVEL_INFO, "Using user requested window manager on " - "display %d: %s", s->display, s->shell); - g_execlp3(s->shell, s->shell, 0); + "display %s %s", sd->display, sp->shell); + g_execlp3(sp->shell, sp->shell, 0); } } } @@ -298,13 +300,13 @@ start_window_manager(const struct login_info *login_info, LOG(LOG_LEVEL_WARNING, "Shell %s requested by user, but not allowed by " "AllowAlternateShell config value.", - s->shell); + sp->shell); } } else { - LOG(LOG_LEVEL_DEBUG, "The user session on display %u did " - "not request a specific window manager", s->display); + LOG(LOG_LEVEL_DEBUG, "The user session on display %s did " + "not request a specific window manager", sd->display); } /* try to execute user window manager if enabled */ @@ -315,8 +317,8 @@ start_window_manager(const struct login_info *login_info, if (g_file_exist(text)) { LOG(LOG_LEVEL_INFO, - "Using window manager on display %u" - " from user home directory: %s", s->display, text); + "Using window manager on display %s" + " from user home directory: %s", sd->display, text); g_execlp3(text, g_cfg->user_wm, 0); } else @@ -329,26 +331,26 @@ start_window_manager(const struct login_info *login_info, } LOG(LOG_LEVEL_INFO, - "Using the default window manager on display %u: %s", - s->display, g_cfg->default_wm); + "Using the default window manager on display %s: %s", + sd->display, g_cfg->default_wm); g_execlp3(g_cfg->default_wm, g_cfg->default_wm, 0); /* still a problem starting window manager just start xterm */ LOG(LOG_LEVEL_WARNING, - "No window manager on display %u started, " + "No window manager on display %s started, " "so falling back to starting xterm for user debugging", - s->display); + sd->display); g_execlp3("xterm", "xterm", 0); /* should not get here */ LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting to start " - "the window manager on display %u, aborting connection", - s->display); + "the window manager on display %s, aborting connection", + sd->display); } /******************************************************************************/ static struct list * -prepare_xorg_xserver_params(const struct session_parameters *s, +prepare_xorg_xserver_params(const struct session_data *sd, const char *authfile) { @@ -369,18 +371,18 @@ prepare_xorg_xserver_params(const struct session_parameters *s, if (g_cfg->sec.xorg_no_new_privileges && g_no_new_privs() != 0) { LOG(LOG_LEVEL_WARNING, - "[session start] (display %u): Failed to disable " + "[session start] (display :%d): Failed to disable " "setuid on X server: %s", - s->display, g_get_strerror()); + sd->params.x11_display, g_get_strerror()); } - g_snprintf(screen, sizeof(screen), ":%u", s->display); + g_snprintf(screen, sizeof(screen), ":%d", sd->params.x11_display); /* some args are passed via env vars */ - g_snprintf(text, sizeof(text), "%d", s->width); + g_snprintf(text, sizeof(text), "%d", sd->params.width); g_setenv_log("XRDP_START_WIDTH", text, 1); - g_snprintf(text, sizeof(text), "%d", s->height); + g_snprintf(text, sizeof(text), "%d", sd->params.height); g_setenv_log("XRDP_START_HEIGHT", text, 1); g_snprintf(text, sizeof(text), "%d", g_cfg->sess.max_idle_time); @@ -408,10 +410,180 @@ prepare_xorg_xserver_params(const struct session_parameters *s, return params; } +/******************************************************************************/ +/** + * Create an Xvnc password file + * + * @param x11_display X11 display number + * @return Name of passwd file, or NULL if no memory. + * + * env_set_user() must be called before calling this function + */ +static char * +get_xvnc_passwd_file_name(int x11_display) +{ + char *result = NULL; + int len; + + char *pw_username = NULL; + char *pw_dir = NULL; + char hostname[256]; + int error; + + /* Get parameters needed for VNC filename */ + hostname[sizeof(hostname) - 1] = '\0'; + g_gethostname(hostname, sizeof(hostname)); + error = g_getuser_info_by_uid(g_getuid(), &pw_username, 0, 0, &pw_dir, 0); + + if (error != 0 || pw_username == NULL || pw_dir == NULL) + { + LOG(LOG_LEVEL_ERROR, "Can't get parameters for XVnc passwd file"); + } + else + { + if (0 == g_cfg->auth_file_path) + { + /* if no auth_file_path is set, then we go for + $HOME/.vnc/sesman_passwd-USERNAME@HOSTNAME:DISPLAY */ + if (!g_directory_exist(".vnc")) + { + if (g_mkdir(".vnc") < 0) + { + LOG(LOG_LEVEL_ERROR, + "Error creating .vnc directory: %s", + g_get_strerror()); + } + } + + len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", + pw_dir, pw_username, hostname, x11_display); + ++len; // Allow for terminator + + result = (char *) g_malloc(len, 1); + if (result != NULL) + { + /* Try legacy names first, remove if found */ + g_snprintf(result, len, + "%s/.vnc/sesman_%s_passwd:%d", + pw_dir, pw_username, x11_display); + if (g_file_exist(result)) + { + LOG(LOG_LEVEL_WARNING, "Removing old " + "password file %s", result); + g_file_delete(result); + } + g_snprintf(result, len, + "%s/.vnc/sesman_%s_passwd", + pw_dir, pw_username); + if (g_file_exist(result)) + { + LOG(LOG_LEVEL_WARNING, "Removing insecure " + "password file %s", result); + g_file_delete(result); + } + g_snprintf(result, len, + "%s/.vnc/sesman_passwd-%s@%s:%d", + pw_dir, pw_username, hostname, x11_display); + } + } + else + { + /* we use auth_file_path as requested */ + len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); + + ++len; // Allow for terminator + result = (char *) g_malloc(len, 1); + if (result != NULL) + { + g_snprintf(result, len, + g_cfg->auth_file_path, pw_username); + } + } + + if (result == NULL) + { + LOG(LOG_LEVEL_ERROR, + "Can't allocate memory for Xvnc passwd file name"); + } + else + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", result); + } + } + g_free(pw_username); + g_free(pw_dir); + + return result; +} + +/******************************************************************************/ +static int +set_xvnc_passwd(const char *filename, const char *passwd) +{ + char encryptedPasswd[16]; + char key[24]; + char passwd_hash[20]; + char passwd_hash_text[40]; + int fd; + int passwd_bytes; + void *des; + void *sha1; + + if (filename == NULL) + { + LOG(LOG_LEVEL_WARNING, "Cannot write VNC password hash to NULL file"); + return 1; + } + + /* + * If we're in FIPS mode, do not write the GUID to disk after it's + * been encrypted with an insecure algorithm. + */ + if (g_fips_mode_enabled()) + { + LOG(LOG_LEVEL_ERROR, "Can't create VNC password file in FIPS mode"); + return 1; + } + /* create password hash from password */ + passwd_bytes = (passwd == NULL) ? 0 : strlen(passwd); + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, "xrdp_vnc", 8); + ssl_sha1_transform(sha1, passwd, passwd_bytes); + ssl_sha1_transform(sha1, passwd, passwd_bytes); + ssl_sha1_complete(sha1, passwd_hash); + ssl_sha1_info_delete(sha1); + g_snprintf(passwd_hash_text, sizeof(passwd_hash_text), + "%2.2x%2.2x%2.2x%2.2x", + (tui8)passwd_hash[0], (tui8)passwd_hash[1], + (tui8)passwd_hash[2], (tui8)passwd_hash[3]); + passwd = passwd_hash_text; + + /* create file from password */ + g_memset(encryptedPasswd, 0, sizeof(encryptedPasswd)); + g_strncpy(encryptedPasswd, passwd, 8); + g_memset(key, 0, sizeof(key)); + g_mirror_memcpy(key, g_fixedkey, 8); + des = ssl_des3_encrypt_info_create(key, 0); + ssl_des3_encrypt(des, 8, encryptedPasswd, encryptedPasswd); + ssl_des3_info_delete(des); + fd = g_file_open_ex(filename, 0, 1, 1, 1); + if (fd == -1) + { + LOG(LOG_LEVEL_WARNING, + "Cannot write VNC password hash to file %s: %s", + filename, g_get_strerror()); + return 1; + } + g_file_write(fd, encryptedPasswd, 8); + g_file_close(fd); + return 0; +} + /******************************************************************************/ /** * Prepare a list of parameters for the Xvnc X server - * @param s Session parameters + * @param sd Session data * @param authfile XAUTHORITY file * @param passwd_file VNC password file, or NULL * @param port UDS port to connect to, or NULL @@ -420,7 +592,7 @@ prepare_xorg_xserver_params(const struct session_parameters *s, * One of passwd_file and port must be set */ static struct list * -prepare_xvnc_xserver_params(const struct session_parameters *s, +prepare_xvnc_xserver_params(const struct session_data *sd, const char *authfile, const char *passwd_file, const char *port) @@ -428,19 +600,17 @@ prepare_xvnc_xserver_params(const struct session_parameters *s, char screen[32] = {0}; /* display number */ char geometry[32] = {0}; char depth[32] = {0}; - char guid_str[GUID_STR_SIZE]; const char *xserver; + const struct session_parameters *sp = &sd->params; struct list *params = list_create(); if (params != NULL) { params->auto_free = 1; - g_snprintf(screen, sizeof(screen), ":%u", s->display); - g_snprintf(geometry, sizeof(geometry), "%dx%d", s->width, s->height); - g_snprintf(depth, sizeof(depth), "%d", s->bpp); - - guid_to_str(&s->guid, guid_str); + g_snprintf(screen, sizeof(screen), ":%d", sp->x11_display); + g_snprintf(geometry, sizeof(geometry), "%dx%d", sp->width, sp->height); + g_snprintf(depth, sizeof(depth), "%d", sp->bpp); /* get path of Xvnc from config */ xserver = (const char *)list_get_item(g_cfg->vnc_params, 0); @@ -456,7 +626,6 @@ prepare_xvnc_xserver_params(const struct session_parameters *s, if (passwd_file != NULL) { /* RFB authorization */ - env_check_password_file(passwd_file, guid_str); list_add_strdup_multi(params, "-rfbauth", passwd_file, LIST_ADD_STRDUP_TERM); @@ -493,7 +662,7 @@ prepare_xvnc_xserver_params(const struct session_parameters *s, /* Either execs the X server, or returns */ static void start_x_server(const struct login_info *login_info, - const struct session_parameters *s, + const struct session_data *sd, void *closure /* unused */) { char authfile[256]; /* The filename for storing xauth information */ @@ -501,22 +670,19 @@ start_x_server(const struct login_info *login_info, char *passwd_file = NULL; struct list *xserver_params = NULL; int unknown_session_type = 0; + const struct session_parameters *sp = &sd->params; - if (s->type == SCP_SESSION_TYPE_XVNC) + env_set_user(login_info->uid, + g_cfg->env_names, + g_cfg->env_values); + + if (sp->type == SCP_SESSION_TYPE_XVNC) { - env_set_user(login_info->uid, - &passwd_file, - s->display, - g_cfg->env_names, - g_cfg->env_values); - } - else - { - env_set_user(login_info->uid, - 0, - s->display, - g_cfg->env_names, - g_cfg->env_values); + char guid_str[GUID_STR_SIZE]; + passwd_file = get_xvnc_passwd_file_name(sp->x11_display); + + guid_to_str(&sp->guid, guid_str); + set_xvnc_passwd(passwd_file, guid_str); } /* prepare the Xauthority stuff */ @@ -531,31 +697,32 @@ start_x_server(const struct login_info *login_info, } /* Add the entry in XAUTHORITY file or exit if error */ - if (add_xauth_cookie(s->display, authfile) != 0) + if (sp->x11_display >= 0 && + add_xauth_cookie(sp->x11_display, authfile) != 0) { LOG(LOG_LEVEL_ERROR, - "Error setting the xauth cookie for display %u in file %s", - s->display, authfile); + "Error setting the xauth cookie for display %s in file %s", + sd->display, authfile); } else { - switch (s->type) + switch (sp->type) { char port[256]; case SCP_SESSION_TYPE_XORG: - xserver_params = prepare_xorg_xserver_params(s, authfile); + xserver_params = prepare_xorg_xserver_params(sd, authfile); break; case SCP_SESSION_TYPE_XVNC: - xserver_params = prepare_xvnc_xserver_params(s, authfile, + xserver_params = prepare_xvnc_xserver_params(sd, authfile, passwd_file, NULL); break; case SCP_SESSION_TYPE_XVNC_UDS: g_snprintf(port, sizeof(port), XRDP_X11RDP_STR, - login_info->uid, s->display); - xserver_params = prepare_xvnc_xserver_params(s, authfile, + login_info->uid, sd->display); + xserver_params = prepare_xvnc_xserver_params(sd, authfile, NULL, port); break; @@ -570,13 +737,13 @@ start_x_server(const struct login_info *login_info, else if (unknown_session_type) { LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", - s->type); + sp->type); } else { /* fire up X server */ - LOG(LOG_LEVEL_INFO, "Starting X server on display %u: %s", - s->display, + LOG(LOG_LEVEL_INFO, "Starting X server on display %s: %s", + sd->display, dumpItemsToString(xserver_params, execvpparams, 2048)); LOG_DEVEL_LEAKING_FDS("X server", 3, -1); g_execvp_list((const char *)xserver_params->items[0], @@ -588,8 +755,8 @@ start_x_server(const struct login_info *login_info, g_free(passwd_file); list_delete(xserver_params); LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting " - "to start the X server on display %u, aborting connection", - s->display); + "to start the X server on display %s, aborting connection", + sd->display); } /******************************************************************************/ @@ -598,10 +765,10 @@ start_x_server(const struct login_info *login_info, static int fork_child( void (*runproc)(const struct login_info *, - const struct session_parameters *, + const struct session_data *, void *closure), const struct login_info *login_info, - const struct session_parameters *s, + const struct session_data *sd, pid_t group_pid, void *closure) { @@ -613,7 +780,7 @@ fork_child( { (void)g_setpgid(0, group_pid); } - runproc(login_info, s, closure); + runproc(login_info, sd, closure); g_exit(0); } @@ -694,7 +861,6 @@ session_start_wrapped(struct login_info *login_info, int display_pid; int window_manager_pid; enum scp_screate_status status = E_SCP_SCREATE_GENERAL_ERROR; - char displaystr[32]; /* Set the secondary groups before starting the session to prevent * problems on PAM-based systems (see Linux pam_setcred(3)). @@ -709,8 +875,7 @@ session_start_wrapped(struct login_info *login_info, } #endif - snprintf(displaystr, sizeof(displaystr), "%d", s->display); - if (auth_start_session(login_info->auth_info, displaystr) != 0) + if (auth_start_session(login_info->auth_info, sd->display) != 0) { // Errors are logged by the auth module, as they are // specific to that module @@ -724,15 +889,15 @@ session_start_wrapped(struct login_info *login_info, if (g_setsid() < 0) { LOG(LOG_LEVEL_WARNING, - "[session start] (display %d): setsid failed - pid %d", - s->display, g_getpid()); + "[session start] (display %s): setsid failed - pid %d", + sd->display, g_getpid()); } if (g_setlogin(login_info->username) < 0) { LOG(LOG_LEVEL_WARNING, - "[session start] (display %d): setlogin failed for user %s - pid %d", - s->display, login_info->username, g_getpid()); + "[session start] (display %s): setlogin failed for user %s - pid %d", + sd->display, login_info->username, g_getpid()); } #endif @@ -743,14 +908,14 @@ session_start_wrapped(struct login_info *login_info, * without affecting sesexec (and vice-versa). This is particularly * important when debugging sesexec as we don't want a SIGINT in * the debugger to be passed to the children */ - display_pid = fork_child(start_x_server, login_info, s, 0, NULL); + display_pid = fork_child(start_x_server, login_info, sd, 0, NULL); if (display_pid > 0) { enum xwait_status xws; xws = wait_for_xserver(login_info->uid, g_cfg->env_names, g_cfg->env_values, - s->display); + s->x11_display); if (xws != XW_STATUS_OK) { @@ -774,12 +939,12 @@ session_start_wrapped(struct login_info *login_info, } else { - LOG(LOG_LEVEL_INFO, "X server :%d is working", s->display); - LOG(LOG_LEVEL_INFO, "Starting window manager for display :%d", - s->display); + LOG(LOG_LEVEL_INFO, "Display %s is working", sd->display); + LOG(LOG_LEVEL_INFO, "Starting window manager for display %s", + sd->display); window_manager_pid = fork_child(start_window_manager, - login_info, s, display_pid, NULL); + login_info, sd, display_pid, NULL); if (window_manager_pid < 0) { g_sigterm(display_pid); @@ -787,15 +952,13 @@ session_start_wrapped(struct login_info *login_info, } else { - char dstr[32]; - g_snprintf(dstr, sizeof(dstr), "%u", s->display); - utmp_login(window_manager_pid, dstr, login_info); + utmp_login(window_manager_pid, sd->display, login_info); LOG(LOG_LEVEL_INFO, - "Starting the xrdp channel server for display :%d", - s->display); + "Starting the xrdp channel server for display %s", + sd->display); chansrv_pid = fork_child(start_chansrv, login_info, - s, display_pid, NULL); + sd, display_pid, NULL); sd->win_mgr = window_manager_pid; sd->x_server = display_pid; @@ -806,9 +969,9 @@ session_start_wrapped(struct login_info *login_info, { // Tell the caller we've started LOG(LOG_LEVEL_INFO, - "Session in progress on display :%d. Waiting until the " + "Session in progress on display %s. Waiting until the " "window manager (pid %d) exits to end the session", - s->display, window_manager_pid); + sd->display, window_manager_pid); status = E_SCP_SCREATE_OK; } @@ -832,7 +995,8 @@ session_start(struct login_info *login_info, const struct session_parameters *sp, struct session_data **session_data) { - enum scp_screate_status status = E_SCP_SCREATE_GENERAL_ERROR; + enum scp_screate_status status = E_SCP_SCREATE_OK; + /* Create the session_data struct first */ struct session_data *sd = session_data_new(sp); if (sd == NULL) @@ -841,15 +1005,38 @@ session_start(struct login_info *login_info, } else { - status = session_start_wrapped(login_info, sp, sd); + if (sp->x11_display >= 0) + { + /* Initialise the display name for logging purposes */ + g_get_display_string_from_x11_display(sp->x11_display, + sd->display, + MAX_DISPLAY_NAME_SIZE); + /* Add the DISPLAY to the list of environment variables we + * set for all the sub-processes */ + char displayname[32]; + snprintf(displayname, sizeof(displayname), ":%d", + sp->x11_display); + + if (!list_add_strdup(g_cfg->env_names, "DISPLAY") || + !list_add_strdup(g_cfg->env_values, displayname)) + { + session_data_free(sd); + status = E_SCP_SCREATE_NO_MEMORY; + } + } + if (status == E_SCP_SCREATE_OK) { - *session_data = sd; - } - else - { - *session_data = NULL; - session_data_free(sd); + status = session_start_wrapped(login_info, sp, sd); + if (status == E_SCP_SCREATE_OK) + { + *session_data = sd; + } + else + { + *session_data = NULL; + session_data_free(sd); + } } } @@ -858,14 +1045,16 @@ session_start(struct login_info *login_info, /******************************************************************************/ static int -cleanup_sockets(int uid, int display) +cleanup_sockets(struct session_data *sd) { LOG_DEVEL(LOG_LEVEL_INFO, "cleanup_sockets:"); char file[XRDP_SOCKETS_MAXPATH]; int error = 0; - g_snprintf(file, sizeof(file), CHANSRV_PORT_OUT_STR, uid, display); + int uid = g_login_info->uid; + + g_snprintf(file, sizeof(file), CHANSRV_PORT_OUT_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -878,7 +1067,7 @@ cleanup_sockets(int uid, int display) } } - g_snprintf(file, sizeof(file), CHANSRV_PORT_IN_STR, uid, display); + g_snprintf(file, sizeof(file), CHANSRV_PORT_IN_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -891,7 +1080,7 @@ cleanup_sockets(int uid, int display) } } - g_snprintf(file, sizeof(file), XRDP_CHANSRV_STR, uid, display); + g_snprintf(file, sizeof(file), XRDP_CHANSRV_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -904,7 +1093,7 @@ cleanup_sockets(int uid, int display) } } - g_snprintf(file, sizeof(file), CHANSRV_API_STR, uid, display); + g_snprintf(file, sizeof(file), CHANSRV_API_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -920,7 +1109,7 @@ cleanup_sockets(int uid, int display) /* the following files should be deleted by xorgxrdp * but just in case the deletion failed */ - g_snprintf(file, sizeof(file), XRDP_X11RDP_STR, uid, display); + g_snprintf(file, sizeof(file), XRDP_X11RDP_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -933,7 +1122,7 @@ cleanup_sockets(int uid, int display) } } - g_snprintf(file, sizeof(file), XRDP_DISCONNECT_STR, uid, display); + g_snprintf(file, sizeof(file), XRDP_DISCONNECT_STR, uid, sd->display); if (g_file_exist(file)) { LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file); @@ -997,16 +1186,16 @@ process_child_exit(struct session_data *sd, { if (pid == sd->x_server) { - LOG(LOG_LEVEL_INFO, "X server pid %d on display :%d finished", - sd->x_server, sd->params.display); + LOG(LOG_LEVEL_INFO, "X server pid %d on display %s finished", + sd->x_server, sd->display); sd->x_server = -1; // No other action - window manager should be going soon } else if (pid == sd->chansrv) { LOG(LOG_LEVEL_INFO, - "xrdp channel server pid %d on display :%d finished", - sd->chansrv, sd->params.display); + "xrdp channel server pid %d on display %s finished", + sd->chansrv, sd->display); sd->chansrv = -1; } else if (pid == sd->win_mgr) @@ -1016,53 +1205,50 @@ process_child_exit(struct session_data *sd, if (e->reason == E_PXR_STATUS_CODE && e->val == 0) { LOG(LOG_LEVEL_INFO, - "Window manager (pid %d, display %d) " + "Window manager (pid %d, display %s) " "finished normally in %d secs", - sd->win_mgr, sd->params.display, wm_wait_time); + sd->win_mgr, sd->display, wm_wait_time); } else { char reason[128]; exit_status_to_str(e, reason, sizeof(reason)); - LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) " + LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %s) " "exited with %s. This " "could indicate a window manager config problem", - sd->win_mgr, sd->params.display, reason); + sd->win_mgr, sd->display, reason); } if (wm_wait_time < 10) { /* This could be a config issue. Log a significant error */ - LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) " + LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %s) " "exited quickly (%d secs). This could indicate a window " "manager config problem", - sd->win_mgr, sd->params.display, wm_wait_time); - } - { - char dstr[32]; - g_snprintf(dstr, sizeof(dstr), "%u", sd->params.display); - utmp_logout(sd->win_mgr, dstr, e); + sd->win_mgr, sd->display, wm_wait_time); } + + utmp_logout(sd->win_mgr, sd->display, e); sd->win_mgr = -1; if (sd->x_server > 0) { - LOG(LOG_LEVEL_INFO, "Terminating X server (pid %d) on display :%d", - sd->x_server, sd->params.display); + LOG(LOG_LEVEL_INFO, "Terminating X server (pid %d) on display %s", + sd->x_server, sd->display); g_sigterm(sd->x_server); } if (sd->chansrv > 0) { LOG(LOG_LEVEL_INFO, "Terminating the xrdp channel server (pid %d) " - "on display :%d", sd->chansrv, sd->params.display); + "on display %s", sd->chansrv, sd->display); g_sigterm(sd->chansrv); } } if (!session_active(sd)) { - cleanup_sockets(g_login_info->uid, sd->params.display); + cleanup_sockets(sd); } } @@ -1104,6 +1290,13 @@ session_get_connect_count(const struct session_data *sd) return (sd == NULL) ? 0 : sd->connect_count; } +/******************************************************************************/ +const char * +session_get_display(const struct session_data *sd) +{ + return (sd == NULL) ? "" : sd->display; +} + /******************************************************************************/ unsigned int session_increment_connect_count(struct session_data *sd) @@ -1157,10 +1350,10 @@ session_send_term(struct session_data *sd, int wait_for_all) /******************************************************************************/ static void start_reconnect_script(const struct login_info *login_info, - const struct session_parameters *s, + const struct session_data *sd, void *closure) { - env_set_user(login_info->uid, 0, s->display, + env_set_user(login_info->uid, g_cfg->env_names, g_cfg->env_values); @@ -1182,14 +1375,14 @@ start_reconnect_script(const struct login_info *login_info, LOG_DEVEL_LEAKING_FDS("reconnect script", 3, -1); LOG(LOG_LEVEL_INFO, - "Starting session reconnection script on display %d: %s", - s->display, g_cfg->reconnect_sh); + "Starting session reconnection script on display %s: %s", + sd->display, g_cfg->reconnect_sh); g_execlp3(g_cfg->reconnect_sh, g_cfg->reconnect_sh, 0); /* should not get here */ LOG(LOG_LEVEL_ERROR, - "Error starting session reconnection script on display %d: %s", - s->display, g_cfg->reconnect_sh); + "Error starting session reconnection script on display %s: %s", + sd->display, g_cfg->reconnect_sh); } else { @@ -1206,7 +1399,7 @@ session_run_reconnect_script(const struct login_info *login_info, const char *vars[]) { if (fork_child(start_reconnect_script, - login_info, &sd->params, sd->x_server, (void *)vars) < 0) + login_info, sd, sd->x_server, (void *)vars) < 0) { LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script"); } @@ -1226,8 +1419,8 @@ session_get_display_server_fd(const struct login_info *login_info, if (sd->x_server <= 0) { LOG(LOG_LEVEL_ERROR, - "Request to connect to display server :%u" - " which has exited", sd->params.display); + "Request to connect to display server %s" + " which has exited", sd->display); } else { @@ -1235,15 +1428,15 @@ session_get_display_server_fd(const struct login_info *login_info, { case SCP_SESSION_TYPE_XVNC: socket_mode = TRANS_MODE_TCP; - snprintf(portname, sizeof(portname), "%u", - 5900 + sd->params.display); + snprintf(portname, sizeof(portname), "%d", + 5900 + sd->params.x11_display); break; case SCP_SESSION_TYPE_XVNC_UDS: case SCP_SESSION_TYPE_XORG: socket_mode = TRANS_MODE_UNIX; snprintf(portname, sizeof(portname), XRDP_X11RDP_STR, - login_info->uid, (int)sd->params.display); + login_info->uid, sd->display); break; @@ -1263,8 +1456,8 @@ session_get_display_server_fd(const struct login_info *login_info, } else if (trans_connect(t, localhost, portname, 3000) != 0) { - LOG(LOG_LEVEL_ERROR, "Can't connect to display server :%u [%s]", - sd->params.display, + LOG(LOG_LEVEL_ERROR, "Can't connect to display server %s [%s]", + sd->display, g_get_strerror()); } else @@ -1291,13 +1484,13 @@ session_get_chansrv_fd(const struct login_info *login_info, if (sd->chansrv <= 0) { LOG(LOG_LEVEL_ERROR, - "Request to connect to chansrv :%u" - " which has exited", sd->params.display); + "Request to connect to chansrv %s" + " which has exited", sd->display); } else { snprintf(portname, sizeof(portname), - XRDP_CHANSRV_STR, login_info->uid, (int)sd->params.display); + XRDP_CHANSRV_STR, login_info->uid, sd->display); // Use the transport library to get the fd struct trans *t = trans_create(TRANS_MODE_UNIX, 8192, 8192); @@ -1307,8 +1500,8 @@ session_get_chansrv_fd(const struct login_info *login_info, } else if (trans_connect(t, NULL, portname, 10 * 1000) != 0) { - LOG(LOG_LEVEL_ERROR, "Can't connect to chansrv :%u [%s]", - sd->params.display, + LOG(LOG_LEVEL_ERROR, "Can't connect to chansrv %s [%s]", + sd->display, g_get_strerror()); } else diff --git a/sesman/sesexec/session.h b/sesman/sesexec/session.h index 43808989..bd4083a5 100644 --- a/sesman/sesexec/session.h +++ b/sesman/sesexec/session.h @@ -41,7 +41,7 @@ struct proc_exit_status; */ struct session_parameters { - unsigned int display; + int x11_display; // >= 0 for X11 only enum scp_session_type type; unsigned short width; unsigned short height; @@ -114,6 +114,17 @@ session_get_start_time(const struct session_data *sd); unsigned int session_get_connect_count(const struct session_data *sd); +/** + * Get a pointer to the session display name + * + * @param self session_data object + * @return session name ("X11-n" or "wayland-n") + * + * A session name is set by a successful call to session_start() + */ +const char * +session_get_display(const struct session_data *sd); + /** * Increment the connect count for an active session * @param sd session_data for this session diff --git a/sesman/sesexec/xwait.c b/sesman/sesexec/xwait.c index 93cfca04..75190681 100644 --- a/sesman/sesexec/xwait.c +++ b/sesman/sesexec/xwait.c @@ -117,8 +117,6 @@ wait_for_xserver(uid_t uid, /* Move to the user context... */ env_set_user(uid, - 0, - display, env_names, env_values); diff --git a/sesman/sesman_restart.c b/sesman/sesman_restart.c index 7b5062d2..69b3ac54 100644 --- a/sesman/sesman_restart.c +++ b/sesman/sesman_restart.c @@ -150,7 +150,7 @@ add_sesexec_fd_to_session_list(const char *filename) // E_SESSION_STARTING state s_item->sesexec_trans = t; s_item->sesexec_pid = sesexec_pid; - s_item->display = -1; + s_item->display[0] = '\0'; // Tell the caller we've added one status = 1; diff --git a/sesman/session_list.c b/sesman/session_list.c index fd11aa5a..067372db 100644 --- a/sesman/session_list.c +++ b/sesman/session_list.c @@ -160,7 +160,7 @@ session_list_new(void) /******************************************************************************/ void -session_list_get_session_displays(struct set_int *alloc_displays) +session_list_get_session_x11_displays(struct set_int *alloc_displays) { int count = (g_session_list == NULL) ? 0 : g_session_list->count; @@ -170,9 +170,13 @@ session_list_get_session_displays(struct set_int *alloc_displays) struct session_item *si; si = (struct session_item *)list_get_item(g_session_list, i); - if (SESSION_IN_USE(si)) + if (SESSION_IN_USE(si) && SCP_SESSION_TYPE_IS_X11(si->type)) { - set_int_add(alloc_displays, si->display); + int display = g_get_x11_display_from_display_string(si->display); + if (display >= 0) + { + set_int_add(alloc_displays, display); + } } } } @@ -289,7 +293,7 @@ session_list_get_bydata(uid_t uid, } LOG(LOG_LEVEL_DEBUG, - "%s: Got match, display=%d", __func__, si->display); + "%s: Got match, display=%s", __func__, si->display); return si; } @@ -351,7 +355,7 @@ session_list_get_byuid(const uid_t *uid, unsigned int *cnt, unsigned int flags) if (SESSION_IN_USE(si) && (uid == NULL || *uid == si->uid)) { sess[index].sid = si->sesexec_pid; - sess[index].display = si->display; + sess[index].display = g_strdup(si->display); sess[index].type = si->type; sess[index].height = si->start_height; sess[index].width = si->start_width; @@ -365,7 +369,8 @@ session_list_get_byuid(const uid_t *uid, unsigned int *cnt, unsigned int flags) sess[index].xrdp_instance_name = g_strdup(si->xrdp_instance_name); /* Check for string allocation failures */ - if (sess[index].start_ip_addr == NULL || + if (sess[index].display == NULL || + sess[index].start_ip_addr == NULL || sess[index].client_ip == NULL || sess[index].client_name == NULL || sess[index].xrdp_instance_name == NULL) @@ -410,6 +415,7 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt) unsigned int i; for (i = 0 ; i < cnt ; ++i) { + g_free(sesslist[i].display); g_free(sesslist[i].start_ip_addr); g_free(sesslist[i].client_ip); g_free(sesslist[i].client_name); diff --git a/sesman/session_list.h b/sesman/session_list.h index 744983ff..1bdcee51 100644 --- a/sesman/session_list.h +++ b/sesman/session_list.h @@ -58,8 +58,8 @@ struct session_item struct trans *sesexec_trans; // trans for sesexec process. Always valid. pid_t sesexec_pid; // pid for sesexec process. Always valid /** - * May be valid if known when the session is starting, otherwise -1 */ - int display; + * May be valid if known when the session is starting, otherwise "" */ + char display[MAX_DISPLAY_NAME_SIZE]; uid_t uid; enum scp_session_type type; unsigned short start_width; @@ -125,10 +125,10 @@ session_list_new(void); /** * @brief Get all session displays * - * Adds displays allocated to sessions to a set + * Adds X11 displays allocated to sessions to a set */ void -session_list_get_session_displays(struct set_int *alloc_displays); +session_list_get_session_x11_displays(struct set_int *alloc_displays); /** * diff --git a/sesman/tools/dis.c b/sesman/tools/dis.c index 2e744ef7..76c2e0ad 100644 --- a/sesman/tools/dis.c +++ b/sesman/tools/dis.c @@ -28,6 +28,7 @@ #include #include +#include "xrdp_constants.h" #include "xrdp_sockets.h" #include "os_calls.h" #include "string_calls.h" @@ -35,10 +36,9 @@ int main(int argc, char **argv) { int sck; - int dis; + char disstr[MAX_DISPLAY_NAME_SIZE]; struct sockaddr_un sa; size_t len; - char *display; if (argc != 1) { @@ -47,23 +47,15 @@ int main(int argc, char **argv) return 0; } - display = getenv("DISPLAY"); - - if (display == 0) + if (g_get_display_string(disstr, sizeof(disstr)) < 0) { - printf("display not set\n"); + printf("Can't find teh display from the environment\n"); return 1; } - dis = g_get_display_num_from_display(display); - if (dis < 0) - { - printf("Can't parse DISPLAY='%s'\n", display); - return 1; - } memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; - sprintf(sa.sun_path, XRDP_DISCONNECT_STR, g_getuid(), dis); + g_sprintf(sa.sun_path, XRDP_DISCONNECT_STR, g_getuid(), disstr); if (access(sa.sun_path, F_OK) != 0) { diff --git a/sesman/tools/sesadmin.c b/sesman/tools/sesadmin.c index 7213bd36..63a55e7a 100644 --- a/sesman/tools/sesadmin.c +++ b/sesman/tools/sesadmin.c @@ -141,7 +141,7 @@ print_session(const struct scp_session_info *s) uptr = (username == NULL) ? "" : username; printf("Session ID: %d\n", s->sid); - printf("\tDisplay: :%u\n", s->display); + printf("\tDisplay: %s\n", s->display); printf("\tUser: %s\n", uptr); printf("\tSession type: %s\n", SCP_SESSION_TYPE_TO_STR(s->type)); printf("\tScreen size: %dx%d, color depth %d\n", diff --git a/sesman/tools/sesrun.c b/sesman/tools/sesrun.c index 1e7564c5..247207d2 100644 --- a/sesman/tools/sesrun.c +++ b/sesman/tools/sesrun.c @@ -520,7 +520,7 @@ static int handle_create_session_response(struct trans *t) { enum scp_screate_status status; - int display; + const char *display; struct guid guid; int rv = scp_sync_wait_specific(t, E_SCP_CREATE_SESSION_RESPONSE); @@ -541,7 +541,7 @@ handle_create_session_response(struct trans *t) else { char guid_str[GUID_STR_SIZE]; - g_printf("ok display=:%d GUID=%s\n", + g_printf("ok display=%s GUID=%s\n", display, guid_to_str(&guid, guid_str)); } diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index 3f392a49..b0a71a54 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -311,10 +311,13 @@ password=ask #pampassword=asksame #delay_ms=2000 ; Use one of these to connect to a chansrv instance created outside of sesman -; (e.g. as part of an x11vnc console session). Replace 'n' with the -; display number of the session, and (if applicable) 'u' with the numeric +; (e.g. as part of an x11vnc console session). Replace 's' with the +; display string of the session, and (if applicable) 'u' with the numeric ; UID of the session. ; +; For compatibility, a completely numeric display string is taken to be +; an X11 display number +; ; You will also need to change the value of SessionSockdirGroup in ; sesman.ini to allow xrdp to reach the chansrv instance ; diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 025d5e9b..f1a76380 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -325,7 +325,7 @@ xrdp_mm_create_session(struct xrdp_mm *self) type = SCP_SESSION_TYPE_XVNC_UDS; break; - case XORG_SESSION_CODE: + case XORG_SESSION_CODE: type = SCP_SESSION_TYPE_XORG; break; @@ -2770,7 +2770,7 @@ static int xrdp_mm_process_create_session_response(struct xrdp_mm *self) { enum scp_screate_status status; - int display; + const char *display; struct guid guid; int rv; @@ -2792,11 +2792,11 @@ xrdp_mm_process_create_session_response(struct xrdp_mm *self) if (status == E_SCP_SCREATE_OK) { xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, - "session is available on display %d for user %s", + "session is available on display %s for user %s", display, username); /* Carry on with the connect state machine */ - self->display = display; + strlcpy(self->display, display, sizeof(self->display)); self->guid = guid; xrdp_mm_connect_sm(self); } @@ -2937,7 +2937,7 @@ cleanup_states(struct xrdp_mm *self) //self->sesman_trans = NULL; /* connection to sesman */ self->chan_trans = NULL; /* connection to chansrv */ self->delete_sesman_trans = 0; - self->display = 0; /* 10 for :10.0, 11 for :11.0, etc */ + memset(self->display, '\0', sizeof(self->display)); guid_clear(&self->guid); self->code = 0; /* ???_SESSION_CODE value */ close_sesman_file_descriptors(self); @@ -2966,7 +2966,7 @@ static int parse_chansrvport(const char *value, char *dest, int dest_size, int uid) { int rv = 0; - int dnum; + char dstr[MAX_DISPLAY_NAME_SIZE]; if (value == NULL) { @@ -2978,22 +2978,34 @@ parse_chansrvport(const char *value, char *dest, int dest_size, int uid) { const char *p = value + 8; const char *end = p; - - /* Check next chars are digits */ - while (isdigit(*end)) + int is_numeric = 1; + /* Look for a ',' or ')' or '\0' */ + while (*end != ',' && *end != ')' && *end != '\0') { + if (!isdigit(*end)) + { + is_numeric = 0; + } ++end; } - if (end == p) + if (end == p || (unsigned int)(end - p) > (sizeof(dstr) - 1)) { LOG(LOG_LEVEL_WARNING, - "Ignoring chansrvport string with bad display number '%s'", + "Ignoring chansrvport string with bad display string '%s'", value); return -1; } - dnum = g_atoi(p); + memcpy(dstr, p, end - p); + dstr[end - p] = '\0'; + if (is_numeric) + { + // X11 compatibility + int dnum = g_atoi(dstr); + (void)g_get_display_string_from_x11_display( + dnum, dstr, sizeof(dstr)); + } if (*end == ',') { @@ -3025,7 +3037,7 @@ parse_chansrvport(const char *value, char *dest, int dest_size, int uid) return -1; } - g_snprintf(dest, dest_size, XRDP_CHANSRV_STR, uid, dnum); + g_snprintf(dest, dest_size, XRDP_CHANSRV_STR, uid, dstr); } else { @@ -5464,17 +5476,24 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) if (!g_is_wait_obj_set(self->wm->pro_layer->self_term_event)) { - if (self->display < 0) - { - LOG(LOG_LEVEL_ERROR, - "Unexpected display value %d setting up module", self->display); - xrdp_mm_set_fatal(self, ERRINFO_SERVER_DWM_CRASH); - } - else if (self->code == XVNC_SESSION_CODE) + if (self->code == XVNC_SESSION_CODE) { if (self->use_sesman) { - g_snprintf(text, sizeof(text), "%d", 5900 + self->display); + // We have to make assumptions about the display format for + // classic VNC + int dnum = g_get_x11_display_from_display_string(self->display); + if (dnum < 0) + { + LOG(LOG_LEVEL_ERROR, + "Unexpected display value %s setting up VNC module", + self->display); + xrdp_mm_set_fatal(self, ERRINFO_SERVER_DWM_CRASH); + } + else + { + g_snprintf(text, sizeof(text), "%d", 5900 + dnum); + } } } else if (self->code == XORG_SESSION_CODE || diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 6be9b93d..2a5be564 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -42,8 +42,7 @@ /* To check whether touch events has been implemented on session type 'mm' */ #define XRDP_MM_IMPLEMENTS_TOUCH(mm) \ - (((mm)->code != XVNC_SESSION_CODE) && \ - ((mm)->code != XVNC_UDS_SESSION_CODE)) + ((mm)->code == XORG_SESSION_CODE) struct source_info; struct list16; @@ -440,7 +439,7 @@ struct xrdp_mm struct xrdp_mod *(*mod_init)(void); int (*mod_exit)(struct xrdp_mod *); struct xrdp_mod *mod; /* module interface */ - int display; /* 10 for :10.0, 11 for :11.0, etc */ + char display[MAX_DISPLAY_NAME_SIZE]; int uid; /* UID for a successful login, -1 otherwise */ struct guid guid; /* GUID for the session, or all zeros */ int code; /* 0=Xvnc session, 20=xorg driver mode */ diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c index 5c0373eb..fe01460f 100644 --- a/xrdpapi/xrdpapi.c +++ b/xrdpapi/xrdpapi.c @@ -35,6 +35,7 @@ #include #include "log.h" +#include "xrdp_constants.h" #include "xrdp_sockets.h" #include "string_calls.h" #include "channel_defs.h" @@ -43,7 +44,7 @@ struct wts_obj { int fd; - int display_num; + char display_name[MAX_DISPLAY_NAME_SIZE]; }; /** @@ -132,8 +133,7 @@ VirtualChannelOpen(unsigned int SessionId, const char *pVirtualName, return 0; } wts->fd = -1; - wts->display_num = g_get_display_num_from_display(getenv("DISPLAY")); - if (wts->display_num < 0) + if (g_get_display_string(wts->display_name, sizeof(wts->display_name)) < 0) { LOG(LOG_LEVEL_ERROR, "WTSVirtualChannelOpenEx: fatal error; invalid DISPLAY"); *errcode = WTS_E_RESOURCE_ERROR; @@ -162,7 +162,8 @@ VirtualChannelOpen(unsigned int SessionId, const char *pVirtualName, memset(&s, 0, sizeof(struct sockaddr_un)); s.sun_family = AF_UNIX; bytes = sizeof(s.sun_path); - snprintf(s.sun_path, bytes - 1, CHANSRV_API_STR, getuid(), wts->display_num); + snprintf(s.sun_path, bytes - 1, CHANSRV_API_STR, + getuid(), wts->display_name); s.sun_path[bytes - 1] = 0; bytes = sizeof(struct sockaddr_un);