375 lines
8.8 KiB
Diff
375 lines
8.8 KiB
Diff
|
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
|
||
|
|