163 lines
10 KiB
Diff
163 lines
10 KiB
Diff
From 9b5c0f5201194158377da6a3366fa87743395b9b Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Wed, 22 Jan 2025 16:45:52 +0100
|
|
Subject: [PATCH] userdbd: implement server side filtering in the Multiplexer
|
|
API
|
|
|
|
This impelements server side filtering in userdbd's multiplexer logic.
|
|
Note thta this means that even if some backend doesn't support it
|
|
natively the multiplexer will deal with it and apply the filtering as
|
|
necessary.
|
|
|
|
(cherry picked from commit 5ec4933dd5c38d09ed6169cbb22c79ca3be217ce)
|
|
|
|
Related: RHEL-143036
|
|
---
|
|
src/userdb/userwork.c | 53 ++++++++++++++++++++++++++++++-------------
|
|
1 file changed, 37 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c
|
|
index da115ec6e5..b030fae84c 100644
|
|
--- a/src/userdb/userwork.c
|
|
+++ b/src/userdb/userwork.c
|
|
@@ -35,8 +35,15 @@ typedef struct LookupParameters {
|
|
gid_t gid;
|
|
};
|
|
const char *service;
|
|
+ UserDBMatch match;
|
|
} LookupParameters;
|
|
|
|
+static void lookup_parameters_done(LookupParameters *p) {
|
|
+ assert(p);
|
|
+
|
|
+ userdb_match_done(&p->match);
|
|
+}
|
|
+
|
|
static int add_nss_service(sd_json_variant **v) {
|
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *status = NULL, *z = NULL;
|
|
sd_id128_t mid;
|
|
@@ -134,16 +141,21 @@ static int userdb_flags_from_service(sd_varlink *link, const char *service, User
|
|
static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
|
|
|
static const sd_json_dispatch_field dispatch_table[] = {
|
|
- { "uid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(LookupParameters, uid), 0 },
|
|
- { "userName", SD_JSON_VARIANT_STRING, json_dispatch_const_user_group_name, offsetof(LookupParameters, name), SD_JSON_RELAX },
|
|
- { "service", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
|
|
+ { "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, uid), 0 },
|
|
+ { "userName", SD_JSON_VARIANT_STRING, json_dispatch_const_user_group_name, offsetof(LookupParameters, name), SD_JSON_RELAX },
|
|
+ { "service", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
|
|
+ { "fuzzyNames", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(LookupParameters, match.fuzzy_names), 0 },
|
|
+ { "dispositionMask", SD_JSON_VARIANT_ARRAY, json_dispatch_dispositions_mask, offsetof(LookupParameters, match.disposition_mask), 0 },
|
|
+ { "uidMin", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.uid_min), 0 },
|
|
+ { "uidMax", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.uid_max), 0 },
|
|
{}
|
|
};
|
|
|
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
|
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
|
|
- LookupParameters p = {
|
|
+ _cleanup_(lookup_parameters_done) LookupParameters p = {
|
|
.uid = UID_INVALID,
|
|
+ .match = USERDB_MATCH_NULL,
|
|
};
|
|
UserDBFlags userdb_flags;
|
|
int r;
|
|
@@ -160,14 +172,14 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
|
|
return r;
|
|
|
|
if (uid_is_valid(p.uid))
|
|
- r = userdb_by_uid(p.uid, /* match= */ NULL, userdb_flags, &hr);
|
|
+ r = userdb_by_uid(p.uid, &p.match, userdb_flags, &hr);
|
|
else if (p.name)
|
|
- r = userdb_by_name(p.name, /* match= */ NULL, userdb_flags, &hr);
|
|
+ r = userdb_by_name(p.name, &p.match, userdb_flags, &hr);
|
|
else {
|
|
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *last = NULL;
|
|
|
|
- r = userdb_all(/* match= */ NULL, userdb_flags, &iterator);
|
|
+ r = userdb_all(&p.match, userdb_flags, &iterator);
|
|
if (IN_SET(r, -ESRCH, -ENOLINK))
|
|
/* We turn off Varlink lookups in various cases (e.g. in case we only enable DropIn
|
|
* backend) — this might make userdb_all return ENOLINK (which indicates that varlink
|
|
@@ -182,7 +194,7 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
|
|
for (;;) {
|
|
_cleanup_(user_record_unrefp) UserRecord *z = NULL;
|
|
|
|
- r = userdb_iterator_get(iterator, /* match= */ NULL, &z);
|
|
+ r = userdb_iterator_get(iterator, &p.match, &z);
|
|
if (r == -ESRCH)
|
|
break;
|
|
if (r < 0)
|
|
@@ -208,6 +220,8 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
|
|
}
|
|
if (r == -ESRCH)
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
+ if (r == -ENOEXEC)
|
|
+ return sd_varlink_error(link, "io.systemd.UserDatabase.NonMatchingRecordFound", NULL);
|
|
if (r < 0) {
|
|
log_debug_errno(r, "User lookup failed abnormally: %m");
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.ServiceNotAvailable", NULL);
|
|
@@ -271,16 +285,21 @@ static int build_group_json(sd_varlink *link, GroupRecord *gr, sd_json_variant *
|
|
static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
|
|
|
static const sd_json_dispatch_field dispatch_table[] = {
|
|
- { "gid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(LookupParameters, gid), 0 },
|
|
- { "groupName", SD_JSON_VARIANT_STRING, json_dispatch_const_user_group_name, offsetof(LookupParameters, name), SD_JSON_RELAX },
|
|
- { "service", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
|
|
+ { "gid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, gid), 0 },
|
|
+ { "groupName", SD_JSON_VARIANT_STRING, json_dispatch_const_user_group_name, offsetof(LookupParameters, name), SD_JSON_RELAX },
|
|
+ { "service", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
|
|
+ { "fuzzyNames", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(LookupParameters, match.fuzzy_names), 0 },
|
|
+ { "dispositionMask", SD_JSON_VARIANT_ARRAY, json_dispatch_dispositions_mask, offsetof(LookupParameters, match.disposition_mask), 0 },
|
|
+ { "gidMin", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.gid_min), 0 },
|
|
+ { "gidMax", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(LookupParameters, match.gid_max), 0 },
|
|
{}
|
|
};
|
|
|
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
|
_cleanup_(group_record_unrefp) GroupRecord *g = NULL;
|
|
- LookupParameters p = {
|
|
+ _cleanup_(lookup_parameters_done) LookupParameters p = {
|
|
.gid = GID_INVALID,
|
|
+ .match = USERDB_MATCH_NULL,
|
|
};
|
|
UserDBFlags userdb_flags;
|
|
int r;
|
|
@@ -296,14 +315,14 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
|
|
return r;
|
|
|
|
if (gid_is_valid(p.gid))
|
|
- r = groupdb_by_gid(p.gid, /* match= */ NULL, userdb_flags, &g);
|
|
+ r = groupdb_by_gid(p.gid, &p.match, userdb_flags, &g);
|
|
else if (p.name)
|
|
- r = groupdb_by_name(p.name, /* match= */ NULL, userdb_flags, &g);
|
|
+ r = groupdb_by_name(p.name, &p.match, userdb_flags, &g);
|
|
else {
|
|
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
|
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *last = NULL;
|
|
|
|
- r = groupdb_all(/* match= */ NULL, userdb_flags, &iterator);
|
|
+ r = groupdb_all(&p.match, userdb_flags, &iterator);
|
|
if (IN_SET(r, -ESRCH, -ENOLINK))
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
if (r < 0)
|
|
@@ -312,7 +331,7 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
|
|
for (;;) {
|
|
_cleanup_(group_record_unrefp) GroupRecord *z = NULL;
|
|
|
|
- r = groupdb_iterator_get(iterator, /* match= */ NULL, &z);
|
|
+ r = groupdb_iterator_get(iterator, &p.match, &z);
|
|
if (r == -ESRCH)
|
|
break;
|
|
if (r < 0)
|
|
@@ -338,6 +357,8 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
|
|
}
|
|
if (r == -ESRCH)
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
+ if (r == -ENOEXEC)
|
|
+ return sd_varlink_error(link, "io.systemd.UserDatabase.NonMatchingRecordFound", NULL);
|
|
if (r < 0) {
|
|
log_debug_errno(r, "Group lookup failed abnormally: %m");
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.ServiceNotAvailable", NULL);
|