chiark / gitweb /
Directory claiming and ephemeral filesystems.
[distorted-keys] / mount-ephemeral
CommitLineData
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
26set -e
27
28QUIS=${0##*/}
29VERSION=1.0.0
30USAGE="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.
37mode=mount
38cipher=aes-xts-plain
39hash=sha256
40random=/dev/random
41randbytes=512
42fail=nil
43backing=/tmp
44unset label
45
46## Report version number.
47version () { echo "$QUIS, version $VERSION"; }
48
49## Report help text.
50help () {
51 version
52 cat <<EOF
53$USAGE
54
55Options:
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.
65EOF
66}
67
68## Loop over the options.
69while 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
82done
83shift $(( $OPTIND - 1 ))
84case $fail,$mode,$# in
85 nil,mount,2) mntpt=$1 size=$2 ;;
86 nil,umount,1) mntpt=$1 ;;
87 *) echo >&2 "$USAGE"; exit 1 ;;
88esac
89
90## Default omitted arguments.
91case "${label+t}" in t) ;; *) label=${mntpt##*/} ;; esac
92
93###--------------------------------------------------------------------------
94### Do the job.
95
96case $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
194esac
195
196###----- That's all, folks --------------------------------------------------