#!/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