1
1
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:
Lennart Poettering 2021-05-08 00:12:01 +02:00 committed by GitHub
commit d799bd47d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 159 additions and 358 deletions

View File

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

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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) {