agama/live/live-root/usr/bin/live-password
2026-06-02 13:38:21 +02:00

175 lines
5.3 KiB
Bash
Executable file

#!/usr/bin/sh
# Helper script which sets the root password from several sources
# - ISO file metadata
# - Kernel boot command line
# - Systemd ask password tool
# - Interactively using a dialog
# - Generates a random password as a fallback
MYDIR=$(realpath "$(dirname "$0")")
export DIALOGRC="$MYDIR/../share/live/misc/dialog.conf"
# dialog titles
BTITLE="Live System Configuration (Press Ctrl+L to refresh the screen)"
TITLE="Set Login Password"
# functions for entering the password in an interactive dialog
confirm_exit() {
# --keep-tite is not a misspelling of "title"
dialog --keep-tite --backtitle "$BTITLE" --defaultno --yesno "Are you sure you want to cancel?" 5 40
}
msg_box() {
dialog --keep-tite --backtitle "$BTITLE" --msgbox "$1" 6 30
}
ask_password() {
# check if user wants dialog password
if ! grep -q "\blive.password_dialog=1\b" /run/agama/cmdline.d/agama.conf; then
return
fi
if ! PWD1=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Password:" 8 40); then
if confirm_exit; then
return
fi
ask_password
fi
if ! PWD2=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Verify Password:" 8 40); then
if confirm_exit; then
return
fi
ask_password
fi
if [ "$PWD1" != "$PWD2" ]; then
msg_box "Passwords do not match.\nPlease try again."
ask_password
elif [ -z "$PWD1" ]; then
msg_box "Password cannot be empty.\nPlease try again."
ask_password
else
echo "$PWD1" | passwd --stdin
fi
# clear the terminal
clear
# unfortunately it also changes the cursor position, move it back to the last line
tput cup $(tput lines) 0
}
# functions for entering the password using the "systemd-ask-password" tool
ask_password_systemd() {
# check if user wants systemd password
if ! grep -q "\blive.password_systemd=1\b" /run/agama/cmdline.d/agama.conf; then
return
fi
if ! PWD1=$(systemd-ask-password --timeout=0 "Set login password: "); then
return
fi
if ! PWD2=$(systemd-ask-password --timeout=0 "Verify password: "); then
return
fi
if [ "$PWD1" != "$PWD2" ]; then
echo "Passwords do not match, please try again."
ask_password_systemd
elif [ -z "$PWD1" ]; then
echo "Password cannot be empty, please try again. To skip the password configuration press Ctrl+C."
ask_password_systemd
else
echo "$PWD1" | passwd --stdin
fi
}
# check if the root password is present in the ISO file metadata
password_from_iso() {
# get the partition where the live ISO is mounted, the real name is set by the
# config.sh script which gets the live partition label name from KIWI
PARTITION=$(blkid -L "@@LIVE_MEDIUM_LABEL@@")
if [ -z "$PARTITION" ]; then
echo "Live ISO partition not found, skipping password configuration"
return
fi
# get the parent device name for the partition (/dev/sda2 -> /dev/sda),
# for some devices just removing the trailing number does not work
DEVICE=$(lsblk --noheadings --output PKNAME "$PARTITION")
# if there is no parent device use the device itself (e.g. /dev/sr0)
if [ -z "$DEVICE" ]; then
DEVICE="$PARTITION"
else
# add the /dev/ prefix
DEVICE="/dev/$DEVICE"
fi
# run tagmedia and extract the password value
TAG=$(tagmedia "$DEVICE" | grep "^live_password = " | sed -e "s/^live_password = //")
if [ -z "$TAG" ]; then
return
fi
if PWD=$(echo "$TAG" | base64 -d); then
usermod -p "$PWD" root
else
echo "Base64 decoding of the password failed!"
fi
}
# generate a random password unless a password is already set
random_password() {
if grep -q '^root:!\*:' /etc/shadow; then
echo "Root password not set, generating a random password..."
# generate a random password, omit symbols and confusing characters to avoid
# mistakes, the password will be very likely re-typed in a different device
# so make the password easy to type (it cannot be copy pasted)
#
# TODO: check this with the security team
PASSWD=$( (base64 -w 0 < /dev/random | tr -d "+/0OolI1" | head -c 8) 2> /dev/null)
if [ -n "$PASSWD" ]; then
echo "$PASSWD" | passwd --stdin
else
# uh, the user cannot login now... =:-o
echo "Failed to generate a password"
return
fi
# display the generated password in the console
mkdir -p /run/issue.d
echo "Password for root user: \e{lightcyan}$PASSWD\e{reset}" > /run/issue.d/99-live-password.issue
# the /etc/issue or /run/issue file must exist to show the issues in console
# hint: run "agetty --show-issue" to see what will be displayed
touch /run/issue
fi
}
password_from_iso
# get the password from the kernel command line. It can contain newlines
PWD=$(grep 'live.password=' < /run/agama/cmdline.d/agama.conf | awk -F 'live.password=' '{sub(/ .*$/, "", $2); print $2}')
if [ -n "$PWD" ]; then
echo "$PWD" | passwd --stdin
fi
# get the password hash from the kernel command line. It can contain newlines
PWD=$(grep 'live.password_hash=' < /run/agama/cmdline.d/agama.conf | awk -F 'live.password_hash=' '{sub(/ .*$/, "", $2); print $2}')
if [ -n "$PWD" ]; then
usermod -p "$PWD" root
fi
# set the password interactively (using dialog)
ask_password
# set the password interactively (using systemd)
ask_password_systemd
# fallback to random password if not set
random_password