Commit | Line | Data |
---|---|---|
33aa94e8 MW |
1 | #! /bin/sh |
2 | ### | |
3 | ### Mount an ephemeral filesystem | |
4 | ### | |
5 | ### (c) 2012 Mark Wooding | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This file is part of the distorted.org.uk key management suite. | |
11 | ### | |
12 | ### distorted-keys is free software; you can redistribute it and/or modify | |
13 | ### it under the terms of the GNU General Public License as published by | |
14 | ### the Free Software Foundation; either version 2 of the License, or | |
15 | ### (at your option) any later version. | |
16 | ### | |
17 | ### distorted-keys is distributed in the hope that it will be useful, | |
18 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ### GNU General Public License for more details. | |
21 | ### | |
22 | ### You should have received a copy of the GNU General Public License | |
23 | ### along with distorted-keys; if not, write to the Free Software Foundation, | |
24 | ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
25 | ||
26 | set -e | |
27 | ||
28 | QUIS=${0##*/} | |
29 | VERSION=1.0.0 | |
30 | USAGE="usage: $QUIS [-u] [-R RANDOM] [-n BYTES] [-C CIPHER] [-H HASH] | |
31 | [-l LABEL] [-t FSTYPE] [-b BACKING-FILE] MOUNTPOINT [SIZE]" | |
32 | ||
33 | ###-------------------------------------------------------------------------- | |
34 | ### Parse the command line. | |
35 | ||
36 | ## Set initial defaults. | |
37 | mode=mount | |
38 | cipher=aes-xts-plain | |
39 | hash=sha256 | |
40 | random=/dev/random | |
41 | randbytes=512 | |
42 | fail=nil | |
43 | backing=/tmp | |
44 | unset label | |
45 | ||
46 | ## Report version number. | |
47 | version () { echo "$QUIS, version $VERSION"; } | |
48 | ||
49 | ## Report help text. | |
50 | help () { | |
51 | version | |
52 | cat <<EOF | |
53 | $USAGE | |
54 | ||
55 | Options: | |
56 | -h Show this help text. | |
57 | -v Show the program's version number. | |
58 | -C CIPHER Cipher to use to encrypt the filesystem [$cipher]. | |
59 | -H HASH Hash function for hashing the random data [$hash]. | |
60 | -R RANDOM Source of random bytes for key material [$random]. | |
61 | -b BACKING Where to store the ciphertext [$backing]. | |
62 | -l LABEL Device mapper label [basename of MOUNTPOINT]. | |
63 | -n RANDBYTES Number of random bytes to read for the key [$randbytes]. | |
64 | -u Unmount the filesystem, destroying all data in it. | |
65 | EOF | |
66 | } | |
67 | ||
68 | ## Loop over the options. | |
69 | while getopts "C:H:R:b:hl:n:t:uv" opt; do | |
70 | case $opt in | |
71 | h) help; exit 0 ;; | |
72 | v) echo "$VERSION"; exit 0 ;; | |
73 | C) cipher=$OPTARG ;; | |
74 | H) hash=$OPTARG ;; | |
75 | R) random=$OPTARG ;; | |
76 | n) randbytes=$OPTARG ;; | |
77 | b) backing=$OPTARG ;; | |
78 | l) label=$OPTARG ;; | |
79 | u) mode=umount ;; | |
80 | *) fail=t ;; | |
81 | esac | |
82 | done | |
83 | shift $(( $OPTIND - 1 )) | |
84 | case $fail,$mode,$# in | |
85 | nil,mount,2) mntpt=$1 size=$2 ;; | |
86 | nil,umount,1) mntpt=$1 ;; | |
87 | *) echo >&2 "$USAGE"; exit 1 ;; | |
88 | esac | |
89 | ||
90 | ## Default omitted arguments. | |
91 | case "${label+t}" in t) ;; *) label=${mntpt##*/} ;; esac | |
92 | ||
93 | ###-------------------------------------------------------------------------- | |
94 | ### Do the job. | |
95 | ||
96 | case $mode in | |
97 | ||
98 | mount) | |
99 | ## Mount the filesystem. | |
100 | ||
101 | ## Determine a name for the backing file. If BACKING is a directory then | |
102 | ## we should make a file there and delete it once we've created a | |
103 | ## mapping. The directory may be a shared bit of filesystem, so we must | |
104 | ## be very careful. | |
105 | rmbacking=nil | |
106 | if [ -d "$backing" ]; then | |
107 | i=0 | |
108 | while :; do | |
109 | gorp=$(openssl rand -base64 6) | |
110 | bkdir=$backing/mnteph.$$.$gorp | |
111 | if mkdir >/dev/null 2>&1 -m700 "$bkdir"; then break; fi | |
112 | i=$(( $i + 1 )) | |
113 | if [ $i -ge 100 ]; then | |
114 | echo >&2 "$QUIS: failed to create backing directory" | |
115 | exit 1 | |
116 | fi | |
117 | done | |
118 | backing=$bkdir/fs | |
119 | trap 'rc=$?; rm "$backing"; rmdir "$bkdir"; exit $rc' EXIT | |
120 | trap 'exit 127' INT TERM | |
121 | rmbacking=t | |
122 | fi | |
123 | ||
124 | ## Create the backing file. | |
125 | truncate -s"$size" "$backing" | |
126 | loop=$(losetup -f --show "$backing") | |
127 | ||
128 | ## Attach a device-mapper entry to the file. | |
129 | dd 2>/dev/null if="$random" bs=1 count="$randbytes" | | |
130 | cryptsetup \ | |
131 | --cipher="$cipher" --hash="$hash" \ | |
132 | --key-file=- \ | |
133 | create "$label" "$loop" | |
134 | ||
135 | ## Create the filesystem. | |
136 | if spew=$(mkfs 2>&1 "/dev/mapper/$label"); then | |
137 | : | |
138 | else | |
139 | rc=$? | |
140 | echo >&2 "$QUIS: mkfs failed (rc = $rc)" | |
141 | echo "$spew" | sed >&2 's/^/| /' | |
142 | exit $rc | |
143 | fi | |
144 | ||
145 | ## Mount. | |
146 | mount "/dev/mapper/$label" "$mntpt" | |
147 | ;; | |
148 | ||
149 | umount) | |
150 | ## Unmount a filesystem. | |
151 | ||
152 | ## Find the numbers of the loopback device. | |
153 | deps=$(dmsetup deps "/dev/mapper/$label") | |
154 | set -- $(echo "$deps" | | |
155 | sed 's!^.*:.*(\([0-9]\+\),[[:space:]]*\([0-9]\+\)).*$!\1 \2!') | |
156 | case "$#" in | |
157 | 2) ;; | |
158 | *) | |
159 | echo >&2 "$QUIS: unexpected answer from \`dmsetup deps'" | |
160 | echo "$deps" | sed >&2 's/^/| /' | |
161 | exit 1 | |
162 | ;; | |
163 | esac | |
164 | maj=$1 min=$2 | |
165 | ||
166 | ## Convert that into a name. | |
167 | dev=$(readlink /sys/dev/block/$maj:$min) | |
168 | dev=${dev##*/} | |
169 | case "$dev" in | |
170 | loop*) ;; | |
171 | *) | |
172 | echo >&2 "$QUIS: expected a loopback device; found \`$dev'" | |
173 | exit 1 | |
174 | ;; | |
175 | esac | |
176 | ||
177 | ## Unmount the filesystem. | |
178 | umount "$mntpt" | |
179 | ||
180 | ## Remove the cryptoloop mapping. | |
181 | if spew=$(cryptsetup 2>&1 remove "$label"); then | |
182 | : | |
183 | else | |
184 | rc=$? | |
185 | echo >&2 "$QUIS: cryptsetup failed (rc = $rc)" | |
186 | echo "$spew" | sed >&2 's/^/| /' | |
187 | exit $rc | |
188 | fi | |
189 | ||
190 | ## Disconnect the loopback device. | |
191 | losetup -d "/dev/$dev" | |
192 | ;; | |
193 | ||
194 | esac | |
195 | ||
196 | ###----- That's all, folks -------------------------------------------------- |