]> granicus.if.org Git - sudo/commitdiff
now is only root when abs necesary
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 2 Feb 1994 06:30:34 +0000 (06:30 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 2 Feb 1994 06:30:34 +0000 (06:30 +0000)
check.c
logging.c
parse.c
sudo.c
sudo.h

diff --git a/check.c b/check.c
index 85c4fc77e9c09ef4c5fadbd005e2a7bb170c318f..47be50eb7fdf934c9251c8e5261e59c546166ef0 100644 (file)
--- 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;
index a46ebfb11f9191464f03ac828e550ebe30f0cf10..e587e246ef41e8269720b31281a1e5bdd5caa66f 100644 (file)
--- 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 4159ceb11cb7175f6bc24ff55ee157bc9e572b8c..ab7c99a06fc771b358ec93f12959bad7320c4cf2 100644 (file)
--- 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 b757cc3592b799fe054a81e82b8355faf772894f..7b30b5bc93afe08eac0c3c6dce05960e16b8cf7d 100644 (file)
--- 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 373cd3956e3063318138d1aed099e23c961df7ed..91c2f08f7b5c1ffe739e73d18eafce8301b72d65 100644 (file)
--- 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 */