From: Todd C. Miller Date: Wed, 2 Feb 1994 06:30:34 +0000 (+0000) Subject: now is only root when abs necesary X-Git-Tag: SUDO_1_3_0~22 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=641911504525fd33ca9e5839ef213a4e16b36906;p=sudo now is only root when abs necesary --- diff --git a/check.c b/check.c index 85c4fc77e..47be50eb7 100644 --- a/check.c +++ b/check.c @@ -113,6 +113,8 @@ static int check_timestamp() timedir_is_good = 1; /* now there's an assumption for ya... */ + /* become root */ + be_root(); /* * walk through the path one directory at a time @@ -158,6 +160,9 @@ static int check_timestamp() } } + /* relinquish root */ + be_user(); + return (timestamp_is_old); } @@ -174,12 +179,18 @@ static void update_timestamp() { register int fd; + /* become root */ + be_root(); + if (timedir_is_good) { unlink(timestampfile_p); if ((fd = open(timestampfile_p, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) perror("update_timestamp: open"); close(fd); } + + /* relinquish root */ + be_user(); } @@ -212,12 +223,14 @@ static void check_passwd() exit(1); } #ifdef __svr4__ + be_root(); if ((spw_ent = getspnam(pw_ent->pw_name)) == NULL) { (void) sprintf(user, "%u", uid); log_error(GLOBAL_NO_PW_ENT); inform_user(GLOBAL_NO_PW_ENT); exit(1); } + be_user(); encrypted = spw_ent -> sp_pwdp; #else encrypted = pw_ent -> pw_passwd; diff --git a/logging.c b/logging.c index a46ebfb11..e587e246e 100644 --- a/logging.c +++ b/logging.c @@ -228,6 +228,9 @@ void log_error(code) syslog(pri, logline); closelog(); #else + /* become root */ + be_root(); + if ((fp = fopen(LOGFILE, "a")) == NULL) { (void) sprintf(logline, "Can\'t open log file: %s", LOGFILE); send_mail(); @@ -235,6 +238,9 @@ void log_error(code) (void) fprintf(fp, "%s\n", logline); (void) fclose(fp); } + + /* relinquish root */ + be_user(); #endif } @@ -260,10 +266,18 @@ static void send_mail() int fd[2]; char buf[MAXLOGLEN + 1024]; + /* become root for find_path() */ + be_root(); + if ((mailer = find_path(mailer)) == NULL) { (void) fprintf(stderr, "%s not found\n", mailer); exit(1); } + + /* relinquish root */ + be_user(); + + /* catch children as they die */ (void) signal(SIGCHLD, reapchild); if (fork()) @@ -272,10 +286,8 @@ static void send_mail() /* * we don't want any security problems ... */ - if (setuid(uid)) { - perror("setuid(uid)"); - exit(1); - } + be_full_user(); + (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); diff --git a/parse.c b/parse.c index 4159ceb11..ab7c99a06 100644 --- a/parse.c +++ b/parse.c @@ -427,6 +427,9 @@ int validate() FILE *sudoers_fp; int i, return_code; + /* become root */ + be_root(); + if ((sudoers_fp = fopen(SUDOERS, "r")) == NULL) { perror(SUDOERS); log_error(NO_SUDOERS_FILE); @@ -450,6 +453,9 @@ int validate() */ (void) fclose(sudoers_fp); + /* relinquish root */ + be_user(); + /* * if a parsing error occurred, set return_code accordingly */ diff --git a/sudo.c b/sudo.c index b757cc359..7b30b5bc9 100644 --- a/sudo.c +++ b/sudo.c @@ -124,6 +124,13 @@ main(argc, argv, envp) load_globals(); /* load the user host cmnd and uid variables */ + /* + * We only want to be root when we absolutely need it. + * This will effectively do setreuid(0, uid) but for portability... + */ + be_root(); + be_user(); + clean_envp(envp); /* build Envp based on envp (w/o LD_*) */ rtn = validate(); @@ -132,12 +139,10 @@ main(argc, argv, envp) case VALIDATE_OK: check_user(); log_error(ALL_SYSTEMS_GO); - if (setuid(0)) { - perror("setuid(0)"); - exit(1); - } + be_root(); execve(cmnd, &Argv[1], Envp); - perror(cmnd); + perror(cmnd); /* execve() failed! */ + exit(-1); break; case VALIDATE_NO_USER: @@ -145,19 +150,11 @@ main(argc, argv, envp) case VALIDATE_ERROR: default: log_error(rtn); - if (setuid(uid)) { - perror("setuid(uid)"); - exit(1); - } + be_full_user(); inform_user(rtn); exit(1); break; } - - /* - * If we get here it's an error (execve failed) - */ - return (-1); } @@ -193,7 +190,10 @@ void load_globals() * loading the cmnd global variable from argv[1] */ strncpy(path, Argv[1], MAXPATHLEN)[MAXPATHLEN] = 0; + /* become root for find_path() only */ + be_root(); cmnd = find_path(path); /* get the absolute path */ + be_user(); if (cmnd == NULL) { (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0], Argv[1]); exit(1); @@ -301,3 +301,59 @@ void clean_envp(envp) *tenvp = NULL; } + + + +/********************************************************************** + * + * be_root() + * + * this function sets the real and effective uids to 0 + */ + +void be_root() +{ + if (setuid(0)) { + perror("setuid(0)"); + exit(1); + } +} + + + +/********************************************************************** + * + * be_user() + * + * this function sets the effective uid to the value of uid + */ + +void be_user() +{ + if (seteuid(uid)) { + perror("seteuid(uid)"); + exit(1); + } +} + + + +/********************************************************************** + * + * be_full_user() + * + * this function sets the real and effective uids to the value of uid + * since our euid is probably already uid we need to setuid(0) first + */ + +void be_full_user() +{ + if (setuid(0)) { + perror("setuid(0)"); + exit(1); + } + if (setuid(uid)) { + perror("setuid(uid)"); + exit(1); + } +} diff --git a/sudo.h b/sudo.h index 373cd3956..91c2f08f7 100644 --- a/sudo.h +++ b/sudo.h @@ -272,6 +272,9 @@ void inform_user(); void check_user(); void clean_envp(); int validate(); +void be_root(); +void be_user(); +void be_full_user(); /* Most of these variables are declared in main() so they don't need * to be extern'ed here if this is main... @@ -296,6 +299,7 @@ extern int errno; */ #ifdef hpux #define getdtablesize() (sysconf(_SC_OPEN_MAX)) +#define seteuid(__EUID) (setresuid((uid_t)-1, __EUID, (uid_t)-1)) #ifndef USE_CWD #define USE_CWD #endif /* USE_CWD */