--- /dev/null
+#ifndef UTIL_LINUX_SHELLS_H
+#define UTIL_LINUX_SHELLS_H
+
+extern int is_known_shell(const char *shell_name);
+
+#endif /* UTIL_LINUX_SHELLS_H */
--- /dev/null
+
+#include <sys/syslog.h>
+#if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
+#include <libeconf.h>
+#endif
+
+#include "closestream.h"
+#include "shells.h"
+
+/*
+ * is_known_shell() -- if the given shell appears in /etc/shells
+ * or vendor defined files.
+ * Return 1 if found and return 0 if not found.
+ */
+extern int is_known_shell(const char *shell_name)
+{
+ int ret = 0;
+
+#if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
+ size_t size = 0;
+ econf_err error;
+ char **keys;
+ econf_file *key_file;
+
+ error = econf_readDirs(&key_file,
+ _PATH_VENDORDIR,
+ "/etc",
+ "shells",
+ NULL,
+ "", /* key only */
+ "#" /* comment */);
+ if (error) {
+ syslog(LOG_ALERT,
+ _("Cannot parse shells files: %s"),
+ econf_errString(error));
+ exit(EXIT_FAILURE);
+ }
+
+ error = econf_getKeys(key_file, NULL, &size, &keys);
+ if (error) {
+ syslog(LOG_ALERT,
+ _("Cannot evaluate entries in shells files: %s"),
+ econf_errString(error));
+ econf_free (key_file);
+ exit(EXIT_FAILURE);
+ }
+
+ for (size_t i = 0; i < size; i++) {
+ if (strcmp (keys[i], shell_name) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ econf_free (key_file);
+#else
+ char *s;
+
+ if (!shell_name)
+ return 0;
+
+ setusershell();
+ while ((s = getusershell())) {
+ if (strcmp(shell_name, s) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ endusershell();
+#endif
+ return ret;
+}
+
chfn_LDADD += -leconf
endif
-chsh_SOURCES = login-utils/chsh.c $(chfn_chsh_sources)
+chsh_SOURCES = login-utils/chsh.c lib/shells.c $(chfn_chsh_sources)
chsh_CFLAGS = $(chfn_chsh_cflags)
chsh_LDFLAGS = $(chfn_chsh_ldflags)
chsh_LDADD = $(LDADD) $(chfn_chsh_ldadd)
+if HAVE_ECONF
+chsh_LDADD += -leconf
+endif
endif # BUILD_CHFN_CHSH
login-utils/su.c \
login-utils/su-common.c \
login-utils/su-common.h \
- lib/logindefs.c
+ lib/logindefs.c \
+ lib/shells.c
su_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS)
su_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
su_LDADD = $(LDADD) libcommon.la -lpam
login-utils/runuser.c \
login-utils/su-common.c \
login-utils/su-common.h \
- lib/logindefs.c
+ lib/logindefs.c \
+ lib/shells.c
runuser_LDADD = $(LDADD) libcommon.la -lpam
if HAVE_LINUXPAM
runuser_LDADD += -lpam_misc
#include "xalloc.h"
#include "ch-common.h"
+#include "shells.h"
#ifdef HAVE_LIBSELINUX
# include <selinux/selinux.h>
exit(EXIT_SUCCESS);
}
-/*
- * is_known_shell() -- if the given shell appears in /etc/shells,
- * return true. if not, return false.
- */
-static int is_known_shell(const char *shell_name)
-{
- char *s, ret = 0;
-
- if (!shell_name)
- return 0;
-
- setusershell();
- while ((s = getusershell())) {
- if (strcmp(shell_name, s) == 0) {
- ret = 1;
- break;
- }
- }
- endusershell();
- return ret;
-}
-
/*
* print_shells () -- /etc/shells is outputted to stdout.
*/
#include "logindefs.h"
#include "su-common.h"
+#include "shells.h"
#include "debug.h"
*/
static bool is_restricted_shell(const char *shell)
{
- char *line;
-
- setusershell();
- while ((line = getusershell()) != NULL) {
- if (*line != '#' && !strcmp(line, shell)) {
- endusershell();
- return false;
- }
+ if (is_known_shell(shell)) {
+ return false;
}
- endusershell();
-
+#ifdef USE_VENDORDIR
+ DBG(MISC, ul_debug("%s is restricted shell (not in e.g. vendor shells file, /etc/shells, ...)", shell));
+#else
DBG(MISC, ul_debug("%s is restricted shell (not in /etc/shells)", shell));
+#endif
return true;
}