group_record_match() handled the other filters, but ignored match->uuid,
so userdbctl group --uuid=... could still return non-matching groups.
Add the same UUID check used by user_record_match().
Reproduced locally:
build/userdbctl --uuid=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa \
--output=json group root
Before result:
The command succeeded and printed the root group record.
Follow-up for: 466562c69b
When doing a userdb lookup we might end up issuing a lot of IPC calls in
parallel to backends and cause them all to do work, with us waiting for
it. Let's optimize this a bit, and indicate on the socket inodes via
xattrs hints which kind of records are provided by a backend. That way
we can suppress lookups to them and optimize runtime behaviour.
This only works on Linux 7.1 and newer where socket inodes gained
support for extended attributes.
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.
Now that we dlopen() so many deps, it might happen by accident that we
end up dlopen()ening stuff when we entered a container, which we should
really avoid, to not mix host and container libraries.
Let's add a global variable we can set when we want to block dlopen() to
ever succeed. This is then checked primarily in
dlopen_many_sym_or_warn(), where we'll generate EPERM plus a log
message.
There are a couple of other places we invoke dlopen(), without going
through dlopen_many_sym_or_warn(). This adds the same check there.
The man page nss-systemd(8) says
> The contents of these files are currently not read, and the files
> should be created empty.
But previously we filtered out such files, as the CONF_FILES_FILTER_MASKED
flag checks if a file is empty (or symlink to null), thus any empty files
were ignored.
To accept empty .membership files, let's use CONF_FILES_FILTER_MASKED_BY_SYMLINK.
Fixes#37945.
Both ENOEXEC and ESRCH is a kind of error that indicate successful
lookup. ENOEXEC means the server found an entry but it does not
pass filter. ESRCH means the server could not find an entry.
Hence, ENOEXEC should have more information, and should be propagated to
the caller.
When the flag is set, even if the specified UID/GID does not exist,
create a synthetic user record for the UID/GID.
Currently, only system UID/GID are supported.
Now that the necessary functions from log.h have been moved to macro.h,
we can stop including log.h in macro.h. This requires modifying source
files all over the tree to include log.h instead.
Since we can evaluate even the case with invalid ids (non-matching) we
can switch the function to pure boolean with no error cases and simpler
(none) return error handling.
The commit 7419291670 ("userdb: move UserDBMatch handling from userdbctl
into generic userdb code to allow it to be done server side")
unintentionally passes return value from group_record_match() as its
return value and thus diverges from other search functions that return 0
on success. Align that by returning 0 instead of 1, all existing callers
are invariant to this change.
This moves around the UserDBMatch handling, moves it out of userdbctl
and into generic userdb code, so that it can be passed to the server
side, to allow server side filtering.
This is preparation for one day allowing complex software to do such
filtering server side, and thus reducing the necessary traffic.
Right now no server side actually knows this, hence care is taken to
downgrade to the userdb varlink API as it was in v257 in case the new
options are not understood. This retains compatibility with any
implementation hence.
We currently set this at two distinct places right before calling
userdb_connect(). let's do this inside of userdb_connect() instead, and
derive it directly from the socket path.
This doesn't change behaviour but simplifies things a bit.
errno handling for NSS is always a bit weird since NSS modules generally
are not particularly careful with it. Hence let's initialize errno
explicitly before we invoke getpwent() so that we know it's in a
reasonable state afterwards on failure, or zero if not.
We do this in most places we use NSS, including in userdb when it comes
to getgrent(), just for getpwent() we don't so far. Address that.
if a userdb service refuse a user/group name as invalid, let's turn this
into ESRCH client-side following that there definitely is no user/group
record for a completely invalid user/group name.
Replaces: #34558
Let's systematically use RTL_NOW|RLTD_NODELETE as flags passed to
dlopen(), across our codebase.
Various distros build with "-z now" anyway, hence it's weird to specify
RTLD_LAZY trying to override that (which it doesn't). Hence, let's
follow suit, and just do what everybody else does.
Also set RTLD_NODELETE, which is apparently what distros will probably
end up implying sooner or later anyway. Given that for pretty much all
our dlopen() calls we never call dlclose() anyway, let's just set this
everywhere too, to make things systematic.
This way, the flags we use by default match what distros such as fedora
do, there are no surprises, and read-only relocations can be a thing.
Fixes: #34537
It's time. sd-json was already done earlier in this cycle, let's now
make sd-varlink public too.
This is mostly just a search/replace job of epical proportions.
I left some functions internal (mostly IDL handling), and I turned some
static inline calls into regular calls.
This is preparation for making our Varlink API a public API. Since our
Varlink API is built on top of our JSON API we need to make that public
first (it's a nice API, but JSON APIs there are already enough, this is
purely about the Varlink angle).
I made most of the json.h APIs public, and just placed them in
sd-json.h. Sometimes I wasn't so sure however, since the underlying data
structures would have to be made public too. If in doubt I didn#t risk
it, and moved the relevant API to src/libsystemd/sd-json/json-util.h
instead (without any sd_* symbol prefixes).
This is mostly a giant search/replace patch.
If we want to allow method replies to be extended without this breaking
compat, then we should set this flag. Do so at various method call
replies hence.
Also do it when parsing user/group records, which are expressly
documented to be extensible, as well as the hibernate JSON record.
varlink_dispatch() is a simple wrapper around json_dispatch() that
returns clean, standards-compliant InvalidParameter error back to
clients, if the specified JSON cannot be parsed properly.
For this json_dispatch() is extended to return the offending field's
name. Because it already has quite a few parameters, I then renamed
json_dispatch() to json_dispatch_full() and made json_dispatch() a
wrapper around it that passes the new argument as NULL. While doing so I
figured we should also get rid of the bad= argument in the short
wrapper, since it's only used in the OCI code.
To simplify the OCI code this adds a second wrapper oci_dispatch()
around json_dispatch_full(), that fills in bad= the way we want.
Net result: instead of one json_dispatch() call there are now:
1. json_dispatch_full() for the fully feature mother of all dispathers.
2. json_dispatch() for the simpler version that you want to use most of
the time.
3. varlink_dispatch() that generates nice Varlink errors
4. oci_dispatch() that does the OCI specific error handling
And that's all there is.
This macro is like JSON_BUILD_STRING() but uses our json library's
ability to use literal strings directly as JsonVariant objects.
The changes all our codebase to use this new macro whenever we build
JSON objects from literal strings.
(I tried to make this automatic, i.e. to detect in JSON_BUILD_STRING()
whether something is a literal string nicely and thus do this stuff
automatically, but I couldn't find a way.)
This should reduce memory usage of our JSON code a bit. Constant strings
we use very often will now be shared and mapped directly from the ELF
image.
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
Let's initialize this at the same place for any iterator allocated. (Yes
not all types of iterator objects need this, but it's still nice to
share this trivial code at one place).
Clearly communicate to callers that we didn't find a single varlink
service, when a lookup is attempted. Note that the fallback's to NSS,
drop-ins and synthesis might eat up this error again, but we should
really make this case reasonably recognizable, in particular as our
various tools already handle this condition correctly and print a nice
message then.