Add support for a vendor directory and libeconf

With this, it is possible for Linux distributors to store their
supplied default configuration files somewhere below /usr, while
/etc only contains the changes made by the user. The new option
--enable-vendordir defines where the shadow suite should additional
look for login.defs if this file is not in /etc.
libeconf is a key/value configuration file reading library, which
handles the split of configuration files in different locations
and merges them transparently for the application.
This commit is contained in:
Thorsten Kukuk 2019-09-20 10:27:31 +02:00 committed by Serge Hallyn
parent a74587a4ea
commit b52ce71c27
6 changed files with 132 additions and 36 deletions

View File

@ -321,6 +321,17 @@ AC_SEARCH_LIBS(inet_ntoa, inet)
AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(socket, socket)
AC_SEARCH_LIBS(gethostbyname, nsl) AC_SEARCH_LIBS(gethostbyname, nsl)
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
if test -n "$LIBECONF"; then
ECONF_CPPFLAGS="-DUSE_ECONF=1"
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
fi
AC_SUBST(ECONF_CPPFLAGS)
AC_SUBST(LIBECONF)
AC_SUBST([VENDORDIR], [$enable_vendordir])
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
if test "$enable_shadowgrp" = "yes"; then if test "$enable_shadowgrp" = "yes"; then
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.]) AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
fi fi

View File

@ -6,6 +6,10 @@ DEFS =
noinst_LTLIBRARIES = libshadow.la noinst_LTLIBRARIES = libshadow.la
libshadow_la_LDFLAGS = -version-info 0:0:0 libshadow_la_LDFLAGS = -version-info 0:0:0
libshadow_la_CPPFLAGS = $(ECONF_CPPFLAGS)
if HAVE_VENDORDIR
libshadow_la_CPPFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
endif
libshadow_la_SOURCES = \ libshadow_la_SOURCES = \
commonio.c \ commonio.c \

View File

@ -40,6 +40,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#ifdef USE_ECONF
#include <libeconf.h>
#endif
#include "getdef.h" #include "getdef.h"
/* /*
* A configuration item definition. * A configuration item definition.
@ -152,11 +155,20 @@ static struct itemdef knowndef_table[] = {
{NULL, NULL} {NULL, NULL}
}; };
#ifdef USE_ECONF
#ifdef VENDORDIR
static const char* vendordir = VENDORDIR;
#else
static const char* vendordir = NULL;
#endif
static const char* sysconfdir = "/etc";
#else
#ifndef LOGINDEFS #ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs" #define LOGINDEFS "/etc/login.defs"
#endif #endif
static const char* def_fname = LOGINDEFS; /* login config defs file */ static const char* def_fname = LOGINDEFS; /* login config defs file */
#endif
static bool def_loaded = false; /* are defs already loaded? */ static bool def_loaded = false; /* are defs already loaded? */
/* local function prototypes */ /* local function prototypes */
@ -433,7 +445,27 @@ out:
void setdef_config_file (const char* file) void setdef_config_file (const char* file)
{ {
#ifdef USE_ECONF
size_t len;
char* cp;
len = strlen(file) + strlen(sysconfdir) + 2;
cp = malloc(len);
if (cp == NULL)
exit (13);
snprintf(cp, len, "%s/%s", file, sysconfdir);
sysconfdir = cp;
#ifdef VENDORDIR
len = strlen(file) + strlen(vendordir) + 2;
cp = malloc(len);
if (cp == NULL)
exit (13);
snprintf(cp, len, "%s/%s", file, vendordir);
vendordir = cp;
#endif
#else
def_fname = file; def_fname = file;
#endif
} }
/* /*
@ -444,9 +476,16 @@ void setdef_config_file (const char* file)
static void def_load (void) static void def_load (void)
{ {
#ifdef USE_ECONF
econf_file *defs_file = NULL;
econf_err error;
char **keys;
size_t key_number;
#else
int i; int i;
FILE *fp; FILE *fp;
char buf[1024], *name, *value, *s; char buf[1024], *name, *value, *s;
#endif
/* /*
* Set the initialized flag. * Set the initialized flag.
@ -454,6 +493,42 @@ static void def_load (void)
*/ */
def_loaded = true; def_loaded = true;
#ifdef USE_ECONF
error = econf_readDirs (&defs_file, vendordir, sysconfdir, "login", "defs", " \t", "#");
if (error) {
if (error == ECONF_NOFILE)
return;
SYSLOG ((LOG_CRIT, "cannot open login definitions [%s]",
econf_errString(error)));
exit (EXIT_FAILURE);
}
if ((error = econf_getKeys(defs_file, NULL, &key_number, &keys))) {
SYSLOG ((LOG_CRIT, "cannot read login definitions [%s]",
econf_errString(error)));
exit (EXIT_FAILURE);
}
for (size_t i = 0; i < key_number; i++) {
char *value;
econf_getStringValue(defs_file, NULL, keys[i], &value);
/*
* Store the value in def_table.
*
* Ignore failures to load the login.defs file.
* The error was already reported to the user and to
* syslog. The tools will just use their default values.
*/
(void)putdef_str (keys[i], value);
}
econf_free (keys);
econf_free (defs_file);
#else
/* /*
* Open the configuration definitions file. * Open the configuration definitions file.
*/ */
@ -517,6 +592,7 @@ static void def_load (void)
} }
(void) fclose (fp); (void) fclose (fp);
#endif
} }

