Skip to content

Commit

Permalink
Add utmp/wtmp support
Browse files Browse the repository at this point in the history
Cherry-pick utmpfix_bp..utmpfix_mp aka 28f175b9..2ff3edd0

See:
* PR#2745 "Add utmp/wtmp support"
  neutrinolabs#2745
* Discussion#2744 "utmp/wtmp/btmp/lastlog"
  neutrinolabs#2744
  • Loading branch information
mlewissmith committed Oct 7, 2024
1 parent 1c33f3d commit 951b5ab
Show file tree
Hide file tree
Showing 18 changed files with 390 additions and 39 deletions.
24 changes: 14 additions & 10 deletions common/os_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3286,25 +3286,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 @@ -3319,12 +3319,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 @@ -3365,10 +3365,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 @@ -3383,12 +3387,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 @@ -6,6 +6,7 @@ AC_DEFINE([VERSION_YEAR], 2024, [Copyright year])
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 @@ -183,6 +184,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 @@ -515,6 +521,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 @@ -632,6 +647,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

0 comments on commit 951b5ab

Please sign in to comment.