summaryrefslogtreecommitdiffstats
path: root/modules.d/90crypt/cryptroot-ask.sh
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
commit9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a (patch)
tree2efb72864cc69e174c9c5ee33efb88a5f1553b48 /modules.d/90crypt/cryptroot-ask.sh
parentInitial commit. (diff)
downloaddracut-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-xmodules.d/90crypt/cryptroot-ask.sh207
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