commit:     11a3470508a6475a5fee00f26ccbd7a98b4f9e01
Author:     Sebastian Bauer <sebastian.j.bauer <AT> gmail <DOT> com>
AuthorDate: Thu Aug 21 21:19:16 2014 +0000
Commit:     Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
CommitDate: Sat Jan  7 23:49:45 2017 +0000
URL:        https://gitweb.gentoo.org/proj/genkernel.git/commit/?id=11a34705

FL-1476: Add support for remote decryption of luks devices via dropbear

(cherry picked from commit 1886bbafecca1c225646e8d297bbb522caedfd9b)
Closes: https://bugs.gentoo.org/show_bug.cgi?id=440126
Signed-off-by: Robin H. Johnson <robbat2 <AT> gentoo.org>

 defaults/initrd.scripts  |  42 ++++++++++++++--
 defaults/login-remote.sh | 127 +++++++++++++++++++++++++++++++++++++++++++++++
 gen_initramfs.sh         |  72 +++++++++++++++++++++++++++
 genkernel.conf           |   3 ++
 4 files changed, 241 insertions(+), 3 deletions(-)

diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index 1ee1699..17166e4 100644
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -752,7 +752,7 @@ prompt_user(){
        bad_msg '- type "shell" for a shell'
        bad_msg '- type "q" to skip...'
        printf "%s" "${2}(${oldvalue}) :: "
-       read ${1}
+       read -t 10 ${1}
        case `eval echo '$'${1}` in
                'q')
                        eval ${1}'='${oldvalue}
