correct locking of open/close operations

in coordination with tray status presence
and lots more cleanups and testing
This commit is contained in:
Jaromil 2011-02-03 20:42:46 +01:00
parent 465e2f63e5
commit c0bd02a8c0
4 changed files with 164 additions and 150 deletions

2
.gitignore vendored
View File

@ -27,4 +27,4 @@ stamp-h1
tags tags
doc/web/public doc/web/public
doc/web/dyne doc/web/dyne
debian

299
src/tomb
View File

@ -131,15 +131,15 @@ ask_usbkey() {
# user interface (just to ask the password) # user interface (just to ask the password)
ask_password() { ask_password() {
exec_as_user xhost # 2&>1 >/dev/null exec_as_user xhost 2>&1 >/dev/null
if [ $? = 0 ]; then # we have access to the X display if [ $? = 0 ]; then # we have access to the X display
exec_as_user which tomb-askpass # 2&>1 > /dev/null exec_as_user which tomb-askpass # 2>&1 > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
export scolopendro="`exec_as_user tomb-askpass ${1} 2>/dev/null`" export scolopendro="`exec_as_user tomb-askpass ${1} 2>/dev/null`"
return return
fi fi
exec_as_user which ssh-askpass # 2&>1 > /dev/null exec_as_user which ssh-askpass # 2>&1 > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
export scolopendro="`exec_as_user ssh-askpass "Tomb: provide the password to unlock"`" export scolopendro="`exec_as_user ssh-askpass "Tomb: provide the password to unlock"`"
return return
@ -193,17 +193,20 @@ exec_as_user() {
fi fi
func "executing as user '$SUDO_USER': ${(f)@}" func "executing as user '$SUDO_USER': ${(f)@}"
which gksu > /dev/null # which gksu > /dev/null
if [ $? = 0 ]; then # if [ $? = 0 ]; then
func "Using gksu for execution of '${(f)@}' as user $SUDO_USER" # func "Using gksu for execution of '${(f)@}' as user $SUDO_USER"
gksu -u $SUDO_USER "${@[@]}" # gksu -u $SUDO_USER "${@[@]}"
return $? # return $?
fi # fi
which sudo > /dev/null which sudo > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
func "Using sudo for execution of '${(f)@}' as user $SUDO_USER" func "Using sudo for execution of '${(f)@}' as user $SUDO_USER"
sudo -u $SUDO_USER "${@[@]}" sudo -u $SUDO_USER "${@[@]}"
return $? return $?
else
error "Tomb requires sudo. please install it."
return 1
fi fi
} }
@ -215,17 +218,18 @@ check_priv() {
which gksu > /dev/null which gksu > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
func "Using gksu for root execution of 'tomb ${(f)ARGS}'" func "Using gksu for root execution of 'tomb ${(f)ARGS}'"
gksu "tomb ${ARGS[@]}" gksu "tomb -q ${ARGS[@]}"
exit $? exit 0
fi fi
which sudo > /dev/null which sudo > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
func "Using sudo for root execution of 'tomb ${(f)ARGS}'" func "Using sudo for root execution of 'tomb ${(f)ARGS}'"
sudo "tomb ${ARGS[@]}" sudo "tomb -q ${ARGS[@]}"
exit $? exit 0
fi fi
exit 1 return 1
fi fi
return 0
} }
@ -233,13 +237,16 @@ check_priv() {
### main() ### main()
### ###
notice "Tomb - simple commandline tool for encrypted storage" echo $@ | grep '\-q' 2>&1 > /dev/null
act "version $VERSION ($DATE) by Jaromil @ dyne.org" if [ $? != 0 ]; then
notice "Tomb - simple commandline tool for encrypted storage"
act "version $VERSION ($DATE) by Jaromil @ dyne.org"
fi
func "invoked with args \"${(f)@}\" " func "invoked with args \"${(f)@}\" "
func "running on `date`" func "running on `date`"
ARGS=$@[@] ARGS=$@[@]
OPTS=`getopt -o hvDs:k: -n 'tomb' -- "$@"` OPTS=`getopt -o hvqDs:k: -n 'tomb' -- "$@"`
while true; do while true; do
case "$1" in case "$1" in
-h) -h)
@ -270,6 +277,7 @@ BEGIN { license=0 }
' '
act "" act ""
exit 0 ;; exit 0 ;;
-q) shift 1 ;;
-D) DEBUG=1; shift 1 ;; -D) DEBUG=1; shift 1 ;;
-s) SIZE=$2; shift 2 ;; -s) SIZE=$2; shift 2 ;;
-k) KEY=$2; shift 2 ;; -k) KEY=$2; shift 2 ;;
@ -282,7 +290,7 @@ done
if [ -z $CMD ]; then if ! [ $CMD ]; then
error "first argument missing, use -h for help" error "first argument missing, use -h for help"
tomb-notify tomb-notify
exit 0 exit 0
@ -290,17 +298,8 @@ fi
func "command: $CMD for file $FILE" func "Tomb called: $CMD $CMD2 $CMD3"
tombdir=${HOME}/.tomb
tombtab=${tombdir}/fstab
if ! [ -r ${tombtab} ]; then
act "creating tomb filesystem tab in your home"
mkdir -m 0700 -p ${HOME}/.tomb
echo "# entombed filesystem information, see man tomb (TODO)" > ${tombtab}
echo "# format here is similar to the system wide fstab" >> ${tombtab}
echo "# <file system> <mount point> <type> <options> <key>" >> ${tombtab}
fi
create_tomb() { create_tomb() {
@ -309,7 +308,7 @@ create_tomb() {
if [ -e "$FILE" ]; then if [ -e "$FILE" ]; then
error "$FILE exists already. I'm not digging here." error "$FILE exists already. I'm not digging here."
exit 1 return 1
fi fi
notice "Creating a new tomb" notice "Creating a new tomb"
@ -318,9 +317,8 @@ create_tomb() {
SIZE=$MOUNT SIZE=$MOUNT
else else
act "No size specified, summoning the Tomb Undertaker to guide us in the creation." act "No size specified, summoning the Tomb Undertaker to guide us in the creation."
tomb-open & tomb-open &!
disown return 0
exit 0
fi fi
fi fi
@ -463,62 +461,84 @@ create_tomb() {
mount_tomb() { mount_tomb() {
if ! [ -r $FILE ]; then if ! [ $CMD2 ]; then
# try also adding a .tomb extension error "need an argument, operation aborted."
FILEtomb="${FILE%\.*}.tomb" return 1
if ! [ -r $FILEtomb ]; then elif [ -r $CMD2 ]; then
error "cannot find a tomb named $FILE" tombfile=$CMD2
exit 1
else
FILE=$FILEtomb
fi
fi
if ! [ $KEY ]; then
enc_key="`basename ${FILE}.gpg`"
else else
enc_key="$KEY" # try also adding a .tomb extension
fi tombfile="${CMD2%\.*}.tomb"
if ! [ -r $tombfile ]; then
error "cannot find a tomb named $CMD"
notice "mounting $FILE on mountpoint $MOUNT" return 1
if [ -z $MOUNT ]; then
MOUNT=/media/`basename ${FILE}`
act "mountpoint not specified, using default: $MOUNT"
mkdir -p $MOUNT
elif ! [ -x $MOUNT ]; then
error "mountpoint $MOUNT doesn't exist"
exit 1
fi
# check if key file is present
if ! [ -r "${enc_key}" ]; then
error "encryption key ${enc_key} not found on disk"
error "use -k option to specify which key to use"
error "or provide a usb key, or press ctrl-c to abort"
ask_usbkey
# returns usbkey_mount, now check if the key is there
if [ -r ${usbkey_mount}/.tomb/${enc_key} ]; then
enc_key=${usbkey_mount}/.tomb/${enc_key}
notice "key found on ${enc_key}"
else
error "key is missing."
exit 1
fi fi
fi fi
file $tombfile | grep -i 'luks encrypted.*cbc-essiv' 2>&1 >/dev/null
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."
return 1
fi
tombdir=`dirname $tombfile`
tombname=`echo $tombfile | cut -d. -f1`
if [ $KEY ]; then
# key manually chosen from commandline with -k
tombkey="`basename $KEY`"
tombkeypath="$KEY"
else
tombkey="`basename ${tombfile}.gpg`"
if [ -r $tombkey ]; then
tombkeypath=$tombkey
elif [ -r "$tombdir/$tombkey" ]; then
tombkeypath="$tombdir/$tombkey"
else
notice "please insert your USB KEY"
error "encryption key ${enc_key} not found on disk"
error "use -k option to specify which key to use"
error "or provide a usb key, or press ctrl-c to abort"
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/`basename ${tombfile}`
act "mountpoint not specified, using default: $tombmount"
elif ! [ -x $CMD3 ]; then
error "mountpoint $CMD2 doesn't exist, operation aborted."
return 1
else
tombmount=$CMD3
fi
notice "mounting $tombfile on mountpoint $tombmount"
# we need root from here on
mkdir -p $tombmount
nstloop=`losetup -f` nstloop=`losetup -f`
losetup -f ${FILE} losetup -f ${tombfile}
act "check for a valid LUKS encrypted device" act "check for a valid LUKS encrypted device"
cryptsetup isLuks ${nstloop} cryptsetup isLuks ${nstloop}
if [ $? != 0 ]; then if [ $? != 0 ]; then
# is it a LUKS encrypted nest? see cryptsetup(1) # is it a LUKS encrypted nest? see cryptsetup(1)
error "$FILE is not a valid Luks encrypted storage file" error "$tombfile is not a valid Luks encrypted storage file"
exit 1 return 1
fi fi
modprobe dm-crypt modprobe dm-crypt
modprobe aes-i586 modprobe aes-i586
@ -526,10 +546,10 @@ mount_tomb() {
mapdate="`date +%s`" mapdate="`date +%s`"
mapdate="`echo ${mapdate}/60 | bc -l | cut -d. -f1`" mapdate="`echo ${mapdate}/60 | bc -l | cut -d. -f1`"
mapper="tomb.`basename $FILE | cut -d. -f1`.$mapdate.`basename $nstloop`" mapper="tomb.`basename $tombfile | cut -d. -f1`.$mapdate.`basename $nstloop`"
notice "Password is required for key ${enc_key}" notice "Password is required for key ${tombkey}"
keyname=`basename $enc_key | cut -d. -f1` keyname=`basename $tombkey | cut -d. -f1`
for c in 1 2 3; do for c in 1 2 3; do
if [ $c = 1 ]; then if [ $c = 1 ]; then
@ -539,7 +559,7 @@ mount_tomb() {
fi fi
echo "${scolopendro}" \ echo "${scolopendro}" \
| gpg --batch --passphrase-fd 0 --no-tty --no-options \ | gpg --batch --passphrase-fd 0 --no-tty --no-options \
-d "${enc_key}" 2>/dev/null \ -d "${tombkeypath}" 2>/dev/null \
| cryptsetup --key-file - luksOpen ${nstloop} ${mapper} | cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
unset scolopendro unset scolopendro
@ -553,109 +573,95 @@ mount_tomb() {
if ! [ -r /dev/mapper/${mapper} ]; then if ! [ -r /dev/mapper/${mapper} ]; then
error "failure mounting the encrypted file" error "failure mounting the encrypted file"
losetup -d ${nstloop} losetup -d ${nstloop}
exit 1 return 1
fi fi
act "encrypted storage filesystem check" act "encrypted storage filesystem check"
fsck -p -C0 /dev/mapper/${mapper} fsck -p -C0 /dev/mapper/${mapper}
mount -o rw,noatime,nodev /dev/mapper/${mapper} ${MOUNT} mount -o rw,noatime,nodev /dev/mapper/${mapper} ${tombmount}
# Ensure the user can write the disk - 10x Hellekin :) # Ensure the user can write the disk - 10x Hellekin :)
ME=${SUDO_USER:-$(whoami)} ME=${SUDO_USER:-$(whoami)}
chmod 0750 ${MOUNT} chmod 0750 ${tombmount}
chown $(id -u $ME):$(id -g $ME) ${MOUNT} chown $(id -u $ME):$(id -g $ME) ${tombmount}
notice "encrypted storage $FILE succesfully mounted on $MOUNT" notice "encrypted storage $tombfile succesfully mounted on $tombmount"
( exec_as_user tomb-status ${mapper} ${FILE} ${MOUNT} ) & exec_as_user tomb-status ${mapper} ${tombfile} ${tombmount} &!
disown return 0
exit 0
} }
umount_tomb() { umount_tomb() {
if [ -z $FILE ]; then if ! [ $1 ]; then
how_many_tombs=`ls /dev/mapper/tomb.* 2> /dev/null | wc -w` how_many_tombs="`find /dev/mapper -name 'tomb.*' | wc -w`"
if [ $how_many_tombs = 0 ]; then if [ "$how_many_tombs" = "0" ]; then
error "there is no open tomb to be closed" error "there is no open tomb to be closed"
exit 0 return 1
elif [ $how_many_tombs = 1 ]; then elif [ "$how_many_tombs" = "1" ]; then
mapper=`ls /dev/mapper/tomb.* 2>/dev/null` mapper=`find /dev/mapper -name 'tomb.*'`
FILE=`mount | grep $mapper | awk '{print $3}'` tombfile=`mount | grep $mapper | awk '{print $3}'`
else else
error "too many tombs mounted, please specify which to unmount:" error "too many tombs mounted, please specify which to unmount:"
ls /dev/mapper/tomb.* ls /dev/mapper/tomb.*
exit 1 error "or issue the command 'tomb close all' to clos'em all."
return 1
fi fi
fi fi
if [ -r $FILE ]; then # accepts relative and absolute path if [ "$1" = "all" ]; then
mapper=$FILE tombs=`find /dev/mapper -name 'tomb.*'`
elif [ -r /dev/mapper/${FILE} ]; then if ! [ $tombs ]; then
mapper=/dev/mapper/${FILE} error "Tombs are all closed, cemetery is quiet."
return 1
fi
for t in ${(f)tombs}; do
umount_tomb ${t}
done
return 0
fi fi
if ! [ -r $mapper ]; then if [ -r "$1" ]; then # accepts relative and absolute path
error "tomb not found: $mapper" mapper="$1"
elif [ -r /dev/mapper/${1} ]; then
mapper=/dev/mapper/${1}
else
error "tomb not found: $1"
error "please specify an existing /dev/mapper/tomb.*" error "please specify an existing /dev/mapper/tomb.*"
ls /dev/mapper/tomb.*
tomb-notify "My tomb vanished" "Crypto undertaker will rest in peace." tomb-notify "My tomb vanished" "Crypto undertaker will rest in peace."
killall -e ${mapper} return 0
exit 1
fi fi
# if [ "$mapper" = "" ]; then
# error "$FILE is not mounted"
# return
# fi
# mapper=`basename $mapper`
# if ! [ -r /dev/mapper/${mapper} ]; then
# error "tomb doesn't seems to be mounted:"
# error "${mapper} is not present in /dev/mapper"
# exit 1
# fi
basemap=`basename $mapper` basemap=`basename $mapper`
tombname=`echo ${basemap} | cut -d. -f2` tombname=`echo ${basemap} | cut -d. -f2`
act "closing tomb $tombname on dm-crypt $basemap" act "closing tomb $tombname on dm-crypt $basemap"
mount | grep $mapper 2&>1 > /dev/null mount | grep $mapper 2>&1 >/dev/null
if [ $? = 0 ]; then # still mounted if [ $? = 0 ]; then # still mounted
errno=`umount ${mapper}` errno=`umount ${mapper}`
if ! [ $? = 0 ]; then if ! [ $? = 0 ]; then
tomb-notify "Tomb '$tombname' is too busy." \ tomb-notify "Tomb '$tombname' is too busy." \
"Close all applications and file managers, then try again." "Close all applications and file managers, then try again."
exit 1 return 1
fi fi
fi fi
cryptsetup luksClose $basemap cryptsetup luksClose $basemap
if ! [ $? = 0 ]; then if ! [ $? = 0 ]; then
error "error occurred in cryptsetup luksClose ${basemap}" error "error occurred in cryptsetup luksClose ${basemap}"
exit 1 return 1
fi fi
losetup -d "/dev/`echo $basemap | cut -d. -f4`" losetup -d "/dev/`echo $basemap | cut -d. -f4`"
# echo ${nstloop} | grep loop 1>/dev/null 2>/dev/null
# # if it's a loopback then we need to do losetup -d
# if [ $? = 0 ]; then
# losetup -d ${nstloop}
# if ! [ $? = 0 ]; then
# error "error occurred in losetup -d ${nstloop}"
# exit 0
# fi
# fi
notice "crypt storage ${mapper} unmounted" notice "crypt storage ${mapper} unmounted"
tomb-notify "Tomb closed: $tombname" "Your bones will Rest In Peace." tomb-notify "Tomb closed: $tombname" "Your bones will Rest In Peace."
exit 0
return 0
} }
# install mime-types, bells and whistles for the desktop # install mime-types, bells and whistles for the desktop
@ -749,9 +755,14 @@ EOF
kill_tomb() { kill_tomb() {
# TODO: fixME - should close all tombs # TODO: fixME - should close all tombs
umount /tmp/tomb* 2&>1 > /dev/null umount /tmp/tomb* 2>&1 > /dev/null
# todo check which are tomb loops # todo check which are tomb loops
losetup -d /dev/loop* 2&>1 > /dev/null losetup -d /dev/loop* 2>&1 > /dev/null
statuses=`ps ax| grep -v awk | awk "/tomb-status.$basemap/"' { print $1 }'`
for ts in ${(f)statuses}; do
kill $ts
done
} }
@ -761,12 +772,12 @@ case "$CMD" in
mount) check_priv ; mount_tomb ;; mount) check_priv ; mount_tomb ;;
open) check_priv ; mount_tomb ;; open) check_priv ; mount_tomb ;;
umount) check_priv ; umount_tomb ;; umount) check_priv ; umount_tomb ${CMD2} ;;
unmount) check_priv ; umount_tomb ;; unmount) check_priv ; umount_tomb ${CMD2} ;;
close) check_priv ; umount_tomb ;; close) check_priv ; umount_tomb ${CMD2} ;;
install) check_priv ; install_tomb ;; install) check_priv ; install_tomb ;;
kill) check_priv ; kill_tomb ;; kill) check_priv ; kill_tomb ;;
status) tomb-status ;; status) tomb-status ;;
notify) tomb-notify $CMD2 $CMD3 ;; notify) tomb-notify $CMD2 $CMD3 ;;
@ -776,5 +787,5 @@ case "$CMD" in
exit 1 exit 1
;; ;;
esac esac
# return codes from called functions
exit 0 exit $?

