use existing logindefs.c and pathnames.h

I'm not sure having /usr/local in _PATH_DEFPATH_ROOT and even putting it
in front is such a good idea though. /usr/local might be on NFS so could
prevent root from logging in if the network is down.
This commit is contained in:
Ludwig Nussel 2012-05-25 10:54:23 +02:00
parent f29fc7e0bb
commit 9c44ac503f
6 changed files with 35 additions and 308 deletions

View File

@ -71,8 +71,8 @@ vipw_SOURCES = \
$(top_srcdir)/lib/fileutils.c
su_SOURCES = \
su.c \
getdef.c \
getdef.h
logindefs.c \
logindefs.h
chfn_LDADD = $(login_ldadd_common)
chsh_LDADD = $(login_ldadd_common)

View File

@ -1,259 +0,0 @@
/* 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

View File

@ -1,29 +0,0 @@
/* 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_ */

View File

@ -45,6 +45,8 @@ struct item {
static struct item *list = NULL;
void (*logindefs_load_defaults)(void) = NULL;
void free_getlogindefs_data(void)
{
struct item *ptr;
@ -77,7 +79,7 @@ static void store(const char *name, const char *value, const char *path)
list = new;
}
static void load_defaults(const char *filename)
void logindefs_load_file(const char *filename)
{
FILE *f;
char buf[BUFSIZ];
@ -139,12 +141,20 @@ static void load_defaults(const char *filename)
fclose(f);
}
static void load_defaults()
{
if (logindefs_load_defaults)
logindefs_load_defaults();
else
logindefs_load_file(_PATH_LOGINDEFS);
}
static struct item *search(const char *name)
{
struct item *ptr;
if (!list)
load_defaults(_PATH_LOGINDEFS);
load_defaults();
ptr = list;
while (ptr != NULL) {
@ -259,7 +269,7 @@ int main(int argc, char *argv[])
errx(EXIT_FAILURE, "usage: %s <filename> "
"[<str|num|bool> <valname>]", argv[0]);
load_defaults(argv[1]);
logindefs_load_file(argv[1]);
if (argc != 4) { /* list all */
struct item *ptr;

View File

@ -1,6 +1,8 @@
#ifndef UTIL_LINUX_LOGINDEFS_H
#define UTIL_LINUX_LOGINDEFS_H
extern void logindefs_load_file(const char *filename);
extern void (*logindefs_load_defaults)(void);
extern int getlogindefs_bool(const char *name, int dflt);
extern long getlogindefs_num(const char *name, long dflt);
extern const char *getlogindefs_str(const char *name, const char *dflt);

View File

@ -69,6 +69,7 @@ enum
#include <stdbool.h>
#include "xalloc.h"
#include "nls.h"
#include "pathnames.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "su"
@ -77,13 +78,7 @@ enum
#define PAM_SERVICE_NAME PROGRAM_NAME
#define PAM_SERVICE_NAME_L PROGRAM_NAME "-l"
#include "getdef.h"
/* The default PATH for simulated logins to non-superuser accounts. */
#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin"
/* The default PATH for simulated logins to superuser accounts. */
#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin"
#include "logindefs.h"
/* The shell to run if none is given in the user's passwd entry. */
#define DEFAULT_SHELL "/bin/sh"
@ -517,8 +512,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
? getdef_str ("PATH", DEFAULT_LOGIN_PATH)
: getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH)));
? getlogindefs_str ("PATH", _PATH_DEFPATH)
: getlogindefs_str ("SUPATH", _PATH_DEFPATH_ROOT)));
}
else
{
@ -528,12 +523,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))
if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
xsetenv ("PATH", (pw->pw_uid
? getdef_str ("PATH",
DEFAULT_LOGIN_PATH)
: getdef_str ("SUPATH",
DEFAULT_ROOT_LOGIN_PATH)));
? getlogindefs_str ("PATH",
_PATH_DEFPATH)
: getlogindefs_str ("SUPATH",
_PATH_DEFPATH_ROOT)));
else
{
char const *path = getenv ("PATH");
@ -687,6 +682,12 @@ A mere - implies -l. If USER not given, assume root.\n\
exit (status);
}
void load_config(void)
{
logindefs_load_file("/etc/default/su");
logindefs_load_file(_PATH_LOGINDEFS);
}
int
main (int argc, char **argv)
{
@ -757,6 +758,8 @@ main (int argc, char **argv)
if (optind < argc)
new_user = argv[optind++];
logindefs_load_defaults = load_config;
pw = getpwnam (new_user);
if (! (pw && pw->pw_name && pw->pw_name[0] && pw->pw_dir && pw->pw_dir[0]
&& pw->pw_passwd))
@ -781,7 +784,7 @@ main (int argc, char **argv)
if (!correct_password (pw))
{
log_su (pw, false);
sleep (getdef_num ("FAIL_DELAY", 1));
sleep (getlogindefs_num ("FAIL_DELAY", 1));
error (EXIT_FAIL, 0, _("incorrect password"));
}
else