Change criteria for expunging items from the user's PATH: instead of
[become] / src / become.c
index c994974..d43bb36 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: become.c,v 1.5 1997/09/05 11:45:19 mdw Exp $
+ * $Id: become.c,v 1.8 1997/09/08 13:56:24 mdw Exp $
  *
  * Main code for `become'
  *
 /*----- Revision history --------------------------------------------------*
  *
  * $Log: become.c,v $
- * Revision 1.5  1997/09/05 11:45:19  mdw
+ * Revision 1.8  1997/09/08 13:56:24  mdw
+ * Change criteria for expunging items from the user's PATH: instead of
+ * removing things starting with `.', remove things not starting with `/'.
+ *
+ * Revision 1.7  1997/09/08  13:43:20  mdw
+ * Change userid when creating tracefiles rather than fiddling with
+ * `access': it works rather better.  Also, insert some stdio buffer
+ * flushing to ensure tracedumps are completely written.
+ *
+ * Revision 1.6  1997/09/05  13:47:44  mdw
+ * Make the `-L' (trace-level) option's argument optional, like the long
+ * version is.
+ *
+ * Revision 1.5  1997/09/05  11:45:19  mdw
  * Add support for different login styles, and environment variable
  * manipulation in a safe and useful way.
  *
@@ -435,7 +448,7 @@ int main(int argc, char *argv[])
     };
 
     i = mdwopt(argc, argv,
-              "-" "huv" "esl" "c:" "dp:f:" T("I:T::L:"),
+              "-" "huv" "esl" "c:" "dp:f:" T("I:T::L::"),
               opts, 0, 0, gFlag_envVar);
     if (i < 0)
       goto done_options;
@@ -528,14 +541,29 @@ int main(int argc, char *argv[])
        if (optarg == 0 || strcmp(optarg, "-") == 0)
          fp = stdout;
        else {
-         if ((flags & f_setuid) && access(optarg, W_OK)) {
-           die("no write permission for trace file file `%s': %s",
-               optarg, strerror(errno));
+         uid_t eu = geteuid(), ru = getuid();
+
+#ifdef HAVE_SETREUID
+         if (setreuid(eu, ru))
+#else
+         if (seteuid(ru))
+#endif
+         {
+           die("couldn't temporarily give up privileges: %s",
+               strerror(errno));
          }
+
          if ((fp = fopen(optarg, "w")) == 0) {
            die("couldn't open trace file `%s' for writing: %s",
                optarg, strerror(errno));
          }
+
+#ifdef HAVE_SETREUID
+          if (setreuid(ru, eu))
+#else
+          if (seteuid(eu))
+#endif
+           die("couldn't regain privileges: %s", strerror(errno));
        }
        traceon(fp, TRACE_DFL);
        trace(TRACE_MISC, "become: tracing enabled");
@@ -829,15 +857,15 @@ done_options:
     static char *preserve[] = {
       "TERM", "DISPLAY", 0
     };
-    
+
     /* --- Variables to be expunged --- *
      *
-     * Any environment string which has one of the following as a prefix
-     * will be expunged from the environment passed to the called process.
-     * The first line lists variables which have been used to list search
-     * paths for shared libraries: by manipulating these, an attacker could
-     * replace a standard library with one of his own.  The second line lists
-     * other well-known dangerous environment variables.
+     * Any environment string which has one of the following as a prefix will
+     * be expunged from the environment passed to the called process.  The
+     * first line lists variables which have been used to list search paths
+     * for shared libraries: by manipulating these, an attacker could replace
+     * a standard library with one of his own.  The second line lists other
+     * well-known dangerous environment variables.
      */
 
     static char *banned[] = {
@@ -854,7 +882,7 @@ done_options:
     size_t sz;
     unsigned f;
     sym_iter i;
-      
+
     /* --- Stage one.  Preserve display-specific variables --- */
 
     for (pp = preserve; *pp; pp++) {
@@ -938,7 +966,7 @@ done_options:
        q = e->val + 5;
 
        for (p = strtok(p, ":"); p; p = strtok(0, ":")) {
-         if (p[0] == '.')
+         if (p[0] != '/')
            continue;
          while (*p)
            *q++ = *p++;
@@ -1030,7 +1058,7 @@ done_options:
       sprintf(rq.cmd, "%s/%s", p, todo[0]);
       if (stat(rq.cmd, &st) == 0 &&    /* Check it exists */
          st.st_mode & 0111 &&          /* Check it's executable */
-         (st.st_mode & S_IFMT) == S_IFREG) /* Check it's a file */
+         S_ISREG(st.st_mode))          /* Check it's a file */
        break;
     }
 
@@ -1152,6 +1180,7 @@ done_options:
   } else {
     if (setuid(rq.to) == -1)
       die("couldn't set uid: %s", strerror(errno));
+    fflush(0);
     execve(rq.cmd, todo, env);
     die("couldn't exec `%s': %s", rq.cmd, strerror(errno));
     return (127);