2014-05-20 00:46:59 +04:00
|
|
|
#!/usr/bin/ash
|
|
|
|
|
|
|
|
sshcs_net_start() {
|
|
|
|
# we must have an 'ip' setting, and a device in it
|
|
|
|
[ -z "${ip}" ] && [ -n "${nfsaddrs}" ] && ip="${nfsaddrs}"
|
|
|
|
[ -z "${ip}" ] && return 1
|
|
|
|
|
|
|
|
net_device=$(echo ${ip} | cut -d: -f6)
|
|
|
|
[ -z "${net_device}" ] && 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}"
|
|
|
|
ipconfig "ip=${ip}" | while read line; do
|
|
|
|
[ "${line#"IP-Config:"}" != "${line}" ] && continue
|
|
|
|
|
|
|
|
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
|
|
|
|
done
|
|
|
|
|
|
|
|
. "${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}"
|
|
|
|
|
|
|
|
[ -n "${net_address}" ]
|
|
|
|
}
|
|
|
|
|
2014-05-21 00:39:32 +04:00
|
|
|
sshcs_trapped_timeout() {
|
|
|
|
err "Timeout reached! Powering off."
|
|
|
|
poweroff -f
|
|
|
|
exit
|
|
|
|
}
|
|
|
|
|
|
|
|
sshcs_trap_timeout() {
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
sshcs_untrap_timeout() {
|
|
|
|
[ -z "${pid_timeout}" ] && return 0
|
|
|
|
kill ${pid_timeout}
|
|
|
|
trap - SIGALRM
|
|
|
|
msg "Timeout cleared."
|
|
|
|
}
|
|
|
|
|
2014-05-20 00:46:59 +04:00
|
|
|
sshcs_dropbear_unlock() {
|
2014-05-21 00:39:32 +04:00
|
|
|
local timeout_poweroff_min=120
|
|
|
|
local pid_timeout=
|
2014-05-20 00:46:59 +04:00
|
|
|
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
|
|
|
|
|
|
|
|
# /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"
|
|
|
|
|
|
|
|
# root login script
|
|
|
|
cat <<EOF > "${dropbear_login_shell}"
|
|
|
|
#!/usr/bin/ash
|
|
|
|
|
|
|
|
. "/init_functions"
|
|
|
|
|
|
|
|
if [ ! -f "${dropbear_cryptsetup_script}" ]; then
|
|
|
|
err "No cryptsetup script present! Please retry."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -c "/dev/mapper/control" ]; then
|
|
|
|
CSQUIET=
|
|
|
|
. "${dropbear_cryptsetup_script}"
|
|
|
|
|
|
|
|
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."
|
|
|
|
fi
|
|
|
|
echo ""
|
|
|
|
EOF
|
|
|
|
chmod a+x "${dropbear_login_shell}"
|
|
|
|
|
|
|
|
[ ! -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}"
|
2014-05-21 00:39:32 +04:00
|
|
|
[ -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}
|
2014-05-20 00:46:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
msg "Starting dropbear ..."
|
|
|
|
dropbear -Emsgjk -P "${path_dropbear_pid}" ${sshcs_opt_listen}
|
|
|
|
|
2014-05-21 00:39:32 +04:00
|
|
|
sshcs_trap_timeout
|
|
|
|
|
2014-05-20 00:46:59 +04:00
|
|
|
# actual script (shared with SSH login) unlocking encrypted devices
|
|
|
|
. "${dropbear_cryptsetup_script}"
|
|
|
|
|
2014-05-21 00:39:32 +04:00
|
|
|
sshcs_untrap_timeout
|
|
|
|
|
2014-05-20 00:46:59 +04:00
|
|
|
# cleanup dropbear
|
|
|
|
if [ -f "${path_dropbear_pid}" ]; then
|
|
|
|
msg "Stopping dropbear ..."
|
|
|
|
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"
|
|
|
|
|
|
|
|
# cleanup /dev/pts if necessary
|
|
|
|
if [ ${dev_pts_mounted} -ne 0 ]; then
|
|
|
|
umount "/dev/pts"
|
|
|
|
rm -R "/dev/pts"
|
|
|
|
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
|
|
|
|
[ "${cryptdev#UUID=}" != "${cryptdev}" ] && cryptdev="/dev/disk/by-uuid/${cryptdev#UUID=}"
|
|
|
|
|
|
|
|
# get crypt options
|
|
|
|
cryptargs=
|
|
|
|
for cryptopt in ${cryptoptions//,/ }; do
|
|
|
|
case ${cryptopt} in
|
|
|
|
allow-discards)
|
|
|
|
cryptargs="${cryptargs} --allow-discards"
|
|
|
|
;;
|
|
|
|
|
|
|
|
luks)
|
|
|
|
;;
|
|
|
|
|
|
|
|
*)
|
|
|
|
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
|
|
|
|
|
|
|
|
# update script used to unlock device either in console or SSH
|
|
|
|
[ -s "${dropbear_cryptsetup_script}" ] || cat <<EOF > "${dropbear_cryptsetup_script}"
|
|
|
|
cycle_or_retry() {
|
|
|
|
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
|
|
|
|
}
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat <<EOF >> "${dropbear_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
|
|
|
|
fi
|
|
|
|
|
|
|
|
cycle_or_retry
|
|
|
|
done
|
|
|
|
EOF
|
|
|
|
else
|
|
|
|
err "Failed to manage encrypted device ${cryptdev_orig}: not a LUKS volume."
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
run_hook() {
|
|
|
|
local etc_crypttab="/etc/crypttab"
|
|
|
|
local dropbear_env="/etc/dropbear/initrd.env"
|
|
|
|
local path_dropbear_pid="/.dropbear.pid"
|
|
|
|
local dropbear_login_shell="/.cryptsetup_shell.sh"
|
|
|
|
local dropbear_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 cryptdev cryptdev_orig crypttype cryptname cryptpass cryptoptions cryptopt cryptargs CSQUIET
|
|
|
|
|
|
|
|
# sanity check: crypttab should be present
|
|
|
|
[ ! -e "${etc_crypttab}" ] && return 0
|
|
|
|
|
|
|
|
modprobe -a -q dm-crypt >/dev/null 2>&1
|
|
|
|
[ "${quiet}" = "y" ] && CSQUIET=">/dev/null"
|
|
|
|
|
|
|
|
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
|
|
|
|
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}"
|
|
|
|
|
|
|
|
if [ ! -e "${dropbear_cryptsetup_script}" ]; then
|
|
|
|
err "No encrypted device found! Skipping crypt remote unlocking."
|
|
|
|
# don't forget to stop the network
|
|
|
|
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
|
|
|
|
}
|