diff --git a/configure.ac b/configure.ac
index 7acc3352..c89acb8d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -317,6 +317,8 @@ AC_SEARCH_LIBS(gethostbyname, nsl)
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
if test -n "$LIBECONF"; then
+ AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
+ [Directory for distribution provided configuration files])
ECONF_CPPFLAGS="-DUSE_ECONF=1"
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
@@ -324,6 +326,9 @@ fi
AC_SUBST(ECONF_CPPFLAGS)
AC_SUBST(LIBECONF)
AC_SUBST([VENDORDIR], [$enable_vendordir])
+if test "x$enable_vendordir" != x; then
+ AC_DEFINE(HAVE_VENDORDIR, 1, [Define to support vendor settings.])
+fi
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
if test "$enable_shadowgrp" = "yes"; then
@@ -740,4 +745,5 @@ echo " sssd support: $with_sssd"
echo " subordinate IDs support: $enable_subids"
echo " use file caps: $with_fcaps"
echo " install su: $with_su"
+echo " enabled vendor dir: $enable_vendordir"
echo
diff --git a/man/chsh.1.xml b/man/chsh.1.xml
index 373aa928..db2d0ceb 100644
--- a/man/chsh.1.xml
+++ b/man/chsh.1.xml
@@ -115,7 +115,7 @@
NOTE
-
+
The only restriction placed on the login shell is that the command
name must be listed in /etc/shells, unless the
invoker is the superuser, and then any value may be added. An
@@ -125,6 +125,25 @@
changing to a restricted shell would prevent the user from ever
changing her login shell back to its original value.
+
+ The only restriction placed on the login shell is that the command
+ name must be listed in /etc/shells.
+ If this file does not exist, the definitions are taken from the files
+ %vendordir%/shells,
+ %vendordir%/shells.d/* and
+ /etc/shells.d/* in that order.
+ If /etc/shells.d/@filename@ exists, then
+ %vendordir%/shells.d/@filename@ will not be used.
+ If the invoker is the superuser any value may be added regardless what is
+ defined in the configuration files.
+ An account with a restricted login shell may not change her login shell.
+
+
+ For this reason, placing /bin/rsh in
+ /etc/shells is discouraged since accidentally
+ changing to a restricted shell would prevent the user from ever
+ changing her login shell back to its original value.
+
@@ -151,9 +170,31 @@
/etc/shells
-
+
List of valid login shells.
+
+ User defined list of valid login shells.
+
+
+
+ %vendordir%/shells
+
+ Default configuration file if
+ /etc/shells does not exist.
+
+
+
+ %vendordir%/shells.d
+
+ Directory for additional vendor specific configuration files.
+
+
+
+ /etc/shells.d
+
+ Directory for additional user defined configuration files.
+
/etc/login.defs
diff --git a/man/generate_mans.mak b/man/generate_mans.mak
index a0721b85..7cadaa0d 100644
--- a/man/generate_mans.mak
+++ b/man/generate_mans.mak
@@ -1,3 +1,8 @@
+if HAVE_VENDORDIR
+VENDORDIR_COND=with_vendordir
+else
+VENDORDIR_COND=without_vendordir
+endif
if USE_PAM
PAM_COND=pam
else
@@ -35,11 +40,12 @@ if ENABLE_REGENERATE_MAN
fi
man1/% man3/% man5/% man8/%: %.xml-config Makefile config.xml
- $(XSLTPROC) --stringparam profile.condition "$(PAM_COND);$(SHADOWGRP_COND);$(TCB_COND);$(SHA_CRYPT_COND);$(SUBIDS_COND)" \
+ $(XSLTPROC) --stringparam profile.condition "$(PAM_COND);$(SHADOWGRP_COND);$(TCB_COND);$(SHA_CRYPT_COND);$(SUBIDS_COND);$(VENDORDIR_COND)" \
--param "man.authors.section.enabled" "0" \
--stringparam "man.output.base.dir" "" \
+ --stringparam vendordir "$(VENDORDIR)" \
--param "man.output.in.separate.dir" "1" \
- -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/profile-docbook.xsl $<
+ -nonet $(top_builddir)/man/shadow-man.xsl $<
clean-local:
rm -rf man1 man3 man5 man8
diff --git a/man/shadow-man.xsl b/man/shadow-man.xsl
new file mode 100644
index 00000000..a3408e6c
--- /dev/null
+++ b/man/shadow-man.xsl
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index d86a3758..f9ca47f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,7 +11,8 @@ AM_CPPFLAGS = \
-I${top_srcdir}/lib \
-I$(top_srcdir)/libmisc \
-I$(top_srcdir) \
- -DLOCALEDIR=\"$(datadir)/locale\"
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ $(ECONF_CPPFLAGS)
AM_CFLAGS = $(LIBBSD_CFLAGS)
diff --git a/src/chsh.c b/src/chsh.c
index 21d1c3ef..fe0f4609 100644
--- a/src/chsh.c
+++ b/src/chsh.c
@@ -33,6 +33,13 @@
#ifndef SHELLS_FILE
#define SHELLS_FILE "/etc/shells"
#endif
+
+#ifdef HAVE_VENDORDIR
+#include
+#define SHELLS "shells"
+#define ETCDIR "/etc"
+#endif
+
/*
* Global variables
*/
@@ -127,17 +134,59 @@ static bool is_restricted_shell (const char *sh)
* If getusershell() is available (Linux, *BSD, possibly others), use it
* instead of re-implementing it.
*/
+
+#ifdef HAVE_VENDORDIR
static bool shell_is_listed (const char *sh)
{
- char *cp;
bool found = false;
-#ifndef HAVE_GETUSERSHELL
- char buf[BUFSIZ];
- FILE *fp;
-#endif
+ size_t size = 0;
+ econf_err error;
+ char **keys;
+ econf_file *key_file;
+
+ error = econf_readDirs(&key_file,
+ VENDORDIR,
+ ETCDIR,
+ SHELLS,
+ NULL,
+ "", /* key only */
+ "#" /* comment */);
+ if (error) {
+ fprintf (stderr,
+ _("Cannot parse shell files: %s"),
+ econf_errString(error));
+ fail_exit (1);
+ }
+
+ error = econf_getKeys(key_file, NULL, &size, &keys);
+ if (error) {
+ fprintf (stderr,
+ _("Cannot evaluate entries in shell files: %s"),
+ econf_errString(error));
+ econf_free (key_file);
+ fail_exit (1);
+ }
+
+ for (size_t i = 0; i < size; i++) {
+ if (strcmp (keys[i], sh) == 0) {
+ found = true;
+ break;
+ }
+ }
+ econf_free (key_file);
+
+ return found;
+}
+
+#else /* without HAVE_VENDORDIR */
+
+static bool shell_is_listed (const char *sh)
+{
+ bool found = false;
#ifdef HAVE_GETUSERSHELL
+ char *cp;
setusershell ();
while ((cp = getusershell ())) {
if (strcmp (cp, sh) == 0) {
@@ -147,6 +196,9 @@ static bool shell_is_listed (const char *sh)
}
endusershell ();
#else
+ char buf[BUFSIZ];
+ FILE *fp;
+
fp = fopen (SHELLS_FILE, "r");
if (NULL == fp) {
return false;
@@ -171,6 +223,7 @@ static bool shell_is_listed (const char *sh)
#endif
return found;
}
+#endif /* with HAVE_VENDORDIR */
/*
* process_flags - parse the command line options