Replace X11 display number with a display string
As far as possible, use of the X11 display number is kept to X11-specific routines. This is to make it easier to restructure the code to add non-X11 display support.
This commit is contained in:
+11
-18
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
#include <sys/stat.h>
|
||||
#include <poll.h>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
+6
-17
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
+11
-9
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
+43
-160
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+341
-148
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+12
-6
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
+5
-13
@@ -28,6 +28,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ print_session(const struct scp_session_info *s)
|
||||
uptr = (username == NULL) ? "<unknown>" : 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",
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user