diff --git a/PKGBUILD b/PKGBUILD index 869e45f..3e81136 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Julien Coloos pkgname=initrd-ssh-cryptsetup -pkgver=0.2 +pkgver=0.3 pkgrel=1 pkgdesc="Allows for LUKS-encrypted devices to be unlocked remotely over SSH" arch=('any') @@ -10,8 +10,8 @@ depends=('dropbear' 'cryptsetup' 'mkinitcpio-nfs-utils' 'iproute2') install=$pkgname.install changelog='ChangeLog' source=("http://julien.coloos.free.fr/archlinux/$pkgname-$pkgver.tar.xz" "$pkgname.install") -md5sums=('27b040fd69d252050c20a2595f8c67ba' - 'a703663472bbd50882a11f6b2cfccbf0') +md5sums=('a25dbbac5cd82a8d87932e646e38d9c4' + 'ac60109d80e7bb2af0d66e69aaf178a6') package() { install -Dm644 "$srcdir/src/install/ssh-cryptsetup" "$pkgdir/usr/lib/initcpio/install/ssh-cryptsetup" diff --git a/README.md b/README.md index 926f45a..3a85873 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ As explained upon installation, the following things need to be done: The LUKS-encrypted devices to unlock are derived from `/etc/crypttab`. -Some options can be set in `/etc/dropbear/initrd.env` (file is sourced in initrd shell): +Some options can be set in `/etc/initcpio/sshcs_env` (file is sourced in initrd shell): + * `sshcs_opt_timeout_ipconfig`: time (in seconds) to configure IP + - default: 10 seconds * `sshcs_opt_listen`: SSH listening port - default: 22 * `sshcs_opt_timeout_poweroff`: time (in seconds) to unlock devices before automatic powering off @@ -24,6 +26,7 @@ Some options can be set in `/etc/dropbear/initrd.env` (file is sourced in initrd For example: + sshcs_opt_timeout_ipconfig=30 sshcs_opt_listen=2222 sshcs_opt_timeout_poweroff=-1 diff --git a/initrd-ssh-cryptsetup.install b/initrd-ssh-cryptsetup.install index cf21d41..27b9f2f 100644 --- a/initrd-ssh-cryptsetup.install +++ b/initrd-ssh-cryptsetup.install @@ -1,8 +1,17 @@ #!/bin/bash post_install() { + local sshcs_env="/etc/initcpio/sshcs_env" + local sshcs_env_old="/etc/dropbear/initrd.env" local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys" local etc_dropbear=$(dirname "${dropbear_authorized_keys}") + [ ! -e "${sshcs_env}" ] && [ -e "${sshcs_env_old}" ] && { + [ -d $(dirname "${sshcs_env}") ] || mkdir -p $(dirname "${sshcs_env}") + mv "${sshcs_env_old}" "${sshcs_env}" + cat < "${net_env}" - ipconfig "ip=${ip}" | while read line; do + + echo "" + echo "Configuring IP (timeout = ${sshcs_opt_timeout_ipconfig}s) ..." + ipconfig_out=$(ipconfig -t "${sshcs_opt_timeout_ipconfig}" "ip=${ip}") + if [ $? -ne 0 ]; then + err "IP configuration timeout!" + return 1 + fi + + echo -n "${ipconfig_out}" | while read line; do [ "${line#"IP-Config:"}" != "${line}" ] && continue line="$(echo "${line}" | sed -e 's/ :/:/g;s/: /=/g')" @@ -36,6 +56,14 @@ sshcs_net_start() { [ -n "${net_address}" ] } +sshcs_net_done() { + # we are done with the network + if [ -n "${net_device}" ]; then + ip addr flush dev "${net_device}" + ip link set dev "${net_device}" down + fi +} + sshcs_trapped_timeout() { err "Timeout reached! Powering off." poweroff -f @@ -68,8 +96,16 @@ sshcs_untrap_timeout() { msg "Timeout cleared." } +sshcs_unlock() { + sshcs_trap_timeout + + # actual script (shared with SSH login) unlocking encrypted devices + . "${sshcs_cryptsetup_script}" + + sshcs_untrap_timeout +} + sshcs_dropbear_unlock() { - local timeout_poweroff_min=120 local pid_timeout= local dev_pts_mounted=0 local listen= @@ -91,14 +127,14 @@ sshcs_dropbear_unlock() { . "/init_functions" -if [ ! -f "${dropbear_cryptsetup_script}" ]; then +if [ ! -f "${sshcs_cryptsetup_script}" ]; then err "No cryptsetup script present! Please retry." exit 0 fi if [ -c "/dev/mapper/control" ]; then CSQUIET= - . "${dropbear_cryptsetup_script}" + . "${sshcs_cryptsetup_script}" echo "" echo "cryptsetup succeeded! Boot sequence should go on." @@ -113,21 +149,11 @@ EOF [ ! -d "/var/log" ] && mkdir -p "/var/log" touch "/var/log/lastlog" - [ -e "${dropbear_env}" ] && . "${dropbear_env}" - [ -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} - - msg "Starting dropbear ..." dropbear -Emsgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen} - sshcs_trap_timeout - - # actual script (shared with SSH login) unlocking encrypted devices - . "${dropbear_cryptsetup_script}" - - sshcs_untrap_timeout + # Actual unlocking + sshcs_unlock # cleanup dropbear if [ -f "${path_dropbear_pid}" ]; then @@ -135,7 +161,7 @@ EOF kill $(cat "${path_dropbear_pid}") rm -f "${path_dropbear_pid}" fi - rm -f "${dropbear_cryptsetup_script}" "${dropbear_login_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog" + rm -f "${sshcs_cryptsetup_script}" "${dropbear_login_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog" # cleanup /dev/pts if necessary if [ ${dev_pts_mounted} -ne 0 ]; then @@ -144,14 +170,6 @@ EOF fi } -sshcs_net_done() { - # we are done with the network - if [ -n "${net_device}" ]; then - ip addr flush dev "${net_device}" - ip link set dev "${net_device}" down - fi -} - sshcs_cryptpart_process() { # ensure there is a device (handle 'UUID=' format) [ -z "${cryptdev}" ] && return 0 @@ -180,7 +198,7 @@ sshcs_cryptpart_process() { if cryptsetup isLuks "${cryptdev}" >/dev/null 2>&1; then # update script used to unlock device either in console or SSH - [ -s "${dropbear_cryptsetup_script}" ] || cat < "${dropbear_cryptsetup_script}" + [ -s "${sshcs_cryptsetup_script}" ] || cat < "${sshcs_cryptsetup_script}" cycle_or_retry() { local res @@ -194,7 +212,7 @@ cycle_or_retry() { } EOF - cat <> "${dropbear_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 @@ -220,14 +238,17 @@ EOF run_hook() { local etc_crypttab="/etc/crypttab" - local dropbear_env="/etc/dropbear/initrd.env" + local sshcs_env="/etc/initcpio/sshcs_env" local path_dropbear_pid="/.dropbear.pid" local dropbear_login_shell="/.cryptsetup_shell.sh" - local dropbear_cryptsetup_script="/.cryptsetup_script.sh" + local sshcs_cryptsetup_script="/.cryptsetup_script.sh" local net_env="/.net_env.sh" - local line iparg net_address net_netmask net_gateway net_dns0 net_dns1 + 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 + # sanity check: crypttab should be present [ ! -e "${etc_crypttab}" ] && return 0 @@ -236,14 +257,6 @@ run_hook() { umask 0022 - # start and check network - if ! sshcs_net_start; then - err "Net interface not available! Skipping crypt remote unlocking." - # stop the network if possible - sshcs_net_done - return 0 - fi - # check encrypted devices to handle cryptdev= crypttype=luks @@ -256,9 +269,17 @@ run_hook() { sshcs_cryptpart_process done < "${etc_crypttab}" - if [ ! -e "${dropbear_cryptsetup_script}" ]; then + if [ ! -e "${sshcs_cryptsetup_script}" ]; then err "No encrypted device found! Skipping crypt remote unlocking." - # don't forget to stop the network + 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 diff --git a/src/install/ssh-cryptsetup b/src/install/ssh-cryptsetup index 59cc929..28d7fd4 100644 --- a/src/install/ssh-cryptsetup +++ b/src/install/ssh-cryptsetup @@ -31,7 +31,7 @@ sshcs_check_keys() { build() { local etc_crypttab="/etc/crypttab" local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys" - local dropbear_env="/etc/dropbear/initrd.env" + local sshcs_env="/etc/initcpio/sshcs_env" local dropbear_key_types=( "dss" "rsa" "ecdsa" ) local dropbear_keyfile_prefix="/etc/dropbear/dropbear_" local dropbear_keyfile_suffix="_host_key" @@ -71,12 +71,14 @@ build() { 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" - [ -e "${dropbear_env}" ] && add_file "${dropbear_env}" add_file "/etc/dropbear/dropbear_rsa_host_key" add_file "/etc/dropbear/dropbear_dss_host_key" add_file "/etc/dropbear/dropbear_ecdsa_host_key" @@ -101,8 +103,10 @@ Network is configured with 'ip=' kernel parameter (see 'mkinitcpio-nfs-utils'). Authorized SSH key(s) must be present in '/etc/dropbear/initrd.authorized_keys'. LUKS encrypted devices to unlock are derived from '/etc/crypttab', which must be present. -Some options can be set in '/etc/dropbear/initrd.env' (file is sourced in +Some options can be set in '/etc/initcpio/sshcs_env' (file is sourced in initrd shell): + * 'sshcs_opt_timeout_ipconfig': time (s) to configure IP + - default: 10 seconds * 'sshcs_opt_listen': listening port (22 by default) * 'sshcs_opt_timeout_poweroff': time (s) to unlock devices before automatic powering off