diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:54:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:54:25 +0000 |
commit | 9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a (patch) | |
tree | 2efb72864cc69e174c9c5ee33efb88a5f1553b48 /modules.d/90crypt/cryptroot-ask.sh | |
parent | Initial commit. (diff) | |
download | dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.tar.xz dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.zip |
Adding upstream version 060+5.upstream/060+5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules.d/90crypt/cryptroot-ask.sh')
-rwxr-xr-x | modules.d/90crypt/cryptroot-ask.sh | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh new file mode 100755 index 0000000..b1f8df8 --- /dev/null +++ b/modules.d/90crypt/cryptroot-ask.sh @@ -0,0 +1,207 @@ +#!/bin/sh + +PATH=/usr/sbin:/usr/bin:/sbin:/bin +NEWROOT=${NEWROOT:-"/sysroot"} + +# do not ask, if we already have root +[ -f "$NEWROOT"/proc ] && exit 0 + +. /lib/dracut-lib.sh + +mkdir -p -m 0700 /run/cryptsetup + +# if device name is /dev/dm-X, convert to /dev/mapper/name +if [ "${1##/dev/dm-}" != "$1" ]; then + device="/dev/mapper/$(dmsetup info -c --noheadings -o name "$1")" +else + device="$1" +fi + +# default luksname - luks-UUID +luksname=$2 + +# is_keysource - ask for passphrase even if a rd.luks.key argument is set +is_keysource=${3:-0} + +# number of tries +numtries=${4:-10} + +# TODO: improve to support what cmdline does +if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -d -n rd_NO_CRYPTTAB; then + while read -r name dev luksfile luksoptions || [ -n "$name" ]; do + # ignore blank lines and comments + if [ -z "$name" -o "${name#\#}" != "$name" ]; then + continue + fi + + # PARTUUID used in crypttab + if [ "${dev%%=*}" = "PARTUUID" ]; then + if [ "luks-${dev##PARTUUID=}" = "$luksname" ]; then + luksname="$name" + break + fi + + # UUID used in crypttab + elif [ "${dev%%=*}" = "UUID" ]; then + if [ "luks-${dev##UUID=}" = "$luksname" ]; then + luksname="$name" + break + fi + + # ID used in crypttab + elif [ "${dev%%=*}" = "ID" ]; then + if [ "luks-${dev##ID=}" = "$luksname" ]; then + luksname="$name" + break + fi + + # path used in crypttab + else + cdev=$(readlink -f "$dev") + mdev=$(readlink -f "$device") + if [ "$cdev" = "$mdev" ]; then + luksname="$name" + break + fi + fi + done < /etc/crypttab + unset name dev +fi + +# check if destination already exists +[ -b /dev/mapper/"$luksname" ] && exit 0 + +# we already asked for this device +asked_file=/tmp/cryptroot-asked-$luksname +[ -f "$asked_file" ] && exit 0 + +# load dm_crypt if it is not already loaded +[ -d /sys/module/dm_crypt ] || modprobe dm_crypt + +. /lib/dracut-crypt-lib.sh + +# +# Open LUKS device +# + +info "luksOpen $device $luksname $luksfile $luksoptions" + +OLD_IFS="$IFS" +IFS=, +# shellcheck disable=SC2086 +set -- $luksoptions +IFS="$OLD_IFS" + +while [ $# -gt 0 ]; do + case $1 in + noauto) + # skip this + exit 0 + ;; + swap) + # skip this + exit 0 + ;; + tmp) + # skip this + exit 0 + ;; + allow-discards) + allowdiscards="--allow-discards" + ;; + header=*) + cryptsetupopts="${cryptsetupopts} --${1}" + ;; + esac + shift +done + +# parse for allow-discards +if strstr "$(cryptsetup --help)" "allow-discards"; then + if discarduuids=$(getargs "rd.luks.allow-discards"); then + discarduuids=$(str_replace "$discarduuids" 'luks-' '') + if strstr " $discarduuids " " ${luksdev##luks-}"; then + allowdiscards="--allow-discards" + fi + elif getargbool 0 rd.luks.allow-discards; then + allowdiscards="--allow-discards" + fi +fi + +if strstr "$(cryptsetup --help)" "allow-discards"; then + cryptsetupopts="$cryptsetupopts $allowdiscards" +fi + +unset allowdiscards + +# fallback to passphrase +ask_passphrase=1 + +if [ -n "$luksfile" -a "$luksfile" != "none" -a -e "$luksfile" ]; then + # shellcheck disable=SC2086 + if readkey "$luksfile" / "$device" \ + | cryptsetup -d - $cryptsetupopts luksOpen "$device" "$luksname"; then + ask_passphrase=0 + fi +elif [ "$is_keysource" -ne 0 ]; then + info "Asking for passphrase because $device is a keysource." +else + while [ -n "$(getarg rd.luks.key)" ]; do + if tmp=$(getkey /tmp/luks.keys "$device"); then + keydev="${tmp%%:*}" + keypath="${tmp#*:}" + else + if [ "$numtries" -eq 0 ]; then + warn "No key found for $device. Fallback to passphrase mode." + break + fi + sleep 1 + info "No key found for $device. Will try $numtries time(s) more later." + initqueue --unique --onetime --settled \ + --name cryptroot-ask-"$luksname" \ + "$(command -v cryptroot-ask)" "$device" "$luksname" "$is_keysource" "$((numtries - 1))" + exit 0 + fi + unset tmp + + info "Using '$keypath' on '$keydev'" + # shellcheck disable=SC2086 + readkey "$keypath" "$keydev" "$device" \ + | cryptsetup -d - $cryptsetupopts luksOpen "$device" "$luksname" \ + && ask_passphrase=0 + unset keypath keydev + break + done +fi + +if [ $ask_passphrase -ne 0 ]; then + luks_open="$(command -v cryptsetup) $cryptsetupopts luksOpen" + _timeout=$(getargs "rd.luks.timeout") + _timeout=${_timeout:-0} + ask_for_password --ply-tries 5 \ + --ply-cmd "$luks_open -T1 $device $luksname" \ + --ply-prompt "Password ($device)" \ + --tty-tries 1 \ + --tty-cmd "$luks_open -T5 -t $_timeout $device $luksname" + unset luks_open + unset _timeout +fi + +if [ "$is_keysource" -ne 0 -a "${luksname##luks-}" != "$luksname" ]; then + luks_close="$(command -v cryptsetup) close" + { + printf -- '[ -e /dev/mapper/%s ] && ' "$luksname" + printf -- '%s "%s"\n' "$luks_close" "$luksname" + } >> "$hookdir/cleanup/31-crypt-keysource.sh" + unset luks_close +fi + +unset device luksname luksfile + +# mark device as asked +: >> "$asked_file" + +need_shutdown +udevsettle + +exit 0 |