# # Shared Functions for nannycam and the associated install hook # ensure_initramfs_environment() { # Check if running outside the initramfs environment if ! type resolve_device &>/dev/null; then # Setup enough of the early userspace environment that resolve_device works source /usr/lib/initcpio/init_functions udevd_running=$(ps aux | grep udevd | grep -v grep | wc -l) rootdelay=1 fi } ensure_mkcpinitio_environment() { # This script is expected to be called from mkinitcpio, if not... if [ -z ${BUILDROOT:-} ]; then # ...then mock out enough of the environment to enable testing saveOpts=$(set +o | egrep 'xtrace|errexit|nounset') saveGlob=$(shopt -p | grep extglob) shopt -s extglob set +e set +u set +x . "/usr/lib/initcpio/functions" BUILDROOT=$(initialize_buildroot $(uname -r) $(mktemp -d --tmpdir mkinitcpio.XXXXXX)) _optgenimg=$(find /boot -name '*.img' 2>/dev/null | head -n 1) _optquiet=1 eval "$saveOpts" eval "$saveGlob" fi } nannycam_usage () { cat <&2 exit 1 } hash_mismatch () { (cat <&2 local response="" while [[ "$response" != "YES" ]]; do read -p "Enter YES to continue booting (not recommended): " response done } determine_mbr_boot_device () { local possibleDevices=$(parted -s -m -l \ | sed -e 's/^$/\x00/' \ | tr -d '\n' \ | tr '\0' '\n' \ | egrep ';([^:]*:){6}boot' \ | cut -f 2 -d ';' \ | cut -f 1 -d ':') [ $(echo "$possibleDevices" | wc -l) -eq 1 ] \ || ( echo "Expected exactly one partition with boot flag set, aborting." >&2; exit 5 ) echo "$possibleDevices" } hash_mbr () { local mbrDevice=$(determine_mbr_boot_device) dd if="$mbrDevice" of=/tmp/mbr.bin bs=512 count=1 &>/dev/null ACTUAL_MBR_HASH="$(openssl dgst -$HASH_ALG /tmp/mbr.bin | cut -f 2 -d ' ')" rm /tmp/mbr.bin } check_mbr () { hash_mbr [[ "$EXPECTED_MBR_HASH" == "$ACTUAL_MBR_HASH" ]] } hash_mbr_gap () { local mbrDevice=$(determine_mbr_boot_device) local part_start=$(parted -s -m "$mbrDevice" unit b print | egrep '^1:' | cut -f 2 -d ':' | tr -d 'Bb') local blocks=$(( part_start / 512 )) local check=$(( $blocks * 512 )) [ $part_start -eq $check ] || ( echo "Partition doesn't start at 512 byte boundary! Aborting." >&2; exit 3 ) dd if="$mbrDevice" of=/tmp/gap.bin bs=512 skip=1 count=$blocks &> /dev/null ACTUAL_MBR_GAP_HASH="$(openssl dgst -$HASH_ALG /tmp/gap.bin | cut -f 2 -d ' ')" rm /tmp/gap.bin } check_mbr_gap () { hash_mbr_gap [[ "$EXPECTED_MBR_GAP_HASH" == "$ACTUAL_MBR_GAP_HASH" ]] } check_already_mounted () { local device="$1" echo $(mount | grep "^$device on" | cut -f 3 -d ' ') } hash_efi_stub () { # Don't bother checking efi stub if booting in MBR mode if ! mount | grep efivarfs &>/dev/null; then return 0 fi # Determine which EFI stub was used local bootinfo="$(efibootmgr -v)" local currentNum=$(echo "$bootinfo" | egrep '^BootCurrent:' | cut -f 2 -d ' ') local current=$(echo "$bootinfo" | grep "^Boot$currentNum\*") # TODO: Support other boot devices other than ESP System Partitions local partitionAndPath=$( echo "$current" | \ sed -nre 's_^.*HD\([0-9]+,GPT,([^,]{36}),[^)]+\)/File\(([^)]+)\)_\1\2_p') local partitionUUID=$(echo "$partitionAndPath" | head -c 36 ) # TODO: Determine how escaped paths work with efibootmgr local path=$(echo "$partitionAndPath" | tail -c +37 | tr '\\' '/' ) local mountDevice=$(resolve_device PARTUUID=$partitionUUID) local mountPoint=$(check_already_mounted "$mountDevice") if [ -z "$mountPoint" ]; then mountPath="/tmp/efi" mount $mountDevice $mountPoint fi ACTUAL_EFI_STUB_HASH=$(openssl dgst -$HASH_ALG "$mountPoint$path" | cut -f 2 -d ' ') } check_efi_stub () { hash_efi_stub [[ "$EXPECTED_EFI_STUB_HASH" == "$ACTUAL_EFI_STUB_HASH" ]] } assert_root() { if [[ "0" != "$(id -u)" ]]; then echo "Must be run as root." >&2 exit 4 fi } assert_ephemeral() { fsType=$(df "$1" | tail -n 1 | cut -f 1 -d ' ') if [[ "tmpfs" != "$fsType" ]]; then (cat <&2 exit 1 fi } assert_encrypted() { fsMnt=$(df "$1" | tail -n 1 | egrep -o ' [^ ]+$' | tail -c +2) isCrypt=$(lsblk -ro TYPE,MOUNTPOINT | egrep "$fsMnt$" | egrep '^crypt' | wc -l) if [ ! $isCrypt -eq 1 ]; then (cat <&2 exit 2 fi }