]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
honor settings in /etc/default/su resp /etc/login.defs
authorLudwig Nussel <ludwig.nussel@suse.de>
Mon, 9 Aug 2010 14:03:12 +0000 (16:03 +0200)
committerLudwig Nussel <ludwig.nussel@suse.de>
Thu, 24 May 2012 11:52:43 +0000 (13:52 +0200)
login-utils/getdef.c [new file with mode: 0644]
login-utils/getdef.h [new file with mode: 0644]
login-utils/su.c

diff --git a/login-utils/getdef.c b/login-utils/getdef.c
new file mode 100644 (file)
index 0000000..a2b978a
--- /dev/null
@@ -0,0 +1,259 @@
+/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
+   Author: Thorsten Kukuk <kukuk@suse.de>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 or
+   later as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "getdef.h"
+
+struct item {
+  char *name;         /* Name of the option.  */
+  char *value;        /* Value of the option.  */
+  struct item *next;  /* Pointer to next option.  */
+};
+
+static struct item *list = NULL;
+
+void
+free_getdef_data (void)
+{
+  struct item *ptr;
+
+  ptr = list;
+  while (ptr != NULL)
+    {
+      struct item *tmp;
+      tmp = ptr->next;
+      free (ptr->name);
+      free (ptr->value);
+      free (ptr);
+      ptr = tmp;
+    }
+
+  list = NULL;
+}
+
+/* Add a new entry to the list.  */
+static void
+store (const char *name, const char *value)
+{
+  struct item *new = malloc (sizeof (struct item));
+
+  if (new == NULL)
+    abort ();
+
+  if (name == NULL)
+    abort ();
+
+  new->name = strdup (name);
+  new->value = strdup (value ?: "");
+  new->next = list;
+  list = new;
+}
+
+/* Search a special entry in the list and return the value.  */
+static const char *
+search (const char *name)
+{
+  struct item *ptr;
+
+  ptr = list;
+  while (ptr != NULL)
+    {
+      if (strcasecmp (name, ptr->name) == 0)
+       return ptr->value;
+      ptr = ptr->next;
+    }
+
+  return NULL;
+}
+
+/* Load the login.defs file (/etc/login.defs).  */
+static void
+load_defaults_internal (const char *filename)
+{
+  FILE *fp;
+  char *buf = NULL;
+  size_t buflen = 0;
+
+  fp = fopen (filename, "r");
+  if (NULL == fp)
+    return;
+
+  while (!feof (fp))
+    {
+      char *tmp, *cp;
+#if defined(HAVE_GETLINE)
+      ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM)
+      ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else
+      ssize_t n;
+
+      if (buf == NULL)
+        {
+          buflen = 8096;
+          buf = malloc (buflen);
+        }
+      buf[0] = '\0';
+      fgets (buf, buflen - 1, fp);
+      if (buf != NULL)
+        n = strlen (buf);
+      else
+        n = 0;
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
+      cp = buf;
+
+      if (n < 1)
+        break;
+
+      tmp = strchr (cp, '#');  /* remove comments */
+      if (tmp)
+        *tmp = '\0';
+      while (isspace ((unsigned char) *cp))    /* remove spaces and tabs */
+        ++cp;
+      if (*cp == '\0')        /* ignore empty lines */
+        continue;
+
+      if (cp[strlen (cp) - 1] == '\n')
+        cp[strlen (cp) - 1] = '\0';
+
+      tmp = strsep (&cp, " \t=");
+      if (cp != NULL)
+       while (isspace ((unsigned char) *cp) || *cp == '=')
+         ++cp;
+
+      store (tmp, cp);
+    }
+  fclose (fp);
+
+  if (buf)
+    free (buf);
+}
+
+static void
+load_defaults (void)
+{
+  load_defaults_internal ("/etc/default/su");
+  load_defaults_internal ("/etc/login.defs");
+}
+
+int
+getdef_bool (const char *name, int dflt)
+{
+  const char *val;
+
+  if (list == NULL)
+    load_defaults ();
+
+  val = search (name);
+
+  if (val == NULL)
+    return dflt;
+
+  return (strcasecmp (val, "yes") == 0);
+}
+
+long
+getdef_num (const char *name, long dflt)
+{
+  const char *val;
+  char *cp;
+  long retval;
+
+  if (list == NULL)
+    load_defaults ();
+
+  val = search (name);
+
+  if (val == NULL)
+    return dflt;
+
+  errno = 0;
+  retval = strtol (val, &cp, 0);
+  if (*cp != '\0'
+      || ((retval == LONG_MAX || retval == LONG_MIN) && errno == ERANGE))
+    {
+      fprintf (stderr,
+              "%s contains invalid numerical value: %s!\n",
+              name, val);
+      retval = dflt;
+    }
+  return retval;
+}
+
+unsigned long
+getdef_unum (const char *name, unsigned long dflt)
+{
+  const char *val;
+  char *cp;
+  unsigned long retval;
+
+  if (list == NULL)
+    load_defaults ();
+
+  val = search (name);
+
+  if (val == NULL)
+    return dflt;
+
+  errno = 0;
+  retval = strtoul (val, &cp, 0);
+  if (*cp != '\0' || (retval == ULONG_MAX && errno == ERANGE))
+    {
+      fprintf (stderr,
+              "%s contains invalid numerical value: %s!\n",
+              name, val);
+      retval = dflt;
+    }
+  return retval;
+}
+
+const char *
+getdef_str (const char *name, const char *dflt)
+{
+  const char *retval;
+
+  if (list == NULL)
+    load_defaults ();
+
+  retval = search (name);
+
+  return retval ?: dflt;
+}
+
+#if defined(TEST)
+
+int
+main ()
+{
+  printf ("CYPT=%s\n", getdef_str ("cRypt", "no"));
+  printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab",""));
+  printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes"));
+  return 0;
+}
+
+#endif
diff --git a/login-utils/getdef.h b/login-utils/getdef.h
new file mode 100644 (file)
index 0000000..a5ebaf5
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 2003, 2005 Thorsten Kukuk
+   Author: Thorsten Kukuk <kukuk@suse.de>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 or
+   later as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _GETDEF_H_
+
+#define _GETDEF_H_ 1
+
+extern int getdef_bool (const char *name, int dflt);
+extern long getdef_num (const char *name, long dflt);
+extern unsigned long getdef_unum (const char *name, unsigned long dflt);
+extern const char *getdef_str (const char *name, const char *dflt);
+
+/* Free all data allocated by getdef_* calls before.  */
+extern void free_getdef_data (void);
+
+#endif /* _GETDEF_H_ */
index 237527ef9310576afa57ad8cf66dbf2f240e8382..69043f6952c1d2537add19679ce67a430f00e718 100644 (file)
 # include <paths.h>
 #endif
 
