diff --git a/src/login/logind-core.c b/src/login/logind-core.c index cd3a3742012..22031f485a0 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -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; diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index 5592eaa3aa4..14712f8735d 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -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) { diff --git a/src/nss-systemd/userdb-glue.c b/src/nss-systemd/userdb-glue.c index 8f8988579b8..73941b2ba56 100644 --- a/src/nss-systemd/userdb-glue.c +++ b/src/nss-systemd/userdb-glue.c @@ -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; } diff --git a/src/shared/userdb.c b/src/shared/userdb.c index e4a04123c0e..caef7cdf063 100644 --- a/src/shared/userdb.c +++ b/src/shared/userdb.c @@ -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); diff --git a/src/shared/userdb.h b/src/shared/userdb.h index ee207b518ed..d69c6db0340 100644 --- a/src/shared/userdb.h +++ b/src/shared/userdb.h @@ -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); diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index e9c6957143a..56511eae447 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -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: diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c index c62a21974a1..71251ccf1d1 100644 --- a/src/userdb/userwork.c +++ b/src/userdb/userwork.c @@ -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) {