diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/user-record.c | 72 | ||||
-rw-r--r-- | src/shared/user-record.h | 6 |
2 files changed, 58 insertions, 20 deletions
diff --git a/src/shared/user-record.c b/src/shared/user-record.c index 966abc5c42..38e5f01c23 100644 --- a/src/shared/user-record.c +++ b/src/shared/user-record.c @@ -167,6 +167,9 @@ static UserRecord* user_record_free(UserRecord *h) { free(h->home_directory); free(h->home_directory_auto); + free(h->fallback_shell); + free(h->fallback_home_directory); + strv_free(h->member_of); strv_free(h->capability_bounding_set); strv_free(h->capability_ambient_set); @@ -1325,23 +1328,26 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp static int dispatch_status(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static const JsonDispatch status_dispatch_table[] = { - { "diskUsage", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_usage), 0 }, - { "diskFree", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_free), 0 }, - { "diskSize", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_size), 0 }, - { "diskCeiling", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_ceiling), 0 }, - { "diskFloor", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_floor), 0 }, - { "state", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, state), JSON_SAFE }, - { "service", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, service), JSON_SAFE }, - { "signedLocally", _JSON_VARIANT_TYPE_INVALID, json_dispatch_tristate, offsetof(UserRecord, signed_locally), 0 }, - { "goodAuthenticationCounter", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, good_authentication_counter), 0 }, - { "badAuthenticationCounter", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, bad_authentication_counter), 0 }, - { "lastGoodAuthenticationUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, last_good_authentication_usec), 0 }, - { "lastBadAuthenticationUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, last_bad_authentication_usec), 0 }, - { "rateLimitBeginUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_begin_usec), 0 }, - { "rateLimitCount", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_count), 0 }, - { "removable", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(UserRecord, removable), 0 }, - { "accessMode", JSON_VARIANT_UNSIGNED, json_dispatch_access_mode, offsetof(UserRecord, access_mode), 0 }, - { "fileSystemType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, file_system_type), JSON_SAFE }, + { "diskUsage", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_usage), 0 }, + { "diskFree", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_free), 0 }, + { "diskSize", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_size), 0 }, + { "diskCeiling", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_ceiling), 0 }, + { "diskFloor", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, disk_floor), 0 }, + { "state", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, state), JSON_SAFE }, + { "service", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, service), JSON_SAFE }, + { "signedLocally", _JSON_VARIANT_TYPE_INVALID, json_dispatch_tristate, offsetof(UserRecord, signed_locally), 0 }, + { "goodAuthenticationCounter", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, good_authentication_counter), 0 }, + { "badAuthenticationCounter", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, bad_authentication_counter), 0 }, + { "lastGoodAuthenticationUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, last_good_authentication_usec), 0 }, + { "lastBadAuthenticationUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, last_bad_authentication_usec), 0 }, + { "rateLimitBeginUSec", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_begin_usec), 0 }, + { "rateLimitCount", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(UserRecord, ratelimit_count), 0 }, + { "removable", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(UserRecord, removable), 0 }, + { "accessMode", JSON_VARIANT_UNSIGNED, json_dispatch_access_mode, offsetof(UserRecord, access_mode), 0 }, + { "fileSystemType", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, file_system_type), JSON_SAFE }, + { "fallbackShell", JSON_VARIANT_STRING, json_dispatch_filename_or_path, offsetof(UserRecord, fallback_shell), 0 }, + { "fallbackHomeDirectory", JSON_VARIANT_STRING, json_dispatch_home_directory, offsetof(UserRecord, fallback_home_directory), 0 }, + { "useFallback", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(UserRecord, use_fallback), 0 }, {}, }; @@ -1752,7 +1758,7 @@ mode_t user_record_access_mode(UserRecord *h) { return h->access_mode != MODE_INVALID ? h->access_mode : 0700; } -const char* user_record_home_directory(UserRecord *h) { +static const char *user_record_home_directory_real(UserRecord *h) { assert(h); if (h->home_directory) @@ -1767,6 +1773,15 @@ const char* user_record_home_directory(UserRecord *h) { return "/"; } +const char* user_record_home_directory(UserRecord *h) { + assert(h); + + if (h->use_fallback && h->fallback_home_directory) + return h->fallback_home_directory; + + return user_record_home_directory_real(h); +} + const char *user_record_image_path(UserRecord *h) { assert(h); @@ -1775,7 +1790,9 @@ const char *user_record_image_path(UserRecord *h) { if (h->image_path_auto) return h->image_path_auto; - return IN_SET(user_record_storage(h), USER_CLASSIC, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT) ? user_record_home_directory(h) : NULL; + /* For some storage types the image is the home directory itself. (But let's ignore the fallback logic for it) */ + return IN_SET(user_record_storage(h), USER_CLASSIC, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT) ? + user_record_home_directory_real(h) : NULL; } const char *user_record_cifs_user_name(UserRecord *h) { @@ -1792,7 +1809,7 @@ unsigned long user_record_mount_flags(UserRecord *h) { (h->nodev ? MS_NODEV : 0); } -const char *user_record_shell(UserRecord *h) { +static const char *user_record_shell_real(UserRecord *h) { assert(h); if (h->shell) @@ -1807,6 +1824,21 @@ const char *user_record_shell(UserRecord *h) { return NOLOGIN; } +const char *user_record_shell(UserRecord *h) { + const char *shell; + + assert(h); + + shell = user_record_shell_real(h); + + /* Return fallback shall if we are told so — except if the primary shell is already a nologin shell, + * then let's not risk anything. */ + if (h->use_fallback && h->fallback_shell) + return is_nologin_shell(shell) ? NOLOGIN : h->fallback_shell; + + return shell; +} + const char *user_record_real_name(UserRecord *h) { assert(h); diff --git a/src/shared/user-record.h b/src/shared/user-record.h index 0afbc796d2..ee63a5364c 100644 --- a/src/shared/user-record.h +++ b/src/shared/user-record.h @@ -293,6 +293,10 @@ typedef struct UserRecord { char *home_directory; char *home_directory_auto; /* when none is set explicitly, this is where we place the implicit home directory */ + /* fallback shell and home dir */ + char *fallback_shell; + char *fallback_home_directory; + uid_t uid; gid_t gid; @@ -322,6 +326,8 @@ typedef struct UserRecord { uint64_t disk_ceiling; uint64_t disk_floor; + bool use_fallback; /* if true → use fallback_shell + fallback_home_directory instead of the regular ones */ + char *state; char *service; int signed_locally; |