From: Tom Gundersen <teg@jklm.no> We detect if the old syntax is used, and if so print a warning and use the old parsing code. Otherwise, we pass everything on to systemd-cryptsetup. Similarly to what was done with the network syntax, we intend to keep the legacy stuff working for a long time. See crypttab(5) for the new syntax[0]. The main reason for this change, is to be closer to what other distros do. The systemd syntax is based on Debian's format, and is essentially what is being used by at least Debian, Ubuntu, Fedora and Suse. Such widespread use means that it will be better documented in non-Arch-specific documentation, and is more likely to see integration with third-party tools. It is also surely appreciated by admins who use more than one distro, that they don't have to know more than one config format for these sorts of basic things. Furthermore, by actually sharing the code with systemd we get to rely on their much more widespread testing and review compared to what we are able to do ourselves. This is particularly important for the encryption code, as it is the most obscure code in initscripts and any bugs in it would have potentially very severe consequences. Lastly, there are a few (albeit minor) issues I see with our current format: /etc/crypttab is not a plaintext file, but needs to be parsed through bash. The (deprecated) embedded passwords have been a source of problems in the past. And, there is no level of abstraction between the crypttab options and cryptsetup, we just pass them on blindly. The new format and the old one cover roughly the same usecases. To the best of my knowledge, the only use-case not (yet) supported by systemd-cryptsetup, is mounting a removable device and reading the key from a file on that device. For this, stick with the old syntax (though be careful, it is inherently racy). [0]: <http://0pointer.de/public/systemd-man/systemd.unit.html> (note that keyfile-offset support is coming in the next systemd version). --- functions | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/functions b/functions index 16f8d8f..7fd5258 100644 --- a/functions +++ b/functions @@ -381,12 +381,13 @@ activate_vgs() { (( $? == 0 )) && stat_done || stat_fail } -do_unlock() { +do_unlock_legacy() { # $1 = requested name # $2 = source device # $3 = password # $4 = options stat_append "${1}.." + printf "${C_FAIL}Using legacy crypttab format. This will stop working in the future. See crypttab(5).${C_OTHER}\n" local open=create a=$1 b=$2 failed=0 # Ordering of options is different if you are using LUKS vs. not. # Use ugly swizzling to deal with it. @@ -448,7 +449,6 @@ do_unlock() { /*) cryptsetup -d "$3" $4 $open "$a" "$b" >/dev/null;; *) - printf "${C_FAIL}crypttab contains a literal encryption key. This will stop working in the future.${C_OTHER}\n" echo "$3" | cryptsetup $4 $open "$a" "$b" >/dev/null;; esac if (( $? )); then @@ -460,10 +460,64 @@ do_unlock() { return $failed } +do_unlock_systemd() { + stat_append "${1}.." + local failed=0 + if ! /usr/lib/systemd/systemd-cryptsetup attach "$1" "$2" "$3" $4; then + failed=1 + else + IFS=, + if in_array swap ${options[@]}; then + if ! mkswap /dev/mapper/$name >/dev/null; then + failed=1 + fi + elif in_array tmp ${options[@]}; then + if ! mke2fs /dev/mapper/$name >/dev/null; then + failed=1 + fi + fi + fi + if (( $failed )); then + stat_append "failed " + else + stat_append "ok " + fi + return $failed +} + +do_unlock() { + local name=$1 device=$2 password=$3 options=$4 + + if [[ ${options:0:2} =~ -. ]]; then + do_unlock_legacy "$name" "$device" "$password" "$options" + return $? + fi + + case $password in + ASK|SWAP) + do_unlock_legacy "$name" "$device" "$password" "$options" + ;; + /dev/*) + if [[ ${password##*:} == $password ]]; then + do_unlock_systemd "$name" "$device" "$password" "$options" + else + do_unlock_legacy "$name" "$device" "$password" "$options" + fi + ;; + /*|none|-) + do_unlock_systemd "$name" "$device" "$password" "$options" + ;; + *) + do_unlock_legacy "$name" "$device" "$password" "$options" + ;; + esac + return $? +} + read_crypttab() { # $1 = function to call with the split out line from the crypttab local line nspo failed=0 - while read line; do + while read line <&3; do [[ $line && $line != '#'* ]] || continue eval nspo=("${line%#*}") if $1 "${nspo[0]}" "${nspo[1]}" "${nspo[2]}" "${nspo[*]:3}"; then @@ -471,7 +525,7 @@ read_crypttab() { else failed=1 fi - done < /etc/crypttab + done 3< /etc/crypttab return $failed } -- 1.7.11.1