Compare commits

...

4 Commits

Author SHA1 Message Date
neeshy 4cd0b14380 su: don't set $PATH
Just /bin is too restrictive, and login shells set the path anyway via
the default profile. Also, carrying the path over for non-login shells
conforms to the behavior of util-linux's su.
2024-03-06 10:12:49 +01:00
neeshy e9bcdcc341 su: check $SHELL for validity
If $SHELL isn't defined in the environment, the call to execve will
fail when -p is specified. Fallback to the user's login shell if $SHELL
is invalid.
2024-03-06 10:11:29 +01:00
neeshy cf9e26d7fa su: fix setting argv0
argv0 was being set to the user's login shell even when -p was
specified. Only populate newargv once the shell is properly determined.
2024-03-06 10:11:23 +01:00
neeshy 8f5a0c3236 su: simplify logic
Inline dologin, and simplify common code
2024-03-06 10:11:07 +01:00
2 changed files with 28 additions and 46 deletions

View File

@ -1,6 +1,5 @@
/* See LICENSE file for copyright and license details. */
#define ENV_SUPATH "/bin"
#define ENV_PATH "/bin"
#define PW_CIPHER "$6$" /* SHA-512 */
#undef UTMP_PATH

73
su.c
View File

@ -9,7 +9,6 @@
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "passwd.h"
#include "util.h"
@ -18,28 +17,6 @@ extern char **environ;
static int lflag = 0;
static int pflag = 0;
static int
dologin(struct passwd *pw)
{
char *shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell;
char *term = getenv("TERM");
clearenv();
setenv("HOME", pw->pw_dir, 1);
setenv("SHELL", shell, 1);
setenv("USER", pw->pw_name, 1);
setenv("LOGNAME", pw->pw_name, 1);
setenv("TERM", term ? term : "linux", 1);
if (strcmp(pw->pw_name, "root") == 0)
setenv("PATH", ENV_SUPATH, 1);
else
setenv("PATH", ENV_PATH, 1);
if (chdir(pw->pw_dir) < 0)
eprintf("chdir %s:", pw->pw_dir);
execlp(shell, shell, "-l", NULL);
weprintf("execlp %s:", shell);
return (errno == ENOENT) ? 127 : 126;
}
static void
usage(void)
{
@ -50,9 +27,9 @@ int
main(int argc, char *argv[])
{
char *usr = "root", *pass;
char *shell;
char *shell, *envshell, *term;
struct passwd *pw;
char *newargv[2];
char *newargv[3];
uid_t uid;
ARGBEGIN {
@ -66,12 +43,9 @@ main(int argc, char *argv[])
usage();
} ARGEND;
if (argc < 1)
;
else if (argc == 1)
usr = argv[0];
else
if (argc != 1)
usage();
usr = argv[0];
errno = 0;
pw = getpwnam(usr);
@ -98,13 +72,26 @@ main(int argc, char *argv[])
if (setuid(pw->pw_uid) < 0)
eprintf("setuid:");
shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell;
if (lflag) {
return dologin(pw);
} else {
shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell;
term = getenv("TERM");
clearenv();
setenv("HOME", pw->pw_dir, 1);
setenv("SHELL", shell, 1);
setenv("USER", pw->pw_name, 1);
setenv("LOGNAME", pw->pw_name, 1);
setenv("TERM", term ? term : "linux", 1);
if (chdir(pw->pw_dir) < 0)
eprintf("chdir %s:", pw->pw_dir);
newargv[0] = shell;
newargv[1] = NULL;
if (!pflag) {
newargv[1] = "-l";
newargv[2] = NULL;
} else {
if (pflag) {
envshell = getenv("SHELL");
if (envshell && envshell[0] != '\0')
shell = envshell;
} else {
setenv("HOME", pw->pw_dir, 1);
setenv("SHELL", shell, 1);
if (strcmp(pw->pw_name, "root") != 0) {
@ -112,14 +99,10 @@ main(int argc, char *argv[])
setenv("LOGNAME", pw->pw_name, 1);
}
}
if (strcmp(pw->pw_name, "root") == 0)
setenv("PATH", ENV_SUPATH, 1);
else
setenv("PATH", ENV_PATH, 1);
execve(pflag ? getenv("SHELL") : shell,
newargv, environ);
weprintf("execve %s:", shell);
return (errno == ENOENT) ? 127 : 126;
newargv[0] = shell;
newargv[1] = NULL;
}
return 0;
}
execve(shell, newargv, environ);
weprintf("execve %s:", shell);
return (errno == ENOENT) ? 127 : 126;
}