tomb

the crypto undertaker
git clone git://parazyd.org/tomb.git
Log | Files | Refs | README | LICENSE

commit c72acdeaa9a40b7cf0acba179e8340dba16ad44e
parent 58decda7fecbd02e7e9bf98d218239c88ffb2668
Author: Anathema <anathema@anche.no>
Date:   Sun,  8 Jan 2012 00:23:49 +0100

Tomb resize

The new 'resize' command lets a user increase the size of the tomb

The operation is quite lengthy as it requires the creation of a new
tomb file and then copying all contents from the old tomb to the new.

Diffstat:
Msrc/tomb | 144++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 143 insertions(+), 1 deletion(-)

diff --git a/src/tomb b/src/tomb @@ -138,6 +138,10 @@ check_bin() { which mktemp > /dev/null || MKTEMP=0 # check for steghide which steghide > /dev/null || STEGHIDE=0 + + # resize suite check bin! + which e2fsck > /dev/null || die "Cannot find e2fsck. Please install it." 1 + which resize2fs > /dev/null || die "Cannot find resize2fs. Please install it." 1 } # }}} @@ -297,6 +301,7 @@ Commands: close close the open tomb called FILE (or all) slam close tomb FILE and kill all pids using it passwd change the password of a tomb key FILE + resize resize a tomb FILE EOF if [ "$STEGHIDE" = 1 ]; then cat <<EOF @@ -308,7 +313,7 @@ EOF Options: - -s size of the tomb file when creating one (in MB) + -s size of the tomb file when creating/resizing one (in MB) -k path to the key to use for opening a tomb -n don't process the hooks found in tomb -o mount options used to open (default: rw,noatime,nodev) @@ -1137,6 +1142,138 @@ change_passwd() { } # }}} +# {{{ - Resize +# resize tomb file size +resize_tomb() { + if ! [ ${CMD2} ]; then + _failure "No tomb name specified for resizing" + elif ! [ -r "${CMD2}" ]; then + _failure "Cannot find ${CMD2}" + fi + + local c tombpass tombkey + local tombfile=`basename ${CMD2}` + local tombdir=`dirname ${CMD2}` + # make sure the file has a .tomb extension + local tombname=${tombfile%%\.*} + tombfile=${tombname}.tomb + + if option_is_set -k ; then + if [[ "`option_value -k`" == "-" ]]; then + # take key from stdin + local tombkeydir + tombkeydir=`safe_dir` + cat > ${tombkeydir}/stdin.tmp + tombkey=${tombkeydir}/stdin.tmp + else + # take key from a file + tombkey=`option_value -k` + fi + else + # guess key as lying besides the tomb + tombkey=${tombdir}/${tombfile}.key + fi + + if ! [ -r ${tombkey} ]; then + _failure "key file not found: ${tombkey}" + fi + + local tmp_resize=`safe_filename tmbrsz` + local newtombsize=$opts[-s] + local oldtombsize=`stat -c %s "${CMD2}" 2>/dev/null` + local mounted_tomb=`mount -l | + awk -vtomb="[$tombname]" '/^\/dev\/mapper\/tomb/ { if($7==tomb) print $1 }'` + + if [ "$mounted_tomb" ]; then + _failure "the tomb $tombname is mounted: to resize, umount it ('tomb close $tombname' is your friend)." + fi + + # MB to bytes conversion + newtombsize=`expr \( $newtombsize \* 1024 \) \* 1024 2> /dev/null` + + if ! [ "$newtombsize" ] ; then + _failure "You must specify the new size of $tombname" + elif [[ $newtombsize != <-> ]]; then + _failure "Size is not an integer" + elif [ "$newtombsize" -le "$oldtombsize" ]; then + _failure "the new size must be greater then old tomb size." + fi + + local delta=`expr $newtombsize \- $oldtombsize` + + local tombsize_4k=`expr $delta \/ 1024` + tombsize_4k=`expr $tombsize_4k \/ 4 ` + + act "Generating ${tombfile} of ${newtombsize}Mb (${tombsize_4k} blocks of 4Kb)" + "$DD" if=/dev/urandom bs=4k count=${tombsize_4k} of="${tmp_resize}" + + if [ $? = 0 -a -e "${tmp_resize}" ]; then + act "OK: `ls -lh ${tmp_resize}`" + else + _failure "Error creating the extra resize $tmp_resize, operation aborted." + fi + + cat "${tmp_resize}" >> "${CMD2}" + "${WIPE}" "${tmp_resize}" + + local nstloop=`losetup -f` + if [ $? = 255 ]; then + _failure "too many tomb opened. Please close any of them to open another tomb" + fi + losetup -f "${CMD2}" + + local mapdate=`date +%s` + local mapper="tomb.${tombname}.${mapdate}.`basename $nstloop`" + + _message "Password is required for key ${keyname}" + for c in 1 2 3; do + if [ $c = 1 ]; then + tombpass=`exec_as_user ${TOMBEXEC} askpass ${keyname}` + else + tombpass=`exec_as_user ${TOMBEXEC} askpass "$keyname (retry $c)"` + fi + (gpg --batch --passphrase-fd 0 --no-tty --no-options \ + -d "${tombkey}" 2> /dev/null <<< ${tombpass} ) \ + | cryptsetup --key-file - luksOpen ${nstloop} ${mapper} + + unset tombpass + + if [ -r /dev/mapper/${mapper} ]; then + break; # password was correct + fi + done + + if ! [ -r /dev/mapper/${mapper} ]; then + losetup -d ${nstloop} + _failure "failure mounting the encrypted file" + fi + + cryptsetup resize "${mapper}" + if [ $? != 0 ]; then + losetup -d ${nstloop} + _failure "cryptsetup failed to resize $mapper" + fi + + e2fsck -f /dev/mapper/${mapper} + if [ $? != 0 ]; then + losetup -d ${nstloop} + _failure "e2fsck failed to check $mapper" + fi + + resize2fs /dev/mapper/${mapper} + if [ $? != 0 ]; then + losetup -d ${nstloop} + _failure "resize2fs failed to resize $mapper" + fi + + # close and free the loop device + cryptsetup luksClose "${mapper}" + losetup -d ${nstloop} + + return 0 +} + +# }}} # {{{ - List # list all tombs mounted in a readable format list_tombs() { @@ -1433,6 +1570,7 @@ main() { subcommands_opts[mktemp]="" subcommands_opts[source]="" subcommands_opts[status]="" + subcommands_opts[resize]="s: -size=s k: -key=k" # subcommands_opts[translate]="" ### Detect subcommand @@ -1551,6 +1689,10 @@ main() { fi decode_key ${CMD2} ;; + resize) + check_priv + resize_tomb + ;; # internal commands useful to developers 'source') return 0 ;; install) check_priv ; install_tomb ;;