#!/bin/sh

# systemd-homed live user provisioning.
#
# The presence of homectl in the live rootfs (it ships only in the
# systemd-homed package, installed when 'homed' is set at build time) selects
# this handler over fll_adduser. The home is seeded on first boot with the end
# user's own credentials, prompted through the systemd password agent (served
# by Plymouth while the splash is up, or the console otherwise).
#
# Storage is chosen from the runtime persist state:
#   plaintext persist  -> luks loopback image on @home (gives the home its own
#                         encryption layer, which @home itself lacks)
#   encrypted persist  -> directory on the already-encrypted @home (avoids a
#                         wasteful LUKS-in-LUKS double layer)
#   no persist         -> directory in the volatile COW (ephemeral live home)

HOMED_KEY_DIR=/var/lib/systemd/home
PUBKEY="${HOMED_KEY_DIR}/local.public"
PRIVKEY="${HOMED_KEY_DIR}/local.private"
HOME_IMAGE="/home/${FLL_LIVE_USER}.home"
PUBKEY_SAVED="/home/${FLL_LIVE_USER}.home.public"
PRIVKEY_SAVED="/home/${FLL_LIVE_USER}.home.private"

FLL_LIVE_USER_GROUPS=$(echo "${FLL_LIVE_USER_GROUPS}" | sed -e 's/\s/,/g')

# The initramfs bind-mounts the persistent @home over /home, and names the LUKS
# mapper 'fll-persist' when the persist partition is encrypted.
if mountpoint -q /home && [ ! -e /dev/mapper/fll-persist ]; then
	HOMECTL_STORAGE="luks"
else
	HOMECTL_STORAGE="directory"
fi

STORAGE_ARGS="--storage=${HOMECTL_STORAGE}"
HOMECTL_AUTOLOGIN="yes"
if [ "${HOMECTL_STORAGE}" = "luks" ]; then
	STORAGE_ARGS="${STORAGE_ARGS} --image-path=${HOME_IMAGE}"
	# An encrypted home cannot be auto-logged-in (it needs the password to
	# unlock); the user logs in at the display-manager greeter, which unlocks
	# it. Reflect that in the record so homed-aware greeters do not attempt it.
	HOMECTL_AUTOLOGIN="no"
fi

# HOMED_KEY_DIR persists in the persist volume's @root COW, so the signing
# keypair survives reboots of the same rootfs. We additionally save it beside
# the home image (see the first-boot branch below); the initramfs seeds the key
# dir from there when a freshly-booted rootfs has no keys yet, so chroots
# sharing one @home share the same homed user. Seeding happens in the initramfs,
# not here, because it must precede systemd-homed (which loads its keys only once
# at startup, and this service is ordered After=systemd-homed.service). Without
# the keypair homed can neither verify nor re-sign the home record, and login
# fails: activating a home is not read-only (it updates auth counters/timestamps
# and rebalances the LUKS image, then writes back a re-signed record). The
# private key cannot decrypt the LUKS home (sealed by the user's password), so
# persisting it in the clear only risks record forgery, not exposure of the
# home's contents.
mkdir -p "${HOMED_KEY_DIR}"

HOMECTL_STATE="absent"
HOMECTL=$(homectl list -EE | jq '.[] | select(.name=="'${FLL_LIVE_USER}'")')
if [ -n "${HOMECTL}" ]; then
	HOMECTL_STATE=$(echo "${HOMECTL}" | jq -r '.state')
fi

case "${HOMECTL_STATE}" in
	fixating*|unfixated|inactive)
		# A home for this user already exists and its record verifies against
		# the restored keypair. There is nothing to change, so don't update it
		# (needless re-sign churn). For an encrypted (luks) home, leave it
		# inactive: autologin is disabled (see fll_home/fll_desktop) and the
		# user unlocks it at the display-manager greeter, where pam_systemd_home
		# prompts for their password exactly once. A directory home has no
		# unlock cost, so activate it eagerly in anticipation of autologin.
		if [ "${HOMECTL_STORAGE}" != "luks" ]; then
			homectl activate "${FLL_LIVE_USER}"
		fi
		;;
	absent|*)
		# First boot: no home yet. homectl auto-generates a signing keypair
		# into the key dir, signs the record once, and embeds it in the home.
		# The password is prompted via the systemd password agent (Plymouth).
		homectl create "${FLL_LIVE_USER}" \
				--real-name="${FLL_LIVE_USER}" \
				--member-of="${FLL_LIVE_USER_GROUPS}" \
				--session-launcher="${FLL_XSESSION}" \
				--session-type="${FLL_XTYPE}" \
				--auto-login="${HOMECTL_AUTOLOGIN}" \
				${STORAGE_ARGS}
		if [ "$?" = "0" ]; then
			# Persist the keypair beside the home image so homed can re-sign and
			# manage the home on future boots (see the restore block above).
			if [ -f "${PUBKEY}" ]; then
				cp "${PUBKEY}" "${PUBKEY_SAVED}"
			fi
			if [ -f "${PRIVKEY}" ]; then
				cp "${PRIVKEY}" "${PRIVKEY_SAVED}"
				chmod 0600 "${PRIVKEY_SAVED}"
			fi
			# A directory home is auto-logged-in, so activate it eagerly. A luks
			# home cannot be auto-logged-in: activating now would prompt for the
			# password a second time, only to have the user unlock it again at
			# the greeter. Leave it inactive and let pam_systemd_home unlock it
			# there, prompting exactly once.
			if [ "${HOMECTL_STORAGE}" != "luks" ]; then
				homectl activate "${FLL_LIVE_USER}"
			fi
		fi
		;;
esac
