]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-util: tighten shell validation a tiny bit
authorLennart Poettering <lennart@poettering.net>
Thu, 24 Oct 2024 08:50:16 +0000 (10:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 24 Oct 2024 20:28:17 +0000 (22:28 +0200)
src/basic/user-util.c
src/basic/user-util.h
src/test/test-user-util.c

index 6de5e4705ebc043a98a7255ff63408f21aff4fcc..9dcf16d7a434fab38eca9022f99bb1a05a5b01ff 100644 (file)
@@ -884,6 +884,17 @@ bool valid_home(const char *p) {
         return true;
 }
 
+bool valid_shell(const char *p) {
+        /* We have the same requirements, so just piggy-back on the home check.
+         *
+         * Let's ignore /etc/shells because this is only applicable to real and not system users. It is also
+         * incompatible with the idea of empty /etc/. */
+        if (!valid_home(p))
+                return false;
+
+        return !endswith(p, "/"); /* one additional restriction: shells may not be dirs */
+}
+
 int maybe_setgroups(size_t size, const gid_t *list) {
         int r;
 
index 9d07ef31d22d852dcb93f1d717e2ff09d38aa2ef..777451b8c88ce91df9668daad79ed632663807d8 100644 (file)
@@ -108,15 +108,7 @@ bool valid_user_group_name(const char *u, ValidUserFlags flags);
 bool valid_gecos(const char *d);
 char* mangle_gecos(const char *d);
 bool valid_home(const char *p);
-
-static inline bool valid_shell(const char *p) {
-        /* We have the same requirements, so just piggy-back on the home check.
-         *
-         * Let's ignore /etc/shells because this is only applicable to real and
-         * not system users. It is also incompatible with the idea of empty /etc.
-         */
-        return valid_home(p);
-}
+bool valid_shell(const char *p);
 
 int maybe_setgroups(size_t size, const gid_t *list);
 
index e21d8da478a66bb414ffcfb63175975841b0208e..af06161bad39ef42369f320587d71467cc11c7d8 100644 (file)
@@ -318,6 +318,24 @@ TEST(valid_home) {
         assert_se(valid_home("/"));
         assert_se(valid_home("/home"));
         assert_se(valid_home("/home/foo"));
+        assert_se(valid_home("/home/foo/"));
+}
+
+TEST(valid_shell) {
+        assert_se(!valid_shell(NULL));
+        assert_se(!valid_shell(""));
+        assert_se(!valid_shell("."));
+        assert_se(!valid_shell("/shell/.."));
+        assert_se(!valid_shell("/shell/../"));
+        assert_se(!valid_shell("/shell\n/foo"));
+        assert_se(!valid_shell("./piep"));
+        assert_se(!valid_shell("piep"));
+        assert_se(!valid_shell("/shell/user:lennart"));
+        assert_se(!valid_shell("/"));
+        assert_se(!valid_shell("/bin/sh/"));
+        assert_se(valid_shell("/shell"));
+        assert_se(valid_shell("/shell/foo"));
+        assert_se(valid_shell("/bin/sh"));
 }
 
 static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) {