Package: dropbear-initramfs
Severity: wishlist

Hi,

when I upgraded my Squeeze box to Jessie, remote unlocking via dropbear
in my initramfs stopped working. This is a remote host in a datacenter,
so I cannot directly investigate the issue.

I propose to add an autopkgtest for dropbear-initramfs to make sure that
the functionality continues to work even as the packages around it
change over time.

I attached a shell script which uses qemu to prepare a system that has
an unencrypted /boot and / and swap on an LVM on luks, which I guess is
the classical layout.

If you like the script, then I could prepare a patch against
src:dropbear which implements an autopkgtest that runs the script.

Thanks!

cheers, josch
#!/bin/sh

set -exu

ssh="ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -i id_rsa"

pkgs="linux-image-amd64,openssh-server,systemd-sysv,libpam-systemd,policykit-1"
pkgs="$pkgs,iproute2,util-linux,e2fsprogs,ifupdown,net-tools,netbase"
pkgs="$pkgs,iputils-ping,isc-dhcp-client,lvm2,parted,cryptsetup"
pkgs="$pkgs,dropbear-initramfs,busybox,fdisk,mmdebstrap,udev"

mmdebstrap --mode=unshare --variant=apt --include=$pkgs \
        --customize-hook='chroot "$1" passwd --delete root' \
        --customize-hook='chroot "$1" useradd --home-dir /home/user 
--create-home user' \
        --customize-hook='chroot "$1" passwd --delete user' \
        --customize-hook='echo host > "$1/etc/hostname"' \
        --customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"' \
        --customize-hook='echo "/dev/sda1 / auto errors=remount-ro 0 1" > 
"$1/etc/fstab"' \
        unstable debian-unstable.tar

fallocate -l 2G crypt.img

cat << END > extlinux.conf
default linux
timeout 0

label linux
kernel /vmlinuz
append initrd=/initrd.img root=/dev/sda1 console=ttyS0
END

cat << END > interfaces
auto lo
iface lo inet loopback

auto ens3
iface ens3 inet dhcp
END

[ -e ./id_rsa ] && [ -e ./id_rsa.pub ] || ssh-keygen -q -t rsa -f ./id_rsa -N ""

guestfish -N debian-unstable.img=disk:2G -- \
        part-disk /dev/sda mbr : \
        part-set-bootable /dev/sda 1 true :  \
        mkfs ext2 /dev/sda1 : \
        mount /dev/sda1 / : \
        tar-in debian-unstable.tar / : \
        extlinux / : \
        mkdir /root/.ssh : \
        copy-in id_rsa.pub /root/ : \
        mv /root/id_rsa.pub /root/.ssh/authorized_keys : \
        chown 0 0 /root/.ssh/authorized_keys : \
        copy-in extlinux.conf / : \
        copy-in interfaces /etc/network

qemu-img convert -O qcow2 debian-unstable.img debian-unstable.qcow2

qemu-system-x86_64 -enable-kvm -m 4G -net user,hostfwd=tcp::10022-:22 \
        -net nic -nographic -serial mon:stdio \
        -drive file=debian-unstable.qcow2 \
        -drive file=crypt.img,format=raw >qemu1.log </dev/null 2>&1 &

QEMUPID=$!

trap "kill $QEMUPID" EXIT

TIMESTAMP=$(sleepenh 0 || [ $? -eq 1 ])
TIMEOUT=3
i=0
while true; do
        rv=0
        $ssh -p 10022 -o ConnectTimeout=$TIMEOUT root@localhost echo success || 
rv=1
        [ $rv -eq 0 ] && break
        # if the command before took less than $TIMEOUT seconds, wait the 
remaining time
        TIMESTAMP=$(sleepenh $TIMESTAMP $TIMEOUT || [ $? -eq 1 ]);
        i=$((i+1))
        if [ $i -ge 10 ]; then
                break
        fi
done

if [ $i -eq 10 ]; then
        echo "timeout reached: unable to connect to qemu via ssh"
        exit 1
fi

$ssh -p 10022 root@localhost << 'SSHSCRIPT'
set -exu

cat << END | sfdisk /dev/sdb
label: gpt
unit: sectors

start=   2048, size=        2048, type=21686148-6449-6E6F-744E-656564454649
start=   4096, size=      999424, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
start=1003520,                    type=CA7D7CCB-63ED-4C53-861C-1742536059CC
END

fdisk -l

printf myinsecurepassphrase | cryptsetup luksFormat /dev/sdb3 -
printf myinsecurepassphrase | cryptsetup luksOpen /dev/sdb3 mycrypt
pvcreate /dev/mapper/mycrypt
vgcreate myvg /dev/mapper/mycrypt
lvcreate --name swap --size 15M myvg
mkswap /dev/myvg/swap
swapon /dev/myvg/swap
lvcreate --name root --size 1G myvg
mkfs.ext4 /dev/myvg/root
mkfs.ext2 /dev/sdb2

BOOTUUID=`blkid -s UUID -o value /dev/sdb2`
SDB3UUID=`blkid -s UUID -o value /dev/sdb3`
SWAPUUID=`blkid -s UUID -o value /dev/myvg/swap`

mount /dev/myvg/root /mnt

# need to use /dev/null on stdin because of #934199
mmdebstrap --debug --mode=root --variant=apt unstable /mnt </dev/null

mkdir -p "/mnt/etc/apt/apt.conf.d"
echo 'APT::Install-Recommends "0";' > 
"/mnt/etc/apt/apt.conf.d/99no-install-recommends"

cat > "/mnt/etc/apt/apt.conf.d/99autoremove" << END
APT::AutoRemove::SuggestsImportant false;
APT::AutoRemove::RecommendsImportant false;
END

