Initial commit.
authorFrancois Fleuret <francois@fleuret.org>
Mon, 31 Jul 2017 22:34:52 +0000 (00:34 +0200)
committerFrancois Fleuret <francois@fleuret.org>
Mon, 31 Jul 2017 22:34:52 +0000 (00:34 +0200)
luks_toolbox.sh [new file with mode: 0755]

diff --git a/luks_toolbox.sh b/luks_toolbox.sh
new file mode 100755 (executable)
index 0000000..ac4e3a2
--- /dev/null
@@ -0,0 +1,262 @@
+#!/bin/bash
+
+#########################################################################
+# This program is free software: you can redistribute it and/or modify  #
+# it under the terms of the version 3 of the GNU General Public License #
+# as published by the Free Software Foundation.                         #
+#                                                                       #
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.  #
+#                                                                       #
+# Written by and Copyright (C) Francois Fleuret                         #
+# Contact <francois.fleuret@idiap.ch> for comments & bug reports        #
+#########################################################################
+
+set -e
+# set -o pipefail
+
+function print_help () {
+    cat <<EOF
+$(basename $0) [--help | clean | sync <source file> <dest file> | fsck [-f] <file|device> | mount <dir> | umount <dir>]
+
+clean
+
+  1. umounts all the volumes using a /dev/dm-* device
+  2. LUKS-close all the volumes appearing in /dev/mapper
+  3. Delete all the loop devices
+
+sync
+
+  Mounts both files as LUKS volumes, runs a dry-run rsync, and asks for
+  interactive confirmation before synchronizing.
+
+fsck
+
+  LUKS-open the provided file and run fsck on it.
+
+mount|umount
+
+  Automagically figures out from /etc/fstab what is the /dev/mapper/
+  device associated to the dir, and both LUKS-opens/mounts or
+  umount/LUKS-closes it.
+
+EOF
+}
+
+######################################################################
+
+if [[ "$@" == "" ]]; then
+    print_help >&2
+    exit 1
+fi
+
+if [[ ! $(id -u) == 0 ]]; then
+    echo "This command should be run as root (no offense, but you are $(id -un))." >&2
+    exit 1
+fi
+
+######################################################################
+
+case $1 in
+
+    clean)
+
+        # mount | grep ^'/dev/dm-[0-9]*' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
+
+        mount | grep ^'/dev/mapper' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
+            while read line; do
+                echo "umount ${line}"
+                umount ${line}
+            done
+
+        \ls /dev/mapper | grep -v ^control$ | \
+            while read line; do
+                echo "cryptsetup luksClose ${line[0]}"
+                cryptsetup luksClose "${line[0]}"
+            done
+
+        losetup -a | sed -e "s/:.*$//" | \
+            while read line; do
+                echo "losetup -d ${line}"
+                losetup -d ${line}
+            done
+
+        exit 0
+
+        ;;
+
+    ######################################################################
+
+    sync)
+
+        shift
+
+        [[ -f "$1" ]] && [[ -f "$2" ]] || (echo "$(basename $0) sync <source file> <dest file>" >&2 && exit 1)
+
+        [[ -e "/dev/mapper/crypt-src" ]] && (echo "/dev/mapper/crypt-src already exists." >&2 && exit 1)
+
+        [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
+
+        ######################################################################
+        # Mount the volumes
+
+        echo "Please confirm that $2 can be modified (press 'y')"
+
+        read -n 1 KEY
+
+        if [[ ! "${KEY}" == "y" ]]; then
+            echo "Cancelled!"
+            exit 1
+        fi
+
+        echo
+
+        LOOP_SRC="$(losetup -f)"
+        losetup "${LOOP_SRC}" "$1"
+        cryptsetup luksOpen "${LOOP_SRC}" crypt-src
+        DIR_MOUNT_SRC="$(mktemp -d /tmp/sync-luks.XXXXXX)"
+        mount -o ro /dev/mapper/crypt-src "${DIR_MOUNT_SRC}"
+
+        LOOP_DST="$(losetup -f)"
+        losetup "${LOOP_DST}" "$2"
+        cryptsetup luksOpen "${LOOP_DST}" crypt-dst
+        DIR_MOUNT_DST="$(mktemp -d /tmp/sync-luks.XXXXXX)"
+        mount /dev/mapper/crypt-dst "${DIR_MOUNT_DST}"
+
+        ######################################################################
+        # First, show the changes
+
+        echo "**********************************************************************"
+        echo "* Dry-run"
+
+        rsync -n --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
+
+        ######################################################################
+        # Ask for confirmation and synchronize
+
+        echo "**********************************************************************"
+        echo "* Press 'y' to synchronize, anything else to cancel."
+
+        read -n 1 KEY
+
+        if [[ "${KEY}" == "y" ]]; then
+            echo
+            rsync --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
+        else
+            echo "No synchronization."
+        fi
+
+        umount "${DIR_MOUNT_SRC}" && rmdir "${DIR_MOUNT_SRC}" && unset DIR_MOUNT_SRC
+        cryptsetup luksClose crypt-src
+        losetup -d "${LOOP_SRC}" && unset LOOP_SRC
+
+        umount "${DIR_MOUNT_DST}" && rmdir "${DIR_MOUNT_DST}" && unset DIR_MOUNT_DST
+        cryptsetup luksClose crypt-dst
+        losetup -d "${LOOP_DST}" && unset LOOP_DST
+
+        exit 0
+
+        ;;
+
+
+    ######################################################################
+
+    fsck)
+
+        shift
+
+        if [[ "$1" == "-f" ]]; then
+            force="-f"
+            shift
+        fi
+
+        if [[ ! -a "$1" ]]; then
+            echo "Cannot find file \`$1'." >&2
+            exit 1
+        fi
+
+        [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
+
+        if [[ -f "$1" ]]; then
+            LOOP_DST="$(losetup -f)"
+            losetup "${LOOP_DST}" "$1"
+            DEVICE="${LOOP_DST}"
+        else
+            DEVICE="$1"
+        fi
+
+        cryptsetup luksOpen "${DEVICE}" crypt-dst
+
+        fsck ${force} /dev/mapper/crypt-dst
+
+        sleep 1
+
+        cryptsetup luksClose crypt-dst
+
+        if [[ "${LOOP_DST}" ]]; then
+            losetup -d "${LOOP_DST}" && unset LOOP_DST
+        fi
+
+        exit 0
+
+        ;;
+
+    ######################################################################
+
+    mount|umount)
+
+        if [[ "$1" == "umount" ]]; then
+            umount=yes
+        fi
+
+        shift
+
+        mount_point=$(echo $1 | sed -e "s;/*$;;")
+        device=$(grep ^/ /etc/fstab | awk '{ print $2" "$1 }' | grep ^${mount_point} | cut -f 2 -d " ")
+
+        if [[ ${device} =~ ^/dev/mapper ]]; then
+
+            mapped_device=${device/'/dev/mapper/'/}
+
+            if [[ ${umount} ]]; then
+                cat <<EOF
+Attempting to unmount
+   ${mount_point}.
+EOF
+                umount ${mount_point} && cryptdisks_stop "${mapped_device}"
+            else
+                cat <<EOF
+Attempting to mount
+  ${device}
+on
+  ${mount_point}
+EOF
+                cryptdisks_start "${mapped_device}" && mount ${mount_point}
+            fi
+
+        else
+
+            echo "\`${device}' does not look like a LUKS one"
+
+        fi
+
+        exit 0
+
+        ;;
+
+    ######################################################################
+
+    -h|--help)
+        print_help
+        ;;
+
+    *)
+        echo "Unknown argument \`$1', aborting." >&2
+        ;;
+
+esac