+#include "getdef.h"
+
 /* The default PATH for simulated logins to non-superuser accounts.  */
 #define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin"
 
@@ -491,23 +493,29 @@ modify_environment (const struct passwd *pw, const char *shell)
       xsetenv ("USER", pw->pw_name);
       xsetenv ("LOGNAME", pw->pw_name);
       xsetenv ("PATH", (pw->pw_uid
-                       ? DEFAULT_LOGIN_PATH
-                       : DEFAULT_ROOT_LOGIN_PATH));
+                       ? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
+                       : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
     }
   else
     {
       /* Set HOME, SHELL, and if not becoming a super-user,
         USER and LOGNAME.  */
       if (change_environment)
-       {
-         xsetenv ("HOME", pw->pw_dir);
-         xsetenv ("SHELL", shell);
-         if (pw->pw_uid)
-           {
-             xsetenv ("USER", pw->pw_name);
-             xsetenv ("LOGNAME", pw->pw_name);
-           }
-       }
+        {
+          xsetenv ("HOME", pw->pw_dir);
+          xsetenv ("SHELL", shell);
+         if (getdef_bool ("ALWAYS_SET_PATH", 0))
+           xsetenv ("PATH", (pw->pw_uid
+                             ? getdef_str ("PATH",
+                                           DEFAULT_LOGIN_PATH)
+                             : getdef_str ("SUPATH",
+                                           DEFAULT_ROOT_LOGIN_PATH)));
+          if (pw->pw_uid)
+            {
+              xsetenv ("USER", pw->pw_name);
+              xsetenv ("LOGNAME", pw->pw_name);
+            }
+        }
     }
 
 #ifdef USE_PAM
@@ -736,6 +744,7 @@ main (int argc, char **argv)
 #ifdef SYSLOG_FAILURE
       log_su (pw, false);
 #endif
+      sleep (getdef_num ("FAIL_DELAY", 1));
       error (EXIT_FAIL, 0, _("incorrect password"));
     }
 #ifdef SYSLOG_SUCCESS