Update.
[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 [[ "$@" == "" ]]
54 then
55     print_help >&2
56     exit 1
57 fi
58
59 if [[ ! $(id -u) == 0 ]]
60 then
61     echo "This command should be run as root (no offense, but you are $(id -un))." >&2
62     exit 1
63 fi
64
65 ######################################################################
66
67 case $1 in
68
69     clean)
70
71         # mount | grep ^'/dev/dm-[0-9]*' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
72
73         mount | grep ^'/dev/mapper' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | \
74             while read line
75             do
76                 echo "umount ${line}"
77                 umount ${line}
78             done
79
80         \ls /dev/mapper | grep -v ^control$ | \
81             while read line
82             do
83                 echo "cryptsetup luksClose ${line[0]}"
84                 cryptsetup luksClose "${line[0]}"
85             done
86
87         losetup -a | sed -e "s/:.*$//" | \
88             while read line
89             do
90                 echo "losetup -d ${line}"
91                 losetup -d ${line}
92             done
93
94         exit 0
95
96         ;;
97
98     ######################################################################
99
100     sync)
101
102         shift
103
104         [[ -f "$1" ]] && [[ -f "$2" ]] || (echo "$(basename $0) sync <source file> <dest file>" >&2 && exit 1)
105
106         [[ -e "/dev/mapper/crypt-src" ]] && (echo "/dev/mapper/crypt-src already exists." >&2 && exit 1)
107
108         [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
109
110         ######################################################################
111         # Mount the volumes
112
113         echo "Please confirm that $2 can be modified (press 'y')"
114
115         read -n 1 KEY
116
117         if [[ ! "${KEY}" == "y" ]]
118         then
119             echo "Cancelled!"
120             exit 1
121         fi
122
123         echo
124
125         LOOP_SRC="$(losetup -f)"
126         losetup "${LOOP_SRC}" "$1"
127         cryptsetup luksOpen "${LOOP_SRC}" crypt-src
128         DIR_MOUNT_SRC="$(mktemp -d /tmp/sync-luks.XXXXXX)"
129         mount -o ro /dev/mapper/crypt-src "${DIR_MOUNT_SRC}"
130
131         LOOP_DST="$(losetup -f)"
132         losetup "${LOOP_DST}" "$2"
133         cryptsetup luksOpen "${LOOP_DST}" crypt-dst
134         DIR_MOUNT_DST="$(mktemp -d /tmp/sync-luks.XXXXXX)"
135         mount /dev/mapper/crypt-dst "${DIR_MOUNT_DST}"
136
137         ######################################################################
138         # First, show the changes
139
140         echo "**********************************************************************"
141         echo "* Dry-run"
142
143         rsync -n --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
144
145         ######################################################################
146         # Ask for confirmation and synchronize
147
148         echo "**********************************************************************"
149         echo "* Press 'y' to synchronize, anything else to cancel."
150
151         read -n 1 KEY
152
153         if [[ "${KEY}" == "y" ]]
154         then
155             echo
156             rsync --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
157         else
158             echo "No synchronization."
159         fi
160
161         umount "${DIR_MOUNT_SRC}" && rmdir "${DIR_MOUNT_SRC}" && unset DIR_MOUNT_SRC
162         cryptsetup luksClose crypt-src
163         losetup -d "${LOOP_SRC}" && unset LOOP_SRC
164
165         umount "${DIR_MOUNT_DST}" && rmdir "${DIR_MOUNT_DST}" && unset DIR_MOUNT_DST
166         cryptsetup luksClose crypt-dst
167         losetup -d "${LOOP_DST}" && unset LOOP_DST
168
169         exit 0
170
171         ;;
172
173
174     ######################################################################
175
176     fsck)
177
178         shift
179
180         if [[ "$1" == "-f" ]]
181         then
182             force="-f"
183             shift
184         fi
185
186         if [[ ! -a "$1" ]]
187         then
188             echo "Cannot find file \`$1'." >&2
189             exit 1
190         fi
191
192         [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
193
194         if [[ -f "$1" ]]
195         then
196             LOOP_DST="$(losetup -f)"
197             losetup "${LOOP_DST}" "$1"
198             DEVICE="${LOOP_DST}"
199         else
200             DEVICE="$1"
201         fi
202
203         cryptsetup luksOpen "${DEVICE}" crypt-dst
204
205         fsck ${force} /dev/mapper/crypt-dst
206
207         sleep 1
208
209         cryptsetup luksClose crypt-dst
210
211         if [[ "${LOOP_DST}" ]]
212         then
213             losetup -d "${LOOP_DST}" && unset LOOP_DST
214         fi
215
216         exit 0
217
218         ;;
219
220     ######################################################################
221
222     mount|umount)
223
224         if [[ "$1" == "umount" ]]
225         then
226             umount=yes
227         fi
228
229         shift
230
231         mount_point=$(echo $1 | sed -e "s;/*$;;")
232         device=$(grep ^/ /etc/fstab | awk '{ print $2" "$1 }' | grep ^${mount_point} | cut -f 2 -d " ")
233
234         if [[ ${device} =~ ^/dev/mapper ]]
235         then
236
237             mapped_device=${device/'/dev/mapper/'/}
238
239             if [[ ${umount} ]]
240             then
241                 cat <<EOF
242 Attempting to unmount
243    ${mount_point}.
244 EOF
245                 umount ${mount_point} && cryptdisks_stop "${mapped_device}"
246             else
247                 cat <<EOF
248 Attempting to mount
249   ${device}
250 on
251   ${mount_point}
252 EOF
253                 cryptdisks_start "${mapped_device}" && mount ${mount_point}
254             fi
255
256         else
257
258             echo "\`${device}' does not look like a LUKS one"
259
260         fi
261
262         exit 0
263
264         ;;
265
266     ######################################################################
267
268     -h|--help)
269         print_help
270         ;;
271
272     *)
273         echo "Unknown argument \`$1', aborting." >&2
274         ;;
275
276 esac