File coreutils-8.6-honor-settings-in-etc-default-su-resp-etc-login.defs.diff of Package coreutils.import4829

From d776b1b67eb1bc1b815426fdf22f38b25ef1e2df Mon Sep 17 00:00:00 2001
From: Ludwig Nussel <ludwig.nussel@suse.de>
Date: Mon, 9 Aug 2010 16:03:12 +0200
Subject: [PATCH 5/7] honor settings in /etc/default/su resp /etc/login.defs

---
 src/Makefile.am |    1 +
 src/getdef.c    |  259 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/getdef.h    |   29 ++++++
 src/su.c        |   13 +++-
 4 files changed, 300 insertions(+), 2 deletions(-)
 create mode 100644 src/getdef.c
 create mode 100644 src/getdef.h

diff --git a/src/Makefile.am b/src/Makefile.am
index bc27274..484f6c2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -352,6 +352,7 @@ factor_LDADD += $(LIB_GMP)
 uptime_LDADD += $(GETLOADAVG_LIBS)
 
 # for crypt and pam
+su_SOURCES = su.c getdef.c
 su_LDADD += $(LIB_CRYPT) $(PAM_LIBS)
 
 # for various ACL functions
diff --git a/src/getdef.c b/src/getdef.c
new file mode 100644
index 0000000..e1872cf
--- /dev/null
+++ b/src/getdef.c
@@ -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 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/src/getdef.h b/src/getdef.h
new file mode 100644
index 0000000..2e86cf9
--- /dev/null
+++ b/src/getdef.h
@@ -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 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_ */
diff --git a/src/su.c b/src/su.c
index 0071622..eaef195 100644
--- a/src/su.c
+++ b/src/su.c
@@ -111,6 +111,8 @@
 # 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"
 
@@ -475,8 +477,8 @@ 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
     {
@@ -486,6 +488,12 @@ modify_environment (const struct passwd *pw, const char *shell)
         {
           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);
@@ -720,6 +728,7 @@ main (int argc, char **argv)
 #ifdef SYSLOG_FAILURE
       log_su (pw, false);
 #endif
+      sleep (getdef_num ("FAIL_DELAY", 1));
       error (EXIT_CANCELED, 0, _("incorrect password"));
     }
 #ifdef SYSLOG_SUCCESS
-- 
1.7.1
openSUSE Build Service is sponsored by