mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +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(name);
|
||||
|
||||
r = userdb_by_name(name, USERDB_AVOID_SHADOW, &ur);
|
||||
r = userdb_by_name(name, USERDB_SUPPRESS_SHADOW, &ur);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -194,7 +194,7 @@ int manager_add_user_by_uid(
|
||||
assert(m);
|
||||
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)
|
||||
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
|
||||
* 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)
|
||||
continue;
|
||||
if (r < 0) {
|
||||
|
@ -11,11 +11,11 @@
|
||||
#include "userdb.h"
|
||||
|
||||
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 */
|
||||
if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
|
||||
flags |= USERDB_AVOID_DYNAMIC_USER;
|
||||
flags |= USERDB_EXCLUDE_DYNAMIC_USER;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
@ -402,6 +402,9 @@ static int userdb_start_query(
|
||||
assert(iterator);
|
||||
assert(method);
|
||||
|
||||
if (FLAGS_SET(flags, USERDB_EXCLUDE_VARLINK))
|
||||
return -ENOLINK;
|
||||
|
||||
e = getenv("SYSTEMD_BYPASS_USERDB");
|
||||
if (e) {
|
||||
r = parse_boolean(e);
|
||||
@ -422,7 +425,7 @@ static int userdb_start_query(
|
||||
}
|
||||
|
||||
/* 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") &&
|
||||
(!only || strv_contains(only, "io.systemd.Multiplexer"))) {
|
||||
_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 */
|
||||
continue;
|
||||
|
||||
if (FLAGS_SET(flags, USERDB_AVOID_DYNAMIC_USER) &&
|
||||
if (FLAGS_SET(flags, USERDB_EXCLUDE_DYNAMIC_USER) &&
|
||||
streq(de->d_name, "io.systemd.DynamicUser"))
|
||||
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
|
||||
* anyway). */
|
||||
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;
|
||||
|
||||
if (strv_contains(except, de->d_name))
|
||||
@ -621,13 +624,13 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
|
||||
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. */
|
||||
|
||||
r = userdb_iterator_block_nss_systemd(iterator);
|
||||
if (r >= 0) {
|
||||
/* 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)
|
||||
return r;
|
||||
}
|
||||
@ -668,11 +671,11 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
|
||||
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);
|
||||
if (r >= 0) {
|
||||
/* 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)
|
||||
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);
|
||||
|
||||
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);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -740,7 +743,7 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
|
||||
if (pw->pw_uid == UID_NOBODY)
|
||||
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);
|
||||
if (r < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
return r;
|
||||
}
|
||||
@ -876,10 +879,10 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
|
||||
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);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -945,7 +948,7 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
|
||||
if (gr->gr_gid == GID_NOBODY)
|
||||
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);
|
||||
if (r < 0) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
r = userdb_iterator_block_nss_systemd(iterator);
|
||||
@ -1059,7 +1062,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
|
||||
r = userdb_iterator_block_nss_systemd(iterator);
|
||||
@ -1100,7 +1103,7 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
typedef enum UserDBFlags {
|
||||
USERDB_AVOID_NSS = 1 << 0, /* don't do client-side nor server-side NSS */
|
||||
USERDB_AVOID_SHADOW = 1 << 1, /* don't do client-side shadow calls (server side might happen though) */
|
||||
USERDB_AVOID_DYNAMIC_USER = 1 << 2, /* exclude looking up in io.systemd.DynamicUser */
|
||||
USERDB_AVOID_MULTIPLEXER = 1 << 3, /* exclude looking up via io.systemd.Multiplexer */
|
||||
USERDB_DONT_SYNTHESIZE = 1 << 4, /* don't synthesize root/nobody */
|
||||
/* The main sources */
|
||||
USERDB_EXCLUDE_NSS = 1 << 0, /* don't do client-side nor server-side NSS */
|
||||
USERDB_EXCLUDE_VARLINK = 1 << 1, /* don't talk to any varlink services */
|
||||
|
||||
/* 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;
|
||||
|
||||
int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret);
|
||||
|
@ -717,7 +717,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
arg_userdb_flags |= USERDB_AVOID_NSS|USERDB_DONT_SYNTHESIZE;
|
||||
arg_userdb_flags |= USERDB_EXCLUDE_NSS|USERDB_DONT_SYNTHESIZE;
|
||||
break;
|
||||
|
||||
case ARG_WITH_NSS:
|
||||
@ -725,7 +725,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FLAG(arg_userdb_flags, USERDB_AVOID_NSS, !r);
|
||||
SET_FLAG(arg_userdb_flags, USERDB_EXCLUDE_NSS, !r);
|
||||
break;
|
||||
|
||||
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))));
|
||||
}
|
||||
|
||||
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 const JsonDispatch dispatch_table[] = {
|
||||
@ -127,6 +142,7 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
||||
LookupParameters p = {
|
||||
.uid = UID_INVALID,
|
||||
};
|
||||
UserDBFlags userdb_flags;
|
||||
int r;
|
||||
|
||||
assert(parameters);
|
||||
@ -135,109 +151,49 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq_ptr(p.service, "io.systemd.NameServiceSwitch")) {
|
||||
if (uid_is_valid(p.uid))
|
||||
r = nss_user_record_by_uid(p.uid, true, &hr);
|
||||
else if (p.user_name)
|
||||
r = nss_user_record_by_name(p.user_name, true, &hr);
|
||||
else {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
||||
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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 (;;) {
|
||||
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
||||
_cleanup_free_ char *sbuf = NULL;
|
||||
struct passwd *pw;
|
||||
struct spwd spwd;
|
||||
r = userdb_all(userdb_flags, &iterator);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
errno = 0;
|
||||
pw = getpwent();
|
||||
if (!pw) {
|
||||
if (errno != 0)
|
||||
log_debug_errno(errno, "Failure while iterating through NSS user database, ignoring: %m");
|
||||
for (;;) {
|
||||
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
||||
|
||||
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);
|
||||
r = userdb_iterator_get(iterator, &z);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
||||
|
||||
r = userdb_iterator_get(iterator, &z);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
if (last) {
|
||||
r = varlink_notify(link, last);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (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;
|
||||
last = json_variant_unref(last);
|
||||
}
|
||||
|
||||
if (!last)
|
||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
|
||||
return varlink_reply(link, last);
|
||||
r = build_user_json(link, z, &last);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} 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)
|
||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
if (r < 0) {
|
||||
@ -313,6 +269,7 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
||||
LookupParameters p = {
|
||||
.gid = GID_INVALID,
|
||||
};
|
||||
UserDBFlags userdb_flags;
|
||||
int r;
|
||||
|
||||
assert(parameters);
|
||||
@ -321,110 +278,49 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
||||
if (r < 0)
|
||||
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))
|
||||
r = nss_group_record_by_gid(p.gid, true, &g);
|
||||
else if (p.group_name)
|
||||
r = nss_group_record_by_name(p.group_name, true, &g);
|
||||
else {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *last = NULL;
|
||||
if (gid_is_valid(p.gid))
|
||||
r = groupdb_by_gid(p.gid, userdb_flags, &g);
|
||||
else if (p.group_name)
|
||||
r = groupdb_by_name(p.group_name, userdb_flags, &g);
|
||||
else {
|
||||
_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 (;;) {
|
||||
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
||||
_cleanup_free_ char *sbuf = NULL;
|
||||
struct group *grp;
|
||||
struct sgrp sgrp;
|
||||
for (;;) {
|
||||
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
||||
|
||||
errno = 0;
|
||||
grp = getgrent();
|
||||
if (!grp) {
|
||||
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);
|
||||
r = groupdb_iterator_get(iterator, &z);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
||||
|
||||
r = groupdb_iterator_get(iterator, &z);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
if (last) {
|
||||
r = varlink_notify(link, last);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (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;
|
||||
last = json_variant_unref(last);
|
||||
}
|
||||
|
||||
if (!last)
|
||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
|
||||
return varlink_reply(link, last);
|
||||
r = build_group_json(link, z, &last);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} 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)
|
||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
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 = {};
|
||||
UserDBFlags userdb_flags;
|
||||
int r;
|
||||
|
||||
assert(parameters);
|
||||
@ -460,167 +359,59 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
||||
if (r < 0)
|
||||
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) {
|
||||
_cleanup_(group_record_unrefp) GroupRecord *g = NULL;
|
||||
const char *last = NULL;
|
||||
char **i;
|
||||
if (p.group_name)
|
||||
r = membershipdb_by_group(p.group_name, userdb_flags, &iterator);
|
||||
else if (p.user_name)
|
||||
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);
|
||||
if (r == -ESRCH)
|
||||
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *user_name = NULL, *group_name = NULL;
|
||||
|
||||
STRV_FOREACH(i, g->members) {
|
||||
|
||||
if (p.user_name && !streq_ptr(p.user_name, *i))
|
||||
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);
|
||||
r = membershipdb_iterator_get(iterator, &user_name, &group_name);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *user_name = NULL, *group_name = NULL;
|
||||
/* If both group + user are specified do a-posteriori filtering */
|
||||
if (p.group_name && p.user_name && !streq(group_name, p.group_name))
|
||||
continue;
|
||||
|
||||
r = membershipdb_iterator_get(iterator, &user_name, &group_name);
|
||||
if (r == -ESRCH)
|
||||
break;
|
||||
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;
|
||||
|
||||
/* If both group + user are specified do a-posteriori filtering */
|
||||
if (p.group_name && p.user_name && !streq(group_name, p.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);
|
||||
free(last_user_name);
|
||||
free(last_group_name);
|
||||
}
|
||||
|
||||
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))));
|
||||
last_user_name = TAKE_PTR(user_name);
|
||||
last_group_name = TAKE_PTR(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) {
|
||||
|
Loading…
Reference in New Issue
Block a user