View File

@ -127,17 +127,20 @@ cat <<EOF
job, but in order to do so you will need to provide your sudo job, but in order to do so you will need to provide your sudo
password: password:
EOF EOF
tomb -S create ${filename}.tomb $size
tomb create ${filename}.tomb $size
if [ $? != 0 ]; then if [ $? != 0 ]; then
echo "An error occurred creating tomb, operation aborted" echo "An error occurred creating tomb, operation aborted."
tomb -S kill tomb kill
echo "Press any key to close this terminal."
read -q read -q
exit 1 exit 1
fi fi
if ! [ -r /usr/share/applications/tomb.desktop ]; then if ! [ -r /usr/share/applications/tomb.desktop ]; then
echo " Well done!" echo " Well done!"
echo " Now the last thing to do is to install Tomb on your desktop:" echo " Now the last thing to do is to install Tomb on your desktop:"
sudo tomb -S install sudo tomb install
fi fi
exit 0 exit 0

View File

@ -172,7 +172,7 @@ gboolean cb_close(GtkWidget *w, GdkEvent *e) {
return FALSE; return FALSE;
} }
if (cpid == 0) { // Child if (cpid == 0) { // Child
execlp("tomb","tomb","-S","umount",mapper,(char*)NULL); execlp("tomb", "tomb", "close", mapper, (char*)NULL);
exit(1); exit(1);
} }
waitpid(cpid, &res, 0); waitpid(cpid, &res, 0);