/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once typedef struct Home Home; #include "homed-manager.h" #include "homed-operation.h" #include "list.h" #include "ordered-set.h" #include "stat-util.h" #include "user-record.h" typedef enum HomeState { HOME_UNFIXATED, /* home exists, but local record does not */ HOME_ABSENT, /* local record exists, but home does not */ HOME_INACTIVE, /* record and home exist, but is not logged in */ HOME_DIRTY, /* like HOME_INACTIVE, but the home directory wasn't cleanly deactivated */ HOME_FIXATING, /* generating local record from home */ HOME_FIXATING_FOR_ACTIVATION, /* fixating in order to activate soon */ HOME_FIXATING_FOR_ACQUIRE, /* fixating because Acquire() was called */ HOME_ACTIVATING, HOME_ACTIVATING_FOR_ACQUIRE, /* activating because Acquire() was called */ HOME_DEACTIVATING, HOME_ACTIVE, /* logged in right now */ HOME_LINGERING, /* not logged in anymore, but we didn't manage to deactivate (because some process keeps it busy?) but we'll keep trying */ HOME_LOCKING, HOME_LOCKED, HOME_UNLOCKING, HOME_UNLOCKING_FOR_ACQUIRE, /* unlocking because Acquire() was called */ HOME_CREATING, HOME_REMOVING, HOME_UPDATING, HOME_UPDATING_WHILE_ACTIVE, HOME_RESIZING, HOME_RESIZING_WHILE_ACTIVE, HOME_PASSWD, HOME_PASSWD_WHILE_ACTIVE, HOME_AUTHENTICATING, HOME_AUTHENTICATING_WHILE_ACTIVE, HOME_AUTHENTICATING_FOR_ACQUIRE, /* authenticating because Acquire() was called */ _HOME_STATE_MAX, _HOME_STATE_INVALID = -EINVAL, } HomeState; static inline bool HOME_STATE_IS_ACTIVE(HomeState state) { return IN_SET(state, HOME_ACTIVE, HOME_LINGERING, HOME_UPDATING_WHILE_ACTIVE, HOME_RESIZING_WHILE_ACTIVE, HOME_PASSWD_WHILE_ACTIVE, HOME_AUTHENTICATING_WHILE_ACTIVE, HOME_AUTHENTICATING_FOR_ACQUIRE); } static inline bool HOME_STATE_IS_EXECUTING_OPERATION(HomeState state) { return IN_SET(state, HOME_FIXATING, HOME_FIXATING_FOR_ACTIVATION, HOME_FIXATING_FOR_ACQUIRE, HOME_ACTIVATING, HOME_ACTIVATING_FOR_ACQUIRE, HOME_DEACTIVATING, HOME_LOCKING, HOME_UNLOCKING, HOME_UNLOCKING_FOR_ACQUIRE, HOME_CREATING, HOME_REMOVING, HOME_UPDATING, HOME_UPDATING_WHILE_ACTIVE, HOME_RESIZING, HOME_RESIZING_WHILE_ACTIVE, HOME_PASSWD, HOME_PASSWD_WHILE_ACTIVE, HOME_AUTHENTICATING, HOME_AUTHENTICATING_WHILE_ACTIVE, HOME_AUTHENTICATING_FOR_ACQUIRE); } static inline bool HOME_STATE_SHALL_PIN(HomeState state) { /* Like HOME_STATE_IS_ACTIVE() – but HOME_LINGERING is missing! */ return IN_SET(state, HOME_ACTIVE, HOME_UPDATING_WHILE_ACTIVE, HOME_RESIZING_WHILE_ACTIVE, HOME_PASSWD_WHILE_ACTIVE, HOME_AUTHENTICATING_WHILE_ACTIVE, HOME_AUTHENTICATING_FOR_ACQUIRE); } #define HOME_STATE_SHALL_REBALANCE(state) HOME_STATE_SHALL_PIN(state) static inline bool HOME_STATE_MAY_RETRY_DEACTIVATE(HomeState state) { /* Indicates when to leave the deactivate retry timer active */ return IN_SET(state, HOME_ACTIVE, HOME_LINGERING, HOME_DEACTIVATING, HOME_LOCKING, HOME_UNLOCKING, HOME_UNLOCKING_FOR_ACQUIRE, HOME_UPDATING_WHILE_ACTIVE, HOME_RESIZING_WHILE_ACTIVE, HOME_PASSWD_WHILE_ACTIVE, HOME_AUTHENTICATING_WHILE_ACTIVE, HOME_AUTHENTICATING_FOR_ACQUIRE); } struct Home { Manager *manager; char *user_name; uid_t uid; char *sysfs; /* When found via plugged in device, the sysfs path to it */ /* Note that the 'state' field is only set to a state while we are doing something (i.e. activating, * deactivating, creating, removing, and such), or when the home is an "unfixated" one. When we are * done with an operation we invalidate the state. This is hint for home_get_state() to check the * state on request as needed from the mount table and similar. */ HomeState state; int signed_locally; /* signed only by us */ UserRecord *record; pid_t worker_pid; int worker_stdout_fd; sd_event_source *worker_event_source; int worker_error_code; /* The message we are currently processing, and thus need to reply to on completion */ Operation *current_operation; /* Stores the raw, plaintext passwords, but only for short periods of time */ UserRecord *secret; /* When we create a home area and that fails, we should possibly unregister the record altogether * again, which is remembered in this boolean. */ bool unregister_on_failure; /* The reading side of a FIFO stored in /run/systemd/home/, the writing side being used for reference * counting. The references dropped to zero as soon as we see EOF. This concept exists twice: once * for clients that are fine if we suspend the home directory on system suspend, and once for clients * that are not ok with that. This allows us to determine for each home whether there are any clients * that support unsuspend. */ sd_event_source *ref_event_source_please_suspend; sd_event_source *ref_event_source_dont_suspend; /* Any pending operations we still need to execute. These are for operations we want to queue if we * can't execute them right-away. */ OrderedSet *pending_operations; /* A defer event source that processes pending acquire/release/eof events. We have a common * dispatcher that processes all three kinds of events. */ sd_event_source *pending_event_source; /* Did we send out a D-Bus notification about this entry? */ bool announced; /* Used to coalesce bus PropertiesChanged events */ sd_event_source *deferred_change_event_source; /* An fd to the top-level home directory we keep while logged in, to keep the dir busy */ int pin_fd; /* A time event used to repeatedly try to unmount home dir after use if it didn't work on first try */ sd_event_source *retry_deactivate_event_source; /* An fd that locks the backing file of LUKS home dirs with a BSD lock. */ int luks_lock_fd; /* Space metrics during rebalancing */ uint64_t rebalance_size, rebalance_usage, rebalance_free, rebalance_min, rebalance_weight, rebalance_goal; /* Whether a rebalance operation is pending */ bool rebalance_pending; }; int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret); Home *home_free(Home *h); DEFINE_TRIVIAL_CLEANUP_FUNC(Home*, home_free); int home_set_record(Home *h, UserRecord *hr); int home_save_record(Home *h); int home_unlink_record(Home *h); int home_fixate(Home *h, UserRecord *secret, sd_bus_error *error); int home_activate(Home *h, UserRecord *secret, sd_bus_error *error); int home_authenticate(Home *h, UserRecord *secret, sd_bus_error *error); int home_deactivate(Home *h, bool force, sd_bus_error *error); int home_create(Home *h, UserRecord *secret, sd_bus_error *error); int home_remove(Home *h, sd_bus_error *error); int home_update(Home *h, UserRecord *new_record, sd_bus_error *error); int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, bool automatic, sd_bus_error *error); int home_passwd(Home *h, UserRecord *new_secret, UserRecord *old_secret, sd_bus_error *error); int home_unregister(Home *h, sd_bus_error *error); int home_lock(Home *h, sd_bus_error *error); int home_unlock(Home *h, UserRecord *secret, sd_bus_error *error); HomeState home_get_state(Home *h); int home_get_disk_status(Home *h, uint64_t *ret_disk_size,uint64_t *ret_disk_usage, uint64_t *ret_disk_free, uint64_t *ret_disk_ceiling, uint64_t *ret_disk_floor, statfs_f_type_t *ret_fstype, mode_t *ret_access_mode); void home_process_notify(Home *h, char **l, int fd); int home_killall(Home *h); int home_augment_status(Home *h, UserRecordLoadFlags flags, UserRecord **ret); int home_create_fifo(Home *h, bool please_suspend); int home_schedule_operation(Home *h, Operation *o, sd_bus_error *error); int home_auto_login(Home *h, char ***ret_seats); int home_set_current_message(Home *h, sd_bus_message *m); int home_wait_for_worker(Home *h); bool home_shall_rebalance(Home *h); bool home_is_busy(Home *h); const char *home_state_to_string(HomeState state); HomeState home_state_from_string(const char *s);