summaryrefslogtreecommitdiffstats
path: root/debian/cryptdisks-functions
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/cryptdisks-functions286
1 files changed, 286 insertions, 0 deletions
diff --git a/debian/cryptdisks-functions b/debian/cryptdisks-functions
new file mode 100644
index 0000000..ce5e6f4
--- /dev/null
+++ b/debian/cryptdisks-functions
@@ -0,0 +1,286 @@
+#
+# This file is for inclusion with
+# . /lib/cryptsetup/cryptdisks-functions
+# and should not be executed directly.
+
+PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+CRYPTDISKS_ENABLE="Yes"
+
+#set -x
+
+# Sanity check #1
+[ -x /sbin/cryptsetup ] || exit 0
+
+. /lib/lsb/init-functions
+. /lib/cryptsetup/functions
+
+if [ -r /etc/default/cryptdisks ]; then
+ . /etc/default/cryptdisks
+fi
+
+MOUNT="$CRYPTDISKS_MOUNT"
+
+
+# do_start()
+# Unlock all devices in the crypttab(5)
+do_start() {
+ [ -s "$TABFILE" ] || return 0
+
+ # Create locking directory before invoking cryptsetup(8) to avoid warnings
+ mkdir -pm0700 /run/cryptsetup
+ modprobe -qb dm-mod || true
+ modprobe -qb dm-crypt || true
+ dmsetup mknodes >/dev/null 2>&1 || true
+
+ if [ "$INITSTATE" != "init" ]; then
+ log_action_begin_msg "Starting $INITSTATE crypto disks"
+ fi
+ mount_fs
+
+ 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
+mount_fs() {
+ local point
+ MOUNTED=""
+
+ for point in $MOUNT; do
+ if mount "$point" >/dev/null; then
+ MOUNTED="$MOUNTED $point"
+ fi
+ done
+}
+
+# Postunmounts file systems
+umount_fs() {
+ local point
+
+ for point in $MOUNTED; do
+ umount "$point" >/dev/null
+ done
+}
+
+# setup_mapping()
+# Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME,
+# $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS.
+setup_mapping() {
+ if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
+ device_msg "running"
+ return 0
+ fi
+
+ local loud="${DEFAULT_LOUD:-}"
+ crypttab_parse_options --export --missing-path=fail || return 1
+ if [ -n "${CRYPTTAB_OPTION_quiet+x}" ]; then
+ loud="no"
+ elif [ -n "${CRYPTTAB_OPTION_loud+x}" ]; then
+ loud="yes"
+ fi
+
+ if [ -z "${FORCE_START-}" ]; then
+ if [ "$INITSTATE" = "early" -a -n "${CRYPTTAB_OPTION_noearly+x}" ] ||
+ [ "$INITSTATE" != "manual" -a -n "${CRYPTTAB_OPTION_noauto+x}" ]; then
+ device_msg "ignored"
+ return 0
+ fi
+ fi
+
+ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
+ if ! crypttab_key_check; then
+ device_msg "invalid key"
+ return 1
+ fi
+ CRYPTTAB_OPTION_tries=1
+ fi
+
+ if ! crypttab_resolve_source; then
+ if [ "$loud" = "yes" ]; then
+ device_msg "skipped, device $CRYPTTAB_SOURCE does not exist"
+ fi
+ return 1
+ fi
+ device_msg "starting"
+
+ local offset_bytes=""
+ if [ -n "${CRYPTTAB_OPTION_offset+x}" ] && [ ${#CRYPTTAB_OPTION_offset} -le 7 ] && [ $CRYPTTAB_OPTION_offset -lt 4194304 ]; then
+ # silently ignore large offset values which might cause the multiplication to overflow...
+ offset_bytes=$((CRYPTTAB_OPTION_offset * 512))
+ fi
+
+ local out tmpdev
+ if [ "$CRYPTTAB_TYPE" != "luks" ] && [ "$CRYPTTAB_TYPE" != "bitlk" ]; then
+ # fail if the device has a filesystem and the disk encryption format doesn't
+ # verify the key digest (unlike LUKS); unless it's swap, otherwise people can't
+ # easily convert an existing plainttext swap partition to an encrypted one
+ if ! out="$(/lib/cryptsetup/checks/un_blkid "$CRYPTTAB_SOURCE" "" ${CRYPTTAB_OPTION_offset+"$offset_bytes"} 2>/dev/null)" &&
+ ! /lib/cryptsetup/checks/blkid "$CRYPTTAB_SOURCE" swap ${CRYPTTAB_OPTION_offset+"$offset_bytes"} >/dev/null; then
+ log_warning_msg "$CRYPTTAB_NAME: the precheck for '$CRYPTTAB_SOURCE' failed: $out"
+ return 1
+ fi
+ fi
+
+ local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype rv
+ 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}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
+ # unlock via keyfile
+ unlock_mapping "$CRYPTTAB_KEY"
+ else
+ # unlock interactively or via keyscript
+ CRYPTTAB_NAME="$target" run_keyscript "$count" | unlock_mapping
+ fi
+ rv=$?
+ count=$(( $count + 1 ))
+
+ if [ $rv -ne 0 ] || ! tmpdev="$(dm_blkdevname "$CRYPTTAB_NAME")"; then
+ continue
+ fi
+ if [ -n "${CRYPTTAB_OPTION_check+x}" ] && \
+ ! "$CRYPTTAB_OPTION_check" "$tmpdev" ${CRYPTTAB_OPTION_checkargs+"$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 "$tmpdev" "" ${CRYPTTAB_OPTION_offset+"$offset_bytes"} 2>/dev/null)" ||
+ /lib/cryptsetup/checks/blkid "$tmpdev" swap ${CRYPTTAB_OPTION_offset+"$offset_bytes"} >/dev/null 2>&1; then
+ mkswap "$tmpdev" >/dev/null 2>&1
+ else
+ 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 "$tmpdev" >/dev/null 2>&1 ||
+ ! mount -t "$CRYPTTAB_OPTION_tmp" "$tmpdev" "$tmpdir" ||
+ ! chmod 1777 "$tmpdir"; then
+ rv=1
+ fi
+ umount "$tmpdir" || true
+ rmdir "$tmpdir" || true
+ [ $rv -eq 0 ] || return $rv
+ fi
+ if command -v udevadm >/dev/null 2>&1; then
+ udevadm settle
+ fi
+ dmsetup rename -- "$CRYPTTAB_NAME" "$target"
+ device_msg "$target" "started"
+ return 0
+ done
+ device_msg "$target" "failed"
+ return 1
+}
+
+# Removes all mappings in crypttab, except the ones holding the root
+# file system or /usr
+do_stop() {
+ local devno_rootfs devno_usr
+ dmsetup mknodes
+ log_action_begin_msg "Stopping $INITSTATE crypto disks"
+
+ devno_rootfs="$(get_mnt_devno /)" || devno_rootfs=""
+ devno_usr="$(get_mnt_devno /usr)" || devno_usr=""
+
+ crypttab_foreach_entry _do_stop_callback
+ log_action_end_msg 0
+}
+_do_stop_callback() {
+ local skip="n" devno rv=0
+
+ # traverse the device tree for each crypttab(5) entry and mark / and
+ # /usr holders as skipped. that's suboptimal but we can't use
+ # mapped device names as they might contain any character other than
+ # NUL. shouldn't be much overhead anyway as the device tree is
+ # likely not that long
+ foreach_cryptdev _do_stop_skipped $devno_rootfs $devno_usr
+ [ "$skip" = "n" ] || return $rv
+
+ if devno="$(dmsetup info -c --noheadings -o devno -- "$CRYPTTAB_NAME" 2>/dev/null)" && [ -n "$devno" ]; then
+ foreach_cryptdev --reverse _do_stop_remove "$devno" || rv=$? # try to remove slave devices first
+ fi
+ return $rv
+}
+_do_stop_skipped() {
+ if [ "$1" = "$CRYPTTAB_NAME" ]; then
+ skip="y"
+ fi
+}
+_do_stop_remove() {
+ local name="$1" i rv=0
+ for i in 1 2 4 8 16 32; do
+ remove_mapping "$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 "$name busy..."
+ sleep $i
+ done
+}
+
+# device_msg([$name], $message)
+# Convenience function to handle $VERBOSE
+device_msg() {
+ local name message
+ if [ $# -eq 1 ]; then
+ name="$CRYPTTAB_NAME"
+ message="$1"
+ else
+ name="$1"
+ message="$2"
+ fi
+
+ if [ "$VERBOSE" != "no" ]; then
+ log_action_cont_msg "$name ($message)"
+ fi
+}
+
+# remove_mapping($target)
+# Remove mapping $target
+remove_mapping() {
+ local CRYPTTAB_NAME="$1"
+
+ if ! dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
+ device_msg "stopped"
+ return 0
+ fi
+
+ if [ "$(dmsetup info --noheadings -c -o subsystem -- "$CRYPTTAB_NAME")" != "CRYPT" ]; then
+ device_msg "error"
+ return 1
+ fi
+
+ local opencount="$(dmsetup info -c --noheadings -o open -- "$CRYPTTAB_NAME" 2>/dev/null || true)"
+ if [ -z "$opencount" ]; then
+ device_msg "error"
+ return 1
+ elif [ "$opencount" != "0" ]; then
+ device_msg "busy"
+ if [ "$INITSTATE" = "early" ] || [ "$INITSTATE" = "manual" ]; then
+ return 1
+ elif [ "$INITSTATE" = "remaining" ]; then
+ return 2
+ fi
+ return 0
+ fi
+
+ if cryptsetup remove -- "$CRYPTTAB_NAME"; then
+ device_msg "stopping"
+ return 0
+ else
+ device_msg "error"
+ return 1
+ fi
+}
+
+# vim: set filetype=sh :