nixos: initrd/luks: cleanup and generalize common shell expressions
Also fix Yubikey timeout handling mess.
This commit is contained in:
parent
dc653449c5
commit
12e6907f33
@ -5,39 +5,79 @@ with lib;
|
|||||||
let
|
let
|
||||||
luks = config.boot.initrd.luks;
|
luks = config.boot.initrd.luks;
|
||||||
|
|
||||||
openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, fallbackToPassword, ... }: assert name' == name; ''
|
commonFunctions = ''
|
||||||
|
die() {
|
||||||
|
echo "$@" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# Wait for a target (e.g. device, keyFile, header, ...) to appear.
|
|
||||||
wait_target() {
|
wait_target() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
local target="$2"
|
local target="$2"
|
||||||
|
local secs="''${3:-10}"
|
||||||
|
local desc="''${4:-$name $target to appear}"
|
||||||
|
|
||||||
if [ ! -e $target ]; then
|
if [ ! -e $target ]; then
|
||||||
echo -n "Waiting 10 seconds for $name $target to appear"
|
echo -n "Waiting $secs seconds for $desc..."
|
||||||
local success=false;
|
local success=false;
|
||||||
for try in $(seq 10); do
|
for try in $(seq $secs); do
|
||||||
echo -n "."
|
echo -n "."
|
||||||
sleep 1
|
sleep 1
|
||||||
if [ -e $target ]; then success=true break; fi
|
if [ -e $target ]; then
|
||||||
|
success=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
if [ $success = true ]; then
|
if [ $success == true ]; then
|
||||||
echo " - success";
|
echo " - success";
|
||||||
|
return 0
|
||||||
else
|
else
|
||||||
echo " - failure";
|
echo " - failure";
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait_yubikey() {
|
||||||
|
local secs="''${1:-10}"
|
||||||
|
|
||||||
|
ykinfo -v 1>/dev/null 2>&1
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
echo -n "Waiting $secs seconds for Yubikey to appear..."
|
||||||
|
local success=false
|
||||||
|
for try in $(seq $secs); do
|
||||||
|
echo -n .
|
||||||
|
sleep 1
|
||||||
|
ykinfo -v 1>/dev/null 2>&1
|
||||||
|
if [ $? == 0 ]; then
|
||||||
|
success=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ $success == true ]; then
|
||||||
|
echo " - success";
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " - failure";
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, fallbackToPassword, ... }: assert name' == name; ''
|
||||||
# Wait for luksRoot (and optionally keyFile and/or header) to appear, e.g.
|
# Wait for luksRoot (and optionally keyFile and/or header) to appear, e.g.
|
||||||
# if on a USB drive.
|
# if on a USB drive.
|
||||||
wait_target "device" ${device}
|
wait_target "device" ${device} || die "${device} is unavailable"
|
||||||
|
|
||||||
${optionalString (keyFile != null) ''
|
|
||||||
wait_target "key file" ${keyFile}
|
|
||||||
''}
|
|
||||||
|
|
||||||
${optionalString (header != null) ''
|
${optionalString (header != null) ''
|
||||||
wait_target "header" ${header}
|
wait_target "header" ${header} || die "${header} is unavailable"
|
||||||
|
''}
|
||||||
|
|
||||||
|
${optionalString (keyFile != null) ''
|
||||||
|
wait_target "key file" ${keyFile} || die "${keyFile} is unavailable"
|
||||||
''}
|
''}
|
||||||
|
|
||||||
open_normally() {
|
open_normally() {
|
||||||
@ -70,7 +110,6 @@ let
|
|||||||
}
|
}
|
||||||
|
|
||||||
open_yubikey() {
|
open_yubikey() {
|
||||||
|
|
||||||
# Make all of these local to this function
|
# Make all of these local to this function
|
||||||
# to prevent their values being leaked
|
# to prevent their values being leaked
|
||||||
local salt
|
local salt
|
||||||
@ -95,10 +134,9 @@ let
|
|||||||
response="$(ykchalresp -${toString yubikey.slot} -x $challenge 2>/dev/null)"
|
response="$(ykchalresp -${toString yubikey.slot} -x $challenge 2>/dev/null)"
|
||||||
|
|
||||||
for try in $(seq 3); do
|
for try in $(seq 3); do
|
||||||
|
|
||||||
${optionalString yubikey.twoFactor ''
|
${optionalString yubikey.twoFactor ''
|
||||||
echo -n "Enter two-factor passphrase: "
|
echo -n "Enter two-factor passphrase: "
|
||||||
read -s k_user
|
read -rs k_user
|
||||||
echo
|
echo
|
||||||
''}
|
''}
|
||||||
|
|
||||||
@ -110,7 +148,7 @@ let
|
|||||||
|
|
||||||
echo -n "$k_luks" | hextorb | cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} --key-file=-
|
echo -n "$k_luks" | hextorb | cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} --key-file=-
|
||||||
|
|
||||||
if [ $? == "0" ]; then
|
if [ $? == 0 ]; then
|
||||||
opened=true
|
opened=true
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
@ -121,8 +159,7 @@ let
|
|||||||
|
|
||||||
if [ "$opened" == false ]; then
|
if [ "$opened" == false ]; then
|
||||||
umount ${yubikey.storage.mountPoint}
|
umount ${yubikey.storage.mountPoint}
|
||||||
echo "Maximum authentication errors reached"
|
die "Maximum authentication errors reached"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "Gathering entropy for new salt (please enter random keys to generate entropy if this blocks for long)..."
|
echo -n "Gathering entropy for new salt (please enter random keys to generate entropy if this blocks for long)..."
|
||||||
@ -157,7 +194,7 @@ let
|
|||||||
echo -n "$new_k_luks" | hextorb > ${yubikey.ramfsMountPoint}/new_key
|
echo -n "$new_k_luks" | hextorb > ${yubikey.ramfsMountPoint}/new_key
|
||||||
echo -n "$k_luks" | hextorb | cryptsetup luksChangeKey ${device} --key-file=- ${yubikey.ramfsMountPoint}/new_key
|
echo -n "$k_luks" | hextorb | cryptsetup luksChangeKey ${device} --key-file=- ${yubikey.ramfsMountPoint}/new_key
|
||||||
|
|
||||||
if [ $? == "0" ]; then
|
if [ $? == 0 ]; then
|
||||||
echo -ne "$new_salt\n$new_iterations" > ${yubikey.storage.mountPoint}${yubikey.storage.path}
|
echo -ne "$new_salt\n$new_iterations" > ${yubikey.storage.mountPoint}${yubikey.storage.path}
|
||||||
else
|
else
|
||||||
echo "Warning: Could not update LUKS key, current challenge persists!"
|
echo "Warning: Could not update LUKS key, current challenge persists!"
|
||||||
@ -170,38 +207,11 @@ let
|
|||||||
umount ${yubikey.storage.mountPoint}
|
umount ${yubikey.storage.mountPoint}
|
||||||
}
|
}
|
||||||
|
|
||||||
${optionalString (yubikey.gracePeriod > 0) ''
|
if wait_yubikey ${toString yubikey.gracePeriod}; then
|
||||||
echo -n "Waiting ${toString yubikey.gracePeriod} seconds as grace..."
|
open_yubikey
|
||||||
for i in $(seq ${toString yubikey.gracePeriod}); do
|
|
||||||
sleep 1
|
|
||||||
echo -n .
|
|
||||||
done
|
|
||||||
echo "ok"
|
|
||||||
''}
|
|
||||||
|
|
||||||
yubikey_missing=true
|
|
||||||
ykinfo -v 1>/dev/null 2>&1
|
|
||||||
if [ $? != "0" ]; then
|
|
||||||
echo -n "waiting 10 seconds for yubikey to appear..."
|
|
||||||
for try in $(seq 10); do
|
|
||||||
sleep 1
|
|
||||||
ykinfo -v 1>/dev/null 2>&1
|
|
||||||
if [ $? == "0" ]; then
|
|
||||||
yubikey_missing=false
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
echo -n .
|
|
||||||
done
|
|
||||||
echo "ok"
|
|
||||||
else
|
else
|
||||||
yubikey_missing=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$yubikey_missing" == true ]; then
|
|
||||||
echo "no yubikey found, falling back to non-yubikey open procedure"
|
echo "no yubikey found, falling back to non-yubikey open procedure"
|
||||||
open_normally
|
open_normally
|
||||||
else
|
|
||||||
open_yubikey
|
|
||||||
fi
|
fi
|
||||||
''}
|
''}
|
||||||
|
|
||||||
@ -397,9 +407,9 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
gracePeriod = mkOption {
|
gracePeriod = mkOption {
|
||||||
default = 2;
|
default = 10;
|
||||||
type = types.int;
|
type = types.int;
|
||||||
description = "Time in seconds to wait before attempting to find the Yubikey.";
|
description = "Time in seconds to wait for the Yubikey.";
|
||||||
};
|
};
|
||||||
|
|
||||||
ramfsMountPoint = mkOption {
|
ramfsMountPoint = mkOption {
|
||||||
@ -520,8 +530,8 @@ in
|
|||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
boot.initrd.preLVMCommands = concatStrings (mapAttrsToList openCommand preLVM);
|
boot.initrd.preLVMCommands = commonFunctions + concatStrings (mapAttrsToList openCommand preLVM);
|
||||||
boot.initrd.postDeviceCommands = concatStrings (mapAttrsToList openCommand postLVM);
|
boot.initrd.postDeviceCommands = commonFunctions + concatStrings (mapAttrsToList openCommand postLVM);
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.cryptsetup ];
|
environment.systemPackages = [ pkgs.cryptsetup ];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user