]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-util: synthesize user records for "nobody" the same way as for "root"
authorLennart Poettering <lennart@poettering.net>
Mon, 4 Dec 2017 16:07:48 +0000 (17:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 6 Dec 2017 12:40:50 +0000 (13:40 +0100)
We already synthesize records for both "root" and "nobody" in
nss-systemd. Let's do the same in our own NSS wrappers that are supposed
to bypass NSS if possible. Previously this was done for "root" only, but
let's clean this up, and do the same for "nobody" too, so that we
synthesize records the same way everywhere, regardless whether in NSS or
internally.

src/basic/user-util.c
src/test/test-user-util.c

index ed54578a6602908a24d2684bd2102287531e0f85..abb0b76866a7bdd2043f28553547e892f29c6b19 100644 (file)
@@ -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;
index 639804f34aad1e03b0822903aa753f586d3f4b5a..17a852074169b424da0821abf4778fae866c9d1b 100644 (file)
@@ -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();