]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
make sure /sbin resp /usr/sbin are in PATH
authorWerner Fink <werner@suse.de>
Tue, 17 Aug 2010 07:09:55 +0000 (09:09 +0200)
committerLudwig Nussel <ludwig.nussel@suse.de>
Thu, 24 May 2012 11:52:43 +0000 (13:52 +0200)
login-utils/su.c

index 69043f6952c1d2537add19679ce67a430f00e718..c2311d5a618c87433c06cfd4fc760d83a4653d3f 100644 (file)
@@ -471,6 +471,117 @@ correct_password (const struct passwd *pw)
 #endif /* !USE_PAM */
 }
 
+/* Add or clear /sbin and /usr/sbin for the su command
+   used without `-'.  */
+
+/* Set if /sbin is found in path.  */
+#define SBIN_MASK      0x01
+/* Set if /usr/sbin is found in path.  */
+#define USBIN_MASK     0x02
+
+static char *
+addsbin (const char *const path)
+{
+  unsigned char smask = 0;
+  char *ptr, *tmp, *cur, *ret = NULL;
+  size_t len;
+
+  if (!path || *path == 0)
+    return NULL;
+
+  tmp = xstrdup (path);
+  cur = tmp;
+  for (ptr = strsep (&cur, ":"); ptr != NULL; ptr = strsep (&cur, ":"))
+    {
+      if (!strcmp (ptr, "/sbin"))
+       smask |= SBIN_MASK;
+      if (!strcmp (ptr, "/usr/sbin"))
+       smask |= USBIN_MASK;
+    }
+
+  if ((smask & (USBIN_MASK|SBIN_MASK)) == (USBIN_MASK|SBIN_MASK))
+    {
+      free (tmp);
+      return NULL;
+    }
+
+  len = strlen (path);
+  if (!(smask & USBIN_MASK))
+    len += strlen ("/usr/sbin:");
+
+  if (!(smask & SBIN_MASK))
+    len += strlen (":/sbin");
+
+  ret = xmalloc (len + 1);
+  strcpy (tmp, path);
+
+  *ret = 0;
+  cur = tmp;
+  for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":"))
+    {
+      if (!strcmp (ptr, "."))
+       continue;
+      if (*ret)
+       strcat (ret, ":");
+      if (!(smask & USBIN_MASK) && !strcmp (ptr, "/bin"))
+       {
+         strcat (ret, "/usr/sbin:");
+         strcat (ret, ptr);
+         smask |= USBIN_MASK;
+         continue;
+       }
+      if (!(smask & SBIN_MASK) && !strcmp (ptr, "/usr/bin"))
+       {
+         strcat (ret, ptr);
+         strcat (ret, ":/sbin");
+         smask |= SBIN_MASK;
+         continue;
+       }
+      strcat (ret, ptr);
+    }
+  free (tmp);
+
+  if (!(smask & USBIN_MASK))
+    strcat (ret, ":/usr/sbin");
+
+  if (!(smask & SBIN_MASK))
+    strcat (ret, ":/sbin");
+
+  return ret;
+}
+
+static char *
+clearsbin (const char *const path)
+{
+  char *ptr, *tmp, *cur, *ret = NULL;
+
+  if (!path || *path == 0)
+    return NULL;
+
+  tmp = strdup (path);
+  if (!tmp)
+    return NULL;
+
+  ret = xmalloc (strlen (path) + 1);
+  *ret = 0;
+  cur = tmp;
+  for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":"))
+    {
+      if (!strcmp (ptr, "/sbin"))
+       continue;
+      if (!strcmp (ptr, "/usr/sbin"))
+       continue;
+      if (!strcmp (ptr, "/usr/local/sbin"))
+       continue;
+      if (*ret)
+       strcat (ret, ":");
+      strcat (ret, ptr);
+    }
+  free (tmp);
+
+  return ret;
+}
+
 /* Update `environ' for the new shell based on PW, with SHELL being
    the value for the SHELL environment variable.  */
 
@@ -510,6 +621,22 @@ modify_environment (const struct passwd *pw, const char *shell)
                                            DEFAULT_LOGIN_PATH)
                              : getdef_str ("SUPATH",
                                            DEFAULT_ROOT_LOGIN_PATH)));
+         else
+           {
+             char const *path = getenv ("PATH");
+             char *new = NULL;
+
+             if (pw->pw_uid)
+               new = clearsbin (path);
+             else
+               new = addsbin (path);
+
+             if (new)
+               {
+                 xsetenv ("PATH", new);
+                 free (new);
+               }
+           }
           if (pw->pw_uid)
             {
               xsetenv ("USER", pw->pw_name);