mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-11-25 14:17:41 +00:00
415 lines
9.7 KiB
Bash
Executable File
415 lines
9.7 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Tomb v3, the Crypto Undertaker portable version 3
|
|
#
|
|
# A commandline tool to easily operate encryption of secret data
|
|
#
|
|
# {{{ License
|
|
|
|
# Copyright (C) 2007-2022 Dyne.org Foundation
|
|
#
|
|
# Tomb is designed, written and maintained by Denis Roio <jaromil@dyne.org>
|
|
#
|
|
# Please refer to the AUTHORS file for more information.
|
|
#
|
|
# This source code is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This source code is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please refer
|
|
# to the GNU Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Public License along with
|
|
# this source code; if not, , see <https://www.gnu.org/licenses/>.
|
|
|
|
# }}} - License
|
|
|
|
# {{{ Global variables
|
|
|
|
VERSION="3.1.0"
|
|
DATE="Nov/2022"
|
|
TOMBEXEC="$0"
|
|
TMPDIR="${TMP:-/tmp}"
|
|
TOMBTMPFILES=""
|
|
PATH="${PATH}:.:/usr/local/bin"
|
|
exitcode=0
|
|
# }}}
|
|
|
|
# {{{ Logging functions
|
|
|
|
_success() {
|
|
echo "[*] " "$1" "$2" "$3" "$4" 1>&2
|
|
}
|
|
_message() {
|
|
echo " . " "$1" "$2" "$3" "$4" 1>&2
|
|
}
|
|
_warning() {
|
|
echo "[W] " "$1" "$2" "$3" "$4" 1>&2
|
|
}
|
|
_verbose() {
|
|
echo "[D] " "$1" "$2" "$3" "$4" 1>&2
|
|
}
|
|
_error() {
|
|
echo "[!] " "$1" "$2" "$3" "$4" 1>&2
|
|
exitcode=1
|
|
}
|
|
_failure() {
|
|
echo "[!!] " "$1" "$2" "$3" "$4" 1>&2
|
|
exitcode=1
|
|
exit 1
|
|
}
|
|
|
|
# }}}
|
|
|
|
_success "Starting Tomb v$VERSION"
|
|
|
|
# {{{ Internal functions
|
|
|
|
_random_string() {
|
|
len=${1:-32}
|
|
[ "$1" != "" ] && {
|
|
echo "print(O.random($len):base58())" | zenroom 2>/dev/null
|
|
}
|
|
return $?
|
|
}
|
|
|
|
_tmp_create() {
|
|
[ -d "$TMPDIR" ] || {
|
|
# we create the tempdir with the sticky bit on
|
|
mkdir -m 1777 "$TMPDIR"
|
|
[ $? = 0 ] || {
|
|
_failure "Fatal error creating the temporary directory: %s" "$TMPDIR"
|
|
}
|
|
}
|
|
tfile="${TMPDIR}/`_random_string 64`" # Temporary file
|
|
umask 066
|
|
[ $? = 0 ] || {
|
|
_failure "Fatal error setting the permission umask for temporary files"
|
|
}
|
|
[ -r "$tfile" ] && {
|
|
_failure "Someone is messing up with us trying to hijack temporary files."
|
|
}
|
|
touch "$tfile"
|
|
[ $? = 0 ] || {
|
|
_failure "Fatal error creating a temporary file: %s" "$tfile"
|
|
}
|
|
_verbose "Created tempfile: ::1 temp file::" "$tfile"
|
|
TOMBTMP="$tfile"
|
|
TOMBTMPFILES="$TOMBTMPFILES:$tfile"
|
|
return 0
|
|
}
|
|
|
|
# }}}
|
|
|
|
# {{{ FreeBSD
|
|
freebsd_mount() {
|
|
file="$1"
|
|
mnt="$2"
|
|
_verbose `${veracrypt} -l "$file"`
|
|
loop=`${veracrypt} -l "$file" | awk '{print $3}'`
|
|
_verbose "fsck $loop"
|
|
fsck.ext4 -p -C0 "$loop"
|
|
lklfuse -o type=ext4 "${loop}" "$mnt"
|
|
return $?
|
|
}
|
|
|
|
freebsd_close() {
|
|
file="$1"
|
|
md=`${veracrypt} -l "$file" | awk '{print $3}'`
|
|
# umount "$mnt"
|
|
_verbose "md: $md"
|
|
mnt=`pgrep -lf "lklfuse.*$md" | awk '{print $6}'`
|
|
_verbose "mnt: $mnt"
|
|
lkl=`pgrep -f "lklfuse.*$md" | awk '{print $1}'`
|
|
_verbose "kill $lkl (lklfuse on $md)"
|
|
# trying to deail with lklfuse bug
|
|
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=239831
|
|
renice -20 $lkl
|
|
kill $lkl
|
|
sync
|
|
sleep 1
|
|
kill -9 $lkl
|
|
# lkl should have really exited now
|
|
_verbose "${veracrypt} -d $file"
|
|
${veracrypt} --text --non-interactive -d "$file"
|
|
return $?
|
|
}
|
|
# }}}
|
|
|
|
# {{{ Linux
|
|
# usage: _mount /tmp/.veracrypt_ mountpoint
|
|
linux_mount() {
|
|
file="$1"
|
|
mnt="$2"
|
|
veralist=`${veracrypt} -l "$file" | awk '{print($2,":",$3,":",$4)}'`
|
|
[ "$veralist" = "" ] && {
|
|
_error "Cannot mount tomb not yet mapped " "$file"
|
|
return 1
|
|
}
|
|
loop=`echo $veralist | cut -d: -f2 | xargs`
|
|
[ "`echo $veralist | cut -d: -f3 | xargs`" != "-" ] && {
|
|
_error "Tomb already mounted " "$file on $loop"
|
|
return 1
|
|
}
|
|
_verbose "fsck $loop"
|
|
fsck.ext4 -p -C0 "$loop" 1>&2
|
|
_verbose "linux_mount $mnt"
|
|
mount "$loop" "$mnt"
|
|
return $?
|
|
}
|
|
# }}}
|
|
|
|
# {{{ POSIX portable
|
|
|
|
# usage: echo PASSWORD | posix_create file size pim
|
|
posix_create() {
|
|
file="$1" # must not exist
|
|
size="$2" # size in bytes
|
|
pim="$3" # any number
|
|
_verbose "posix_create $file $size $pim"
|
|
${veracrypt} --text --non-interactive --stdin \
|
|
-m nokernelcrypto \
|
|
-c "$file" --volume-type normal \
|
|
--hash sha512 --encryption serpent-aes \
|
|
--filesystem none --size "${size}" --pim "$pim" \
|
|
--random-source /dev/urandom -k ''
|
|
return $?
|
|
}
|
|
|
|
posix_format() {
|
|
file="$1"
|
|
loop=`${veracrypt} -l "$file" | awk '{print $3}'`
|
|
_verbose "posix_format: ${loop}"
|
|
mkfs.ext4 -L "`basename $file`" "$loop" # -E root_owner="${user_uid}:${user_gid}" "$loop"
|
|
return $?
|
|
}
|
|
|
|
# usage: echo PASSWORD | posix_map file pim
|
|
posix_map() {
|
|
file="$1"
|
|
pim="$2"
|
|
_verbose "posix_map $file $pim"
|
|
${veracrypt} --text --non-interactive --stdin \
|
|
--protect-hidden no -m nokernelcrypto \
|
|
-k '' --pim "$pim" --filesystem none \
|
|
"$file"
|
|
return $?
|
|
}
|
|
|
|
posix_close() {
|
|
file="$1"
|
|
_verbose "posix_close $file"
|
|
${veracrypt} --text --non-interactive -d "$file"
|
|
return $?
|
|
}
|
|
# }}}
|
|
|
|
# {{{ Initialization
|
|
|
|
system="unknown"
|
|
create=""
|
|
format=""
|
|
map=""
|
|
mount=""
|
|
close=""
|
|
veracrypt="veracrypt"
|
|
|
|
tomb_init() {
|
|
system="`uname -s`"
|
|
case "$system" in
|
|
FreeBSD)
|
|
cat <<EOF
|
|
create=posix_create
|
|
format=posix_format
|
|
map=posix_map
|
|
mount=freebsd_mount
|
|
close=freebsd_close
|
|
EOF
|
|
;;
|
|
Linux)
|
|
cat <<EOF
|
|
create=posix_create
|
|
format=posix_format
|
|
map=posix_map
|
|
mount=linux_mount
|
|
close=posix_close
|
|
EOF
|
|
;;
|
|
Darwin)
|
|
cat <<EOF
|
|
create=posix_create
|
|
format=posix_format
|
|
map=posix_map
|
|
mount=freebsd_mount
|
|
close=freebsd_close
|
|
veracrypt=/Applications/Veracrypt.app/Contents/MacOS/Veracrypt
|
|
EOF
|
|
;;
|
|
*)
|
|
_failure "Unsupported system: %s" "$system"
|
|
esac
|
|
echo "system=$system"
|
|
# _verbose "system detected: %s" $system
|
|
}
|
|
|
|
# }}}
|
|
|
|
|
|
# {{{ Main
|
|
[ "$1" = "source" ] && return 0
|
|
eval "`tomb_init`"
|
|
tombfile=""
|
|
tombsize=""
|
|
PIM=69
|
|
|
|
cmd="$1"
|
|
shift 1
|
|
|
|
case "$cmd" in
|
|
dig)
|
|
args=2
|
|
while [ $args -gt 0 ]; do
|
|
[ "$1" = '-s' ] && { tombsize="$2"; shift 2; }
|
|
[ "$1" != "" ] && { tombfile="$1"; shift 1; }
|
|
args=$(( $args - 1 ))
|
|
done
|
|
|
|
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
|
[ "$tombsize" = "" ] && _failure "Size argument missing, use -s"
|
|
# TODO: check if size is integer
|
|
# [ "$tombsize" -ge 10 ] || _failure "Tombs can't be smaller than 10 mebibytes"
|
|
[ -e "$tombfile" ] && {
|
|
_error "A tomb exists already. I'm not digging here:"
|
|
ls -l "$tombfile"; exit 1
|
|
}
|
|
_message "Commanded to dig tomb " "$tombfile" " sized $tombsize MiB"
|
|
touch "$tombfile" || _failure "Error creating the tomb " "$tombfile"
|
|
# dd if=/dev/urandom bs=1048576 count=$tombsize of="$tombfile" || {
|
|
# _failure "Error creating the tomb " "$tombfile"
|
|
# exit 1
|
|
# }
|
|
bytesize="$(( $tombsize * 1048576 ))"
|
|
[ "$bytesize" = "" ] &&
|
|
_failure "Error reading tomb size " "$tombsize"
|
|
if [ "$system" = "Linux" ]; then
|
|
fallocate -x -l "$bytesize" "$tombfile" ||
|
|
_failure "Error creating the tomb " "$tombfile"
|
|
else
|
|
dd if=/dev/zero of="$tombfile" count="$tombsize" bs=1048576 ||
|
|
_failure "Error creating the tomb " "$tombfile of $tombsize MiB"
|
|
fi
|
|
;;
|
|
|
|
forge)
|
|
args=1
|
|
[ "$1" = "" ] && _failure "Missing argument in command " "forge"
|
|
while [ $args -gt 0 ]; do
|
|
case "$1" in
|
|
'-k') tombkey="$2"; shift 2 ;;
|
|
*) tombkey="$1"; shift 1 ;;
|
|
esac
|
|
args=$(( $args - 1 ))
|
|
done
|
|
[ "$tombkey" = "" ] && _failure "Missing path to tomb key"
|
|
[ -e "$tombkey" ] && {
|
|
_error "A tomb key exists already. I'm not forging here:"
|
|
ls -l "$tombkey"; exit 1
|
|
}
|
|
_message "Commanded to forge tomb key " "$tombkey"
|
|
touch "$tombkey" || _failure "Error creating the tomb key " "$tombkey"
|
|
cat <<EOF | zenroom -z | cut -d\" -f4 > "$tombkey"
|
|
rule check version 2.0.0
|
|
Given nothing
|
|
When I create the random object of '64' bytes
|
|
Then print the 'random object' as 'hex'
|
|
EOF
|
|
;;
|
|
|
|
lock)
|
|
args=2
|
|
while [ $args -gt 0 ]; do
|
|
case "$1" in
|
|
'-k') tombkey="$2"; shift 2 ;;
|
|
*) tombfile="$1"; shift 1 ;;
|
|
esac
|
|
args=$(( $args - 1 ))
|
|
done
|
|
case "$system" in
|
|
Linux)
|
|
bytesize=`stat "$tombfile" | awk '/Size:/ {print $2; exit}'`
|
|
;;
|
|
*)
|
|
bytesize=`stat -f '%z' "$tombfile"`
|
|
;;
|
|
esac
|
|
_message "Commanded to lock tomb " "$tombfile with key $tombkey"
|
|
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
|
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
|
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
|
[ -r "$tombkey" ] || _failure "Key file not readable"
|
|
"$create" "$tombfile" "$bytesize" "$PIM" < "$tombkey" || {
|
|
_failure "Error creating the tomb " "$tombfile"
|
|
exit 1
|
|
}
|
|
"$map" "$tombfile" "$PIM" < "$tombkey" ||
|
|
_failure "Error mapping the tomb " "$tombfile with key $tombkey"
|
|
"$format" "$tombfile" ||
|
|
_error "Error formatting tomb " "$tombfile"
|
|
"$close" "$tombfile"
|
|
[ $exitcode = 0 ] &&
|
|
_success "Success locking tomb " "$tombfile with key $tombkey"
|
|
;;
|
|
|
|
open)
|
|
args=3
|
|
while [ $args -gt 0 ]; do
|
|
case "$1" in
|
|
'-k') tombkey="$2"; shift 2 ;;
|
|
*) if [ "$tombfile" = "" ]; then
|
|
tombfile="$1"
|
|
else
|
|
tombmount="$1"
|
|
fi
|
|
shift 1 ;;
|
|
esac
|
|
args=$(( $args - 1 ))
|
|
done
|
|
_message "Commanded to open tomb " "$tombfile with key $tombkey on $tombmount"
|
|
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
|
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
|
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
|
[ -r "$tombkey" ] || _failure "Key file not readable"
|
|
[ "$tombmount" = "" ] && tombmount="`basename $tombfile`"
|
|
"$map" "$tombfile" "$PIM" < "$tombkey"
|
|
[ $? != 0 ] &&
|
|
_failure "Error mapping the tomb " "$tombfile with key $tombkey"
|
|
"$mount" "$tombfile" "$tombmount" || {
|
|
"$close" "$tombfile"
|
|
_failure "Error mounting the tomb " "$tombfile on $tombmount"
|
|
}
|
|
;;
|
|
|
|
close)
|
|
# args=1
|
|
if [ "$1" = "all" ]; then
|
|
"$close"
|
|
elif [ -e "$1" ]; then
|
|
"$close" "`realpath $1`" ||
|
|
_failure "Error closing " "$1"
|
|
elif [ "$1" = "" ]; then
|
|
_failure "Missing argument: tomb file or mountpoint"
|
|
else
|
|
_failure "Wrong argument: $1"
|
|
fi
|
|
;;
|
|
list)
|
|
${veracrypt} -l
|
|
;;
|
|
esac
|
|
# }}}
|
|
|
|
exit 0
|