Use SHA256 checksums instead of MD5

v0.9-2
0.9-2
Julien Coloos 2021-11-12 18:03:46 +01:00
parent c3cafcf6cd
commit 3449995d4a
5 changed files with 327 additions and 304 deletions

View File

@ -1,3 +1,16 @@
2021-11-12 Julien Coloos <julien.coloos [at] gmail [dot] com>
* 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 <julien.coloos [at] gmail [dot] com>
* v0.9-2
Use SHA256 checksums instead of MD5
2021-10-24 Julien Coloos <julien.coloos [at] gmail [dot] com> 2021-10-24 Julien Coloos <julien.coloos [at] gmail [dot] com>
* v0.9-1 * v0.9-1

View File

@ -1,17 +1,17 @@
# Maintainer: Julien Coloos <julien.coloos [at] gmail [dot] com> # Maintainer: Julien Coloos <julien.coloos [at] gmail [dot] com>
pkgname=initrd-ssh-cryptsetup pkgname=initrd-ssh-cryptsetup
pkgver=0.9 pkgver=0.10
pkgrel=1 pkgrel=1
pkgdesc="Allows for LUKS-encrypted devices to be unlocked remotely over SSH" pkgdesc="Allows for LUKS-encrypted devices to be unlocked remotely over SSH"
arch=('any') arch=('any')
url="https://github.com/suiryc/archlinux-$pkgname" url="https://github.com/suiryc/archlinux-$pkgname"
license=('GPL3') license=('GPL3')
depends=('dropbear' 'cryptsetup' 'mkinitcpio-nfs-utils' 'iproute2') depends=('dropbear' 'cryptsetup' 'mkinitcpio-nfs-utils' 'iproute2' 'ethtool')
install=$pkgname.install install=$pkgname.install
changelog='ChangeLog' changelog='ChangeLog'
source=("http://julien.coloos.free.fr/archlinux/$pkgname-$pkgver.tar.xz" "$pkgname.install") source=("http://julien.coloos.free.fr/archlinux/$pkgname-$pkgver.tar.xz" "$pkgname.install")
md5sums=('c94a905ca91f7afe2c0f771bd5182cb2' sha256sums=('c3fa91fc8ba2228b3492d3709231918c8015cc3da49f516c3eacea5c0217536c'
'ac60109d80e7bb2af0d66e69aaf178a6') 'b84978b3c2ef32208c2b104ee2d3ce8aaec26da0bd4e9e1c83942f373bbf6285')
package() { package() {
install -Dm644 "$srcdir/src/install/ssh-cryptsetup" "$pkgdir/usr/lib/initcpio/install/ssh-cryptsetup" install -Dm644 "$srcdir/src/install/ssh-cryptsetup" "$pkgdir/usr/lib/initcpio/install/ssh-cryptsetup"

View File

@ -64,5 +64,6 @@ For example:
3. Update ChangeLog 3. Update ChangeLog
4. Update `PKGBUILD` 4. Update `PKGBUILD`
* bump `pkgver` if `src` was modified, or `pkgrel` if building files were modified * 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 5. Delete generated archive file if any

View File

@ -1,311 +1,318 @@
#!/usr/bin/ash #!/usr/bin/ash
dbg () { dbg () {
[ ${sshcs_opt_debug} != 0 ] && echo "$@" [ ${sshcs_opt_debug} != 0 ] && echo "$@"
} }
sshcs_env_load() { sshcs_env_load() {
local debug_default=0 local debug_default=0
local timeout_ipconfig_default=10 local timeout_ipconfig_default=10
local timeout_poweroff_min=120 local timeout_poweroff_min=120
local use_shell_default=0
[ -e "${sshcs_env}" ] && . "${sshcs_env}" [ -e "${sshcs_env}" ] && . "${sshcs_env}"
[ -z "${sshcs_opt_debug}" ] && sshcs_opt_debug=${debug_default} [ -z "${sshcs_opt_debug}" ] && sshcs_opt_debug=${debug_default}
[ -z "${sshcs_opt_timeout_ipconfig}" ] && sshcs_opt_timeout_ipconfig=${timeout_ipconfig_default} [ -z "${sshcs_opt_timeout_ipconfig}" ] && sshcs_opt_timeout_ipconfig=${timeout_ipconfig_default}
[ -n "${sshcs_opt_listen}" ] && sshcs_opt_listen="-p ${sshcs_opt_listen}" [ -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_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} [ -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() { sshcs_net_start() {
# we must have an 'ip' setting, and a device in it # we must have an 'ip' setting, and a device in it
[ -z "${ip}" ] && [ -n "${nfsaddrs}" ] && ip="${nfsaddrs}" [ -z "${ip}" ] && [ -n "${nfsaddrs}" ] && ip="${nfsaddrs}"
[ -z "${ip}" ] && { [ -z "${ip}" ] && {
dbg "No ip setting to setup network" dbg "No ip setting to setup network"
return 1 return 1
} }
net_device=$(echo ${ip} | cut -d: -f6) net_device=$(echo ${ip} | cut -d: -f6)
[ -z "${net_device}" ] && { [ -z "${net_device}" ] && {
dbg "No network device to setup" dbg "No network device to setup"
return 1 return 1
} }
# Setup network and save some values # Setup network and save some values
# Note: some useful redirection means ('< <(...)' and '<<< "$(...)"') are # Note: some useful redirection means ('< <(...)' and '<<< "$(...)"') are
# not supported in the available shell. So we have to write code in a # not supported in the available shell. So we have to write code in a
# temporary file and 'source' it since '... | while read ...' spawns a # temporary file and 'source' it since '... | while read ...' spawns a
# subshell from which outer variables cannot be altered. # subshell from which outer variables cannot be altered.
: > "${net_env}" : > "${net_env}"
echo "" echo ""
echo "Configuring IP (timeout = ${sshcs_opt_timeout_ipconfig}s) ..." 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 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}") ipconfig_out=$(ipconfig -t "${sshcs_opt_timeout_ipconfig}" "ip=${ip}")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
err "IP configuration timeout!" err "IP configuration timeout!"
echo "Devices probing:" echo "Devices probing:"
ipconfig -n -t 5 -c none all ipconfig -n -t 5 -c none all
return 1 return 1
fi fi
echo -n "${ipconfig_out}" | while read line; do echo -n "${ipconfig_out}" | while read line; do
[ "${line#"IP-Config:"}" != "${line}" ] && continue [ "${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 for iparg in ${line}; do
case "${iparg}" in case "${iparg}" in
address=*|netmask=*|gateway=*|dns0=*|dns1=*) address=*|netmask=*|gateway=*|dns0=*|dns1=*)
echo "net_${iparg}" >> "${net_env}" echo "net_${iparg}" >> "${net_env}"
;; ;;
esac esac
done
done done
done
. "${net_env}" . "${net_env}"
rm -f "${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() { sshcs_net_done() {
# we are done with the network # we are done with the network
if [ -n "${net_device}" ]; then if [ -n "${net_device}" ]; then
dbg "Setting network device=${net_device} down" dbg "Setting network device=${net_device} down"
ip addr flush dev "${net_device}" ip addr flush dev "${net_device}"
ip link set dev "${net_device}" down ip link set dev "${net_device}" down
fi fi
} }
sshcs_trapped_timeout() { sshcs_trapped_timeout() {
err "Timeout reached! Powering off." err "Timeout reached! Powering off."
poweroff -f poweroff -f
exit exit
} }
sshcs_trap_timeout() { sshcs_trap_timeout() {
local pid_init=$$ local pid_init=$$
if [ ${sshcs_opt_timeout_poweroff} -gt 0 ]; then if [ ${sshcs_opt_timeout_poweroff} -gt 0 ]; then
echo "" echo ""
echo "WARNING! Automatic poweroff will be triggered in ${sshcs_opt_timeout_poweroff}s" echo "WARNING! Automatic poweroff will be triggered in ${sshcs_opt_timeout_poweroff}s"
echo "To deactivate, please unlock devices" echo "To deactivate, please unlock devices"
echo "" echo ""
trap sshcs_trapped_timeout SIGALRM trap sshcs_trapped_timeout SIGALRM
( (
sleep ${sshcs_opt_timeout_poweroff} sleep ${sshcs_opt_timeout_poweroff}
kill -SIGALRM ${pid_init} kill -SIGALRM ${pid_init}
# Signal is not processed if cryptsetup is waiting for the password # Signal is not processed if cryptsetup is waiting for the password
killall cryptsetup > /dev/null 2>&1 killall cryptsetup > /dev/null 2>&1
) & ) &
pid_timeout=$! pid_timeout=$!
fi fi
} }
sshcs_untrap_timeout() { sshcs_untrap_timeout() {
[ -z "${pid_timeout}" ] && return 0 [ -z "${pid_timeout}" ] && return 0
kill ${pid_timeout} kill ${pid_timeout}
trap - SIGALRM trap - SIGALRM
msg "Timeout cleared." msg "Timeout cleared."
} }
sshcs_unlock() { sshcs_unlock() {
sshcs_trap_timeout sshcs_trap_timeout
# actual script (shared with SSH login) unlocking encrypted devices # actual script (shared with SSH login) unlocking encrypted devices
. "${sshcs_cryptsetup_script}" . "${sshcs_cryptsetup_script}"
sshcs_untrap_timeout sshcs_untrap_timeout
} }
sshcs_dropbear_unlock() { sshcs_dropbear_unlock() {
local pid_timeout= local pid_timeout=
local dev_pts_mounted=0 local dev_pts_mounted=0
local listen= local listen=
# ensure /dev/pts is present # ensure /dev/pts is present
if [ ! -d "/dev/pts" ]; then if [ ! -d "/dev/pts" ]; then
mkdir -p "/dev/pts" mkdir -p "/dev/pts"
mount -t devpts devpts "/dev/pts" mount -t devpts devpts "/dev/pts"
dev_pts_mounted=1 dev_pts_mounted=1
fi fi
# /etc/passwd file for the root user # /etc/passwd file for the root user
echo "root:x:0:0:root:/root:${dropbear_login_shell}" > "/etc/passwd" if [ ${sshcs_opt_use_shell} -eq 0 ]; then
echo "${dropbear_login_shell}" > "/etc/shells" 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 # root login script
cat <<EOF > "${dropbear_login_shell}" cat <<EOF > "${dropbear_cryptsetup_shell}"
#!/usr/bin/ash #!/usr/bin/ash
. "/init_functions" . "/init_functions"
if [ ! -f "${sshcs_cryptsetup_script}" ]; then if [ ! -f "${sshcs_cryptsetup_script}" ]; then
err "No cryptsetup script present! Please retry." err "No cryptsetup script present! Please retry."
exit 0 exit 0
fi fi
if [ -c "/dev/mapper/control" ]; then if [ -c "/dev/mapper/control" ]; then
CSQUIET= CSQUIET=
. "${sshcs_cryptsetup_script}" . "${sshcs_cryptsetup_script}"
echo "" echo ""
echo "cryptsetup succeeded! Boot sequence should go on." echo "cryptsetup succeeded! Boot sequence should go on."
echo "Please wait and retry for standard SSH service." echo "Please wait and retry for standard SSH service."
else else
err "Device resources missing! Please retry." err "Device resources missing! Please retry."
fi fi
echo "" echo ""
EOF EOF
chmod a+x "${dropbear_login_shell}" chmod a+x "${dropbear_cryptsetup_shell}"
[ ! -d "/var/log" ] && mkdir -p "/var/log" [ ! -d "/var/log" ] && mkdir -p "/var/log"
touch "/var/log/lastlog" touch "/var/log/lastlog"
msg "Starting dropbear ..." msg "Starting dropbear ..."
dropbear -Esgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen} dropbear -Esgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen}
# Actual unlocking # Actual unlocking
sshcs_unlock sshcs_unlock
# cleanup dropbear # cleanup dropbear
if [ -f "${path_dropbear_pid}" ]; then if [ -f "${path_dropbear_pid}" ]; then
msg "Stopping dropbear ..." msg "Stopping dropbear ..."
kill $(cat "${path_dropbear_pid}") kill $(cat "${path_dropbear_pid}")
rm -f "${path_dropbear_pid}" rm -f "${path_dropbear_pid}"
fi fi
rm -f "${sshcs_cryptsetup_script}" "${dropbear_login_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog" rm -f "${sshcs_cryptsetup_script}" "${dropbear_cryptsetup_shell}" "/etc/passwd" "/etc/shells" "/var/log/lastlog"
# cleanup /dev/pts if necessary # cleanup /dev/pts if necessary
if [ ${dev_pts_mounted} -ne 0 ]; then if [ ${dev_pts_mounted} -ne 0 ]; then
umount "/dev/pts" umount "/dev/pts"
rm -R "/dev/pts" rm -R "/dev/pts"
fi fi
} }
sshcs_cryptpart_process() { sshcs_cryptpart_process() {
# ensure there is a device (handle 'UUID=' format) # ensure there is a device (handle 'UUID=' format)
[ -z "${cryptdev}" ] && return 0 [ -z "${cryptdev}" ] && return 0
[ "${cryptdev#UUID=}" != "${cryptdev}" ] && cryptdev="/dev/disk/by-uuid/${cryptdev#UUID=}" [ "${cryptdev#UUID=}" != "${cryptdev}" ] && cryptdev="/dev/disk/by-uuid/${cryptdev#UUID=}"
# get crypt options # get crypt options
cryptargs= cryptargs=
for cryptopt in ${cryptoptions//,/ }; do for cryptopt in ${cryptoptions//,/ }; do
case ${cryptopt} in case ${cryptopt} in
discard) discard)
cryptargs="${cryptargs} --allow-discards" cryptargs="${cryptargs} --allow-discards"
;; ;;
luks) luks)
;; ;;
*) *)
echo "Device ${cryptdev} encryption option '${cryptopt}' not known, ignoring." echo "Device ${cryptdev} encryption option '${cryptopt}' not known, ignoring."
;; ;;
esac esac
done done
# ensure device is encrypted and handled # ensure device is encrypted and handled
cryptdev_orig=${cryptdev} cryptdev_orig=${cryptdev}
if cryptdev=$(resolve_device "${cryptdev_orig}" ${rootdelay}); then if cryptdev=$(resolve_device "${cryptdev_orig}" ${rootdelay}); then
if cryptsetup isLuks "${cryptdev}" >/dev/null 2>&1; then if cryptsetup isLuks "${cryptdev}" >/dev/null 2>&1; then
dbg "Adding crypt device=${cryptdev} type=${crypttype} name=${cryptname} args=<${cryptargs}> in setup script" 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 # update script used to unlock device either in console or SSH
[ -s "${sshcs_cryptsetup_script}" ] || cat <<EOF > "${sshcs_cryptsetup_script}" [ -s "${sshcs_cryptsetup_script}" ] || cat <<EOF > "${sshcs_cryptsetup_script}"
cycle_or_retry() { 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 read -n 1 -s -t 5 -p "Whithin 5s press 'P' to poweroff, 'R' to reboot or any other key to retry. " res
echo "" echo ""
if [ "\${res}" = "P" ]; then if [ "\${res}" = "P" ]; then
poweroff -f poweroff -f
elif [ "\${res}" = "R" ]; then elif [ "\${res}" = "R" ]; then
reboot -f reboot -f
fi fi
} }
EOF EOF
cat <<EOF >> "${sshcs_cryptsetup_script}" cat <<EOF >> "${sshcs_cryptsetup_script}"
# loop until device is available # loop until device is available
while [ ! -e "/dev/mapper/${cryptname}" ]; do while [ ! -e "/dev/mapper/${cryptname}" ]; do
if cryptsetup open --type "${crypttype}" "${cryptdev}" "${cryptname}" ${cryptargs} "\${CSQUIET}"; then if cryptsetup open --type "${crypttype}" "${cryptdev}" "${cryptname}" ${cryptargs} "\${CSQUIET}"; then
if poll_device "/dev/mapper/${cryptname}" ${rootdelay}; then if poll_device "/dev/mapper/${cryptname}" ${rootdelay}; then
killall cryptsetup > /dev/null 2>&1 killall cryptsetup > /dev/null 2>&1
break 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 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 done
EOF EOF
else else
err "Failed to manage encrypted device ${cryptdev_orig}: not a LUKS volume." err "Failed to manage encrypted device ${cryptdev_orig}: not a LUKS volume."
fi
fi fi
fi
} }
run_hook() { run_hook() {
local etc_crypttab="/etc/crypttab" local etc_crypttab="/etc/crypttab"
local sshcs_env="/etc/initcpio/sshcs_env" local sshcs_env="/etc/initcpio/sshcs_env"
local path_dropbear_pid="/.dropbear.pid" local path_dropbear_pid="/.dropbear.pid"
local dropbear_login_shell="/.cryptsetup_shell.sh" local dropbear_cryptsetup_shell="/.cryptsetup_shell.sh"
local sshcs_cryptsetup_script="/.cryptsetup_script.sh" local sshcs_cryptsetup_script="/.cryptsetup_script.sh"
local net_env="/.net_env.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 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 cryptdev cryptdev_orig crypttype cryptname cryptpass cryptoptions cryptopt cryptargs CSQUIET
# Load our options # Load our options
sshcs_env_load sshcs_env_load
# sanity check: crypttab should be present # sanity check: crypttab should be present
[ ! -e "${etc_crypttab}" ] && { [ ! -e "${etc_crypttab}" ] && {
dbg "No crypttab configuration to process" dbg "No crypttab configuration to process"
return 0 return 0
} }
modprobe -a -q dm-crypt >/dev/null 2>&1 modprobe -a -q dm-crypt >/dev/null 2>&1
[ "${quiet}" = "y" ] && CSQUIET=">/dev/null" [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"
umask 0022 umask 0022
# check encrypted devices to handle # check encrypted devices to handle
cryptdev= cryptdev=
crypttype=luks crypttype=luks
while read cryptname cryptdev cryptpass cryptoptions; do while read cryptname cryptdev cryptpass cryptoptions; do
# skip comment lines # skip comment lines
[ "${cryptname:0:1}" = "#" ] && continue [ "${cryptname:0:1}" = "#" ] && continue
# skip devices with given password # skip devices with given password
[ -n "${cryptpass}" ] && [ "${cryptpass}" != "none" ] && [ "${cryptpass}" != "-" ] && continue [ -n "${cryptpass}" ] && [ "${cryptpass}" != "none" ] && [ "${cryptpass}" != "-" ] && continue
sshcs_cryptpart_process sshcs_cryptpart_process
done < "${etc_crypttab}" done < "${etc_crypttab}"
if [ ! -e "${sshcs_cryptsetup_script}" ]; then if [ ! -e "${sshcs_cryptsetup_script}" ]; then
err "No encrypted device found! Skipping crypt remote unlocking." err "No encrypted device found! Skipping crypt remote unlocking."
return 0 return 0
fi fi
# start and check network # start and check network
if ! sshcs_net_start; then if ! sshcs_net_start; then
err "Net interface not available! Skipping crypt remote unlocking." err "Net interface not available! Skipping crypt remote unlocking."
# We still allow to unlock locally with timeout # We still allow to unlock locally with timeout
sshcs_unlock sshcs_unlock
# stop the network if possible # 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 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
} }

View File

@ -1,109 +1,110 @@
#!/bin/bash #!/bin/bash
sshcs_check_nonempty() { 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() { sshcs_check_keys() {
local dropbear_keyfile local dropbear_keyfile
local openssh_keyfile local openssh_keyfile
local fingerprint local fingerprint
for keytype in "${dropbear_key_types[@]}"; do for keytype in "${dropbear_key_types[@]}"; do
dropbear_keyfile=${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix} dropbear_keyfile=${dropbear_keyfile_prefix}${keytype}${dropbear_keyfile_suffix}
openssh_keyfile=${openssh_keyfile_prefix}${keytype}${openssh_keyfile_suffix} openssh_keyfile=${openssh_keyfile_prefix}${keytype}${openssh_keyfile_suffix}
# Prefer OpenSSH keys, or generate missing ones # Prefer OpenSSH keys, or generate missing ones
if [ -e "${openssh_keyfile}" ]; then if [ -e "${openssh_keyfile}" ]; then
#echo "Copying OpenSSH ${keytype} host key for dropbear ..." #echo "Copying OpenSSH ${keytype} host key for dropbear ..."
dropbearconvert openssh dropbear "${openssh_keyfile}" "${dropbear_keyfile}" > /dev/null 2>&1 dropbearconvert openssh dropbear "${openssh_keyfile}" "${dropbear_keyfile}" > /dev/null 2>&1
elif [ ! -e "${dropbear_keyfile}" ]; then elif [ ! -e "${dropbear_keyfile}" ]; then
#echo "Generating ${keytype} host key for dropbear ..." #echo "Generating ${keytype} host key for dropbear ..."
dropbearkey -t "${keytype}" -f "${dropbear_keyfile}" > /dev/null 2>&1 dropbearkey -t "${keytype}" -f "${dropbear_keyfile}" > /dev/null 2>&1
fi fi
fingerprint=$(dropbearkey -y -f "${dropbear_keyfile}" | sed -n '/^Fingerprint:/ {s/Fingerprint: *//; p}') fingerprint=$(dropbearkey -y -f "${dropbear_keyfile}" | sed -n '/^Fingerprint:/ {s/Fingerprint: *//; p}')
echo "$(basename "${dropbear_keyfile}") : ${fingerprint}" echo "$(basename "${dropbear_keyfile}") : ${fingerprint}"
done done
} }
build() { build() {
local etc_crypttab="/etc/crypttab" local etc_crypttab="/etc/crypttab"
local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys" local dropbear_authorized_keys="/etc/dropbear/initrd.authorized_keys"
local sshcs_env="/etc/initcpio/sshcs_env" local sshcs_env="/etc/initcpio/sshcs_env"
local dropbear_key_types=( "rsa" "ecdsa" "ed25519" ) local dropbear_key_types=( "rsa" "ecdsa" "ed25519" )
local dropbear_keyfile_prefix="/etc/dropbear/dropbear_" local dropbear_keyfile_prefix="/etc/dropbear/dropbear_"
local dropbear_keyfile_suffix="_host_key" local dropbear_keyfile_suffix="_host_key"
local openssh_keyfile_prefix="/etc/ssh/ssh_host_" local openssh_keyfile_prefix="/etc/ssh/ssh_host_"
local openssh_keyfile_suffix="_key" local openssh_keyfile_suffix="_key"
# Check we are needed # Check we are needed
if ! sshcs_check_nonempty "${dropbear_authorized_keys}"; then if ! sshcs_check_nonempty "${dropbear_authorized_keys}"; then
echo "There is no root key(s) in ${dropbear_authorized_keys}. Skipping." echo "There is no root key(s) in ${dropbear_authorized_keys}. Skipping."
return 0 return 0
fi fi
if ! sshcs_check_nonempty "${etc_crypttab}"; then if ! sshcs_check_nonempty "${etc_crypttab}"; then
echo "There is no device in ${etc_crypttab}. Skipping." echo "There is no device in ${etc_crypttab}. Skipping."
return 0 return 0
fi fi
umask 0022 umask 0022
sshcs_check_keys sshcs_check_keys
add_checked_modules "/drivers/net/" add_checked_modules "/drivers/net/"
# Note: parts of this script (modules/binaries added) are the same than the # Note: parts of this script (modules/binaries added) are the same than the
# 'encrypt' install script (/usr/lib/initcpio/install/encrypt) which is the # 'encrypt' install script (/usr/lib/initcpio/install/encrypt) which is the
# nominal one to deal with encrypted volumes at boot time. # nominal one to deal with encrypted volumes at boot time.
add_module dm-crypt add_module dm-crypt
# Note: crypto modules are necessary # Note: crypto modules are necessary
if [ -n "${CRYPTO_MODULES}" ]; then if [ -n "${CRYPTO_MODULES}" ]; then
local mod local mod
for mod in ${CRYPTO_MODULES}; do for mod in ${CRYPTO_MODULES}; do
add_module "${mod}" 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}"
done done
else
add_all_modules "/crypto/"
fi
# cryptsetup-related files # Note: dmsetup is necessary for device mapper features
add_file "${etc_crypttab}" add_binary "cryptsetup"
add_file "/usr/lib/udev/rules.d/10-dm.rules" add_binary "dmsetup"
add_file "/usr/lib/udev/rules.d/13-dm-disk.rules" add_binary "dropbear"
add_file "/usr/lib/udev/rules.d/95-dm-notify.rules" add_binary "ip"
add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules" add_binary "/usr/lib/initcpio/ipconfig" "/bin/ipconfig"
add_binary "ethtool"
# At least with LUKS v2 volumes, cryptsetup calls pthread_cancel(), which # Our hook files
# dlopen()s libgcc_s.so.1. [ -e "${sshcs_env}" ] && add_file "${sshcs_env}"
# 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 # 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() { help() {
cat <<EOF cat <<EOF
This hook allows for LUKS encrypted devices to be unlocked either locally This hook allows for LUKS encrypted devices to be unlocked either locally
(boot console) or remotely over SSH. (boot console) or remotely over SSH.
@ -127,3 +128,4 @@ if present or generated if missing. Fingerprints are displayed upon building
the initramfs image. the initramfs image.
EOF EOF
} }