@@ -1169,7 +1169,7 @@ openLUKS() {
 
        eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"' LUKS_NAME="$1" 
LUKS_KEY='"${CRYPT_'${TYPE}'_KEY}"' LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"' 
LUKS_TRIM='"${CRYPT_'${TYPE}'_TRIM}"'
        local DEV_ERROR=0 KEY_ERROR=0 KEYDEV_ERROR=0
-       local mntkey="/mnt/key/" cryptsetup_options=''
+       local mntkey="/mnt/key/" cryptsetup_options='' 
flag_opened="/${TYPE}.decrypted"
 
        [ ! -e /sbin/cryptsetup ] && bad_msg "The ramdisk does not support 
LUKS" && exit 1
        while [ 1 ]
@@ -1191,6 +1191,10 @@ openLUKS() {
                then
                        prompt_user "LUKS_KEYDEV" "${LUKS_NAME} key device"
                        KEYDEV_ERROR=0
+               elif [ -e ${flag_opened} ]
+               then
+                       good_msg "The LUKS device ${LUKS_DEVICE} meanwhile was 
opened by someone else."
+                       break
                else
                        LUKS_DEVICE=$(find_real_device "${LUKS_DEVICE}")
 
@@ -1284,6 +1288,8 @@ openLUKS() {
                                crypt_filter "${gpg_cmd}cryptsetup 
${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
                                crypt_filter_ret=$?
 
+                               touch ${flag_opened}
+
                                [ -e /dev/tty.org ] \
                                        && rm -f /dev/tty \
                                        && mv /dev/tty.org /dev/tty
@@ -1307,7 +1313,12 @@ openLUKS() {
 
 startLUKS() {
 
-       # if key is set but key device isn't, find it
+       # if key is set but neither ssh enabled or key device is given, find
+       # the key device
+       
+       if [ -e "/usr/sbin/dropbear" ]; then
+               startdropbear
+       fi
 
        [ -n "${CRYPT_ROOT_KEY}" ] && [ -z "${CRYPT_ROOT_KEYDEV}" ] \
                && sleep 6 && bootstrapKey "ROOT"
@@ -1335,6 +1346,31 @@ startLUKS() {
                        REAL_RESUME="/dev/mapper/swap"
                fi
        fi
+
+       if [ -e "/usr/sbin/dropbear" ]; then
+               /bin/kill $(cat /var/run/dropbear.pid)
+               /sbin/ifconfig $(echo "${IP}" | awk -F":" '{print $6}' ) 0.0.0.0
+       fi
+
+       if [ -e /root.decrypted ]; then
+               rm /root.decrypted
+       fi
+
+       if [ -e /swap.decrypted ]; then
+               rm /swap.decrypted
+       fi
+}
+
+startdropbear() {
+       if [ "${IP}" == '' ] ; then
+               busybox udhcpc -n -T 15 -q
+       fi
+
+       # setup environment variables for the ssh login shell
+       echo "CRYPT_ROOT=${CRYPT_ROOT}" >  /etc/login-remote.conf
+       echo "CRYPT_SWAP=${CRYPT_SWAP}" >> /etc/login-remote.conf
+       touch /var/log/lastlog
+       /usr/sbin/dropbear
 }
 
 sdelay() {

diff --git a/defaults/login-remote.sh b/defaults/login-remote.sh
new file mode 100644
index 0000000..630d484
--- /dev/null
+++ b/defaults/login-remote.sh
@@ -0,0 +1,127 @@
+#!/bin/sh
+
+. /etc/login-remote.conf
+. /etc/initrd.defaults
+. /etc/initrd.scripts
+KEYFILE_ROOT="/tmp/root.key"
+KEYFILE_SWAP="/tmp/swap.key"
+
+splash() {
+       return 0
+}
+
+[ -e /etc/initrd.splash ] && . /etc/initrd.splash
+
+receivefile() {
+       case ${1} in
+               root)
+                       file=${KEYFILE_ROOT}
+                       ;;
+               swap)
+                       file=${KEYFILE_SWAP}
+                       ;;
+       esac
+       # limit maximum stored bytes to 1M to avoid killing the server
+       dd of=${file} count=1k bs=1k 2>/dev/null
+       exit $?
+}
+
+openLUKSremote() {
+       case $1 in
+               root)
+                       local TYPE=ROOT
+                       ;;
+               swap)
+                       local TYPE=SWAP
+                       ;;
+       esac
+       
+       [ ! -d /tmp/key ] && mkdir -p /tmp/key
+       
+       eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"' LUKS_NAME="$1" 
LUKS_KEY='"${KEYFILE_'${TYPE}'}"'
+       local DEV_ERROR=0 KEY_ERROR=0
+       local input="" cryptsetup_options="" flag_opened="/${TYPE}.decrypted"
+       while [ 1 ]
+       do
+               local gpg_cmd="" crypt_filter_ret=42
+               echo $-
+               sleep 1
+
+               if [ -e ${flag_opened} ]
+               then
+                       good_msg "The LUKS device ${LUKS_DEVICE} meanwhile was 
opened by someone else."
+                       break
+               elif [ ${DEV_ERROR} -eq 1 ]
+               then
+                       prompt_user "LUKS_DEVICE" "${LUKS_NAME}"
+                       DEV_ERROR=0
+               else
+                       LUKS_DEVICE=$(find_real_device "${LUKS_DEVICE}")
+
+                       setup_md_device ${LUKS_DEVICE}
+                       cryptsetup isLuks ${LUKS_DEVICE}
+                       if [ $? -ne 0 ]
+                       then
+                               bad_msg "The LUKS device ${LUKS_DEVICE} does 
not contain a LUKS header" ${CRYPT_SILENT}
+                               DEV_ERROR=1
+                               continue
+                       else
+                               # Handle keys
+                               if [ "x${LUKS_TRIM}" = "xyes" ]
+                               then
+                                       good_msg "Enabling TRIM support for 
${LUKS_NAME}." ${CRYPT_SILENT}
+                                       
cryptsetup_options="${cryptsetup_options} --allow-discards"
+                               fi
+
+                               if [ ${crypt_filter_ret} -ne 0 ]
+                               then
+                                       # 1st try: unencrypted keyfile
+                                       crypt_filter "cryptsetup 
${cryptsetup_options} --key-file ${LUKS_KEY} luksOpen ${LUKS_DEVICE} 
${LUKS_NAME}"
+                                       crypt_filter_ret=$?
+
+                                       if [ ${crypt_filter_ret} -ne 0 ]
+                                       then
+                                               # 2nd try: gpg-encrypted keyfile
+                                               [ -e /dev/tty ] && mv /dev/tty 
/dev/tty.org
+                                               mknod /dev/tty c 5 1
+                                               gpg_cmd="/sbin/gpg 
--logger-file /dev/null --quiet --decrypt ${LUKS_KEY} |"
+                                               crypt_filter 
"${gpg_cmd}cryptsetup ${cryptsetup_options} --key-file ${LUKS_KEY} luksOpen 
${LUKS_DEVICE} ${LUKS_NAME}"
+                                               crypt_filter_ret=$?
+
+                                               [ -e /dev/tty.org ] \
+                                                       && rm -f /dev/tty \
+                                                       && mv /dev/tty.org 
/dev/tty
+                                       fi
+                               fi
+
+                               if [ ${crypt_filter_ret} -eq 0 ]
+                               then
+                                       touch ${flag_opened}
+                                       good_msg "LUKS device ${LUKS_DEVICE} 
opened" ${CRYPT_SILENT}
+                                       break
+                               else
+                                       bad_msg "Failed to open LUKS device 
${LUKS_DEVICE}" ${CRYPT_SILENT}
+                                       DEV_ERROR=1
+                               fi
+                       fi
+               fi
+       done
+       rm -f ${LUKS_KEY}
+       cd /
+       rmdir -p tmp/key
+}
+
+if [ "x${1}" = "x-c" ]
+then
+       command=$(echo ${2} | awk -F" " '{print $1}')
+       type=$(echo ${2} | awk -F" " '{print $2}')
+
+       case ${command} in 
+               post)
+                       receivefile ${type}
+                       ;;
+       esac
+else
+       [ -n "${CRYPT_ROOT}" ] && openLUKSremote root
+       [ -n "${CRYPT_SWAP}" ] && openLUKSremote swap
+fi

diff --git a/gen_initramfs.sh b/gen_initramfs.sh
index 10108fb..e81b477 100755
--- a/gen_initramfs.sh
+++ b/gen_initramfs.sh
@@ -632,6 +632,77 @@ append_luks() {
        rm -r "${TEMP}/initramfs-luks-temp/"
 }
 
+append_dropbear(){
+       if [ -d "${TEMP}"/initramfs-dropbear-temp ]
+       then
+               rm -r "${TEMP}"/initramfs-dropbear-temp
+       fi
+
+       if [ ! -d /etc/dropbear ]
+       then
+               mkdir /etc/dropbear
+       fi
+       if [ ! -e /etc/dropbear/dropbear_rsa_host_key ]
+       then
+               if [ -e /usr/bin/dropbearconvert -a /etc/ssh/ssh_host_rsa_key ]
+               then
+                       /usr/bin/dropbearconvert openssh dropbear 
/etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key
+               else
+                       /usr/bin/dropbearkey -t rsa -f 
/etc/dropbear/dropbear_rsa_host_key -s 4096 > /dev/null
+               fi
+       fi
+       
+       if [ ! -e /etc/dropbear/dropbear_dss_host_key ]
+       then
+               /usr/bin/dropbearkey -t dss -f 
/etc/dropbear/dropbear_dss_host_key > /dev/null
+       fi
+
+       cd "${TEMP}" \
+                || gen_die "cd '${TEMP}' failed"
+       mkdir -p ${TEMP}/initramfs-dropbear-temp/var/run
+       mkdir -p ${TEMP}/initramfs-dropbear-temp/var/log
+       mkdir -p ${TEMP}/initramfs-dropbear-temp/etc/dropbear
+       mkdir -p ${TEMP}/initramfs-dropbear-temp/bin
+       mkdir -p ${TEMP}/initramfs-dropbear-temp/root/.ssh
+
+       cp -L ${GK_SHARE}/defaults/login-remote.sh 
${TEMP}/initramfs-dropbear-temp/bin/
+       cp -L /etc/dropbear/{dropbear_rsa_host_key,dropbear_dss_host_key} 
${TEMP}/initramfs-dropbear-temp/etc/dropbear/
+       cp -L /etc/dropbear/authorized_keys 
${TEMP}/initramfs-dropbear-temp/root/.ssh
+       cp -L /etc/localtime ${TEMP}/initramfs-dropbear-temp/etc/
+       if [ ${ARCH} = "x86_64" ]
+       then
+               mkdir -p ${TEMP}/initramfs-dropbear-temp/lib64
+               cp -L /lib64/libnss_files.so.2 
${TEMP}/initramfs-dropbear-temp/lib64/
+       else
+               mkdir -p ${TEMP}/initramfs-dropbear-temp/lib
+               cp -L /lib/libnss_files.so.2 
${TEMP}/initramfs-dropbear-temp/lib/
+       fi
+       
+       sed "s/compat/files/g" /etc/nsswitch.conf > 
${TEMP}/initramfs-dropbear-temp/etc/nsswitch.conf
+       echo "root:x:0:0:root:/root:/bin/login-remote.sh" > 
${TEMP}/initramfs-dropbear-temp/etc/passwd
+       echo "/bin/login-remote.sh" > ${TEMP}/initramfs-dropbear-temp/etc/shells
+       echo "root:!:0:0:99999:7:::" > 
${TEMP}/initramfs-dropbear-temp/etc/shadow
+       echo "root:x:0:root" > ${TEMP}/initramfs-dropbear-temp/etc/group
+       echo "" > ${TEMP}/initramfs-dropbear-temp/var/log/lastlog
+
+       chmod 0755 ${TEMP}/initramfs-dropbear-temp/bin/login-remote.sh
+       chmod 0700 ${TEMP}/initramfs-dropbear-temp/root/.ssh
+       chmod 0640 ${TEMP}/initramfs-dropbear-temp/etc/shadow
+       chmod 0644 ${TEMP}/initramfs-dropbear-temp/etc/passwd
+       chmod 0644 ${TEMP}/initramfs-dropbear-temp/etc/group
+       mkfifo ${TEMP}/initramfs-dropbear-temp/etc/dropbear/fifo_root
+       mkfifo ${TEMP}/initramfs-dropbear-temp/etc/dropbear/fifo_swap
+       
+       copy_binaries "${TEMP}"/initramfs-dropbear-temp/ /usr/sbin/dropbear \
+               /bin/login /usr/bin/passwd
+       
+       log_future_cpio_content
+       cd "${TEMP}"/initramfs-dropbear-temp \
+               || gen_die "cd '${TEMP}/initramfs-dropbear-temp' failed"
+       find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+       rm -rf "${TEMP}"/initramfs-dropbear-temp > /dev/null
+}
+
 append_firmware() {
        if [ -z "${FIRMWARE_FILES}" -a ! -d "${FIRMWARE_DIR}" ]
        then
@@ -882,6 +953,7 @@ create_initramfs() {
        append_data 'iscsi' "${ISCSI}"
        append_data 'mdadm' "${MDADM}"
        append_data 'luks' "${LUKS}"
+       append_data 'dropbear' "${SSH}"
        append_data 'multipath' "${MULTIPATH}"
        append_data 'gpg' "${GPG}"
 

diff --git a/genkernel.conf b/genkernel.conf
index a95978d..d8f4ede 100644
--- a/genkernel.conf
+++ b/genkernel.conf
@@ -83,6 +83,9 @@ USECOLOR="yes"
 # Add DMRAID support.
 #DMRAID="no"
 
+# Add SSH support.
+#SSH="no"
+
 # Include (or suppresses the inclusion of) busybox in the initrd or initramfs.
 # If included, busybox is rebuilt if the cached copy is out of date.
 #BUSYBOX="yes"

Reply via email to