parent
c3cafcf6cd
commit
3449995d4a
13
ChangeLog
13
ChangeLog
|
@ -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
|
||||||
|
|
8
PKGBUILD
8
PKGBUILD
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue