-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathgocryptfs-helper
executable file
Β·411 lines (366 loc) Β· 10.8 KB
/
gocryptfs-helper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
#!/usr/bin/env bash
# https://github.com/rfjakob/gocryptfs/blob/master/Documentation/MANPAGE.md
function gocryptfs_helper() (
source "$DOROTHY/sources/bash.bash"
# =====================================
# Arguments
function help {
cat <<-EOF >/dev/stderr
ABOUT:
Wrappers around gocryptfs to make things easier.
USAGE:
gocryptfs-helper <action>
ACTIONS:
new -- <vault>
Creates a new vault at <vault> with the best algorithm for it.
compare -- <vault-one> <vault-two>
Compares the features of two vaults, returning 0 if the same.
features -- <vault>
Outputs the enabled feature flags of teh gocryptfs vault.
info -- <vault>
Prints information about gocryptfs version, speed, and vault information.
migrate -- <vault>
Upgrades the gocryptfs vault to the best algorithm for it, this can take a while.
mount -- <vault> <mount-point> [--owner=<owner>] [--user=<user>] [--group=<group>]
Mounts the vault at the mount-point.
unmount -- <mount-point>
Unmounts the mount-point.
upgrade -- <vault>
Upgrades the gocryptfs version.
version
Prints the version of gocryptfs.
verify -- <vault> [--user=<user>] [--group=<group>]
Verifies that the path is a gocryptfs vault.
EOF
if [[ $# -ne 0 ]]; then
echo-error "$@"
fi
return 22 # EINVAL 22 Invalid argument
}
# process
local item action='' option_args=()
while [[ $# -ne 0 ]]; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
'--')
option_args+=("$@")
shift $#
break
;;
'--'*) help "An unrecognised flag was provided: $item" ;;
*)
if [[ -z $action ]]; then
action="$item"
else
help "An unrecognised argument was provided: $item"
fi
;;
esac
done
# ensure valid action
local actions=(
new
compare
features
info
migrate
mount
unmount
upgrade
verify
version
)
action="$(
choose --required \
--question='What action to perform?' \
--skip-default --default="$action" -- "${actions[@]}"
)"
# =====================================
# Dependencies
setup-util-gocryptfs --quiet
# =====================================
# Helpers
# -------------------------------------
# Minor Actions
function act_version {
gocryptfs --version | echo-regexp -o --regexp='20\d+-\d+-\d+'
}
function act_info {
local vault="${1-}"
eval-helper --no-quiet --wrap \
-- gocryptfs --speed # dumps version info
if [[ -n $vault ]]; then
eval-helper --no-quiet --wrap \
-- gocryptfs --info "$vault" # dumps vault info
fi
}
function act_verify {
# process
local item vault='' owner='' user='' group=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
'--user='*) user="${item#*=}" ;;
'--group='*) group="${item#*=}" ;;
'--'*) help "An unrecognised flag was provided: $item" ;;
*)
if [[ -z $vault ]]; then
vault="$item"
else
help "An unrecognised argument was provided: $item"
fi
;;
esac
done
# check
if is-file --user="$user" --group="$group" -- "$vault/gocryptfs.conf"; then
echo-style --code-good1="$vault" --good1=' is a gocryptfs vault'
else
echo-style --code-error1="$vault" --error1=' is not a gocryptfs vault' >/dev/stderr
return 1
fi
}
function act_features {
local vault="$1"
gocryptfs --info "$vault" | grep FeatureFlags
}
function act_compare {
local old_vault="$1" new_vault="$2" result=0
local old_vault_features new_vault_features
old_vault_features="$(
act_features "$old_vault"
)"
new_vault_features="$(
act_features "$new_vault"
)"
# compare the features
if [[ $old_vault_features == "$new_vault_features" ]]; then
echo-style --success="Vaults have the same features."
result=0
else
echo-style --warning="Vaults have different features."
result=1
fi
echo-style --element="$old_vault"
__print_lines "$old_vault_features"
echo-style --/element="$old_vault"
echo-style --element="$new_vault"
__print_lines "$new_vault_features"
echo-style --/element="$new_vault"
return "$result"
}
function act_upgrade {
setup-util-gocryptfs --upgrade
}
function act_mount {
# process
local item mount_source='' mount_target='' owner='' user='' group=''
while [[ $# -ne 0 ]]; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
'--owner='*) owner="${item#*=}" ;;
'--user='*) user="${item#*=}" ;;
'--group='*) group="${item#*=}" ;;
'--'*) help "An unrecognised flag was provided: $item" ;;
*)
if [[ -z $mount_source ]]; then
mount_source="$item"
elif [[ -z $mount_target ]]; then
mount_target="$item"
elif [[ -z $owner ]]; then
owner="$item"
else
help "An unrecognised argument was provided: $item"
fi
;;
esac
done
# check
if [[ -z $mount_source || -z $mount_target ]]; then
help "No <path>s provided."
fi
# construct command
local mount_cmd=() ls_cmd=()
if [[ -n $owner || -n $user || -n $group ]]; then
# https://github.com/rfjakob/gocryptfs/issues/638#issuecomment-1009578054
mount_cmd+=(
'sudo-helper'
"--user=$user"
"--group=$group"
'--'
)
ls_cmd+=(
'sudo-helper'
"--user=$user"
"--group=$group"
'--'
)
fi
mount_cmd+=(
'gocryptfs'
'--rw'
'--noprealloc'
'--allow_other'
)
if [[ -n $owner ]]; then
mount_cmd+=(
'--force_owner'
"$owner"
)
fi
mount_cmd+=(
"$mount_source"
"$mount_target"
)
ls_cmd+=(
'ls'
'-la'
"$mount_target"
)
# mount
echo-style --bold='Enter the cipher password for mounting:' --newline \
--code="$mount_source" --bold=' => ' --code="$mount_target"
eval-helper --no-quiet --wrap \
-- "${mount_cmd[@]}"
eval-helper --no-quiet --wrap \
-- "${ls_cmd[@]}"
if [[ -n $owner || -n $user || -n $group ]]; then
eval-helper --no-quiet --wrap \
-- fs-own --ug --owner="$owner" --user="$user" --group="$group" --recursive \
-- "$mount_target"
fi
__print_line
}
# -------------------------------------
# Init Action
function act_new {
local new_vault="$1" algorithm=''
# optional
if is-raspi; then
algorithm='xchacha'
fi
algorithm="$(
choose \
--question='Which algorithm to use for the new vault?' \
--label --default="$algorithm" -- aessiv 'AES-SIV (RFC5297) - Best for AES Hardware Acceleration' xchacha 'XChaCha20-Poly1305 β Best for Raspberry Pi'
)"
# create
if is-missing -- "$new_vault" || is-empty-directory -- "$new_vault"; then
__mkdirp "$new_vault"
echo-style --bold="Creating a new vault vault at [$new_vault] with algorithm [$algorithm]."
gocryptfs --init --"$algorithm" "$new_vault"
else
{
echo-style --error="Something already existed at [$new_vault]..."
echo-style --notice='Leaving for you to figure out.'
fs-structure -- "$new_vault"
} >/dev/stderr
return 1
fi
}
# -------------------------------------
# Migrate Action
function act_migrate {
local old_vault="$1" algorithm='' verify_status compare_status temp_dir new_vault old_plain new_plain
# optional
if is-raspi; then
algorithm='xchacha'
fi
algorithm="$(
choose \
--question="Which algorithm to use for the new vault?" \
--label --default="$algorithm" -- aessiv 'AES-SIV (RFC5297) - Best for AES Hardware Acceleration' xchacha 'XChaCha20-Poly1305 β Best for Raspberry Pi'
)"
# prepare temporary mount points
temp_dir="$(fs-temp --directory='gocryptfs-helper' --directory)"
new_vault="$(fs-temp --root="$temp_dir" --directory='new_vault')"
old_plain="$(fs-temp --root="$temp_dir" --directory='old_plain')"
new_plain="$(fs-temp --root="$temp_dir" --directory='new_plain')"
# ensure clean exit
if [[ $0 != "${BASH_SOURCE[0]}" ]]; then
echo-error '[gocryptfs-helper migrate] requires being run as a command, not a function, such that cleanup always occurs, even on failures.'
return 1 # EPERM 1 Operation not permitted
fi
function on_gocryptfs_finish {
mount-helper --unmount --target="$old_plain" || :
mount-helper --unmount --target="$new_plain" || :
fs-rm --quiet --no-confirm-if-empty -- "$temp_dir" || :
}
trap on_gocryptfs_finish EXIT
# create
__print_line
eval_capture --statusvar=verify_status -- act_verify "$new_vault"
if [[ $verify_status -eq 0 ]]; then
echo-style --notice="The new vault [$new_vault] already exists..." --newline \
'This means a vault upgrade was started but not finished.' --newline \
'We will continue with this vault, if you wish setup a new one, remove the old one first.'
elif is-missing -- "$new_vault" || is-empty-directory -- "$new_vault"; then
echo-style --bold="Creating a new vault vault at [$new_vault] with algorithm [$algorithm]."
gocryptfs --init --"$algorithm" "$new_vault"
act_chown "$new_vault"
else
{
echo-style \
--error="Something already existed at [$new_vault] which was not a known vault structure..." --newline \
--notice='Leaving for you to figure out.'
fs-structure -- "$new_vault"
} >/dev/stderr
return 1
fi
# gocryptfs --info "$new_vault"
# verify there is a difference
eval_capture --statusvar=compare_status -- act_compare "$old_vault" "$new_vault"
if [[ $compare_status -eq 0 ]]; then
echo-style --error='Vault migration is nonsensical, as both vaults have the same features.' >/dev/stderr
return 1
fi
# mount
act_mount "$old_vault" "$old_plain"
act_mount "$new_vault" "$new_plain"
# migrate
cpr --remove --tool=rsync -- \
"${old_plain}/" \
"${new_plain}/"
# replace
__print_lines '' 'Prepping replacement:'
fs-rm --no-confirm -- "$old_plain/"
fs-structure -- "$new_plain/"
mount-helper \
-- --unmount --target="$old_plain" \
-- --unmount --target="$new_plain"
fs-structure -- "$old_vault" "$new_vault"
# @todo style with var_dump or something
echo-style --bold='Confirm the following replacement:' --newline \
--bold+red='Delete:' ' ' --code="$old_vault" --newline \
--bold+yellow='Move:' ' ' --code="$new_vault" --bold=' => ' --code="$old_vault"
if ! confirm --bool --ppid=$$ -- 'Proceed with replacement?'; then
return 1
fi
fs-rm --no-confirm -- "$old_vault"
sudo-helper -- mv -v -- "$new_vault" "$old_vault"
# @todo style with var_dump or something
echo-style --bold='Replacement complete:' --newline \
--bold+red='Deleted:' ' ' --code="$old_vault" --newline \
--bold+yellow='Moved:' ' ' --code="$new_vault" --bold=' => ' --code="$old_vault"
# done
echo-style --success='Migration complete. β
'
}
# =====================================
# Act
if [[ "$(type -t "act_$action")" == 'function' ]]; then
"act_$action" "${option_args[@]}"
else
echo-style --stderr --error1="Action not yet implemented: " --code-error1="$action"
return 78 # ENOSYS 78 Function not implemented
fi
)
# fire if invoked standalone
if [[ $0 == "${BASH_SOURCE[0]}" ]]; then
gocryptfs_helper "$@"
fi