=== modified file 'Makefile' --- Makefile 2018-08-15 09:13:36 +0000 +++ Makefile 2018-08-19 01:35:11 +0000 @@ -396,6 +396,8 @@ "$(CONFDIR)/network-hooks.d" install --mode=u=rwx,go=rx \ --target-directory=$(LIBDIR)/mandos plugin-runner + install --mode=u=rwx,go=rx \ + --target-directory=$(LIBDIR)/mandos mandos-to-cryptroot-unlock install --mode=u=rwx,go=rx --target-directory=$(PREFIX)/sbin \ mandos-keygen install --mode=u=rwx,go=rx \ @@ -425,6 +427,8 @@ $(INITRAMFSTOOLS)/conf-hooks.d/mandos install initramfs-tools-script \ $(INITRAMFSTOOLS)/scripts/init-premount/mandos + install initramfs-tools-script-stop \ + $(INITRAMFSTOOLS)/scripts/local-premount/mandos install --mode=u=rw,go=r plugin-runner.conf $(CONFDIR) gzip --best --to-stdout mandos-keygen.8 \ > $(MANDIR)/man8/mandos-keygen.8.gz === modified file 'debian/mandos-client.dirs' --- debian/mandos-client.dirs 2009-02-07 04:50:39 +0000 +++ debian/mandos-client.dirs 2018-08-19 01:35:11 +0000 @@ -3,3 +3,4 @@ usr/share/initramfs-tools/hooks usr/share/initramfs-tools/conf-hooks.d usr/share/initramfs-tools/scripts/init-premount +usr/share/initramfs-tools/scripts/local-premount === modified file 'initramfs-tools-hook' --- initramfs-tools-hook 2017-02-21 22:15:43 +0000 +++ initramfs-tools-hook 2018-08-19 01:35:11 +0000 @@ -80,6 +80,8 @@ --mode=u=rwx "${DESTDIR}${PLUGINDIR}" \ "${DESTDIR}${PLUGINHELPERDIR}" +copy_exec "$libdir"/mandos/mandos-to-cryptroot-unlock "${MANDOSDIR}" + # Copy the Mandos plugin runner copy_exec "$libdir"/mandos/plugin-runner "${MANDOSDIR}" === modified file 'initramfs-tools-script' --- initramfs-tools-script 2017-08-20 14:41:20 +0000 +++ initramfs-tools-script 2018-08-19 01:35:11 +0000 @@ -51,9 +51,6 @@ chmod a=rwxt /tmp -test -r /conf/conf.d/cryptroot -test -w /conf/conf.d - # Get DEVICE from /conf/initramfs.conf and other files . /conf/initramfs.conf for conf in /conf/conf.d/*; do @@ -105,74 +102,80 @@ fi fi -# Do not replace cryptroot file unless we need to. -replace_cryptroot=no - -# Our keyscript -mandos=/lib/mandos/plugin-runner -test -x "$mandos" - -# parse /conf/conf.d/cryptroot. Format: -# target=sda2_crypt,source=/dev/sda2,rootdev,key=none,keyscript=/foo/bar/baz -# Is the root device specially marked? -changeall=yes -while read -r options; do - case "$options" in - rootdev,*|*,rootdev,*|*,rootdev) - # If the root device is specially marked, don't change all - # lines in crypttab by default. - changeall=no - ;; - esac -done < /conf/conf.d/cryptroot - -exec 3>/conf/conf.d/cryptroot.mandos -while read -r options; do - newopts="" - keyscript="" - changethis="$changeall" - # Split option line on commas - old_ifs="$IFS" - IFS="$IFS," - for opt in $options; do - # Find the keyscript option, if any - case "$opt" in - keyscript=*) - keyscript="${opt#keyscript=}" - newopts="$newopts,$opt" - ;; - "") : ;; - # Always use Mandos on the root device, if marked - rootdev) - changethis=yes - newopts="$newopts,$opt" - ;; - # Don't use Mandos on resume device, if marked - resumedev) - changethis=no - newopts="$newopts,$opt" - ;; - *) - newopts="$newopts,$opt" +if [ -r /conf/conf.d/cryptroot ]; then + test -w /conf/conf.d + + # Do not replace cryptroot file unless we need to. + replace_cryptroot=no + + # Our keyscript + mandos=/lib/mandos/plugin-runner + test -x "$mandos" + + # parse /conf/conf.d/cryptroot. Format: + # target=sda2_crypt,source=/dev/sda2,rootdev,key=none,keyscript=/foo/bar/baz + # Is the root device specially marked? + changeall=yes + while read -r options; do + case "$options" in + rootdev,*|*,rootdev,*|*,rootdev) + # If the root device is specially marked, don't change all + # lines in crypttab by default. + changeall=no ;; esac - done - IFS="$old_ifs" - unset old_ifs - # If there was no keyscript option, add one. - if [ "$changethis" = yes ] && [ -z "$keyscript" ]; then - replace_cryptroot=yes - newopts="$newopts,keyscript=$mandos" + done < /conf/conf.d/cryptroot + + exec 3>/conf/conf.d/cryptroot.mandos + while read -r options; do + newopts="" + keyscript="" + changethis="$changeall" + # Split option line on commas + old_ifs="$IFS" + IFS="$IFS," + for opt in $options; do + # Find the keyscript option, if any + case "$opt" in + keyscript=*) + keyscript="${opt#keyscript=}" + newopts="$newopts,$opt" + ;; + "") : ;; + # Always use Mandos on the root device, if marked + rootdev) + changethis=yes + newopts="$newopts,$opt" + ;; + # Don't use Mandos on resume device, if marked + resumedev) + changethis=no + newopts="$newopts,$opt" + ;; + *) + newopts="$newopts,$opt" + ;; + esac + done + IFS="$old_ifs" + unset old_ifs + # If there was no keyscript option, add one. + if [ "$changethis" = yes ] && [ -z "$keyscript" ]; then + replace_cryptroot=yes + newopts="$newopts,keyscript=$mandos" + fi + newopts="${newopts#,}" + echo "$newopts" >&3 + done < /conf/conf.d/cryptroot + exec 3>&- + + # If we need to, replace the old cryptroot file with the new file. + if [ "$replace_cryptroot" = yes ]; then + mv /conf/conf.d/cryptroot /conf/conf.d/cryptroot.mandos-old + mv /conf/conf.d/cryptroot.mandos /conf/conf.d/cryptroot + else + rm -f /conf/conf.d/cryptroot.mandos fi - newopts="${newopts#,}" - echo "$newopts" >&3 -done < /conf/conf.d/cryptroot -exec 3>&- - -# If we need to, replace the old cryptroot file with the new file. -if [ "$replace_cryptroot" = yes ]; then - mv /conf/conf.d/cryptroot /conf/conf.d/cryptroot.mandos-old - mv /conf/conf.d/cryptroot.mandos /conf/conf.d/cryptroot -else - rm /conf/conf.d/cryptroot.mandos +elif [ -x /usr/bin/cryptroot-unlock ]; then + setsid /lib/mandos/mandos-to-cryptroot-unlock & fi === added file 'initramfs-tools-script-stop' --- initramfs-tools-script-stop 1970-01-01 00:00:00 +0000 +++ initramfs-tools-script-stop 2018-08-19 01:35:11 +0000 @@ -0,0 +1,65 @@ +#!/bin/sh -e +# +# Script to wait for plugin-runner to exit before continuing boot +# +# Copyright © 2018 Teddy Hogeborn +# Copyright © 2018 Björn Påhlsson +# +# This file is part of Mandos. +# +# Mandos is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Mandos is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Mandos. If not, see . +# +# Contact the authors at . +# +# This script will run in the initrd environment at boot and remove +# the file keeping the dummy plugin running, forcing plugin-runner to +# exit if it is still running. + +# This script should be installed as +# "/usr/share/initramfs-tools/scripts/local-premount/mandos" which will +# eventually be "/scripts/local-premount/mandos" in the initrd.img +# file. + +PREREQ="" +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +pid=$(cat /run/mandos-plugin-runner.pid 2>/dev/null) + +# If the dummy plugin is running, removing this file should force the +# dummy plugin to exit successfully, thereby making plugin-runner shut +# down all its other plugins and then exit itself. +rm -f /run/mandos-keep-running >/dev/null 2>&1 + +# Wait for exit of plugin-runner, if still running +if [ -n "$pid" ]; then + while :; do + case "$(readlink /proc/"$pid"/exe 2>/dev/null)" in + */plugin-runner) sleep 1;; + *) break;; + esac + done + rm -f /run/mandos-plugin-runner.pid >/dev/null 2>&1 +fi === added file 'mandos-to-cryptroot-unlock' --- mandos-to-cryptroot-unlock 1970-01-01 00:00:00 +0000 +++ mandos-to-cryptroot-unlock 2018-08-19 01:35:11 +0000 @@ -0,0 +1,82 @@ +#!/bin/sh +# +# Script to get password from plugin-runner to cryptroot-unlock +# +# Copyright © 2018 Teddy Hogeborn +# Copyright © 2018 Björn Påhlsson +# +# This file is part of Mandos. +# +# Mandos is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Mandos is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Mandos. If not, see . +# +# Contact the authors at . + +# This script is made to run in the initramfs, and must not be run in +# the normal system environment. + +# Temporary file for the password +passfile=$(mktemp -p /run -t mandos.XXXXXX) +trap "rm -f -- $passfile 2>/dev/null" EXIT + +# Disable the plugins which conflict with "askpass" as distributed by +# cryptsetup. +cat <<-EOF >>/conf/conf.d/mandos/plugin-runner.conf + + --disable=askpass-fifo + --disable=password-prompt + --disable=plymouth +EOF + +# In case a password is retrieved by other means than by plugin-runner +# (such as typing it on the console into the prompt given by the +# "askpass" program), this dummy plugin will be made to exit +# successfully, thereby forcing plugin-runner to stop all its plugins +# and also exit itself. +cat <<-EOF > /lib/mandos/plugins.d/dummy + #!/bin/sh + + while [ -e /run/mandos-keep-running ]; do + sleep 1 + done + + # exit successfully to force plugin-runner to finish + exit 0 +EOF +chmod u=rwx,go=rx /lib/mandos/plugins.d/dummy + +# This file is the flag which keeps the dummy plugin running +touch /run/mandos-keep-running + +# Keep running plugin-runner and trying any password, until either a +# password is accepted by cryptroot-unlock, or plugin-runner fails, or +# the file /run/mandos-keep-running has been removed. +while type cryptroot-unlock >/dev/null 2>&1; do + /lib/mandos/plugin-runner > "$passfile" & + echo $! > /run/mandos-plugin-runner.pid + wait %% || break + + # Try this password ten times (or ten seconds) + for loop in 1 2 3 4 5 6 7 8 9 10; do + if [ -e /run/mandos-keep-running ]; then + cryptroot-unlock < "$passfile" >/dev/null 2>&1 && break 2 + sleep 1 + else + break 2 + fi + done +done + +exec >/dev/null 2>&1 + +rm -f /run/mandos-plugin-runner.pid /run/mandos-keep-running