From 74600c13cafe0b34a3556f301e5b7919599143b4 Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Tue, 6 Aug 2024 12:21:49 +0200 Subject: [PATCH] feature/dialog: feature provides a wrapper around dialogs This feature provides a wrapper around dialogs such as password prompts. Work with dialogs becomes more challenging when plymouth is used. Other utilities can also be used to display the dialog. Signed-off-by: Alexey Gladkov --- features/dialog/README.md | 5 + features/dialog/config.mk | 3 + features/dialog/data/bin/dialog-sh-functions | 118 ++++++++++++++++++ features/dialog/rules.mk | 3 + features/luks/config.mk | 2 +- .../luks/data/lib/uevent/handlers/085-luks | 84 ++----------- 6 files changed, 138 insertions(+), 77 deletions(-) create mode 100644 features/dialog/README.md create mode 100644 features/dialog/config.mk create mode 100644 features/dialog/data/bin/dialog-sh-functions create mode 100644 features/dialog/rules.mk diff --git a/features/dialog/README.md b/features/dialog/README.md new file mode 100644 index 00000000..7cf712ad --- /dev/null +++ b/features/dialog/README.md @@ -0,0 +1,5 @@ +# Feature: dialog + +This feature provides a wrapper around dialogs such as password prompts. Work +with dialogs becomes more challenging when using bootsplash/plymouth. Other +utilities can also be used to display the dialog. diff --git a/features/dialog/config.mk b/features/dialog/config.mk new file mode 100644 index 00000000..019adb42 --- /dev/null +++ b/features/dialog/config.mk @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +DIALOG_DATADIR ?= $(FEATURESDIR)/dialog/data diff --git a/features/dialog/data/bin/dialog-sh-functions b/features/dialog/data/bin/dialog-sh-functions new file mode 100644 index 00000000..567f0e4b --- /dev/null +++ b/features/dialog/data/bin/dialog-sh-functions @@ -0,0 +1,118 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-3.0-or-later + +if [ -z "${__dialog_sh_functions-}" ]; then +__dialog_sh_functions=1 + +__dialog_plymouth_is_running= + +# shellcheck disable=SC2120 +dialog_plymouth_is_running() +{ + local recheck="${1-}" + + if [ -n "$recheck" ] || [ -z "${__dialog_plymouth_is_running-}" ]; then + type -P plymouth >/dev/null && plymouth --ping 2>/dev/null && + __dialog_plymouth_is_running=1 || + __dialog_plymouth_is_running=0 + fi + + [ "$__dialog_plymouth_is_running" = 1 ] +} + +__ask_pass_directly() +{ + local prompt tries cmd rc + + prompt="$1"; shift + tries="$1"; shift + cmd="$1"; shift + + ! dialog_plymouth_is_running || + plymouth hide-splash 2>/dev/null + + rc=2 + + while [ "$rc" != 0 ] && [ "$tries" != 0 ]; do + "$cmd" + rc="$?" + tries=$(($tries - 1)) + done + + ! dialog_plymouth_is_running || + plymouth show-splash 2>/dev/null + + return $rc +} + +__ask_pass_with_unl0kr() +{ + local prompt tries cmd rc + + prompt="$1"; shift + tries="$1"; shift + cmd="$1"; shift + + ! dialog_plymouth_is_running || + plymouth hide-splash 2>/dev/null + + rc=2 + + while [ "$rc" != 0 ] && [ "$tries" != 0 ]; do + unl0kr 2>/dev/null | "$cmd" + rc="$?" + tries=$(($tries - 1)) + done + + ! dialog_plymouth_is_running || + plymouth show-splash 2>/dev/null + + return $rc +} + +__ask_pass_with_plymouth() +{ + local prompt tries cmd + + prompt="$1"; shift + tries="$1"; shift + cmd="$1"; shift + + plymouth ask-for-password \ + --prompt "$prompt" \ + --number-of-tries="$tries" \ + --command="$cmd" +} + +dialog_ask_pass() +{ + local rc tries ask + + prompt="$1"; shift + tries="$1"; shift + + ask=__ask_pass_directly + + ! dialog_plymouth_is_running || ask=__ask_pass_with_plymouth + ! type -P unl0kr >/dev/null || ask=__ask_pass_with_unl0kr + + # To avoid issues with quoting arguments for the utility, a temporary + # wrapper can be created. + local cmdwrapper + cmdwrapper="/.initrd/dialog-ask-pass-$$.$BASHPID" + { + printf '#!/bin/bash\n' + printf 'exec ' + printf ' %q' "$@" + } > "$cmdwrapper" + chmod +x "$cmdwrapper" + + rc=0 + "$ask" "$prompt" "$tries" "$cmdwrapper" || rc="$?" + + rm -f -- "$cmdwrapper" + + return $rc +} + +fi # __dialog_sh_functions diff --git a/features/dialog/rules.mk b/features/dialog/rules.mk new file mode 100644 index 00000000..46d890b6 --- /dev/null +++ b/features/dialog/rules.mk @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +PUT_FEATURE_DIRS += $(DIALOG_DATADIR) diff --git a/features/luks/config.mk b/features/luks/config.mk index 3b1a76d7..dc69e25d 100644 --- a/features/luks/config.mk +++ b/features/luks/config.mk @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-3.0-or-later -$(call feature-requires,depmod-image devmapper modules-crypto-user-api system-glibc) +$(call feature-requires,depmod-image devmapper modules-crypto-user-api system-glibc dialog) CRYPTSETUP_BIN ?= cryptsetup LUKS_DATADIR ?= $(FEATURESDIR)/luks/data diff --git a/features/luks/data/lib/uevent/handlers/085-luks b/features/luks/data/lib/uevent/handlers/085-luks index 87d43c6f..32ec2eb9 100755 --- a/features/luks/data/lib/uevent/handlers/085-luks +++ b/features/luks/data/lib/uevent/handlers/085-luks @@ -8,6 +8,7 @@ . uevent-sh-functions . initrd-sh-functions +. dialog-sh-functions . crypttab-sh-functions PROG="${QUEUE:--}: session=${SESSION:-0}: $PROG" @@ -48,28 +49,6 @@ match_dev_in_array() { return 1 } -luks_unl0kr_ask_pass() { - [ "$#" = 2 ] || return 1 - - local cmd tries rc - - rc=2 - cmd="$1"; shift - tries="$1"; shift - - plymouth hide-splash 2>/dev/null - - while [ "$rc" != 0 ] && [ "$tries" != 0 ]; do - unl0kr 2>/dev/null | $cmd - rc=$? - tries=$(($tries - 1)) - done - - plymouth show-splash 2>/dev/null - - return $rc -} - read_pkcs11_key() { local keyid="$1" tries=${luks_tries:-3} @@ -104,25 +83,10 @@ read_pkcs11_key() { type="data" output_file="$path" flags="-l -r" - if plymouth --ping 2>/dev/null; then - if type -P unl0kr >/dev/null; then - luks_unl0kr_ask_pass pkcs11-tool-wrapper $tries - rc=$? - else - add_new_line="true"\ - plymouth ask-for-password \ - --prompt "Please enter passphrase for smart card:" \ - --number-of-tries=$tries \ - --command="pkcs11-tool-wrapper" - rc=$? - fi - else - rc=1 - while [ "$rc" != "0" ]; do - pkcs11-tool-wrapper - rc="$?" - done - fi + + dialog_ask_pass "Please enter passphrase for smart card:" "$tries" \ + "pkcs11-tool-wrapper" + rc="$?" return "$rc" } @@ -194,40 +158,6 @@ findkey() { return 2 } -cryptsetup_ask_pass() { - local rc=0 tries=${luks_tries:-3} - - { - printf 'exec cryptsetup' - printf ' %q' "$@" - } > /.initrd/cryptsetup-ask-pass - - if plymouth --ping 2>/dev/null; then - if type -P unl0kr >/dev/null; then - luks_unl0kr_ask_pass "bash /.initrd/cryptsetup-ask-pass" $tries - rc=$? - else - plymouth ask-for-password \ - --prompt "Please enter passphrase for $LUKS_ROOT:" \ - --number-of-tries=$tries \ - --command="bash /.initrd/cryptsetup-ask-pass" - rc="$?" - fi - else - rc=2 - # WARNING: Wait decrypt forever! - while [ "$rc" = 2 ] && [ "$tries" -ne 0 ]; do - bash /.initrd/cryptsetup-ask-pass - rc="$?" - tries=$(( $tries - 1 )) - done - fi - - rm -f -- /.initrd/cryptsetup-ask-pass - - return $rc -} - in_list() { local a n="$1" for a; do @@ -427,7 +357,9 @@ handler() { fi if [ "$rc" -ne 0 ]; then message "Trying to ask the user for a password." - cryptsetup_ask_pass "$@" + dialog_ask_pass \ + "Please enter passphrase for $LUKS_ROOT:" "$luks_tries" \ + "cryptsetup" "$@" rc="$?" fi fi