user-util: synthesize user records for "nobody" the same way as for "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.
This commit is contained in:
Lennart Poettering 2017-12-04 17:07:48 +01:00
parent 3a664727fa
commit 7e61fd02b0
2 changed files with 87 additions and 7 deletions

View 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;

View 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();