]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Supporting vendor given "shells" configuration file
authorStefan Schubert <schubi@suse.de>
Tue, 29 Nov 2022 15:55:04 +0000 (16:55 +0100)
committerStefan Schubert <schubi@suse.de>
Tue, 29 Nov 2022 15:55:04 +0000 (16:55 +0100)
include/shells.h [new file with mode: 0644]
lib/shells.c [new file with mode: 0644]
login-utils/Makemodule.am
login-utils/chsh.c
login-utils/su-common.c

diff --git a/include/shells.h b/include/shells.h
new file mode 100644 (file)
index 0000000..f165693
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef UTIL_LINUX_SHELLS_H
+#define UTIL_LINUX_SHELLS_H
+
+extern int is_known_shell(const char *shell_name);
+
+#endif /* UTIL_LINUX_SHELLS_H */
diff --git a/lib/shells.c b/lib/shells.c
new file mode 100644 (file)
index 0000000..2d3ec01
--- /dev/null
@@ -0,0 +1,72 @@
+
+#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;
+}
+
index 6d35d4dcdc430ba65f9732e92e7fbf1f696cfa54..1c5a11d846b556868ced49e069101be05946a523 100644 (file)
@@ -152,10 +152,13 @@ if HAVE_ECONF
 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
 
 
@@ -167,7 +170,8 @@ su_SOURCES = \
        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
@@ -194,7 +198,8 @@ runuser_SOURCES = \
        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
index b7e70174897eb3464cfd084a12cf12dfa90c4cae..eb02a7271421aeee8ef5c2562824d9d95785166f 100644 (file)
@@ -44,6 +44,7 @@
 #include "xalloc.h"
 
 #include "ch-common.h"
+#include "shells.h"
 
 #ifdef HAVE_LIBSELINUX
 # include <selinux/selinux.h>
@@ -81,28 +82,6 @@ static void __attribute__((__noreturn__)) usage(void)
        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.
  */
index 6f30c607f0204292a96d7e4d9eaa9f34f2e7f884..04ff72c018cbf57b19b6ce5470c4126a65badee1 100644 (file)
@@ -68,6 +68,7 @@
 
 #include "logindefs.h"
 #include "su-common.h"
+#include "shells.h"
 
 #include "debug.h"
 
@@ -867,18 +868,14 @@ static void run_shell(
  */
 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;
 }