From 255ebaf535c9f6d8a88e23d55d8be04b0ea73343 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 27 Mar 2023 08:57:40 +0100 Subject: drop: adjust environment on privilege change Some environment variables are subject to special treatment: USER, LOGNAME, HOME and SHELL are initialised when the shell starts if they don't already have a value. Some adjustments are necessary when changing privilege level: - USERNAME is added to the set of variables subject to special treatment. Unlike the others this is normally set on Windows. - The special variables are now also updated on shell start up if the current process is running with elevated privileges. This is necessary so USER, USERNAME and LOGNAME have the correct value. - USER, USERNAME and LOGNAME are set to the name of the unprivileged user when elevated privileges are dropped, though not if they've been changed from the expected value of "root". Costs 160-208 bytes. (GitHub issue #300) --- miscutils/drop.c | 16 ++++++++++++++++ shell/ash.c | 11 ++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/miscutils/drop.c b/miscutils/drop.c index 6effc1831..db3d709d1 100644 --- a/miscutils/drop.c +++ b/miscutils/drop.c @@ -58,6 +58,18 @@ #include #include "NUM_APPLETS.h" +// Set an environment variable to the name of the unprivileged user, +// but only if it was previously unset or contained "root". +static void setenv_name(const char *key) +{ + const char *name = get_user_name(); + const char *oldname = getenv(key); + + if (name && (!oldname || strcmp(oldname, "root") == 0)) { + setenv(key, name, 1); + } +} + int drop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int drop_main(int argc, char **argv) { @@ -166,6 +178,10 @@ int drop_main(int argc, char **argv) si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; + setenv_name("USER"); + setenv_name("USERNAME"); + setenv_name("LOGNAME"); + if (!CreateProcessAsUserA(token, exe, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { xfunc_error_retval = 126; diff --git a/shell/ash.c b/shell/ash.c index d78c6e828..1eddec4ea 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -15550,7 +15550,7 @@ exitshell(void) # undef getenv static void xsetenv_if_unset(const char *key, const char *value) { - if (!getenv(key)) + if (!getenv(key) || getuid() == 0) xsetenv(key, value); } #endif @@ -15641,12 +15641,13 @@ init(void) } /* Initialise some variables normally set at login, but - * only if someone hasn't already set them. */ + * only if someone hasn't already set them or we're root. */ pw = getpwuid(getuid()); if (pw) { - xsetenv_if_unset("USER", pw->pw_name); - xsetenv_if_unset("LOGNAME", pw->pw_name); - xsetenv_if_unset("HOME", pw->pw_dir); + xsetenv_if_unset("USER", pw->pw_name); + xsetenv_if_unset("USERNAME", pw->pw_name); + xsetenv_if_unset("LOGNAME", pw->pw_name); + xsetenv_if_unset("HOME", pw->pw_dir); } xsetenv_if_unset("SHELL", DEFAULT_SHELL); } -- cgit v1.2.3-55-g6feb