mkdir -p "/mnt/etc/default"

cat > "/mnt/etc/default/grub" << 'END'
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="ip=:::::ens3:dhcp cgroup_enable=memory swapaccount=1 
console=ttyS0 "
END

cat > "/mnt/etc/fstab" << END
/dev/myvg/root  /     auto    errors=remount-ro 0 1
UUID=$BOOTUUID  /boot auto    defaults          0 2
/dev/myvg/swap  none  swap    sw                0 0
END

chroot /mnt passwd --delete root
chroot /mnt useradd --home-dir /home/user --create-home user
chroot /mnt passwd --delete user
echo host > "/mnt/etc/hostname"
echo "127.0.0.1 localhost host" > "/mnt/etc/hosts"

cat > "/mnt/etc/crypttab" << END
mycrypt UUID=$SDB3UUID none luks
END

mkdir -p "/mnt/etc/initramfs-tools/conf.d"
echo RESUME=UUID=$SWAPUUID > "/mnt/etc/initramfs-tools/conf.d/resume"

cat > "/mnt/etc/initramfs-tools/conf.d/dropbear" << END
IP=":::::ens3:dhcp"
END

mkdir -p /mnt/etc/dropbear-initramfs
{ printf 
'no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="/bin/cryptroot-unlock"
 ';
  head -1 /root/.ssh/authorized_keys;
} > /mnt/etc/dropbear-initramfs/authorized_keys

mkdir -p /mnt/root/.ssh
cp /root/.ssh/authorized_keys /mnt/root/.ssh/authorized_keys

mkdir -p /mnt/etc/network/
cat << END > /mnt/etc/network/interfaces
auto lo
iface lo inet loopback

auto ens3
iface ens3 inet dhcp
END

mount -t proc proc "/mnt/proc"
mount -t sysfs sysfs "/mnt/sys"
mount --bind /dev "/mnt/dev"
mount --bind /run "/mnt/run"
mount /dev/sdb2 "/mnt/boot"

cat > "/mnt/usr/sbin/policy-rc.d" << END
#!/bin/sh
echo "sysvinit: All runlevel operations denied by policy" >&2
exit 101
END
chmod +x "/mnt/usr/sbin/policy-rc.d"

export DEBIAN_FRONTEND=noninteractive
export DEBCONF_NONINTERACTIVE_SEEN=true

chroot "/mnt" apt-get update
chroot "/mnt" apt-get upgrade
chroot "/mnt" apt-get dist-upgrade
chroot "/mnt" apt-get -y install lvm2 grub2 linux-image-amd64 openssl 
cryptsetup dropbear-initramfs busybox udev mount systemd-sysv util-linux 
e2fsprogs initramfs-tools cryptsetup-initramfs cryptsetup-run console-setup 
openssh-server ifupdown net-tools netbase iproute2 libpam-systemd policykit-1 
iputils-ping isc-dhcp-client

rm "/mnt/usr/sbin/policy-rc.d"

echo 'DROPBEAR_OPTIONS="-p 2222"' >> /mnt/etc/dropbear-initramfs/config

chroot /mnt update-initramfs -u -k all
chroot /mnt grub-install --no-floppy --modules=part_gpt /dev/sdb
chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg

umount "/mnt/proc"
umount "/mnt/sys"
umount "/mnt/dev"
umount "/mnt/run"
umount "/mnt/boot"
umount "/mnt"
swapoff /dev/myvg/swap
vgchange -an myvg
cryptsetup luksClose mycrypt

SSHSCRIPT

trap - EXIT

$ssh -p 10022 root@localhost systemctl poweroff

wait $QEMUPID

qemu-system-x86_64 -enable-kvm -m 4G -net 
user,hostfwd=tcp::10022-:22,hostfwd=tcp::12222-:2222 \
        -net nic -nographic -serial mon:stdio \
        -drive file=crypt.img,format=raw >qemu2.log </dev/null 2>&1 &

QEMUPID=$!

trap "kill $QEMUPID" EXIT

TIMESTAMP=$(sleepenh 0 || [ $? -eq 1 ])
TIMEOUT=3
i=0
while true; do
        rv=0
        printf myinsecurepassphrase | $ssh -p 12222 -o ConnectTimeout=$TIMEOUT 
root@localhost || rv=1
        [ $rv -eq 0 ] && break
        # if the command before took less than $TIMEOUT seconds, wait the 
remaining time
        TIMESTAMP=$(sleepenh $TIMESTAMP $TIMEOUT || [ $? -eq 1 ]);
        i=$((i+1))
        if [ $i -ge 10 ]; then
                break
        fi
done

if [ $i -eq 10 ]; then
        echo "timeout reached: unable to connect to qemu via ssh"
        exit 1
fi

TIMESTAMP=$(sleepenh 0 || [ $? -eq 1 ])
TIMEOUT=3
i=0
while true; do
        rv=0
        $ssh -p 10022 -o ConnectTimeout=$TIMEOUT root@localhost echo success || 
rv=1
        [ $rv -eq 0 ] && break
        # if the command before took less than $TIMEOUT seconds, wait the 
remaining time
        TIMESTAMP=$(sleepenh $TIMESTAMP $TIMEOUT || [ $? -eq 1 ]);
        i=$((i+1))
        if [ $i -ge 10 ]; then
                break
        fi
done

if [ $i -eq 10 ]; then
        echo "timeout reached: unable to connect to qemu via ssh"
        exit 1
fi

$ssh -p 10022 root@localhost mount

$ssh -p 10022 root@localhost systemctl poweroff

wait $QEMUPID

trap - EXIT

Reply via email to