Merge pull request #1843 from aquesnel/add_logging_session_c

Adding logs to sesman/session.c (#1843)

Unit test framework check also added (https://libcheck.github.io/check/)
This commit is contained in:
matt335672 2021-04-14 10:40:32 +01:00 committed by GitHub
commit 3a9d62b05c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 712 additions and 142 deletions

View File

@ -6,7 +6,7 @@ FreeBSD_task:
freebsd_instance:
image_family: freebsd-12-2
prepare_script:
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check
- git submodule update --init --recursive
configure_script:
- ./bootstrap

2
.gitignore vendored
View File

@ -42,7 +42,9 @@ sesman/xrdp-sesman
sesman/sesman.ini
*.so
stamp-h1
tap-driver.sh
test-driver
tests/common/test_common
tests/memtest/memtest
tools/devel/tcp_proxy/tcp_proxy
*.trs

View File

@ -32,7 +32,10 @@ if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
AM_CFLAGS = $(OPENSSL_CFLAGS)
# -no-suppress is an automake-specific flag which is needed
# to prevent us missing compiler errors in some circumstances
# (see https://github.com/neutrinolabs/xrdp/pull/1843 )
AM_CFLAGS = -no-suppress $(OPENSSL_CFLAGS)
module_LTLIBRARIES = \
libcommon.la

View File

@ -2591,16 +2591,41 @@ g_get_errno(void)
/*****************************************************************************/
/* does not work in win32 */
#define ARGS_STR_LEN 1024
int
g_execvp(const char *p1, char *args[])
{
#if defined(_WIN32)
return 0;
#else
int rv;
char args_str[ARGS_STR_LEN];
int args_len;
args_len = 0;
while (args[args_len] != NULL)
{
args_len++;
}
g_strnjoin(args_str, ARGS_STR_LEN, " ", (const char **) args, args_len);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
p1, args_str);
g_rm_temp_dir();
rv = execvp(p1, args);
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"returned errno: %d, description: %s",
p1, args_str, g_get_errno(), g_get_strerror());
g_mk_socket_path(0);
return rv;
#endif
@ -2615,9 +2640,24 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
return 0;
#else
int rv;
const char *args[] = {a2, a3, NULL};
char args_str[ARGS_STR_LEN];
g_strnjoin(args_str, ARGS_STR_LEN, " ", args, 2);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
a1, args_str);
g_rm_temp_dir();
rv = execlp(a1, a2, a3, (void *)0);
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"returned errno: %d, description: %s",
a1, args_str, g_get_errno(), g_get_strerror());
g_mk_socket_path(0);
return rv;
#endif
@ -2716,6 +2756,12 @@ g_fork(void)
{
g_mk_socket_path(0);
}
else if (rv == -1) /* error */
{
LOG(LOG_LEVEL_ERROR,
"Process fork failed with errno: %d, description: %s",
g_get_errno(), g_get_strerror());
}
return rv;
#endif
@ -2876,6 +2922,51 @@ g_waitpid(int pid)
#endif
}
/*****************************************************************************/
/* does not work in win32
returns exit status code of child process with pid */
struct exit_status
g_waitpid_status(int pid)
{
struct exit_status exit_status;
#if defined(_WIN32)
exit_status.exit_code = -1;
exit_status.signal_no = 0;
return exit_status;
#else
int rv;
int status;
exit_status.exit_code = -1;
exit_status.signal_no = 0;
if (pid > 0)
{
LOG(LOG_LEVEL_DEBUG, "waiting for pid %d to exit", pid);
rv = waitpid(pid, &status, 0);
if (rv != -1)
{
if (WIFEXITED(status))
{
exit_status.exit_code = WEXITSTATUS(status);
}
if (WIFSIGNALED(status))
{
exit_status.signal_no = WTERMSIG(status);
}
}
else
{
LOG(LOG_LEVEL_WARNING, "wait for pid %d returned unknown result", pid);
}
}
return exit_status;
#endif
}
/*****************************************************************************/
/* does not work in win32 */
void

View File

