aed8dc013eed9dca01c6de29d85992984fbe957b
[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, then rsync.
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   umounts/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/mapper' | sed -e 's/^.* on \([^ ]*\) .*$/\1/' | while read line
72         do
73             echo "umount ${line}"
74             umount "${line}"
75         done
76
77         find /dev/mapper -type l | while read line
78         do
79             echo "cryptsetup luksClose ${line}"
80             cryptsetup luksClose "${line}"
81         done
82
83         losetup -a | sed -e "s/:.*$//" | while read line
84         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" ]]
113         then
114             echo "Cancelled!"
115             exit 1
116         fi
117
118         echo
119
120         LOOP_SRC="$(losetup -f)"
121         losetup "${LOOP_SRC}" "$1"
122         cryptsetup luksOpen "${LOOP_SRC}" crypt-src
123         DIR_MOUNT_SRC="$(mktemp -d /tmp/sync-luks.XXXXXX)"
124         mount -o ro /dev/mapper/crypt-src "${DIR_MOUNT_SRC}"
125
126         LOOP_DST="$(losetup -f)"
127         losetup "${LOOP_DST}" "$2"
128         cryptsetup luksOpen "${LOOP_DST}" crypt-dst
129         DIR_MOUNT_DST="$(mktemp -d /tmp/sync-luks.XXXXXX)"
130         mount /dev/mapper/crypt-dst "${DIR_MOUNT_DST}"
131
132         ######################################################################
133         # First, show the changes
134
135         echo "**********************************************************************"
136         echo "* Dry-run"
137
138         rsync -n --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
139
140         ######################################################################
141         # Ask for confirmation and synchronize
142
143         echo "**********************************************************************"
144         echo "* Press 'y' to synchronize, anything else to cancel."
145
146         read -n 1 KEY
147
148         if [[ "${KEY}" == "y" ]]
149         then
150             echo
151             rsync --itemize-changes --delete --progress -axz "${DIR_MOUNT_SRC}/" "${DIR_MOUNT_DST}/"
152         else
153             echo "No synchronization."
154         fi
155
156         umount "${DIR_MOUNT_SRC}" && rmdir "${DIR_MOUNT_SRC}" && unset DIR_MOUNT_SRC
157         cryptsetup luksClose crypt-src
158         losetup -d "${LOOP_SRC}" && unset LOOP_SRC
159
160         umount "${DIR_MOUNT_DST}" && rmdir "${DIR_MOUNT_DST}" && unset DIR_MOUNT_DST
161         cryptsetup luksClose crypt-dst
162         losetup -d "${LOOP_DST}" && unset LOOP_DST
163
164         exit 0
165
166         ;;
167
168
169     ######################################################################
170
171     fsck)
172
173         shift
174
175         if [[ "$1" == "-f" ]]
176         then
177             force="-f"
178             shift
179         fi
180
181         if [[ ! -a "$1" ]]
182         then
183             echo "Cannot find file \`$1'." >&2
184             exit 1
185         fi
186
187         [[ -e "/dev/mapper/crypt-dst" ]] && (echo "/dev/mapper/crypt-dst already exists." >&2 && exit 1)
188
189         if [[ -f "$1" ]]
190         then
191             LOOP_DST="$(losetup -f)"
192             losetup "${LOOP_DST}" "$1"
193             DEVICE="${LOOP_DST}"
194         else
195             DEVICE="$1"
196         fi
197
198         cryptsetup luksOpen "${DEVICE}" crypt-dst
199
200         fsck ${force} /dev/mapper/crypt-dst
201
202         sleep 1
203
204         cryptsetup luksClose crypt-dst
205
206         if [[ "${LOOP_DST}" ]]
207         then
208             losetup -d "${LOOP_DST}" && unset LOOP_DST
209         fi
210
211         exit 0
212
213         ;;
214
215     ######################################################################
216
217     mount|umount)
218
219         if [[ "$1" == "umount" ]]
220         then
221             umount=yes
222         fi
223
224         shift
225
226         mount_point=$(echo $1 | sed -e "s;/*$;;")
227         device=$(grep ^/ /etc/fstab | awk '{ print $2" "$1 }' | grep ^${mount_point} | cut -f 2 -d " ")
228
229         if [[ ${device} =~ ^/dev/mapper ]]
230         then
231
232             mapped_device=${device/'/dev/mapper/'/}
233
234             if [[ ${umount} ]]
235             then
236                 cat <<EOF
237 Attempting to unmount
238    ${mount_point}.
239 EOF
240                 umount ${mount_point} && cryptdisks_stop "${mapped_device}"
241             else
242                 cat <<EOF
243 Attempting to mount
244   ${device}
245 on
246   ${mount_point}
247 EOF
248                 cryptdisks_start "${mapped_device}" && mount ${mount_point}
249             fi
250
251         else
252
253             echo "\`${device}' does not look like a luks one"
254
255         fi
256
257         exit 0
258
259         ;;
260
261     ######################################################################
262
263     -h|--help)
264         print_help
265         ;;
266
267     *)
268         echo "Unknown argument \`$1', aborting." >&2
269         ;;
270
271 esac