Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utmp/wtmp support #2745

Merged
merged 22 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,11 @@ jobs:
# define the standard environment variable used in the rest of the steps.
CONF_FLAGS_amd64_min: "--disable-ipv6 --disable-jpeg --disable-fuse --disable-mp3lame
--disable-fdkaac --disable-opus --disable-rfxcodec --disable-painter
--disable-pixman"
--disable-pixman --disable-utmp"
CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
--enable-pixman --with-imlib2 --with-freetype2 --enable-tests"
--enable-pixman --enable-utmp
--with-imlib2 --with-freetype2 --enable-tests"
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-mp3lame
--enable-opus --enable-rfxcodec --enable-painter
--disable-pixman --with-imlib2 --with-freetype2
Expand Down
24 changes: 14 additions & 10 deletions common/os_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3302,25 +3302,25 @@ g_set_allusercontext(int uid)
/*****************************************************************************/
/* does not work in win32
returns pid of process that exits or zero if signal occurred
an exit_status struct can optionally be passed in to get the
a proc_exit_status struct can optionally be passed in to get the
exit status of the child */
int
g_waitchild(struct exit_status *e)
g_waitchild(struct proc_exit_status *e)
{
#if defined(_WIN32)
return 0;
#else
int wstat;
int rv;

struct exit_status dummy;
struct proc_exit_status dummy;

if (e == NULL)
{
e = &dummy; // Set this, then throw it away
}

e->reason = E_XR_UNEXPECTED;
e->reason = E_PXR_UNEXPECTED;
e->val = 0;

rv = waitpid(-1, &wstat, WNOHANG);
Expand All @@ -3335,12 +3335,12 @@ g_waitchild(struct exit_status *e)
}
else if (WIFEXITED(wstat))
{
e->reason = E_XR_STATUS_CODE;
e->reason = E_PXR_STATUS_CODE;
e->val = WEXITSTATUS(wstat);
}
else if (WIFSIGNALED(wstat))
{
e->reason = E_XR_SIGNAL;
e->reason = E_PXR_SIGNAL;
e->val = WTERMSIG(wstat);
}

Expand Down Expand Up @@ -3381,10 +3381,14 @@ g_waitpid(int pid)

