From 43941ec75753960d27d9d3e639be736a2a38af3e Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 6 Dec 2019 10:11:18 -0600 Subject: [PATCH 1/4] drop dual boot support This hasn't been used in a very long time and is just aging code --- casper/scripts/99dell_bootstrap | 5 ---- casper/seeds/dual.seed | 51 --------------------------------- debian/dell-recovery.templates | 12 +------- late/scripts/FAIL-SCRIPT | 7 ----- late/scripts/SUCCESS-SCRIPT | 6 ---- ubiquity/dell-bootstrap.py | 24 ---------------- 6 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 casper/seeds/dual.seed diff --git a/casper/scripts/99dell_bootstrap b/casper/scripts/99dell_bootstrap index 09af940e..909b38ae 100755 --- a/casper/scripts/99dell_bootstrap +++ b/casper/scripts/99dell_bootstrap @@ -109,11 +109,6 @@ done # Now load all the defaults included in all installs casper-set-selections "/root/usr/share/dell/casper/seeds/ubuntu.seed" -# If we have a dual boot option, load the dual boot preseed -if db_get dell-recovery/dual_boot && [ "$RET" = true ]; then - casper-set-selections "/root/usr/share/dell/casper/seeds/dual.seed" -fi - # Lastly, reload the override / configurations preseeds so that it is allowed to override stuff from ubuntu.seed and dual.seed for seed in dell-recovery gfx wlan; do if [ -e /root/cdrom/preseed/$seed.seed ]; then diff --git a/casper/seeds/dual.seed b/casper/seeds/dual.seed deleted file mode 100644 index 4334f782..00000000 --- a/casper/seeds/dual.seed +++ /dev/null @@ -1,51 +0,0 @@ -# -# -# -# Dell Ubuntu preseed file used for dual boot -# * Last updated for Ubuntu 11.04 -# -# Copyright 2008-2011 Dell Inc. -# Mario Limonciello -# Hatim Amro -# Michael E Brown -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. - -# Provide an expert recipe because the default recipe will make all -# logical partitions - d-i partman-auto/expert_recipe string \ - \ - dell :: \ - 100 150 200 free \ - $iflabel{ gpt } \ - $reusemethod{ } \ - method{ efi } \ - format{ } . \ - \ - 500 10000 4000000 ext4 \ - $primary{ } \ - method{ format } \ - format{ } \ - use_filesystem{ } \ - filesystem{ ext4 } \ - mountpoint{ / } . - -### Dell Factory Process specific -#These control what partitions are deleted initially - dell-recovery dell-recovery/os_partition string DUALSYS - -#This controls whether dell-recovery, dell-oobe, and dell-eula get installed - dell-recovery dell-recovery/dual_boot boolean true diff --git a/debian/dell-recovery.templates b/debian/dell-recovery.templates index 6a70047c..bf2e37ce 100644 --- a/debian/dell-recovery.templates +++ b/debian/dell-recovery.templates @@ -3,16 +3,6 @@ Type: boolean Default: false Description: for internal use; determines if wyse mode is on. -Template: dell-recovery/dual_boot -Type: boolean -Default: false -Description: for internal use; determines if EFI enabled dual boot enabled - -Template: dell-recovery/os_partition -Type: string -Default: -Description: for internal use; determines the label of the OS partition to remove - Template: dell-recovery/destination Type: string Default: none @@ -21,7 +11,7 @@ Description: for internal use; determines whether to generate recovery media Template: dell-recovery/recovery_type Type: string Default: dynamic -Description: for internal use;determines whether to offer the bootstrap +Description: for internal use;determines whether to offer the bootstrap ubiquity plugin to the user. valid: [dynamic, factory, usb, dvd] Template: dell-recovery/build_start diff --git a/late/scripts/FAIL-SCRIPT b/late/scripts/FAIL-SCRIPT index b8d14b18..aa3463c7 100755 --- a/late/scripts/FAIL-SCRIPT +++ b/late/scripts/FAIL-SCRIPT @@ -49,13 +49,6 @@ if [ "$BOOTDEV" = "$TARGETDEV" ]; then mount -o remount,rw $RP fistlog="/tmp/fist.err" - if [ -f $RP/SDR ]; then - dualos=`sed -n '/DUALOS/=' $RP/SDR` - if [ $dualos ]; then - fistlog="/tmp/DUALOS_FIST.ERR" - fi - fi - IFHALT "Resetting grub fail state" [ -s $RP/factory/grubenv ] || rm -f $RP/factory/grubenv grub-editenv $RP/factory/grubenv set recordfail=1 diff --git a/late/scripts/SUCCESS-SCRIPT b/late/scripts/SUCCESS-SCRIPT index f266d1ee..a73a55ec 100755 --- a/late/scripts/SUCCESS-SCRIPT +++ b/late/scripts/SUCCESS-SCRIPT @@ -70,12 +70,6 @@ if [ "$BOOTDEV" = "$TARGETDEV" ]; then fi fistlog="/tmp/fist.log" - if [ -f $RP/SDR ]; then - dualos=`sed -n '/DUALOS/=' $RP/SDR` - if [ $dualos ]; then - fistlog="/tmp/DUALOS_FIST.LOG" - fi - fi IFHALT "Clean up FI Env..." rm -rf $RP/scripts/chroot-scripts/os-post/95-set_UTC_TZ.sh diff --git a/ubiquity/dell-bootstrap.py b/ubiquity/dell-bootstrap.py index 27337342..dede939e 100644 --- a/ubiquity/dell-bootstrap.py +++ b/ubiquity/dell-bootstrap.py @@ -364,15 +364,6 @@ def remove_extra_partitions(self): #on small disks or big mem, don't look for extended or delete swap. os_part = EFI_OS_PARTITION - # check dual boot or not - try: - if self.db.get('dell-recovery/dual_boot') == 'true': - ##dual boot get the partition number of OS and swap - os_label = self.db.get('dell-recovery/os_partition') - os_part = self.dual_partition_num(os_label) - except debconf.DebconfError as err: - self.log(str(err)) - #remove extras if os_part.isdigit(): remove = misc.execute_root('parted', '-s', self.device, 'rm', os_part) @@ -382,21 +373,6 @@ def remove_extra_partitions(self): if refresh is False: self.log("Error updating partition %s for kernel device %s (this may be normal)'" % (os_part, self.device)) - def dual_partition_num(self,label): - #remove UBUNTU patition for dual boot - ##OS num - os_part = '' - digits = re.compile('\d+') - try: - os_path = magic.fetch_output(['readlink','/dev/disk/by-label/'+label]).split('\n') - except Exception as err: - # compatible with DUALSYS partition label when boot from hdd - os_path = magic.fetch_output(['readlink','/dev/disk/by-label/UBUNTU']).split('\n') - if not os_path: - self.log('os_path command is executed failed, the error is %s'%str(err)) - os_part = digits.search(os_path[0].split('/')[-1]).group() - - return os_part def explode_sdr(self): '''Explodes all content explicitly defined in an SDR From 51ec6c13c00c2cb9d8da0f90398f5a4b7aa9c7a2 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 9 Dec 2019 11:23:07 -0600 Subject: [PATCH 2/4] Try to build initramfs more like mkinitramfs --- Dell/recovery_common.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Dell/recovery_common.py b/Dell/recovery_common.py index 0e92d8a6..a73a9f46 100644 --- a/Dell/recovery_common.py +++ b/Dell/recovery_common.py @@ -560,17 +560,20 @@ def create_new_uuid(old_initrd_directory, old_casper_directory, continue chain0 = subprocess.Popen(['find'], cwd=root, stdout=subprocess.PIPE) - chain1 = subprocess.Popen(['cpio', '--quiet', '-o', '-H', 'newc'], - cwd=root, stdin=chain0.stdout, + chain1 = subprocess.Popen(['sort'], cwd=root, + stdin=chain0.stdout, + stdout=subprocess.PIPE) + chain2 = subprocess.Popen(['cpio', '-R', '0:0', '--reproducible', '--quiet', '-o', '-H', 'newc'], + cwd=root, stdin=chain1.stdout, stdout=subprocess.PIPE) with open(new_initrd_file, 'ab') as initrd_fd: if component == 'main': - chain2 = subprocess.Popen(compress_command, - stdin=chain1.stdout, - stdout=subprocess.PIPE) - initrd_fd.write(chain2.communicate()[0]) + chain3 = subprocess.Popen(compress_command, + stdin=chain2.stdout, + stdout=subprocess.PIPE) + initrd_fd.write(chain3.communicate()[0]) else: - initrd_fd.write(chain1.communicate()[0]) + initrd_fd.write(chain2.communicate()[0]) walk_cleanup(tmpdir) From a9ffa17cf1d64a1a2a2a8b686413a8b9535b85d3 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 9 Dec 2019 11:31:12 -0600 Subject: [PATCH 3/4] Add recommends for the TPM packages needed for clevis to work well --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 95601b1b..89f8f3b6 100644 --- a/debian/control +++ b/debian/control @@ -34,7 +34,8 @@ Depends: ${python3:Depends}, uuid-runtime, Replaces: dell-artwork, dell-oobe Conflicts: dell-oobe -Recommends: cryptsetup, +Recommends: clevis-tpm2, + cryptsetup, cryptsetup-bin, dvd+rw-tools, isolinux, From d6be4f283209f81a7b43581f3b20e4c77d8689ae Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 6 Dec 2019 10:13:21 -0600 Subject: [PATCH 4/4] Add support for enabling full disk encryption --- casper/scripts/99dell_bootstrap | 7 ++ casper/seeds/ubuntu.seed | 2 +- debian/dell-recovery.templates | 5 + late/chroot_scripts/99-encrypt.sh | 35 +++++++ late/scripts/SUCCESS-SCRIPT | 6 +- late/scripts/chroot.sh | 3 +- late/scripts/oem_config.sh | 8 ++ late/scripts/simple_partitioner.sh | 95 +++++++++++++++++ late/scripts/update_tpm_policy.sh | 67 ++++++++++++ ubiquity/dell-bootstrap.py | 130 ++++++++++++++++++++--- ubiquity/stepDellBootstrap.ui | 161 +++++++++++++++++++++-------- 11 files changed, 455 insertions(+), 64 deletions(-) create mode 100755 late/chroot_scripts/99-encrypt.sh create mode 100755 late/scripts/simple_partitioner.sh create mode 100755 late/scripts/update_tpm_policy.sh diff --git a/casper/scripts/99dell_bootstrap b/casper/scripts/99dell_bootstrap index 909b38ae..52277f3b 100755 --- a/casper/scripts/99dell_bootstrap +++ b/casper/scripts/99dell_bootstrap @@ -106,6 +106,13 @@ for seed in dell-recovery gfx wlan; do fi done +#HACK: make ubiquity think partitioning is done +#if db_get dell-recovery/encryption && [ "$RET" = true ]; then +# sed -i "s,self.partitioned = False,self.partitioned = True," /root/usr/lib/ubiquity/ubiquity/frontend/gtk_ui.py +# rm -f /root/usr/lib/ubiquity/plugins/ubi-partman.py +#fi +#alternatively include https://code.launchpad.net/~ubuntu-installer/ubiquity/+git/ubiquity/+merge/376777 + # Now load all the defaults included in all installs casper-set-selections "/root/usr/share/dell/casper/seeds/ubuntu.seed" diff --git a/casper/seeds/ubuntu.seed b/casper/seeds/ubuntu.seed index ce23eac3..62877eb0 100644 --- a/casper/seeds/ubuntu.seed +++ b/casper/seeds/ubuntu.seed @@ -87,7 +87,7 @@ method{ efi } \ format{ } . \ \ - 500 10000 4000000 ext4 \ + 500 10000 -1 ext4 \ $primary{ } \ method{ format } \ format{ } \ diff --git a/debian/dell-recovery.templates b/debian/dell-recovery.templates index bf2e37ce..e2f0eac2 100644 --- a/debian/dell-recovery.templates +++ b/debian/dell-recovery.templates @@ -14,6 +14,11 @@ Default: dynamic Description: for internal use;determines whether to offer the bootstrap ubiquity plugin to the user. valid: [dynamic, factory, usb, dvd] +Template: dell-recovery/encryption +Type: boolean +Default: false +Description: for internal use; determines whether to encrypt the disk + Template: dell-recovery/build_start Type: text _Description: Building Dell Recovery Media... diff --git a/late/chroot_scripts/99-encrypt.sh b/late/chroot_scripts/99-encrypt.sh new file mode 100755 index 00000000..930970c5 --- /dev/null +++ b/late/chroot_scripts/99-encrypt.sh @@ -0,0 +1,35 @@ +#!/bin/bash -ex +# +# <99-encrypt.sh> +# +# Binds FDE key to the TPM +# +# Copyright 2020 Dell Inc. +# Mario Limonciello +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +# Detect if user selected encryption +if [ -f /etc/default/dell-recovery ]; then + . /etc/default/dell-recovery +fi +if [ "$ENCRYPTION" = "true" ]; then + # bind to the TPM (no PCR's; will be added later) + clevis luks bind -d /dev/dell_lvm/rootfs -k /tmp/key tpm2 '{}' + + #remove our installer key + cryptsetup luksRemoveKey /dev/dell_lvm/rootfs --key-file /tmp/key +fi \ No newline at end of file diff --git a/late/scripts/SUCCESS-SCRIPT b/late/scripts/SUCCESS-SCRIPT index a73a55ec..0c0d52b6 100755 --- a/late/scripts/SUCCESS-SCRIPT +++ b/late/scripts/SUCCESS-SCRIPT @@ -52,7 +52,11 @@ if [ -f "$TARGET/etc/init/network-manager.conf.orig" ]; then mv $TARGET/etc/init/network-manager.conf.orig $TARGET/etc/init/network-manager.conf fi -if [ "$BOOTDEV" = "$TARGETDEV" ]; then +# Dell Recovery initiated encryption can not be selected if user does custom partitions +if [ -f $TARGET/etc/default/dell-recovery ]; then + . $TARGET/etc/default/dell-recovery +fi +if [ "$ENCRYPTION" = "true" ] || [ "$BOOTDEV" = "$TARGETDEV" ]; then if [ -d "/isodevice" ]; then RP="/isodevice" else diff --git a/late/scripts/chroot.sh b/late/scripts/chroot.sh index f23ac4e6..a3ecd0d0 100755 --- a/late/scripts/chroot.sh +++ b/late/scripts/chroot.sh @@ -164,8 +164,7 @@ fi #check the checked_uninstalled file is empty or not, we will turn to FAIL-SCRIPT if it is not empty [ ! -s "$TARGET/var/lib/ubiquity/dell_uninstalled" ] - # reset traps, as we are now exiting normally trap - TERM INT HUP EXIT QUIT -. /usr/share/dell/scripts/SUCCESS-SCRIPT $BOOT_DEV $BOOT_PART_NUM +. /usr/share/dell/scripts/SUCCESS-SCRIPT diff --git a/late/scripts/oem_config.sh b/late/scripts/oem_config.sh index 98e966d9..126b8880 100755 --- a/late/scripts/oem_config.sh +++ b/late/scripts/oem_config.sh @@ -70,6 +70,14 @@ elif [ "$1" = "late" ]; then done #if this was installed to work around secure boot, clean it up rm -f /boot/efi/EFI/ubuntu/MokSBStateSet.efi + + #Update encryption policy to match secure boot status + if [ -f /etc/default/dell-recovery ]; then + . /etc/default/dell-recovery + fi + if [ "$ENCRYPTION" = "true" ]; then + /usr/share/dell/scripts/update_tpm_policy.sh -d /dev/dell_lvm/rootfs + fi else echo "Unknown arguments $1 $2" fi diff --git a/late/scripts/simple_partitioner.sh b/late/scripts/simple_partitioner.sh new file mode 100755 index 00000000..8a7c72b3 --- /dev/null +++ b/late/scripts/simple_partitioner.sh @@ -0,0 +1,95 @@ +#!/bin/bash -ex +# +# +# +# Creates a simple partition layout +# +# Copyright 2020 Dell Inc. +# Mario Limonciello +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +DEVICE=$1 +ESP_PART=$2 +OS_PART=$3 +GROUP=dell_lvm + +#create new ones in free space +sfdisk --force -a ${DEVICE} < /tmp/key +cryptsetup luksFormat /dev/${GROUP}/rootfs < /tmp/key +LUKS_UUID=`blkid /dev/${GROUP}/rootfs -s UUID -o value` +cryptsetup luksOpen /dev/${GROUP}/rootfs decrypted_rootfs --key-file /tmp/key +mkfs.ext4 /dev/mapper/decrypted_rootfs +DECRYPTED_UUID=`blkid /dev/mapper/decrypted_rootfs -s UUID -o value` + +#mount the disks +mkdir -p /target +mount /dev/mapper/decrypted_rootfs /target +mkdir -p /target/boot +mount /dev/${GROUP}/boot /target/boot +mkdir -p /target/boot/efi +mount ${DEVICE}${ESP_PART} /target/boot/efi +ESP_UUID=`blkid ${DEVICE}${ESP_PART} -s UUID -o value` + +#create swapfile +available=$(df -P /target/ | sed 1d | while read fs size used available usep mounted on; do + echo $available +done) +size=$((available/100)) +size=$((size*5)) +limit=$((1024*2048)) +if [ $size -gt $limit ] +then + size=$limit +fi +fallocate -l ${size}KiB /target/swapfile +dd if=/dev/zero of=/target/swapfile bs=1024 count=$size +chmod 600 /target/swapfile +mkswap /target/swapfile +swapon /target/swapfile + +#write out fstab +mkdir -p /target/etc +cat > /target/etc/fstab << EOF +UUID=$DECRYPTED_UUID / ext4 errors=remount-ro 0 1 +UUID=$BOOT_UUID /boot ext4 errors=remount-ro 0 1 +UUID=$ESP_UUID /boot/efi vfat umask=0077 0 1 +EOF +cat > /target/etc/crypttab << EOF +decrypted_rootfs UUID=$LUKS_UUID none luks,initramfs +EOF + +#copy key into target (will be discarded later) +mkdir -p /target/tmp +cp /tmp/key /target/tmp/key diff --git a/late/scripts/update_tpm_policy.sh b/late/scripts/update_tpm_policy.sh new file mode 100755 index 00000000..9317c15c --- /dev/null +++ b/late/scripts/update_tpm_policy.sh @@ -0,0 +1,67 @@ +#!/bin/bash -e +# +# Script to read current clevis passphrase stored to TPM with no PCR policy +# and update it to a new clevis passphrase stored to TPM with policy tied to +# secure boot state. +# +# intended use is OOBE. Slot numbers are hardcoded from coming into OOBE. +# + +usage() { + exec >&2 + echo + echo "Usage: $0 -d DEV" + echo + echo "Updates TPM policy to use PCR7": + echo + echo " -d DEV The bound LUKS device" + echo + exit 2 +} + +luks2_jwe() { + # jose jwe fmt -c outputs extra \n, so clean it up + cryptsetup token export "$@" \ + | jose fmt -j- -Og jwe -o- \ + | jose jwe fmt -i- -c \ + | tr -d '\n' + + local rc + for rc in "${PIPESTATUS[@]}"; do + [ $rc -eq 0 ] || return $rc + done + return 0 +} + +get_current_passphrase() { +cryptsetup luksDump "$1" | sed -rn 's|^\s+([0-9]+): clevis|\1|p' | +while read -r id; do + jwe="$(luks2_jwe --token-id "$id" "$1")" || continue + + if pt="$(echo -n "$jwe" | clevis decrypt)"; then + echo -n "$pt" + break + fi +done +} + +while getopts "d:" o; do + case "$o" in + d) DEV="$OPTARG";; + *) usage;; + esac +done + +if [ -z "$DEV" ]; then + echo "Did not specify a device!" >&2 + usage +fi + +if ! cryptsetup isLuks "$DEV"; then + echo "$DEV is not a LUKS device!" >&2 + exit 1 +fi + +CURRENT=$(get_current_passphrase $DEV) +echo $CURRENT | clevis luks bind -d $DEV -s 2 tpm2 '{"pcr_bank":"sha256", "pcr_ids":"7"}' -k - +clevis luks unbind -d $DEV -s 1 -f diff --git a/ubiquity/dell-bootstrap.py b/ubiquity/dell-bootstrap.py index dede939e..7f20d7a9 100644 --- a/ubiquity/dell-bootstrap.py +++ b/ubiquity/dell-bootstrap.py @@ -54,10 +54,12 @@ EFI_ESP_PARTITION = '1' EFI_RP_PARTITION = '2' EFI_OS_PARTITION = '3' -EFI_SWAP_PARTITION = '4' +EFI_BOOT_PARTITION = '4' #Continually Reused ubiquity templates -RECOVERY_TYPE_QUESTION = 'dell-recovery/recovery_type' +RECOVERY_TYPE_QUESTION = 'dell-recovery/recovery_type' +ENCRYPTION_QUESTION = 'dell-recovery/encryption' +SKIP_PARTITION_QUESTION = 'ubiquity/skip_partitioning' no_options = GLib.Variant('a{sv}', {}) @@ -70,6 +72,9 @@ def __init__(self, controller, *args, **kwargs): self.controller = controller PluginUI.__init__(self, controller, *args, **kwargs) + def get_encryption(self): + return False + def get_type(self): '''For the noninteractive frontend, get_type always returns an empty str This is because the noninteractive frontend always runs in "factory" @@ -137,6 +142,9 @@ def __init__(self, controller, *args, **kwargs): self.restart_box = builder.get_object('restart_box') self.err_dialog = builder.get_object('err_dialog') self.log_dialog = builder.get_object('log_dialog') + self.encryption = builder.get_object('encrypt_checkbox') + self.encryption_box = builder.get_object('encryption_box') + self.encyption_supported = self.check_encryption_supported() #advanced page widgets icon = builder.get_object('dell_image') @@ -150,10 +158,29 @@ def __init__(self, controller, *args, **kwargs): builder.get_object('error_box').show() PluginUI.__init__(self, controller, *args, **kwargs) + def check_encryption_supported(self): + #no TPM on the machine + if not os.path.exists('/dev/tpm0'): + return False + import apt.cache + cache = apt.cache.Cache() + #check what's in the apt cache (or installed) + try: + clevis_version = cache['clevis-tpm2'].versions[0].version + if clevis_version < '12': + return False + tpm2_tools_version = cache['tpm2-tools'].versions[0].version + if tpm2_tools_version < '4': + return False + except KeyError: + return False + return True + def plugin_get_current_page(self): """Called when ubiquity tries to realize this page. * Disable the progress bar * Check whether we are on genuine hardware + * Determine whether to offer encryption """ #are we real? if not (self.genuine and 'UBIQUITY_AUTOMATIC' in os.environ): @@ -161,7 +188,10 @@ def plugin_get_current_page(self): self.automated_recovery_box.hide() self.automated_recovery.set_sensitive(False) self.interactive_recovery.set_sensitive(False) + self.encryption_box.hide() self.controller.allow_go_forward(False) + if not self.encyption_supported: + self.encryption_box.hide() self.toggle_progress() return self.plugin_widgets @@ -172,6 +202,9 @@ def toggle_progress(self): hasattr(self.controller, 'toggle_progress_section'): self.controller.toggle_progress_section() + def get_encryption(self): + return self.encryption.get_active() + def get_type(self): """Returns the type of recovery to do from GUI""" if self.automated_recovery.get_active(): @@ -191,6 +224,10 @@ def get_selected_device(self): size = model.get_value(iterator, 1) return (device, size) + def set_encryption(self, value): + if self.encyption_supported: + self.encryption.set_active(value) + def set_type(self, value, stage): """Sets the type of recovery to do in GUI""" if not self.genuine: @@ -199,8 +236,11 @@ def set_type(self, value, stage): if value == "automatic": self.automated_recovery.set_active(True) + self.encryption.set_sensitive(True) elif value == "interactive": self.interactive_recovery.set_active(True) + self.encryption.set_active(False) + self.encryption.set_sensitive(False) elif value == "factory": if stage == 2: self.plugin_widgets.hide() @@ -212,11 +252,17 @@ def set_type(self, value, stage): self.automated_recovery_box.hide() self.interactive_recovery.set_sensitive(False) self.automated_recovery.set_sensitive(False) + self.encryption.set_sensitive(True) def toggle_type(self, widget): """Allows the user to go forward after they've made a selection'""" self.controller.allow_go_forward(True) - self.automated_combobox.set_sensitive(self.automated_recovery.get_active()) + automated = self.automated_recovery.get_active() + hdd = self.hdd_recovery.get_active() + self.automated_combobox.set_sensitive(automated) + if self.encryption.get_active() and (automated or hdd): + self.encryption.set_active(False) + self.encryption_box.set_sensitive(automated or hdd) def show_dialog(self, which, data = None): """Shows a dialog""" @@ -226,12 +272,14 @@ def show_dialog(self, which, data = None): self.controller.allow_go_forward(False) self.automated_recovery_box.hide() self.interactive_recovery_box.hide() + self.encryption_box.hide() self.info_box.show_all() self.info_spinner.start() self.toggle_progress() elif which == "forward": self.automated_recovery_box.hide() self.interactive_recovery_box.hide() + self.encryption.hide() self.toggle_progress() else: self.info_spinner.stop() @@ -360,19 +408,29 @@ def sleep_network(self): def remove_extra_partitions(self): """Removes partitions we are installing on for the process to start""" - #check for small disks. - #on small disks or big mem, don't look for extended or delete swap. - os_part = EFI_OS_PARTITION - - #remove extras - if os_part.isdigit(): - remove = misc.execute_root('parted', '-s', self.device, 'rm', os_part) + dmsetup = misc.execute_root('dmsetup', 'remove_all') + if dmsetup is False: + self.log("Error calling dmsetup") + for part in [EFI_OS_PARTITION, EFI_BOOT_PARTITION]: + remove = misc.execute_root('parted', '-s', self.device, 'rm', part) if remove is False: - self.log("Error removing partition number: %s on %s (this may be normal)'" % (os_part, self.device)) - refresh = misc.execute_root('partx', '-d', '--nr', os_part, self.device) + self.log("Error removing partition number: %s on %s (this may be normal)'" % (part, self.device)) + refresh = misc.execute_root('partx', '-d', '--nr', part, self.device) if refresh is False: - self.log("Error updating partition %s for kernel device %s (this may be normal)'" % (os_part, self.device)) + self.log("Error updating partition %s for kernel device %s (this may be normal)'" % (part, self.device)) + def simple_partitioner(self): + """Runs all partitioning stuff for dell recovery""" + if self.device[-1].isnumeric(): + esp_part = 'p' + EFI_ESP_PARTITION + os_part = 'p' + EFI_OS_PARTITION + else: + esp_part = EFI_ESP_PARTITION + os_part = EFI_OS_PARTITION + result = misc.execute_root("/usr/share/dell/scripts/simple_partitioner.sh", + self.device, esp_part, os_part) + if result is False: + raise RuntimeError("Error running partitioner") def explode_sdr(self): '''Explodes all content explicitly defined in an SDR @@ -613,6 +671,17 @@ def fixup_factory_devices(self, rec_part): self.log("Detected device we are operating on is %s" % self.device) self.log("Detected a %s filesystem on the %s recovery partition" % (rec_part["fs"], rec_part["label"])) + def get_default_encryption_policy(self): + #whether to use encryption or not + try: + if self.db.get(ENCRYPTION_QUESTION) == 'true': + encryption = True + else: + encryption = False + except debconf.DebconfError: + encryption = False + return encryption + def prepare(self, unfiltered=False): """Prepare the Debconf portion of the plugin and gather all data""" #version @@ -695,6 +764,8 @@ def prepare(self, unfiltered=False): break self.mem = round(self.mem/1048575) #in GB + encryption = self.get_default_encryption_policy() + #Fill in UI data twiddle = {"mount": mount, "version": version, @@ -704,6 +775,7 @@ def prepare(self, unfiltered=False): for twaddle in reversed(sorted(twiddle)): self.ui.set_advanced(twaddle, twiddle[twaddle]) self.ui.set_type(rec_type, self.stage) + self.ui.set_encryption(encryption) #Make sure some locale was set so we can guarantee automatic mode try: @@ -770,6 +842,15 @@ def ok_handler(self): if size: self.device_size = size self.log("selected device %s %d" % (device, size)) + if self.ui.get_encryption(): + encryption = "true" + else: + encryption = "false" + self.preseed(SKIP_PARTITION_QUESTION, encryption) + self.preseed_config += SKIP_PARTITION_QUESTION + "=" + encryption + " " + self.preseed_config += ENCRYPTION_QUESTION + "=" + encryption + " " + self.preseed(ENCRYPTION_QUESTION, encryption) + self.log("enabled encryption: %s" % encryption) return Plugin.ok_handler(self) @@ -828,16 +909,22 @@ def cleanup(self): else: if 'dell-recovery/recovery_type=hdd' in open('/proc/cmdline', 'r').read().split(): self.ui.toggle_progress() + if self.db.get(ENCRYPTION_QUESTION) == 'true': + encryption = True + else: + encryption = False self.sleep_network() self.delete_swap() self.remove_extra_partitions() + if encryption: + self.simple_partitioner() self.explode_sdr() except Exception as err: #For interactive types of installs show an error then reboot #Otherwise, just reboot the system - if rec_type == "automatic" or rec_type == "interactive" or \ - ('UBIQUITY_DEBUG' in os.environ and 'UBIQUITY_ONLY' in os.environ): - self.handle_exception(err) +# if rec_type == "automatic" or rec_type == "interactive" or \ +# ('UBIQUITY_DEBUG' in os.environ and 'UBIQUITY_ONLY' in os.environ): + self.handle_exception(err) self.cancel_handler() #translate languages @@ -1268,6 +1355,17 @@ def install(self, target, progress, *args, **kwargs): with open(fname, 'w') as wfd: wfd.write('WARRANTY=%s\n' % destination) + #for turning on FDE + try: + encryption = progress.get(ENCRYPTION_QUESTION) + except debconf.DebconfError: + encryption = '' + fname = os.path.join(self.target, 'etc', 'default', 'dell-recovery') + if encryption and not os.path.exists(fname): + to_install += ['clevis-tpm2', 'clevis-systemd', 'tpm2-tools'] + with open(fname, 'w') as wfd: + wfd.write('ENCRYPTION=%s\n' % encryption) + #mark all upgrades and unconditional installs to_install += magic.mark_packages(rec_part) diff --git a/ubiquity/stepDellBootstrap.ui b/ubiquity/stepDellBootstrap.ui index 635bd461..da28112a 100644 --- a/ubiquity/stepDellBootstrap.ui +++ b/ubiquity/stepDellBootstrap.ui @@ -1,5 +1,5 @@ - + @@ -11,6 +11,9 @@ center dialog False + + + True @@ -63,9 +66,9 @@ True False - 0 <b>Runtime Details</b> True + 0 False @@ -77,8 +80,8 @@ True False - 0 version + 0 True @@ -90,8 +93,8 @@ True False - 0 mount + 0 True @@ -103,8 +106,8 @@ True False - 0 memory + 0 True @@ -211,11 +214,11 @@ True False - 0 - 0 This Dell Recovery Media can be used to restore the original factory software. True True + 0 + 0 False @@ -227,11 +230,11 @@ True False - 0 - 0 <b>It is recommended you back up all important data before running this tool.</b> True True + 0 + 0 False @@ -309,11 +312,11 @@ 600 True False - 0 - 0 This will rebuild all OS and swap partitions to factory defaults. True True + 0 + 0 @@ -333,11 +336,11 @@ 600 True False - 0 - 0 <b>WARNING: </b>All personal files and changes will be lost. True True + 0 + 0 @@ -439,11 +442,11 @@ 600 True False - 0 - 0 This will rebuild all recovery, and OS partitions. True True + 0 + 0 @@ -463,11 +466,11 @@ 600 True False - 0 - 0 <b>WARNING: </b>All personal files and changes will be lost. True True + 0 + 0 @@ -491,6 +494,87 @@ 1 + + + True + False + + + True + False + 48 + emblem-readonly + + + False + False + 0 + + + + + True + False + 5 + + + True + False + + + Encrypt the installation + True + True + False + start + True + + + + + True + True + 0 + + + + + True + False + 25 + + + 600 + True + False + Encryption will be enabled using the Trusted Platform Module (TPM). + True + True + 0 + 0 + + + + + False + False + 1 + + + + + True + True + 1 + + + + + True + False + 2 + + True @@ -542,11 +626,11 @@ 600 True False - 0 - 0 e.g. Disk encryption, partitions resizing..etc. True True + 0 + 0 @@ -566,11 +650,11 @@ 600 True False - 0 - 0 WARNING: No recovery feature included. True True + 0 + 0 @@ -591,7 +675,7 @@ True False - 2 + 3 @@ -607,7 +691,7 @@ True False - 3 + 4 @@ -630,10 +714,10 @@ True False - 0.05000000074505806 <b>ERROR:</b> This recovery media only functions on Dell or Alienware systems. True True + 0.05000000074505806 True @@ -645,7 +729,7 @@ True False - 4 + 5 @@ -656,11 +740,11 @@ True False - 0 - 0 <b>Building Recovery Partition</b> True True + 0 + 0 False @@ -672,11 +756,11 @@ True False - 0 - 0 <b>NOTE:</b> Please be patient, this may take a while. True True + 0 + 0 False @@ -688,11 +772,11 @@ True False - 0 - 0 Your system will restart automatically several times. True True + 0 + 0 True @@ -701,24 +785,13 @@ - - True - False - - - - - - True - True - 3 - + True False - 5 + 6