diff --git a/src/basic/user-util.c b/src/basic/user-util.c index ed54578a66029..abb0b76866a7b 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -117,15 +117,14 @@ int get_user_creds( assert(username); assert(*username); - /* We enforce some special rules for uid=0: in order to avoid - * NSS lookups for root we hardcode its data. */ + /* We enforce some special rules for uid=0 and uid=65534: in order to avoid NSS lookups for root we hardcode + * their user record data. */ - if (streq(*username, "root") || streq(*username, "0")) { + if (STR_IN_SET(*username, "root", "0")) { *username = "root"; if (uid) *uid = 0; - if (gid) *gid = 0; @@ -138,6 +137,23 @@ int get_user_creds( return 0; } + if (STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) { + *username = NOBODY_USER_NAME; + + if (uid) + *uid = UID_NOBODY; + if (gid) + *gid = GID_NOBODY; + + if (home) + *home = "/"; + + if (shell) + *shell = "/sbin/nologin"; + + return 0; + } + if (parse_uid(*username, &u) >= 0) { errno = 0; p = getpwuid(u); @@ -218,7 +234,7 @@ int get_group_creds(const char **groupname, gid_t *gid) { /* We enforce some special rules for gid=0: in order to avoid * NSS lookups for root we hardcode its data. */ - if (streq(*groupname, "root") || streq(*groupname, "0")) { + if (STR_IN_SET(*groupname, "root", "0")) { *groupname = "root"; if (gid) @@ -227,6 +243,15 @@ int get_group_creds(const char **groupname, gid_t *gid) { return 0; } + if (STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) { + *groupname = NOBODY_GROUP_NAME; + + if (gid) + *gid = GID_NOBODY; + + return 0; + } + if (parse_gid(*groupname, &id) >= 0) { errno = 0; g = getgrgid(id); @@ -258,6 +283,8 @@ char* uid_to_name(uid_t uid) { /* Shortcut things to avoid NSS lookups */ if (uid == 0) return strdup("root"); + if (uid == UID_NOBODY) + return strdup(NOBODY_USER_NAME); if (uid_is_valid(uid)) { long bufsize; @@ -296,6 +323,8 @@ char* gid_to_name(gid_t gid) { if (gid == 0) return strdup("root"); + if (gid == GID_NOBODY) + return strdup(NOBODY_GROUP_NAME); if (gid_is_valid(gid)) { long bufsize; @@ -387,7 +416,7 @@ int get_home_dir(char **_h) { return 0; } - /* Hardcode home directory for root to avoid NSS */ + /* Hardcode home directory for root and nobody to avoid NSS */ u = getuid(); if (u == 0) { h = strdup("/root"); @@ -397,6 +426,14 @@ int get_home_dir(char **_h) { *_h = h; return 0; } + if (u == UID_NOBODY) { + h = strdup("/"); + if (!h) + return -ENOMEM; + + *_h = h; + return 0; + } /* Check the database... */ errno = 0; @@ -434,7 +471,7 @@ int get_shell(char **_s) { return 0; } - /* Hardcode home directory for root to avoid NSS */ + /* Hardcode shell for root and nobody to avoid NSS */ u = getuid(); if (u == 0) { s = strdup("/bin/sh"); @@ -444,6 +481,14 @@ int get_shell(char **_s) { *_s = s; return 0; } + if (u == UID_NOBODY) { + s = strdup("/sbin/nologin"); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } /* Check the database... */ errno = 0; diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index 639804f34aad1..17a852074169b 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -23,6 +23,7 @@ #include "string-util.h" #include "user-util.h" #include "util.h" +#include "path-util.h" static void test_uid_to_name_one(uid_t uid, const char *name) { _cleanup_free_ char *t = NULL; @@ -144,17 +145,51 @@ static void test_valid_home(void) { assert_se(valid_home("/home/foo")); } +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) { + const char *rhome; + const char *rshell; + uid_t ruid; + gid_t rgid; + + assert_se(get_user_creds(&id, &ruid, &rgid, &rhome, &rshell) >= 0); + assert_se(streq_ptr(id, name)); + assert_se(ruid == uid); + assert_se(rgid == gid); + assert_se(path_equal(rhome, home)); + assert_se(path_equal(rshell, shell)); +} + +static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) { + gid_t rgid; + + assert_se(get_group_creds(&id, &rgid) >= 0); + assert_se(streq_ptr(id, name)); + assert_se(rgid == gid); +} + int main(int argc, char*argv[]) { test_uid_to_name_one(0, "root"); + test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME); test_uid_to_name_one(0xFFFF, "65535"); test_uid_to_name_one(0xFFFFFFFF, "4294967295"); test_gid_to_name_one(0, "root"); + test_gid_to_name_one(GID_NOBODY, NOBODY_GROUP_NAME); test_gid_to_name_one(TTY_GID, "tty"); test_gid_to_name_one(0xFFFF, "65535"); test_gid_to_name_one(0xFFFFFFFF, "4294967295"); + test_get_user_creds_one("root", "root", 0, 0, "/root", "/bin/sh"); + test_get_user_creds_one("0", "root", 0, 0, "/root", "/bin/sh"); + test_get_user_creds_one(NOBODY_USER_NAME, NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin"); + test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin"); + + test_get_group_creds_one("root", "root", 0); + test_get_group_creds_one("0", "root", 0); + test_get_group_creds_one(NOBODY_GROUP_NAME, NOBODY_GROUP_NAME, GID_NOBODY); + test_get_group_creds_one("65534", NOBODY_GROUP_NAME, GID_NOBODY); + test_parse_uid(); test_uid_ptr();