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.
This commit is contained in:
@@ -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)));
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user