diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 6de5e4705e..9dcf16d7a4 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -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; diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 9d07ef31d2..777451b8c8 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -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); diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index e21d8da478..af06161bad 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -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) {