From: Lennart Poettering Date: Fri, 17 Feb 2023 21:22:16 +0000 (+0100) Subject: user-record: extend user records with an ambient and bounding caps set field X-Git-Tag: v254-rc1~1143^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e1bc689de4c0824f674c0dea7e4c741c601be4c;p=thirdparty%2Fsystemd.git user-record: extend user records with an ambient and bounding caps set field In particular the ambieht caps field is useful: we can use it later to pass caps such as CAP_WAKE_ALARM to regular users on login. --- diff --git a/src/shared/user-record-show.c b/src/shared/user-record-show.c index da181c6078a..28fa7a86324 100644 --- a/src/shared/user-record-show.c +++ b/src/shared/user-record-show.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "cap-list.h" #include "format-util.h" #include "fs-util.h" #include "process-util.h" @@ -287,6 +288,22 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) { if (hr->access_mode != MODE_INVALID) printf(" Access Mode: 0%03o\n", user_record_access_mode(hr)); + uint64_t caps = user_record_capability_bounding_set(hr); + if (caps != UINT64_MAX) { + _cleanup_free_ char *scaps = NULL; + + (void) capability_set_to_string_negative(caps, &scaps); + printf(" Bound. Caps: %s\n", strna(scaps)); + } + + caps = user_record_capability_ambient_set(hr); + if (caps != UINT64_MAX) { + _cleanup_free_ char *scaps = NULL; + + (void) capability_set_to_string(caps, &scaps); + printf("Ambient Caps: %s\n", strna(scaps)); + } + if (storage == USER_LUKS) { printf("LUKS Discard: online=%s offline=%s\n", yes_no(user_record_luks_discard(hr)), yes_no(user_record_luks_offline_discard(hr))); diff --git a/src/shared/user-record.c b/src/shared/user-record.c index 06bc699572f..b51d8add1af 100644 --- a/src/shared/user-record.c +++ b/src/shared/user-record.c @@ -2,6 +2,7 @@ #include +#include "cap-list.h" #include "cgroup-util.h" #include "dns-domain.h" #include "env-util.h" @@ -165,6 +166,8 @@ static UserRecord* user_record_free(UserRecord *h) { free(h->home_directory_auto); strv_free(h->member_of); + strv_free(h->capability_bounding_set); + strv_free(h->capability_ambient_set); free(h->file_system_type); free(h->luks_cipher); @@ -1203,6 +1206,8 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp { "uid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, uid), 0 }, { "gid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, gid), 0 }, { "memberOf", JSON_VARIANT_ARRAY, json_dispatch_user_group_list, offsetof(UserRecord, member_of), JSON_RELAX}, + { "capabilityBoundingSet", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(UserRecord, capability_bounding_set), JSON_SAFE }, + { "capabilityAmbientSet", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(UserRecord, capability_ambient_set), JSON_SAFE }, { "fileSystemType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, file_system_type), JSON_SAFE }, { "partitionUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, partition_uuid), 0 }, { "luksUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, luks_uuid), 0 }, @@ -1557,6 +1562,8 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla { "uid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, uid), 0 }, { "gid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, gid), 0 }, { "memberOf", JSON_VARIANT_ARRAY, json_dispatch_user_group_list, offsetof(UserRecord, member_of), JSON_RELAX}, + { "capabilityBoundingSet", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(UserRecord, capability_bounding_set), JSON_SAFE }, + { "capabilityAmbientSet", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(UserRecord, capability_ambient_set), JSON_SAFE }, { "fileSystemType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, file_system_type), JSON_SAFE }, { "partitionUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, partition_uuid), 0 }, { "luksUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, luks_uuid), 0 }, @@ -2018,6 +2025,43 @@ uint64_t user_record_rebalance_weight(UserRecord *h) { return h->rebalance_weight; } +static uint64_t parse_caps_strv(char **l) { + uint64_t c = 0; + int r; + + STRV_FOREACH(i, l) { + r = capability_from_name(*i); + if (r < 0) + log_debug_errno(r, "Don't know capability '%s', ignoring: %m", *i); + else + c |= UINT64_C(1) << r; + } + + return c; +} + +uint64_t user_record_capability_bounding_set(UserRecord *h) { + assert(h); + + /* Returns UINT64_MAX if no bounding set is configured (!) */ + + if (!h->capability_bounding_set) + return UINT64_MAX; + + return parse_caps_strv(h->capability_bounding_set); +} + +uint64_t user_record_capability_ambient_set(UserRecord *h) { + assert(h); + + /* Returns UINT64_MAX if no ambient set is configured (!) */ + + if (!h->capability_ambient_set) + return UINT64_MAX; + + return parse_caps_strv(h->capability_ambient_set) & user_record_capability_bounding_set(h); +} + uint64_t user_record_ratelimit_next_try(UserRecord *h) { assert(h); diff --git a/src/shared/user-record.h b/src/shared/user-record.h index 73fb86cc945..298dc244fe4 100644 --- a/src/shared/user-record.h +++ b/src/shared/user-record.h @@ -366,6 +366,9 @@ typedef struct UserRecord { RecoveryKey *recovery_key; size_t n_recovery_key; + char **capability_bounding_set; + char **capability_ambient_set; + JsonVariant *json; } UserRecord; @@ -410,6 +413,8 @@ bool user_record_can_authenticate(UserRecord *h); bool user_record_drop_caches(UserRecord *h); AutoResizeMode user_record_auto_resize_mode(UserRecord *h); uint64_t user_record_rebalance_weight(UserRecord *h); +uint64_t user_record_capability_bounding_set(UserRecord *h); +uint64_t user_record_capability_ambient_set(UserRecord *h); int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret);