user-record-nss: preserve valid nss lookup aliases in records

NSS lookups may resolve an alias-like name to a canonical user or group
name. For example, SSSD can resolve a userPrincipalName such as
"testuser@example.test" while returning a passwd record whose pw_name is
the canonical login name "testuser".

The NSS userdb worker currently converts such records using only the
canonical name. As a result, the originally requested lookup name is lost,
and lookups through the varlink/multiplexer path may fail with
ConflictingRecordFound even though direct NSS lookup succeeds.

Preserve the originally requested lookup name as an alias when it differs
from the canonical passwd/group name and passes normal alias validation.
Add the alias both to the parsed record fields and to the JSON
representation so serialized records remain self-consistent.

Extend group record loading and matching to understand aliases too.
When both a name and UID/GID are specified in a userdb lookup, prefer
the by-name path so alias-aware records can satisfy the subsequent
consistency checks.

This allows canonicalized NSS results to match the original lookup name
correctly and fixes session setup for users logging in with
NSS-resolvable aliases such as UPNs.
This commit is contained in:
Arseniy Kostevich
2026-06-15 16:54:35 +03:00
parent b85a12dfb2
commit caf6d7b6b5
8 changed files with 76 additions and 21 deletions
+11 -7
View File
@@ -176,10 +176,12 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
if (r < 0)
return r;
if (uid_is_valid(p.uid))
r = userdb_by_uid(p.uid, &p.match, userdb_flags, &hr);
else if (p.name)
/* Prefer lookup by name if both name and UID are specified, so NSS-backed records preserve
* the requested lookup name as an alias before we check the UID below. */
if (p.name)
r = userdb_by_name(p.name, &p.match, userdb_flags, &hr);
else if (uid_is_valid(p.uid))
r = userdb_by_uid(p.uid, &p.match, userdb_flags, &hr);
else {
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
@@ -317,10 +319,12 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
if (r < 0)
return r;
if (gid_is_valid(p.gid))
r = groupdb_by_gid(p.gid, &p.match, userdb_flags, &g);
else if (p.name)
/* Prefer lookup by name if both name and GID are specified, so NSS-backed records preserve
* the requested lookup name as an alias before we check the GID below. */
if (p.name)
r = groupdb_by_name(p.name, &p.match, userdb_flags, &g);
else if (gid_is_valid(p.gid))
r = groupdb_by_gid(p.gid, &p.match, userdb_flags, &g);
else {
_cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL;
@@ -360,7 +364,7 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
return sd_varlink_error(link, "io.systemd.UserDatabase.ServiceNotAvailable", NULL);
}
if ((uid_is_valid(p.gid) && g->gid != p.gid) ||
if ((gid_is_valid(p.gid) && g->gid != p.gid) ||
(p.name && !group_record_matches_group_name(g, p.name)))
return sd_varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL);