504 lines
21 KiB
Diff
504 lines
21 KiB
Diff
From d2d21aa57f8c266002c96ea41e811db28b40eeca Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Thu, 16 Jan 2025 14:08:51 +0100
|
|
Subject: [PATCH] homed: support user record aliases
|
|
|
|
(cherry picked from commit 40fd0e0423ed9e4ae47d7f1adba83c0487d7decd)
|
|
|
|
Resolves: RHEL-109902
|
|
---
|
|
src/home/homectl.c | 12 +-----
|
|
src/home/homed-home-bus.c | 7 +++-
|
|
src/home/homed-home.c | 28 ++++++++++++-
|
|
src/home/homed-home.h | 5 +++
|
|
src/home/homed-manager-bus.c | 76 ++++++++++++++++++++++++++----------
|
|
src/home/homed-manager.c | 50 +++++++++++++++++++-----
|
|
src/home/homed-manager.h | 2 +
|
|
src/home/homed-varlink.c | 28 +++++++------
|
|
8 files changed, 154 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/src/home/homectl.c b/src/home/homectl.c
|
|
index 47ca015813..f48b8dc833 100644
|
|
--- a/src/home/homectl.c
|
|
+++ b/src/home/homectl.c
|
|
@@ -741,17 +741,9 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
|
|
uid_t uid;
|
|
|
|
r = parse_uid(*i, &uid);
|
|
- if (r < 0) {
|
|
- if (!valid_user_group_name(*i, 0)) {
|
|
- log_error("Invalid user name '%s'.", *i);
|
|
- if (ret == 0)
|
|
- ret = -EINVAL;
|
|
-
|
|
- continue;
|
|
- }
|
|
-
|
|
+ if (r < 0)
|
|
r = bus_call_method(bus, bus_mgr, "GetUserRecordByName", &error, &reply, "s", *i);
|
|
- } else
|
|
+ else
|
|
r = bus_call_method(bus, bus_mgr, "GetUserRecordByUID", &error, &reply, "u", (uint32_t) uid);
|
|
if (r < 0) {
|
|
log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
|
|
diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c
|
|
index 80e2773447..a3e6a32162 100644
|
|
--- a/src/home/homed-home-bus.c
|
|
+++ b/src/home/homed-home-bus.c
|
|
@@ -799,8 +799,11 @@ static int bus_home_object_find(
|
|
|
|
if (parse_uid(e, &uid) >= 0)
|
|
h = hashmap_get(m->homes_by_uid, UID_TO_PTR(uid));
|
|
- else
|
|
- h = hashmap_get(m->homes_by_name, e);
|
|
+ else {
|
|
+ r = manager_get_home_by_name(m, e, &h);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ }
|
|
if (!h)
|
|
return 0;
|
|
|
|
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
|
|
index 32691e4f81..44e3274c42 100644
|
|
--- a/src/home/homed-home.c
|
|
+++ b/src/home/homed-home.c
|
|
@@ -106,6 +106,7 @@ static int suitable_home_record(UserRecord *hr) {
|
|
int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
|
_cleanup_(home_freep) Home *home = NULL;
|
|
_cleanup_free_ char *nm = NULL, *ns = NULL, *blob = NULL;
|
|
+ _cleanup_strv_free_ char **aliases = NULL;
|
|
int r;
|
|
|
|
assert(m);
|
|
@@ -118,19 +119,29 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
|
if (hashmap_contains(m->homes_by_name, hr->user_name))
|
|
return -EBUSY;
|
|
|
|
+ STRV_FOREACH(a, hr->aliases)
|
|
+ if (hashmap_contains(m->homes_by_name, *a))
|
|
+ return -EBUSY;
|
|
+
|
|
if (hashmap_contains(m->homes_by_uid, UID_TO_PTR(hr->uid)))
|
|
return -EBUSY;
|
|
|
|
if (sysfs && hashmap_contains(m->homes_by_sysfs, sysfs))
|
|
return -EBUSY;
|
|
|
|
- if (hashmap_size(m->homes_by_name) >= HOME_USERS_MAX)
|
|
+ if (hashmap_size(m->homes_by_uid) >= HOME_USERS_MAX)
|
|
return -EUSERS;
|
|
|
|
nm = strdup(hr->user_name);
|
|
if (!nm)
|
|
return -ENOMEM;
|
|
|
|
+ if (!strv_isempty(hr->aliases)) {
|
|
+ aliases = strv_copy(hr->aliases);
|
|
+ if (!aliases)
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
if (sysfs) {
|
|
ns = strdup(sysfs);
|
|
if (!ns)
|
|
@@ -144,6 +155,7 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
|
*home = (Home) {
|
|
.manager = m,
|
|
.user_name = TAKE_PTR(nm),
|
|
+ .aliases = TAKE_PTR(aliases),
|
|
.uid = hr->uid,
|
|
.state = _HOME_STATE_INVALID,
|
|
.worker_stdout_fd = -EBADF,
|
|
@@ -157,6 +169,12 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
|
if (r < 0)
|
|
return r;
|
|
|
|
+ STRV_FOREACH(a, home->aliases) {
|
|
+ r = hashmap_put(m->homes_by_name, *a, home);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ }
|
|
+
|
|
r = hashmap_put(m->homes_by_uid, UID_TO_PTR(home->uid), home);
|
|
if (r < 0)
|
|
return r;
|
|
@@ -202,6 +220,9 @@ Home *home_free(Home *h) {
|
|
if (h->user_name)
|
|
(void) hashmap_remove_value(h->manager->homes_by_name, h->user_name, h);
|
|
|
|
+ STRV_FOREACH(a, h->aliases)
|
|
+ (void) hashmap_remove_value(h->manager->homes_by_name, *a, h);
|
|
+
|
|
if (uid_is_valid(h->uid))
|
|
(void) hashmap_remove_value(h->manager->homes_by_uid, UID_TO_PTR(h->uid), h);
|
|
|
|
@@ -223,6 +244,7 @@ Home *home_free(Home *h) {
|
|
h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source);
|
|
safe_close(h->worker_stdout_fd);
|
|
free(h->user_name);
|
|
+ strv_free(h->aliases);
|
|
free(h->sysfs);
|
|
|
|
h->ref_event_source_please_suspend = sd_event_source_disable_unref(h->ref_event_source_please_suspend);
|
|
@@ -262,6 +284,10 @@ int home_set_record(Home *h, UserRecord *hr) {
|
|
if (!user_record_compatible(h->record, hr))
|
|
return -EREMCHG;
|
|
|
|
+ /* For now do not allow changing list of aliases */
|
|
+ if (!strv_equal_ignore_order(h->aliases, hr->aliases))
|
|
+ return -EREMCHG;
|
|
+
|
|
if (!FLAGS_SET(hr->mask, USER_RECORD_REGULAR) ||
|
|
FLAGS_SET(hr->mask, USER_RECORD_SECRET))
|
|
return -EINVAL;
|
|
diff --git a/src/home/homed-home.h b/src/home/homed-home.h
|
|
index 8c92e39fe5..93689563d3 100644
|
|
--- a/src/home/homed-home.h
|
|
+++ b/src/home/homed-home.h
|
|
@@ -109,7 +109,12 @@ static inline bool HOME_STATE_MAY_RETRY_DEACTIVATE(HomeState state) {
|
|
|
|
struct Home {
|
|
Manager *manager;
|
|
+
|
|
+ /* The fields this record can be looked up by. This is kinda redundant, as the same information is
|
|
+ * available in the .record field, but we keep separate copies of these keys to make memory
|
|
+ * management for the hashmaps easier. */
|
|
char *user_name;
|
|
+ char **aliases;
|
|
uid_t uid;
|
|
|
|
char *sysfs; /* When found via plugged in device, the sysfs path to it */
|
|
diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c
|
|
index 08c917aee2..a08cc3803c 100644
|
|
--- a/src/home/homed-manager-bus.c
|
|
+++ b/src/home/homed-manager-bus.c
|
|
@@ -37,7 +37,7 @@ static int property_get_auto_login(
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
_cleanup_strv_free_ char **seats = NULL;
|
|
_cleanup_free_ char *home_path = NULL;
|
|
|
|
@@ -97,11 +97,9 @@ static int lookup_user_name(
|
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_HOME, "Client's UID " UID_FMT " not managed.", uid);
|
|
|
|
} else {
|
|
-
|
|
- if (!valid_user_group_name(user_name, 0))
|
|
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name %s is not valid", user_name);
|
|
-
|
|
- h = hashmap_get(m->homes_by_name, user_name);
|
|
+ r = manager_get_home_by_name(m, user_name, &h);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
if (!h)
|
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_HOME, "No home for user %s known", user_name);
|
|
}
|
|
@@ -342,6 +340,31 @@ static int method_deactivate_home(sd_bus_message *message, void *userdata, sd_bu
|
|
return generic_home_method(userdata, message, bus_home_method_deactivate, error);
|
|
}
|
|
|
|
+static int check_for_conflicts(Manager *m, const char *name, sd_bus_error *error) {
|
|
+ int r;
|
|
+
|
|
+ assert(m);
|
|
+ assert(name);
|
|
+
|
|
+ Home *other = hashmap_get(m->homes_by_name, name);
|
|
+ if (other)
|
|
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists already, refusing.", name);
|
|
+
|
|
+ r = getpwnam_malloc(name, /* ret= */ NULL);
|
|
+ if (r >= 0)
|
|
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists in the NSS user database, refusing.", name);
|
|
+ if (r != -ESRCH)
|
|
+ return r;
|
|
+
|
|
+ r = getgrnam_malloc(name, /* ret= */ NULL);
|
|
+ if (r >= 0)
|
|
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s conflicts with an NSS group by the same name, refusing.", name);
|
|
+ if (r != -ESRCH)
|
|
+ return r;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int validate_and_allocate_home(Manager *m, UserRecord *hr, Hashmap *blobs, Home **ret, sd_bus_error *error) {
|
|
_cleanup_(user_record_unrefp) UserRecord *signed_hr = NULL;
|
|
bool signed_locally;
|
|
@@ -356,21 +379,32 @@ static int validate_and_allocate_home(Manager *m, UserRecord *hr, Hashmap *blobs
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- other = hashmap_get(m->homes_by_name, hr->user_name);
|
|
- if (other)
|
|
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists already, refusing.", hr->user_name);
|
|
-
|
|
- r = getpwnam_malloc(hr->user_name, /* ret= */ NULL);
|
|
- if (r >= 0)
|
|
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists in the NSS user database, refusing.", hr->user_name);
|
|
- if (r != -ESRCH)
|
|
+ r = check_for_conflicts(m, hr->user_name, error);
|
|
+ if (r < 0)
|
|
return r;
|
|
|
|
- r = getgrnam_malloc(hr->user_name, /* ret= */ NULL);
|
|
- if (r >= 0)
|
|
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s conflicts with an NSS group by the same name, refusing.", hr->user_name);
|
|
- if (r != -ESRCH)
|
|
- return r;
|
|
+ if (hr->realm) {
|
|
+ r = check_for_conflicts(m, user_record_user_name_and_realm(hr), error);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ }
|
|
+
|
|
+ STRV_FOREACH(a, hr->aliases) {
|
|
+ r = check_for_conflicts(m, *a, error);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
+ if (hr->realm) {
|
|
+ _cleanup_free_ char *alias_with_realm = NULL;
|
|
+ alias_with_realm = strjoin(*a, "@", hr->realm);
|
|
+ if (!alias_with_realm)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ r = check_for_conflicts(m, alias_with_realm, error);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ }
|
|
+ }
|
|
|
|
if (blobs) {
|
|
const char *failed = NULL;
|
|
@@ -637,7 +671,7 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus
|
|
* for every suitable home we have and only when all of them completed we send a reply indicating
|
|
* completion. */
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
|
|
if (!home_shall_suspend(h))
|
|
continue;
|
|
@@ -676,7 +710,7 @@ static int method_deactivate_all_homes(sd_bus_message *message, void *userdata,
|
|
* systemd-homed.service itself since we want to allow restarting of it without tearing down all home
|
|
* directories. */
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
|
|
if (!o) {
|
|
o = operation_new(OPERATION_DEACTIVATE_ALL, message);
|
|
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
|
|
index de7c3d8dbe..6b9e4fcf11 100644
|
|
--- a/src/home/homed-manager.c
|
|
+++ b/src/home/homed-manager.c
|
|
@@ -75,7 +75,6 @@ static bool uid_is_home(uid_t uid) {
|
|
#define UID_CLAMP_INTO_HOME_RANGE(rnd) (((uid_t) (rnd) % (HOME_UID_MAX - HOME_UID_MIN + 1)) + HOME_UID_MIN)
|
|
|
|
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_uid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
|
|
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_name_hash_ops, char, string_hash_func, string_compare_func, Home, home_free);
|
|
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
|
|
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, path_hash_func, path_compare, Home, home_free);
|
|
|
|
@@ -191,7 +190,7 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
|
|
log_debug("%s has been moved away, revalidating.", j);
|
|
|
|
h = hashmap_get(m->homes_by_name, n);
|
|
- if (h) {
|
|
+ if (h && streq(h->user_name, n)) {
|
|
manager_revalidate_image(m, h);
|
|
(void) bus_manager_emit_auto_login_changed(m);
|
|
}
|
|
@@ -242,7 +241,7 @@ int manager_new(Manager **ret) {
|
|
if (!m->homes_by_uid)
|
|
return -ENOMEM;
|
|
|
|
- m->homes_by_name = hashmap_new(&homes_by_name_hash_ops);
|
|
+ m->homes_by_name = hashmap_new(&string_hash_ops);
|
|
if (!m->homes_by_name)
|
|
return -ENOMEM;
|
|
|
|
@@ -697,6 +696,11 @@ static int manager_add_home_by_image(
|
|
if (h) {
|
|
bool same;
|
|
|
|
+ if (!streq(h->user_name, user_name)) {
|
|
+ log_debug("Found an image for user %s which already is an alias for another user, skipping.", user_name);
|
|
+ return 0; /* Ignore images that would synthesize a user that conflicts with an alias of another user */
|
|
+ }
|
|
+
|
|
if (h->state != HOME_UNFIXATED) {
|
|
log_debug("Found an image for user %s which already has a record, skipping.", user_name);
|
|
return 0; /* ignore images that synthesize a user we already have a record for */
|
|
@@ -1714,7 +1718,7 @@ int manager_gc_images(Manager *m) {
|
|
} else {
|
|
/* Gc all */
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name)
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid)
|
|
manager_revalidate_image(m, h);
|
|
}
|
|
|
|
@@ -1734,12 +1738,14 @@ static int manager_gc_blob(Manager *m) {
|
|
return log_error_errno(errno, "Failed to open %s: %m", home_system_blob_dir());
|
|
}
|
|
|
|
- FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m"))
|
|
- if (!hashmap_contains(m->homes_by_name, de->d_name)) {
|
|
+ FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m")) {
|
|
+ Home *found = hashmap_get(m->homes_by_name, de->d_name);
|
|
+ if (!found || !streq(found->user_name, de->d_name)) {
|
|
r = rm_rf_at(dirfd(d), de->d_name, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
|
|
if (r < 0)
|
|
log_warning_errno(r, "Failed to delete blob dir for missing user '%s', ignoring: %m", de->d_name);
|
|
}
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -1834,7 +1840,7 @@ static bool manager_shall_rebalance(Manager *m) {
|
|
if (IN_SET(m->rebalance_state, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING))
|
|
return true;
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name)
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid)
|
|
if (home_shall_rebalance(h))
|
|
return true;
|
|
|
|
@@ -1880,7 +1886,7 @@ static int manager_rebalance_calculate(Manager *m) {
|
|
* (home dirs get 100 by default, i.e. 5x more). This weight
|
|
* is not configurable, the per-home weights are. */
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
statfs_f_type_t fstype;
|
|
h->rebalance_pending = false; /* First, reset the flag, we only want it to be true for the
|
|
* homes that qualify for rebalancing */
|
|
@@ -2017,7 +2023,7 @@ static int manager_rebalance_apply(Manager *m) {
|
|
|
|
assert(m);
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
if (!h->rebalance_pending)
|
|
@@ -2258,3 +2264,29 @@ int manager_reschedule_rebalance(Manager *m) {
|
|
|
|
return 1;
|
|
}
|
|
+
|
|
+int manager_get_home_by_name(Manager *m, const char *user_name, Home **ret) {
|
|
+ assert(m);
|
|
+ assert(user_name);
|
|
+
|
|
+ Home *h = hashmap_get(m->homes_by_name, user_name);
|
|
+ if (!h) {
|
|
+ /* Also search by username and realm. For that simply chop off realm, then look for the home, and verify it afterwards. */
|
|
+ const char *realm = strrchr(user_name, '@');
|
|
+ if (realm) {
|
|
+ _cleanup_free_ char *prefix = strndup(user_name, realm - user_name);
|
|
+ if (!prefix)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ Home *j;
|
|
+ j = hashmap_get(m->homes_by_name, prefix);
|
|
+ if (j && user_record_matches_user_name(j->record, user_name))
|
|
+ h = j;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ret)
|
|
+ *ret = h;
|
|
+
|
|
+ return !!h;
|
|
+}
|
|
diff --git a/src/home/homed-manager.h b/src/home/homed-manager.h
|
|
index 3369284e2a..7f9a8a8199 100644
|
|
--- a/src/home/homed-manager.h
|
|
+++ b/src/home/homed-manager.h
|
|
@@ -91,3 +91,5 @@ int manager_acquire_key_pair(Manager *m);
|
|
int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus_error *error);
|
|
|
|
int bus_manager_emit_auto_login_changed(Manager *m);
|
|
+
|
|
+int manager_get_home_by_name(Manager *m, const char *user_name, Home **ret);
|
|
diff --git a/src/home/homed-varlink.c b/src/home/homed-varlink.c
|
|
index cfd46ea51a..ef30ea7eaf 100644
|
|
--- a/src/home/homed-varlink.c
|
|
+++ b/src/home/homed-varlink.c
|
|
@@ -100,15 +100,17 @@ int vl_method_get_user_record(sd_varlink *link, sd_json_variant *parameters, sd_
|
|
|
|
if (uid_is_valid(p.uid))
|
|
h = hashmap_get(m->homes_by_uid, UID_TO_PTR(p.uid));
|
|
- else if (p.user_name)
|
|
- h = hashmap_get(m->homes_by_name, p.user_name);
|
|
- else {
|
|
+ else if (p.user_name) {
|
|
+ r = manager_get_home_by_name(m, p.user_name, &h);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ } else {
|
|
|
|
/* If neither UID nor name was specified, then dump all homes. Do so with varlink_notify()
|
|
* for all entries but the last, so that clients can stream the results, and easily process
|
|
* them piecemeal. */
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
|
|
if (!home_user_match_lookup_parameters(&p, h))
|
|
continue;
|
|
@@ -212,11 +214,13 @@ int vl_method_get_group_record(sd_varlink *link, sd_json_variant *parameters, sd
|
|
|
|
if (gid_is_valid(p.gid))
|
|
h = hashmap_get(m->homes_by_uid, UID_TO_PTR((uid_t) p.gid));
|
|
- else if (p.group_name)
|
|
- h = hashmap_get(m->homes_by_name, p.group_name);
|
|
- else {
|
|
+ else if (p.group_name) {
|
|
+ r = manager_get_home_by_name(m, p.group_name, &h);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ } else {
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
|
|
if (!home_group_match_lookup_parameters(&p, h))
|
|
continue;
|
|
@@ -279,7 +283,9 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|
if (p.user_name) {
|
|
const char *last = NULL;
|
|
|
|
- h = hashmap_get(m->homes_by_name, p.user_name);
|
|
+ r = manager_get_home_by_name(m, p.user_name, &h);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
if (!h)
|
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
|
|
|
@@ -315,7 +321,7 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|
} else if (p.group_name) {
|
|
const char *last = NULL;
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name) {
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
|
|
|
|
if (!strv_contains(h->record->member_of, p.group_name))
|
|
continue;
|
|
@@ -340,7 +346,7 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|
} else {
|
|
const char *last_user_name = NULL, *last_group_name = NULL;
|
|
|
|
- HASHMAP_FOREACH(h, m->homes_by_name)
|
|
+ HASHMAP_FOREACH(h, m->homes_by_uid)
|
|
STRV_FOREACH(j, h->record->member_of) {
|
|
|
|
if (last_user_name) {
|