mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 11:19:32 +03:00
Enable booting from nested encrypted datasets
- enable booting from nested encrypted datasets - fix plymouth boot splash passphrase entry - optimize unlock process Co-authored-by: Kash Pande <kash@tripleback.net> Co-authored-by: Matthew Thode <mthode@mthode.org> Signed-off-by: Kash Pande <kash@tripleback.net> Signed-off-by: Matthew Thode <mthode@mthode.org> Closes #7214
This commit is contained in:
parent
bf95a000c4
commit
7280d58197
@ -59,28 +59,13 @@ if import_pool "${ZFS_POOL}" ; then
|
||||
# Load keys if we can or if we need to
|
||||
if [ $(zpool list -H -o feature@encryption $(echo "${ZFS_POOL}" | awk -F\/ '{print $1}')) == 'active' ]; then
|
||||
# if the root dataset has encryption enabled
|
||||
if $(zfs list -H -o encryption "${ZFS_DATASET}" | grep -q -v off); then
|
||||
# figure out where the root dataset has its key, the keylocation should not be none
|
||||
while true; do
|
||||
if [[ $(zfs list -H -o keylocation "${ZFS_DATASET}") == 'none' ]]; then
|
||||
ZFS_DATASET=$(echo -n "${ZFS_DATASET}" | awk 'BEGIN{FS=OFS="/"}{NF--; print}')
|
||||
if [[ "${ZFS_DATASET}" == '' ]]; then
|
||||
rootok=0
|
||||
break
|
||||
fi
|
||||
else
|
||||
rootok=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ "${rootok}" -eq 0 ]]&& return 1
|
||||
ENCRYPTIONROOT=$(zfs get -H -o value encryptionroot ${ZFS_DATASET})
|
||||
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
|
||||
# decrypt them
|
||||
TRY_COUNT=5
|
||||
while [ $TRY_COUNT != 0 ]; do
|
||||
zfs load-key "${ZFS_DATASET}"
|
||||
[ $? == 0 ] && break
|
||||
((TRY_COUNT-=1))
|
||||
done
|
||||
ask_for_password \
|
||||
--tries 5 \
|
||||
--prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
|
||||
--cmd "zfs load-key ${ENCRYPTIONROOT}"
|
||||
fi
|
||||
fi
|
||||
# Let us tell the initrd to run on shutdown.
|
||||
|
@ -103,3 +103,75 @@ export_all() {
|
||||
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
# 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 type plymouth >/dev/null 2>&1 && plymouth --ping 2>/dev/null; then
|
||||
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
|
||||
}
|
||||
|
@ -33,21 +33,13 @@ fi
|
||||
|
||||
# if pool encryption is active and the zfs command understands '-o encryption'
|
||||
if [[ $(zpool list -H -o feature@encryption $(echo "${root}" | awk -F\/ '{print $1}')) == 'active' ]]; then
|
||||
# check if root dataset has encryption enabled
|
||||
if $(zfs list -H -o encryption "${root}" | grep -q -v off); then
|
||||
# figure out where the root dataset has its key, the keylocation should not be none
|
||||
while true; do
|
||||
if [[ $(zfs list -H -o keylocation "${root}") == 'none' ]]; then
|
||||
root=$(echo -n "${root}" | awk 'BEGIN{FS=OFS="/"}{NF--; print}')
|
||||
[[ "${root}" == '' ]] && exit 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
# if the root dataset has encryption enabled
|
||||
ENCRYPTIONROOT=$(zfs get -H -o value encryptionroot ${ZFS_DATASET})
|
||||
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
|
||||
# decrypt them
|
||||
TRY_COUNT=5
|
||||
while [ $TRY_COUNT != 0 ]; do
|
||||
zfs load-key "$root" <<< $(systemd-ask-password "Encrypted ZFS password for ${root}: ")
|
||||
zfs load-key "${ENCRYPTIONROOT}" <<< $(systemd-ask-password "Encrypted ZFS password for ${root}: ")
|
||||
[[ $? == 0 ]] && break
|
||||
((TRY_COUNT-=1))
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user