huge cleanup

tomb shell command doesn't depends from X,
 all GUI notifications are moved into tomb-open including USB key handling,
 gksu has been dropped completely as a method to gain privileges,
 there is a new -n flag to avoid processing hooks,
 variable names have been sanitized, duplicate code eliminated,
 documentation has been updated and the code cleaned up

we are very close to the 1.0 now
This commit is contained in:
Jaromil 2011-02-20 14:59:30 +01:00
parent fd8df548f4
commit b521e32110
4 changed files with 423 additions and 403 deletions

View File

@ -92,6 +92,10 @@ file adding a '.gpg' suffix, but can be later renamed and transported
on other media. When a key is not found, the program asks to insert a
USB storage device and it will look for the key file inside it.
.B
.IP "-n"
Skip processing of post-hooks and bind-hooks if found inside the tomb.
See the \fIHOOKS\fR section in this manual for more information.
.B
.IP "-h"
Display a help text and quit
.B

563
src/tomb
View File

@ -20,7 +20,7 @@
# this source code; if not, write to:
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
VERSION=0.9.2
VERSION=0.9.3
DATE=Feb/2011
# PATH=/usr/bin:/usr/sbin:/bin:/sbin
@ -48,114 +48,6 @@ else
WIPE=(rm -f)
fi
# usb auto detect using dmesg
# tested on ubuntu 10.04 - please test and patch on other systems if you can
# TODO: use udev rules, see how archlinux folks document it - arch rox 8)
# https://wiki.archlinux.org/index.php/System_Encryption_with_LUKS_for_dm-crypt
# here we could modularize the choice of methods using function pointers,
# so that they are configurable when calling tomb.
ask_usbkey() {
notice "Waiting 1 minute for a usb key to connect"
echo -n " . please insert your usb key "
exec_as_user notify-send -i monmort \
-u normal -h string:App:Tomb \
-h double:Version:${VERSION} \
-t 60 \
"Insert your USB KEY" \
"Tomb is waiting 1 minute for you to insert an external key."
plugged=false
c=0
while [ "$plugged" != "true" ]; do
dmesg | tail -n 12 | grep -q 'new.*USB device'
if [ $? = 0 ]; then plugged=true; fi
echo -n "."
sleep .5
c=`expr $c + 1`
if [ $c -gt 15 ]; then
echo
error "timeout."
export usbkey_mount=none
return 1;
fi
done
echo
echo -n " . usb key inserted, attaching "
c=0
attached=false
while [ "$attached" != "true" ]; do
dmesg | tail -n 12| grep -q 'Attached.*removable disk'
if [ $? = 0 ]; then attached=true; fi
echo -n "."
sleep 1
c=`expr $c + 1`
if [ $c -gt 15 ]; then
echo
error "timeout."
export usbkey_mount=none
return 1;
fi
done
echo
echo -n " . usb attached, opening "
# get the first partition
# usbpart=`dmesg |tail -n 12 | grep ' sd.:' |cut -d: -f2 |tr -d ' '`
for i in $(seq 1 10); do
usbpart=$(dmesg | tail -n 12 | sed '/ sd.:/!d;s/^.*: \(sd.[0-9]*\)/\1/')
if [ -n "$usbpart" ]; then
break
elif [ $i -eq 10 ]; then
error "timeout."
return 1
else
echo -n .
sleep 1
fi
done
# # wait that is mounted (it automount is on)
# c=0
# mounted=false
# while [ "$mounted" != "true" ]; do
# cat /proc/mounts | tail -n 2 | grep -q $usbpart
# if [ $? = 0 ]; then mounted=true; fi
# echo -n "."
# sleep .5
# c=`expr $c + 1`
# if [ $c -gt 30 ]; then
# echo
# error "timeout."
# export usbkey_mount=none
# return 1;
# fi
# done
# # check where it is mounted
# usbmount=`cat /proc/mounts | awk -v p=$usbpart '{ if( $1 == "/dev/" p) print $2 }'`
# sleep 1
# mount the first partition on the usb key
# mtmp=`tempfile -p tomb`
# rm -f $mtmp
# mkdir -p $mtmp
mtmp=$(/bin/mktemp -d --tmpdir tomb.XXXXXXXXXXXX)
mount /dev/$usbpart $mtmp
if [ $? = 0 ]; then
usbmount=$mtmp
else
error "cannot mount usbkey partition $usbmount"
return 1
fi
echo
act "usb key mounted on $usbmount"
export usbkey_mount=$usbmount
return 0
}
# we use pinentry now
# comes from gpg project and is much more secure
@ -166,7 +58,10 @@ ask_password() {
# so we need to temporary modify the gtk theme
if [ -r ~/.gtkrc-2.0 ]; then
cp ~/.gtkrc-2.0 ~/.gtkrc-2.0.tomb.bak
else
touch ~/.gtkrc-2.0
fi
cat <<EOF >> ~/.gtkrc-2.0
pixmap_path "/usr/local/share/pixmaps"
style "normal" { stock["gtk-dialog-authentication"] = {{"monmort.xpm"}} }
@ -174,8 +69,8 @@ ask_password() {
EOF
cat <<EOF | pinentry | awk '/^D/ { print $2 }'
SETTITLE Opening Tomb $1
SETDESC You need a password to use its key
SETTITLE Insert tomb password
SETDESC Open tomb: $1
SETPROMPT Password:
GETPIN
EOF
@ -184,33 +79,12 @@ EOF
if [ -r ~/.gtkrc-2.0.tomb.bak ]; then
cp ~/.gtkrc-2.0.tomb.bak ~/.gtkrc-2.0
rm ~/.gtkrc-2.0.tomb.bak
fi
}
# popup notification
tomb-notify() {
# look for our icon in common prefixes
if [ -r /usr/share/pixmaps/monmort.xpm ]; then icon=/usr/share/pixmaps/monmort.xpm
elif [ -r /usr/share/icons/monmort.xpm ]; then icon=/usr/share/icons/monmort.xpm
elif [ -r /usr/local/share/pixmaps/monmort.xpm ]; then icon=/usr/local/share/pixmaps/monmort.xpm
elif [ -r /usr/local/share/icons/monmort.xpm ]; then icon=/usr/local/share/icons/monmort.xpm
elif [ -r /opt/share/pixmaps/monmort.xpm ]; then icon=/opt/share/pixmaps/monmort.xpm
elif [ -r /sw/share/pixmaps/monmort.xpm ]; then icon=/sw/share/pixmaps/monmort.xpm
fi
if [ -z $1 ]; then
exec_as_user notify-send -i $icon \
-u low -h string:App:Tomb \
-h double:Version:${VERSION} \
"Tomb version $VERSION" \
"Hi, I'm the Undertaker.
Let's start setting your Crypt?"
else
exec_as_user notify-send -i $icon ${@}
rm -f ~/.gtkrc-2.0
fi
}
# drop privileges
exec_as_user() {
@ -235,77 +109,127 @@ exec_as_user() {
check_priv() {
id | grep root > /dev/null
if [ $? != 0 ]; then
which gksu > /dev/null
if [ $? = 0 ]; then
func "Using gksu for root execution of 'tomb ${(f)ARGS}'"
gksudo "tomb ${ARGS[@]}"
exit $?
fi
which sudo > /dev/null
if [ $? = 0 ]; then
func "Using sudo for root execution of 'tomb ${(f)ARGS}'"
if [ $? != 0 ]; then
error "Tomb requires sudo. please install it."
exit 1
fi
func "Using sudo for root execution of 'tomb ${(f)ARGS}'"
# check if sudo has a timestamp active
sudok=false
sudo -n tomb 2> /dev/null
if [ $? != 0 ]; then # if not then ask a password
cat <<EOF | pinentry | awk '/^D/ { print $2 }' | sudo -S -v
sudok=false
sudo -n tomb 2> /dev/null
if [ $? != 0 ]; then # if not then ask a password
cat <<EOF | pinentry | awk '/^D/ { print $2 }' | sudo -S -v
SETTITLE Super user privileges required
SETDESC Sudo execution of Tomb ${ARGS[@]}
SETPROMPT Insert your USER password:
GETPIN
EOF
fi
sudo "tomb" ${(s: :)ARGS}
exit $?
fi # have sudo
return 1
fi
sudo "tomb" ${(s: :)ARGS}
exit $?
fi # are we root already
return 0
}
get_arg_tomb() {
# set up variables to be used by caller:
# tombfile - filename without path
# tombdir - directory where the tomb is
# tombname - name of the tomb (filename without extension)
# the full path is made with $tombdir/$tombfile
if [ -z $1 ]; then
error "internal: get_arg_tomb called without argument"
return 1
fi
arg=${1}
if ! [ -r ${arg} ]; then
error "file not found: $arg"
return 1
fi
tombfile=`basename $arg`
tombdir=`dirname $arg`
file ${tombdir}/${tombfile} | grep -i 'luks encrypted file' 2>&1 >/dev/null
if [ $? != 0 ]; then
error "$arg is not a valid tomb file, operation aborted"
return 1
fi
tombname=${tombfile%%\.*}
act "tomb found: ${tombdir}/${tombfile}"
# now check if the key is kept beside or in args
# we use the extension .key
# the problem with .tomb.gpg is that decoding by hand using gpg it
# can override the tomb contents if the key is in the same
# directory than the tomb
if [ $KEY ]; then
tombkey=$KEY # commandline -k flag
act "tomb key specified manually: $tombkey"
elif [ -r ${tombdir}/${tombname}.key ]; then
tombkey=${tombdir}/${tombname}.key
act "key found for tomb '${tombname}': ${tombkey}"
else
error "key not found for tomb '${tombname}'"
return 1
fi
return 0
}
############################
### main()
###
echo $@ | grep '\-q' 2>&1 > /dev/null
if [ $? != 0 ]; then
notice "Tomb - simple commandline tool for encrypted storage"
act "version $VERSION ($DATE) by Jaromil @ dyne.org"
fi
echo $@ | grep '\-D' 2>&1 > /dev/null
if [ $? = 0 ]; then
echo "[D] invoked with args \"${(f)@}\" "
echo "[D] running on `date`"
fi
ARGS=$@[@]
OPTS=`getopt -o hvqDs:k: -n 'tomb' -- "$@"`
OPTS=`getopt -o hvqDs:k:n -n 'tomb' -- "$@"`
while true; do
case "$1" in
-h)
act ""
notice "Syntax: tomb [options] command [file] [mountpoint]"
act ""
notice "Commands:"
act "create create a new encrypted storage FILE and keys"
act "open open an existing tomb FILE on MOUNTPOINT"
act "close closes the tomb on MOUNTPOINT"
act "bury hide a tomb key inside a jpeg image"
act "exhume extract an hidden tomb key from a jpeg image"
cat <<EOF
Tomb $VERSION - a strong and gentle undertaker for your secrets
act ""
notice "Options:"
act "-s size of the storage file when creating one (MB)"
act "-k path to the key to use for decryption"
act ""
act "-h print this help"
act "-v version information for this tool"
act "-q run quietly without printing informations"
act "-D print debugging information at runtime"
echo; exit 2 ;;
Copyright (C) 2007-2011 Dyne.org Foundation, License GNU GPL v3+
This is free software: you are free to change and redistribute it
The latest Tomb sourcecode is published on <http://tomb.dyne.org>
Syntax: tomb [options] command [file] [place]
Commands:
create create a new tomb FILE and its keys
open open an existing tomb FILE on PLACE
close closes the tomb open on PLACE
bury hide a tomb key FILE inside a jpeg PLACE
exhume extract a tomb key FILE from a jpeg PLACE
Options:
-s size of the tomb file when creating one (in MB)
-k path to the key to use for opening a tomb
-n don't process the hooks found in tomb
-h print this help
-v version information for this tool
-q run quietly without printing informations
-D print debugging information at runtime
For more informations on Tomb read the manual: man tomb
Please report bugs on <http://bugs.dyne.org>.
EOF
exit 0 ;;
-v)
notice "Tomb - simple commandline tool for encrypted storage"
act "version $VERSION ($DATE) by Jaromil @ dyne.org"
# print out the GPL license in this file
act ""
cat $0 | awk '
@ -317,9 +241,13 @@ BEGIN { license=0 }
act ""
exit 0 ;;
-q) QUIET=1; shift 1 ;;
-D) DEBUG=1; shift 1 ;;
-D)
echo "[D] Tomb invoked with args \"${(f)@}\" "
echo "[D] running on `date`"
DEBUG=1; shift 1 ;;
-s) SIZE=$2; shift 2 ;;
-k) KEY=$2; shift 2 ;;
-b) NOBIND=1; shift 1 ;;
--) shift; break ;;
*) CMD=$1;
FILE=$2; MOUNT=$3; # compat with old args
@ -331,44 +259,52 @@ done
if ! [ $CMD ]; then
error "first argument missing, use -h for help"
tomb-notify
exit 0
fi
func "Tomb called: $CMD $CMD2 $CMD3"
func "Tomb command: $CMD $CMD2 $CMD3"
create_tomb() {
# make sure the file has a .tomb extension
FILE="${FILE%\.*}.tomb"
if ! [ ${CMD2} ]; then
error "no tomb name specified for creation"
return 1
fi
if [ -e "$FILE" ]; then
error "$FILE exists already. I'm not digging here."
tombfile=`basename ${CMD2}`
tombdir=`dirname ${CMD2}`
# make sure the file has a .tomb extension
tombname=${tombfile%%\.*}
tombfile=${tombname}.tomb
if [ -e ${tombdir}/${tombfile} ]; then
error "tomb exists already. I'm not digging here:"
ls -lh ${tombdir}/${tombfile}
return 1
fi
notice "Creating a new tomb"
notice "Creating a new tomb in ${tombdir}/${tombfile}"
if [ -z $SIZE ]; then
if [ $MOUNT ]; then
SIZE=$MOUNT
if [ $CMD3 ]; then
tombsize=${CMD3}
else
act "No size specified, summoning the Tomb Undertaker to guide us in the creation."
tomb-open &!
return 0
fi
else
tombsize=${SIZE}
fi
SIZE_4k=`expr $SIZE \* 1000 / 4`
act "Generating ${FILE} of ${SIZE}Mb (${SIZE_4k} blocks of 4Kb)"
$DD if=/dev/urandom bs=4k count=${SIZE_4k} of=${FILE}
tombsize_4k=`expr $tombsize \* 1000 / 4`
act "Generating ${tombfile} of ${tombsize}Mb (${tombsize_4k} blocks of 4Kb)"
$DD if=/dev/urandom bs=4k count=${tombsize_4k} of=${tombdir}/${tombfile}
if [ $? = 0 -a -e ${FILE} ]; then
act "OK: `ls -lh ${FILE}`"
if [ $? = 0 -a -e ${tombdir}/${tombfile} ]; then
act "OK: `ls -lh ${tombdir}/${tombfile}`"
else
error "Error creating the tomb ${FILE}, operation aborted."
error "Error creating the tomb ${tombdir}/${tombfile}, operation aborted."
exit 1
fi
@ -376,7 +312,7 @@ create_tomb() {
modprobe aes-i586
nstloop=`losetup -f` # get the number for next loopback device
losetup -f ${FILE} # allocates the next loopback for our file
losetup -f ${tombdir}/${tombfile} # allocates the next loopback for our file
# create the keyfile in tmpfs so that we leave less traces in RAM
keytmp=`tempfile -p tomb`
@ -404,15 +340,14 @@ create_tomb() {
exit 1
fi
notice "Setup your secret key file ${FILE}.gpg"
tomb-notify "The Tomb key is being forged:" "please set your password."
notice "Setup your secret key file ${tombname}.key"
# here user is prompted for key password
for c in 1 2 3; do
# 3 tries to write two times a matching password
tombpass=`exec_as_user tomb -q askpass ${FILE}`
tombpass=`exec_as_user tomb askpass ${tombname}`
tombpasstmp=$tombpass
tombpass=`exec_as_user tomb -q askpass "${FILE} (again)"`
tombpass=`exec_as_user tomb askpass "${tombname} (again)"`
if [ "$tombpasstmp" = "$tombpass" ]; then
break;
fi
@ -428,8 +363,9 @@ create_tomb() {
exit 1
fi
echo "${tombpass}" | gpg --batch --no-options --no-tty --passphrase-fd 0 \
-o "${FILE}.gpg" -c -a ${keytmp}/tomb.tmp
echo "${tombpass}" | gpg \
--openpgp --batch --no-options --no-tty --passphrase-fd 0 \
-o "${tombdir}/${tombname}.key" -c -a ${keytmp}/tomb.tmp
if [ $? = 2 ]; then
error "setting password failed: gnupg returns 2"
@ -460,12 +396,11 @@ create_tomb() {
act "formatting your Tomb with Ext4 filesystem"
mkfs.ext4 -q -F -j -L "${FILE%%.*}" /dev/mapper/tomb.tmp
mkfs.ext4 -q -F -j -L ${tombname} /dev/mapper/tomb.tmp
if [ $? = 0 ]; then
act "OK, encrypted storage succesfully formatted"
else
act "error formatting Tomb"
if [ $? != 0 ]; then
error "Tomb format returns error"
error "your tomb ${tombfile} maybe corrupt"
fi
sync
@ -473,101 +408,19 @@ create_tomb() {
cryptsetup luksClose tomb.tmp
losetup -d ${nstloop}
notice "done creating $FILE encrypted storage (using Luks dm-crypt AES/SHA256)"
tomb-notify "The Tomb is ready!" "We will now open your new Tomb for the first time."
notice "Your tomb is ready on ${FILE} and secured with key ${FILE}.gpg"
act "Would you like to save the key on an external usb device?"
act "This is recommended for safety:"
act "Always keep the key in a different place than the door!"
act "If you answer yes, you'll need a USB KEY now: (y/n)"
tomb-notify "Tomb has forged a key." "Would you like to save it on USB?"
echo -n " > "
read -q
if [ $? = 0 ]; then
ask_usbkey
if ! [ -e ${usbkey_mount} ]; then
error "cannot save the key in a separate place, move it yourself later."
else
mkdir -m 0700 -p ${usbkey_mount}/.tomb
cp -v ${FILE}.gpg ${usbkey_mount}/.tomb/
chmod -R go-rwx ${usbkey_mount}/.tomb
umount ${usbkey_mount}
unset usbkey_mount
notice "Key ${FILE}.gpg succesfully saved on your USB"
act "now we proceed opening your new tomb"
KEY=${FILE}.gpg
CMD2=${FILE}
CMD3=/media/${FILE}
mount_tomb ${FILE}
${WIPE[@]} ${FILE}.gpg
fi
else # kept besides (deprecated behaviour)
act "now we proceed opening your new tomb"
KEY=${FILE}.gpg
unset CMD2
unset CMD3
mount_tomb ${FILE}
fi
act "done creating $tombname encrypted storage (using Luks dm-crypt AES/SHA256)"
notice "Your tomb is ready in ${tombdir}/${tombfile} and secured with key ${tombname}.key"
}
mount_tomb() {
if ! [ $CMD2 ]; then
error "need an argument, operation aborted."
return 1
elif [ -r $CMD2 ]; then
tombfile=`basename $CMD2`
else
# try also adding a .tomb extension
tombfile=${tombfile%%\.*}.tomb
if ! [ -r $tombfile ]; then
error "cannot find a tomb named $CMD2"
return 1
fi
fi
tombdir=`dirname $CMD2`
file ${tombdir}/${tombfile} | grep -i 'luks encrypted.*cbc-essiv' 2>&1 >/dev/null
get_arg_tomb $CMD2
if [ $? != 0 ]; then
error "$CMD2 is not a valid tomb file, operation aborted"
tomb-notify "Not a tomb." "$CMD2 doesn't seems a real tomb."
error "operation aborted."
return 1
fi
tombname=${tombfile%%\.*}
act "mounting tomb named $tombname"
if [ $KEY ]; then
tombkey="`basename $KEY`"
tombkeypath="$KEY"
act "tomb key specified manually, using: $tombkeypath"
else
tombkey=${tombfile}.gpg
if [ -r $tombkey ]; then
tombkeypath=$tombkey
elif [ -r "$tombdir/$tombkey" ]; then
tombkeypath="$tombdir/$tombkey"
else
error "encryption key ${enc_key} not found on disk"
error "use -k option to specify which key to use"
error "provide a usb key now, or press ctrl-c to abort"
notice "please insert your USB KEY"
ask_usbkey
# returns usbkey_mount, now check if the key is there
if [ -r ${usbkey_mount}/.tomb/${tombkey} ]; then
tombkeypath=${usbkey_mount}/.tomb/${tombkey}
notice "key found on ${tombkeypath}"
else
error "key is missing, try to locate $tombkey in your files."
error "operation aborted"
return 1
fi
fi
fi
if ! [ $CMD3 ]; then
tombmount=/media/${tombfile}
act "mountpoint not specified, using default: $tombmount"
@ -610,19 +463,19 @@ mount_tomb() {
mapdate="`echo ${mapdate}/60 | bc -l | cut -d. -f1`"
mapper="tomb.${tombname}.${mapdate}.`basename $nstloop`"
notice "Password is required for key ${tombkey}"
keyname=`basename $tombkey | cut -d. -f1`
keyname=`basename $tombkey | cut -d. -f1`
notice "Password is required for key ${keyname}"
for c in 1 2 3; do
if [ $c = 1 ]; then
tombpass=`exec_as_user tomb -q askpass ${keyname}`
tombpass=`exec_as_user tomb askpass ${keyname}`
else
tombpass=`exec_as_user tomb -q askpass "$keyname (retry $c)"`
tombpass=`exec_as_user tomb askpass "$keyname (retry $c)"`
fi
echo "${tombpass}" \
| gpg --batch --passphrase-fd 0 --no-tty --no-options \
-d "${tombkeypath}" \
-d "${tombkey}" \
| cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
unset tombpass
@ -632,12 +485,6 @@ mount_tomb() {
fi
done
if [ -r ${usbkey_mount}/.tomb/${tombkey} ]; then
umount ${usbkey_mount}
rmdir ${usbkey_mount}
unset usbkey_mount
fi
if ! [ -r /dev/mapper/${mapper} ]; then
error "failure mounting the encrypted file"
@ -660,8 +507,10 @@ mount_tomb() {
notice "encrypted storage $tombfile succesfully mounted on $tombmount"
# exec_bind_hooks ${tombmount}
exec_safe_bind_hooks ${tombmount}
exec_post_hooks ${tombmount} open
if ! [ $NOBIND ]; then
exec_safe_bind_hooks ${tombmount}
exec_post_hooks ${tombmount} open
fi
return 0
}
@ -686,9 +535,9 @@ encode_key() {
# here user is prompted for key password
for c in 1 2 3; do
# 3 tries to write two times a matching password
tombpass=`exec_as_user tomb -q askpass ${FILE}`
tombpass=`exec_as_user tomb askpass ${tombkey}`
tombpasstmp=$tombpass
tombpass=`exec_as_user tomb -q askpass "${FILE} (again)"`
tombpass=`exec_as_user tomb askpass "${tombkey} (again)"`
if [ "$tombpasstmp" = "$tombpass" ]; then
break;
fi
@ -704,7 +553,6 @@ encode_key() {
awk '
/^-----/ {next}
/^Version/ {next}
/^Comment/ {next}
{print $0}' ${tombkey} \
| steghide embed --embedfile - --coverfile ${imagefile} \
-p ${tombpass} -z 9 -e serpent cbc
@ -732,27 +580,26 @@ decode_key() {
return 1
fi
tombfile=${tombname%%\.*}.tomb.gpg
notice "Decoding a key out of image $imagefile"
keyfile=${tombname%%\.*}.key
notice "Trying to exhume a key out of image $imagefile"
for c in 1 2 3; do
if [ $c = 1 ]; then
tombpass=`exec_as_user tomb -q askpass ${keyname}`
tombpass=`exec_as_user tomb askpass ${keyfile}`
else
tombpass=`exec_as_user tomb -q askpass "$keyname (retry $c)"`
tombpass=`exec_as_user tomb askpass "$keyfile (retry $c)"`
fi
steghide extract -sf ${imagefile} -p ${tombpass} -xf - \
| awk '
BEGIN {
print "-----BEGIN PGP MESSAGE-----"
print "Version: GnuPG v1.4.10 (GNU/Linux)"
}
{ print $0 }
END {
print "-----END PGP MESSAGE-----"
}' > ${tombfile}
}' > ${keyfile}
if [ "`cat ${tombfile} | wc -l`" != "3" ]; then
act "${tombfile} succesfully decoded"
if [ "`cat ${keyfile} | wc -l`" != "3" ]; then
act "${keyfile} succesfully decoded"
res=0
break;
fi
@ -780,7 +627,8 @@ exec_bind_hooks() {
{ if($1 && $2) print "mount -o bind \${mnt}/" $1 " " $2 "; " }
'`
# restore $HOME for the calling user
HOME=/home/${SUDO_USER}
ME=${SUDO_USER:-$(whoami)}
HOME=$(grep $ME /etc/passwd | sed "s/^${ME}:.*:.*:.*:.*:\([\/a-z]*\):.*$/\1/" 2>/dev/null)
act "bind hooks found, mounting directories as requested"
# execute the mount commands
@ -800,9 +648,9 @@ exec_safe_bind_hooks() {
error "cannot exec bind hooks without a mounted tomb."
return 1
fi
if [ ! -r "$MOUNTPOINT/bind-hooks" ]; then
func "cannot read bind-hooks."
return
if ! [ -r "$MOUNTPOINT/bind-hooks" ]; then
func "bind-hooks not found in $MOUNTPOINT"
return 1
fi
typeset -al created
typeset -al mounted
@ -820,7 +668,7 @@ exec_safe_bind_hooks() {
return 1
fi
if [ ! -d "$HOME/${maps[$dir]}" ]; then
notice "creating $HOME/${maps[$dir]}"
act "creating $HOME/${maps[$dir]}"
mkdir -p $HOME/${maps[$dir]}
created+=("$HOME/${maps[$dir]}")
fi
@ -844,38 +692,6 @@ exec_post_hooks() {
fi
}
get_arg_tomb() {
# set up variables to be used by caller:
# tombfile - filename without path
# tombdir - directory where the tomb is
# tombname - name of the tomb (filename without extension)
# the full path is made with $tombdir/$tombfile
if [ -z $1 ]; then
error "internal: get_arg_tomb called without argument"
return 1
fi
# make sure there is a .tomb extension
arg=${1%%\.*}.tomb
if ! [ -r ${arg} ]; then
error "file not found: $arg"
return 1
fi
tombfile=`basename $arg`
tombdir=`dirname $arg`
file ${tombdir}/${tombfile} | grep -i 'luks encrypted file' 2>&1 >/dev/null
if [ $? != 0 ]; then
error "$arg is not a valid tomb file, operation aborted"
tomb-notify "Not a tomb." "$arg doesn't seems a real tomb."
return 1
fi
tombname=${tombfile%%\.*}
return 0
}
backup_tomb() { # FIXME - duplicity asks passwords too often
# using duplicity
@ -913,10 +729,10 @@ backup_tomb() { # FIXME - duplicity asks passwords too often
act "ssh connection requires a password"
FTP_PASSWORD="`exec_as_user tomb askpass $bckurl`"
dupopts="--ssh-askpass"
# TODO verify ssh access before duplicity does
# since it blocks the thing retrying 5 times and such crap
# i.e. try ssh true to sshurl="`echo $bckurl | sed -e 's/ssh:\/\///'`"
# --no-print-statistics
# TODO verify ssh access before duplicity does
# since it blocks the thing retrying 5 times and such crap
# i.e. try ssh true to sshurl="`echo $bckurl | sed -e 's/ssh:\/\///'`"
# --no-print-statistics
fi
# duplicity works only on directories
@ -984,8 +800,8 @@ umount_tomb() {
if [ "$1" = "all" ]; then
tombs=`find /dev/mapper -name 'tomb.*'`
if ! [ $tombs ]; then
error "Tombs are all closed, cemetery is quiet."
return 1
notice "Tombs are all closed, cemetery is quiet."
return 0
fi
for t in ${(f)tombs}; do
umount_tomb ${t}
@ -1000,7 +816,6 @@ umount_tomb() {
else
error "tomb not found: $1"
error "please specify an existing /dev/mapper/tomb.*"
tomb-notify "Tomb was already closed." "Undertaker will rest in peace."
return 0
fi
@ -1021,15 +836,17 @@ umount_tomb() {
fi
# Execute post-hooks for eventual cleanup
exec_post_hooks ${tombmount} close
if ! [ $NOBIND ]; then
exec_post_hooks ${tombmount} close
fi
act "closing tomb $tombname on dm-crypt $basemap"
mount | grep $mapper 2>&1 >/dev/null
if [ $? = 0 ]; then # still mounted
umount ${mapper}
if ! [ $? = 0 ]; then
tomb-notify "Tomb '$tombname' is too busy." \
"Close all applications and file managers, then try again."
# TODO: ask user if wanting to SLAM the tomb closed
# then kill all processes found using it with fuser and lsof
return 1
fi
fi
@ -1042,8 +859,7 @@ umount_tomb() {
losetup -d "/dev/`echo $basemap | cut -d. -f4`"
notice "crypt storage ${mapper} unmounted"
tomb-notify "Tomb closed: $tombname" "Your bones will Rest In Peace."
notice "Tomb $tombname closed: your bones will rest in peace."
return 0
}
@ -1053,7 +869,7 @@ umount_tomb() {
install_tomb() {
# TODO: distro package deps (for binary)
# debian: zsh, cryptsetup, libgtk2.0-0, libnotify-bin
# debian: zsh, cryptsetup, sudo
act "updating mimetypes..."
cat <<EOF > /tmp/dyne-tomb.xml
<?xml version="1.0"?>
@ -1064,7 +880,7 @@ install_tomb() {
</mime-type>
<mime-type type="application/x-tomb-key">
<comment>Tomb crypto key</comment>
<glob pattern="*.tomb.gpg"/>
<glob pattern="*.key"/>
</mime-type>
</mime-info>
EOF
@ -1115,7 +931,7 @@ application/x-tomb-volume
ext: tomb
application/x-tomb-key
ext: tomb.gpg
ext: key
EOF
cat <<EOF > /usr/lib/mime/packages/tomb
application/x-tomb-volume; tomb-open '%s'; priority=8
@ -1155,9 +971,8 @@ case "$CMD" in
install) check_priv ; install_tomb ;;
askpass) ask_password $CMD2 $CMD3 ;;
askpass) ask_password $CMD2 ;;
status) tomb-status ;;
notify) tomb-notify $CMD2 $CMD3 ;;
*) error "command \"$CMD\" not recognized"
act "try -h for help"

View File

@ -31,35 +31,188 @@ try() {
else return -1; fi
}
tombdir=`dirname $1`
tombfile=`basename $1`
tombname=${tombfile%%\.*}
# popup notification
tomb-notify() {
which notify-send > /dev/null
if [ $? != 0 ]; then return 1; fi
# look for our icon in common prefixes
if [ -r /usr/share/pixmaps/monmort.xpm ]; then icon=/usr/share/pixmaps/monmort.xpm
elif [ -r /usr/share/icons/monmort.xpm ]; then icon=/usr/share/icons/monmort.xpm
elif [ -r /usr/local/share/pixmaps/monmort.xpm ]; then icon=/usr/local/share/pixmaps/monmort.xpm
elif [ -r /usr/local/share/icons/monmort.xpm ]; then icon=/usr/local/share/icons/monmort.xpm
elif [ -r /opt/share/pixmaps/monmort.xpm ]; then icon=/opt/share/pixmaps/monmort.xpm
elif [ -r /sw/share/pixmaps/monmort.xpm ]; then icon=/sw/share/pixmaps/monmort.xpm
fi
if [ -z $1 ]; then
notify-send -i $icon \
-u low -h string:App:Tomb \
-h double:Version:${VERSION} \
"Tomb version $VERSION" \
"Hi, I'm the Undertaker.
Let's start setting your Crypt?"
else
notify-send -i $icon ${@}
fi
}
# USB plug auto detect using dmesg
# tested on ubuntu 10.04 and debian 6.0
# please test and patch on other systems if you can.
# TODO: use udev rules, see how archlinux folks document it:
# https://wiki.archlinux.org/index.php/System_Encryption_with_LUKS_for_dm-crypt
# here we could modularize the choice of methods using function pointers,
# so that they are configurable when calling tomb.
ask_usbkey() {
unset usbkey_mount
echo "Waiting 1 minute for a usb key to connect"
echo -n " . please insert your usb key "
tomb-notify "Insert your USB KEY" \
"Tomb is waiting 30 seconds for you to insert an external key."
plugged=false
c=0
while [ "$plugged" != "true" ]; do
dmesg | tail -n 12 | grep -q 'new.*USB device'
if [ $? = 0 ]; then plugged=true; fi
echo -n "."
sleep .5
c=`expr $c + 1`
if [ $c -gt 60 ]; then
echo
echo "[!] timeout."
return 1;
fi
done
echo
echo -n " . usb key inserted, attaching "
c=0
attached=false
while [ "$attached" != "true" ]; do
dmesg | tail -n 12| grep -q 'Attached.*removable disk'
if [ $? = 0 ]; then attached=true; fi
echo -n "."
sleep .5
c=`expr $c + 1`
if [ $c -gt 30 ]; then
echo
echo "[!] timeout."
export usbkey_mount=none
return 1;
fi
done
echo
echo -n " . usb attached, opening "
# get the first partition
# usbpart=`dmesg |tail -n 12 | grep ' sd.:' |cut -d: -f2 |tr -d ' '`
for i in $(seq 1 10); do
usbpart=$(dmesg | tail -n 12 | sed '/ sd.:/!d;s/^.*: \(sd.[0-9]*\)/\1/')
if [ -n "$usbpart" ]; then
break
elif [ $i -eq 10 ]; then
echo "[!] timeout."
return 1
else
echo -n .
sleep 1
fi
done
mtmp=$(/bin/mktemp -d --tmpdir tomb.XXXXXXXXXXXX)
sudo mount /dev/$usbpart $mtmp
if [ $? = 0 ]; then
usbmount=$mtmp
else
echo "[!] cannot mount usbkey partition $usbmount"
return 1
fi
echo
echo " . usb key mounted on $usbmount"
usbkey_mount=$usbmount
return 0
}
launch_status() {
# calculates the correct arguments to launch tomb-status tray
# applet; it takes the tomb name as an argument and should be
# launched after a successful tomb mount.
if ! [ $1 ]; then
echo "[!] cannot launch status tray applet: we don't even know the name of our tomb."
exit 1
fi
tombname=${1}
tombmap=`mount -l | awk "/\[${tombname}\]$/"' { print $1 } '`
tombmount=`mount -l | awk "/\[${tombname}\]$/"' { print $3 } '`
tomb-status $tombmap $tombname $tombmount &!
}
# got an argument
if [ $1 ]; then # is it a file?
tombdir=`dirname $1`
tombfile=`basename $1`
tombname=${tombfile%%\.*}
if [ -f ${tombdir}/${tombfile} ]; then
# is it a luks partition
file ${tombdir}/${tombfile} | grep LUKS
file ${tombdir}/${tombfile} | grep -i LUKS > /dev/null
if [ $? = 0 ]; then # tomb is a valid LUKS file
if [ -r ${tombdir}/${tombname}.key ]; then
tombkey=${tombdir}/${tombname}.key
else
ask_usbkey
if ! [ $usbkey_mount ]; then # no usb key was mounted
echo "key not provided for tomb: $tombname"
echo "operation aborted." # TODO: dialog with pinentry
exit 1
else # usb mounted, check key presence
if [ -r ${usbkey_mount}/.tomb/${tombname}.key ]; then
tombkey=${usbkey_mount}/.tomb/${tombname}.key
elif [ -r ${usbkey_mount}/.tomb ]; then
echo "we can't find the right key, have a look yourself:"
ls -lha ${usbkey_mount}/.tomb
exit 1
else
echo "there are no keys stored in your usb"
exit 1
fi
fi
fi
if ! [ ${tombkey} ]; then # just to be sure
echo "key not found, operation aborted."
exit 1
else
tomb -k ${tombkey} mount ${tombdir}/${tombfile}
success=$?
fi
tomb mount ${tombdir}/${tombfile}
if [ $usbkey_mount ]; then
sudo umount ${usbkey_mount}
rmdir ${usbkey_mount}
unset usbkey_mount
fi
if [ $? = 0 ]; then # mount was succesfull (with password and all)
# strip extension if there
tombmap=`mount -l | awk "/\[${tombname}\]$/"' { print $1 } '`
tombmount=`mount -l | awk "/\[${tombname}\]$/"' { print $3 } '`
echo "tomb-status $tombmap $tombname $tombmount"
tomb-status $tombmap $tombname $tombmount &!
if [ $success = 0 ]; then # mount was succesfull (with password and all)
launch_status ${tombname}
exit 0
else
tomb notify "Tomb cannot open." "Are you knocking the wrong door?"
tomb-notify "Tomb cannot open." "Are you knocking the wrong door?"
exit 1
fi
else
tomb notify "Not a real Tomb." "We found no real bones in there."
tomb-notify "Not a real Tomb." "We found no real bones in there."
exit 1
fi
@ -74,7 +227,7 @@ if [ $1 ]; then # is it a file?
try rox; if [ $? = 0 ]; then rox ${1}; exit 0; fi
try fsviewer; if [ $? = 0 ]; then fsviewer ${1}; exit 0; fi
# try xnc; if [ $? = 0 ]; then xnc ${1}; exit 0; fi
tomb notify "File manager not found." "Tomb cannot guess which filemanager you are using"
tomb-notify "File manager not found." "Tomb cannot guess which filemanager you are using"
exit 1
fi
fi
@ -88,7 +241,13 @@ if [ -z $DISPLAY ]; then
fi
# no arguments: start guided tomb creation
tomb notify
tomb-notify
# we do it on the desktop by default
if [ -r $HOME/Desktop ]; then
cd $HOME/Desktop;
# or inside HOME
else cd $HOME; fi
cat <<EOF
Create a new Tomb
=================
@ -115,13 +274,14 @@ fi
# let's proceed
echo " Please type in the name for your new tomb file:"
echo -n "> "
read filename
read tombname
echo " How big you want the Tomb to be?"
echo " Type a size number in Megabytes:"
echo -n "> "
read size
read tombsize
clear
echo " You have commanded the creation of this Tomb:"
echo " $filename ( $size MBytes )";
echo " $tombname ( $tombsize MBytes )";
echo
cat <<EOF
Please confirm if you want to proceed now:
@ -146,22 +306,60 @@ cat <<EOF
password:
EOF
tomb create ${filename}.tomb $size
tombfile=${tombname}.tomb
tomb -s $tombsize create ${tombfile}
if [ $? != 0 ]; then
echo "An error occurred creating tomb, operation aborted."
exit 1
else
tombname="${filename%%.*}"
tombmap=`mount -l | awk "/\[${tombname}\]$/"' { print $1 } '`
tombmount=`mount -l | awk "/\[${tombname}\]$/"' { print $3 } '`
tomb-status $tombmap $tombname $tombmount &!
fi
tomb-notify "The Tomb is ready!" "We will now open your new Tomb for the first time."
cat <<EOF
Would you like to save the key on an external usb device?"
This is recommended for safety:"
Always keep the key in a different place than the door!"
If you answer yes, you'll need a USB KEY now: (y/n)"
EOF
# tomb-notify "Tomb has forged a key." "Would you like to save it on USB?"
echo -n " > "
read -q
if [ $? = 0 ]; then
ask_usbkey
if [ ${usbkey_mount} ]; then
# if ! [ -r /usr/share/applications/tomb.desktop ]; then
# echo " Well done!"
# echo " Now the last thing to do is to install Tomb on your desktop:"
# sudo tomb install
# fi
sudo mkdir -m 0700 -p ${usbkey_mount}/.tomb
sudo cp -v ${tombname}.key ${usbkey_mount}/.tomb/
sudo chmod -R go-rwx ${usbkey_mount}/.tomb
echo "${tombname}.key succesfully saved on your USB"
echo "now we'll proceed opening your brand new tomb"
tomb -k ${tombname}.key open ${tombfile}
if [ $? = 0 ]; then
launch_status ${tombname}
fi
rm -f ${tombname}.key
sudo umount ${usbkey_mount}
rmdir ${usbkey_mount}
unset usbkey_mount
exit 0
fi
fi
cat <<EOF
Impossible to save the key on USB.
We recommend to preserve the key in a separate place!
You can move it yourself later, place it in a hidden directory
named .tomb inside the first partition of an usb key.
EOF
tomb -k ${tombname}.key open ${tombfile}
if [ $? = 0 ]; then
launch_status ${tombname}
fi
exit 0

View File

@ -215,6 +215,9 @@ gboolean cb_close(GtkWidget *w, GdkEvent *e) {
notify_uninit();
exit(0);
}
/* tomb-notify "Tomb '$tombname' is too busy." \
"Close all applications and file managers, then try again."
*/
return TRUE;
}