Skip to content

Commit

Permalink
user-util: synthesize user records for "nobody" the same way as for "…
Browse files Browse the repository at this point in the history
…root"

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.
  • Loading branch information
poettering committed Dec 6, 2017
1 parent 3a66472 commit 7e61fd0
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 7 deletions.
59 changes: 52 additions & 7 deletions src/basic/user-util.c
Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand Down
35 changes: 35 additions & 0 deletions src/test/test-user-util.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down

0 comments on commit 7e61fd0

Please sign in to comment.