From c4e4112bdc8aa5fe92d797ab77744d3bcd70caf9 Mon Sep 17 00:00:00 2001 From: Eric Hameleers Date: Fri, 22 Jan 2016 15:15:17 +0100 Subject: Add support for a LUKS-encrypted /home in the USB Live version. Using iso2usb.sh script's new '-c' parameter, you can define the size for a container file in the root of the USB stick's Linux partition. - The container file will be loop-mounted and LUKS-encrypted and the Live OS will mount the filesystem inside the container on /home/. - The LUKS passphrase will be defined when executing the 'iso2usb.sh' script. - The original /home content of the ISO will be copied into the LUKS-encrypted container during execution of the 'iso2usb.sh' script. - If for whatever reason you do not want to unlock & mount the LUKS container during boot, you must add the boot parameter " luksvol= " to the syslinux or grub commandline. --- iso2usb.sh | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 172 insertions(+), 33 deletions(-) (limited to 'iso2usb.sh') diff --git a/iso2usb.sh b/iso2usb.sh index 680fc29..e9c27dd 100644 --- a/iso2usb.sh +++ b/iso2usb.sh @@ -39,10 +39,17 @@ VERBOSE=0 # Seconds to add to the initrd as wait-for-root value: WAIT=5 +# No LUKS encryption by default: +DOLUKS=0 +CNTDEV="" +CNTFILE="" +LODEV="" + # Define ahead of time, so that cleanup knows about them: IMGDIR="" EFIMNT="" ISOMNT="" +LKSMNT="" USBMNT="" # @@ -56,8 +63,16 @@ cleanup() { # During cleanup, do not abort due to non-zero exit code: set +e sync + if [ $DOLUKS -eq 1 ]; then + if mount |grep -q ${CNTDEV} ; then + umount -f ${CNTDEV} + cryptsetup luksClose ${CNTBASE} + losetup -d ${LODEV} + fi + fi [ -n "${EFIMNT}" ] && ( /sbin/umount -f ${EFIMNT} 2>/dev/null; rmdir $EFIMNT ) [ -n "${ISOMNT}" ] && ( /sbin/umount -f ${ISOMNT} 2>/dev/null; rmdir $ISOMNT ) + [ -n "${LKSMNT}" ] && ( /sbin/umount -f ${LKSMNT} 2>/dev/null; rmdir $LKSMNT ) [ -n "${USBMNT}" ] && ( /sbin/umount -f ${USBMNT} 2>/dev/null; rmdir $USBMNT ) [ -n "${IMGDIR}" ] && ( rm -rf $IMGDIR ) set -e @@ -75,30 +90,38 @@ cat < Full path to the ISO image file -# -o|--outdev The device name of your USB drive -# -p|--persistence Custom name of the 'persistence' directory -# -u|--unattended Do not ask any questions -# -v|--verbose Show verbose messages -# -w|--wait Pause boot seconds to initialize USB +# -c|--crypt size|perc Add LUKS encrypted /home ; parameter is the +# requested size of the container in kB, MB, GB, +# or as a percentage of free space. +# Examples: '-c 125M', '-c 1.3G', '-c 20%'. +# -f|--force Ignore most warnings (except the back-out). +# -h|--help This help. +# -i|--infile Full path to the ISO image file. +# -o|--outdev The device name of your USB drive. +# -p|--persistence Custom name of the 'persistence' directory. +# -u|--unattended Do not ask any questions. +# -v|--verbose Show verbose messages. +# -w|--wait Add seconds wait time to initialize USB. # -# Example: +# Examples: # # $(basename $0) -i ~/download/slackware64-live-14.2.iso -o /dev/sdX +# $(basename $0) -i slackware64-live-xfce-current.iso -o /dev/sdX -c 750M -w 15 # EOT } # Add longer USB WAIT to the initrd: update_initrd() { - # USB boot medium needs a few seconds boot delay else the overlay will fail. + IMGFILE="$1" + # USB boot medium needs a few seconds boot delay else the overlay will fail. # Check if we need to update the wait-for-root file in the initrd: - OLDWAIT=$(gunzip -cd ${USBMNT}/boot/initrd.img |cpio -i --to-stdout wait-for-root 2>/dev/null) - [ "$OLDWAIT" = "$WAIT" ] && return + OLDWAIT=$(gunzip -cd ${IMGFILE} |cpio -i --to-stdout wait-for-root 2>/dev/null) + if [ "$OLDWAIT" = "$WAIT" -a $DOLUKS -eq 0 ]; then + return + fi if [ -z "$IMGDIR" ]; then # Create a temporary extraction directory for the initrd: @@ -113,17 +136,120 @@ update_initrd() { echo "--- Extracting Slackware initrd and adding rootdelay for USB..." cd ${IMGDIR} - gunzip -cd ${USBMNT}/boot/initrd.img \ + gunzip -cd ${IMGFILE} \ | cpio -i -d -H newc --no-absolute-filenames echo "--- Updating 'waitforroot' time from '$OLDWAIT' to '$WAIT':" echo ${WAIT} > wait-for-root + + if [ $DOLUKS -eq 1 ]; then + if ! grep -q ${CNTFILE} luksdev ; then + echo "--- Adding '${CNTFILE}' as LUKS /home:" + echo "${CNTFILE}" >> luksdev + fi + fi + echo "--- Compressing the initrd image again:" chmod 0755 ${IMGDIR} - find . |cpio -o -H newc |gzip > ${USBMNT}/boot/initrd.img + find . |cpio -o -H newc |gzip > ${IMGFILE} cd - 2>/dev/null rm -rf $IMGDIR/* } # End of update_initrd() +# Create a container file in the empty space of the partition +create_container() { + CNTPART=$1 + CNTSIZE=$2 + CNTBASE=$3 + + # Determine size of the target partition (in MB), and the free space: + PARTSIZE=$(df -P -BM ${CNTPART} |tail -1 |tr -s '\t' ' ' |cut -d' ' -f2) + PARTSIZE=${PARTSIZE%M} + PARTFREE=$(df -P -BM ${CNTPART} |tail -1 |tr -s '\t' ' ' |cut -d' ' -f4) + PARTFREE=${PARTFREE%M} + + if [ $PARTFREE -lt 10 ]; then + echo "** Free space on USB partition is less than 10 MB;" + echo "** Not creating a container file!" + exit 1 + fi + + # Determine requested container size (allow for '%|k|K|m|M|g|G' suffix): + case "${CNTSIZE: -1}" in + "%") CNTSIZE="$(( $PARTFREE * ${CNTSIZE%\%} / 100 ))" ;; + "k") CNTSIZE="$(( ${CNTSIZE%k} / 1024 ))" ;; + "K") CNTSIZE="$(( ${CNTSIZE%K} / 1024 ))" ;; + "m") CNTSIZE="${CNTSIZE%m}" ;; + "M") CNTSIZE="${CNTSIZE%M}" ;; + "g") CNTSIZE="$(( ${CNTSIZE%g} * 1024 ))" ;; + "G") CNTSIZE="$(( ${CNTSIZE%G} * 1024 ))" ;; + *) ;; + esac + + if [ $CNTSIZE -le 0 ]; then + echo "** Container size must be larger than ZERO!" + echo "** Check your '-c' commandline parameter." + exit 1 + elif [ $CNTSIZE -ge $PARTFREE ]; then + echo "** Not enough free space for container file!" + echo "** Check your '-c' commandline parameter." + exit 1 + fi + + # Create an empty container file (allow for previously created ones): + for III in $(seq 1 9); do + if [ ! -f $USBMNT/${CNTBASE}0${III} ]; then + break + fi + done + if [ $III -eq 9 ]; then + echo "*** You already have NINE container files? Please clean up first." + exit 1 + else + echo "--- Creating ${CNTSIZE}MB container file using 'dd if=/dev/urandom', patience please..." + dd if=/dev/urandom of=$USBMNT/${CNTBASE}0${III}.img bs=1M count=$CNTSIZE + CNTFILE="${CNTBASE}0${III}.img" + fi + + # Setup a loopback device that we can use with cryptsetup: + LODEV=$(losetup -f) + losetup $LODEV $USBMNT/${CNTBASE}0${III}.img + if [ $DOLUKS -eq 1 ]; then + # Format the loop device with LUKS: + echo "--- Encrypting the container file with LUKS; enter 'YES' and a passphrase..." + cryptsetup -y luksFormat $LODEV + # Unlock the LUKS encrypted container: + echo "--- Unlocking the LUKS container requires your passphrase again..." + cryptsetup luksOpen $LODEV ${CNTBASE} + CNTDEV=/dev/mapper/${CNTBASE} + else + CNTDEV=$LODEV + fi + # Format the now available block device with a linux fs: + mkfs.ext4 ${CNTDEV} + # Tune the ext4 filesystem: + tune2fs -m 0 -c 0 -i 0 ${CNTDEV} + # Create a mount point for the unlocked container: + LKSMNT=$(mktemp -d -p /mnt -t alienlks.XXXXXX) + if [ ! -d $LKSMNT ]; then + echo "*** Failed to create a temporary mount point for the LUKS container!" + exit 1 + else + chmod 711 $LKSMNT + fi + # Copy the original /home content into the container: + echo "--- Copying /home from LiveOS to LUKS container..." + HOMESRC=$(find ${USBMNT} -name "0099-slackware_zzzconf*" |tail -1) + mount ${CNTDEV} ${LKSMNT} + unsquashfs -n -d ${LKSMNT}/temp ${HOMESRC} /home + mv ${LKSMNT}/temp/home/* ${LKSMNT}/ + rm -rf ${LKSMNT}/temp + # And clean up after ourselves: + umount ${CNTDEV} + cryptsetup luksClose ${CNTBASE} + losetup -d ${LODEV} + +} # End of create_container() { + # # -- end of function definitions -- # @@ -135,6 +261,11 @@ if [ -z "$1" ]; then fi while [ ! -z "$1" ]; do case $1 in + -c|--crypt) + LUKSSIZE="$2" + DOLUKS=1 + shift 2 + ;; -f|--force) FORCE=1 shift @@ -203,7 +334,7 @@ fi # Are all the required not-so-common add-on tools present? PROG_MISSING="" -for PROGN in blkid cpio extlinux fdisk gdisk iso-info mkdosfs sgdisk ; do +for PROGN in blkid cpio extlinux fdisk gdisk iso-info mkdosfs sgdisk unsquashfs ; do if ! PATH="/sbin:$PATH" which $PROGN 1>/dev/null 2>/dev/null ; then PROG_MISSING="${PROG_MISSING}-- $PROGN\n" fi @@ -310,27 +441,12 @@ else chmod 711 $USBMNT fi -# Loop-mount the ISO (or 1st partition if this is a hybrid ISO): -/sbin/mount -o loop ${SLISO} ${ISOMNT} - -if [ $EFIBOOT -eq 1 ]; then - # Mount the EFI partition and copy /EFI as well as /boot directories into it: - /sbin/mount -t vfat -o shortname=mixed ${TARGET}2 ${USBMNT} - mkdir -p ${USBMNT}/EFI/BOOT - rsync -rlptD ${ISOMNT}/EFI/BOOT/* ${USBMNT}/EFI/BOOT/ - mkdir -p ${USBMNT}/boot - rsync -rlptD ${ISOMNT}/boot/* ${USBMNT}/boot/ - # Add more USB WAIT seconds to the initrd: - update_initrd ${USBMNT}/boot/initrd.img -fi - -# No longer needed: -/sbin/umount ${USBMNT} -/sbin/umount ${EFIMNT} - # Mount the Linux partition: /sbin/mount -t auto ${TARGET}3 ${USBMNT} +# Loop-mount the ISO (or 1st partition if this is a hybrid ISO): +/sbin/mount -o loop ${SLISO} ${ISOMNT} + # Copy the ISO content into the USB Linux partition: echo "--- Copying files from ISO to USB... takes some time." rsync -a ${RVERBOSE} --exclude=EFI ${ISOMNT}/* ${USBMNT}/ @@ -341,6 +457,11 @@ if [ -n "$VERSION" ]; then echo "$VERSION" > ${USBMNT}/.isoversion fi +if [ $DOLUKS -eq 1 ]; then + # Create LUKS container file: + create_container ${TARGET}3 ${LUKSSIZE} slhome +fi + # Add more USB WAIT seconds to the initrd: update_initrd ${USBMNT}/boot/initrd.img @@ -354,6 +475,24 @@ mv ${USBMNT}/boot/extlinux/isolinux.cfg ${USBMNT}/boot/extlinux/extlinux.conf rm ${USBMNT}/boot/extlinux/isolinux.* /sbin/extlinux --install ${USBMNT}/boot/extlinux +# No longer needed: +/sbin/umount ${USBMNT} + +if [ $EFIBOOT -eq 1 ]; then + # Mount the EFI partition and copy /EFI as well as /boot directories into it: + /sbin/mount -t vfat -o shortname=mixed ${TARGET}2 ${USBMNT} + mkdir -p ${USBMNT}/EFI/BOOT + rsync -rlptD ${ISOMNT}/EFI/BOOT/* ${USBMNT}/EFI/BOOT/ + mkdir -p ${USBMNT}/boot + rsync -rlptD ${ISOMNT}/boot/* ${USBMNT}/boot/ + # Add more USB WAIT seconds to the initrd: + update_initrd ${USBMNT}/boot/initrd.img +fi + +# No longer needed: +/sbin/umount ${USBMNT} +/sbin/umount ${EFIMNT} + # Unmount/remove stuff: cleanup -- cgit v1.2.3