From 729e870e0e9950e39daf681154b4f04615026484 Mon Sep 17 00:00:00 2001 From: Jaromil Date: Sat, 12 Feb 2011 00:36:21 +0100 Subject: [PATCH] steganography encoding of keys in images (mostly for key backup) just from the tomb commandline for now (we start missing a simple GUI wizard eh) also includes fixes for backward compat (renames tomb volumes after files) this helps scripts track all mounted tombs via mount -l which prints labels and some tomb-open wrapper fixes too --- src/tomb | 151 ++++++++++++++++++++++++++++++++++++++++---------- src/tomb-open | 21 +++---- 2 files changed, 134 insertions(+), 38 deletions(-) diff --git a/src/tomb b/src/tomb index c591ef0..a766ab5 100755 --- a/src/tomb +++ b/src/tomb @@ -147,17 +147,17 @@ ask_usbkey() { # user interface (just to ask the password) ask_password() { - exec_as_user xhost 2>&1 >/dev/null + xhost 2>&1 >/dev/null if [ $? = 0 ]; then # we have access to the X display - exec_as_user which tomb-askpass > /dev/null + which tomb-askpass > /dev/null if [ $? = 0 ]; then - export scolopendro="`exec_as_user tomb-askpass ${1} 2>/dev/null`" + export scolopendro="`tomb-askpass ${1} 2>/dev/null`" return fi - exec_as_user which ssh-askpass # 2>&1 > /dev/null + which ssh-askpass # 2>&1 > /dev/null if [ $? = 0 ]; then - export scolopendro="`exec_as_user ssh-askpass "Tomb: provide the password to unlock"`" + export scolopendro="`ssh-askpass "Tomb: provide the password to unlock"`" return fi @@ -486,37 +486,37 @@ create_tomb() { mount_tomb() { - if ! [ $CMD2 ]; then error "need an argument, operation aborted." return 1 elif [ -r $CMD2 ]; then - tombfile=$CMD2 + tombfile=`basename $CMD2` + tombdir=`dirname $CMD2` else # try also adding a .tomb extension - tombfile="${CMD2%\.*}.tomb" + tombfile=${tombfile%%\.*}.tomb if ! [ -r $tombfile ]; then error "cannot find a tomb named $CMD" return 1 fi fi - file $tombfile | grep -i 'luks encrypted.*cbc-essiv' 2>&1 >/dev/null + file ${tombdir}/${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` + tombname=${tombfile%%\.*} + act "mounting tomb named after $tombname" if [ $KEY ]; then # key manually chosen from commandline with -k tombkey="`basename $KEY`" tombkeypath="$KEY" else - tombkey="`basename ${tombfile}.gpg`" + tombkey=${tombfile}.gpg if [ -r $tombkey ]; then tombkeypath=$tombkey elif [ -r "$tombdir/$tombkey" ]; then @@ -543,7 +543,7 @@ mount_tomb() { tombmount=/media/`basename ${tombfile}` act "mountpoint not specified, using default: $tombmount" elif ! [ -x $CMD3 ]; then - error "mountpoint $CMD2 doesn't exist, operation aborted." + error "mountpoint $CMD3 doesn't exist, operation aborted." return 1 else tombmount=$CMD3 @@ -555,7 +555,7 @@ mount_tomb() { mkdir -p $tombmount nstloop=`losetup -f` - losetup -f ${tombfile} + losetup -f ${tombdir}/${tombfile} act "check for a valid LUKS encrypted device" cryptsetup isLuks ${nstloop} @@ -572,7 +572,7 @@ mount_tomb() { mapdate="`date +%s`" mapdate="`echo ${mapdate}/60 | bc -l | cut -d. -f1`" - mapper="tomb.`basename $tombfile | cut -d. -f1`.$mapdate.`basename $nstloop`" + mapper="tomb.${tombname}.${mapdate}.`basename $nstloop`" notice "Password is required for key ${tombkey}" keyname=`basename $tombkey | cut -d. -f1` @@ -609,7 +609,9 @@ mount_tomb() { act "encrypted storage filesystem check" fsck -p -C0 /dev/mapper/${mapper} - + act "tomb engraved as $tombname" + tune2fs -L ${tombname} /dev/mapper/${mapper} + mount -o rw,noatime,nodev /dev/mapper/${mapper} ${tombmount} # Ensure the user can write the disk - 10x Hellekin :) @@ -623,6 +625,108 @@ mount_tomb() { return 0 } +encode_key() { + tombkey=$CMD2 + imagefile=$CMD3 + + file $tombkey | grep PGP > /dev/null + if [ $? != 0 ]; then + error "encode failed: $tombkey is not a tomb key" + return 1 + fi + file $imagefile | grep JPEG > /dev/null + if [ $? != 0 ]; then + error "encode failed: $imagefile is not a jpeg image" + return 1 + fi + + notice "Encoding key $tombkey inside image $imagefile" + act "please choose a password for the encoding" + + # here user is prompted for key password + for c in 1 2 3; do + # 3 tries to write two times a matching password + ask_password ${FILE} + scolotemp=$scolopendro + ask_password "${FILE} (again)" + if [ "$scolotemp" = "$scolopendro" ]; then + break; + fi + unset $scolotemp + unset $scolopendro + done + + if [ -z $scolopendro ]; then + error "passwords don't match, aborting operation." + return 1 + fi + + awk ' +/^-----/ {next} +/^Version/ {next} +/^Comment/ {next} +{print $0}' ${tombkey} \ + | steghide embed --embedfile - --coverfile ${imagefile} \ + -p ${scolopendro} -z 9 -e serpent cbc + if [ $? != 0 ]; then + error "encoding error: steghide reports problems" + res=1 + else + notice "tomb key encoded succesfully into image ${imagefile}" + res=0 + fi + + unset scolopendro + + return $res +} + +decode_key() { + tombname=$CMD2 + imagefile=$CMD3 + res=1 + + file $imagefile | grep JPEG > /dev/null + if [ $? != 0 ]; then + error "encode failed: $imagefile is not a jpeg image" + return 1 + fi + + tombfile=${tombname%%\.*}.tomb.gpg + notice "Decoding a key out of image $imagefile" + for c in 1 2 3; do + if [ $c = 1 ]; then + ask_password ${keyname} + else + ask_password "$keyname (retry $c)" + fi + steghide extract -sf ${imagefile} -p ${scolopendro} -xf - \ + | awk ' +BEGIN { +print "-----BEGIN PGP MESSAGE-----" +print "Version: GnuPG v1.4.10 (GNU/Linux)" +} +{ print $0 } +END { +print "-----END PGP MESSAGE-----" +}' > ${tombfile} + + if [ "`cat ${tombfile} | wc -l`" != "3" ]; then + act "${tombfile} succesfully decoded" + res=0 + break; + fi + done + + unset scolopendro + + if [ $res != 0 ]; then + error "nothing found." + fi + + return $res +} + exec_bind_hooks() { mnt=$1 # first argument is where the tomb is mounted if ! [ -r ${mnt}/bind-hooks ]; then return; fi @@ -830,17 +934,6 @@ EOF act "Tomb is now installed." } -kill_tomb() { - # TODO: fixME - should close all tombs - umount /tmp/tomb* 2>&1 > /dev/null - # todo check which are tomb loops - 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 - -} case "$CMD" in @@ -853,8 +946,10 @@ case "$CMD" in unmount) check_priv ; umount_tomb ${CMD2} ;; close) check_priv ; umount_tomb ${CMD2} ;; + encode) encode_key ${CMD2} ${CMD3} ;; + decode) decode_key ${CMD2} ;; + install) check_priv ; install_tomb ;; - kill) check_priv ; kill_tomb ;; status) tomb-status ;; notify) tomb-notify $CMD2 $CMD3 ;; diff --git a/src/tomb-open b/src/tomb-open index f6e2c87..e5ceb55 100755 --- a/src/tomb-open +++ b/src/tomb-open @@ -30,26 +30,28 @@ try() { if [ $? = 0 ]; then return 0; else return -1; fi } - + +tombdir=`dirname $1` +tombfile=`basename $1` +tombname=${tombfile%%\.*} # got an argument -if [ $1 ]; then -# is it a tomb? - arg="${1%%\.*}.tomb" +if [ $1 ]; then # is it a file? - if [ -f $arg ]; then - file $arg | grep LUKS + if [ -f ${tombdir}/${tombfile} ]; then + # is it a luks partition + file ${tombdir}/${tombfile} | grep LUKS if [ $? = 0 ]; then # tomb is a valid LUKS file - tomb mount $arg + tomb mount ${tombdir}/${tombfile} if [ $? = 0 ]; then # mount was succesfull (with password and all) # strip extension if there - tombname="${arg%%.*}" 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 &! exit 0 else @@ -62,8 +64,7 @@ if [ $1 ]; then fi - elif [ -d $1 ]; then - # its a directory + elif [ -d $1 ]; then # its a directory # FIXME: somehow xdg-open loses mailcap mimes when executed by tomb-status # try xdg-open; if [ $? = 0 ]; then xdg-open ${1}; exit 0; fi