diff --git a/ChangeLog b/ChangeLog index 2429ef2..b624570 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2021-11-12 Julien Coloos + + * v0.10-1 + Option to use login shell instead of cryptsetup script + Re-enable Wake-on-LAN on network device + + +2021-11-12 Julien Coloos + + * v0.9-2 + Use SHA256 checksums instead of MD5 + + 2021-10-24 Julien Coloos * v0.9-1 diff --git a/PKGBUILD b/PKGBUILD index 9a32228..b7a7404 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,17 +1,17 @@ # Maintainer: Julien Coloos pkgname=initrd-ssh-cryptsetup -pkgver=0.9 +pkgver=0.10 pkgrel=1 pkgdesc="Allows for LUKS-encrypted devices to be unlocked remotely over SSH" arch=('any') url="https://github.com/suiryc/archlinux-$pkgname" license=('GPL3') -depends=('dropbear' 'cryptsetup' 'mkinitcpio-nfs-utils' 'iproute2') +depends=('dropbear' 'cryptsetup' 'mkinitcpio-nfs-utils' 'iproute2' 'ethtool') install=$pkgname.install changelog='ChangeLog' source=("http://julien.coloos.free.fr/archlinux/$pkgname-$pkgver.tar.xz" "$pkgname.install") -md5sums=('c94a905ca91f7afe2c0f771bd5182cb2' - 'ac60109d80e7bb2af0d66e69aaf178a6') +sha256sums=('c3fa91fc8ba2228b3492d3709231918c8015cc3da49f516c3eacea5c0217536c' + 'b84978b3c2ef32208c2b104ee2d3ce8aaec26da0bd4e9e1c83942f373bbf6285') package() { install -Dm644 "$srcdir/src/install/ssh-cryptsetup" "$pkgdir/usr/lib/initcpio/install/ssh-cryptsetup" diff --git a/README.md b/README.md index 3d4bfef..55bbb81 100644 --- a/README.md +++ b/README.md @@ -64,5 +64,6 @@ For example: 3. Update ChangeLog 4. Update `PKGBUILD` * bump `pkgver` if `src` was modified, or `pkgrel` if building files were modified - * refresh `md5sums` if necessary (based on `md5sum initrd-ssh-cryptsetup-*.tar.xz initrd-ssh-cryptsetup.install` output) + * refresh `sha256sums` with `updpkgsums` if necessary + - or manually, based on `sha256sum initrd-ssh-cryptsetup-*.tar.xz initrd-ssh-cryptsetup.install` output 5. Delete generated archive file if any diff --git a/src/hooks/ssh-cryptsetup b/src/hooks/ssh-cryptsetup index c5b55d7..696d905 100644 --- a/src/hooks/ssh-cryptsetup +++ b/src/hooks/ssh-cryptsetup @@ -1,311 +1,318 @@ #!/usr/bin/ash dbg () { - [ ${sshcs_opt_debug} != 0 ] && echo "$@" + [ ${sshcs_opt_debug} != 0 ] && echo "$@" } sshcs_env_load() { - local debug_default=0 - local timeout_ipconfig_default=10 - local timeout_poweroff_min=120 + local debug_default=0 + local timeout_ipconfig_default=10 + local timeout_poweroff_min=120 + local use_shell_default=0 - [ -e "${sshcs_env}" ] && . "${sshcs_env}" - [ -z "${sshcs_opt_debug}" ] && sshcs_opt_debug=${debug_default} - [ -z "${sshcs_opt_timeout_ipconfig}" ] && sshcs_opt_timeout_ipconfig=${timeout_ipconfig_default} - [ -n "${sshcs_opt_listen}" ] && sshcs_opt_listen="-p ${sshcs_opt_listen}" - [ -z "${sshcs_opt_timeout_poweroff}" ] && sshcs_opt_timeout_poweroff=${timeout_poweroff_min} - [ ${sshcs_opt_timeout_poweroff} -ge 0 ] && [ ${sshcs_opt_timeout_poweroff} -lt ${timeout_poweroff_min} ] && sshcs_opt_timeout_poweroff=${timeout_poweroff_min} + [ -e "${sshcs_env}" ] && . "${sshcs_env}" + [ -z "${sshcs_opt_debug}" ] && sshcs_opt_debug=${debug_default} + [ -z "${sshcs_opt_timeout_ipconfig}" ] && sshcs_opt_timeout_ipconfig=${timeout_ipconfig_default} + [ -n "${sshcs_opt_listen}" ] && sshcs_opt_listen="-p ${sshcs_opt_listen}" + [ -z "${sshcs_opt_timeout_poweroff}" ] && sshcs_opt_timeout_poweroff=${timeout_poweroff_min} + [ -z "${sshcs_opt_use_shell}" ] && sshcs_opt_use_shell=${use_shell_default} + [ ${sshcs_opt_timeout_poweroff} -ge 0 ] && [ ${sshcs_opt_timeout_poweroff} -lt ${timeout_poweroff_min} ] && sshcs_opt_timeout_poweroff=${timeout_poweroff_min} } sshcs_net_start() { - # we must have an 'ip' setting, and a device in it - [ -z "${ip}" ] && [ -n "${nfsaddrs}" ] && ip="${nfsaddrs}" - [ -z "${ip}" ] && { - dbg "No ip setting to setup network" - return 1 - } + # we must have an 'ip' setting, and a device in it + [ -z "${ip}" ] && [ -n "${nfsaddrs}" ] && ip="${nfsaddrs}" + [ -z "${ip}" ] && { + dbg "No ip setting to setup network" + return 1 + } - net_device=$(echo ${ip} | cut -d: -f6) - [ -z "${net_device}" ] && { - dbg "No network device to setup" - return 1 - } + net_device=$(echo ${ip} | cut -d: -f6) + [ -z "${net_device}" ] && { + dbg "No network device to setup" + return 1 + } - # Setup network and save some values - # Note: some useful redirection means ('< <(...)' and '<<< "$(...)"') are - # not supported in the available shell. So we have to write code in a - # temporary file and 'source' it since '... | while read ...' spawns a - # subshell from which outer variables cannot be altered. - : > "${net_env}" + # Setup network and save some values + # Note: some useful redirection means ('< <(...)' and '<<< "$(...)"') are + # not supported in the available shell. So we have to write code in a + # temporary file and 'source' it since '... | while read ...' spawns a + # subshell from which outer variables cannot be altered. + : > "${net_env}" - echo "" - echo "Configuring IP (timeout = ${sshcs_opt_timeout_ipconfig}s) ..." - # ipconfig manual: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/tree/usr/kinit/ipconfig/README.ipconfig - ipconfig_out=$(ipconfig -t "${sshcs_opt_timeout_ipconfig}" "ip=${ip}") - if [ $? -ne 0 ]; then - err "IP configuration timeout!" - echo "Devices probing:" - ipconfig -n -t 5 -c none all - return 1 - fi + echo "" + echo "Configuring IP (timeout = ${sshcs_opt_timeout_ipconfig}s) ..." + # ipconfig manual: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/tree/usr/kinit/ipconfig/README.ipconfig + ipconfig_out=$(ipconfig -t "${sshcs_opt_timeout_ipconfig}" "ip=${ip}") + if [ $? -ne 0 ]; then + err "IP configuration timeout!" + echo "Devices probing:" + ipconfig -n -t 5 -c none all + return 1 + fi - echo -n "${ipconfig_out}" | while read line; do - [ "${line#"IP-Config:"}" != "${line}" ] && continue + echo -n "${ipconfig_out}" | while read line; do + [ "${line#"IP-Config:"}" != "${line}" ] && continue - line="$(echo "${line}" | sed -e 's/ :/:/g;s/: /=/g')" + line="$(echo "${line}" | sed -e 's/ :/:/g;s/: /=/g')" - for iparg in ${line}; do - case "${iparg}" in - address=*|netmask=*|gateway=*|dns0=*|dns1=*) - echo "net_${iparg}" >> "${net_env}" - ;; - esac - done + for iparg in ${line}; do + case "${iparg}" in + address=*|netmask=*|gateway=*|dns0=*|dns1=*) + echo "net_${iparg}" >> "${net_env}" + ;; + esac done + done - . "${net_env}" - rm -f "${net_env}" + . "${net_env}" + rm -f "${net_env}" - echo "IP-Config: device=${net_device} ip=${net_address}/${net_netmask} gw=${net_gateway} dns0=${net_dns0} dns1=${net_dns1}" + echo "IP-Config: device=${net_device} ip=${net_address}/${net_netmask} gw=${net_gateway} dns0=${net_dns0} dns1=${net_dns1}" - [ -n "${net_address}" ] + [ -n "${net_address}" ] } sshcs_net_done() { - # we are done with the network - if [ -n "${net_device}" ]; then - dbg "Setting network device=${net_device} down" - ip addr flush dev "${net_device}" - ip link set dev "${net_device}" down - fi + # we are done with the network + if [ -n "${net_device}" ]; then + dbg "Setting network device=${net_device} down" + ip addr flush dev "${net_device}" + ip link set dev "${net_device}" down + fi } sshcs_trapped_timeout() { - err "Timeout reached! Powering off." - poweroff -f - exit + err "Timeout reached! Powering off." + poweroff -f + exit } sshcs_trap_timeout() { - local pid_init=$$ + local pid_init=$$ - if [ ${sshcs_opt_timeout_poweroff} -gt 0 ]; then - echo "" - echo "WARNING! Automatic poweroff will be triggered in ${sshcs_opt_timeout_poweroff}s" - echo "To deactivate, please unlock devices" - echo "" - trap sshcs_trapped_timeout SIGALRM - ( - sleep ${sshcs_opt_timeout_poweroff} - kill -SIGALRM ${pid_init} - # Signal is not processed if cryptsetup is waiting for the password - killall cryptsetup > /dev/null 2>&1 - ) & - pid_timeout=$! - fi + if [ ${sshcs_opt_timeout_poweroff} -gt 0 ]; then + echo "" + echo "WARNING! Automatic poweroff will be triggered in ${sshcs_opt_timeout_poweroff}s" + echo "To deactivate, please unlock devices" + echo "" + trap sshcs_trapped_timeout SIGALRM + ( + sleep ${sshcs_opt_timeout_poweroff} + kill -SIGALRM ${pid_init} + # Signal is not processed if cryptsetup is waiting for the password + killall cryptsetup > /dev/null 2>&1 + ) & + pid_timeout=$! + fi } sshcs_untrap_timeout() { - [ -z "${pid_timeout}" ] && return 0 - kill ${pid_timeout} - trap - SIGALRM - msg "Timeout cleared." + [ -z "${pid_timeout}" ] && return 0 + kill ${pid_timeout} + trap - SIGALRM + msg "Timeout cleared." } sshcs_unlock() { - sshcs_trap_timeout + sshcs_trap_timeout - # actual script (shared with SSH login) unlocking encrypted devices - . "${sshcs_cryptsetup_script}" + # actual script (shared with SSH login) unlocking encrypted devices + . "${sshcs_cryptsetup_script}" - sshcs_untrap_timeout + sshcs_untrap_timeout } sshcs_dropbear_unlock() { - local pid_timeout= - local dev_pts_mounted=0 - local listen= + local pid_timeout= + local dev_pts_mounted=0 + local listen= - # ensure /dev/pts is present - if [ ! -d "/dev/pts" ]; then - mkdir -p "/dev/pts" - mount -t devpts devpts "/dev/pts" - dev_pts_mounted=1 - fi + # ensure /dev/pts is present + if [ ! -d "/dev/pts" ]; then + mkdir -p "/dev/pts" + mount -t devpts devpts "/dev/pts" + dev_pts_mounted=1 + fi - # /etc/passwd file for the root user - echo "root:x:0:0:root:/root:${dropbear_login_shell}" > "/etc/passwd" - echo "${dropbear_login_shell}" > "/etc/shells" + # /etc/passwd file for the root user + if [ ${sshcs_opt_use_shell} -eq 0 ]; then + echo "root:x:0:0:root:/root:${dropbear_cryptsetup_shell}" > "/etc/passwd" + echo "${dropbear_cryptsetup_shell}" > "/etc/shells" + else + echo "root:x:0:0:root:/root:/usr/bin/ash" > "/etc/passwd" + fi - # root login script - cat < "${dropbear_login_shell}" + # root login script + cat < "${dropbear_cryptsetup_shell}" #!/usr/bin/ash . "/init_functions" if [ ! -f "${sshcs_cryptsetup_script}" ]; then - err "No cryptsetup script present! Please retry." - exit 0 + err "No cryptsetup script present! Please retry." + exit 0 fi if [ -c "/dev/mapper/control" ]; then - CSQUIET= - . "${sshcs_cryptsetup_script}" + CSQUIET= + . "${sshcs_cryptsetup_script}" - echo "" - echo "cryptsetup succeeded! Boot sequence should go on." - echo "Please wait and retry for standard SSH service." + echo "" + echo "cryptsetup succeeded! Boot sequence should go on." + echo "Please wait and retry for standard SSH service." else - err "Device resources missing! Please retry." + err "Device resources missing! Please retry." fi echo "" EOF - chmod a+x "${dropbear_login_shell}" + chmod a+x "${dropbear_cryptsetup_shell}" - [ ! -d "/var/log" ] && mkdir -p "/var/log" - touch "/var/log/lastlog" + [ ! -d "/var/log" ] && mkdir -p "/var/log" + touch "/var/log/lastlog" - msg "Starting dropbear ..." - dropbear -Esgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen} + msg "Starting dropbear ..." + dropbear -Esgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen} - # Actual unlocking - sshcs_unlock + # Actual unlocking + sshcs_unlock - # cleanup dropbear - if [ -f "${path_dropbear_pid}" ]; then - msg "Stopping dropbear ..." - kill $(cat "${path_dropbear_pid}") - rm -f "${path_dropbear_pid}" - fi - rm -f "${sshcs_cryptsetup_script}" "${dropbear_login_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog" + # cleanup dropbear + if [ -f "${path_dropbear_pid}" ]; then + msg "Stopping dropbear ..." + kill $(cat "${path_dropbear_pid}") + rm -f "${path_dropbear_pid}" + fi + rm -f "${sshcs_cryptsetup_script}" "${dropbear_cryptsetup_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog" - # cleanup /dev/pts if necessary - if [ ${dev_pts_mounted} -ne 0 ]; then - umount "/dev/pts" - rm -R "/dev/pts" - fi + # cleanup /dev/pts if necessary + if [ ${dev_pts_mounted} -ne 0 ]; then + umount "/dev/pts" + rm -R "/dev/pts" + fi } sshcs_cryptpart_process() { - # ensure there is a device (handle 'UUID=' format) - [ -z "${cryptdev}" ] && return 0 - [ "${cryptdev#UUID=}" != "${cryptdev}" ] && cryptdev="/dev/disk/by-uuid/${cryptdev#UUID=}" + # ensure there is a device (handle 'UUID=' format) + [ -z "${cryptdev}" ] && return 0 + [ "${cryptdev#UUID=}" != "${cryptdev}" ] && cryptdev="/dev/disk/by-uuid/${cryptdev#UUID=}" - # get crypt options - cryptargs= - for cryptopt in ${cryptoptions//,/ }; do - case ${cryptopt} in - discard) - cryptargs="${cryptargs} --allow-discards" - ;; + # get crypt options + cryptargs= + for cryptopt in ${cryptoptions//,/ }; do + case ${cryptopt} in + discard) + cryptargs="${cryptargs} --allow-discards" + ;; - luks) - ;; + luks) + ;; - *) - echo "Device ${cryptdev} encryption option '${cryptopt}' not known, ignoring." - ;; - esac - done + *) + echo "Device ${cryptdev} encryption option '${cryptopt}' not known, ignoring." + ;; + esac + done - # ensure device is encrypted and handled - cryptdev_orig=${cryptdev} - if cryptdev=$(resolve_device "${cryptdev_orig}" ${rootdelay}); then - if cryptsetup isLuks "${cryptdev}" >/dev/null 2>&1; then - dbg "Adding crypt device=${cryptdev} type=${crypttype} name=${cryptname} args=<${cryptargs}> in setup script" + # ensure device is encrypted and handled + cryptdev_orig=${cryptdev} + if cryptdev=$(resolve_device "${cryptdev_orig}" ${rootdelay}); then + if cryptsetup isLuks "${cryptdev}" >/dev/null 2>&1; then + dbg "Adding crypt device=${cryptdev} type=${crypttype} name=${cryptname} args=<${cryptargs}> in setup script" - # update script used to unlock device either in console or SSH - [ -s "${sshcs_cryptsetup_script}" ] || cat < "${sshcs_cryptsetup_script}" + # update script used to unlock device either in console or SSH + [ -s "${sshcs_cryptsetup_script}" ] || cat < "${sshcs_cryptsetup_script}" cycle_or_retry() { - local res + local res - read -n 1 -s -t 5 -p "Whithin 5s press 'P' to poweroff, 'R' to reboot or any other key to retry. " res - echo "" - if [ "\${res}" = "P" ]; then - poweroff -f - elif [ "\${res}" = "R" ]; then - reboot -f - fi + read -n 1 -s -t 5 -p "Whithin 5s press 'P' to poweroff, 'R' to reboot or any other key to retry. " res + echo "" + if [ "\${res}" = "P" ]; then + poweroff -f + elif [ "\${res}" = "R" ]; then + reboot -f + fi } EOF - cat <> "${sshcs_cryptsetup_script}" + cat <> "${sshcs_cryptsetup_script}" # loop until device is available while [ ! -e "/dev/mapper/${cryptname}" ]; do - if cryptsetup open --type "${crypttype}" "${cryptdev}" "${cryptname}" ${cryptargs} "\${CSQUIET}"; then - if poll_device "/dev/mapper/${cryptname}" ${rootdelay}; then - killall cryptsetup > /dev/null 2>&1 - break - fi - err "Device still not mapped! Please wait or retry." - elif [ ! -e "/dev/mapper/${cryptname}" ]; then - err "cryptsetup failed! Please retry." - else - break + if cryptsetup open --type "${crypttype}" "${cryptdev}" "${cryptname}" ${cryptargs} "\${CSQUIET}"; then + if poll_device "/dev/mapper/${cryptname}" ${rootdelay}; then + killall cryptsetup > /dev/null 2>&1 + break fi + err "Device still not mapped! Please wait or retry." + elif [ ! -e "/dev/mapper/${cryptname}" ]; then + err "cryptsetup failed! Please retry." + else + break + fi - cycle_or_retry + cycle_or_retry done EOF - else - err "Failed to manage encrypted device ${cryptdev_orig}: not a LUKS volume." - fi + else + err "Failed to manage encrypted device ${cryptdev_orig}: not a LUKS volume." fi + fi } run_hook() { - local etc_crypttab="/etc/crypttab" - local sshcs_env="/etc/initcpio/sshcs_env" - local path_dropbear_pid="/.dropbear.pid" - local dropbear_login_shell="/.cryptsetup_shell.sh" - local sshcs_cryptsetup_script="/.cryptsetup_script.sh" - local net_env="/.net_env.sh" - local line iparg net_address net_device ipconfig_out net_netmask net_gateway net_dns0 net_dns1 - local cryptdev cryptdev_orig crypttype cryptname cryptpass cryptoptions cryptopt cryptargs CSQUIET + local etc_crypttab="/etc/crypttab" + local sshcs_env="/etc/initcpio/sshcs_env" + local path_dropbear_pid="/.dropbear.pid" + local dropbear_cryptsetup_shell="/.cryptsetup_shell.sh" + local sshcs_cryptsetup_script="/.cryptsetup_script.sh" + local net_env="/.net_env.sh" + local line iparg net_address net_device ipconfig_out net_netmask net_gateway net_dns0 net_dns1 + local cryptdev cryptdev_orig crypttype cryptname cryptpass cryptoptions cryptopt cryptargs CSQUIET - # Load our options - sshcs_env_load + # Load our options + sshcs_env_load - # sanity check: crypttab should be present - [ ! -e "${etc_crypttab}" ] && { - dbg "No crypttab configuration to process" - return 0 - } + # sanity check: crypttab should be present + [ ! -e "${etc_crypttab}" ] && { + dbg "No crypttab configuration to process" + return 0 + } - modprobe -a -q dm-crypt >/dev/null 2>&1 - [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" + modprobe -a -q dm-crypt >/dev/null 2>&1 + [ "${quiet}" = "y" ] && CSQUIET=">/dev/null" - umask 0022 + umask 0022 - # check encrypted devices to handle - cryptdev= - crypttype=luks - while read cryptname cryptdev cryptpass cryptoptions; do - # skip comment lines - [ "${cryptname:0:1}" = "#" ] && continue - # skip devices with given password - [ -n "${cryptpass}" ] && [ "${cryptpass}" != "none" ] && [ "${cryptpass}" != "-" ] && continue + # check encrypted devices to handle + cryptdev= + crypttype=luks + while read cryptname cryptdev cryptpass cryptoptions; do + # skip comment lines + [ "${cryptname:0:1}" = "#" ] && continue + # skip devices with given password + [ -n "${cryptpass}" ] && [ "${cryptpass}" != "none" ] && [ "${cryptpass}" != "-" ] && continue - sshcs_cryptpart_process - done < "${etc_crypttab}" + sshcs_cryptpart_process + done < "${etc_crypttab}" - if [ ! -e "${sshcs_cryptsetup_script}" ]; then - err "No encrypted device found! Skipping crypt remote unlocking." - return 0 - fi + if [ ! -e "${sshcs_cryptsetup_script}" ]; then + err "No encrypted device found! Skipping crypt remote unlocking." + return 0 + fi - # start and check network - if ! sshcs_net_start; then - err "Net interface not available! Skipping crypt remote unlocking." - # We still allow to unlock locally with timeout - sshcs_unlock - # stop the network if possible - sshcs_net_done - return 0 - fi - - # time to unlock (through console or dropbear) - sshcs_dropbear_unlock - # stop the network before going on in boot sequence + # start and check network + if ! sshcs_net_start; then + err "Net interface not available! Skipping crypt remote unlocking." + # We still allow to unlock locally with timeout + sshcs_unlock + # stop the network if possible sshcs_net_done + return 0 + fi + + # time to unlock (through console or dropbear) + sshcs_dropbear_unlock + # stop the network before going on in boot sequence + sshcs_net_done } + diff --git a/src/install/ssh-cryptsetup b/src/install/ssh-cryptsetup index dd32577..bad6031 100644 --- a/src/install/ssh-cryptsetup +++ b/src/install/ssh-cryptsetup @@ -1,109 +1,110 @@ #!/bin/bash sshcs_check_nonempty() { - local filepath="$1" + local filepath="$1" - [ -e "${filepath}" ] && grep -q -v '^\s*\(#\|$\)' "${filepath}" + [ -e "${filepath}" ] && grep -q -v '^\s*\(#\|$\)' "${filepath}" } sshcs_check_keys() { - local dropbear_keyfile - local openssh_keyfile - local fingerprint + local dropbear_keyfile + local openssh_keyfile + local fingerprint - for keytype in "${dropbear_key_types[@]}"; do - dropbear_keyfile=${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix} - openssh_keyfile=${openssh_keyfile_prefix}${keytype}${openssh_keyfile_suffix} + for keytype in "${dropbear_key_types[@]}"; do + dropbear_keyfile=${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix} + openssh_keyfile=${openssh_keyfile_prefix}${keytype}${openssh_keyfile_suffix} - # Prefer OpenSSH keys, or generate missing ones - if [ -e "${openssh_keyfile}" ]; then - #echo "Copying OpenSSH ${keytype} host key for dropbear ..." - dropbearconvert openssh dropbear "${openssh_keyfile}" "${dropbear_keyfile}" > /dev/null 2>&1 - elif [ ! -e "${dropbear_keyfile}" ]; then - #echo "Generating ${keytype} host key for dropbear ..." - dropbearkey -t "${keytype}" -f "${dropbear_keyfile}" > /dev/null 2>&1 - fi - fingerprint=$(dropbearkey -y -f "${dropbear_keyfile}" | sed -n '/^Fingerprint:/ {s/Fingerprint: *//; p}') - echo "$(basename "${dropbear_keyfile}") : ${fingerprint}" - done + # Prefer OpenSSH keys, or generate missing ones + if [ -e "${openssh_keyfile}" ]; then + #echo "Copying OpenSSH ${keytype} host key for dropbear ..." + dropbearconvert openssh dropbear "${openssh_keyfile}" "${dropbear_keyfile}" > /dev/null 2>&1 + elif [ ! -e "${dropbear_keyfile}" ]; then + #echo "Generating ${keytype} host key for dropbear ..." + dropbearkey -t "${keytype}" -f "${dropbear_keyfile}" > /dev/null 2>&1 + fi + fingerprint=$(dropbearkey -y -f "${dropbear_keyfile}" | sed -n '/^Fingerprint:/ {s/Fingerprint: *//; p}') + echo "$(basename "${dropbear_keyfile}") : ${fingerprint}" + done } build() { - local etc_crypttab="/etc/crypttab" - local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys" - local sshcs_env="/etc/initcpio/sshcs_env" - local dropbear_key_types=( "rsa" "ecdsa" "ed25519" ) - local dropbear_keyfile_prefix="/etc/dropbear/dropbear_" - local dropbear_keyfile_suffix="_host_key" - local openssh_keyfile_prefix="/etc/ssh/ssh_host_" - local openssh_keyfile_suffix="_key" + local etc_crypttab="/etc/crypttab" + local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys" + local sshcs_env="/etc/initcpio/sshcs_env" + local dropbear_key_types=( "rsa" "ecdsa" "ed25519" ) + local dropbear_keyfile_prefix="/etc/dropbear/dropbear_" + local dropbear_keyfile_suffix="_host_key" + local openssh_keyfile_prefix="/etc/ssh/ssh_host_" + local openssh_keyfile_suffix="_key" - # Check we are needed - if ! sshcs_check_nonempty "${dropbear_authorized_keys}"; then - echo "There is no root key(s) in ${dropbear_authorized_keys}. Skipping." - return 0 - fi - if ! sshcs_check_nonempty "${etc_crypttab}"; then - echo "There is no device in ${etc_crypttab}. Skipping." - return 0 - fi + # Check we are needed + if ! sshcs_check_nonempty "${dropbear_authorized_keys}"; then + echo "There is no root key(s) in ${dropbear_authorized_keys}. Skipping." + return 0 + fi + if ! sshcs_check_nonempty "${etc_crypttab}"; then + echo "There is no device in ${etc_crypttab}. Skipping." + return 0 + fi - umask 0022 + umask 0022 - sshcs_check_keys + sshcs_check_keys - add_checked_modules "/drivers/net/" - # Note: parts of this script (modules/binaries added) are the same than the - # 'encrypt' install script (/usr/lib/initcpio/install/encrypt) which is the - # nominal one to deal with encrypted volumes at boot time. - add_module dm-crypt - # Note: crypto modules are necessary - if [ -n "${CRYPTO_MODULES}" ]; then - local mod - for mod in ${CRYPTO_MODULES}; do - add_module "${mod}" - done - else - add_all_modules "/crypto/" - fi - - # Note: dmsetup is necessary for device mapper features - add_binary "cryptsetup" - add_binary "dmsetup" - add_binary "dropbear" - add_binary "ip" - add_binary "/usr/lib/initcpio/ipconfig" "/sbin/ipconfig" - - # Our hook files - [ -e "${sshcs_env}" ] && add_file "${sshcs_env}" - - # auth-related files - add_file "/lib/libnss_files.so" - - # SSH-related files - add_file "${dropbear_authorized_keys}" "/root/.ssh/authorized_keys" - for keytype in "${dropbear_key_types[@]}"; do - add_file "${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix}" + add_checked_modules "/drivers/net/" + # Note: parts of this script (modules/binaries added) are the same than the + # 'encrypt' install script (/usr/lib/initcpio/install/encrypt) which is the + # nominal one to deal with encrypted volumes at boot time. + add_module dm-crypt + # Note: crypto modules are necessary + if [ -n "${CRYPTO_MODULES}" ]; then + local mod + for mod in ${CRYPTO_MODULES}; do + add_module "${mod}" done + else + add_all_modules "/crypto/" + fi - # cryptsetup-related files - add_file "${etc_crypttab}" - add_file "/usr/lib/udev/rules.d/10-dm.rules" - add_file "/usr/lib/udev/rules.d/13-dm-disk.rules" - add_file "/usr/lib/udev/rules.d/95-dm-notify.rules" - add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules" + # Note: dmsetup is necessary for device mapper features + add_binary "cryptsetup" + add_binary "dmsetup" + add_binary "dropbear" + add_binary "ip" + add_binary "/usr/lib/initcpio/ipconfig" "/bin/ipconfig" + add_binary "ethtool" - # At least with LUKS v2 volumes, cryptsetup calls pthread_cancel(), which - # dlopen()s libgcc_s.so.1. - # See the nominal 'encrypt' module, and similar/related bug reports (e.g. - # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=950254). - add_binary "/usr/lib/libgcc_s.so.1" + # Our hook files + [ -e "${sshcs_env}" ] && add_file "${sshcs_env}" - add_runscript + # auth-related files + add_file "/lib/libnss_files.so" + + # SSH-related files + add_file "${dropbear_authorized_keys}" "/root/.ssh/authorized_keys" + for keytype in "${dropbear_key_types[@]}"; do + add_file "${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix}" + done + + # cryptsetup-related files + add_file "${etc_crypttab}" + add_file "/usr/lib/udev/rules.d/10-dm.rules" + add_file "/usr/lib/udev/rules.d/13-dm-disk.rules" + add_file "/usr/lib/udev/rules.d/95-dm-notify.rules" + add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules" + + # At least with LUKS v2 volumes, cryptsetup calls pthread_cancel(), which + # dlopen()s libgcc_s.so.1. + # See the nominal 'encrypt' module, and similar/related bug reports (e.g. + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=950254). + add_binary "/usr/lib/libgcc_s.so.1" + + add_runscript } help() { - cat <