Initial commit.
[scripts.git] / luks_toolbox.sh
1 #!/bin/bash
2
3 #########################################################################
4 # This program is free software: you can redistribute it and/or modify  #
5 # it under the terms of the version 3 of the GNU General Public License #
6 # as published by the Free Software Foundation.                         #
7 #                                                                       #
8 # This program is distributed in the hope that it will be useful, but   #
9 # WITHOUT ANY WARRANTY; without even the implied warranty of            #
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      #
11 # General Public License for more details.                              #
12 #                                                                       #
13 # You should have received a copy of the GNU General Public License     #
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.  #
15 #                                                                       #
16 # Written by and Copyright (C) Francois Fleuret                         #
17 # Contact <francois.fleuret@idiap.ch> for comments & bug reports        #
18 #########################################################################
19
20 set -e
21 # set -o pipefail
22
23 function print_help () {
24     cat <<EOF
25 $(basename $0) [--help | clean | sync <source file> <dest file> | fsck [-f] <file|device> | mount <dir> | umount <dir>]
26
27 clean
28
29   1. umounts all the volumes using a /dev/dm-* device
30   2. LUKS-close all the volumes appearing in /dev/mapper
31   3. Delete all the loop devices
32
33 sync
34
35   Mounts both files as LUKS volumes, runs a dry-run rsync, and asks for
36   interactive confirmation before synchronizing.
37
38 fsck
39
40   LUKS-open the provided file and run fsck on it.
41
42 mount|umount
43
44   Automagically figures out from /etc/fstab what is the /dev/mapper/
45   device associated to the dir, and both LUKS-opens/mounts or
46   umount/LUKS-closes it.
47
48 EOF
49 }
50
51 ######################################################################
52
53 if [[ "$@" == "" ]]; then
54     print_help >&2
55     exit 1
56 fi
57
58 if [[ ! $(id -u) == 0 ]]; then
59     echo "This command should be run as root (no offense, but you are $(id -un))." >&2
60     exit 1
61 fi
62
63 ######################################################################
64
65 case $1 in
66
67     clean)
68
69         # mount | grep ^'/dev/dm-[0-9]*' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
70
71         mount | grep ^'/dev/mapper' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
72             while read line; do
73                 echo "umount ${line}"
74                 umount ${line}
75             done
76
77         \ls /dev/mapper | grep -v ^control$ | \
78             while read line; do
79                 echo "cryptsetup luksClose ${line[0]}"
80                 cryptsetup luksClose "${line[0]}"
81             done
82
83         losetup -a | sed -e "s/:.*$//" | \
84             while read line; do
85                 echo "losetup -d ${line}"
86                 losetup -d ${line}
87             done
88
89         exit 0
90
91         ;;
92
93     ######################################################################
94
95     sync)
96
97         shift
98
99         [[ -f "$1" ]] && [[ -f "$2" ]] || (echo "$(basename $0) sync <source file> <dest file>" >&2 && exit 1)
100
101         [[ -e "/dev/mapper/crypt-src" ]] && (echo "/dev/mapper/crypt-src already exists." >&2 && exit 1)
102
103         [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
104
105         ######################################################################
106         # Mount the volumes
107
108         echo "Please confirm that $2 can be modified (press 'y')"
109
110         read -n 1 KEY
111
112         if [[ ! "${KEY}" == "y" ]]; then
113             echo "Cancelled!"
114             exit 1
115         fi
116
117         echo
118
119         LOOP_SRC="$(losetup -f)"
120         losetup "${LOOP_SRC}" "$1"
121         cryptsetup luksOpen "${LOOP_SRC}" crypt-src
122         DIR_MOUNT_SRC="$(mktemp -d /tmp/sync-luks.XXXXXX)"
123         mount -o ro /dev/mapper/crypt-src "${DIR_MOUNT_SRC}"
124
125         LOOP_DST="$(losetup -f)"
126         losetup "${LOOP_DST}" "$2"
127         cryptsetup luksOpen "${LOOP_DST}" crypt-dst
128         DIR_MOUNT_DST="$(mktemp -d /tmp/sync-luks.XXXXXX)"
129         mount /dev/mapper/crypt-dst "${DIR_MOUNT_DST}"
130
131         ######################################################################
132         # First, show the changes
133
134         echo "**********************************************************************"
135         echo "* Dry-run"
136
137         rsync -n --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
138
139         ######################################################################
140         # Ask for confirmation and synchronize
141
142         echo "**********************************************************************"
143         echo "* Press 'y' to synchronize, anything else to cancel."
144
145         read -n 1 KEY
146
147         if [[ "${KEY}" == "y" ]]; then
148             echo
149             rsync --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
150         else
151             echo "No synchronization."
152         fi
153
154         umount "${DIR_MOUNT_SRC}" && rmdir "${DIR_MOUNT_SRC}" && unset DIR_MOUNT_SRC
155         cryptsetup luksClose crypt-src
156         losetup -d "${LOOP_SRC}" && unset LOOP_SRC
157
158         umount "${DIR_MOUNT_DST}" && rmdir "${DIR_MOUNT_DST}" && unset DIR_MOUNT_DST
159         cryptsetup luksClose crypt-dst
160         losetup -d "${LOOP_DST}" && unset LOOP_DST
161
162         exit 0
163
164         ;;
165
166
167     ######################################################################
168
169     fsck)
170
171         shift
172
173         if [[ "$1" == "-f" ]]; then
174             force="-f"
175             shift
176         fi
177
178         if [[ ! -a "$1" ]]; then
179             echo "Cannot find file \`$1'." >&2
180             exit 1
181         fi
182
183         [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
184
185         if [[ -f "$1" ]]; then
186             LOOP_DST="$(losetup -f)"
187             losetup "${LOOP_DST}" "$1"
188             DEVICE="${LOOP_DST}"
189         else
190             DEVICE="$1"
191         fi
192
193         cryptsetup luksOpen "${DEVICE}" crypt-dst
194
195         fsck ${force} /dev/mapper/crypt-dst
196
197         sleep 1
198
199         cryptsetup luksClose crypt-dst
200
201         if [[ "${LOOP_DST}" ]]; then
202             losetup -d "${LOOP_DST}" && unset LOOP_DST
203         fi
204
205         exit 0
206
207         ;;
208
209     ######################################################################
210
211     mount|umount)
212
213         if [[ "$1" == "umount" ]]; then
214             umount=yes
215         fi
216
217         shift
218
219         mount_point=$(echo $1 | sed -e "s;/*$;;")
220         device=$(grep ^/ /etc/fstab | awk '{ print $2" "$1 }' | grep ^${mount_point} | cut -f 2 -d " ")
221
222         if [[ ${device} =~ ^/dev/mapper ]]; then
223
224             mapped_device=${device/'/dev/mapper/'/}
225
226             if [[ ${umount} ]]; then
227                 cat <<EOF
228 Attempting to unmount
229    ${mount_point}.
230 EOF
231                 umount ${mount_point} && cryptdisks_stop "${mapped_device}"
232             else
233                 cat <<EOF
234 Attempting to mount
235   ${device}
236 on
237   ${mount_point}
238 EOF
239                 cryptdisks_start "${mapped_device}" && mount ${mount_point}
240             fi
241
242         else
243
244             echo "\`${device}' does not look like a LUKS one"
245
246         fi
247
248         exit 0
249
250         ;;
251
252     ######################################################################
253
254     -h|--help)
255         print_help
256         ;;
257
258     *)
259         echo "Unknown argument \`$1', aborting." >&2
260         ;;
261
262 esac