#!/bin/sh # # Set up a SSH daemon, the sole purpose of which is to slurp the key for # full disk encryption, so that it doesn't have to be manually entered # to the installer. # # Copyright 2013 Guilhem Moulin # # Licensed under the GNU GPL version 3 or higher. set -ue root=/cdrom . /usr/share/debconf/confmodule debconf-loadtemplate fripost-install $root/preseed/fripost-install.template db_input high fripost-install/full-disk-encryption || true db_go db_get fripost-install/full-disk-encryption [ x"${RET:-true}" = x"false" ] && exit 0 ############################################################################## # Crypto, disk and network modules, required to unlock the system from # our initramfs. # TODO: should probably be stored in debconf, since we'll need the # modules in the target only while read k rest; do /sbin/modinfo -F filename "$k"; done < /proc/modules \ | sed -nr "s@^/lib/modules/`uname -r`/kernel/(arch|drivers/(ata|scsi))(/.*)?/([^/]+)\.ko\$@\4@p" \ > /tmp/initramfs-modules ############################################################################## # Slurp encryption key db_input high fripost-install/full-disk-encryption-password || true db_go db_get fripost-install/full-disk-encryption-password keyfile=~root/root.key if [ -n "$RET" ]; then touch "$keyfile" chmod 0644 "$keyfile" echo $RET >> "$keyfile" # TODO: remove passord from debconf else anna-install openssh-server-udeb mkdir -pm0755 /etc/ssh/ sshHostKey=/etc/ssh/ssh_host_rsa_key ssh-keygen -b 4096 -t rsa -N '' -C $sshHostKey -f $sshHostKey cat > /etc/ssh/sshd_config <<- EOF Port 22 Protocol 2 HostKey $sshHostKey UsePrivilegeSeparation no PasswordAuthentication no ChallengeResponseAuthentication no HostbasedAuthentication no PubkeyAuthentication yes PermitRootLogin yes AllowUsers root StrictModes yes #ForceCommand /bin/sh -c 'umask 0077; cat > $keyfile' EOF # Populate the authorized keys. test -d ~root/.ssh || mkdir -m 0700 ~root/.ssh sed 's/^/no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding /' \ $root/preseed/authorized_keys > ~root/.ssh/authorized_keys chmod og-rwx ~root/.ssh/authorized_keys # Start the SSH daemon touch /var/log/lastlog /usr/sbin/sshd # Tell the user we're ready db_subst fripost-install/full-disk-encryption-slurpkey_text IPv4 \ "$(ip addr show eth0 | sed -nr 's/^\s+inet\s([0-9.]{4,32}).*/\1/p')" db_subst fripost-install/full-disk-encryption-slurpkey_text SSHFPR_SERVER \ "$(ssh-keygen -lf $sshHostKey)" db_subst fripost-install/full-disk-encryption-slurpkey_text SSHFPR_AUTHORIZED \ "$($root/preseed/sshfprs.sh ~root/.ssh/authorized_keys ' - ')" # Anything sent to the SSH is stored into $keyfile, which is our LUKS key. until test -r "$keyfile"; do db_settitle fripost-install/full-disk-encryption-slurpkey_title db_input critical fripost-install/full-disk-encryption-slurpkey_text db_go done kill `cat /var/run/sshd.pid` || true fi ############################################################################## # Fill the disk with random data db_input high fripost-install/full-disk-encryption-fill || true db_go db_get fripost-install/full-disk-encryption-fill dev="$RET" heartbeat () { local pid sig sleep pid=$1 sig=${2:-SIGHUP} sleep=${3:-1} until false; do sleep $sleep /bin/kill -$sig $pid 2>/dev/null || break done } if [ x"$RET" != x"none" ]; then source="/dev/$RET" bs=4096 disk=$(list-devices disk | head -1) size=$(parted_devices "$disk" | cut -f2) fill="dd if=$source of=$disk bs=$bs" db_subst fripost-install/full-disk-encryption-fill_progress_title DISK "$disk" db_subst fripost-install/full-disk-encryption-fill_progress_title SIZE "$size" if [ x"$source" = x"/dev/zero" ]; then db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "zeroes" elif [ x"$source" = x"/dev/random" -o x"$source" = x"/dev/urandom" ]; then db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "bytes of random data" else db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "bytes" fi db_progress START 0 $(( $size / $bs )) fripost-install/full-disk-encryption-fill_progress_title db_subst fripost-install/full-disk-encryption-fill_progress_info COMMAND "$fill" db_progress INFO fripost-install/full-disk-encryption-fill_progress_info fifo=$(mktemp -u) mknod "$fifo" p trap 'echo kill $pid' EXIT $fill 2> "$fifo" & pid=$! heartbeat $pid USR1 & while read -u 7 n records dir; do [ x"$records" = x"records" -a x"$dir" = x"out" ] && db_progress SET ${n%+*} done 7< "$fifo" rm "$fifo" trap '' EXIT db_progress STOP db_unregister fripost-install/full-disk-encryption-fill_progress_title db_unregister fripost-install/full-disk-encryption-fill_progress_info # http://horde.net/~jwm/blog/progress-bars-with-debconf/ # http://horde.net/~jwm/blog/how-shell-scripts-communicate-with-debconf/ fi ############################################################################## # Partitioning anna-install parted-udeb dev=/dev/sda offset=`cat /sys/block/${dev#/dev/}/alignment_offset` bs=`cat /sys/block/${dev#/dev/}/queue/physical_block_size` if [ $offset -eq 0 ]; then offset=64 else offset=$(( $offset / $bs )) fi parted -sm $dev mklabel gpt grain=$(( 256*32 )) # All offset2's must be multiple of 256*32 = 8192 if [ -d /proc/efi ] || [ -d /sys/firmware/efi ]; then offset2=$(( 256 * 1024**2 / $bs )) offset2=$(( $offset2 - $offset2 % $grain )) parted -a minimal -sm $dev mkpart uefi ${offset}s $(( $offset2 - 1 ))s offset=$offset2 offset2=$(( $offset + 64 * 1024**2 / $bs )) offset2=$(( $offset2 - $offset2 % $grain )) parted -a minimal -sm $dev mkpart boot ${offset}s $(( $offset2 - 1))s parted -sm $dev set 1 boot on else offset2=$(( 64 * 1024**2 / $bs )) parted -a minimal -sm $dev mkpart boot ${offset}s $(( $offset2 - 1))s fi offset=$offset2 offset2=$(( `cat /sys/block/${dev#/dev/}/size` - 1 )) offset2=$(( $offset2 - $offset2 % $grain )) parted -a optimal -sm $dev mkpart system ${offset}s $(( $offset2 - 1))s system=${dev}$(parted -sm $dev p | grep -m 1 '^[1-9][0-9]*:.*:system:[^:]*;$' | sed 's/:.*//') parted -sm $dev align-check opt ${system#$dev} ############################################################################## # Encryption anna-install cryptsetup-udeb crypto-dm-modules arch=$(uname -m) if [ x"$arch" = x"x86_64" ]; then keysize=256 hash=sha512 elif [ x"$arch" = x"i386" -o x"$arch" = x"i686" ]; then keysize=128 hash=sha256 fi # Notes: 1/ XTS requires the key size to be doubled, 2/ We use AES128 # and SHA-256 on 32-bits platforms, and AES256 and SHA-512 on 64-bits # platforms. # TODO: Note: Generating key... (this may take a while) /sbin/cryptsetup -q --align-payload $grain \ --cipher aes-xts-plain64 --key-size $(( $keysize * 2 )) --hash $hash \ --iter-time 5000 --use-random --key-file="$keyfile" \ luksFormat $system /sbin/cryptsetup luksOpen --key-file="$keyfile" $system system_crypt rm "$keyfile" # We are on a ramdisk, so it's good enough to unlink(2) ############################################################################## # LVM /sbin/pvcreate /dev/mapper/system_crypt db_get netcfg/get_hostname /sbin/vgcreate "$RET" /dev/mapper/system_crypt # TODO: Point the installer at the partitions we created