mirror of
https://github.com/systemd/systemd.git
synced 2025-01-28 21:47:38 +03:00
Merge pull request #19538 from poettering/userdbd-simplify-nss-listing
userdbd: refactoring to simplify NSS user listing
This commit is contained in:
commit
d799bd47d8
@ -176,7 +176,7 @@ int manager_add_user_by_name(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(name);
|
assert(name);
|
||||||
|
|
||||||
r = userdb_by_name(name, USERDB_AVOID_SHADOW, &ur);
|
r = userdb_by_name(name, USERDB_SUPPRESS_SHADOW, &ur);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ int manager_add_user_by_uid(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(uid_is_valid(uid));
|
assert(uid_is_valid(uid));
|
||||||
|
|
||||||
r = userdb_by_uid(uid, USERDB_AVOID_SHADOW, &ur);
|
r = userdb_by_uid(uid, USERDB_SUPPRESS_SHADOW, &ur);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -582,7 +582,7 @@ enum nss_status _nss_systemd_initgroups_dyn(
|
|||||||
/* The group might be defined via traditional NSS only, hence let's do a full look-up without
|
/* The group might be defined via traditional NSS only, hence let's do a full look-up without
|
||||||
* disabling NSS. This means we are operating recursively here. */
|
* disabling NSS. This means we are operating recursively here. */
|
||||||
|
|
||||||
r = groupdb_by_name(group_name, (nss_glue_userdb_flags() & ~USERDB_AVOID_NSS) | USERDB_AVOID_SHADOW, &g);
|
r = groupdb_by_name(group_name, (nss_glue_userdb_flags() & ~USERDB_EXCLUDE_NSS) | USERDB_SUPPRESS_SHADOW, &g);
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
continue;
|
continue;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
@ -11,11 +11,11 @@
|
|||||||
#include "userdb.h"
|
#include "userdb.h"
|
||||||
|
|
||||||
UserDBFlags nss_glue_userdb_flags(void) {
|
UserDBFlags nss_glue_userdb_flags(void) {
|
||||||
UserDBFlags flags = USERDB_AVOID_NSS;
|
UserDBFlags flags = USERDB_EXCLUDE_NSS;
|
||||||
|
|
||||||
/* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
|
/* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
|
||||||
if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
|
if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
|
||||||
flags |= USERDB_AVOID_DYNAMIC_USER;
|
flags |= USERDB_EXCLUDE_DYNAMIC_USER;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
@ -402,6 +402,9 @@ static int userdb_start_query(
|
|||||||
assert(iterator);
|
assert(iterator);
|
||||||
assert(method);
|
assert(method);
|
||||||
|
|
||||||
|
if (FLAGS_SET(flags, USERDB_EXCLUDE_VARLINK))
|
||||||
|
return -ENOLINK;
|
||||||
|
|
||||||
e = getenv("SYSTEMD_BYPASS_USERDB");
|
e = getenv("SYSTEMD_BYPASS_USERDB");
|
||||||
if (e) {
|
if (e) {
|
||||||
r = parse_boolean(e);
|
r = parse_boolean(e);
|
||||||
@ -422,7 +425,7 @@ static int userdb_start_query(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* First, let's talk to the multiplexer, if we can */
|
/* First, let's talk to the multiplexer, if we can */
|
||||||
if ((flags & (USERDB_AVOID_MULTIPLEXER|USERDB_AVOID_DYNAMIC_USER|USERDB_AVOID_NSS|USERDB_DONT_SYNTHESIZE)) == 0 &&
|
if ((flags & (USERDB_AVOID_MULTIPLEXER|USERDB_EXCLUDE_DYNAMIC_USER|USERDB_EXCLUDE_NSS|USERDB_DONT_SYNTHESIZE)) == 0 &&
|
||||||
!strv_contains(except, "io.systemd.Multiplexer") &&
|
!strv_contains(except, "io.systemd.Multiplexer") &&
|
||||||
(!only || strv_contains(only, "io.systemd.Multiplexer"))) {
|
(!only || strv_contains(only, "io.systemd.Multiplexer"))) {
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *patched_query = json_variant_ref(query);
|
_cleanup_(json_variant_unrefp) JsonVariant *patched_query = json_variant_ref(query);
|
||||||
@ -454,7 +457,7 @@ static int userdb_start_query(
|
|||||||
if (streq(de->d_name, "io.systemd.Multiplexer")) /* We already tried this above, don't try this again */
|
if (streq(de->d_name, "io.systemd.Multiplexer")) /* We already tried this above, don't try this again */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (FLAGS_SET(flags, USERDB_AVOID_DYNAMIC_USER) &&
|
if (FLAGS_SET(flags, USERDB_EXCLUDE_DYNAMIC_USER) &&
|
||||||
streq(de->d_name, "io.systemd.DynamicUser"))
|
streq(de->d_name, "io.systemd.DynamicUser"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -463,7 +466,7 @@ static int userdb_start_query(
|
|||||||
* (and when we run as part of systemd-userdbd.service we don't want to talk to ourselves
|
* (and when we run as part of systemd-userdbd.service we don't want to talk to ourselves
|
||||||
* anyway). */
|
* anyway). */
|
||||||
is_nss = streq(de->d_name, "io.systemd.NameServiceSwitch");
|
is_nss = streq(de->d_name, "io.systemd.NameServiceSwitch");
|
||||||
if ((flags & (USERDB_AVOID_NSS|USERDB_AVOID_MULTIPLEXER)) && is_nss)
|
if ((flags & (USERDB_EXCLUDE_NSS|USERDB_AVOID_MULTIPLEXER)) && is_nss)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strv_contains(except, de->d_name))
|
if (strv_contains(except, de->d_name))
|
||||||
@ -621,13 +624,13 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !iterator->nss_covered) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && !iterator->nss_covered) {
|
||||||
/* Make sure the NSS lookup doesn't recurse back to us. */
|
/* Make sure the NSS lookup doesn't recurse back to us. */
|
||||||
|
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
/* Client-side NSS fallback */
|
/* Client-side NSS fallback */
|
||||||
r = nss_user_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
|
r = nss_user_record_by_name(name, !FLAGS_SET(flags, USERDB_SUPPRESS_SHADOW), ret);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -668,11 +671,11 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !iterator->nss_covered) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && !iterator->nss_covered) {
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
/* Client-side NSS fallback */
|
/* Client-side NSS fallback */
|
||||||
r = nss_user_record_by_uid(uid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
|
r = nss_user_record_by_uid(uid, !FLAGS_SET(flags, USERDB_SUPPRESS_SHADOW), ret);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -703,7 +706,7 @@ int userdb_all(UserDBFlags flags, UserDBIterator **ret) {
|
|||||||
|
|
||||||
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetUserRecord", true, NULL, flags);
|
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetUserRecord", true, NULL, flags);
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && (r < 0 || !iterator->nss_covered)) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && (r < 0 || !iterator->nss_covered)) {
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -740,7 +743,7 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
|
|||||||
if (pw->pw_uid == UID_NOBODY)
|
if (pw->pw_uid == UID_NOBODY)
|
||||||
iterator->synthesize_nobody = false;
|
iterator->synthesize_nobody = false;
|
||||||
|
|
||||||
if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
|
if (!FLAGS_SET(iterator->flags, USERDB_SUPPRESS_SHADOW)) {
|
||||||
r = nss_spwd_for_passwd(pw, &spwd, &buffer);
|
r = nss_spwd_for_passwd(pw, &spwd, &buffer);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
|
log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
|
||||||
@ -832,10 +835,10 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && !(iterator && iterator->nss_covered)) {
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
r = nss_group_record_by_name(name, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
|
r = nss_group_record_by_name(name, !FLAGS_SET(flags, USERDB_SUPPRESS_SHADOW), ret);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -876,10 +879,10 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && !(iterator && iterator->nss_covered)) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && !(iterator && iterator->nss_covered)) {
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
r = nss_group_record_by_gid(gid, !FLAGS_SET(flags, USERDB_AVOID_SHADOW), ret);
|
r = nss_group_record_by_gid(gid, !FLAGS_SET(flags, USERDB_SUPPRESS_SHADOW), ret);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -910,7 +913,7 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
|
|||||||
|
|
||||||
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetGroupRecord", true, NULL, flags);
|
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetGroupRecord", true, NULL, flags);
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, USERDB_AVOID_NSS) && (r < 0 || !iterator->nss_covered)) {
|
if (!FLAGS_SET(flags, USERDB_EXCLUDE_NSS) && (r < 0 || !iterator->nss_covered)) {
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -945,7 +948,7 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
|
|||||||
if (gr->gr_gid == GID_NOBODY)
|
if (gr->gr_gid == GID_NOBODY)
|
||||||
iterator->synthesize_nobody = false;
|
iterator->synthesize_nobody = false;
|
||||||
|
|
||||||
if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
|
if (!FLAGS_SET(iterator->flags, USERDB_SUPPRESS_SHADOW)) {
|
||||||
r = nss_sgrp_for_group(gr, &sgrp, &buffer);
|
r = nss_sgrp_for_group(gr, &sgrp, &buffer);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name);
|
log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name);
|
||||||
@ -1016,7 +1019,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, query, flags);
|
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, query, flags);
|
||||||
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
|
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_EXCLUDE_NSS))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
@ -1059,7 +1062,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, query, flags);
|
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, query, flags);
|
||||||
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
|
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_EXCLUDE_NSS))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
@ -1100,7 +1103,7 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret) {
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, NULL, flags);
|
r = userdb_start_query(iterator, "io.systemd.UserDatabase.GetMemberships", true, NULL, flags);
|
||||||
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_AVOID_NSS))
|
if ((r >= 0 && iterator->nss_covered) || FLAGS_SET(flags, USERDB_EXCLUDE_NSS))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
r = userdb_iterator_block_nss_systemd(iterator);
|
r = userdb_iterator_block_nss_systemd(iterator);
|
||||||
|
@ -15,11 +15,18 @@ UserDBIterator *userdb_iterator_free(UserDBIterator *iterator);
|
|||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UserDBIterator*, userdb_iterator_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(UserDBIterator*, userdb_iterator_free);
|
||||||
|
|
||||||
typedef enum UserDBFlags {
|
typedef enum UserDBFlags {
|
||||||
USERDB_AVOID_NSS = 1 << 0, /* don't do client-side nor server-side NSS */
|
/* The main sources */
|
||||||
USERDB_AVOID_SHADOW = 1 << 1, /* don't do client-side shadow calls (server side might happen though) */
|
USERDB_EXCLUDE_NSS = 1 << 0, /* don't do client-side nor server-side NSS */
|
||||||
USERDB_AVOID_DYNAMIC_USER = 1 << 2, /* exclude looking up in io.systemd.DynamicUser */
|
USERDB_EXCLUDE_VARLINK = 1 << 1, /* don't talk to any varlink services */
|
||||||
USERDB_AVOID_MULTIPLEXER = 1 << 3, /* exclude looking up via io.systemd.Multiplexer */
|
|
||||||
USERDB_DONT_SYNTHESIZE = 1 << 4, /* don't synthesize root/nobody */
|
/* Modifications */
|
||||||
|
USERDB_SUPPRESS_SHADOW = 1 << 3, /* don't do client-side shadow calls (server side might happen though) */
|
||||||
|
USERDB_EXCLUDE_DYNAMIC_USER = 1 << 4, /* exclude looking up in io.systemd.DynamicUser */
|
||||||
|
USERDB_AVOID_MULTIPLEXER = 1 << 5, /* exclude looking up via io.systemd.Multiplexer */
|
||||||
|
USERDB_DONT_SYNTHESIZE = 1 << 6, /* don't synthesize root/nobody */
|
||||||
|
|
||||||
|
/* Combinations */
|
||||||
|
USERDB_NSS_ONLY = USERDB_EXCLUDE_VARLINK|USERDB_DONT_SYNTHESIZE,
|
||||||
} UserDBFlags;
|
} UserDBFlags;
|
||||||
|
|
||||||
int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret);
|
int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret);
|
||||||
|
@ -717,7 +717,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
arg_userdb_flags |= USERDB_AVOID_NSS|USERDB_DONT_SYNTHESIZE;
|
arg_userdb_flags |= USERDB_EXCLUDE_NSS|USERDB_DONT_SYNTHESIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_WITH_NSS:
|
case ARG_WITH_NSS:
|
||||||
@ -725,7 +725,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
SET_FLAG(arg_userdb_flags, USERDB_AVOID_NSS, !r);
|
SET_FLAG(arg_userdb_flags, USERDB_EXCLUDE_NSS, !r);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_SYNTHESIZE:
|
case ARG_SYNTHESIZE:
|
||||||
|
@ -113,6 +113,21 @@ static int build_user_json(Varlink *link, UserRecord *ur, JsonVariant **ret) {
|
|||||||
JSON_BUILD_PAIR("incomplete", JSON_BUILD_BOOLEAN(stripped->incomplete))));
|
JSON_BUILD_PAIR("incomplete", JSON_BUILD_BOOLEAN(stripped->incomplete))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int userdb_flags_from_service(Varlink *link, const char *service, UserDBFlags *ret) {
|
||||||
|
assert(link);
|
||||||
|
assert(service);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (streq_ptr(service, "io.systemd.NameServiceSwitch"))
|
||||||
|
*ret = USERDB_NSS_ONLY|USERDB_AVOID_MULTIPLEXER;
|
||||||
|
else if (streq_ptr(service, "io.systemd.Multiplexer"))
|
||||||
|
*ret = USERDB_AVOID_MULTIPLEXER;
|
||||||
|
else
|
||||||
|
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
|
static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
|
||||||
|
|
||||||
static const JsonDispatch dispatch_table[] = {
|
static const JsonDispatch dispatch_table[] = {
|
||||||
@ -127,6 +142,7 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
|||||||
LookupParameters p = {
|
LookupParameters p = {
|
||||||
.uid = UID_INVALID,
|
.uid = UID_INVALID,
|
||||||
};
|
};
|
||||||
|
UserDBFlags userdb_flags;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
@ -135,109 +151,49 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||||||
if (uid_is_valid(p.uid))
|
if (r < 0)
|
||||||
r = nss_user_record_by_uid(p.uid, true, &hr);
|
return r;
|
||||||
else if (p.user_name)
|
|
||||||
r = nss_user_record_by_name(p.user_name, true, &hr);
|
|
||||||
else {
|
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
|
||||||
|
|
||||||
setpwent();
|
if (uid_is_valid(p.uid))
|
||||||
|
r = userdb_by_uid(p.uid, userdb_flags, &hr);
|
||||||
|
else if (p.user_name)
|
||||||
|
r = userdb_by_name(p.user_name, userdb_flags, &hr);
|
||||||
|
else {
|
||||||
|
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
||||||
|
|
||||||
for (;;) {
|
r = userdb_all(userdb_flags, &iterator);
|
||||||
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
if (r < 0)
|
||||||
_cleanup_free_ char *sbuf = NULL;
|
return r;
|
||||||
struct passwd *pw;
|
|
||||||
struct spwd spwd;
|
|
||||||
|
|
||||||
errno = 0;
|
for (;;) {
|
||||||
pw = getpwent();
|
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
||||||
if (!pw) {
|
|
||||||
if (errno != 0)
|
|
||||||
log_debug_errno(errno, "Failure while iterating through NSS user database, ignoring: %m");
|
|
||||||
|
|
||||||
break;
|
r = userdb_iterator_get(iterator, &z);
|
||||||
}
|
if (r == -ESRCH)
|
||||||
|
break;
|
||||||
r = nss_spwd_for_passwd(pw, &spwd, &sbuf);
|
|
||||||
if (r < 0)
|
|
||||||
log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
|
|
||||||
|
|
||||||
r = nss_passwd_to_user_record(pw, NULL, &z);
|
|
||||||
if (r < 0) {
|
|
||||||
endpwent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
r = varlink_notify(link, last);
|
|
||||||
if (r < 0) {
|
|
||||||
endpwent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = json_variant_unref(last);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = build_user_json(link, z, &last);
|
|
||||||
if (r < 0) {
|
|
||||||
endpwent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpwent();
|
|
||||||
|
|
||||||
if (!last)
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
|
|
||||||
return varlink_reply(link, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (streq_ptr(p.service, "io.systemd.Multiplexer")) {
|
|
||||||
|
|
||||||
if (uid_is_valid(p.uid))
|
|
||||||
r = userdb_by_uid(p.uid, USERDB_AVOID_MULTIPLEXER, &hr);
|
|
||||||
else if (p.user_name)
|
|
||||||
r = userdb_by_name(p.user_name, USERDB_AVOID_MULTIPLEXER, &hr);
|
|
||||||
else {
|
|
||||||
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
|
||||||
|
|
||||||
r = userdb_all(USERDB_AVOID_MULTIPLEXER, &iterator);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
if (last) {
|
||||||
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
r = varlink_notify(link, last);
|
||||||
|
|
||||||
r = userdb_iterator_get(iterator, &z);
|
|
||||||
if (r == -ESRCH)
|
|
||||||
break;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (last) {
|
last = json_variant_unref(last);
|
||||||
r = varlink_notify(link, last);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
last = json_variant_unref(last);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = build_user_json(link, z, &last);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last)
|
r = build_user_json(link, z, &last);
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
if (r < 0)
|
||||||
|
return r;
|
||||||
return varlink_reply(link, last);
|
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
if (!last)
|
||||||
|
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|
||||||
|
return varlink_reply(link, last);
|
||||||
|
}
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -313,6 +269,7 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
|||||||
LookupParameters p = {
|
LookupParameters p = {
|
||||||
.gid = GID_INVALID,
|
.gid = GID_INVALID,
|
||||||
};
|
};
|
||||||
|
UserDBFlags userdb_flags;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
@ -321,110 +278,49 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (gid_is_valid(p.gid))
|
if (gid_is_valid(p.gid))
|
||||||
r = nss_group_record_by_gid(p.gid, true, &g);
|
r = groupdb_by_gid(p.gid, userdb_flags, &g);
|
||||||
else if (p.group_name)
|
else if (p.group_name)
|
||||||
r = nss_group_record_by_name(p.group_name, true, &g);
|
r = groupdb_by_name(p.group_name, userdb_flags, &g);
|
||||||
else {
|
else {
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
||||||
|
|
||||||
setgrent();
|
r = groupdb_all(userdb_flags, &iterator);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
||||||
_cleanup_free_ char *sbuf = NULL;
|
|
||||||
struct group *grp;
|
|
||||||
struct sgrp sgrp;
|
|
||||||
|
|
||||||
errno = 0;
|
r = groupdb_iterator_get(iterator, &z);
|
||||||
grp = getgrent();
|
if (r == -ESRCH)
|
||||||
if (!grp) {
|
break;
|
||||||
if (errno != 0)
|
|
||||||
log_debug_errno(errno, "Failure while iterating through NSS group database, ignoring: %m");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = nss_sgrp_for_group(grp, &sgrp, &sbuf);
|
|
||||||
if (r < 0)
|
|
||||||
log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", grp->gr_name);
|
|
||||||
|
|
||||||
r = nss_group_to_group_record(grp, r >= 0 ? &sgrp : NULL, &z);
|
|
||||||
if (r < 0) {
|
|
||||||
endgrent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
r = varlink_notify(link, last);
|
|
||||||
if (r < 0) {
|
|
||||||
endgrent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = json_variant_unref(last);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = build_group_json(link, z, &last);
|
|
||||||
if (r < 0) {
|
|
||||||
endgrent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endgrent();
|
|
||||||
|
|
||||||
if (!last)
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
|
|
||||||
return varlink_reply(link, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (streq_ptr(p.service, "io.systemd.Multiplexer")) {
|
|
||||||
|
|
||||||
if (gid_is_valid(p.gid))
|
|
||||||
r = groupdb_by_gid(p.gid, USERDB_AVOID_MULTIPLEXER, &g);
|
|
||||||
else if (p.group_name)
|
|
||||||
r = groupdb_by_name(p.group_name, USERDB_AVOID_MULTIPLEXER, &g);
|
|
||||||
else {
|
|
||||||
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
|
||||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
|
||||||
|
|
||||||
r = groupdb_all(USERDB_AVOID_MULTIPLEXER, &iterator);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
if (last) {
|
||||||
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
r = varlink_notify(link, last);
|
||||||
|
|
||||||
r = groupdb_iterator_get(iterator, &z);
|
|
||||||
if (r == -ESRCH)
|
|
||||||
break;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (last) {
|
last = json_variant_unref(last);
|
||||||
r = varlink_notify(link, last);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
last = json_variant_unref(last);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = build_group_json(link, z, &last);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last)
|
r = build_group_json(link, z, &last);
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
if (r < 0)
|
||||||
|
return r;
|
||||||
return varlink_reply(link, last);
|
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
if (!last)
|
||||||
|
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|
||||||
|
return varlink_reply(link, last);
|
||||||
|
}
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -451,7 +347,10 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_cleanup_free_ char *last_user_name = NULL, *last_group_name = NULL;
|
||||||
|
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
||||||
LookupParameters p = {};
|
LookupParameters p = {};
|
||||||
|
UserDBFlags userdb_flags;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
@ -460,167 +359,59 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (p.group_name) {
|
if (p.group_name)
|
||||||
_cleanup_(group_record_unrefp) GroupRecord *g = NULL;
|
r = membershipdb_by_group(p.group_name, userdb_flags, &iterator);
|
||||||
const char *last = NULL;
|
else if (p.user_name)
|
||||||
char **i;
|
r = membershipdb_by_user(p.user_name, userdb_flags, &iterator);
|
||||||
|
else
|
||||||
|
r = membershipdb_all(userdb_flags, &iterator);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = nss_group_record_by_name(p.group_name, true, &g);
|
for (;;) {
|
||||||
if (r == -ESRCH)
|
_cleanup_free_ char *user_name = NULL, *group_name = NULL;
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
STRV_FOREACH(i, g->members) {
|
r = membershipdb_iterator_get(iterator, &user_name, &group_name);
|
||||||
|
if (r == -ESRCH)
|
||||||
if (p.user_name && !streq_ptr(p.user_name, *i))
|
break;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
r = varlink_notifyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(g->group_name))));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = *i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!last)
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
|
|
||||||
return varlink_replyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(g->group_name))));
|
|
||||||
} else {
|
|
||||||
_cleanup_free_ char *last_user_name = NULL, *last_group_name = NULL;
|
|
||||||
|
|
||||||
setgrent();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
struct group *grp;
|
|
||||||
const char* two[2], **users, **i;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
grp = getgrent();
|
|
||||||
if (!grp) {
|
|
||||||
if (errno != 0)
|
|
||||||
log_debug_errno(errno, "Failure while iterating through NSS group database, ignoring: %m");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.user_name) {
|
|
||||||
if (!strv_contains(grp->gr_mem, p.user_name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
two[0] = p.user_name;
|
|
||||||
two[1] = NULL;
|
|
||||||
|
|
||||||
users = two;
|
|
||||||
} else
|
|
||||||
users = (const char**) grp->gr_mem;
|
|
||||||
|
|
||||||
STRV_FOREACH(i, users) {
|
|
||||||
|
|
||||||
if (last_user_name) {
|
|
||||||
assert(last_group_name);
|
|
||||||
|
|
||||||
r = varlink_notifyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
|
||||||
if (r < 0) {
|
|
||||||
endgrent();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(last_user_name);
|
|
||||||
free(last_group_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_user_name = strdup(*i);
|
|
||||||
last_group_name = strdup(grp->gr_name);
|
|
||||||
if (!last_user_name || !last_group_name) {
|
|
||||||
endgrent();
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endgrent();
|
|
||||||
|
|
||||||
if (!last_user_name) {
|
|
||||||
assert(!last_group_name);
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(last_group_name);
|
|
||||||
|
|
||||||
return varlink_replyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (streq_ptr(p.service, "io.systemd.Multiplexer")) {
|
|
||||||
|
|
||||||
_cleanup_free_ char *last_user_name = NULL, *last_group_name = NULL;
|
|
||||||
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
|
||||||
|
|
||||||
if (p.group_name)
|
|
||||||
r = membershipdb_by_group(p.group_name, USERDB_AVOID_MULTIPLEXER, &iterator);
|
|
||||||
else if (p.user_name)
|
|
||||||
r = membershipdb_by_user(p.user_name, USERDB_AVOID_MULTIPLEXER, &iterator);
|
|
||||||
else
|
|
||||||
r = membershipdb_all(USERDB_AVOID_MULTIPLEXER, &iterator);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (;;) {
|
/* If both group + user are specified do a-posteriori filtering */
|
||||||
_cleanup_free_ char *user_name = NULL, *group_name = NULL;
|
if (p.group_name && p.user_name && !streq(group_name, p.group_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
r = membershipdb_iterator_get(iterator, &user_name, &group_name);
|
if (last_user_name) {
|
||||||
if (r == -ESRCH)
|
assert(last_group_name);
|
||||||
break;
|
|
||||||
|
r = varlink_notifyb(link, JSON_BUILD_OBJECT(
|
||||||
|
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
||||||
|
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* If both group + user are specified do a-posteriori filtering */
|
free(last_user_name);
|
||||||
if (p.group_name && p.user_name && !streq(group_name, p.group_name))
|
free(last_group_name);
|
||||||
continue;
|
|
||||||
|
|
||||||
if (last_user_name) {
|
|
||||||
assert(last_group_name);
|
|
||||||
|
|
||||||
r = varlink_notifyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
free(last_user_name);
|
|
||||||
free(last_group_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_user_name = TAKE_PTR(user_name);
|
|
||||||
last_group_name = TAKE_PTR(group_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last_user_name) {
|
last_user_name = TAKE_PTR(user_name);
|
||||||
assert(!last_group_name);
|
last_group_name = TAKE_PTR(group_name);
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(last_group_name);
|
|
||||||
|
|
||||||
return varlink_replyb(link, JSON_BUILD_OBJECT(
|
|
||||||
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
|
||||||
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
if (!last_user_name) {
|
||||||
|
assert(!last_group_name);
|
||||||
|
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(last_group_name);
|
||||||
|
|
||||||
|
return varlink_replyb(link, JSON_BUILD_OBJECT(
|
||||||
|
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(last_user_name)),
|
||||||
|
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(last_group_name))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_connection(VarlinkServer *server, int fd) {
|
static int process_connection(VarlinkServer *server, int fd) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user