diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-05-06 16:01:44 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-05-07 22:19:41 +0200 |
commit | 134ff8f4d1bbfe189957fb9418d88392ab315867 (patch) | |
tree | 4848a883d785d74cae573dd589f91eea9d93dcfb /src/userdb | |
parent | b214825433ba716ec87a0cafb8cbf9870efc21c1 (diff) | |
download | systemd-134ff8f4d1bbfe189957fb9418d88392ab315867.tar.gz |
userdbd: simplify logic for generating NSS listings
So far we basically had two ways to iterate through NSS records: one via
the varlink IPC and one via the userdb.[ch] infra, with slightly
different implementations.
Let's clean this up, and always use userdb.[ch] also when resolving via
userdbd. The different codepaths for the NameServiceSwitch and the
Multiplexer varlink service now differ only in the different flags
passed to the userdb lookup.
Behaviour shouldn't change by this. This is mostly refactoring, reducing
redundant codepaths.
Diffstat (limited to 'src/userdb')
-rw-r--r-- | src/userdb/userwork.c | 441 |
1 files changed, 116 insertions, 325 deletions
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c index c62a21974a..71251ccf1d 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 = userdb_iterator_get(iterator, &z); + if (r == -ESRCH) + break; + if (r < 0) + return r; - r = nss_spwd_for_passwd(pw, &spwd, &sbuf); + if (last) { + r = varlink_notify(link, last); 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; - } + last = json_variant_unref(last); } - 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 = build_user_json(link, z, &last); if (r < 0) return r; + } - for (;;) { - _cleanup_(user_record_unrefp) UserRecord *z = NULL; - - r = userdb_iterator_get(iterator, &z); - if (r == -ESRCH) - break; - 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; - } - - if (!last) - return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); + if (!last) + return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); - return varlink_reply(link, last); - } - } else - return varlink_error(link, "io.systemd.UserDatabase.BadService", 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")) { - - 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; + r = userdb_flags_from_service(link, p.service, &userdb_flags); + if (r < 0) + return r; - setgrent(); + 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; - for (;;) { - _cleanup_(group_record_unrefp) GroupRecord *z = NULL; - _cleanup_free_ char *sbuf = NULL; - struct group *grp; - struct sgrp sgrp; + r = groupdb_all(userdb_flags, &iterator); + if (r < 0) + return r; - errno = 0; - grp = getgrent(); - if (!grp) { - if (errno != 0) - log_debug_errno(errno, "Failure while iterating through NSS group database, ignoring: %m"); + for (;;) { + _cleanup_(group_record_unrefp) GroupRecord *z = NULL; - break; - } + r = groupdb_iterator_get(iterator, &z); + if (r == -ESRCH) + break; + if (r < 0) + return r; - r = nss_sgrp_for_group(grp, &sgrp, &sbuf); + if (last) { + r = varlink_notify(link, last); 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; - } + last = json_variant_unref(last); } - 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 = build_group_json(link, z, &last); if (r < 0) return r; + } - for (;;) { - _cleanup_(group_record_unrefp) GroupRecord *z = NULL; - - r = groupdb_iterator_get(iterator, &z); - if (r == -ESRCH) - break; - 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; - } - - if (!last) - return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); + if (!last) + return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); - return varlink_reply(link, last); - } - } else - return varlink_error(link, "io.systemd.UserDatabase.BadService", 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")) { - - if (p.group_name) { - _cleanup_(group_record_unrefp) GroupRecord *g = NULL; - const char *last = NULL; - char **i; - - 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; - - 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)))); - } + r = userdb_flags_from_service(link, p.service, &userdb_flags); + if (r < 0) + return r; - } else if (streq_ptr(p.service, "io.systemd.Multiplexer")) { + 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; - _cleanup_free_ char *last_user_name = NULL, *last_group_name = NULL; - _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL; + for (;;) { + _cleanup_free_ char *user_name = NULL, *group_name = 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); - } - - if (!last_user_name) { - assert(!last_group_name); - return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); + free(last_user_name); + free(last_group_name); } - assert(last_group_name); + last_user_name = TAKE_PTR(user_name); + last_group_name = TAKE_PTR(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)))); + if (!last_user_name) { + assert(!last_group_name); + return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL); } - return varlink_error(link, "io.systemd.UserDatabase.BadService", 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) { |