@ -23,6 +23,15 @@
#include "arch.h"
struct exit_status
{
/* set to -1 when the process exited via a signal */
uint8_t exit_code;
/* set to 0 when the process exited normally */
uint8_t signal_no;
};
#define g_tcp_can_recv g_sck_can_recv
#define g_tcp_can_send g_sck_can_send
#define g_tcp_recv g_sck_recv
@ -145,6 +154,7 @@ int g_getlogin(char *name, unsigned int len);
int g_setlogin(const char *name);
int g_waitchild(void);
int g_waitpid(int pid);
struct exit_status g_waitpid_status(int pid);
void g_clearenv(void);
int g_setenv(const char *name, const char *value, int rewrite);
char *g_getenv(const char *name);

View File

@ -30,6 +30,7 @@
#include "log.h"
#include "os_calls.h"
#include "string_calls.h"
#include "defines.h"
unsigned int
g_format_info_string(char *dest, unsigned int len,
@ -806,3 +807,50 @@ g_strtrim(char *str, int trim_flags)
free(text1);
return 0;
}
/*****************************************************************************/
char *
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len)
{
int len = 0;
int joiner_len;
int i = 0;
int dest_remaining;
char *dest_pos = dest;
char *dest_end;
if (dest == NULL || dest_len < 1)
{
return dest;
}
if (src == NULL || src_len < 1)
{
dest[0] = '\0';
return dest;
}
dest[0] = '\0';
dest_end = dest + dest_len - 1;
joiner_len = g_strlen(joiner);
for (i = 0; i < src_len - 1 && dest_pos < dest_end; i++)
{
len = g_strlen(src[i]);
dest_remaining = dest_end - dest_pos;
g_strncat(dest_pos, src[i], dest_remaining);
dest_pos += MIN(len, dest_remaining);
if (dest_pos < dest_end)
{
dest_remaining = dest_end - dest_pos;
g_strncat(dest_pos, joiner, dest_remaining);
dest_pos += MIN(joiner_len, dest_remaining);
}
}
if (i == src_len - 1 && dest_pos < dest_end)
{
g_strncat(dest_pos, src[i], dest_end - dest_pos);
}
return dest;
}

View File

