--- /dev/null
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+. /lib/dracut-lib.sh
+
+# Try to mount specified device (by path, by UUID or by label) and check
+# the path with 'test'.
+#
+# example:
+# test_dev -f LABEL="nice label" /some/file1
+test_dev() {
+ local test_op=$1; local dev="$2"; local f="$3"
+ local ret=1; local mount_point=$(mkuniqdir /mnt testdev)
+ local path
+
+ [ -n "$dev" -a -n "$*" ] || return 1
+ [ -d "$mount_point" ] || die 'Mount point does not exist!'
+
+ if mount -r "$dev" "$mount_point" >/dev/null 2>&1; then
+ test $test_op "${mount_point}/${f}"
+ ret=$?
+ umount "$mount_point"
+ fi
+
+ rmdir "$mount_point"
+
+ return $ret
+}
+
+# Get kernel name for given device. Device may be the name too (then the same
+# is returned), a symlink (full path), UUID (prefixed with "UUID=") or label
+# (prefixed with "LABEL="). If just a beginning of the UUID is specified or
+# even an empty, function prints all device names which UUIDs match - every in
+# single line.
+#
+# NOTICE: The name starts with "/dev/".
+#
+# Example:
+# devnames UUID=123
+# May print:
+# /dev/dm-1
+# /dev/sdb1
+# /dev/sdf3
+devnames() {
+ local dev="$1"; local d; local names
+
+ case "$dev" in
+ UUID=*)
+ dev="$(foreach_uuid_until '! blkid -U $___' "${dev#UUID=}")" \
+ && return 255
+ [ -z "$dev" ] && return 255
+ ;;
+ LABEL=*) dev="$(blkid -L "${dev#LABEL=}")" || return 255 ;;
+ /dev/?*) ;;
+ *) return 255 ;;
+ esac
+
+ for d in $dev; do
+ names="$names
+$(readlink -e -q "$d")" || return 255
+ done
+
+ echo "${names#
+}"
+}
+
+# match_dev devpattern dev
+#
+# Returns true if 'dev' matches 'devpattern'. Both 'devpattern' and 'dev' are
+# expanded to kernel names and then compared. If name of 'dev' is on list of
+# names of devices matching 'devpattern', the test is positive. 'dev' and
+# 'devpattern' may be anything which function 'devnames' recognizes.
+#
+# If 'devpattern' is empty or '*' then function just returns true.
+#
+# Example:
+# match_dev UUID=123 /dev/dm-1
+# Returns true if /dev/dm-1 UUID starts with "123".
+match_dev() {
+ [ -z "$1" -o "$1" = '*' ] && return 0
+ local devlist; local dev
+
+ devlist="$(devnames "$1")" || return 255
+ dev="$(devnames "$2")" || return 255
+
+ strstr "
+$devlist
+" "
+$dev
+"
+}
+
+# getkey keysfile for_dev
+#
+# Reads file <keysfile> produced by probe-keydev and looks for first line to
+# which device <for_dev> matches. The successful result is printed in format
+# "<keydev>|<keypath>". When nothing found, just false is returned.
+#
+# Example:
+# getkey /tmp/luks.keys /dev/sdb1
+# May print:
+# /dev/sdc1|/keys/some.key
+getkey() {
+ local keys_file="$1"; local for_dev="$2"
+ local luks_dev; local key_dev; local key_path
+
+ [ -z "$keys_file" -o -z "$for_dev" ] && die 'getkey: wrong usage!'
+ [ -f "$keys_file" ] || return 1
+
+ while IFS='|' read luks_dev key_dev key_path; do
+ if match_dev "$luks_dev" "$for_dev"; then
+ echo "${key_dev}|${key_path}"
+ return 0
+ fi
+ done < "$keys_file"
+
+ return 1
+}
# load dm_crypt if it is not already loaded
[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
-. /lib/dracut-lib.sh
+. /lib/dracut-crypt-lib.sh
# default luksname - luks-UUID
luksname=$2
device="$1"
fi
+# TODO: improve to support what cmdline does
if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -n rd_NO_CRYPTTAB; then
while read name dev rest; do
# ignore blank lines and comments
unset name dev rest
fi
-#
-# Search key on external devices
-#
-
-# Try to mount device specified by UUID and probe for existence of any of
-# the paths. On success return 0 and print "<uuid> <first-existing-path>",
-# otherwise return 1.
-# Function leaves mount point created.
-probe_keydev() {
- local uuid="$1"; shift; local keypaths="$*"
- local ret=1; local mount_point=/mnt/keydev
- local path
-
- [ -n "${uuid}" -a -n "${keypaths}" ] || return 1
- [ -d ${mount_point} ] || mkdir -p "${mount_point}" || return 1
-
- if mount -r -U "${uuid}" "${mount_point}" 2>/dev/null >/dev/null; then
- for path in ${keypaths}; do
- if [ -f "${mount_point}/${path}" ]; then
- echo "${uuid} ${path}"
- ret=0
- break
- fi
- done
- fi
-
- umount "${mount_point}" 2>/dev/null >/dev/null
-
- return ${ret}
-}
-
-keypaths="$(getargs rd.luks.keypath rd_LUKS_KEYPATH)"
-unset keydev_uuid keypath
-
-if [ -n "$keypaths" ]; then
- keydev_uuids="$(getargs rd.luks.keydev.uuid rd_LUKS_KEYDEV_UUID)"
- [ -n "$keydev_uuids" ] || {
- warn 'No UUID of device storing LUKS key specified.'
- warn 'It is recommended to set rd_LUKS_KEYDEV_UUID.'
- warn 'Performing scan of *all* devices accessible by UUID...'
- }
- tmp=$(foreach_uuid_until "probe_keydev \$full_uuid $keypaths" \
- $keydev_uuids) && {
- keydev_uuid="${tmp%% *}"
- keypath="${tmp#* }"
- } || {
- warn "Key for $device not found."
- }
- unset tmp keydev_uuids
-fi
-
-unset keypaths
-
#
# Open LUKS device
#
info "luksOpen $device $luksname"
-if [ -n "$keydev_uuid" ]; then
- mntp=/mnt/keydev
- mkdir -p "$mntp"
- mount -r -U "$keydev_uuid" "$mntp"
+if [ -n "$(getarg rd.luks.key)" ]; then
+ if tmp=$(getkey /tmp/luks.keys $device); then
+ keydev="${tmp%%|*}"
+ keypath="${tmp#*|}"
+ else
+ info "No key found for $device. Will try later."
+ /sbin/initqueue --unique --onetime --settled \
+ --name cryptroot-ask-$luksname \
+ /sbin/cryptroot-ask "$@"
+ exit 0
+ fi
+ unset tmp
+
+ mntp=$(mkuniqdir /mnt keydev)
+ mount -r "$keydev" "$mntp" || die 'Mounting rem. dev. failed!'
cryptsetup -d "$mntp/$keypath" luksOpen "$device" "$luksname"
umount "$mntp"
- rmdir -p "$mntp" 2>/dev/null
- unset mntp keypath keydev_uuid
+ rmdir "$mntp"
+ unset mntp keypath keydev
else
# Prompt for password with plymouth, if installed.
# Should we check if plymouthd is running?
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
inst cryptsetup
+inst rmdir
+inst readlink
inst "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask
+inst "$moddir"/probe-keydev.sh /sbin/probe-keydev
+inst_hook cmdline 10 "$moddir/parse-keydev.sh"
inst_hook cmdline 30 "$moddir/parse-crypt.sh"
inst_hook pre-pivot 30 "$moddir/crypt-cleanup.sh"
inst /etc/crypttab
+inst "$moddir/crypt-lib.sh" "/lib/dracut-crypt-lib.sh"
} > /etc/udev/rules.d/70-luks.rules
LUKS=$(getargs rd.luks.uuid rd_LUKS_UUID)
- unset settled
- [ -n "$(getargs rd.luks.keypath rd_LUKS_KEYPATH)" ] && \
- [ -z "$(getargs rd.luks.keydev.uuid rd_LUKS_KEYDEV_UUID)" ] && \
- settled='--settled'
if [ -n "$LUKS" ]; then
for luksid in $LUKS; do
{
printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", '
printf 'ENV{ID_FS_UUID}=="*%s*", ' $luksid
- printf 'RUN+="/sbin/initqueue --unique --onetime %s ' "$settled"
+ printf 'RUN+="/sbin/initqueue --unique --onetime '
printf -- '--name cryptroot-ask-%%k /sbin/cryptroot-ask '
printf '$env{DEVNAME} luks-$env{ID_FS_UUID}"\n'
} >> /etc/udev/rules.d/70-luks.rules
} >> /emergency/00-crypt.sh
done
else
- echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue' $settled \
+ echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue' \
'--unique --onetime --name cryptroot-ask-%k' \
'/sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"' \
>> /etc/udev/rules.d/70-luks.rules
--- /dev/null
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+if getargbool 1 rd.luks -n rd_NO_LUKS && \
+ [ -n "$(getarg rd.luks.key)" ]; then
+ exec 7>/etc/udev/rules.d/65-luks-keydev.rules
+ echo 'SUBSYSTEM!="block", GOTO="luks_keydev_end"' >&7
+ echo 'ACTION!="add|change", GOTO="luks_keydev_end"' >&7
+
+ for arg in $(getargs rd.luks.key); do
+ unset keypath keydev luksdev
+ splitsep : "$arg" keypath keydev luksdev
+
+ info "rd.luks.key: keypath='$keypath' keydev='$keydev' luksdev='$luksdev'"
+
+ if [ -z "$keypath" ]; then
+ warn 'keypath required!'
+ continue
+ fi
+
+ if [ -n "$keydev" ]; then
+ udevmatch "$keydev" >&7 || {
+ warn 'keydev incorrect!'
+ continue
+ }
+ printf ', ' >&7
+ fi
+
+ {
+ printf 'RUN+="/sbin/initqueue --unique --onetime '
+ printf -- '--name probe-keydev-%%k '
+ printf '/sbin/probe-keydev /dev/%%k %s %s"\n' \
+ "${keypath}" "${luksdev}"
+ } >&7
+ done
+ unset arg keypath keydev luksdev
+
+ echo 'LABEL="luks_keydev_end"' >&7
+ exec 7>&-
+fi
--- /dev/null
+#!/bin/sh
+
+. /lib/dracut-crypt-lib.sh
+
+
+real_keydev="$1"; keypath="$2"; luksdev="$3"
+
+[ -z "$real_keydev" -o -z "$keypath" ] && die 'probe-keydev: wrong usage!'
+[ -z "$luksdev" ] && luksdev='*'
+
+info "Probing $real_keydev for $keypath..."
+test_dev -f "$real_keydev" "$keypath" || exit 1
+
+info "Found $keypath on $real_keydev"
+echo "$luksdev|$real_keydev|$keypath" >> /tmp/luks.keys