View File

@ -1,7 +1,7 @@
EXTRA_DIST = .indent.pro xgetXXbyYY.c EXTRA_DIST = .indent.pro xgetXXbyYY.c
AM_CPPFLAGS = -I$(top_srcdir)/lib AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECONF_CPPFLAGS)
noinst_LIBRARIES = libmisc.a noinst_LIBRARIES = libmisc.a

View File

@ -141,10 +141,14 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
sub_gid_setdbname(sgid_db_file); sub_gid_setdbname(sgid_db_file);
#endif #endif
#ifdef USE_ECONF
setdef_config_file(prefix);
#else
len = strlen(prefix) + strlen("/etc/login.defs") + 2; len = strlen(prefix) + strlen("/etc/login.defs") + 2;
def_conf_file = xmalloc(len); def_conf_file = xmalloc(len);
snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs"); snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs");
setdef_config_file(def_conf_file); setdef_config_file(def_conf_file);
#endif
} }
if (prefix == NULL) if (prefix == NULL)

View File

@ -88,42 +88,43 @@ else
LIBCRYPT_NOPAM = $(LIBCRYPT) LIBCRYPT_NOPAM = $(LIBCRYPT)
endif endif
chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
newuidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP) newuidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
newgidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP) newgidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT) chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) expiry_LDADD = $(LDADD) $(LIBECONF)
groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBECONF)
grpck_LDADD = $(LDADD) $(LIBSELINUX) groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF)
grpconv_LDADD = $(LDADD) $(LIBSELINUX) grpck_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
grpunconv_LDADD = $(LDADD) $(LIBSELINUX) grpconv_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
lastlog_LDADD = $(LDADD) $(LIBAUDIT) grpunconv_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF)
login_SOURCES = \ login_SOURCES = \
login.c \ login.c \
login_nopam.c login_nopam.c
login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF)
newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF)
nologin_LDADD = nologin_LDADD =
passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF)
pwck_LDADD = $(LDADD) $(LIBSELINUX) pwck_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
pwconv_LDADD = $(LDADD) $(LIBSELINUX) pwconv_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
pwunconv_LDADD = $(LDADD) $(LIBSELINUX) pwunconv_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
su_SOURCES = \ su_SOURCES = \
su.c \ su.c \
suauth.c suauth.c
su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF)
sulogin_LDADD = $(LDADD) $(LIBCRYPT) sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF)
useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF)
userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF)
usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF)
vipw_LDADD = $(LDADD) $(LIBSELINUX) vipw_LDADD = $(LDADD) $(LIBSELINUX) $(LIBECONF)
install-am: all-am install-am: all-am
$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am $(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am