summaryrefslogtreecommitdiff
path: root/src/userdb
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-05-06 16:01:44 +0200
committerLennart Poettering <lennart@poettering.net>2021-05-07 22:19:41 +0200
commit134ff8f4d1bbfe189957fb9418d88392ab315867 (patch)
tree4848a883d785d74cae573dd589f91eea9d93dcfb /src/userdb
parentb214825433ba716ec87a0cafb8cbf9870efc21c1 (diff)
downloadsystemd-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.c441
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) {