summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2018-07-17 20:30:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2018-07-17 20:30:25 +0000
commit0ead009cdd3f0bae7b9af73cb8929851190010cb (patch)
tree39d0207925e85aad45a1dbe4b5ebacc33bbcf4db
parentReleasing progress-linux version 2:2.0.3-4~dschinn1. (diff)
downloadcryptsetup-0ead009cdd3f0bae7b9af73cb8929851190010cb.zip
cryptsetup-0ead009cdd3f0bae7b9af73cb8929851190010cb.tar.xz
Merging debian version 2:2.0.3-5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--debian/README.keyctl4
-rw-r--r--debian/TODO42
-rw-r--r--debian/TODO.md71
-rw-r--r--debian/askpass.c2
-rw-r--r--debian/changelog54
-rw-r--r--debian/checks/blkid2
-rw-r--r--debian/checks/un_blkid2
-rw-r--r--debian/control7
-rw-r--r--debian/cryptdisks-functions141
-rw-r--r--debian/cryptsetup-run.postinst54
-rw-r--r--debian/doc/crypttab.xml5
-rw-r--r--debian/functions315
-rw-r--r--debian/initramfs/conf-hook3
-rw-r--r--debian/initramfs/cryptroot-unlock65
-rw-r--r--debian/initramfs/hooks/cryptgnupg20
-rw-r--r--debian/initramfs/hooks/cryptopensc31
-rw-r--r--debian/initramfs/hooks/cryptroot365
-rw-r--r--debian/initramfs/scripts/local-top/cryptroot112
-rw-r--r--debian/patches/disable-internal-tests.patch35
-rw-r--r--debian/patches/series1
-rwxr-xr-xdebian/rules12
-rw-r--r--debian/scripts/cryptdisks_start9
-rw-r--r--debian/scripts/cryptdisks_stop8
-rw-r--r--debian/scripts/decrypt_derived58
-rw-r--r--debian/scripts/passdev.c2
25 files changed, 811 insertions, 609 deletions
diff --git a/debian/README.keyctl b/debian/README.keyctl
index 9c65495..a6f3764 100644
--- a/debian/README.keyctl
+++ b/debian/README.keyctl
@@ -6,7 +6,7 @@ When there are multiple cryptsetup (either plain or LUKS) volumes with the same
passphrase, it is an unnecessary task to input the passphrase more than once.
Just add this script as keyscript to your /etc/crypttab and it will cache the
-passphrase of all cryptab entries with the same identifier.
+passphrase of all crypttab entries with the same identifier.
Either copy decrypt_keyctl into the default search path for keyscripts from
cryptsetup /lib/cryptdisks/scripts/. So you can just write
@@ -71,7 +71,7 @@ description).
Keyscript:
Keyctl_keyscript uses the Linux kernel keyring facility to securly cache
passphrases between multiple invocations.
-The keyfile parameter from cryptab is used to find the same passphrase between
+The keyfile parameter from crypttab is used to find the same passphrase between
multiple invocations.
Currently the cache timeout is 60 seconds and not configurable (please report a
diff --git a/debian/TODO b/debian/TODO
deleted file mode 100644
index d8351ac..0000000
--- a/debian/TODO
+++ /dev/null
@@ -1,42 +0,0 @@
-## Post-Stretch
-
-* systemd is the default init system since stretch, and has its own
- logic for unlocking LUKS/dm-crypt devices. However not all options
- (in particular keyscript=) in crypttab(5) are currently implemented,
- hence crypttab(5) entries with unsupported options can't be processed
- aftet pivot_root(8). We should either convince the systemd
- maintainers to merge patches implementing the missing options, or skip
- systemd's own cryptsetup helper. Cf.
- https://lists.alioth.debian.org/pipermail/pkg-systemd-maintainers/2016-September/012641.html
-* cryptroot hook script:
- - Parent device detection for multiple-parent-device support is spread
- all over the hook. for btrfs, the source devices are detected in
- get_fs_device(), for lvm a dedicated function exists and it is invoked
- from add_device().
- - After doing the above refactoring, we should add parent device detection
- for mdadm (#629236) and ZFS (#820888) so users don't have to manually add
- the 'initramfs' option to the crypttab.
-* cryptroot local-top script:
- - Find a solution to run 'lvm vgchange' only after all lvm parent devices
- are unlocked. At the moment, ugly errors and warnings are shown in case
- of several encrypted parent devices.
-
-
-## Post-Lenny
-
-* Would a fallback make sense? like when using any keyscript, try passphrase
- in the case that it fails. if we implement that at all, never make it the
- default, and warn about security issues in README.Debian. even explain that
- backup passphrase keyslots thwart the extra security of keyfiles/keyscripts.
- (#438481, #471729)
-
-* Implement something like 'ignore-if-no-device' to mount (/etc/fstab), and
- thus support several situations where cryptsetup fails to setup a device:
- -> the device is not attached at all
- -> wrong passphrase/no keyfile available
- -> timeouts arise
- (#474120)
- * seems like the fstab flag alread does exists: nofail. so reimplement
- timeout?
-
-* Reimplement timeout support in a cleaner way?
diff --git a/debian/TODO.md b/debian/TODO.md
new file mode 100644
index 0000000..28db74d
--- /dev/null
+++ b/debian/TODO.md
@@ -0,0 +1,71 @@
+# TODO list
+
+* luksSuspend integration
+ * https://www.freedesktop.org/wiki/Software/systemd/inhibit/ might give a cleaner interface
+ * https://lwn.net/Articles/582648/ (flag is now `SUSPEND_SKIP_SYNC`)
+ * https://guilhem.org/tmp/suspend
+ * implementations for other distros:
+ * https://github.com/jonasmalacofilho/ubuntu-luks-suspend
+ * https://github.com/vianney/arch-luks-suspend
+ * https://github.com/zhongfu/ubuntu-luks-suspend
+ * https://github.com/Microcentillion/ubuntu-lukssuspend/
+ * https://askubuntu.com/questions/348196/how-do-i-enable-ubuntu-using-full-disk-encryption-to-call-lukssupend-before-sl#675540
+ * https://superuser.com/questions/648333/how-to-make-suspend-to-ram-secure-on-ubuntu-with-full-disk-encryption-lvm-on-to#676531
+ * clearly document the limits: data in memory is never protected
+ * suspend/resume
+ * root@debian:~# systemctl suspend
+ * root@debian:~# (qemu) info status
+ * VM status: paused (suspended)
+ * (qemu) sendkey x
+ * (qemu) info status
+ * VM status: running
+
+* luks nuke feature
+ * https://www.kali.org/tutorials/nuke-kali-linux-luks/
+ * https://pkg.kali.org/pkg/cryptsetup
+ * https://github.com/offensive-security/cryptsetup-nuke-keys
+ * TODO:
+ * review and improve original patch to address upstream's concerns
+ * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/7184
+ * patch luks2 functions to support it as well
+ * documentation in manpage (and README.Debian?)
+ * bash completion
+
+* systemd integration and future of cryptscripts
+ * patch cryptsetup.c in systemd to support cryptscripts?
+ * try the patches
+ * https://github.com/systemd/systemd/pull/3007#pullrequestreview-39358162
+ * https://lists.freedesktop.org/archives/systemd-devel/2012-June/005693.html
+ * or completely remove crytpscripts feature from cryptsetup in Debian?
+
+* ephemeral swap encryption
+
+* improve test suite
+
+* cryptroot hook script:
+ - We should add parent device detection for mdadm (#629236) and ZFS (#820888)
+ so users don't have to manually add the 'initramfs' option to the crypttab.
+* cryptroot local-top script:
+ - Find a solution to run 'lvm vgchange' only after all lvm parent devices
+ are unlocked. At the moment, ugly errors and warnings are shown in case
+ of several encrypted parent devices.
+
+
+## Old list
+
+* Would a fallback make sense? like when using any keyscript, try passphrase
+ in the case that it fails. if we implement that at all, never make it the
+ default, and warn about security issues in README.Debian. even explain that
+ backup passphrase keyslots thwart the extra security of keyfiles/keyscripts.
+ (#438481, #471729)
+
+* Implement something like 'ignore-if-no-device' to mount (/etc/fstab), and
+ thus support several situations where cryptsetup fails to setup a device:
+ -> the device is not attached at all
+ -> wrong passphrase/no keyfile available
+ -> timeouts arise
+ (#474120)
+ * seems like the fstab flag alread does exists: nofail. so reimplement
+ timeout?
+
+* Reimplement timeout support in a cleaner way?
diff --git a/debian/askpass.c b/debian/askpass.c
index 44b7599..39df952 100644
--- a/debian/askpass.c
+++ b/debian/askpass.c
@@ -21,7 +21,7 @@
#define _GNU_SOURCE
-#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <unistd.h>
diff --git a/debian/changelog b/debian/changelog
index 32c3752..c67aae1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,57 @@
+cryptsetup (2:2.0.3-5) unstable; urgency=medium
+
+ [ Jonas Meurer ]
+ * debian/askpass.c, debian/scripts/passdev.c, debian/rules:
+ + Drop _BSD_SOURCE in favor of _DEFAULT_SOURCE
+ + Drop c99 std, as the default is now higher than that
+ * debian/control:
+ + Drop explicit dependencies on libgcrypt20 and libgpg-error0 from
+ libcryptsetup12. They're pulled in by ${shlibs:Depends} automatically.
+
+ [ Guilhem Moulin ]
+ * debian/initramfs/cryptroot-unlock: Keep looping forever (as long as the
+ disk is locked) if the CRYPTTAB_OPTION_tries variable is set to 0, cf.
+ crypttab(5).
+ * debian/doc/crypttab.xml: Clarify that the 'readonly' flag sets up a
+ read-only mapping. Cf. `cryptsetup --readonly`.
+ * debian/initramfs/hooks/cryptroot:
+ + Fix generation of initrd crypttab(5) with `update-initramfs -u -v` for
+ key files matching $KEYFILE_PATTERN, or when a 'keyscript' is specified
+ in the crypttab options. Regression since 2:2.0.3-2. (Closes: #902733.)
+ + Avoid processing entries multiple times in get_crypttab_entry(), which
+ could happen with 'keyscript=decrypt_derived' for instance.
+ + Don't complain that the sysfs dir can't be found when the hook failed to
+ normalize the device (another warning is shown already).
+ + If source device is mapped (for instance if it's a logical volume), put
+ its dm name into the initrd crypttab. LVM2's local-block script doesn't
+ work with UUIDs, and giving it a VG+LV is better anyway as we avoid to
+ activate all volumes at initramfs stage. (Closes: #902943.)
+ * debian/initramfs/conf-hook: Clarify that if KEYFILE_PATTERN if null or
+ unset then no key file is copied.
+ * debian/initramfs/*, debian/functions, debian/cryptdisks-functions:
+ + Use major:minor device IDs internally, as this facilitate discovery of
+ sysfs directories, and we don't have to take care of the udev mangling.
+ + Decode octal sequences when reading /etc/crypttab or /etc/fstab. This
+ means that key files and option values can contain blanks and special
+ characters encoded as octal sequences.
+ + Refactor crypttab(5) parsing logic, to avoid duplication of boilerplate
+ code.
+ * debian/functions: If the key file is a symlink, warn about insecure
+ permissions of the target, not the link itself.
+ * debian/scripts/decrypt_derived: For devices with keys in the kernel
+ keyring (e.g., LUKS2 by default), refuse to derive anything.
+ * debian/patches/disable-internal-tests.patch: Add configure option
+ '--disable-internal-tests' to disable the internal test suite.
+ * debian/rules: Don't run upstream's internal test suite if
+ $DEB_BUILD_OPTIONS contains the string "skip-internal-tests". (Tests are
+ still run by default.)
+ * debian/cryptdisks-functions: Restore support for crypttab(5) entries with
+ regular files as source device. Regression since 2:2.0.3-2.
+ (Closes: #902879.)
+ * debian/control: Bump Standards-Version to 4.1.5 (no changes necessary).
+
+ -- Guilhem Moulin <guilhem@debian.org> Sat, 07 Jul 2018 01:47:57 +0200
+
cryptsetup (2:2.0.3-4~dschinn1) dschinn-backports; urgency=low
* Uploading to dschinn-backports, remaining changes:
diff --git a/debian/checks/blkid b/debian/checks/blkid
index e679d94..490c93c 100644
--- a/debian/checks/blkid
+++ b/debian/checks/blkid
@@ -16,7 +16,7 @@ fi
dev="$1"
fs="$2"
-blkid="$(/sbin/blkid -o value -s TYPE -p $dev)"
+blkid="$(/sbin/blkid -o value -s TYPE -p -- "$dev")"
# blkid output is empty if $dev has an unknown filesystem
if [ -z "$blkid" ] && [ -z "$fs" ]; then
diff --git a/debian/checks/un_blkid b/debian/checks/un_blkid
index 6392286..ef98fc8 100644
--- a/debian/checks/un_blkid
+++ b/debian/checks/un_blkid
@@ -15,7 +15,7 @@ fi
dev="$1"
fs="$2"
-blkid="$(/sbin/blkid -o value -s TYPE -p $dev)"
+blkid="$(/sbin/blkid -o value -s TYPE -p -- "$dev")"
# blkid output is empty if $dev has an unknown filesystem
if [ -n "$blkid" ] && [ -z "$fs" ]; then
diff --git a/debian/control b/debian/control
index 8d16f41..e16cc2f 100644
--- a/debian/control
+++ b/debian/control
@@ -28,7 +28,7 @@ Build-Depends: autoconf,
po-debconf,
uuid-dev,
xsltproc
-Standards-Version: 4.1.4
+Standards-Version: 4.1.5
Homepage: https://gitlab.com/cryptsetup/cryptsetup
Vcs-Browser: https://sources.progress-linux.org/distributions/dschinn-backports/packages/cryptsetup
Vcs-Git: https://sources.progress-linux.org/distributions/dschinn-backports/packages/cryptsetup
@@ -102,10 +102,7 @@ Package: libcryptsetup12
Section: libs
Architecture: linux-any
Multi-Arch: same
-Depends: libgcrypt20,
- libgpg-error0,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends: ${misc:Depends}, ${shlibs:Depends}
Description: disk encryption support - shared library
Cryptsetup provides an interface for configuring encryption on block
devices (such as /home or swap partitions), using the Linux kernel
diff --git a/debian/cryptdisks-functions b/debian/cryptdisks-functions
index 7cc28ae..555f459 100644
--- a/debian/cryptdisks-functions
+++ b/debian/cryptdisks-functions
@@ -4,7 +4,6 @@
# and should not be executed directly.
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
-TABFILE=${TABFILE-"/etc/crypttab"}
CRYPTDISKS_ENABLE="Yes"
#set -x
@@ -13,6 +12,7 @@ CRYPTDISKS_ENABLE="Yes"
[ -x /sbin/cryptsetup ] || exit 0
. /lib/lsb/init-functions
+. /lib/cryptsetup/functions
if [ -r /etc/default/cryptdisks ]; then
. /etc/default/cryptdisks
@@ -20,13 +20,10 @@ fi
MOUNT="$CRYPTDISKS_MOUNT"
-. /lib/cryptsetup/functions
-
# do_start()
# Unlock all devices in the crypttab(5)
do_start() {
- local target source key options
[ -s "$TABFILE" ] || return 0
# Create locking directory before invoking cryptsetup(8) to avoid warnings
@@ -40,14 +37,14 @@ do_start() {
fi
mount_fs
- while read target source key options <&3; do
- [ "${target#\#}" = "$target" ] || continue
- setup_mapping "$target" "$source" "$key" "$options" 3<&- || log_action_end_msg $?
- done 3< "$TABFILE"
+ crypttab_foreach_entry _do_start_callback
umount_fs
log_action_end_msg 0
}
+_do_start_callback() {
+ setup_mapping || log_action_end_msg $?
+}
# mount_fs()
# Premounts file systems
@@ -71,19 +68,17 @@ umount_fs() {
done
}
-# setup_mapping($target, $source, $key, $options)
-# Set up a given crypttab(5) mapping
+# setup_mapping()
+# Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME,
+# $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS.
setup_mapping() {
- export CRYPTTAB_NAME="$1" CRYPTTAB_SOURCE="$2" CRYPTTAB_OPTIONS="$4"
- local key="$3"
-
- if [ -e "/dev/mapper/$CRYPTTAB_NAME" ]; then
+ if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
device_msg "running"
return 0
fi
local loud="${DEFAULT_LOUD:-}"
- crypttab_parse_options || return 1
+ crypttab_parse_options --export || return 1
if [ -n "${CRYPTTAB_OPTION_quiet+x}" ]; then
loud="no"
elif [ -n "${CRYPTTAB_OPTION_loud+x}" ]; then
@@ -99,8 +94,8 @@ setup_mapping() {
return 0
fi
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$key" != "none" ]; then
- if ! check_key "$key"; then
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
+ if ! crypttab_key_check; then
device_msg "invalid key"
return 1
fi
@@ -108,16 +103,18 @@ setup_mapping() {
fi
local source
- if ! source="$(normalise_device --quiet "$CRYPTTAB_SOURCE" )"; then
- if [ "$loud" = "yes" ]; then
- device_msg "skipped, device $CRYPTTAB_SOURCE does not exist"
+ if [ ! -f "$CRYPTTAB_SOURCE" ]; then
+ if ! source="$(get_device_id --quiet "$CRYPTTAB_SOURCE")"; then
+ if [ "$loud" = "yes" ]; then
+ device_msg "skipped, device $CRYPTTAB_SOURCE does not exist"
+ fi
+ return 1
fi
- return 1
+ CRYPTTAB_SOURCE="/dev/block/$source"
fi
- CRYPTTAB_SOURCE="$source"
device_msg "starting"
- local type="$(get_crypt_type)" out
+ local type="$(get_crypt_type)" out tmpdev
if [ "$type" != "luks" ]; then
if ! out="$(/lib/cryptsetup/checks/un_blkid "$CRYPTTAB_SOURCE" 2>/dev/null)" &&
! /lib/cryptsetup/checks/blkid "$CRYPTTAB_SOURCE" swap >/dev/null; then
@@ -130,40 +127,41 @@ setup_mapping() {
fi
local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype rv
- local tmptarget="${CRYPTTAB_NAME}_unformatted" # XXX potential conflict
+ local target="$CRYPTTAB_NAME"
+ CRYPTTAB_NAME="${CRYPTTAB_NAME}_unformatted" # XXX potential conflict
while [ $maxtries -le 0 ] || [ $count -lt $maxtries ]; do
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$key" != "none" ]; then
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
# unlock via keyfile
- unlock_mapping "$key" "$tmptarget"
+ unlock_mapping "$CRYPTTAB_KEY"
else
# unlock interactively or via keyscript
- run_keyscript "$key" "$count" | unlock_mapping - "$tmptarget"
+ CRYPTTAB_NAME="$target" run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping
fi
rv=$?
count=$(( $count + 1 ))
- if [ $rv -ne 0 ] || [ ! -e "/dev/mapper/$tmptarget" ]; then
+ if [ $rv -ne 0 ] || ! tmpdev="$(dm_blkdevname "$CRYPTTAB_NAME")"; then
continue
fi
if [ -n "${CRYPTTAB_OPTION_check+x}" ] && \
- ! "$CRYPTTAB_OPTION_check" "/dev/mapper/$tmptarget" $CRYPTTAB_OPTION_checkargs ; then
- log_warning_msg "$CRYPTTAB_NAME: the check for '/dev/mapper/$tmptarget' failed"
- cryptsetup remove -- "$tmptarget"
+ ! "$CRYPTTAB_OPTION_check" "$tmpdev" $CRYPTTAB_OPTION_checkargs ; then
+ log_warning_msg "$target: the check for '$CRYPTTAB_NAME' failed"
+ cryptsetup remove -- "$CRYPTTAB_NAME"
continue
fi
if [ "${CRYPTTAB_OPTION_swap+x}" ]; then
- if out="$(/lib/cryptsetup/checks/un_blkid "/dev/mapper/$tmptarget" 2>/dev/null)" ||
- /lib/cryptsetup/checks/blkid "/dev/mapper/$tmptarget" swap >/dev/null 2>&1; then
- mkswap "/dev/mapper/$tmptarget" >/dev/null 2>&1
+ if out="$(/lib/cryptsetup/checks/un_blkid "$tmpdev" 2>/dev/null)" ||
+ /lib/cryptsetup/checks/blkid "$tmpdev" swap >/dev/null 2>&1; then
+ mkswap "$tmpdev" >/dev/null 2>&1
else
- log_warning_msg "$CRYPTTAB_NAME: the check for '/dev/mapper/$tmptarget' failed. /dev/mapper/$tmptarget contains data: $out"
- cryptsetup remove -- "$tmptarget"
+ log_warning_msg "$target: the check for '$CRYPTTAB_NAME' failed. $CRYPTTAB_NAME contains data: $out"
+ cryptsetup remove -- "$CRYPTTAB_NAME"
return 1
fi
elif [ "${CRYPTTAB_OPTION_tmp+x}" ]; then
local tmpdir="$(mktemp --tmpdir="/run/cryptsetup" --directory)" rv=0
- if ! mkfs -t "$CRYPTTAB_OPTION_tmp" -q "/dev/mapper/$tmptarget" >/dev/null 2>&1 ||
- ! mount -t "$CRYPTTAB_OPTION_tmp" "/dev/mapper/$tmptarget" "$tmpdir" ||
+ if ! mkfs -t "$CRYPTTAB_OPTION_tmp" -q "$tmpdev" >/dev/null 2>&1 ||
+ ! mount -t "$CRYPTTAB_OPTION_tmp" "$tmpdev" "$tmpdir" ||
! chmod 1777 "$tmpdir"; then
rv=1
fi
@@ -174,58 +172,36 @@ setup_mapping() {
if command -v udevadm >/dev/null 2>&1; then
udevadm settle
fi
- dmsetup rename "$tmptarget" "$CRYPTTAB_NAME"
- device_msg "started"
+ dmsetup rename -- "$CRYPTTAB_NAME" "$target"
+ device_msg "$target" "started"
return 0
done
- device_msg "failed"
- return 1
-}
-
-# crypttab_find_target($name)
-# Look for a crypttab(5) entry with target $name, and set
-# CRYPTTAB_NAME, CRYPTTAB_SOURCE, CRYPTTAB_KEY and CRYPTTAB_OPTIONS if
-# there a match.
-crypttab_find_target() {
- local name="$1"
- local target source key options
- while read target source key options; do
- [ "${target#\#}" = "$target" ] || continue
- if [ "$target" = "$name" ]; then
- CRYPTTAB_NAME="$target"
- CRYPTTAB_SOURCE="$source"
- CRYPTTAB_KEY="$key"
- CRYPTTAB_OPTIONS="$options"
- return 0
- fi
- done <"$TABFILE"
+ device_msg "$target" "failed"
return 1
}
# Removes all mappings in crypttab
-do_stop () {
- local target source key options i rv
-
+do_stop() {
dmsetup mknodes
log_action_begin_msg "Stopping $INITSTATE crypto disks"
- while read target source key options <&3; do
- [ "${target#\#}" = "$target" ] || continue
- for i in 1 2 4 8 16 32; do
- remove_mapping "$target" "$options" 3<&- && break || rv=$?
- if [ $rv -eq 1 ] || [ $rv -eq 2 -a $i -gt 16 ]; then
- log_action_end_msg $rv
- break
- fi
- log_action_cont_msg "$target busy..."
- sleep $i
- done
- done 3< "$TABFILE"
-
+ crypttab_foreach_entry _do_stop_callback
log_action_end_msg 0
}
+_do_stop_callback() {
+ local i rv=0
+ for i in 1 2 4 8 16 32; do
+ remove_mapping "$CRYPTTAB_NAME" 3<&- && break || rv=$?
+ if [ $rv -eq 1 ] || [ $rv -eq 2 -a $i -gt 16 ]; then
+ log_action_end_msg $rv
+ break
+ fi
+ log_action_cont_msg "$CRYPTTAB_NAME busy..."
+ sleep $i
+ done
+}
-# device_msg($message)
+# device_msg([$name], $message)
# Convenience function to handle $VERBOSE
device_msg() {
local name message
@@ -242,12 +218,12 @@ device_msg() {
fi
}
-# remove_mapping($target, $options)
+# remove_mapping($target)
# Remove mapping $target
remove_mapping() {
- local CRYPTTAB_NAME="$1" options="$2"
+ local CRYPTTAB_NAME="$1"
- if [ ! -b "/dev/mapper/$CRYPTTAB_NAME" ]; then
+ if ! dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
device_msg "stopped"
return 0
fi
@@ -257,9 +233,6 @@ remove_mapping() {
return 1
fi
- crypttab_parse_options "$options" n 2>/dev/null || true
-
-
local opencount="$(dmsetup info -c --noheadings -o open -- "$CRYPTTAB_NAME" 2>/dev/null || true)"
if [ -z "$opencount" ]; then
device_msg "error"
diff --git a/debian/cryptsetup-run.postinst b/debian/cryptsetup-run.postinst
index 1c9eece..199bea2 100644
--- a/debian/cryptsetup-run.postinst
+++ b/debian/cryptsetup-run.postinst
@@ -16,51 +16,15 @@ set -e
case "$1" in
configure)
- for file in cryptdisks_start cryptdisks_stop; do
- if [ ! -e /usr/sbin/$file ]; then
- ln -s /sbin/$file /usr/sbin/$file
- fi
- done
-
- # Do a number of checks on the currently installed crypttab
-
- egrep -v "^[[:space:]]*(#|$)" /etc/crypttab | while read dst src key opts; do
- if [ -z "$dst" ]; then
- continue
- elif [ -z "$src" ] || [ -z "$key" ] || [ -z "$opts" ]; then
- # All fields must be present
- echo "WARNING: $dst in /etc/crypttab is missing some arguments, see man cryptab(5)." >&2
- continue
- else
- # Strip comments - https://bugs.launchpad.net/bugs/185380
- opts=$(echo -n $opts | sed 's/ *#.*//')
- plainopts="0"
- IFS=','
- for opt in $opts; do
- PARAM=$(echo "$opt" | sed 's/=.*//')
- case "$PARAM" in
- # Some options are deprecated
- gpg)
- echo "WARNING: $dst in /etc/crypttab uses the deprecated gpg option, see man crypttab(5)." >&2
- ;;
- ssl)
- echo "WARNING: $dst in /etc/crypttab uses the deprecated ssl option, see man crypttab(5)." >&2
- ;;
- luks)
- plainopts="2"
- ;;
- cipher|size)
- plainopts="$(($plainopts+1))"
- ;;
- esac
- done
- if [ "$plainopts" -lt 2 ]; then
- echo "WARNING: you need to set both cipher and size for the plain dm-crypt mapping $dst in /etc/crypttab." >&2
- fi
- unset IFS
- fi
-
- done
+ for file in cryptdisks_start cryptdisks_stop; do
+ if [ ! -e "/usr/sbin/$file" ]; then
+ ln -s "/sbin/$file" "/usr/sbin/$file"
+ fi
+ done
+
+ # Do a number of checks on the currently installed crypttab
+ . /lib/cryptsetup/functions
+ crypttab_foreach_entry crypttab_parse_options || true
;;
abort-upgrade|abort-remove|abort-deconfigure)
diff --git a/debian/doc/crypttab.xml b/debian/doc/crypttab.xml
index e839634..4512c6a 100644
--- a/debian/doc/crypttab.xml
+++ b/debian/doc/crypttab.xml
@@ -57,7 +57,8 @@
as a key for decrypting the data of the <emphasis>source device</emphasis>.
In case of a <emphasis>keyscript</emphasis>, the value of this field is
given as argument to the keyscript. Values with spaces and special
- characters need to be quoted.
+ characters need to be escaped using octal sequence, like for
+ <emphasis>fstab(5)</emphasis>.
Note that the <emphasis>entire</emphasis> key file will be used as the
passphrase; the passphrase must <emphasis>not</emphasis> be followed by a
newline character.
@@ -217,7 +218,7 @@
<varlistentry>
<term><emphasis>readonly</emphasis>, <emphasis>read-only</emphasis></term>
<listitem>
- <simpara>The backing device is read-only (eg: a dvd).</simpara>
+ <simpara>Set up a read-only mapping.</simpara>
</listitem>
</varlistentry>
diff --git a/debian/functions b/debian/functions
index 3835f7e..195ac93 100644
--- a/debian/functions
+++ b/debian/functions
@@ -1,10 +1,20 @@
-TABFILE="${TABFILE-/etc/crypttab}"
+if [ "${0#/usr/share/initramfs-tools/hooks/}" != "$0" ] ||
+ [ "${0#/etc/initramfs-tools/hooks/}" != "$0" ]; then
+ # called from an initramfs-tools hook script
+ TABFILE="$DESTDIR/cryptroot/crypttab"
+elif [ "${0#/scripts/}" != "$0" ]; then
+ # called at initramfs stage from a boot script
+ TABFILE="/cryptroot/crypttab"
+else
+ TABFILE="${TABFILE-/etc/crypttab}"
+fi
+export DM_DEFAULT_NAME_MANGLING_MODE=hex # for dmsetup(8)
# Logging helpers. Send the argument list to plymouth(1), or fold it
# and print it to the standard error.
cryptsetup_message() {
local IFS=' '
- if [ "${INITSTATE-}" = "initramfs" ] && [ -x /bin/plymouth ] && plymouth --ping; then
+ if [ "${0#/scripts/}" != "$0" ] && [ -x /bin/plymouth ] && plymouth --ping; then
plymouth message --text="cryptsetup: $*"
elif [ ${#*} -lt 70 ]; then
echo "cryptsetup: $*" >&2
@@ -15,12 +25,27 @@ cryptsetup_message() {
return 0
}
-# crypttab_parse_options([$CRYPTTAB_OPTIONS, $export])
-# Parse CRYPTTAB_OPTIONS, a comma-separated option string from the
-# crypttab(5) 4th column, build a suitable CRYPTTAB_OPTION_<option>
-# environment unless $export is "n"
+# crypttab_parse_options([--export], [--quiet])
+# Parse $_CRYPTTAB_OPTIONS, a comma-separated option string from the
+# crypttab(5) 4th column, and sets corresponding variables
+# CRYPTTAB_OPTION_<option>=<value> (which are added to the environment
+# if --export is set).
+# For error and warning messages, CRYPTTAB_NAME, (resp. CRYPTTAB_KEY)
+# should be set to the (unmangled) mapped device name (resp. key
+# file).
+# Return 1 on parsing error, 0 otherwise (incl. if unknown options
+# were encountered).
crypttab_parse_options() {
- local options="${1:-$CRYPTTAB_OPTIONS}" export="${2:-y}"
+ local quiet="n" export="n"
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --quiet) quiet="y";;
+ --export) export="y";;
+ *) cryptsetup_message "WARNING: crypttab_parse_options(): unknown option $1"
+ esac
+ shift
+ done
+
local IFS=',' x OPTION VALUE
unset -v CRYPTTAB_OPTION_cipher \
CRYPTTAB_OPTION_size \
@@ -48,38 +73,45 @@ crypttab_parse_options() {
CRYPTTAB_OPTION_keyslot \
CRYPTTAB_OPTION_header \
CRYPTTAB_OPTION_tcrypthidden
- for x in $options; do
+ # use $_CRYPTTAB_OPTIONS not $CRYPTTAB_OPTIONS as options values may
+ # contain '\054' which is decoded to ',' in the latter
+ for x in $_CRYPTTAB_OPTIONS; do
OPTION="${x%%=*}"
VALUE="${x#*=}"
if [ "$x" = "$OPTION" ]; then
unset -v VALUE
+ else
+ VALUE="$(printf '%b' "$VALUE")"
fi
- if ! _crypttab_validate_option; then
- cryptsetup_message "ERROR: $CRYPTTAB_NAME: invalid value for '${x%%=*}' option, skipping"
+ if ! crypttab_validate_option; then
+ if [ "$quiet" = "n" ]; then
+ cryptsetup_message "ERROR: $CRYPTTAB_NAME: invalid value for '${x%%=*}' option, skipping"
+ fi
return 1
elif [ -z "${OPTION+x}" ]; then
continue
fi
- if [ "$export" != "n" ]; then
+ if [ "$export" = "y" ]; then
export "CRYPTTAB_OPTION_$OPTION"="${VALUE-yes}"
else
eval "CRYPTTAB_OPTION_$OPTION"='${VALUE-yes}'
fi
done
- IFS=' '
+ IFS=" "
- if [ -z "${CRYPTTAB_OPTION_luks+x}" ] && [ -n "${CRYPTTAB_OPTION_header+x}" ]; then
+ if [ "$quiet" = "n" ] &&
+ [ -z "${CRYPTTAB_OPTION_luks+x}" ] && [ -n "${CRYPTTAB_OPTION_header+x}" ]; then
cryptsetup_message "WARNING: Option 'luks' missing in crypttab for target $CRYPTTAB_NAME." \
"Headers are only supported for LUKS devices."
fi
if [ -z "${CRYPTTAB_OPTION_luks+x}" ] && [ -z "${CRYPTTAB_OPTION_tcrypt+x}" ]; then
# the compiled-in default for these are subject to change
options='cipher size'
- if [ -n "${CRYPTTAB_OPTION_keyscript+x}" ] || [ "$key" = "none" ]; then
+ if [ -n "${CRYPTTAB_OPTION_keyscript+x}" ] || [ "$CRYPTTAB_KEY" = "none" ]; then
options="$options hash" # --hash is being ignored in plain mode with keyfile specified
fi
for o in $options; do
- if eval [ -z "\${CRYPTTAB_OPTION_$o+x}" ]; then
+ if [ "$quiet" = "n" ] && eval [ -z "\${CRYPTTAB_OPTION_$o+x}" ]; then
cryptsetup_message "WARNING: Option '$o' missing in crypttab for plain dm-crypt" \
"mapping $CRYPTTAB_NAME. Please read /usr/share/doc/cryptsetup/README.initramfs and" \
"add the correct '$o' option to your crypttab(5)."
@@ -88,10 +120,10 @@ crypttab_parse_options() {
fi
}
-# _crypttab_validate_option()
+# crypttab_validate_option()
# Validate $OPTION=$VALUE (or flag $OPTION if VALUE is unset). return
# 1 on error, unsets OPTION for unknown or useless options.
-_crypttab_validate_option() {
+crypttab_validate_option() {
# option aliases
case "$OPTION" in
read-only) OPTION="readonly";;
@@ -174,112 +206,57 @@ _crypttab_validate_option() {
veracrypt) ;;
tcrypthidden) ;;
*)
- cryptsetup_message "WARNING: $CRYPTTAB_NAME: ignoring unknown option '$o'";
+ if [ "${quiet:-n}" = "n" ]; then
+ cryptsetup_message "WARNING: $CRYPTTAB_NAME: ignoring unknown option '$o'";
+ fi
unset -v OPTION
;;
esac
}
-# crypttab_copy_keys_to_initramfs($keyscript)
-# Copy keys to the initramfs image for each crypttab(5) entry using
-# the given $keyscript.
-# Return 0 on success, 1 on error. Exits if the keyscript isn't
-# already installed to the initramfs (by the cryptroot hook file).
-crypttab_copy_keys_to_initramfs() {
- local keyscript="/lib/cryptsetup/scripts/$1"
- local crypttab="$DESTDIR/cryptroot/crypttab"
- local CRYPTTAB_NAME CRYPTTAB_SOURCE key options v
- local rv=0
-
- if [ ! -x "$DESTDIR/$keyscript" ] || [ ! -f "$crypttab" ]; then
- exit 0
- fi
-
- # Install cryptroot key files into initramfs
- while read CRYPTTAB_NAME CRYPTTAB_SOURCE key options; do
- [ "${CRYPTTAB_NAME#\#}" = "$CRYPTTAB_NAME" ] || continue
- crypttab_parse_options "$options" n || continue
- if [ "${CRYPTTAB_OPTION_keyscript-}" = "$keyscript" ]; then
- if [ -f "$key" ]; then
- copy_file keyfile "$key"
- else
- cryptsetup_message "ERROR: Target $CRYPTTAB_NAME has a non-existing key file $key"
- rv=1
- fi
- fi
- done <"$crypttab"
- return $rv
-}
-
-# gen_crypttab_from_kernel_cmdline()
-# Create or replace the initramfs' crypttab(5) with the entries
-# computed from the "cryptopts" kernel boot arguments, if there are
-# any. (If there are no "cryptopts" kernel boot arguments, then the
-# initramfs' crypttab(5) is preserved.) This function always touches
-# /cryptroot/crypttab, so other scripts can determine whether it is up
-# to date by comparing its ctime with the uptime.
-gen_crypttab_from_kernel_cmdline() {
- mkdir -p /cryptroot # might not exist if there is no crypttab(5) yet
- if ! grep -qE '^(.*\s)?cryptopts=' /proc/cmdline; then
- touch /cryptroot/crypttab
- return 0
- fi
-
- local IFS=',' cryptopts x
- local target source key options
- tr ' ' '\n' </proc/cmdline | sed -n 's/^cryptopts=//p' | while read cryptopts; do
- # skip empty values (which can be used to disable the initramfs
- # scripts for a particular boot, cf. #873840)
- [ -n "$cryptopts" ] || continue
-
- unset -v target source key options
- for x in $cryptopts; do
- case "$x" in
- target=*) target="${x#target=}";;
- source=*) source="${x#source=}";;
- key=*) key="${x#key=}";;
- *) options="${options+$options,}$x";;
- esac
- done
- if [ -z "${source:+x}" ]; then
- cryptsetup_message "ERROR: Missing source= value in kernel parameter cryptopts=$cryptopts"
- continue
- else
- printf '%s %s %s %s\n' "${target:-cryptroot}" "$source" \
- "${key:-none}" "$options"
- fi
- done >/cryptroot/crypttab
+# get_device_id([--quiet], $device)
+# Print major-ID:minor-ID, where major-ID (resp. minor-ID) is the
+# major (resp. minor) ID decimal value of the given (symlink to a)
+# block $device.
+# Like for fstab(5), LABEL=<label> UUID=<uuid>, PARTUUID=<partuuid>
+# and PARTLABEL=<partlabel> may be given instead of a device path.
+# Return 0 on success, 1 on error.
+get_device_id() {
+ local MAJ MIN
+ resolve_device_id "$@" || return $?
+ printf '%d:%d\n' "$MAJ" "$MIN"
return 0
}
-# normalise_device([--quiet],$device)
-# Print the block device (not symlink) associated with the given
-# (link to a) block $device. Like for fstab(5), LABEL=<label>
-# UUID=<uuid>, PARTUUID=<partuuid> and PARTLABEL=<partlabel> may be
-# given instead of a device name.
-# Return 0 on success, 1 on error.
-normalise_device() {
+# resolve_device_id([--quiet], $device)
+# Like get_device_id(), but don't print anything and instead set MAJ
+# (resp. MIN) to the major-ID (resp. minor ID) decimal value on
+# success.
+resolve_device_id() {
local dev="$1" quiet='n'
if [ "$dev" = '--quiet' ] && [ $# -eq 2 ]; then
quiet='y'
dev="$2"
fi
- local input="$dev"
- if [ "${dev#UUID=}" != "$dev" ] && [ -n "${dev#UUID=}" ]; then
- dev="/dev/disk/by-uuid/${dev#UUID=}"
- elif [ "${dev#LABEL=}" != "$dev" ] && [ -n "${dev#LABEL=}" ]; then
- dev="/dev/disk/by-label/$(printf '%s' "${dev#LABEL=}" | sed 's,/,\\x2f,g')"
- elif [ "${dev#PARTUUID=}" != "$dev" ] && [ -n "${dev#PARTUUID=}" ]; then
- dev="/dev/disk/by-partuuid/${dev#PARTUUID=}"
- elif [ "${dev#PARTLABEL=}" != "$dev" ] && [ -n "${dev#PARTLABEL=}" ]; then
- dev="/dev/disk/by-partlabel/$(printf '%s' "${dev#PARTLABEL=}" | sed 's,/,\\x2f,g')"
- fi
- if dev="$(readlink -f -- "$dev")" && [ -n "$dev" ] && [ -b "$dev" ]; then
- printf '%s\n' "$dev"
+ local arg="$dev" devno maj min
+ case "$dev" in
+ UUID=*|LABEL=*|PARTUUID=*|PARTLABEL=*)
+ # don't use /dev/disk/by-label/... to avoid gessing udev mangling
+ dev="$(blkid -l -t "$dev" -o device)" || dev=
+ ;;
+ esac
+ if [ -n "$dev" ] && [ -b "$dev" ] &&
+ devno="$(stat -L -c"%t:%T" -- "$dev" 2>/dev/null)" &&
+ maj="${devno%:*}" && min="${devno#*:}" &&
+ [ "$devno" = "$maj:$min" ] && [ -n "$maj" ] && [ -n "$min" ] &&
+ maj=$(( 0x$maj )) && min=$(( 0x$min )) && devno="$maj:$min" &&
+ [ -b "/dev/block/$devno" ]; then
+ MAJ="$maj"
+ MIN="$min"
return 0
elif [ "$quiet" = n ]; then
- cryptsetup_message "ERROR: Couldn't normalise device $input"
+ cryptsetup_message "ERROR: Couldn't resolve device $arg"
fi
return 1
}
@@ -295,6 +272,7 @@ normalise_device() {
# pipe, or similar.
run_keyscript() {
local keyscriptarg="$1" CRYPTTAB_TRIED="$2" keyscript;
+ export CRYPTTAB_NAME CRYPTTAB_SOURCE CRYPTTAB_OPTIONS
export CRYPTTAB_TRIED
if [ -n "${CRYPTTAB_OPTION_keyscript+x}" ] && \
@@ -328,15 +306,15 @@ get_crypt_type() {
echo "$type"
}
-# unlock_mapping($keyfile, $name)
+# unlock_mapping([$keyfile])
# Run cryptsetup(8) with suitable options and arguments to unlock
# $CRYPTTAB_SOURCE and setup dm-crypt managed device-mapper mapping
-# $name
+# $CRYPTTAB_NAME.
unlock_mapping() {
- local keyfile="$1" name="$2"
+ local keyfile="${1:--}"
- if [ -n "${CRYPTTAB_OPTION_header+x}" ] && [ ! -f "${CRYPTTAB_OPTION_header}" ]; then
- cryptsetup_message "ERROR: $name: LUKS header '${CRYPTTAB_OPTION_header}' missing"
+ if [ -n "${CRYPTTAB_OPTION_header+x}" ] && [ ! -f "$CRYPTTAB_OPTION_header" ]; then
+ cryptsetup_message "ERROR: $CRYPTTAB_NAME: LUKS header '$CRYPTTAB_OPTION_header' missing"
return 1
fi
@@ -380,21 +358,20 @@ unlock_mapping() {
${CRYPTTAB_OPTION_tcrypthidden:+--tcrypt-hidden} \
${CRYPTTAB_OPTION_keyfile_size:+--keyfile-size="$CRYPTTAB_OPTION_keyfile_size"} \
${CRYPTTAB_OPTION_keyfile_offset:+--keyfile-offset="$CRYPTTAB_OPTION_keyfile_offset"} \
- --type="$type" --key-file="${keyfile:--}" \
- open -- "$CRYPTTAB_SOURCE" "$name"
+ --type="$type" --key-file="$keyfile" \
+ open -- "$CRYPTTAB_SOURCE" "$CRYPTTAB_NAME"
}
-# check_key($keyfile)
-# Sanity check for keys
-check_key() {
- local keyfile="$1"
-
- if [ ! -f "$keyfile" ] && [ ! -b "$keyfile" ] && [ ! -c "$keyfile" ] ; then
- cryptsetup_message "WARNING: $CRYPTTAB_NAME: keyfile '$keyfile' not found"
+# crypttab_key_check()
+# Sanity checks for keyfile $CRYPTTAB_KEY. CRYPTTAB_NAME and
+# CRYPTTAB_OPTION_<option> must be set appropriately.
+crypttab_key_check() {
+ if [ ! -f "$CRYPTTAB_KEY" ] && [ ! -b "$CRYPTTAB_KEY" ] && [ ! -c "$CRYPTTAB_KEY" ] ; then
+ cryptsetup_message "WARNING: $CRYPTTAB_NAME: keyfile '$CRYPTTAB_KEY' not found"
return 0
fi
- if [ "$keyfile" = "/dev/random" -o "$keyfile" = "/dev/urandom" ]; then
+ if [ "$CRYPTTAB_KEY" = "/dev/random" ] || [ "$CRYPTTAB_KEY" = "/dev/urandom" ]; then
if [ -n "${CRYPTTAB_OPTION_luks+x}" ] || [ -n "${CRYPTTAB_OPTION_tcrypt+x}" ]; then
cryptsetup_message "WARNING: $CRYPTTAB_NAME: has random data as key"
return 1
@@ -403,11 +380,99 @@ check_key() {
fi
fi
- local mode="$(stat -c '%04a' "$keyfile")"
- if [ $(stat -c%u "$keyfile") -ne 0 ] || [ "${mode%00}" = "$mode" ]; then
- cryptsetup_message "WARNING: $CRYPTTAB_NAME: key file $keyfile has" \
+ local mode="$(stat -L -c"%04a" -- "$CRYPTTAB_KEY")"
+ if [ $(stat -L -c"%u" -- "$CRYPTTAB_KEY") -ne 0 ] || [ "${mode%00}" = "$mode" ]; then
+ cryptsetup_message "WARNING: $CRYPTTAB_NAME: key file $CRYPTTAB_KEY has" \
"insecure ownership, see /usr/share/doc/cryptsetup/README.Debian."
fi
}
+# dm_blkdevname($name)
+# Print the mapped device name, or return 1 if the the device doesn't exist.
+dm_blkdevname() {
+ local name="$1" dev
+ # /dev/mapper/$name isn't reliable due to udev mangling
+ if dev="$(dmsetup info -c --noheadings -o blkdevname -- "$name" 2>/dev/null)" &&
+ [ -n "$dev" ] && [ -b "/dev/$dev" ]; then
+ echo "/dev/$dev"
+ return 0
+ else
+ return 1
+ fi
+}
+
+# crypttab_find_entry([--quiet], $target)
+# Search in the crypttab(5) for the given $target, and sets the
+# variables CRYPTTAB_NAME, CRYPTTAB_SOURCE, CRYPTTAB_KEY and
+# CRYPTTAB_OPTIONS accordingly. (In addition _CRYPTTAB_NAME,
+# _CRYPTTAB_SOURCE, _CRYPTTAB_KEY and _CRYPTTAB_OPTIONS are set to the
+# unmangled values before decoding the escape sequence.) If there are
+# duplicates then only the first match is considered.
+# Return 0 if a match is found, and 1 otherwise.
+crypttab_find_entry() {
+ local target="$1" quiet="n" IFS
+ if [ "$target" = "--quiet" ] && [ $# -eq 2 ]; then
+ quiet="y"
+ target="$2"
+ fi
+
+ while IFS=" " read -r _CRYPTTAB_NAME _CRYPTTAB_SOURCE _CRYPTTAB_KEY _CRYPTTAB_OPTIONS; do
+ if [ "${_CRYPTTAB_NAME#\#}" != "$_CRYPTTAB_NAME" ] || [ -z "$_CRYPTTAB_NAME" ]; then
+ # ignore comments and empty lines
+ continue
+ fi
+
+ # unmangle names
+ CRYPTTAB_NAME="$(printf '%b' "$_CRYPTTAB_NAME")"
+ if [ -z "$_CRYPTTAB_SOURCE" ] || [ -z "$_CRYPTTAB_KEY" ] || [ -z "$_CRYPTTAB_OPTIONS" ]; then
+ cryptsetup_message "WARNING: '$CRYPTTAB_NAME' is missing some arguments, see crypttab(5)"
+ continue
+ elif [ "$CRYPTTAB_NAME" = "$target" ]; then
+ CRYPTTAB_SOURCE="$( printf '%b' "$_CRYPTTAB_SOURCE" )"
+ CRYPTTAB_KEY="$( printf '%b' "$_CRYPTTAB_KEY" )"
+ CRYPTTAB_OPTIONS="$(printf '%b' "$_CRYPTTAB_OPTIONS")"
+ return 0
+ fi
+ done <"$TABFILE"
+
+ if [ "$quiet" = "n" ]; then
+ cryptsetup_message "WARNING: target '$target' not found in $TABFILE"
+ fi
+ return 1
+}
+
+# crypttab_foreach_entry($callback)
+# Iterate through the crypttab(5) and run the given $callback for each
+# entry found. Variables CRYPTTAB_NAME, CRYPTTAB_SOURCE, CRYPTTAB_KEY
+# and CRYPTTAB_OPTIONS are set accordingly and available to the
+# $callback. (In addition _CRYPTTAB_NAME, _CRYPTTAB_SOURCE,
+# _CRYPTTAB_KEY and _CRYPTTAB_OPTIONS are set to the unmangled values
+# before decoding the escape sequence.)
+# Return 0 if a match is found, and 1 otherwise.
+crypttab_foreach_entry() {
+ local callback="$1" IFS
+ local _CRYPTTAB_NAME _CRYPTTAB_SOURCE _CRYPTTAB_KEY _CRYPTTAB_OPTIONS \
+ CRYPTTAB_NAME CRYPTTAB_SOURCE CRYPTTAB_KEY CRYPTTAB_OPTIONS
+
+ while IFS=" " read -r _CRYPTTAB_NAME _CRYPTTAB_SOURCE _CRYPTTAB_KEY _CRYPTTAB_OPTIONS <&9; do
+ if [ "${_CRYPTTAB_NAME#\#}" != "$_CRYPTTAB_NAME" ] || [ -z "$_CRYPTTAB_NAME" ]; then
+ # ignore comments and empty lines
+ continue
+ fi
+
+ # unmangle names
+ CRYPTTAB_NAME="$( printf '%b' "$_CRYPTTAB_NAME" )"
+ CRYPTTAB_SOURCE="$( printf '%b' "$_CRYPTTAB_SOURCE" )"
+ CRYPTTAB_KEY="$( printf '%b' "$_CRYPTTAB_KEY" )"
+ CRYPTTAB_OPTIONS="$(printf '%b' "$_CRYPTTAB_OPTIONS")"
+
+ if [ -z "$CRYPTTAB_SOURCE" ] || [ -z "$CRYPTTAB_KEY" ] || [ -z "$CRYPTTAB_OPTIONS" ]; then
+ cryptsetup_message "WARNING: '$CRYPTTAB_NAME' is missing some arguments, see crypttab(5)"
+ continue
+ fi
+
+ "$callback" 9<&-
+ done 9<"$TABFILE"
+}
+
# vim: set filetype=sh :
diff --git a/debian/initramfs/conf-hook b/debian/initramfs/conf-hook
index 873082d..8a6a474 100644
--- a/debian/initramfs/conf-hook
+++ b/debian/initramfs/conf-hook
@@ -27,7 +27,8 @@
# /etc/keys/{root,swap}.key, you can set KEYFILE_PATTERN="/etc/keys/*.key"
# to add them to the initrd.)
#
-# Setting KEYFILE_PATTERN to a non-empty value implies "CRYPTSETUP=y".
+# If KEYFILE_PATTERN if null or unset (default) then no key file is
+# copied to the initramfs image.
#
# WARNING: If the initramfs image is to include private key material,
# you'll want to create it with a restrictive umask in order to keep
diff --git a/debian/initramfs/cryptroot-unlock b/debian/initramfs/cryptroot-unlock
index 6b4c522..11c0eab 100644
--- a/debian/initramfs/cryptroot-unlock
+++ b/debian/initramfs/cryptroot-unlock
@@ -25,21 +25,22 @@ PASSFIFO=/lib/cryptsetup/passfifo
ASKPASS=/lib/cryptsetup/askpass
UNLOCK_ALL=n
-CRYPTTAB="/cryptroot/crypttab"
-if [ ! -f "$CRYPTTAB" ] || [ "$CRYPTTAB" -ot "/proc/1" ]; then
+[ -f /lib/cryptsetup/functions ] || return 0
+. /lib/cryptsetup/functions
+TABFILE="/cryptroot/crypttab"
+unset -v IFS
+
+if [ ! -f "$TABFILE" ] || [ "$TABFILE" -ot "/proc/1" ]; then
# Too early, init-top/cryptroot hasn't finished yet
echo "Try again later" >&2
exit 1
fi
-# The list of configured devices to unlock.
-CRYPTDEVS="$(sed -nr 's/^\s*([^#[:blank:]]\S*)\s.*/\1/p' "$CRYPTTAB")"
-
# Print the list of PIDs the executed command of which is $exe.
pgrep_exe() {
local exe="$1" pid
ps -eo pid= | while read pid; do
- [ "$(readlink -f /proc/$pid/exe)" != "$exe" ] || printf '%i\n' "$pid"
+ [ "$(readlink -f "/proc/$pid/exe")" != "$exe" ] || printf '%d\n' "$pid"
done
}
@@ -68,20 +69,12 @@ get_askpass_pid() {
# Print the number of configured crypt devices that have not been unlocked yet.
count_locked_devices() {
- local dev n=0
- for dev in $CRYPTDEVS; do
- [ -b "/dev/mapper/$dev" ] || n=$(( $n + 1 ))
- done
- echo $n
+ local COUNT=0
+ crypttab_foreach_entry count_locked_devices_callback
+ printf '%d\n' "$COUNT"
}
-
-# Return 0 if the $target is in $CRYPTDEVS, and 1 otherwise.
-is_device_known() {
- local dev target="$1"
- for dev in $CRYPTDEVS; do
- [ "$dev" != "$target" ] || return 0
- done
- return 1
+count_locked_devices_callback() {
+ dm_blkdevname "$CRYPTTAB_NAME" >/dev/null || COUNT=$(( $COUNT + 1 ))
}
# Wait for askpass, then set $PID (resp. $BIRTH) to the PID (resp.
@@ -115,9 +108,19 @@ wait_for_prompt() {
done
# find the cryptsetup process with same $CRYPTTAB_NAME
- CRYPTTAB_OPTION_tries=
- eval $(grep -Ez '^CRYPTTAB_(NAME|TRIED|SOURCE|OPTION_tries)=' "/proc/$pid/environ" | tr '\0' '\n')
- if ! is_device_known "$CRYPTTAB_NAME"; then
+ local o v
+ for o in NAME TRIED OPTION_tries; do
+ if v="$(grep -z -m1 "^CRYPTTAB_$o=" "/proc/$pid/environ")"; then
+ eval "CRYPTTAB_$o"="\${v#CRYPTTAB_$o=}"
+ else
+ eval unset -v "CRYPTTAB_$o"
+ fi
+ done
+ if [ -z "${CRYPTTAB_NAME:+x}" ] || [ -z "${CRYPTTAB_TRIED:+x}" ]; then
+ return 1
+ fi
+ if ( ! crypttab_find_entry --quiet "$CRYPTTAB_NAME" ); then
+ # use a subshell to avoid polluting our enironment
echo "Error: Refusing to process unknown device $CRYPTTAB_NAME" >&2
exit 1
fi
@@ -125,7 +128,7 @@ wait_for_prompt() {
for pid in $(pgrep_exe "/sbin/cryptsetup"); do
if grep -Fxqz "CRYPTTAB_NAME=$CRYPTTAB_NAME" "/proc/$pid/environ"; then
PID=$pid
- BIRTH=$(stat -c'%Z' "/proc/$PID")
+ BIRTH=$(stat -c"%Z" "/proc/$PID" 2>/dev/null) || break
return 0
fi
done
@@ -141,8 +144,8 @@ wait_for_prompt() {
# maximum number of tries exceeded. Otherwise (if the unlocking
# failed), return with value 1.
wait_for_answer() {
- local timer=$(( 10 * $TIMEOUT )) dev
- until [ ! -d "/proc/$PID" ] || [ $(stat -c'%Z' "/proc/$PID") -gt $BIRTH ]; do
+ local timer=$(( 10 * $TIMEOUT )) b
+ while [ -d "/proc/$PID" ] && b=$(stat -c"%Z" "/proc/$PID" 2>/dev/null) && [ $b -le $BIRTH ]; do
usleep 100000
timer=$(( $timer - 1 ))
if [ $timer -le 0 ]; then
@@ -151,10 +154,11 @@ wait_for_answer() {
fi
done
- if [ -b "/dev/mapper/$CRYPTTAB_NAME" ]; then
+ if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
echo "cryptsetup: $CRYPTTAB_NAME set up successfully" >&2
[ "$UNLOCK_ALL" = y ] && return 0 || exit 0
- elif [ $(( ${CRYPTTAB_TRIED:-0} + 1 )) -ge ${CRYPTTAB_OPTION_tries:-3} ]; then
+ elif [ $(( ${CRYPTTAB_TRIED:-0} + 1 )) -ge ${CRYPTTAB_OPTION_tries:-3} ] &&
+ [ ${CRYPTTAB_OPTION_tries:-3} -gt 0 ]; then
echo "cryptsetup: maximum number of tries exceeded for $CRYPTTAB_NAME" >&2
exit 1
else
@@ -171,14 +175,17 @@ if [ -t 0 ] && [ -x "$ASKPASS" ]; then
while :; do
# note: if the script is not killed before pivot_root it should
# exit on its own once $TIMEOUT is reached
- wait_for_prompt || continue
+ if ! wait_for_prompt; then
+ usleep 100000
+ continue
+ fi
read -rs -p "Please unlock disk $CRYPTTAB_NAME: "; echo
printf '%s' "$REPLY" >"$PASSFIFO"
wait_for_answer || true
done
else
# non-interactive mode: slurp the passphrase from stdin and exit
- wait_for_prompt || continue
+ wait_for_prompt || exit 1
echo "Please unlock disk $CRYPTTAB_NAME"
cat >"$PASSFIFO"
wait_for_answer || exit 1
diff --git a/debian/initramfs/hooks/cryptgnupg b/debian/initramfs/hooks/cryptgnupg
index 4d3c60d..77a0241 100644
--- a/debian/initramfs/hooks/cryptgnupg
+++ b/debian/initramfs/hooks/cryptgnupg
@@ -19,9 +19,27 @@ esac
. /usr/share/initramfs-tools/hook-functions
. /lib/cryptsetup/functions
+if [ ! -x "$DESTDIR/lib/cryptsetup/scripts/decrypt_gnupg" ] || [ ! -f "$TABFILE" ]; then
+ exit 0
+fi
+
# Hooks for loading gnupg software and symmetrically encrypted key into
# the initramfs
-crypttab_copy_keys_to_initramfs 'decrypt_gnupg' || exit 1
+copy_keys() {
+ crypttab_parse_options
+ if [ "${CRYPTTAB_OPTION_keyscript-}" = "/lib/cryptsetup/scripts/decrypt_gnupg" ]; then
+ if [ -f "$CRYPTTAB_KEY" ]; then
+ copy_file keyfile "$CRYPTTAB_KEY"
+ else
+ cryptsetup_message "ERROR: Target $CRYPTTAB_NAME has a non-existing key file $CRYPTTAB_KEY"
+ RV=1
+ fi
+ fi
+}
+
+RV=0
+crypttab_foreach_entry copy_keys
# Install gnupg software
copy_exec /usr/bin/gpg
+exit $RV
diff --git a/debian/initramfs/hooks/cryptopensc b/debian/initramfs/hooks/cryptopensc
index 88b5de3..20cfe5d 100644
--- a/debian/initramfs/hooks/cryptopensc
+++ b/debian/initramfs/hooks/cryptopensc
@@ -19,12 +19,29 @@ esac
. /usr/share/initramfs-tools/hook-functions
. /lib/cryptsetup/functions
+if [ ! -x "$DESTDIR/lib/cryptsetup/scripts/decrypt_opensc" ] || [ ! -f "$TABFILE" ]; then
+ exit 0
+fi
+
# Hooks for loading smartcard reading software into the initramfs
-crypttab_copy_keys_to_initramfs 'decrypt_opensc' || exit 1
+copy_keys() {
+ crypttab_parse_options
+ if [ "${CRYPTTAB_OPTION_keyscript-}" = "/lib/cryptsetup/scripts/decrypt_opensc" ]; then
+ if [ -f "$CRYPTTAB_KEY" ]; then
+ copy_file keyfile "$CRYPTTAB_KEY"
+ else
+ cryptsetup_message "ERROR: Target $CRYPTTAB_NAME has a non-existing key file $CRYPTTAB_KEY"
+ RV=1
+ fi
+ fi
+}
+
+RV=0
+crypttab_foreach_entry copy_keys
# Install directories needed by smartcard reading daemon, command, and
# key-script
-mkdir -p "$DESTDIR/etc/opensc" "$DESTDIR/usr/lib/pcsc" "$DESTDIR/var/run" "$DESTDIR/tmp"
+mkdir -p -- "$DESTDIR/etc/opensc" "$DESTDIR/usr/lib/pcsc" "$DESTDIR/var/run" "$DESTDIR/tmp"
# Install pcscd daemon, drivers, conf file, and include libgcc as well since
# pcscd utilizes pthread_cancel
@@ -34,11 +51,13 @@ find -L "$LIBC_DIR" -maxdepth 1 \( -name 'libgcc_s.*' -o -name 'libusb-*.so*' -o
copy_exec "$so"
done
-cp -r /usr/lib/pcsc "$DESTDIR/usr/lib"
-cp /etc/reader.conf "$DESTDIR/etc" || true
-cp /etc/libccid_Info.plist "$DESTDIR/etc"
+cp -rt "$DESTDIR/usr/lib" /usr/lib/pcsc
+cp -t "$DESTDIR/etc" /etc/reader.conf || true
+cp -t "$DESTDIR/etc" /etc/libccid_Info.plist
# Install opensc commands and conf file
copy_exec /usr/bin/opensc-tool
copy_exec /usr/bin/pkcs15-crypt
-cp /etc/opensc/opensc.conf "$DESTDIR/etc/opensc"
+cp -t "$DESTDIR/etc/opensc" /etc/opensc/opensc.conf
+
+exit $RV
diff --git a/debian/initramfs/hooks/cryptroot b/debian/initramfs/hooks/cryptroot
index 390aa51..ab0c7b4 100644
--- a/debian/initramfs/hooks/cryptroot
+++ b/debian/initramfs/hooks/cryptroot
@@ -16,6 +16,7 @@ esac
. /usr/share/initramfs-tools/hook-functions
. /lib/cryptsetup/functions
+TABFILE="/etc/crypttab"
# blkid_tag($device, $tag)
@@ -23,8 +24,8 @@ esac
# Return 0 on success, 1 on error.
blkid_tag() {
local device="$1" tag="$2" val
- if [ "${device#$tag=}" != "$device" ]; then
- printf '%s\n' "${device#$tag=}"
+ if [ "${device#"$tag="}" != "$device" ]; then
+ printf '%s\n' "${device#"$tag="}"
elif ! val="$(blkid -s "$2" -o value -- "$device")" || [ -z "$val" ]; then
cryptsetup_message "ERROR: $device: Couldn't determine $tag"
return 1
@@ -34,145 +35,149 @@ blkid_tag() {
return 0
}
-# get_mnt_devices($mountpoint)
-# Print the device (or list of devices - one per line - for multiple
-# device filesystems) currenty mounted on $mountpoint.
+# get_mnt_devno($mountpoint)
+# Print the major:minor device ID(s) holding the file system currently
+# mounted currenty mounted on $mountpoint.
# Return 0 on success, 1 on error (if $mountpoint is not a mountpoint).
-get_mnt_devices() {
- local wantmount="$1" devices= uuid dev
- local device mount type options _
+get_mnt_devno() {
+ local wantmount="$1" devnos= uuid dev devno IFS
+ local device mountpoint fstype _
- while read device mountpoint type options _; do
+ while IFS=" " read -r device mountpoint fstype _; do
# treat lines starting with '#' as comments; /proc/mounts
# doesn't seem to contain these but per procfs(5) the format of
# that file is analogous to fstab(5)'s
- [ "${device#\#}" = "$device" ] || continue
- if [ "$mountpoint" = "$wantmount" ]; then
+ if [ "${device#\#}" = "$device" ] && [ -n "$device" ] &&
+ [ "$(printf '%b' "$mountpoint")" = "$wantmount" ]; then
# take the last mountpoint if used several times (shadowed)
- unset -v devices
- if [ "$type" = btrfs ]; then
+ unset -v devnos
+ device="$(printf '%b' "$device")"
+ devno="$(get_device_id "$device")" || continue
+ fstype="$(printf '%b' "$fstype")"
+ if [ "$fstype" = "btrfs" ]; then
# btrfs can span over multiple devices
- if uuid=$(blkid_tag "$device" UUID); then
- for dev in "/sys/fs/btrfs/$uuid/devices"/*; do
- dev="/dev/${dev#/sys/fs/btrfs/$uuid/devices/}"
- devices="${devices:+$devices }$dev"
+ if uuid="$(blkid_tag "/dev/block/$devno" UUID)"; then
+ for dev in "/sys/fs/$fstype/$uuid/devices"/*/dev; do
+ devnos="${devnos:+$devnos }$(cat "$dev")"
done
- # blkid_tag() produces a warning upon failure, so we
- # skip error handling here
+ # blkid_tag() produces a warning upon failure, so we
+ # skip error handling here
fi
- else
- devices="$device"
+ elif [ -n "$fstype" ]; then
+ devnos="$devno"
fi
fi
done </proc/mounts
- [ -n "${devices:+x}" ] || return 1 # not found
- printf '%s\n' "$devices" | tr ' ' '\n'
-}
-# sysfs_devdir($name)
-# Print the sysfs(5) entry /sys/dev/block/$maj:$min (a symlink to
-# pointing to the sysfs directory for the device) corresponding to
-# device $name, where $maj:$min are its major/minor device numbers.
-# Return 0 on success, 1 on error.
-sysfs_devdir() {
- local dev="$(normalise_device "$1")" || return 1
- local devno dir maj min
- # normalise_device() fails if $dev isn't a block device
- if devno="$(stat -c"%t:%T" -- "$dev" 2>/dev/null)" &&
- maj="${devno%:*}" && min="${devno#*:}" &&
- [ "$devno" = "$maj:$min" ] && [ -n "$maj" ] && [ -n "$min" ] &&
- maj=$(( 0x$maj )) && min=$(( 0x$min )) &&
- dir="/sys/dev/block/$maj:$min" && [ -d "$dir" ]; then
- printf '%s\n' "$dir"
- return 0
+ if [ -z "${devnos:+x}" ]; then
+ return 1 # not found
else
- cryptsetup_message "ERROR: Couldn't find sysfs directory corresponding to $1"
- return 1
+ printf '%s' "$devnos"
fi
}
# get_dmcrypt_slaves({/sys/dev/block/$maj:$min | /sys/devices/...})
-# Recursively print the list of underlying dm-crypt devices names for
-# the given sysfs directory (typically corresponding to an md, lv, or
-# dm-crypt device). Slaves that aren't dm-crypt devices are NOT
-# listed.
+# Recursively print the crypttab(5) entries to FD nr. 3, for each
+# dm-crypt device holding $maj:$min (typically corresponding to an md,
+# lv, or dm-crypt device). Slaves that aren't dm-crypt devices are
+# NOT printed.
get_dmcrypt_slaves() {
- local d="$1" name slave
+ local d="$1" devno maj min name slave
[ -d "$d/slaves" ] || return 0
- if [ -d "$d/dm" ]; then
- name="$(cat "$d/dm/name")"
- if [ "$(dmsetup info --noheadings -c -o subsystem -- "$name")" = "CRYPT" ]; then
- printf '%s\n' "$name"
- fi
+ if [ -d "$d/dm" ] && devno="$(cat "$d/dev")" &&
+ maj="${devno%:*}" && min="${devno#*:}" &&
+ [ "$devno" = "$maj:$min" ] && [ -n "$maj" ] && [ -n "$min" ] &&
+ [ "$(dmsetup info -c --noheadings -o subsystem -j "$maj" -m "$min")" = "CRYPT" ] &&
+ name="$(dmsetup info -c --noheadings -o unmangled_name -j "$maj" -m "$min")"; then
+ # search for a crypttab entry with the given unmangled name
+ crypttab_find_and_print_entry "$name"
fi
for slave in "$d/slaves"/*; do
- if slave="$(readlink -e "$slave")"; then
+ if [ -d "$slave" ] && slave="$(realpath -e -- "$slave")"; then
get_dmcrypt_slaves "$slave"
fi
done
}
-# get_crypttab_entry($target)
-# Print the crypttab(5) entry for the given $target. The entry source
-# is replaced by the corresponding UUID=<uuid> if possible. If the
-# entry uses the 'decrypt_derived' keyscript, the other crypttab(5)
-# entries it depends on are (recursively) printed before hand.
+# crypttab_find_and_print_entry($target)
+# Find the crypttab(5) entry for the given (unmangled) $target and
+# print it - preserving the mangling - to FD nr. 3; but only if the
+# target has not already been processed during an earlier function
+# call. (Processed target names are stored in
+# $DESTDIR/cryptroot/targets.)
# Return 0 on success, 1 on error.
-get_crypttab_entry() {
- local name="$1" found="n" slave uuid base
- local CRYPTTAB_NAME source key options derived
- while read CRYPTTAB_NAME source key options; do
- [ "${CRYPTTAB_NAME#\#}" = "$CRYPTTAB_NAME" ] || continue
- [ "$CRYPTTAB_NAME" = "$name" ] || continue
- if slave="$(normalise_device "$source")"; then
- if base="$(sysfs_devdir "/dev/mapper/$name")" && \
- [ ! -e "$base/slaves/${slave#/dev/}" ]; then
- cryptsetup_message "ERROR: Source mismatch: $source != $slave"
- elif uuid="$(blkid_tag "$slave" UUID 2>/dev/null)"; then
- source="UUID=$uuid"
- fi
- fi
- found="y"
- break
- done <"$TABFILE"
-
- if [ "$found" = n ]; then
- cryptsetup_message "WARNING: No crypttab entry for $name"
- return 1
+crypttab_find_and_print_entry() {
+ local target="$1"
+ if ! grep -Fxqz -e "$target" -- "$DESTDIR/cryptroot/targets"; then
+ printf '%s\0' "$target" >>"$DESTDIR/cryptroot/targets"
+ crypttab_find_entry "$target" || return 1
+ crypttab_parse_options || return 1
+ crypttab_print_entry
fi
+}
- crypttab_parse_options "$options" n || return 1
+# crypttab_print_entry()
+# Print an unmangled crypttab(5) entry to FD nr. 3, using CRYPTTAB_*
+# and _CRYPTTAB_* values.
+# _CRYPTTAB_SOURCE is replaced with /dev/mapper/$sourcename for mapped
+# sources, otherwise by UUID=<uuid> if possible (eg, for LUKS). If
+# the entry uses the 'decrypt_derived' keyscript, the other
+# crypttab(5) entries it depends on are (recursively) printed before
+# hand.
+# Various checks are performed on the key and crypttab options, but no
+# parsing is done so it's the responsibility of the caller to call
+# crypttab_parse_options().
+# Return 0 on success, 1 on error.
+crypttab_print_entry() {
+ local MIN MAJ sourcename uuid keyfile
+ if resolve_device_id "$CRYPTTAB_SOURCE"; then
+ if [ "$(dmsetup info -c --noheadings -o devnos_used -- "$CRYPTTAB_NAME" 2>/dev/null)" != "$MAJ:$MIN" ]; then
+ cryptsetup_message "ERROR: $CRYPTTAB_NAME: Source mismatch"
+ elif sourcename="$(dmsetup info -c --noheadings -o mangled_name -j "$MAJ" -m "$MIN" 2>/dev/null)" &&
+ [ -b "/dev/mapper/$sourcename" ]; then
+ # for mapped sources, use the dm name as the lvm
+ # local-block script doesn't work with UUIDs (#902943)
+ _CRYPTTAB_SOURCE="/dev/mapper/$sourcename"
+ elif uuid="$(blkid_tag "/dev/block/$MAJ:$MIN" UUID 2>/dev/null)"; then
+ # otherwise, use its UUID if possible (eg. for LUKS)
+ _CRYPTTAB_SOURCE="UUID=$uuid"
+ fi
+ fi
if [ -n "${CRYPTTAB_OPTION_header+x}" ] && [ ! -f "$CRYPTTAB_OPTION_header" ]; then
- cryptsetup_message "WARNING: Target $name has an invalid header $CRYPTTAB_OPTION_header"
+ cryptsetup_message "WARNING: Target $CRYPTTAB_NAME has an invalid header $CRYPTTAB_OPTION_header"
fi
- local newkey
# if keyscript is set, the "key" is just an argument to the script
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$key" != "none" ]; then
- check_key "$key" || return 1
- case "$key" in
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
+ crypttab_key_check || return 1
+ case "$CRYPTTAB_KEY" in
$KEYFILE_PATTERN)
- mkdir -pm0700 "$DESTDIR/cryptroot/keyfiles"
- newkey="/cryptroot/keyfiles/$name.key"
- copy_file keyfile "$key" "$newkey"
- key="$newkey"
+ mkdir -pm0700 -- "$DESTDIR/cryptroot/keyfiles"
+ # $CRYPTTAB_NAME can't contain '/' (even after unmangling)
+ keyfile="/cryptroot/keyfiles/$CRYPTTAB_NAME.key"
+ copy_file keyfile "$CRYPTTAB_KEY" "$keyfile"
+ _CRYPTTAB_KEY="/cryptroot/keyfiles/$_CRYPTTAB_NAME.key" # preserve mangled name
;;
*)
if [ "$usage" = rootfs ]; then
- cryptsetup_message "WARNING: Skipping root target $name: uses a key file"
+ cryptsetup_message "WARNING: Skipping root target $CRYPTTAB_NAME: uses a key file"
return 1
elif [ "$usage" = resume ]; then
- cryptsetup_message "WARNING: Resume target $name uses a key file"
+ cryptsetup_message "WARNING: Resume target $CRYPTTAB_NAME uses a key file"
fi
- if newkey=$(readlink -f -- "$key") && [ -f "$newkey" ]; then
- if [ "$(stat -c %m -- "$newkey" 2>/dev/null)" != "/" ]; then
- cryptsetup_message "WARNING: Skipping target $name: key file is not on the root FS"
- return 1
- fi
- key="/FIXME-initramfs-rootmnt$newkey"
- elif [ ! -e "$key" ]; then
- cryptsetup_message "WARNING: Target $name has a non-existing key file $key"
+ if [ -L "$CRYPTTAB_KEY" ] && keyfile="$(readlink -- "$CRYPTTAB_KEY")" &&
+ [ "${keyfile#/}" != "$keyfile" ]; then
+ cryptsetup_message "WARNING: Skipping target $CRYPTTAB_NAME: key file is a symlink with absolute target"
+ return 1
+ elif [ -f "$CRYPTTAB_KEY" ] && [ "$(stat -L -c"%m" -- "$CRYPTTAB_KEY" 2>/dev/null)" != "/" ]; then
+ cryptsetup_message "WARNING: Skipping target $CRYPTTAB_NAME: key file is not on the root FS"
+ return 1
+ fi
+ if [ ! -e "$CRYPTTAB_KEY" ]; then
+ cryptsetup_message "WARNING: Target $CRYPTTAB_NAME has a non-existing key file $CRYPTTAB_KEY"
+ else
+ _CRYPTTAB_KEY="/FIXME-initramfs-rootmnt$_CRYPTTAB_KEY" # preserve mangled name
fi
esac
fi
@@ -182,29 +187,32 @@ get_crypttab_entry() {
fi
if [ "${CRYPTTAB_OPTION_keyscript-}" = "/lib/cryptsetup/scripts/decrypt_derived" ]; then
# (recursively) list first the device to derive the key from (so
- # the boot scripts unlocks it first)
- get_crypttab_entry "$key"
+ # the boot scripts unlock it first)
+ crypttab_find_and_print_entry "$CRYPTTAB_KEY"
fi
- printf '%s %s %s %s\n' "$name" "$source" "$key" "$options"
+ printf '%s %s %s %s\n' \
+ "$_CRYPTTAB_NAME" "$_CRYPTTAB_SOURCE" "$_CRYPTTAB_KEY" "$_CRYPTTAB_OPTIONS" >&3
}
-# get_cryptdevs($device, [$device ..])
-# Print the list of crypttab(5) entries for each dm-crypt device
-# holding any of the given $device (which can be an md, a lv, a
-# mapped device, or a regular block device).
+# get_cryptdevs($maj:$min, [$maj:$min ..])
+# Print the list of crypttab(5) entries to FD nr. 3, for dm-crypt
+# devices holding any of the given devices (which can be an md, a lv,
+# a mapped device, or a regular block device).
get_cryptdevs() {
- local dev base name
- for dev in "$@"; do
- base="$(sysfs_devdir "$dev")" || return 1
- for name in $(get_dmcrypt_slaves "$base"); do
- get_crypttab_entry "$name"
- done
+ local devno base
+ for devno in "$@"; do
+ base="/sys/dev/block/$devno"
+ if [ ! -d "$base" ]; then
+ cryptsetup_message "ERROR: Couldn't find sysfs directory for $devno"
+ return 1
+ fi
+ get_dmcrypt_slaves "$base"
done
}
-# get_resume_device()
-# Return the device(s) used for system suspend/hibernate.
-get_resume_device() {
+# get_resume_devno()
+# Return the device ID(s) used for system suspend/hibernate.
+get_resume_devno() {
local dev filename
# uswsusp
@@ -213,86 +221,102 @@ get_resume_device() {
dev="$(sed -nr 's/^resume device\s*[:=]\s*//p' "$filename")"
if [ -n "$dev" ] && [ "$dev" != "<path_to_resume_device_file>" ]; then
# trim quotes
- dev=$(printf '%s' "$dev" | sed -re 's/^"(.*)"\s*$/\1/' -e "s/^'(.*)'\s*$/\1/")
- printf '%s\n' "$dev"
+ dev="$(printf '%s' "$dev" | sed -re 's/^"(.*)"\s*$/\1/' -e "s/^'(.*)'\s*$/\1/")"
+ dev="$(printf '%b' "$dev")" # unmangle
+ get_device_id "$dev"
fi
done
# regular swsusp
- sed -nr 's,^(.*\s)?resume=(\S+)(\s.*)?$,\2,p' /proc/cmdline
+ dev="$(sed -nr 's,^(.*\s)?resume=(\S+)(\s.*)?$,\2,p' /proc/cmdline)"
+ dev="$(printf '%b' "$dev")" # unmangle
+ if [ -n "$dev" ]; then
+ get_device_id "$dev"
+ fi
# initramfs-tools >=0.129
dev="${RESUME:-auto}"
if [ "$dev" != none ]; then
if [ "$dev" = auto ]; then
# next line from /usr/share/initramfs-tools/hooks/resume
- grep ^/dev/ /proc/swaps | sort -rnk3 | head -n 1 | cut -d " " -f 1
- else
- printf '%s\n' "$dev"
+ dev="$(grep ^/dev/ /proc/swaps | sort -rnk3 | head -n 1 | cut -d " " -f 1)"
fi
+ dev="$(printf '%b' "$dev")" # unmangle
+ if [ -n "$dev" ]; then
+ get_device_id "$dev"
+ fi
+ fi
+}
+
+# crypttab_print_initramfs_entry()
+# Print a crypttab(5) entry - unless it was already processed - if it
+# has the 'initramfs' option set.
+crypttab_print_initramfs_entry() {
+ local usage=
+ if ! grep -Fxqz -e "$CRYPTTAB_NAME" -- "$DESTDIR/cryptroot/targets" &&
+ crypttab_parse_options --quiet &&
+ [ "${CRYPTTAB_OPTION_initramfs-no}" = "yes" ]; then
+ printf '%s\0' "$CRYPTTAB_NAME" >>"$DESTDIR/cryptroot/targets"
+ crypttab_print_entry
fi
}
# generate_initrd_crypttab()
# Generate the crypttab(5) snippet that is relevant at initramfs
# stage. (Devices that aren't required at initramfs stage are
-# ignore.)
+# ignored.)
generate_initrd_crypttab() {
- local dev usage
+ local devnos usage IFS=" "
+ local name CRYPTTAB_NAME source key options
+ mkdir -- "$DESTDIR/cryptroot"
+ >"$DESTDIR/cryptroot/targets"
+
{
- if ! dev="$(get_mnt_devices /)"; then
- cryptsetup_message "WARNING: Couldn't determine root device"
+ if devnos="$(get_mnt_devno /)"; then
+ usage=rootfs get_cryptdevs $devnos
else
- usage=rootfs get_cryptdevs $dev
+ cryptsetup_message "WARNING: Couldn't determine root device"
fi
- if dev="$(get_resume_device)"; then
- usage=resume get_cryptdevs $dev
+ if devnos="$(get_resume_devno)"; then
+ usage=resume get_cryptdevs $devnos
fi
- if dev="$(get_mnt_devices /usr)"; then
- usage= get_cryptdevs $dev
+ if devnos="$(get_mnt_devno /usr)"; then
+ usage= get_cryptdevs $devnos
fi
# add crypttab entries with the 'initramfs' option set
- for dev in $(sed -nr 's/^\s*([^#[:blank:]]\S*)\s+\S+\s+\S+\s+(\S+,)?initramfs(,\S+)?$/\1/p' "$TABFILE"); do
- get_crypttab_entry "$dev"
- done
-
- # remove duplicates (but preserve order)
- } | awk '!seen[$1]++'
+ crypttab_foreach_entry crypttab_print_initramfs_entry
+ } 3>"$DESTDIR/cryptroot/crypttab"
+ rm -f "$DESTDIR/cryptroot/targets"
}
-# populate_CRYPTO_MODULES($name, [$name])
-# Find out which crytpo modules are required for the given list of
-# mapped (crypt) devices names, and append them to the CRYPTO_MODULES
-# variable.
+# populate_CRYPTO_MODULES()
+# Find out which crytpo modules are required for a crypttab(5) entry,
+# and append them to the CRYPTO_MODULES variable.
populate_CRYPTO_MODULES() {
- local name cipher iv
- for name in "$@"; do
- # cf. dmsetup(8) and https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
- cipher="$(dmsetup table --target crypt -- "$name" | cut -d' ' -f4)"
- if [ -z "$cipher" ]; then
- cryptsetup_message "WARNING: Couldn't determine cipher modules to load for $name"
- continue
- fi
-
- if [ "${cipher#capi:}" = "$cipher" ]; then
- # direct specification "cipher[:keycount]-chainmode-ivmode[:ivopts]"
- CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${cipher%%[-:]*}" # cipher
- cipher="${cipher#${cipher%%-*}-}" # chainmode-ivmode[:ivopts]"
- CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${cipher%-*}" # chainmode
- iv="${cipher##*-}" # ivmode[:ivopts]"
- if [ "${iv#*:}" != "$iv" ]; then
- CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${iv#*:}" # ivopts
- fi
- else
- # kernel crypto API format "capi:cipher_api_spec-ivmode[:ivopts]", since linux 4.12
- cipher="${cipher#capi:}"
- cryptsetup_message "WARNING: Couldn't determine cipher modules to load for $name" \
- "(kernel crypto API format isn't supported yet)"
+ local cipher iv
+
+ # cf. dmsetup(8) and https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
+ cipher="$(dmsetup table --target crypt -- "$CRYPTTAB_NAME" | cut -d' ' -f4)"
+ if [ -z "$cipher" ]; then
+ cryptsetup_message "WARNING: Couldn't determine cipher modules to load for $CRYPTTAB_NAME"
+ elif [ "${cipher#capi:}" = "$cipher" ]; then
+ # direct specification "cipher[:keycount]-chainmode-ivmode[:ivopts]"
+ CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${cipher%%[-:]*}" # cipher
+ cipher="${cipher#"${cipher%%-*}-"}" # chainmode-ivmode[:ivopts]"
+ CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${cipher%-*}" # chainmode
+ iv="${cipher##*-}" # ivmode[:ivopts]"
+ if [ "${iv#*:}" != "$iv" ]; then
+ CRYPTO_MODULES="${CRYPTO_MODULES:+$CRYPTO_MODULES }${iv#*:}" # ivopts
fi
- done
+ else
+ # kernel crypto API format "capi:cipher_api_spec-ivmode[:ivopts]", since linux 4.12
+ cipher="${cipher#capi:}"
+ cryptsetup_message "WARNING: Couldn't determine cipher modules to load for $CRYPTTAB_NAME" \
+ "(kernel crypto API format isn't supported yet)"
+ fi
}
# add_modules($glob, $moduledir, [$moduledir ..])
@@ -334,7 +358,8 @@ add_crypto_modules() {
#######################################################################
# Begin real processing
-unset -v CRYPTSETUP
+unset -v CRYPTSETUP KEYFILE_PATTERN
+KEYFILE_PATTERN=
# Load the hook config
if [ -f "/etc/cryptsetup-initramfs/conf-hook" ]; then
@@ -363,11 +388,9 @@ fi
CRYPTO_MODULES=
if [ -r "$TABFILE" ]; then
- mkdir "$DESTDIR/cryptroot"
- generate_initrd_crypttab >"$DESTDIR/cryptroot/crypttab"
-
- populate_CRYPTO_MODULES \
- $(sed -rn 's/^\s*([^#[:blank:]]\S*)\s.*/\1/p' "$DESTDIR/cryptroot/crypttab")
+ generate_initrd_crypttab
+ TABFILE="$DESTDIR/cryptroot/crypttab"
+ crypttab_foreach_entry populate_CRYPTO_MODULES
fi
# per comment in the config file a non-empty KEYFILE_PATTERN value
@@ -403,7 +426,7 @@ else
if [ "$MODULES" = most ]; then
for d in "$MODULESDIR"/kernel/arch/*/crypto; do
- copy_modules_dir "${d#$MODULESDIR/}"
+ copy_modules_dir "${d#"$MODULESDIR/"}"
done
copy_modules_dir "kernel/crypto"
else
diff --git a/debian/initramfs/scripts/local-top/cryptroot b/debian/initramfs/scripts/local-top/cryptroot
index b0ec673..14bec2f 100644
--- a/debian/initramfs/scripts/local-top/cryptroot
+++ b/debian/initramfs/scripts/local-top/cryptroot
@@ -25,7 +25,7 @@ prereqs)
esac
. /scripts/functions
-INITSTATE="initramfs"
+
[ -f /lib/cryptsetup/functions ] || return 0
. /lib/cryptsetup/functions
@@ -35,12 +35,12 @@ INITSTATE="initramfs"
# $CRYPTTAB_SOURCE to its normalized device name when it shows up;
# return 1 if timeout.
wait_for_source() {
- local device
+ local devno
wait_for_udev 10
- if device="$(normalise_device --quiet "$CRYPTTAB_SOURCE")"; then
+ if devno="$(get_device_id --quiet "$CRYPTTAB_SOURCE")"; then
# the device is here already, no need to loop
- CRYPTTAB_SOURCE="$device"
+ CRYPTTAB_SOURCE="/dev/block/$devno"
return 0
fi
@@ -63,9 +63,9 @@ wait_for_source() {
/scripts/local-block/lvm2 "$CRYPTTAB_SOURCE"
fi
- if device="$(normalise_device --quiet "$CRYPTTAB_SOURCE")"; then
+ if devno="$(get_device_id --quiet "$CRYPTTAB_SOURCE")"; then
wait_for_udev 10
- CRYPTTAB_SOURCE="$device"
+ CRYPTTAB_SOURCE="/dev/block/$devno"
return 0
fi
@@ -74,19 +74,19 @@ wait_for_source() {
return 1
}
-# setup_mapping($target, $source, $key, $options)
-# Set up a given crypttab(5) mapping
+# setup_mapping()
+# Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME,
+# $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS.
setup_mapping() {
- export CRYPTTAB_NAME="$1" CRYPTTAB_SOURCE="$2" CRYPTTAB_OPTIONS="$4"
- local key="$3"
+ local dev
# The same target can be specified multiple times
# e.g. root and resume lvs-on-lvm-on-crypto
- if [ -e "/dev/mapper/$CRYPTTAB_NAME" ]; then
+ if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
return 0
fi
- crypttab_parse_options || return 1
+ crypttab_parse_options --export || return 1
if ! wait_for_source; then
# we've given up
@@ -99,33 +99,41 @@ setup_mapping() {
echo " or missing modules, devices: cat /proc/modules; ls /dev"
panic "Dropping to a shell."
fi
- return 1
+ return 1 # can't continue because environment is lost
fi
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "${key#/FIXME-initramfs-rootmnt/}" != "$key" ]; then
- # skip the mapping if the root FS is not mounted yet
- sed -rn 's/^\s*[^#[:blank:]]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq -- "$rootmnt" || return 1
- # substitute the "/FIXME-initramfs-rootmnt/" prefix by the real root FS mountpoint otherwise
- key="$rootmnt/${key#/FIXME-initramfs-rootmnt/}"
- fi
+ # our `cryptroot-unlock` script searches for cryptsetup processes
+ # with a given CRYPTTAB_NAME it their environment
+ export CRYPTTAB_NAME
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$key" != "none" ]; then
- if [ ! -e "$key" ]; then
- cryptsetup_message "ERROR: Skipping target $CRYPTTAB_NAME: missing key file $key"
- return 1
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ]; then
+ # no keyscript: interactive unlocking, or key file
+
+ if [ "${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}" != "$CRYPTTAB_KEY" ]; then
+ # skip the mapping for now if the root FS is not mounted yet
+ sed -rn 's/^\s*[^#[:blank:]]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq -- "$rootmnt" || return 1
+ # substitute the "/FIXME-initramfs-rootmnt/" prefix by the real root FS mountpoint otherwise
+ CRYPTTAB_KEY="$rootmnt/${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}"
+ fi
+
+ if [ "$CRYPTTAB_KEY" != "none" ]; then
+ if [ ! -e "$CRYPTTAB_KEY" ]; then
+ cryptsetup_message "ERROR: Skipping target $CRYPTTAB_NAME: non-existing key file $CRYPTTAB_KEY"
+ return 1
+ fi
+ # try only once if we have a key file
+ CRYPTTAB_OPTION_tries=1
fi
- # try only once if we have a key file
- CRYPTTAB_OPTION_tries=1
fi
local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype vg rv
while [ $maxtries -le 0 ] || [ $count -lt $maxtries ]; do
- if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$key" != "none" ]; then
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
# unlock via keyfile
- unlock_mapping "$key" "$CRYPTTAB_NAME"
+ unlock_mapping "$CRYPTTAB_KEY"
else
# unlock interactively or via keyscript
- run_keyscript "$key" "$count" | unlock_mapping - "$CRYPTTAB_NAME"
+ run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping
fi
rv=$?
count=$(( $count + 1 ))
@@ -134,12 +142,12 @@ setup_mapping() {
cryptsetup_message "ERROR: $CRYPTTAB_NAME: cryptsetup failed, bad password or options?"
sleep 1
continue
- elif [ ! -e "/dev/mapper/$CRYPTTAB_NAME" ]; then
+ elif ! dev="$(dm_blkdevname "$CRYPTTAB_NAME")"; then
cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown error setting up device mapping"
return 1
fi
- if ! fstype="$(get_fstype "/dev/mapper/$CRYPTTAB_NAME")" || [ "$fstype" = unknown ]; then
+ if ! fstype="$(get_fstype "$dev")" || [ "$fstype" = unknown ]; then
# bad password for plain dm-crypt device? or mkfs not run yet?
cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown fstype, bad password or options?"
wait_for_udev 10
@@ -150,7 +158,7 @@ setup_mapping() {
if [ ! -x /sbin/lvm ]; then
cryptsetup_message "WARNING: $CRYPTTAB_NAME: lvm is not available"
return 1
- elif vg="$(lvm pvs --noheadings -o vg_name --config 'log{prefix=""}' "/dev/mapper/$CRYPTTAB_NAME")"; then
+ elif vg="$(lvm pvs --noheadings -o vg_name --config 'log{prefix=""}' -- "$dev")"; then
# activate the VG held by the PV we just unlocked
lvm lvchange -a y --sysinit --ignoreskippedcluster -- "$vg"
fi
@@ -169,19 +177,47 @@ setup_mapping() {
#######################################################################
# Begin real processing
+mkdir -p /cryptroot # might not exist yet if the main system has no crypttab(5)
+
# Do we have any kernel boot arguments?
-gen_crypttab_from_kernel_cmdline
+if ! grep -qE '^(.*\s)?cryptopts=' /proc/cmdline; then
+ # ensure $TABFILE exists and has a mtime greater than the boot time
+ # (existing $TABFILE is preserved)
+ touch -- "$TABFILE"
+else
+ # let the read builtin unescape the '\' as GRUB substitutes '\' by '\\' in the cmdline
+ tr ' ' '\n' </proc/cmdline | sed -n 's/^cryptopts=//p' | while IFS= read cryptopts; do
+ # skip empty values (which can be used to disable the initramfs
+ # scripts for a particular boot, cf. #873840)
+ [ -n "$cryptopts" ] || continue
+ unset -v target source key options
+
+ IFS=","
+ for x in $cryptopts; do
+ case "$x" in
+ target=*) target="${x#target=}";;
+ source=*) source="${x#source=}";;
+ key=*) key="${x#key=}";;
+ *) options="${options+$options,}$x";;
+ esac
+ done
+
+ if [ -z "${source:+x}" ]; then
+ cryptsetup_message "ERROR: Missing source= value in kernel parameter cryptopts=$cryptopts"
+ else
+ # preserve mangling
+ printf '%s %s %s %s\n' "${target:-cryptroot}" "$source" "${key:-none}" "${options-}"
+ fi
+ done >"$TABFILE"
+fi
-# Do we have any settings from the /cryptroot/crypttab file?
-if [ -s /cryptroot/crypttab ]; then
+# Do we have any settings from the $TABFILE?
+if [ -s "$TABFILE" ]; then
# Create locking directory before invoking cryptsetup(8) to avoid warnings
mkdir -pm0700 /run/cryptsetup
modprobe -q dm_crypt
- while read target source key options <&3; do
- [ "${target#\#}" = "$target" ] || continue
- setup_mapping "$target" "$source" "$key" "$options" 3<&-
- done 3< /cryptroot/crypttab
+ crypttab_foreach_entry setup_mapping
fi
exit 0
diff --git a/debian/patches/disable-internal-tests.patch b/debian/patches/disable-internal-tests.patch
new file mode 100644
index 0000000..4c6814a
--- /dev/null
+++ b/debian/patches/disable-internal-tests.patch
@@ -0,0 +1,35 @@
+From: Guilhem Moulin <guilhem@debian.org>
+Date: Fri, 06 Jul 2018 16:32:10 +0200
+Subject: Add configure option '--disable-internal-tests' to disable the internal test suite
+
+---
+ Makefile.am | 5 ++++-
+ configure.ac | 5 +++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,5 +1,8 @@
+ EXTRA_DIST = COPYING.LGPL FAQ docs misc
+-SUBDIRS = po tests
++SUBDIRS = po
++if !SKIP_INTERNAL_TESTS
++SUBDIRS += tests
++endif
+ TESTS =
+ CLEANFILES =
+ DISTCLEAN_TARGETS =
+--- a/configure.ac
++++ b/configure.ac
+@@ -567,6 +567,11 @@ test "x$with_tmpfilesdir" = "xno" || {
+ }
+ AM_CONDITIONAL(CRYPTSETUP_TMPFILE, test -n "$DEFAULT_TMPFILESDIR")
+
++AC_ARG_ENABLE([internal-tests],
++ AS_HELP_STRING([--disable-internal-tests],
++ [skip the internal test suite]),[], [skip_internal_tests=no])
++AM_CONDITIONAL(SKIP_INTERNAL_TESTS, test x$skip_internal_tests != xno)
++
+ CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/cryptsetup])
+ test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup
+ CS_ABSPATH([${with_luks2_lock_path}],[with-luks2-lock-path])
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..9cbb023
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+disable-internal-tests.patch
diff --git a/debian/rules b/debian/rules
index 4711bbf..c6f37b4 100755
--- a/debian/rules
+++ b/debian/rules
@@ -8,15 +8,21 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow,+pie
DEB_CFLAGS_MAINT_APPEND = -Wall
include /usr/share/dpkg/architecture.mk
+CONFFLAGS =
+
# Used e.g. for manpages (to build them in a reprodicible way)
include /usr/share/dpkg/pkg-info.mk
DEB_DATE := $(strip $(shell LC_ALL=C date -u +%F -d@$(SOURCE_DATE_EPOCH)))
+ifneq (,$(findstring skip-internal-tests,$(DEB_BUILD_OPTIONS)))
+CONFFLAGS += --disable-internal-tests
+endif
+
%:
dh $@
override_dh_auto_configure:
- dh_auto_configure -- $(confflags) \
+ dh_auto_configure -- $(CONFFLAGS) \
--libdir=/lib/$(DEB_HOST_MULTIARCH) \
--sbindir=/sbin \
--enable-libargon2 \
@@ -27,8 +33,8 @@ override_dh_auto_build:
dh_auto_build
# build askpass and passdev keyscripts
- $(CC) -o debian/askpass debian/askpass.c $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pedantic -std=c99
- $(CC) -o debian/scripts/passdev debian/scripts/passdev.c $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pedantic -std=c99
+ $(CC) -o debian/askpass debian/askpass.c $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pedantic
+ $(CC) -o debian/scripts/passdev debian/scripts/passdev.c $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pedantic
# generate manpages
sed 's/VERSION/$(DEB_VERSION)/;s/DATE/$(DEB_DATE)/' \
diff --git a/debian/scripts/cryptdisks_start b/debian/scripts/cryptdisks_start
index ea5c6ad..623423f 100644
--- a/debian/scripts/cryptdisks_start
+++ b/debian/scripts/cryptdisks_start
@@ -46,12 +46,15 @@ mount_fs
rv=0
for name in "$@"; do
- if ! crypttab_find_target "$name"; then
+ if ! crypttab_find_entry --quiet "$name"; then
device_msg "$name" "failed, not found in crypttab"
rv=1
else
- CRYPTTAB_OPTIONS="$CRYPTTAB_OPTIONS${CRYPTTAB_EXTRA_OPTIONS:+,$CRYPTTAB_EXTRA_OPTIONS}"
- setup_mapping "$CRYPTTAB_NAME" "$CRYPTTAB_SOURCE" "$CRYPTTAB_KEY" "$CRYPTTAB_OPTIONS" || rv=$?
+ if [ -n "$CRYPTTAB_EXTRA_OPTIONS" ]; then
+ CRYPTTAB_OPTIONS="$CRYPTTAB_OPTIONS,$CRYPTTAB_EXTRA_OPTIONS"
+ _CRYPTTAB_OPTIONS="$_CRYPTTAB_OPTIONS,$CRYPTTAB_EXTRA_OPTIONS"
+ fi
+ setup_mapping || rv=$?
fi
done
umount_fs
diff --git a/debian/scripts/cryptdisks_stop b/debian/scripts/cryptdisks_stop
index 5dfc23b..ea0faaf 100644
--- a/debian/scripts/cryptdisks_stop
+++ b/debian/scripts/cryptdisks_stop
@@ -31,13 +31,7 @@ log_action_begin_msg "Stopping crypto disk"
rv=0
for name in "$@"; do
- if crypttab_find_target "$name"; then
- remove_mapping "$CRYPTTAB_NAME" "$CRYPTTAB_OPTIONS" || rv=$?
- elif cryptsetup status -- "$name" >/dev/null; then
- remove_mapping "$name" '' || rv=$?
- else
- device_msg "$name" "failed, no such device"
- fi
+ remove_mapping "$name" || rv=$?
done
log_action_end_msg $rv
diff --git a/debian/scripts/decrypt_derived b/debian/scripts/decrypt_derived
index 6b7ae2a..864e049 100644
--- a/debian/scripts/decrypt_derived
+++ b/debian/scripts/decrypt_derived
@@ -8,48 +8,24 @@
# backup, or better a backup of the data on the derived device may be
# a good idea. See the Cryptsetup FAQ on how to do this right.
-countlines() {
- local IFS input count tmp
- input="$1"
- count=0
- IFS='
-'
- for tmp in $input; do
- count=$(( $count + 1 ))
- done
- echo $count
-}
-
if [ -z "$1" ]; then
- echo "$0: must be executed with a crypto device as argument" >&2
- exit 1
-fi
-
-if ! device=$(dmsetup --showkeys table 2>/dev/null \
- | awk -vtarget="$1" '$1 == target ":" {print}'); then
- echo "$0: failed to find $1 in dmtable" >&2
- exit 1
-fi
-
-if [ -z "$device" ]; then
- echo "$0: device $1 doesn't exist" >&2
- exit 1
+ echo "$0: must be executed with a crypto device as argument" >&2
+ exit 1
fi
-count=$(countlines "$device")
-if [ $count -ne 1 ]; then
- echo "$0: more than one device match $1" >&2
- exit 1
+unset -v keys count
+keys="$(dmsetup table --target crypt --showkeys -- "$1" 2>/dev/null | cut -s -d' ' -f5)"
+count="$(printf '%s' "$keys" | wc -l)"
+
+if [ -n "$keys" ] && [ $count -le 1 ]; then
+ if [ "${keys#:}" = "$keys" ]; then
+ printf '%s' "$keys" | tr -d '\n'
+ else
+ echo "$0: device $1 uses the kernel keyring"
+ fi
+elif [ $count -eq 0 ]; then
+ echo "$0: device $1 doesn't exist or isn't a crypto device" >&2
+else
+ echo "$0: more than one device match" >&2
fi
-
-eval set -- $device
-type="$4"
-key="$6"
-
-if [ "$type" != "crypt" ]; then
- echo "$0: device $1 is not a crypto device" >&2
- exit 1
-fi
-
-echo -n "$key"
-exit 0
+exit 1
diff --git a/debian/scripts/passdev.c b/debian/scripts/passdev.c
index 8fb9bad..845ccae 100644
--- a/debian/scripts/passdev.c
+++ b/debian/scripts/passdev.c
@@ -20,7 +20,7 @@
*/
-#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>