Note that signal handlers are established with BSD-style semantics,
so this call is NOT interrupted by a signal */
struct exit_status
struct proc_exit_status
g_waitpid_status(int pid)
{
struct exit_status exit_status = {.reason = E_XR_UNEXPECTED, .val = 0};
struct proc_exit_status exit_status =
{
.reason = E_PXR_UNEXPECTED,
.val = 0
};

#if !defined(_WIN32)
if (pid > 0)
Expand All @@ -3399,12 +3403,12 @@ g_waitpid_status(int pid)
{
if (WIFEXITED(status))
{
exit_status.reason = E_XR_STATUS_CODE;
exit_status.reason = E_PXR_STATUS_CODE;
exit_status.val = WEXITSTATUS(status);
}
if (WIFSIGNALED(status))
{
exit_status.reason = E_XR_SIGNAL;
exit_status.reason = E_PXR_SIGNAL;
exit_status.val = WTERMSIG(status);
}
}
Expand Down
16 changes: 8 additions & 8 deletions common/os_calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@

#include "arch.h"

enum exit_reason
enum proc_exit_reason
{
E_XR_STATUS_CODE = 0, ///< 'val' contains exit status
E_XR_SIGNAL, ///< 'val' contains a signal number
E_XR_UNEXPECTED
E_PXR_STATUS_CODE = 0, ///< 'val' contains exit status
E_PXR_SIGNAL, ///< 'val' contains a signal number
E_PXR_UNEXPECTED
};

struct exit_status
struct proc_exit_status
{
enum exit_reason reason;
enum proc_exit_reason reason;
int val;
};

Expand Down Expand Up @@ -352,9 +352,9 @@ int g_setlogin(const char *name);
*/
int g_set_allusercontext(int uid);
#endif
int g_waitchild(struct exit_status *e);
int g_waitchild(struct proc_exit_status *e);
int g_waitpid(int pid);
struct exit_status g_waitpid_status(int pid);
struct proc_exit_status g_waitpid_status(int pid);
/*
* Sets the process group ID of the indicated process to the specified value.
* (POSIX.1)
Expand Down
21 changes: 21 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ AC_INIT([xrdp], [0.10.80], [[email protected]])
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
AM_INIT_AUTOMAKE([1.7.2 foreign])
AC_CONFIG_MACRO_DIR([m4])
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_CXX
AC_C_CONST
Expand Down Expand Up @@ -182,6 +183,11 @@ AC_ARG_ENABLE(rdpsndaudin, AS_HELP_STRING([--enable-rdpsndaudin],
[], [enable_rdpsndaudin=no])
AM_CONDITIONAL(XRDP_RDPSNDAUDIN, [test x$enable_rdpsndaudin = xyes])

AC_ARG_ENABLE(utmp, AS_HELP_STRING([--enable-utmp],
[Update utmp (default: no)]),
[], [enable_utmp=no])
AM_CONDITIONAL(XRDP_UTMP, [test x$enable_utmp = xyes])

AC_ARG_WITH(imlib2, AS_HELP_STRING([--with-imlib2=ARG], [imlib2 library to use for non-BMP backgrounds (ARG=yes/no/<abs-path>)]),,)

AC_ARG_WITH(freetype2, AS_HELP_STRING([--with-freetype2=ARG], [freetype2 library to use for rendering fonts (ARG=yes/no/<abs-path>)]),,)
Expand Down Expand Up @@ -514,6 +520,15 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [],
[AC_MSG_ERROR([please install libxrandr-dev or libXrandr-devel])],
[#include <X11/Xlib.h>])

if test "x$enable_utmp" = "xyes"
then
AC_CHECK_HEADERS(utmp.h utmpx.h)

# Test for non-standard extensions in struct utmpx
AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_host], [HAVE_UTMPX_UT_HOST])
AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_exit], [HAVE_UTMPX_UT_EXIT])
fi

CFLAGS="$save_CFLAGS"

# perform unit tests if libcheck and libmocka found
Expand Down Expand Up @@ -631,6 +646,12 @@ echo " ipv6only $enable_ipv6only"
echo " vsock $enable_vsock"
echo " auth mechanism $auth_mech"
echo " rdpsndaudin $enable_rdpsndaudin"
echo " utmp support $enable_utmp"
if test x$enable_utmp = xyes; then
echo " utmpx.ut_host $ac_cv_utmpx_has_ut_host"
echo " utmpx.ut_exit $ac_cv_utmpx_has_ut_exit"
fi

echo
echo " with imlib2 $use_imlib2"
echo " with freetype2 $use_freetype2"
Expand Down
4 changes: 3 additions & 1 deletion instfiles/pam.d/xrdp-sesman.arch
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#%PAM-1.0
auth include system-remote-login
-auth optional pam_gnome_keyring.so
-auth optional pam_kwallet5.so
Expand All @@ -8,5 +7,8 @@ account include system-remote-login
password include system-remote-login

session include system-remote-login
# For wtmp/lastlog support uncomment one of the following lines:-
#session optional pam_lastlog.so quiet
#session optional pam_lastlog2.so silent
-session optional pam_gnome_keyring.so auto_start
-session optional pam_kwallet5.so auto_start
4 changes: 4 additions & 0 deletions instfiles/pam.d/xrdp-sesman.debian
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ auth required pam_env.so readenv=1 envfile=/etc/default/locale

@include common-password

# Set the loginuid process attribute.
session required pam_loginuid.so
# Update wtmp/lastlog
session optional pam_lastlog.so quiet
@include common-session
-session optional pam_gnome_keyring.so auto_start
-session optional pam_kwallet5.so auto_start
6 changes: 6 additions & 0 deletions instfiles/pam.d/xrdp-sesman.redhat
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#%PAM-1.0
auth include password-auth
account include password-auth

# Set the loginuid process attribute.
session required pam_loginuid.so
# Update wtmp/lastlog
session optional pam_lastlog.so quiet

session include password-auth
password include password-auth
6 changes: 6 additions & 0 deletions instfiles/pam.d/xrdp-sesman.suse
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#%PAM-1.0
auth include common-auth
account include common-account

# Set the loginuid process attribute.
session required pam_loginuid.so
# Update lastlog database
session optional pam_lastlog2.so silent

session include common-session
password include common-password
4 changes: 4 additions & 0 deletions instfiles/pam.d/xrdp-sesman.system
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
auth include system-auth
account include system-auth
password include system-auth

# For wtmp/lastlog support uncomment one of the following lines:-
#session optional pam_lastlog.so quiet
#session optional pam_lastlog2.so silent
session include system-auth
43 changes: 43 additions & 0 deletions m4/axrdp.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# SYNOPSIS
#
# AXRDP_CHECK_UTMPX_MEMBER_EXISTS(MEMBER, COMPILE-DEFINE)
#
# EXAMPLE
#
# AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_exit], [HAVE_UTMPX_UT_EXIT])
#
# DESCRIPTION
#
# If the member MEMBER exists in the utmpx struct, the COMPILE-DEFINE
# is set for the C compiler.
#
# The shell variable 'ac_cv_utmpx_has_$MEMBER' is set to 'yes' or 'no'
# and cached
#
AC_DEFUN([AXRDP_CHECK_UTMPX_MEMBER_EXISTS],
[
AS_VAR_PUSHDEF([x_var], [ac_cv_utmpx_has_$1])
AS_VAR_PUSHDEF([x_define], [$2])
AC_CACHE_CHECK(
[for $1 in struct utmpx],
[x_var],
[AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([[
# include <utmpx.h>
# include <stddef.h>
int main()
{
return offsetof(struct utmpx,$1);
}]])],
[AS_VAR_SET([x_var], [yes])],
[AS_VAR_SET([x_var], [no])])]
)
AS_VAR_IF(
[x_var],
[yes],
[AC_DEFINE([x_define], [1], [Define if '$1' is in struct utmpx.])])
AS_VAR_POPDEF([x_var])
AS_VAR_POPDEF([x_define])
])


6 changes: 6 additions & 0 deletions sesman/sesexec/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ AM_CPPFLAGS = \

SESEXEC_EXTRA_LIBS =

if XRDP_UTMP
AM_CPPFLAGS += -DUSE_UTMP
endif

pkglibexec_PROGRAMS = \
xrdp-sesexec

Expand All @@ -25,6 +29,8 @@ xrdp_sesexec_SOURCES = \
env.h \
login_info.c \
login_info.h \
sessionrecord.c \
sessionrecord.h \
xauth.c \
xauth.h \
xwait.c \
Expand Down
2 changes: 1 addition & 1 deletion sesman/sesexec/sesexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ sesexec_terminate_main_loop(int status)
static void
process_sigchld_event(void)
{
struct exit_status e;
struct proc_exit_status e;
int pid;

// Check for any finished children
Expand Down
13 changes: 8 additions & 5 deletions sesman/sesexec/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "login_info.h"
#include "os_calls.h"
#include "sesexec.h"
#include "sessionrecord.h"
#include "string_calls.h"
#include "xauth.h"
#include "xwait.h"
Expand Down Expand Up @@ -656,6 +657,7 @@ session_start_wrapped(struct login_info *login_info,
}
else
{
utmp_login(window_manager_pid, s->display, login_info);
LOG(LOG_LEVEL_INFO,
"Starting the xrdp channel server for display :%d",
s->display);
Expand Down Expand Up @@ -807,11 +809,11 @@ cleanup_sockets(int uid, int display)

/******************************************************************************/
static void
exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
exit_status_to_str(const struct proc_exit_status *e, char buff[], int bufflen)
{
switch (e->reason)
{
case E_XR_STATUS_CODE:
case E_PXR_STATUS_CODE:
if (e->val == 0)
{
g_snprintf(buff, bufflen, "exit code zero");
Expand All @@ -822,7 +824,7 @@ exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
}
break;

case E_XR_SIGNAL:
case E_PXR_SIGNAL:
{
char sigstr[MAXSTRSIGLEN];
g_snprintf(buff, bufflen, "signal %s",
Expand All @@ -840,7 +842,7 @@ exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
void
session_process_child_exit(struct session_data *sd,
int pid,
const struct exit_status *e)
const struct proc_exit_status *e)
{
if (pid == sd->x_server)
{
Expand All @@ -860,7 +862,7 @@ session_process_child_exit(struct session_data *sd,
{
int wm_wait_time = g_time1() - sd->start_time;

if (e->reason == E_XR_STATUS_CODE && e->val == 0)
if (e->reason == E_PXR_STATUS_CODE && e->val == 0)
{
LOG(LOG_LEVEL_INFO,
"Window manager (pid %d, display %d) "
Expand All @@ -886,6 +888,7 @@ session_process_child_exit(struct session_data *sd,
sd->win_mgr, sd->params.display, wm_wait_time);
}

utmp_logout(sd->win_mgr, sd->params.display, e);
sd->win_mgr = -1;

if (sd->x_server > 0)
Expand Down
4 changes: 2 additions & 2 deletions sesman/sesexec/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "xrdp_constants.h"

struct login_info;
struct exit_status;
struct proc_exit_status;

/**
* Information used to start a session
Expand Down Expand Up @@ -89,7 +89,7 @@ session_start(struct login_info *login_info,
void
session_process_child_exit(struct session_data *sd,
int pid,
const struct exit_status *e);
const struct proc_exit_status *e);

/**
* Returns a count of active processes in the session
Expand Down
Loading
Loading