{
char **ep, **nep;
static char *newenv[7];
+ extern char *prev_user;
for (ep = envp; *ep; ep++) {
switch (**ep) {
case 'S':
if (strncmp("SHELL=", *ep, 6) == 0)
user_shell = *ep + 6;
- else if (!user_prompt && !strncmp("SUDO_PROMPT=", *ep, 12))
+ else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
user_prompt = *ep + 12;
+ else if (strncmp("SUDO_USER=", *ep, 10) == 0)
+ prev_user = *ep + 10;
continue;
case 'T':
if (strncmp("TZ=", *ep, 3) == 0)
*/
int Argc, NewArgc;
char **Argv, **NewArgv;
+char *prev_user;
struct sudo_user sudo_user;
struct passwd *auth_pw;
FILE *sudoers_fp;
/*
* Get a local copy of the user's struct passwd with the shadow password
* if necessary. It is assumed that euid is 0 at this point so we
- * can read the shadow passwd file if necessary.
+ * can read the shadow passwd file if necessary. If we are being run
+ * as root and the user is chaining sudo commands, use the SUDO_USER
+ * environment variable to determine the user's real identity.
+ * It is not safe to trust SUDO_USER if the real uid != 0.
*/
- if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
+ if (getuid() == 0 && prev_user != NULL)
+ sudo_user.pw = sudo_getpwnam(prev_user);
+ else
+ sudo_user.pw = sudo_getpwuid(getuid());
+ if (sudo_user.pw == NULL) {
/* Need to make a fake struct passwd for logging to work. */
struct passwd pw;
char pw_name[MAX_UID_T_LEN + 1];
char **dst, **src = NewArgv;
NewArgv = (char **) emalloc2((++NewArgc + 1), sizeof(char *));
- if (sudo_mode & MODE_LOGIN_SHELL)
+ if (sudo_mode & MODE_LOGIN_SHELL)
NewArgv[0] = runas_pw->pw_shell;
else if (user_shell && *user_shell)
NewArgv[0] = user_shell;