@ -80,6 +80,33 @@ g_bool2text(int value);
int
g_text2bool(const char *s);
/**
* Joins an array of strings into a single string.
*
* Note: The joiner is placed between each source string. The joiner is not
* placed after the last source string. If there is only one source string,
* then the result string will be equal to the source string.
*
* Note: any content that is present in dest will be overwritten with the new
* joined string.
*
* Note: If the destination array is not large enough to hold the entire
* contents of the joined string, then the joined string will be truncated
* to fit in the destination array.
*
* @param[out] dest The destination array to write the joined string into.
* @param[in] dest_len The max number of characters to write to the destination
* array including the terminating null. Must be > 0
* @param[in] joiner The string to concatenate between each source string.
* The joiner string may be NULL which is processed as a zero length string.
* @param[in] src An array of strings to join. The array must be non-null.
* Array items may be NULL and are processed as zero length strings.
* @param[in] src_len The number of strings to join in the src array. Must be > 0
* @return A pointer to the begining of the joined string (ie. returns dest).
*/
char *
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len);
/**
* Converts a binary array into a hux dump suitable for displaying to a user.
*

View File

@ -357,6 +357,11 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [],
CFLAGS="$save_CFLAGS"
# checking for libcheck (used for unit testing)
PKG_CHECK_MODULES([CHECK], [check >= 0.10.0])
AC_CHECK_HEADER([check.h], [],
[AC_MSG_ERROR([please install check])])
AC_SUBST([moduledir], '${libdir}/xrdp')
AC_ARG_ENABLE([strict-locations],
@ -398,6 +403,7 @@ AC_CONFIG_FILES([
sesman/Makefile
sesman/tools/Makefile
tests/Makefile
tests/common/Makefile
tests/memtest/Makefile
tools/Makefile
tools/devel/Makefile
@ -409,6 +415,7 @@ AC_CONFIG_FILES([
xup/Makefile
])
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AC_OUTPUT
echo ""

View File

@ -1,21 +1,19 @@
#!/bin/sh
set -eufx
FEATURE_SET="$1"
ARCH="$2"
shift
shift
FEATURE_SET=min
ARCH=amd64
if [ $# -ge 1 ]; then
FEATURE_SET="$1"
shift
fi
if [ $# -ge 1 ]; then
ARCH="$1"
shift
fi
APT_EXTRA_ARGS="$@"
if [ -z "$FEATURE_SET" ]; then
FEATURE_SET=min
fi
if [ -z "$ARCH" ]; then
ARCH=amd64
fi
# common build tools for all architectures and feature sets
PACKAGES=" \
autoconf \
@ -26,7 +24,8 @@ PACKAGES=" \
libtool \
make \
nasm \
pkg-config\
pkg-config \
check \
"
case "$ARCH"

View File

@ -116,23 +116,19 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
return 0;
}
#if 0
LOG(LOG_LEVEL_INFO,
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
policy, name, width, height, bpp, type, client_ip);
#endif
while (tmp != 0)
{
#if 0
LOG(LOG_LEVEL_INFO,
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s",
tmp->item,
tmp->item->name,
tmp->item->width, tmp->item->height,
tmp->item->bpp, tmp->item->type,
tmp->item->client_ip);
#endif
if (g_strncmp(name, tmp->item->name, 255) == 0 &&
(!(policy & SESMAN_CFG_SESS_POLICY_D) ||
@ -173,12 +169,14 @@ x_server_running_check_ports(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, "/tmp/.X%d-lock", display);
x_running = g_file_exist(text);
}
if (!x_running) /* check 59xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "59%2.2d", display);
@ -189,6 +187,7 @@ x_server_running_check_ports(int display)
if (!x_running) /* check 60xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "60%2.2d", display);
@ -199,6 +198,7 @@ x_server_running_check_ports(int display)
if (!x_running) /* check 62xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "62%2.2d", display);
@ -209,34 +209,44 @@ x_server_running_check_ports(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, XRDP_CHANSRV_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_PORT_OUT_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_PORT_IN_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_API_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, XRDP_X11RDP_STR, display);
x_running = g_file_exist(text);
}
if (x_running)
{
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
}
return x_running;
}
@ -259,10 +269,20 @@ x_server_running(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, "/tmp/.X%d-lock", display);
x_running = g_file_exist(text);
}
if (x_running)
{
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
}
else
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
}
return x_running;
}
@ -314,7 +334,9 @@ session_get_avail_display_from_chain(void)
display++;
}
LOG(LOG_LEVEL_ERROR, "X server -- no display in range is available");
LOG(LOG_LEVEL_ERROR, "X server -- no display in range (%d to %d) is available",
g_cfg->sess.x11_display_offset,
g_cfg->sess.x11_display_offset + g_cfg->sess.max_sessions);
return 0;
}
@ -328,14 +350,16 @@ wait_for_xserver(int display)
/* wait up to 10 secs for x server to start */
i = 0;
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
while (!x_server_running(display))
{
i++;
if (i > 40)
{
LOG(LOG_LEVEL_ERROR,
"X server for display %d startup timeout",
LOG(LOG_LEVEL_WARNING,
"Timed out waiting for X server on display %d to startup",
display);
break;
}
@ -357,13 +381,16 @@ session_start_chansrv(char *username, int display)
chansrv_pid = g_fork();
if (chansrv_pid == 0)
{
LOG(LOG_LEVEL_INFO,
"Starting the xrdp channel server for display %d", display);
chansrv_params = list_create();
chansrv_params->auto_free = 1;
/* building parameters */
g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp-chansrv",
XRDP_SBIN_PATH);
list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
list_add_item(chansrv_params, 0); /* mandatory */
@ -373,9 +400,8 @@ session_start_chansrv(char *username, int display)
/* executing chansrv */
g_execvp(exe_path, (char **) (chansrv_params->items));
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting chansrv "
"- user %s - pid %d", username, g_getpid());
list_delete(chansrv_params);
g_exit(1);
}
@ -390,13 +416,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
{
int display = 0;
int pid = 0;
int i = 0;
char geometry[32];
char depth[32];
char screen[32]; /* display number */
char text[256];
char execvpparams[2048];
char *xserver; /* absolute/relative path to Xorg/X11rdp/Xvnc */
char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
char *passwd_file;
char **pp1 = (char **)NULL;
struct session_chain *temp = (struct session_chain *)NULL;
@ -421,7 +446,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* check to limit concurrent sessions */
if (g_session_count >= g_cfg->sess.max_sessions)
{
LOG(LOG_LEVEL_INFO, "max concurrent session limit "
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
"exceeded. login for user %s denied", s->username);
return 0;
}
@ -430,8 +455,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (temp == 0)
{
LOG(LOG_LEVEL_ERROR, "cannot create new chain "
"element - user %s", s->username);
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
"chain element - user %s", s->username);
return 0;
}
@ -440,7 +465,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (temp->item == 0)
{
g_free(temp);
LOG(LOG_LEVEL_ERROR, "cannot create new session "
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
"item - user %s", s->username);
return 0;
}
@ -459,11 +484,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"[session start] (display %d): Failed to fork for scp with "
"errno: %d, description: %s",
display, g_get_errno(), g_get_strerror());
}
else if (pid == 0)
{
LOG(LOG_LEVEL_INFO, "calling auth_start_session from pid %d",
g_getpid());
LOG(LOG_LEVEL_INFO,
"[session start] (display %d): calling auth_start_session from pid %d",
display, g_getpid());
auth_start_session(data, display);
g_delete_wait_obj(g_term_event);
g_tcp_close(g_sck);
@ -494,15 +524,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
*/
if (g_setsid() < 0)
{
LOG(LOG_LEVEL_ERROR,
"setsid failed - pid %d", g_getpid());
LOG(LOG_LEVEL_WARNING,
"[session start] (display %d): setsid failed - pid %d",
display, g_getpid());
}
if (g_setlogin(s->username) < 0)
{
LOG(LOG_LEVEL_ERROR,
"setlogin failed for user %s - pid %d", s->username,
g_getpid());
LOG(LOG_LEVEL_WARNING,
"[session start] (display %d): setlogin failed for user %s - pid %d",
display, s->username, g_getpid());
}
}
@ -521,6 +552,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
child forks wm, and waits, todo */
if (window_manager_pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"Failed to fork for the window manager on display %d", display);
}
else if (window_manager_pid == 0)
{
@ -540,79 +573,74 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
g_set_current_dir(s->directory);
}
}
if (s->program != 0)
if (s->program != 0 && s->program[0] != 0)
{
if (s->program[0] != 0)
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
{
LOG(LOG_LEVEL_DEBUG,
"starting program with parameters: %s ",
s->program);
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
{
const char *params[] = {"sh", "-c", s->program, NULL};
g_execvp("/bin/sh", (char **)params);
}
else
{
g_execlp3(s->program, s->program, 0);
}
LOG(LOG_LEVEL_ALWAYS,
"error starting program %s for user %s - pid %d",
s->program, s->username, g_getpid());
LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on "
"display %d with embeded arguments using a shell: %s",
display, s->program);
const char *params[] = {"sh", "-c", s->program, NULL};
g_execvp("/bin/sh", (char **)params);
}
else
{
LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on "
"display %d: %s", display, s->program);
g_execlp3(s->program, s->program, 0);
}
}
else
{
LOG(LOG_LEVEL_DEBUG, "The user session on display %d did "
"not request a specific window manager", display);
}
/* try to execute user window manager if enabled */
if (g_cfg->enable_user_wm)
{
g_sprintf(text, "%s/%s", g_getenv("HOME"), g_cfg->user_wm);
if (g_file_exist(text))
{
LOG(LOG_LEVEL_INFO,
"Starting window manager on display %d"
"from user home directory: %s", display, text);
g_execlp3(text, g_cfg->user_wm, 0);
LOG(LOG_LEVEL_ALWAYS, "error starting user "
"wm for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, "
"description: %s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter "
"list:");
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
}
else
{
LOG(LOG_LEVEL_DEBUG,
"The user home directory window manager configuration "
"is enabled but window manager program does not exist: %s",
text);
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
g_cfg->user_wm);
}
}
/* if we're here something happened to g_execlp3
so we try running the default window manager */
LOG(LOG_LEVEL_INFO,
"Starting the default window manager on display %d: %s",
display, g_cfg->default_wm);
g_execlp3(g_cfg->default_wm, g_cfg->default_wm, 0);
LOG(LOG_LEVEL_ALWAYS, "error starting default "
"wm for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter list:");
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
g_cfg->default_wm);
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
g_cfg->default_wm);
/* still a problem starting window manager just start xterm */
LOG(LOG_LEVEL_WARNING,
"No window manager on display %d started, "
"so falling back to starting xterm for user debugging",
display);
g_execlp3("xterm", "xterm", 0);
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting xterm "
"for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
}
else
{
LOG(LOG_LEVEL_ERROR, "another Xserver might "
"already be active on display %d - see log", display);
LOG(LOG_LEVEL_ERROR,
"There is no X server active on display %d", display);
}
LOG(LOG_LEVEL_DEBUG, "aborting connection...");
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
"the window manager on display %d, aborting connection",
display);
g_exit(0);
}
else
@ -621,6 +649,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
child becomes X */
if (display_pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"Failed to fork for the X server on display %d", display);
}
else if (display_pid == 0) /* child */
{
@ -641,7 +671,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
g_cfg->env_values);
}
/* setting Xserver environment variables */
g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time);
g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1);
g_snprintf(text, 255, "%d", g_cfg->sess.max_disc_time);
@ -663,6 +693,13 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* Add the entry in XAUTHORITY file or exit if error */
if (add_xauth_cookie(display, authfile) != 0)
{
LOG(LOG_LEVEL_ERROR,
"Error setting the xauth cookie for display %d in file %s",
display, authfile);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
"the X server on display %d, aborting connection",
display);
g_exit(1);
}
@ -678,8 +715,9 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
{
LOG(LOG_LEVEL_WARNING,
"Failed to disable setuid on X server: %s",
g_get_strerror());
"[session start] (display %d): Failed to disable "
"setuid on X server: %s",
display, g_get_strerror());
}
#endif
@ -703,17 +741,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
pp1 = (char **) xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
/* some args are passed via env vars */
g_sprintf(geometry, "%d", s->width);
g_setenv("XRDP_START_WIDTH", geometry, 1);
g_sprintf(geometry, "%d", s->height);
g_setenv("XRDP_START_HEIGHT", geometry, 1);
/* fire up Xorg */
g_execvp(xserver, pp1);
}
else if (type == SESMAN_SESSION_TYPE_XVNC)
{
@ -748,8 +781,6 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* make sure it ends with a zero */
list_add_item(xserver_params, 0);
pp1 = (char **)xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
}
else if (type == SESMAN_SESSION_TYPE_XRDP)
{
@ -777,72 +808,105 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* make sure it ends with a zero */
list_add_item(xserver_params, 0);
pp1 = (char **)xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
}
else
{
LOG(LOG_LEVEL_ALWAYS, "bad session type - "
"user %s - pid %d", s->username, g_getpid());
LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
"to start the X server on display %d, aborting connection",
display);
g_exit(1);
}
/* fire up X server */
LOG(LOG_LEVEL_INFO, "Starting X server on display %d: %s",
display, dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting X server "
"- user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execve parameter list size: "
"%d", (xserver_params)->count);
for (i = 0; i < (xserver_params->count); i++)
{
LOG(LOG_LEVEL_DEBUG, " argv[%d] = %s",
i, (char *)list_get_item(xserver_params, i));
}
LOG(LOG_LEVEL_ERROR,
"Error starting X server on display %d", display);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
"to start the X server on display %d, aborting connection",
display);
list_delete(xserver_params);
g_exit(1);
}
else
{
int wm_wait_time;
struct exit_status wm_exit_status;
struct exit_status xserver_exit_status;
struct exit_status chansrv_exit_status;
wait_for_xserver(display);
chansrv_pid = session_start_chansrv(s->username, display);
LOG(LOG_LEVEL_INFO,
"Session started successfully for user %s on display %d",
s->username, display);
/* Monitor the amount of time we wait for the
* window manager. This is approximately how long the window
* manager was running for */
LOG(LOG_LEVEL_INFO, "waiting for window manager "
"(pid %d) to exit", window_manager_pid);
LOG(LOG_LEVEL_INFO, "Session in progress on display %d, waiting "
"until the window manager (pid %d) exits to end the session",
display, window_manager_pid);
wm_wait_time = g_time1();
g_waitpid(window_manager_pid);
wm_exit_status = g_waitpid_status(window_manager_pid);
wm_wait_time = g_time1() - wm_wait_time;
if (wm_exit_status.exit_code > 0)
{
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
"exited with non-zero exit code %d and signal %d. This "
"could indicate a window manager config problem",
window_manager_pid, display, wm_exit_status.exit_code,
wm_exit_status.signal_no);
}
if (wm_wait_time < 10)
{
/* This could be a config issue. Log a significant error */
LOG(LOG_LEVEL_ALWAYS, "window manager exited quickly "
"(%d secs). Window manager config problem?",
wm_wait_time);
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
"exited quickly (%d secs). This could indicate a window "
"manager config problem",
window_manager_pid, display, wm_wait_time);
}
else
{
LOG(LOG_LEVEL_INFO, "window manager (pid %d) was running "
"for approximately %d seconds.",
window_manager_pid, wm_wait_time);
LOG(LOG_LEVEL_DEBUG, "Window manager (pid %d, display %d) "
"was running for %d seconds.",
window_manager_pid, display, wm_wait_time);
}
LOG(LOG_LEVEL_INFO, "Cleaning up session. Calling "
"auth_stop_session and auth_end from pid %d", g_getpid());
LOG(LOG_LEVEL_INFO,
"Calling auth_stop_session and auth_end from pid %d",
g_getpid());
auth_stop_session(data);
auth_end(data);
LOG(LOG_LEVEL_INFO,
"Terminating X server (pid %d) on display %d",
display_pid, display);
g_sigterm(display_pid);
LOG(LOG_LEVEL_INFO, "Terminating the xrdp channel server (pid %d) "
"on display %d", chansrv_pid, display);
g_sigterm(chansrv_pid);
/* make sure socket cleanup happen after child process exit */
g_waitpid(display_pid);
g_waitpid(chansrv_pid);
xserver_exit_status = g_waitpid_status(display_pid);
LOG(LOG_LEVEL_INFO,
"X server on display %d (pid %d) returned exit code %d "
"and signal number %d",
display, display_pid, xserver_exit_status.exit_code,
xserver_exit_status.signal_no);
chansrv_exit_status = g_waitpid_status(chansrv_pid);
LOG(LOG_LEVEL_INFO,
"xrdp channel server for display %d (pid %d) "
"exit code %d and signal number %d",
display, chansrv_pid, chansrv_exit_status.exit_code,
chansrv_exit_status.signal_no);
cleanup_sockets(display);
g_deinit();
@ -852,6 +916,10 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
}
else
{
LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
"display :%d.0, width %d, height %d, bpp %d, client ip %s, "
"user name %s",
pid, display, s->width, s->height, s->bpp, s->client_ip, s->username);
temp->item->pid = pid;
temp->item->display = display;
temp->item->width = s->width;
@ -898,6 +966,7 @@ session_reconnect_fork(int display, char *username, long data)
if (pid == -1)
{
LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script");
}
else if (pid == 0)
{
@ -910,9 +979,25 @@ session_reconnect_fork(int display, char *username, long data)
if (g_file_exist(g_cfg->reconnect_sh))
{
LOG(LOG_LEVEL_INFO,
"Starting session reconnection script on display %d: %s",
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",
display, g_cfg->reconnect_sh);
}
else
{
LOG(LOG_LEVEL_WARNING,
"Session reconnection script file does not exist: %s",
g_cfg->reconnect_sh);
}
/* TODO: why is this existing with a success error code when the
reconnect script failed to be executed? */
g_exit(0);
}
@ -972,7 +1057,9 @@ session_kill(int pid)
if (tmp->item->pid == pid)
{
/* deleting the session */
LOG(LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
LOG(LOG_LEVEL_INFO,
"++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
g_free(tmp->item);
if (prev == 0)
@ -1011,8 +1098,7 @@ session_sigkill_all(void)
{
if (tmp->item == 0)
{
LOG(LOG_LEVEL_ERROR, "found null session "
"descriptor!");
LOG(LOG_LEVEL_ERROR, "found null session descriptor!");
}
else
{
@ -1045,8 +1131,7 @@ session_get_bypid(int pid)
{
if (tmp->item == 0)
{
LOG(LOG_LEVEL_ERROR, "session descriptor for "
"pid %d is null!", pid);
LOG(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid);
g_free(dummy);
return 0;
}
@ -1078,15 +1163,14 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
tmp = g_sessions;
LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
while (tmp != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "user: %s", user);
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
"result=%d", (tmp->item->status), flags,
((tmp->item->status) & flags));
LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
"result=%d", (tmp->item->status), flags,
((tmp->item->status) & flags));
if ((tmp->item->status) & flags)
{
@ -1169,7 +1253,7 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
int
cleanup_sockets(int display)
{
LOG(LOG_LEVEL_DEBUG, "cleanup_sockets:");
LOG(LOG_LEVEL_INFO, "cleanup_sockets:");
char file[256];
int error;

View File

@ -3,4 +3,5 @@ EXTRA_DIST = \
readme.txt
SUBDIRS = \
common \
memtest

23
tests/common/Makefile.am Normal file
View File

@ -0,0 +1,23 @@
AM_CPPFLAGS = \
-I$(top_builddir) \
-I$(top_srcdir)/common
if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh
TESTS = test_common
check_PROGRAMS = test_common
test_common_SOURCES = \
test_common.h \
test_common_main.c \
test_string_calls.c
test_common_LDADD = \
$(top_builddir)/common/libcommon.la \
@CHECK_LIBS@

View File

@ -0,0 +1,9 @@
#ifndef TEST_COMMON_H
#define TEST_COMMON_H
#include <check.h>
Suite *make_suite_test_string(void);
#endif /* TEST_COMMON_H */

View File

@ -0,0 +1,23 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include <stdlib.h>
#include <check.h>
#include "test_common.h"
int main (void)
{
int number_failed;
SRunner *sr;
sr = srunner_create (make_suite_test_string());
// srunner_add_suite(sr, make_list_suite());
srunner_set_tap(sr, "-");
srunner_run_all (sr, CK_ENV);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -0,0 +1,240 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "test_common.h"
#include "string_calls.h"
#define RESULT_LEN 1024
START_TEST(test_strnjoin__when_src_is_null__returns_empty_string)
{
/* setup */
const char **src = NULL;
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 0);
/* verify */
ck_assert_str_eq(result, "");
}
END_TEST
START_TEST(test_strnjoin__when_src_has_null_item__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, NULL };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value ");
}
END_TEST
START_TEST(test_strnjoin__when_src_has_one_item__returns_copied_source_string)
{
/* setup */
const char *expected_value = "test_value";
const char *src[] = { expected_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 1);
/* verify */
ck_assert_str_eq(result, expected_value);
}
END_TEST
START_TEST(test_strnjoin__when_src_has_two_items__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value test_value");
}
END_TEST
START_TEST(test_strnjoin__when_joiner_is_empty_string__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, "", src, 2);
/* verify */
ck_assert_str_eq(result, "test_valuetest_value");
}
END_TEST
START_TEST(test_strnjoin__when_joiner_is_NULL__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, NULL, src, 2);
/* verify */
ck_assert_str_eq(result, "test_valuetest_value");
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_NULL__returns_NULL)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value };
char *result = NULL;
/* test */
g_strnjoin(result, 0, " ", src, 1);
/* verify */
ck_assert_ptr_eq(result, NULL);
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value };
char result[5];
result[0] = '\0';
/* test */
g_strnjoin(result, 5, " ", src, 1);
/* verify */
ck_assert_str_eq(result, "test");
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value};
char result[16];
result[0] = '\0';
/* test */
g_strnjoin(result, 16, " joiner ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value join");
}
END_TEST
START_TEST(test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value};
char result[RESULT_LEN] = "1234567890";
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value test_value");
}
END_TEST
START_TEST(test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination)
{
/* setup */
const char *src[] = { "a","b","c"};
char result[5+1+1]; /* a-b-c + term null + guard value */
/* test */
result[6] = '\x7f';
g_strnjoin(result, 5 + 1, "-", src, 3);
/* verify */
ck_assert_int_eq(result[6], '\x7f');
}
END_TEST
/******************************************************************************/
Suite *
make_suite_test_string(void)
{
Suite *s;
TCase *tc_strnjoin;
s = suite_create("String");
tc_strnjoin = tcase_create("strnjoin");
suite_add_tcase(s, tc_strnjoin);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_is_null__returns_empty_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_null_item__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_one_item__returns_copied_source_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_two_items__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_empty_string__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_NULL__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_NULL__returns_NULL);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten);
tcase_add_test(tc_strnjoin, test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination);
return s;
}

View File

@ -9,6 +9,9 @@ endif
noinst_PROGRAMS = \
memtest
check_PROGRAMS = \
memtest
memtest_SOURCES = \
libmem.h \
libmem.c \