From a925219efb526188780ecba8d3fc8c8961405816 Mon Sep 17 00:00:00 2001 From: Jonathon Hall Date: Mon, 13 Nov 2023 13:54:37 -0500 Subject: [PATCH] oem-factory-reset: Improve prompt flow formatting flash drive Combine prompt to disconnect other devices with prompt to connect the desired device. Show block device sizes in MB/GB when selecting device so it is easier to select. file_selector now supports --show-size to include block device sizes in menu. Rework file_selector so menu options can contain spaces (use bash array) and to simplify logic. Prompt to select flash drive and LUKS percentage in OEM reset before actually taking any actions, so aborting doesn't half-reset the system. Abort OEM reset if user aborts the flash drive selection instead of looping forever. (Canceling the confirmation still loops to retry but it is possible to exit by aborting the repeated menu.) Signed-off-by: Jonathon Hall --- initrd/bin/oem-factory-reset | 101 +++++++++++++-------------- initrd/etc/gui_functions | 128 ++++++++++++++++++++++++----------- 2 files changed, 138 insertions(+), 91 deletions(-) diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset index 2960d7ee..9cd2c257 100755 --- a/initrd/bin/oem-factory-reset +++ b/initrd/bin/oem-factory-reset @@ -307,22 +307,12 @@ keytocard_subkeys_to_smartcard() { TRACE "oem-factory-reset:keytocard_subkeys_to_smartcard done" } -#Whiptail prompt to disconnect any external USB storage device -prompt_disconnect_external_USB_storage_device() { - TRACE "Under oem-factory-reset:disconnect_external_USB_storage_device" - #Whiptail $BG_COLOR_WARNING warning about removing any external USB storage device currently connected - whiptail $BG_COLOR_WARNING --title 'WARNING: Please disconnect any external USB storage device' \ - --msgbox "An external USB storage device will be WIPED next.\n\nPlease disconnect all external USB storage devices." 0 80 || - die "Error displaying warning about removing any external USB storage device currently connected" - -} - #Whiptail prompt to insert to be wiped thumb drive prompt_insert_to_be_wiped_thumb_drive() { TRACE "Under oem-factory-reset:prompt_insert_to_be_wiped_thumb_drive" #Whiptail warning about having only desired to be wiped thumb drive inserted whiptail $BG_COLOR_WARNING --title 'WARNING: Please insert the thumb drive to be wiped' \ - --msgbox "The thumb drive will be WIPED next.\n\nPlease have connected only the thumb drive to be wiped." 0 80 || + --msgbox "The thumb drive will be WIPED next.\n\nPlease connect only the thumb drive to be wiped and disconnect others." 0 80 || die "Error displaying warning about having only desired to be wiped thumb drive inserted" } @@ -412,10 +402,13 @@ export_public_key_to_thumbdrive_public_partition() { TRACE "oem-factory-reset:export_public_key_to_thumbdrive_public_partition done" } -#Wipe a thumb drive and export master key and subkeys to it -wipe_thumb_drive_and_copy_gpg_key_material() { +# Select thumb drive and LUKS container size for GPG key export +# Sets variables containing selections: +# - thumb_drive +# - thumb_drive_luks_percent +select_thumb_drive_for_key_material() { TRACE "Under oem-factory-reset:wipe_thumb_drive_and_copy_gpg_key_material" - prompt_disconnect_external_USB_storage_device + #enable usb storage enable_usb enable_usb_storage @@ -426,41 +419,32 @@ wipe_thumb_drive_and_copy_gpg_key_material() { prompt_insert_to_be_wiped_thumb_drive #list usb storage devices list_usb_storage disks >/tmp/usb_disk_list - if [ $(cat /tmp/usb_disk_list | wc -l) -gt 0 ]; then - file_selector "/tmp/usb_disk_list" "Select USB device to partition" - if [ "$FILE" == "" ]; then - #No USB storage device selected - warn "No USB storage device selected!" - else - # Obtain size of thumb drive to be wiped with fdisk - disk_size_bytes="$(blockdev --getsize64 "$FILE")" - #Convert disk size to GB - thumb_drive_size_mb=$((disk_size_bytes / 1024 / 1024)) - thumb_drive_size_gb=$((thumb_drive_size_mb / 1024 )) - - #if thumb_drive_size_gb is 0, then disk size is less than 1GB - thumb_drive_size_message="" - if [ "$thumb_drive_size_gb" -eq 0 ]; then - thumb_drive_size_message="$thumb_drive_size_mb MB" - if [ "$thumb_drive_size_mb" -lt 128 ]; then - warn "Thumb drive size is less than 128MB!" - warn "LUKS container needs to be at least 8mb!" - warn "If the next operation fails, try with a bigger thumb drive" - fi - else - thumb_drive_size_message="$thumb_drive_size_gb GB" - fi - - # confirm with user size of thumb drive to be wiped - whiptail --title "Confirm thumb drive to be wiped" --yesno "Are you sure you want to wipe the following thumb drive?\n\n$FILE\n\nSize: $thumb_drive_size_message" 0 0 - if [ $? -ne 0 ]; then - warn "Thumb drive wipe aborted by user!" - continue - fi - - #User chose and confirmed a thumb drive and its size to be wiped - thumb_drive=$FILE + # Abort if: + # - no disks found (prevent file_selector's nonsense prompt) + # - file_selector fails for any reason + # - user aborts (file_selector succeeds but FILE is empty) + if [ $(cat /tmp/usb_disk_list | wc -l) -gt 0 ] && + file_selector --show-size "/tmp/usb_disk_list" "Select USB device to partition" && + [ -n "$FILE" ]; then + # Obtain size of thumb drive to be wiped with fdisk + disk_size_bytes="$(blockdev --getsize64 "$FILE")" + if [ "$disk_size_bytes" -lt "$((128*1024*1024))" ]; then + warn "Thumb drive size is less than 128MB!" + warn "LUKS container needs to be at least 8MB!" + warn "If the next operation fails, try with a bigger thumb drive" fi + + thumb_drive_size_message="$(display_size "$disk_size_bytes")" + # confirm with user size of thumb drive to be wiped + whiptail --title "Confirm thumb drive to be wiped" --yesno \ + "Are you sure you want to wipe the following thumb drive?\n\n$FILE\n\nSize: $thumb_drive_size_message" 0 0 + if [ $? -ne 0 ]; then + warn "Thumb drive wipe aborted by user!" + continue + fi + + #User chose and confirmed a thumb drive and its size to be wiped + thumb_drive=$FILE else #No USB storage device detected warn "No USB storage device detected! Aborting OEM Factory Reset / Re-Ownership" @@ -470,8 +454,21 @@ wipe_thumb_drive_and_copy_gpg_key_material() { done select_luks_container_size_percent + thumb_drive_luks_percent="$(cat /tmp/luks_container_size_percent)" +} + +#Wipe a thumb drive and export master key and subkeys to it +# $1 - thumb drive block device +# $2 - LUKS container percentage [1-99] +wipe_thumb_drive_and_copy_gpg_key_material() { + TRACE "Under oem-factory-reset:wipe_thumb_drive_and_copy_gpg_key_material" + + local thumb_drive thumb_drive_luks_percent + thumb_drive="$1" + thumb_drive_luks_percent="$2" + #Wipe thumb drive with a LUKS container of size $(cat /tmp/luks_container_size_percent) - prepare_thumb_drive --device "$thumb_drive" --percentage "$(cat /tmp/luks_container_size_percent)" --pass "${ADMIN_PIN}" + prepare_thumb_drive --device "$thumb_drive" --percentage "$thumb_drive_luks_percent" --pass "${ADMIN_PIN}" #Export master key and subkeys to thumb drive first partition export_master_key_subkeys_and_revocation_key_to_private_LUKS_container --mode rw --device "$thumb_drive"1 --mountpoint /media --pass "${ADMIN_PIN}" #Export public key to thumb drive's public partition @@ -1068,6 +1065,10 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then } done fi + + if [ "$GPG_GEN_KEY_IN_MEMORY" = "y" ]; then + select_thumb_drive_for_key_material + fi fi # If nothing is stored in custom variables, we set them to their defaults @@ -1184,7 +1185,7 @@ if [ "$GPG_GEN_KEY_IN_MEMORY" = "y" ]; then else die "Unsupported GPG_ALGO: $GPG_ALGO" fi - wipe_thumb_drive_and_copy_gpg_key_material + wipe_thumb_drive_and_copy_gpg_key_material "$thumb_drive" "$thumb_drive_luks_percent" set_user_config "CONFIG_HAVE_GPG_KEY_BACKUP" "y" if [ "$GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD" = "y" ]; then keytocard_subkeys_to_smartcard diff --git a/initrd/etc/gui_functions b/initrd/etc/gui_functions index ac9fbcfb..86e09916 100755 --- a/initrd/etc/gui_functions +++ b/initrd/etc/gui_functions @@ -34,54 +34,100 @@ mount_usb() fi } +# Create display text for a size in bytes in either MB or GB, unit selected +# automatically, rounded to nearest +display_size() { + local size_bytes unit_divisor unit_symbol + size_bytes="$1" + + # If it's less than 1 GB, display MB + if [ "$((size_bytes))" -lt "$((1024*1024*1024))" ]; then + unit_divisor=$((1024*1024)) + unit_symbol="MB" + else + unit_divisor=$((1024*1024*1024)) + unit_symbol="GB" + fi + + # Divide by the unit divisor and round to nearest + echo "$(( (size_bytes + unit_divisor/2) / unit_divisor )) $unit_symbol" +} + +# Create display text for the size of a block device using MB or GB, rounded to +# nearest +display_block_device_size() { + local block_dev disk_size_bytes + block_dev="$1" + + # Obtain size of thumb drive to be wiped with fdisk + if ! disk_size_bytes="$(blockdev --getsize64 "$block_dev")"; then + exit 1 + fi + + display_size "$disk_size_bytes" +} + +# Display a menu to select a file from a list. Pass the name of a file +# containing the list. +# --show-size: Append sizes of files listed. Currently only supports block +# devices. +# $1: Name of file listing files that can be chosen (one per line) +# $2: Optional prompt message +# $3: Optional prompt title +# +# Success: Sets FILE with the selected file +# User aborted: Exits successfully with FILE empty +# No entries in list: Displays error and exits unsuccessfully file_selector() { - TRACE "under gui_functions:file_selector" - FILE="" - FILE_LIST=$1 - MENU_MSG=${2:-"Choose the file"} - MENU_TITLE=${3:-"Select your File"} + TRACE "under gui_functions:file_selector" - # create file menu options - if [ `cat "$FILE_LIST" | wc -l` -gt 0 ]; then - option="" - while [ -z "$option" ] - do - MENU_OPTIONS="" - n=0 - while read option - do - n=`expr $n + 1` - option=$(echo $option | tr " " "_") - MENU_OPTIONS="$MENU_OPTIONS $n ${option}" - done < $FILE_LIST + local FILE_LIST MENU_MSG MENU_TITLE CHOICE_ARGS SHOW_SIZE OPTION_SIZE option_index - MENU_OPTIONS="$MENU_OPTIONS a Abort" - whiptail --title "${MENU_TITLE}" \ - --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail || die "Aborting" + FILE="" - option_index=$(cat /tmp/whiptail) + if [ "$1" = "--show-size" ]; then + SHOW_SIZE=y + shift + fi - if [ "$option_index" = "a" ]; then - option="a" - return - fi + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} + MENU_TITLE=${3:-"Select your File"} - option=`head -n $option_index $FILE_LIST | tail -1` - if [ "$option" == "a" ]; then - return - fi - done - if [ -n "$option" ]; then - FILE=$option - fi - else - whiptail $BG_COLOR_ERROR --title 'ERROR: No Files Found' \ - --msgbox "No Files found matching the pattern. Aborting." 0 80 - exit 1 - fi + CHOICE_ARGS=() + n=0 + while read option; do + n="$((++n))" + + if [ "$SHOW_SIZE" = "y" ] && OPTION_SIZE="$(display_block_device_size "$option")"; then + option="$option - $OPTION_SIZE" + fi + CHOICE_ARGS+=("$n" "$option") + done < "$FILE_LIST" + + if [ "${#CHOICE_ARGS[@]}" -eq 0 ]; then + whiptail $BG_COLOR_ERROR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 0 80 + exit 1 + fi + + CHOICE_ARGS+=(a Abort) + + # create file menu options + option_index="" + while [ -z "$option_index" ]; do + whiptail --title "${MENU_TITLE}" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- "${CHOICE_ARGS[@]}" \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" != "a" ]; then + FILE="$(head -n "$option_index" "$FILE_LIST" | tail -1)" + fi + done } show_system_info()