|
|
|
#!/bin/sh
|
|
|
|
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
|
|
|
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
|
|
|
|
|
|
|
command -v getarg >/dev/null || . /lib/dracut-lib.sh
|
|
|
|
|
|
|
|
# ask_for_password
|
|
|
|
#
|
|
|
|
# Wraps around plymouth ask-for-password and adds fallback to tty password ask
|
|
|
|
# if plymouth is not present.
|
|
|
|
#
|
|
|
|
# --cmd command
|
|
|
|
# Command to execute. Required.
|
|
|
|
# --prompt prompt
|
|
|
|
# Password prompt. Note that function already adds ':' at the end.
|
|
|
|
# Recommended.
|
|
|
|
# --tries n
|
|
|
|
# How many times repeat command on its failure. Default is 3.
|
|
|
|
# --ply-[cmd|prompt|tries]
|
|
|
|
# Command/prompt/tries specific for plymouth password ask only.
|
|
|
|
# --tty-[cmd|prompt|tries]
|
|
|
|
# Command/prompt/tries specific for tty password ask only.
|
|
|
|
# --tty-echo-off
|
|
|
|
# Turn off input echo before tty command is executed and turn on after.
|
|
|
|
# It's useful when password is read from stdin.
|
|
|
|
ask_for_password() {
|
|
|
|
local cmd; local prompt; local tries=3
|
|
|
|
local ply_cmd; local ply_prompt; local ply_tries=3
|
|
|
|
local tty_cmd; local tty_prompt; local tty_tries=3
|
|
|
|
local ret
|
|
|
|
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
case "$1" in
|
|
|
|
--cmd) ply_cmd="$2"; tty_cmd="$2" shift;;
|
|
|
|
--ply-cmd) ply_cmd="$2"; shift;;
|
|
|
|
--tty-cmd) tty_cmd="$2"; shift;;
|
|
|
|
--prompt) ply_prompt="$2"; tty_prompt="$2" shift;;
|
|
|
|
--ply-prompt) ply_prompt="$2"; shift;;
|
|
|
|
--tty-prompt) tty_prompt="$2"; shift;;
|
|
|
|
--tries) ply_tries="$2"; tty_tries="$2"; shift;;
|
|
|
|
--ply-tries) ply_tries="$2"; shift;;
|
|
|
|
--tty-tries) tty_tries="$2"; shift;;
|
|
|
|
--tty-echo-off) tty_echo_off=yes;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
{ flock -s 9;
|
|
|
|
# Prompt for password with plymouth, if installed and running.
|
|
|
|
if [ -x /bin/plymouth ] && /bin/plymouth --ping; then
|
|
|
|
/bin/plymouth ask-for-password \
|
|
|
|
--prompt "$ply_prompt" --number-of-tries=$ply_tries \
|
|
|
|
--command="$ply_cmd"
|
|
|
|
ret=$?
|
|
|
|
else
|
|
|
|
if [ "$tty_echo_off" = yes ]; then
|
|
|
|
stty_orig="$(stty -g)"
|
|
|
|
stty -echo
|
|
|
|
fi
|
|
|
|
|
|
|
|
local i=1
|
|
|
|
while [ $i -le $tty_tries ]; do
|
|
|
|
[ -n "$tty_prompt" ] && \
|
|
|
|
printf "$tty_prompt [$i/$tty_tries]:" >&2
|
|
|
|
eval "$tty_cmd" && ret=0 && break
|
|
|
|
ret=$?
|
|
|
|
i=$(($i+1))
|
|
|
|
[ -n "$tty_prompt" ] && printf '\n' >&2
|
|
|
|
done
|
|
|
|
|
|
|
|
[ "$tty_echo_off" = yes ] && stty $stty_orig
|
|
|
|
fi
|
|
|
|
} 9>/.console_lock
|
|
|
|
|
|
|
|
[ $ret -ne 0 ] && echo "Wrong password" >&2
|
|
|
|
return $ret
|
|
|
|
}
|
|
|
|
|
|
|
|
# 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
|
|
|
|
}
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
local IFS=:
|
|
|
|
while 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
|
|
|
|
}
|
|
|
|
|
|
|
|
# readkey keypath keydev device
|
|
|
|
#
|
|
|
|
# Mounts <keydev>, reads key from file <keypath>, optionally processes it (e.g.
|
|
|
|
# if encrypted with GPG) and prints to standard output which is supposed to be
|
|
|
|
# read by cryptsetup. <device> is just passed to helper function for
|
|
|
|
# informational purpose.
|
|
|
|
readkey() {
|
|
|
|
local keypath="$1"
|
|
|
|
local keydev="$2"
|
|
|
|
local device="$3"
|
|
|
|
|
|
|
|
local mntp=$(mkuniqdir /mnt keydev)
|
|
|
|
mount -r "$keydev" "$mntp" || die 'Mounting rem. dev. failed!'
|
|
|
|
|
|
|
|
case "${keypath##*.}" in
|
|
|
|
gpg)
|
|
|
|
if [ -f /lib/dracut-crypt-gpg-lib.sh ]; then
|
|
|
|
. /lib/dracut-crypt-gpg-lib.sh
|
|
|
|
gpg_decrypt "$mntp" "$keypath" "$keydev" "$device"
|
|
|
|
else
|
|
|
|
die "No GPG support to decrypt '$keypath' on '$keydev'."
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
*) cat "$mntp/$keypath" ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
umount "$mntp"
|
|
|
|
rmdir "$mntp"
|
|
|
|
}
|